Theme (or Plugin) Development – Attach hook to version change (flush rewrite rules)

The rewrite rules for WordPress control which pages and posts to display based on the URL. These are normally updated via the Permalinks setting. When you hit ‘save changes’ ¬†all the rules for which URL maps to which page are saved to the database.

When developing plugins and themes it is common to add some custom post types, or custom taxonomies. These both add to the rewrite rules. Rather than constantly clicking to save the permalinks button, we can use the flush_rewrite_rules() function call. It is expensive to do (calculating the rules and writing to the database uses lots of server resources). However, you don’t want to make your end-user have update their permalinks manually every time you release an update. This is why the codex recommends hooking into the activation hook, as this will get fired when the plugin is installed or updated from wordpress.org.

I am often faced with two scenarios that are not covered by the activation hook. Firstly, whilst developing I don’t update my plugin like that – I just change the code. And¬†secondly I mostly write bespoke code for clients not hosted on wordpress.org, and updated using version control, not from inside WordPress admin.

So I need some other trigger. Something that happens automatically, but not all the time. I decided to hook into the theme version changing.

add_action( 'admin_init', 'tcb_version_update_check' );
function tcb_version_update_check(){
  $theme           = wp_get_theme();
  $in_file_version = $theme->Version;
  $slug            = $theme->stylesheet;
  $optionkey       = "tcb_vesion_check_{$slug}";
  $in_db_version   = get_option( $optionkey, 0 );

  $version_diff    = version_compare( $in_db_version, $in_file_version );
  if( !$version_diff ) return;

  error_log( "Theme version has changed: $in_db_version -> $in_file_version" );
  if( $version_diff == 1 ) :
    error_log( "Theme version has gone down. Doesn't compute. Not running update hook." );
    return;
  endif;

  do_action( 'tcb_theme_version_update', $in_file_version, $in_db_version );

  update_option( $optionkey, $in_file_version );
}

add_action( 'tcb_theme_version_update', 'tcb_update_flush_rewrite_rules', 10, 2 );
function tcb_update_flush_rewrite_rules( $new_version, $old_version ){
  error_log( "Flushing rewrite rules" );
  flush_rewrite_rules( false );
}

What I’ve done is hooked into admin_init to check whether the theme version has changed. Added a little sanity check to see if it has gone down!?! And invoked my own hook to let myself expand on the version change trigger.

Generate post name and slug from meta data

The post title is sometimes a little more complex than just a string of characters. It can contain multiple pieces of information about the post content. With more extensive use of custom post types, such a¬†situation¬†is increasingly common. Whether a normal blog post or a custom post type, you might be¬†writing about a person. A trivial example would be that you want to make a list of people, one of whom would be ‘Joe Blogs’, and you want to sort your list of people by their last name. Here I will explain how I go about dealing with this problem.

There are two choices. You can either split the post title into parts and try to work out where the pieces go, or you can collect the pieces individually and assemble them together to create your post title. The former seems at first easier and straight forward, whilst the latter is more cumbersome. Both for the user and to write the code for. I was in two minds when faced with this, the latter option would be my natural choice, but it involves re-inventing the wheel (It would need to re-write the core post_title and post_name values). And I am very keen on not fudging around with core code.

I fired off and email to the WordPress hackers mailing list. The replies were pretty quick, and they all agreed with me. Back to my example problem. I have a custom post type ¬†‘speaker‘ that can handle up to four parts to the full name. Allowing me to handle something like ‘Dr Joe Blogs MBE’.

How to handle complex names (of people) in your posts

