WordPress Plugin – Cite the Source for Images Attached to Your WordPress Posts

WordPress is clever with data storage in that it likes to avoid redundancy. And since, arguably speaking, storing data like the content of posts, in a database is a handy thing, so is storing “other data” within the same field and table structure.

While I (Keith here) don’t want to get into how databases are structured, and being that it took me forever and a day to wrap my mind around MySQL after thinking I knew it all after mastering Microsoft Access, I am probably not completely qualified to do so. Instead, I would like to talk a little about some WordPress defaults in terms of database storage.

Built in WordPress Post Types

OK, at present, there are 5 built in “post types” (if you will) in WordPress. Naturally, this includes posts themselves… or “journal entries” as I have been calling them while I introduce my 8-year old daughter to blogs. And… WordPress also stores post “revisions” and drafts within the same table structure. Pages are essentially the same in terms of what is stored. And strangely, menus and attachments are stored in a similar way, with their own post type.

Attachments include images which is what I would like to discuss today.

Adding New Fields to WordPress Post Types

With WordPress, we can create our own custom post types, or, if desired, we can add our own fields to existing post types. Fields are simply unique pieces of data (like a title) that make up an object (like a post).

Although WordPress gives us some fields for images such as: title, caption, alt text, and description… there are some scenarios where it is helpful to add our own. Now, we can add multiple elements to one existing field (like we could within an image description), or instead, we can break up those elements into individual elements, and store each of them in their own field.

But what fields would we add to images?

Giving Credit to Image Authors

Well, my upbringing and belief system tells me that I should give credit where it is deserved. That says to me that, if I grab an image from another source, which I often do since I am neither a graphic designer nor a photographer, creative commons zero (CC0) or not, I should give props to those that deserve it. i.e. I should cite the source of the images that I attach to my WordPress posts.

Automating Image Citation

There is a relatively simple way to cite images in WordPress, but is it the best way? You could realistically add your attribution to the bottom of your WordPress post. Easy peasy. No PHP or WordPress hooks required. But there’s a problem with that approach. The attribution data is stored with the post, not the image. Therefore, if you use the same image from the WordPress Media Library within a different post in the future, how are you (or the post author) going to know where that image came from to properly source it? Rainman will be able to source the image from memory, but you might not be able to. You will likely need WordPress to pull that data from custom image fields from the database.

So… let’s store the attribution data with the image where it belongs, and then automate the citation, shall we?

If you like that idea, read on, and learn exactly how, complete with source code.

Simplifying the Creative Commons Licenses for Images

I cannot offer legal advice. And I cannot guarantee that citing your images in the way that I will be discussing will be sufficient to keep you legit. There are a variety of license types, and probably even some custom types that exist. It might be best to read through them for a better understanding.

For me, these days, I keep it simple and primarily just look for CC0 images. This means I can use the images to generate income from them, and I can modify them. Technically I do not have to credit the source, but I do anyway whenever possible. The CC BY license is also quite flexible in that you can modify the work, and make money from it, but you are required to cite the source. So to me, CCO and CC BY can be considered the same, since I like to always cite the source anyway.

Now, in many cases it may seem like we are not making money from the images, and that we are not modifying them. However, if you are like me and making money from your web sites (not necessarily the images), and since WordPress automatically modifies the images during upload (cropping, resizing, etc.), to be on the safer side, it’s probably better to *not* use images that disallow commercial use or derivatives to be made. Therefore, I tend to stick to CC0 and CC BY like I said.

What Makes Up an Image Attribution?

Let’s have a quick peek at the elements of an attribution. You can read more here, and make decisions about how you would like to do it, but below is an example of the way that I tend to do it to cover all bases (to my understanding).

Example:

“{image name}” by {image author} is licensed under {license name}, {optional modification description, or license for modified work}

The first 3 elements in the citation above are properly linked when the URLs are available. Since most images are found on the Web, finding the link for {image name} is rather simple. It might not always be obvious where to link the {image author} element though, but if we can, we probably should. We should always have the URLs available for the licenses.

Adding Custom Fields to Images

Alright, finally, let’s create some code that will add our custom fields so we can store more information about our images.

You can add this code to a functions.php template file in your main or child theme, or in a custom plugin.

You will see in the code that I used the prefix “tthqkl_” for the field IDs. That was done as an attempt to keep things unique from other plugins/themes that define custom fields in the wild. Also, in the definition for the “license” field, I added just two license types (CCO and CC BY). You can follow the same pattern as I did to add additional licenses to the drop box. Ideally we would create an options screen for adding/editing licenses in a nice GUI way. Perhaps in v2 🙂

