Change “Enter Title Here” text for your WordPress custom post type

When you add a new post, WordPress pre-fills the title input box with the gentle greyed out text ‘Enter title here’. It does this by default for all post types, including any custom ones you have registered. This might not always make sense.

As of WordPress 3.1 there is now a filter to easily change this.

add_filter( 'enter_title_here', 'tcb_enter_title_here' );
function tcb_enter_title_here( $message ){
  global $post;
  if( 'album' == $post->post_type ):
    $message = 'Enter Album Name';
  endif;

  return $message;
}

The above snippet will replace the text for the post type ‘album’.

Adding custom styling to WordPress custom post types admin screens

My WordPress projects usually end up using at least 3 custom post types, sometimes more than 10. Together with some extra admin screens (from external plugins[1]), the admin menu gets cluttered. All the various edit post admin screens can look very similar to the untrained eye.

What to do about!? Well, I’m not a designer, but I can certainly kick-start things by providing inspiration to my colleagues. What I need is some way of boldly showing them that we can add some styling to specific post type admin screens.

add_filter( 'admin_body_class', 'tcb_custom_post_type_body_class' );
function tcb_custom_post_type_body_class( $classes ){
  global $post;

  $post_class = get_post_type( $post->ID ) . '_admin';
  if( is_array($classes) ):
    $classes[] = $post_class;
  else :
    $classes .= " {$post_class}";
  endif;

  return $classes;
}

That will add a class to the page’s body tag, which can be targeted with CSS. Here is a rather pathetic example for my albums and artists post types:

.albums_admin{
  background-color: #0f0;
}
.artists_admin{
  background-color: #f00;
}

Good luck with that!

Restrict WordPress category drop down to custom post type

Whilst working on a theme that has several custom post types, all supporting the core category taxonomy, I came across an annoying little problem. I wanted to be able to show a drop down of all the categories with posts in a custom post type, whilst excluding those (post types) that didn’t. The term count stored in the database is independent of post type, so merely setting the hide_empty argument to true would not suffice. Categories with posts in other post types would still be displayed.

Faced with time constraints, I came up with a quick clunky solution.

<?php
$exclusive_post_type = 'book';
$exclude_cats        = array();
$nonemptycats        = get_terms( 'category' );
foreach( $nonemptycats as $term ){
  $term_id      = $term->term_id;
  $term_objects = get_objects_in_term( $term_id, 'category' );
  $exclude_term = true;
  foreach( $term_objects as $post_id ){
    if ( $exclusive_post_type === get_post_type( $post_id ) ){
      $exclude_term = false;
      break;
    }
  }
  if ( $exclude_term ) $exclude_cats[] = $term_id;
}

$args = array(
  'orderby'         => 'name',
  'show_count'      => false,
  'hide_if_empty'   => true,
  'show_option_all' => 'All categories',
  'depth'           => 1,
  'exclude'         => $exclude_cats,
);
?>
Categories: <?php wp_dropdown_categories( $args ); ?>

The above example creates a drop down of categories that have ‘book’ posts.

Unique WordPress style sheets for Custom Post Type admin screen

Custom post types are an awesome WordPress feature. Anyone designing a website using WordPress that has more than blog posts and pages, should use custom post types. One of the main advantages of this is that you get a clean and focussed admin screen just for that particular asset type. To further enhance this, it would be great if we could specify a specific style sheet just for that post type

Filter to add custom post type editor styles

function tcb_cpt_editor_styles(){
  global $current_screen;
  $css_post_type = 'editor-style-' . $current_screen->post_type . '.css';
  add_editor_style($css_post_type);
}
add_action( 'admin_head', 'tcb_cpt_editor_styles' );

Using the above code, if you have created a post type ‘cars‘, then you would need the style file ‘editor-style-cars.css‘. If you get a chance to use it, let me know.

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.