Featured Image Metabox Customization


This is day 18 of my WordPress Developer Advent Calendar.

The featured image metabox is a great feature of WordPress. It allows you to quickly choose the featured image for a post or page. But what about custom post types? Yes, you can also enable the featured image metabox for your custom post types by using the ‘supports’ parameter. Take this example below, where I am registering a Company post type:

register_post_type( 'company', 
    'supports' => array( 'title', 'editor', 'thumbnail')

Notice the value ‘thumbnail’ included in the array for the supports parameter. The metabox will now show up for that post type.

‘Featured Image’ Doesn’t Make Sense

The wording ‘Featured image’ might not make sense for every post type. In our above example, I do not want to “set a featured image” for a company, but would rather “set a company logo”. So there are a couple things we need to do:

  1. Change the “Featured Image” metabox title.
  2. Change the links with the wording “Set featured image” and “Remove featured image”.
  3. Change the “Set Featured Image” header inside the media manager modal.
  4. Change the “Set featured image” button text inside the media manager modal.

Change Featured Image Metabox Title

This is not as straight forward as it may seem. You will need to hook into the add_meta_boxes action and remove the existing metabox with the name postimagediv and add it back again, but with a new title:

function company_change_featured_image_metabox_title( $post_type, $post ) {
	if ( $post_type === 'company' ) {
		//remove original featured image metabox
		remove_meta_box( 'postimagediv', 'company', 'side' );
		//add our customized metabox
		add_meta_box( 'postimagediv', __('Company Logo'), 'post_thumbnail_meta_box', 'company', 'side', 'low' );
add_action( 'add_meta_boxes', 'company_change_featured_image_metabox_title', 10, 2 );

Notice how I target the ‘company’ post type. This is very important, so that you do not change every featured image metabox across all your post types.

Change Featured Image Links

Changing the links with the wording “Set featured image” and “Remove featured image” was probably the most difficult part. It is very easy to change if you do it across the board for all post types, but very tricky if you want to target a specific post type. The reason is the action we hook into (admin_post_thumbnail_html) gets called via ajax after you select the image, so we can’t easily see what post type we are dealing with. We need a new helper function that returns the post type from within the AJAX call:

function get_ajax_referer_post_type() {
	//extract the querystring from the referer
	$query = parse_url( wp_get_referer(), PHP_URL_QUERY );
	//extract the querystring into an array
	parse_str( $query, $query_array );
	//get the post_type querystring value
	if ( array_key_exists( 'post_type', $query_array ) ) {
		return $query_array['post_type'];
	//if all else fails, we are most likely dealing with a post
	return 'post';

You can read the comments in the code to see what it is doing. And then we need to check for an AJAX call and call this function. If we are not in an AJAX call, then simply get the post type from the current screen object:

function get_featured_image_metabox_post_type() {
	//we first need to check if this is an ajax call
	if (defined('DOING_AJAX') && DOING_AJAX) {
		return get_ajax_referer_post_type();
	//get the post type in the usual way
	$screen = get_current_screen();
	return $screen->post_type;

And then we hook into the admin_post_thumbnail_html filter and replace some text:

function company_change_featured_image_metabox_content( $content ) {
	if (get_featured_image_metabox_post_type() === 'company' ) {
		$content = str_replace( __('Set featured image'), __('Set Company logo', 'feat-img-custom'), $content );
		$content = str_replace( __('Remove featured image'), __('Remove Company logo', 'feat-img-custom'), $content );
	return $content;
add_filter( 'admin_post_thumbnail_html', 'company_change_featured_image_metabox_content' );

Change Text Within Media Manager

The last two changes are for two strings that are displayed within the media manager modal. This means we need to hook into the media_view_strings filter:

function company_change_featured_image_media_strings( $strings, $post ){
	if ($post->post_type === 'company') {
		$strings['setFeaturedImage'] = __('Set logo', 'feat-img-custom');
		$strings['setFeaturedImageTitle'] = __('Set Logo', 'feat-img-custom');
	return $strings;
add_filter( 'media_view_strings', 'company_change_featured_image_media_strings', 10, 2);

A Helper Class Please

I wrapped all this functionality into a small helper class and posted it on Github. Now all you need to do is include the class and instantiate it:

require_once 'class-featured-image-metabox-cusomizer.php';
new Featured_Image_Metabox_Customizer(array(
	'post_type'     => 'company',
	'metabox_title' => __( 'Company Logo', 'my-plugin-slug' ),
	'set_text'      => __( 'Set Company logo', 'my-plugin-slug' ),
	'remove_text'   => __( 'Remove Company logo', 'my-plugin-slug' )

Fork, play, enjoy!

Template File Loader Class


This is day 17 of my WordPress Developer Advent Calendar.

Pippin recently posted a tutorial about a template file loader class, which I thought would be a great addition to any complex plugin that uses templates for shortcode output.

What Is A Template Loader?

In a nutshell, a template loader scans a number of different locations for a template file (just a plain old php file). If it finds the desired template, it is included. If no other template is found, then a default is included. This makes it really easy for theme authors to override any templates that you have in your plugin. And by placing them in a specific folder inside their theme, it means that your plugin updates will never override the theme templates. Oh yes, and it also supports parent and child themes.

How To Use The Template Loader Class

It is a class, so you have to extend Gamajo_Template_Loader with your own class. Here is a really simple example:

class FooBar_Template_Loader extends Gamajo_Template_Loader {
	 * Prefix for filter hooks called within the class.
	protected $filter_prefix = 'foobar';
	 * Directory name where custom templates for this plugin should be found in the theme.
	protected $theme_template_directory = 'foobar-templates';
	 * Reference to the root directory path of your plugin.
	protected $plugin_directory = FOOBAR_PLUGIN_DIR;

Now you can instantiate this class and call get_template_part:

$loader = new FooBar_Template_Loader();
$loader->get_template_part('email', 'body');

This code will then look for the following files:

  1. wp-content/themes/CURRENT_THEME/foobar-templates/email-body.php
  2. wp-content/themes/PARENT_THEME/foobar-templates/email-body.php
  3. wp-content/plugins/foobar/templates/email-body.php
  4. wp-content/themes/CURRENT_THEME/foobar-templates/email.php
  5. wp-content/themes/PARENT_THEME/foobar-templates/email.php
  6. wp-content/plugins/foobar/templates/email.php

As soon as it finds the specific file in one of the above locations, it stops looking any further and includes the file. Also notice how it first looks for the more specific file email-body.php and then the less specific email.php. It also checks the parent theme folder, but only if the current theme is a child theme.

Example Plugin

Check out Pippin’s example plugin that uses the template loader class.

This is a great bit of code that can really take your plugin to a new level, especially when you are generating HTML code on the frontend.

Grunt For WordPress Developers


This is day 16 of my WordPress Developer Advent Calendar.

Chris Coyier recently published a great article Grunt for People Who Think Things Like Grunt are Weird and Hard. I love Grunt too and use it daily.

What Is Grunt?

Grunt is a task runner that runs on node.js. It allows you to automate all those boring, repetitive tasks that we deal with every day as developers. For example:

  • Minify and combine all your javscript source files
  • Compress images
  • Compile your SASS into CSS

I am not going to over how to install Grunt or set it up. I will leave that to Chris’ article as he does a great job. I rather wanted to share how you could use it as a WordPress developer.

If I Code for WordPress, Should I Care?

Oh hell yes! If you write plugins or themes for WordPress, the chances that you write a bit of javascript and CSS is pretty high. Obviously, there are Grunt plugins that work with JS and CSS, but it doesn’t just stop there. Grunt has tons of plugins, and here are a few which you could start using in your next WordPress plugin or theme:

  • CSS
    • contrib-less - compile your LESS files to CSS.
    • contrib-compass - compile your Sass files to CSS.
    • contrib-csslint - run CSS Lint on your CSS files.
    • contrib-css - minify your CSS files.
  • Javascript
    • contrib-coffee - compile your Coffeescript files to javascript.
    • contrib-jshint - validate your javscript with JS Hint.
    • contrib-uglify - minify your javascript files.
  • Images
    • contrib-imagemin - Minify your PNG, JPG and GIF images.
  • General
    • contrib-concat - combine your JS or CSS files.
    • contrib-copy - copy files and folders around.
  • PHP
    • phpunit - run your phpunit unit tests.
    • phplint - validate your PHP files.
  • WordPress
    • pot - generates a .POT file that can be used for translations.
    • checkwpversion - make sure your plugin version numbers are all in sync. (in your plugin’s header, readme.txt and package.json)
    • checktextdomain - checks the correct text domain is passed when using the WordPress translation functions.
    • wp-readme-to-markdown - Converts readme.txt file to for use in Github repo.

Other Uses For Grunt

Grunt also provides project scaffolding, which allows you to generate your boilerplate code with little effort. I created a grunt-init template which is based off the WordPress Plugin Boilerplate.