<?php
$tthqkl_text_domain = "tthqkl_text_domain";
$tthqkl_att_options = array(
'tthqkl_image_name' => array(
'label' => __( 'Image Name', $tthqkl_text_domain ),
'input' => 'text',
'helps' => __( 'Enter the image name', $tthqkl_text_domain ),
'application' => 'image',
'exclusions' => array( 'audio', 'video', 'document' )
),
'tthqkl_image_source_url' => array(
'label' => __( 'Image Source URL', $tthqkl_text_domain ),
'input' => 'text',
'helps' => __( 'Enter the URL where the image can be found, if available', $tthqkl_text_domain ),
'application' => 'image',
'exclusions' => array( 'audio', 'video', 'document' )
),
'tthqkl_image_author_name' => array(
'label' => __( 'Image Author Name', $tthqkl_text_domain ),
'input' => 'text',
'helps' => __( 'Enter the name of image author, if available', $tthqkl_text_domain ),
'application' => 'image',
'exclusions' => array( 'audio', 'video', 'document' )
),
'tthqkl_image_author_url' => array(
'label' => __( 'Image Author URL', $tthqkl_text_domain ),
'input' => 'text',
'helps' => __( 'Enter the URL of the author, if available', $tthqkl_text_domain ),
'application' => 'image',
'exclusions' => array( 'audio', 'video', 'document' )
),
'tthqkl_image_license' => array(
'label' => __( 'License', $tthqkl_text_domain ),
'input' => 'select',
'options' => array(
'none' => __( 'None', $tthqkl_text_domain ),
'https://creativecommons.org/publicdomain/zero/1.0/|CC0' => __( 'CC0', $tthqkl_text_domain ),
'http://creativecommons.org/licenses/by/4.0/|CC BY 4.0' => __( 'CC BY 4.0', $tthqkl_text_domain )
),
'application' => 'image',
'exclusions' => array( 'audio', 'video', 'document' )
),
'tthqkl_image_miscellaneous' => array(
'label' => __( 'Miscellaneous', $tthqkl_text_domain ),
'input' => 'text',
'helps' => __( 'You can optionally fill in this box if you would like to add additional info, or describe any modifications to the image, or provide a license to satisfy "ShareAlike", if applicable.', $tthqkl_text_domain ),
'application' => 'image',
'exclusions' => array( 'audio', 'video', 'document' )
)
);

class tthqkl_img_citations_meta_box {

private $media_fields = array();

function __construct( $fields ) {
$this->media_fields = $fields;
add_filter( 'attachment_fields_to_edit', array( $this, 'applyFilter' ), 11, 2 );
add_filter( 'attachment_fields_to_save', array( $this, 'saveFields' ), 11, 2 );
}

public function applyFilter( $form_fields, $post = null ) {
if ( ! empty( $this->media_fields ) ) {
foreach ( $this->media_fields as $field => $values ) {
if ( preg_match( "/" . $values['application'] . "/", $post->post_mime_type) && ! in_array( $post->post_mime_type, $values['exclusions'] ) ) {
$meta = get_post_meta( $post->ID, '_' . $field, true );
switch ( $values['input'] ) {
default:
case 'text':
$values['input'] = 'text';
break;
case 'select':
$values['input'] = 'html';
$html = '<select name="attachments[' . $post->ID . '][' . $field . ']">';
if ( isset( $values['options'] ) ) {
foreach ( $values['options'] as $k => $v ) {
if ( $meta == $k ) {
$selected = ' selected="selected"';
} else {
$selected = '';
}
$html .= '<option' . $selected . ' value="' . $k . '">' . $v . '</option>';
}
}
$html .= '</select>';
$values['html'] = $html;
break;
}
$values['value'] = $meta;
$form_fields[$field] = $values;
}
}
}
return $form_fields;
}

function saveFields( $post, $attachment ) {
if ( ! empty( $this->media_fields ) ) {
foreach ( $this->media_fields as $field => $values ) {
if ( isset( $attachment[$field] ) ) {
update_post_meta( $post['ID'], '_' . $field, $attachment[$field] );
}
}
}
return $post;
}
}
$tthqkl_img_citations_meta_box = new tthqkl_img_citations_meta_box( $tthqkl_att_options );
?>

I realize that is a lot of code. You can download a .zip of the plugin that I created for this project at the end of this article, for your convenience.

Video: Image Citations in Action

As you can see in the video above, the plugin successfully adds the custom fields to the image edit screens, and the data gets saved as expected.

Generating the Attribution Lines

Now I would like to provide the code that generates the attribution line(s) within the single post screen.

Naturally, I could create an options page where you can set preferences for this tool (perhaps in version 3), but instead I am going to hard code some defaults. I am going to include a little heading that says “Image Credits”, plus I am going to include the attribution lines immediately after the post content, for all post types, each preceded by a bullet.

