Add Author Photo — My First WordPress Filter
Oct 9th, 2009
The request was simple enough. I had just built a WordPress blog for a law firm and now they wanted to have their thumbnail photos in the articles they write. I had done this for another website (also a law firm) a year ago, modifying each of the theme’s templates that displayed posts but, when I went back and looked at that code, I thought, “Too messy, there’s got to be a better way.”
A plug-in search turned up nothing. No surprise—Wordpress does not support user profile pictures natively. There’s no field in the database for an user’s image file name. Then I remembered reading an article in Smashing Magazine about filters a couple of months ago. They had an example where a subscribe request was appended to the end of each post’s content. Maybe that technique would work to prepend a photo.
In WordPress, a filter is like a plug-in except for two important distinctions: It’s not packaged for distribution and it’s associated with the theme. That is, you can’t manage the filter from the dashboard’s plug-in manager and, if you change themes, it disappears. That was all right for my purposes. The clients were quite happy with the theme we’d chosen – Mistylook, by Sadish Bala – and I could provide instructions on how to remove the filter from the theme’s functions file should they ever want to “deactivate” the feature.
I got the images from the client for the four lawyer/authors—a wallet-sized image and a thumbnail for each. The larger image would appear on the author’s profile page and the thumbnails would be placed at the beginning of their posts, floated left of the text. For the larger image, I modified the author’s template (author.php) as I had with the previous website. For the thumbnails, I would use the filter approach since post content is accessed in several templates and I wanted a unified solution. For the sake of brevity, I’ll skip the part about the author template mods in this article. If you’re interested in that piece, leave a comment and I’ll write another article.
I created a new directory, /wp-content/authors for the larger images and a sub-directory, /wp-content/authors/thumbs for the smaller versions. In each, I renamed the images files to match the corresponding login usernames. If, for example, there was a user with the login username of ‘bobama’, then the two images files would be: /wp-content/authors/bobama.jpg and /wp-content/authors/thumbs/bobama.jpg . I did this with an ftp program but you can use the dashboard’s Media manager, in which case, the image files will be somewhere in your /wp-content/uploads directory with your other media files. All of the other work described in this article can be done through the dashboard’s theme editor by an admin user but I highly recommend using a good code editor with color syntax highlighting. BBEdit is my favorite.
A WordPress filter goes into the theme’s functions file (functions.php) and consists of two parts: A function definition and a call to add that function to a named WordPress “hook”. I called my function: add_author_photo() and added it to the ‘the_content’ hook. You can think of this hook as the point in the page building process when WordPress gets the page or post content from the database and starts to get it in shape for the web page it’s building. WordPress passes the content to the function as a string and expects it back in return. Roughly, the outline of the process looks like this:
<?php function add_author_photo($content) { ... return $content; }
add_filter('the_content', 'add_author_photo'); ?>
Note how the entire filter is enclosed in a PHP container. This is important! Now, all we need to do is fill in the “dots”.
First, we need to make sure that our function does its work in the right place since it will be called anytime WordPress fetches the content from the database. We want the thumbnail photo to appear in posts on the home page and on single post pages, but not on static pages (which are, in a sense, “authorless”) nor on the archive and search result pages and especially not in RSS feeds. The following if statement does what we want:
if (is_home() || is_single()) { ... }
Next, the code needs to check that the image file we want for the current post author actually exists. The client may add more authors and contributors before their photos are available and we don’t want an ugly, empty missing-image square to appear where a nice photo is expected. This is a bit tricky. There’s a PHP function, file_exists(), for checking whether a file exists or not but it takes, as its argument, the full Unix path to the file, as opposed to a URL fragment. WordPress provides a function for doing this: get_theme_root() which returns a string that, depending on your hosting company’s site configuration, might look like this:
/var/web/clients/abc.com/htdocs/wp-content/themes
Since my ‘authors’ directory is at the same level in /wp-content as the themes directory, all I have to do is replace the ‘themes’ part in the string above with ‘authors/thumbs/’ and append the image’s file name. The following two lines of code will assign the username to a variable and do the replacement using PHP’s str_replace() function.
$author_uname = get_the_author_meta('user_login'); $author_photo = str_replace( 'themes', 'authors/thumbs/' . $author_uname . '.jpg', get_theme_root() );
We can check whether the file exists with another if statement:
if (file_exists($author_photo)) { ... }
Now we are ready to add the image tag to the beginning of the post content. I’ll add a CSS class, ‘authorImage’, to the image tag which I’ll use to make the image float left and set appropriate margins and padding (see below.) I’ll also enclose the image in an anchor tag that links the image to the author’s profile page. I’ve laid this out here in several lines for readability. The dot at the end of each line is the PHP concatenation operator.
$image_src = '/wp-content/authors/thumbs/' . $author_uname . '.jpg'; $content = '<a href="/author/' . $author_uname . '"><img class="authorImage" src="' . $image_src . '" alt="' . get_the_author() . '" /></a>' . $content;
Here’s a screenshot of the final code I pasted into the theme’s functions file. Because I’m a nice guy, I added /* comments */ to explain what was going on. Click on the image to open a text division with the actual code you can copy.
[RAW]
[/RAW]
The final version took a bit of debugging to fix some stupid typing errors but it worked as I wanted it to. A look at the source code for the home page shows the generated image tag and link:
<a href="/author/larryaronson"><img class="authorImage" src="/wp-content/authors/thumbs/larryaronson.jpg" alt="Larry Aronson" /></a>
All that remained was adding some simple CSS to the style sheet to float the image to the left of the post text. The rules shown below does that and sets appropriate margins. The images already incorporated a border so I removed the border set elsewhere in the CSS and removed the drop shadow background that Mistylook adds to images as a matter of taste.
img.authorImage { float: left; margin: 0 1em 0 0; border: 0; padding: 0; background-image: none; }
That’s it. I hope you found this article useful. Suggestions for improvements are welcome.