Hide custom post types provided by a theme to prevent theme lock-in. Or just to declutter the admin area.
Custom Post Types (CPTs) were introduced in WordPress 3.0 back in 2010. This was a significant enhancement (maybe even revolutionary) and opened up so many possibilities. I used a CPT for Special Offers for the Body Connection Spa site.
In the competitive themes market some themes attempt to be the complete solution, often including features that should be provided by plugins. Some include CPTs to manage features in the theme.
When I was developing the Cork Entertainment event listing site I decided to hide some of the CPTs that were included with the theme that the client had purchased. The majority of them were not being used on the site and were only cluttering the admin area and confusing to the client. Furthermore, there was an ‘Events‘ CPT that conflicted with the ‘Events‘ CPT provided by the Events Manager plugin.
I also wanted to avoid “theme lock-in” where changing the site theme would result in lost data. Well, it wouldn’t truly be lost as it is still in the database, but the code to make use of it would be gone (as it was part of the deactivated theme).
Within the parent theme, I couldn’t see a way to prevent the CPTs from being registered. Nor could I see a filter in the core register_post_type() function to modify the CPT arguments before the post type is created. There was a do_action() call but I didn’t think that it would be useful – I always believed that only apply_filters() calls can change data.
Hiding the Theme CPTs
I searched around and found that the do_action() call was the route to the solution. By modifying the $wp_post_types global, the CPT’s arguments could be modified and take effect immediately. I found a post describing Altering Registered Post Type Args (with a great example).
Back with the client’s theme, I looked up the post type names in the theme source and put those names in an array. The code simply checked whether the passed post type was in the array before hiding it. Unfortunately this wasn’t quite right – it also hid the Events Manager Events CPT too!
After a bit of debugging and displaying the complete post type arguments, I found a difference between the theme’s Events type and the Events Manager’s type – Events Manager included a description while the theme’s one didn’t! Phew! Now I had something to use to distinguish them.
I updated the code to check for the description, skipping that CPT if it is set to ‘Display events on your blog.‘