Changes to Registering Custom Post Types in WordPress 4.4

Whilst building a plugin recently I found a change in WordPress 4.4 which actually broke my plugin, but was very easy to fix. The problem was with a custom post type that had completely disappeared from the admin menu. Here is why it disappeared and how I got it back again!

First a little background about the plugin in question. It used a post type in order for the user to add a single post. The content of this single post was then outputted with a shortcode and therefore I did not want the post type to have a permalink page at all. For this I had set the public argument used in register_post_type() to false. I also did not want the regular post type menu item to show in the backend, as I was adding my own menu item and therefore I had set the show_ui argument to false too. This worked fine in WordPress 4.3.1 and when I added my own menu item using add_menu_page() which used the edit post screen for the content for a post within the custom post type the menu item showed up no problem.

When I recently upgraded the site to WordPress 4.4 there was a large problem. The menu item completed disappeared. After some digging around and making some changes to test what was going on, I found the problem. The fix was to set show_ui to false but to set show_in_menu to true.

When I tweeted about this issue, John Blackbourn, one of the core developers kindly responded with a link to a post outlining the changes.

Sort Posts by Term on Custom Post Type Archives

When building sites with WordPress I often make use of custom post types to add custom content types. I also use the custom post type archives in order to display an archive of this content. Recently I came across an issue where I wanted to be able to list posts on the archive grouped by terms from a taxonomy. Having quickly found out this was not so easy, I set about trying to find a solution.

The client site I was working on wanted to have a meet the team page. In fact this is a popular request amongst clients and something I often have to do. Therefore to achieve this I use a custom post type called person (prefixed of course). For the purpose of this post the custom post type is called wpmark_person.

This particular project was very specific in that it needed to have the people in the team split into the different sections they belonged to in the company e.g. Senior Leaders, Teachers etc. To achieve this grouping of posts I used a custom taxonomy which was named wpmark_person_type.

Now came the issue of displaying the team members. The design called for a page which was split into different sections, each section being a type of person (the different person types from my taxonomy). The people belonging to that section where then listed under those headings (as a thumbnail images) and each section was collapsed by default (I used jQuery to expand/contract the section but that is not covered here). Clicking the person type title revealed the actual people, in this case an image linking through to the person single post view.

Below is a wireframe of what the page layout for the meet the team would look like.

The wireframe provided indicated a different sorting of posts.
The wireframe provided indicated a different sorting of posts.

With custom post types you can declare an argument when register the custom post type of whether or not you want it to have an archive. This archive, like posts (your sites blog in a vanilla WordPress install) lists the posts in chronological order with the newest first, paginated according the number of posts per page set in the WordPress settings area for reading.

Essentially this was what I wanted, however I just wanted to order them differently and show them all. Instead of ordering them by date, I wanted to have them ordered by term from the person type taxonomy. Therefore all posts from one term and then all posts from the next etc.

In essence this is straight forward to do, but would require you to add lots of custom loops to the archive using WP_Query. This was something that I didn’t really want to do as it would mean that I am querying things twice. WordPress would query the person posts (as normal for the post type archive) and then I would throw this query away and get the posts again within the different terms. As I already have the posts I want and it was just a matter of re-ordering them, I decided there must be a more efficient way and went about tying to find a solution. First I posted on the WordPress.org support forums after Google searches revealed little.

I posted on the WordPress Support Forums for a Solution
I posted on the WordPress Support Forums for a Solution

After much trial and error and testing I landed on a solution that worked. Using the Query Monitor plugin I could see that it only added one more query to the page, which I thought was reasonable. My solution is as follows.

The first part was to make the archive show all the posts for that post type. I did not want pagination here and therefore wanted every person to be listed, albeit in their respective person types. To do this I used the excellent pre_get_posts action which allows you to change the query parameters WordPress uses before it actually queries the database for posts. Below shows the code to do this:

https://gist.github.com/wpmark/6e31f167c3fe6e4e411c

So now I have a post type archive that queries all the person posts. I can access these by the normal loop, however I needed to do some ordering before that. Therefore I need to get the post objects for these posts and manipulate them. I can access my posts through $wp_query->posts which is what I needed.

The next part was to create a function that would output an array of all the posts, split into the different terms they were assigned to. Essentially the output of my function would be like so:

https://gist.github.com/wpmark/08fda1934286e3e20207

The function that I used to do this was like so:

https://gist.github.com/wpmark/9da1176af487d744d2c7

Lets talk through what this is doing. First we set some default args, which can of course be changed if passed through to the function as an array of parameters. We then create an empty output array to fill with all the terms and posts.