The way the tool determines which images to display an attribution line for is, it looks for image attachments that have the post as their parent. Sometimes though, if someone manually removes the WordPress generated image code from a post for the img HTML tag, the image still *thinks* it’s attached to the post, and this tool with cite the source. I will explain below how to remove those confused images so the citation lines don’t show up for them.

<?php
function tthqkl_draw_citation_line($attachment_id) {
$attributions .= ‘&bull; ‘;
if (get_post_meta($attachment_id, ‘_tthqkl_image_source_url’, true)) {
$attributions .= ‘<a href=”‘ . get_post_meta($attachment_id, ‘_tthqkl_image_source_url’, true) . ‘” target=”_blank”>’ . get_post_meta($attachment_id, ‘_tthqkl_image_name’, true) . ‘</a>’;
} else {
$attributions .= get_post_meta($attachment_id, ‘_tthqkl_image_name’, true);
}
if (get_post_meta($attachment_id, ‘_tthqkl_image_author_name’, true)) {
$attributions .= ‘ by ‘;
if (get_post_meta($attachment_id, ‘_tthqkl_image_author_url’, true)) {
$attributions .= ‘<a href=”‘ . get_post_meta($attachment_id, ‘_tthqkl_image_author_url’, true) . ‘” target=”_blank”>’ . get_post_meta($attachment_id, ‘_tthqkl_image_author_name’, true) . ‘</a>’;
} else {
$attributions .= get_post_meta($attachment_id, ‘_tthqkl_image_author_name’, true);
}
}
if (get_post_meta($attachment_id, ‘_tthqkl_image_license’, true) != ‘none’) {
$attributions .= ‘ is licensed under ‘;
$pipe_pos = strpos(get_post_meta($attachment_id, ‘_tthqkl_image_license’, true), ‘|’);
if ($pipe_pos === false) {
$license_name = get_post_meta($attachment_id, ‘_tthqkl_image_license’, true);
$license_url = ”;
} else {
$license_params = explode(‘|’, get_post_meta($attachment_id, ‘_tthqkl_image_license’, true));
$license_name = $license_params[1];
$license_url = $license_params[0];
}
if ($license_url != ”) {
$attributions .= ‘<a href=”‘ . $license_url . ‘” target=”_blank”>’ . $license_name . ‘</a>’;
} else {
$attributions .= $license_name;
}
}
if (get_post_meta($attachment_id, ‘_tthqkl_image_miscellaneous’, true)) {
$attributions .= ‘, ‘ . get_post_meta($attachment_id, ‘_tthqkl_image_miscellaneous’, true);
}
return $attributions;
}

function tthqkl_content_append_image_citation($content) {
if (is_singular() && is_main_query()) {
$attachments = get_children( array(‘post_parent’ => get_the_ID(), ‘post_type’ => ‘attachment’, ‘post_mime_type’ =>’image’) );
foreach ( $attachments as $attachment_id => $attachment ) {
if (get_post_meta($attachment_id, ‘_tthqkl_image_name’, true)) {
$attributions .= tthqkl_draw_citation_line($attachment_id);
}
if ($attributions != ”) {
$attributions .= ‘<br />’;
}
}
if ($attributions != ”) {
$new_content = ‘<p><strong>Image Credits:</strong><br />’ . $attributions . ‘</p>’;
if (get_post_thumbnail_id()) {
$new_content .= ‘<p><strong>Featured Image Credit:</strong><br />’ . tthqkl_draw_citation_line(get_post_thumbnail_id()) . ‘</p>’;
}
}
$content .= $new_content;
}
return $content;
}
add_filter(‘the_content’, ‘tthqkl_content_append_image_citation’);
?>

That’s all there is for code.

Download the Image Citation Fields Plugin

You can download the .zip file here for the plugin.

Removing Confused Images from Posts

Just in case you run into issues where the image citation tool is citing images that it shouldn’t (because the image HTML was removed from the post, but WordPress still thinks it’s attached), then you can follow the steps below to fix that.

  1. Firstly, click on Media >> Library.
  2. Make sure that you are in “list” view by clicking the first icon just below the Media Library heading.
  3. From here you will see an “Uploaded to” column. Look for the image in question, and click “Detach” below the post name that it thinks it is attached to.

If you have a whole heap of images in your Media Library, you can perform a search by image title. If you don’t know the image title, go to the edit screen for the post you are working with, click on the “Add Media” button, click on the “Media Library” tab, then choose the “Uploaded to this post” option in the first drop down. Click the image you want to detach, and look to the right for the title. Now you can search for it with the above steps, and detach it from the post *officially*. Don’t delete the image though, it can be being used in other posts.

Speak Your Mind

*