This website uses cookies to allow us to see how the site is used. If you continue to use this site, we assume that you are okay with this. If you want to use the sites without cookies, please see our privacy policy.

Make menu highlights work for custom post types

I’ve written on my own blog about how WordPress’s navigation menus are great, but sometimes need some enhancement. One area they fall down in is how they work with custom post types.

Lets say you create a custom post type called ‘resources’ (I’ve done this on a couple of sites recently – see Send My Friend to School and Flesh and Blood). You are going to make use of the built in archive that gets generated at /resources, and you’re going to put this in your menu.

There are two issues in this scenario:

  1. A page displaying an item(s) from a post type seems to highlight any menu item linked to the blog archive page – perhaps your “Home” link, or your “Blog” link. It does this by setting the “current_page_parent” class on that menu item to highlight it. We need to prevent this happening for the post type.
  2. WordPress doesn’t appropriately highlight the menu item you create that links to your post type’s archive. We need to highlight this menu item if viewing post(s) from that post type. We can do this by adding a class like “current_page_parent” to that menu item at the appropriate times.

Before we get the code, we’ll need a way to specify that a certain menu item is to be used for this purpose. To do this you need to know another little trick that you may (or may not) know about.

When editing menus, you can use the “Screen Options” menu in the top right of the edit screen to show some extra fields for each menu item. Importantly here, you can turn on “CSS Classes” from the “Advanced menu properties” section of the Screen Options menu. Once this is enabled you can add a CSS class to your menu item. The code below uses the class “post-type-xxx” where xxx is your post type’s name.

So, in summary, to use the code below you’ll need to:

  • Add a menu item to your menu that links to the index of your post type
  • Add the “post-type-xxx” class to the menu item as described above
  • Add the code below to your functions.php, or other suitable file
  • Sit back and watch the magic!

Here’s the code for the filter:

/*
 * This filter fixes an issue where the blog page is highlighted as a menu item
 * for archives/singles of other post types.
 */
add_filter('nav_menu_css_class', 'mytheme_custom_type_nav_class', 10, 2);

function mytheme_custom_type_nav_class($classes, $item) {
	$post_type = get_post_type();

	// Remove current_page_parent from classes if the current item is the blog page
	// Note: The object_id property seems to be the ID of the menu item's target.
	if ($post_type != 'post' && $item->object_id == get_option('page_for_posts')) {
    	$current_value = "current_page_parent"; 
    	$classes = array_filter($classes, function ($element) use ($current_value) { return ($element != $current_value); } );
	}

	// Now look for post-type-<name> in the classes. A menu item with this class
	// should be given a class that will highlight it.
	$this_type_class = 'post-type-' . $post_type;
	if (in_array( $this_type_class, $classes )) {       
    	array_push($classes, 'current_page_parent');
	};

	return $classes;
}

Getting static images for YouTube videos ready for your WordPress posts

This one’s a little complicated, but it’s a neat trick to getting static images for YouTube videos ready for your WordPress posts.

Lets say you want a site that uses lots of embedded YouTube videos. You want to show an index of these videos on your front page, or as an archive, but you don’t want to fetch an embed from YouTube for every video – you’d rather use something like featured images, but without having to do a screen grab, crop it, resize it, and upload.

Well, here’s a snippet that creates an automatic thumbnail from a YouTube URL when you save a post. To make this work you will need a piece of meta-data (the snippet uses ’_mytheme_embed_url’). When a post with this meta data item is saved, the snippet creates a new meta-data item called ’_mytheme_video_img_url’ with the URL of the thumbnail in.

You can use the thumbnail in your theme by doing something like:

  $preview_img = get_post_meta( get_the_ID(), ’_mytheme_video_img_url', true );
  if ($preview_img) {
    printf( '&lt;img src=&quot;%s&quot; /&gt;', $preview_img );
  }

Here’s the snippet:

// This action attempts to generate a YouTube thumbnail URL from the provided YouTube URL.
add_action( 'updated_post_meta', 'mytheme_generate_youtube_url', 10, 4);
add_action( 'added_post_meta', 'mytheme_generate_youtube_url', 10, 4);
function mytheme_generate_youtube_url( $meta_id, $object_id, $meta_key, $meta_value ) {
    if ($meta_key == '_mytheme_embed_url') {
        if (strlen($meta_value) &gt; 7 ) { // Eliminates default 'http://'
            if (preg_match( '/youtube.com/', $meta_value )) {
                if (preg_match ('/\/embed\/(.*)/', $meta_value, $vid_matches )) {
                    $vid_tmp = $vid_matches[1];
                    $vid_tmp = explode('?', $vid_tmp);
                    $vid = $vid_tmp[0];
                } else {
                    $url_query = parse_url( $meta_value, PHP_URL_QUERY );
                    parse_str( $url_query, $params );
                    $vid = $params['v'];
                }
            } elseif (preg_match( '/youtu.be/', $meta_value )) {
                $vid = ltrim( parse_url( $meta_value, PHP_URL_PATH ), '/');
            }
            if ($vid) {
                $img_url = sprintf('http://i.ytimg.com/vi/%s/hqdefault.jpg', $vid);
                update_post_meta( $object_id, '_mytheme_video_img_url', $img_url );
            }
        }
    }
}

There’s a full write up of this on my own blog.

Credits:

This is mostly my own collation of things I found elsewhere so here are my sources – with thanks!

Add Custom Columns to WordPress Post Type Lists

The combination of custom post types and custom meta boxes is a powerful one for using WordPress as a content management system. But if key data about a post is stored in meta boxes it’s often helpful to see it in the list of posts.  For example, the “Countries” post type shown below benefits from some custom columns, including one that displays a little flag.

This snippet lets you modify, and add to the  columns for a given post type. The comments explain as we go. Be sure to edit the <prefix> and <post-type> to be your own.

// Add a filter to add extra columns for a specific post type's edit list
add_filter("manage_edit-<post-type>_columns", "<prefix>_<post-type>_edit_columns");

// Add an action to populate the custom columns
add_action("manage_<post-type>_posts_custom_column", "<prefix>_<post-type>_custom_columns");

// This function takes an array of columns and should return an array of columns.  It should add
// to the list of columns that's given as an input.  The array keys are column ID strings and the array
// values are column heading strings.
function <prefix>_<post-type>_edit_columns( $columns ) {
    // Add the extra custom columns
    $columns['logo'] = 'Logo (Featured Image)';
    $columns['link'] = 'Link';
    return $columns;
}

// This function is called for all columns.  It takes a string that's a column ID from the $columns
// array mentioned above.  The function should determine which column is being output and output the
// content of that column for the current post.  Note the column content should be OUTPUT, not
// returned.
function <prefix>_<post-type>_custom_columns( $column ) {
    global $post;

    // This gets all the custom meta for the post in an array.
    $meta = get_post_custom( $post->ID );

    switch( $column ) {
        case 'logo':
            if (has_post_thumbnail( $post->ID ) ) {
                // This returns an array containing url, width and height.
                $image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'small' );
                // To access the URL of the thumbnail we need to use $image[0]
                printf( '<img src="%s" alt="" height="32px" />', $image[0]);
            }
        break;
        case 'link':
            if (isset($meta['link-url'])) {
                printf( '<a href="%1$s">%1$s</a>', $meta['link-url'][0]);
            }
        break;
    }
}

I’m indebted to Rev VooDoo and this WordPress support post for the idea. I hope I’ve refined it slightly and given a bit of insight into its workings.