The first real part in the function is to get all the terms from the taxonomy (in this case are person type taxonomy). This is actually the one additional query that is carried out on the page. When we do this we are going to order them by their ID. The one created first, is shown first although we could order by name etc. We are also going to just return the term names here to keep the query as light as possible as the name is all we need to output on the page.

We then loop through each term, adding the term name as a key to our output array. Next we loop through all the posts (remember these were queried in the normal process of using a post type archive and we passed them to this function using $wp_query->posts). Inside this loop we get all the terms this post has (it should only be one as the UI for this taxonomy only enable one term to be assigned) and then push this post object into an array inside our output array for this term. Finally we return the entire array, which is now sorted into terms and posts.

Back on the post type archive template now we can use this code to output the posts.

https://gist.github.com/wpmark/2dd9265f9e4d3316dc17

Summarising the above code, we loop through the top level elements of the array first outputing the term name as a title. We then do a second loop through to output the posts within that term.

The output of the page looks lie this:

Custom Post Types Archive with Posted Ordered By Term
Custom Post Types Archive with Posted Ordered By Term

So there you have it, if you ever want to sort posts by a specific taxonomy term of a post type archive you can do it with just one additional query.

WP Post Type Meta WordPress Plugin

Working with custom post types for the last 3 or 4 years has on the whole been great. However there was always one thing that I found lacking and that was the lack of an (editable) post type description. Therefore I set about to try and change this, adding some extras along the way. Let me introduce the WP Post Type Meta WordPress plugin.

I must start off this post by letting you know that this idea is not new. In fact my idea for this came from Steven Jones in his post 5 Improvements to WordPress’ User Experience. In this post Steven added a simple link to a plugin that adds a post type description to custom post types. Essentially this is what WP Post Type Meta does “out of the box”, however I wanted to take this further and allow further meta to be added to custom post types.

Screen Shot 2014-12-01 at 18.40.59

The need for this was seen when I was working on sites that made use of the term description field in a taxonomy term. This description is often displayed at the top of the archive for that term to indicate the nature of the posts found in the term archive. This was something that a lot of my clients wanted for custom post types. For example many want an FAQ section and I often deliver this through a custom post type with an accordion style jQuery addition on the front end. The post type archive acts as the FAQ page. However many clients wanted to have a paragraph of text appear at the top of this archive to explain the page. The problem them comes as to how to allow the client to edit the text. There are other ways to achieve a solution to this such as a page that is pulled in at the top and also a theme option style settings, however I was not really happy with either. Steven’s post type description plugin did the job.

This got me thinking that we could actually add other fields to the post type description page added in the admin. For example what if you had a post type about products and you wanted to add a standard sizing link to a PDF that would show on the archive page at the top in useful info. You can easily add a text input box and add your link into that or even a post type select input to choose a page for the sizing information.

This is what the WP Post Type Meta plugin does. It provides an additional sub admin menu for each custom post type in your site named {Post Type} Meta. By default on the page is a description box to add a post type description, however the plugin is extensible and easily allows you to add other fields including text, textarea, WYSISYG, select and checkbox inputs. The post type description field is added in this way.

All of the plugin meta data is stored in the WordPress option named wpptm_meta as an array. Each piece of meta added is prefixed with the post type name. For example to get the post type description field you would use the following:

https://gist.github.com/wpmark/2dbb0d59c898acd4adda

You can add your own fields by using the wpptm_settings filter. The example below shows you how to add a select input:

https://gist.github.com/wpmark/8d96847316d5f46a6174

Other fields can be added in a similar way. The field above would be retrieved on the front end like so:

https://gist.github.com/wpmark/aa92cc2ee556f7d7c9f0

I have tried to build the plugin in an extensible way to allow developers to build upon and extend its functionality. I look forward to using it in the future.

You can download the WP Post Type Meta plugin on WordPress.org or add it to your site through your WordPress dashboard.

Altering Registered Post Type Args

Today I was working on a project where I needed to change how a post type had been registered. The post type in question was setting public to false, so the post type was not a public post type. However I was utilising the post type somewhere else and needed to change this. Here is how I went about it.

Obviously when doing this I did not want to change any core or plugin code. The plugin creating the post type was the excellent whistles plugin from Justin Tadlock. This is a plugin that enables you to add snippets of content here and there including adding stuff in accordions and tabs etc.

I wanted to to use the post type as a featured content slider with the Soliloquy slider plugin. However the problem was that the post type did not exist in the drop down to select when creating a new slider. Having looked at the way in which the Whistles plugin registered its post type, it was clear that the reason it wasn’t showing as a post type to choose in the slider was because the post types ‘public’ arg was set to false. Therefore I set about finding a way to change this without chaining the plugin itself.