add_filter('wp_insert_post_data', 'tcb_auto_generate_name_title');
function tcb_auto_generate_name_title($data){
  global $post;
  if( $post->post_type != 'speaker' ) return $data;
  $speaker_meta['name_prefix'] = trim($_POST['name_prefix']);
  $speaker_meta['name_first']  = trim($_POST['name_first']);
  $speaker_meta['name_last']   = trim($_POST['name_last']);
  $speaker_meta['name_suffix'] = trim($_POST['name_suffix']);

  $fullname = array($speaker_meta['name_prefix'], $speaker_meta['name_first'], $speaker_meta['name_last'], $speaker_meta['name_suffix']);
  $fullname = implode(' ', $fullname);
  $slug     = wp_unique_post_slug(sanitize_title($fullname), $post->ID, $post->post_status, $post->post_type, $post->post_parent);

  $data['post_title'] = $fullname;
  $data['post_name']  = $slug;

  return $data;
}

And there you have it. With this you get to keep the full post title and post slug, and make it easy to order your speakers by last name. Not only does it look good, but it helps with search engine optimisation.

Add featured image thumbnail to WordPress admin columns

The admin pages listing the site’s posts and pages come with various text columns (title, tags, categories, author and so on). In order to see what the featured images are, you have to visit each post or page individually. What I will show here, is how to get add a column with a reasonably sized thumbnail copy of the featured image. Please note that this only works for themes that support featured images.

Add a new image size

First we add a new image size. Full details for this function are found on the WordPress add_image_size() codex page.

add_image_size( 'admin-list-thumb', 100, 100, false );

If your theme already has a 100 x 100 image size, you can skip this step. If not, then you may end up with an image size that messes up the layout of the columns.

Add featured image column

Next up, we add the featured image column to the posts and pages list view and pull in the featured image itself using our newly defined image size.

// Dummy up theme support.
//add_theme_support( 'post-thumbnails' );

// Add the posts and pages columns filter. They can both use the same function.
add_filter('manage_posts_columns', 'tcb_add_post_thumbnail_column', 5);
add_filter('manage_pages_columns', 'tcb_add_post_thumbnail_column', 5);

// Add the column
function tcb_add_post_thumbnail_column($cols){
  $cols['tcb_post_thumb'] = __('Featured');
  return $cols;
}

// Hook into the posts an pages column managing. Sharing function callback again.
add_action('manage_posts_custom_column', 'tcb_display_post_thumbnail_column', 5, 2);
add_action('manage_pages_custom_column', 'tcb_display_post_thumbnail_column', 5, 2);

// Grab featured-thumbnail size post thumbnail and display it.
function tcb_display_post_thumbnail_column($col, $id){
  switch($col){
    case 'tcb_post_thumb':
      if( function_exists('the_post_thumbnail') )
        echo the_post_thumbnail( 'admin-list-thumb' );
      else
        echo 'Not supported in theme';
      break;
  }
}

There is a caveat

One of the less desirable features of WordPress is that images uploaded to the media library before an image size is defined, will not have that image size available. Instead a current image size will be HTML resized. There are plugins that will fix this problem.

The eagle-eyed

Observant regular visitors may have noticed that every page and post on this site has a unique header image. I took all of them myself. Remembering which I have already used can get tricky, so I am using this very idea on my site!

Update
I have updated the code to handle themes without post-thumb support. See the codex on how to enable theme support for post thumbnails.

Update 2 – Placing the featured image in a different column position

function tcb_add_post_thumbnail_column( $cols ){
  $colsstart = array_slice( $cols, 0, 1, true );
  $colsend   = array_slice( $cols, 1, null, true );

  $colls = array_merge(
    $colsstart,
    array( 'tcb_post_thumb' => __('Featured') ),
    $colsend
  );
  return $mycolls;
}

Remove images from post content on your WordPress homepage

Worried that all the images in your posts on your home page are slowing your page speed down? Or just want to de-clutter things? Or perhaps you need to cut down on bandwidth and want to reduce the page size on your most visited page (your homepage).

WordPress snippet to remove images from your homepage posts

function tcb_remove_images_from_homepage( $content ) {
   if( is_home() )
     $content = preg_replace('/<img[^>]+./','', $content);
   return $content;
}
add_filter( 'the_content', 'tcb_remove_images_from_homepage', 100 );

Personally, I’d just get some better hosting and not worry about it ūüôā