The first thing I did was to find in the plugin files where the post type was registered, hoping for a hook or filter which I could use in order to change the args when registering the post type. However in inspection it became clear nothing was present. This left me looking in core.

I found the file containing the function register_post_type() and noticed at the bottom of this function is a cal to do action named registered_post_type. Passed to this action is the post type name and the args for registering that post type. This meant that I could use this action in order to change any of the registered post type args.

Below is the code I used in order to change the public arg from false to true.

[wpmark_gist id=”86a965d71a6a7333ddd9″]

You can change any of the args that are registered. A dump of the ‘args’ from that function shows the following:

[wpmark_gist id=”292d91a50c6c9bafa009″]

Therefore any of these can be changed in a similar way.

WordPress Press This With Custom Post Types

A few days ago I posted a question on twitter asking about the use of the WordPress Press This feature with custom post types. As I use a custom post type on this site for my Bookmarks I wanted to be able to use the WordPress Press This feature to quickly add a bookmark to my site. After a response from @_mfields I have managed to create a solution.

Continue reading WordPress Press This With Custom Post Types

Using Nivo Slider with WordPress Custom Post Types

I have been using the Nivo Slider for a while on a number of sites, mainly using a function to grab all the images from a particular WordPress post or page and then showing these in the Nivo Slider. Then I found out that it could take HTML for the captions and therefore wanted to use this for a “Featured Content” slider on a website. The featured content post would be a WordPress custom post type. Here is how I did it.

The first stage is to install the Nivo Slider onto your WordPress theme following the excellent and simple to follow instructions provided by the author at dev7studios.com. Once this has been completed and you are happy that the Nivo Slider works correctly then we can start with the fun stuff, by making it show information from our custom post type. In this example I named by custom post type ‘rs_featured’. You should always prefix your custom post types.

In order to display the images in the slider I wanted to make use of the WordPress featured image function which using the_post_thumbnail() in your themes template files – in my case header.php. The first step is to set up a new WP_Query in order to provide us with a custom loop to query posts from our rs_featured custom post type. To do this I used the following code:

<?php
$pj_slider = new WP_Query('post_type=rs_featured&showposts=4'); while($pj_slider->have_posts()) : $pj_slider->the_post();

    // we will do stuff in here later

endwhile;
?>

What this does is that it queries the latest 4 posts from our custom post type. Now we have to decide what we are going to show for each of the posts that are returned and then add this code inside the above loop. With the Nivo Slider instead of using the images title as the caption text you have the options of using HTML. To do this you need to set the title attribute of the image to a unique CSS ID for each of the posts. To do this we will use the posts ID as this is always unique. Therefore I set up the following variable to store the CSS ID that I wanted to attach to the title.

<?php $pj_slider_caption = '#slider-caption-'.get_the_ID(); ?>

We now have a the unique ID setup. Therefore we can go back our code above and add the image from the posts featured image so that this shows for each of the posts in our custom post type. The code for the loop should now look like this:

<?php $pj_slider = new WP_Query('post_type=rs_featured&showposts=4'); while($pj_slider->have_posts()) : $pj_slider->the_post(); ?>

<?php $pj_slider_caption = '#slider-caption-'.get_the_ID(); ?>

<?php if(has_post_thumbnail() ) { ?>
<?php the_post_thumbnail('slider', array('title' => ''.$pj_slider_caption.'')); ?>
<?php } ?>

<?php endwhile; ?>

We pass the new caption ID to the title attribute of the featured image inside the_post_thumbnail() function as an array. The next stage is to set up a DIV that uses the same ID we created above (#slider-caption-theid) as well as the class nivo-html-caption. As we need one of these divs for each of the posts in the loop, so we need a secondary loop, which is similar to the first. The code for this, to be placed underneath the first loop which shows the images is as follows:

<?php $pj_slider_caption = new WP_Query(‘post_type=rs_featured&showposts=4’); while($pj_slider_caption->have_posts()) : $pj_slider_caption->the_post(); ?>

” class=”nivo-html-caption”>“>Read more about this feature »

<!– // nivo-html-caption –>

<?php endwhile; ?>

We are using the posts excerpt as the captions content as well as the post title above the content. Now all you need is to use CSS in order to position and style the caption area as required. This has provided a really useful piece of code and I will no doubt be using it on a few more sites to come. Thanks to Dev 7 Studios for a great jQuery slider.