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.

Admin Customisations for a 1-Page WordPress Site

Recently I was tasked with creating a fairly straight forward 1 page website in WordPress. It was one of those sites with the different sections and the main navigation scrolls you down to the correct section. The trouble was that for such as a simple website the admin experience was very complicated. Therefore I set about trying to make the admin more like the front end – more simple. Here is how I got on.

I have blogged and spoken about admin customisations before and those people that know and have worked with me know that it is something I both enjoy working with and something I feel is a little underdone at times with many WordPress websites. We spend all our time focussing on the front-end (which is not a bad thing in itself) but little time thinking about the experience for the person or people that have to manage the website.

The site that was in question is shown below and was designed by the team at Pixel Junction.

c-capital

First a little bit about the setup I used with the website. As everything was on 1-page it kind of makes sense to me to make everything editable from within a page in WordPress. Therefore I created a page titled home and then set this as the front page under Settings > Reading.

The first step was then to edit the post edit screen for this page to better reflect the front end of the site.

The page itself was separated in four sections:

  • Header with background image including the navigation
  • Services section,
  • Contact us section
  • Footer area.

Therefore I went about creating these in the backend.

To do this I used the excellent Custom Meta Boxes library/framework/plugin by Human Made (although there are a lot of other alternatives out there!). This allows me to quickly add additional meta boxes on the post edit screen, in order to better reflect the front-end. I could then add fields into these meta boxes which I could pull through to the front end rather than having the traditional content box. Below is what this page’s edit screen looks like:

1 Page Post Edit Screen Customised

Inside each of the meta boxes I could then add the custom fields necessary for the front end. Below shows the header content section expended.

Post meta (Custom Fields) can be displayed inside each meta box.

In this post I won’t go into how these fields are pulled through onto the front end, other than to say that all of the data in these meta boxes is stored as post meta for this page and therefore using the get_post_meta() function allows us to do this.

The next issue to tackle was the menus in the admin. I wanted to end up with the following menu items in the left in the WordPress admin to clean things up and little removing menus that would not be needed:

  • Dashboard – which was actually my custom dashboard using my WP Basis plugin
  • Media
  • Forms – the site would use Gravity Forms for the contact form
  • Content – this would be a link straight to the page edit screen for our front page
  • Menus
  • Users
  • Site Options – I was using the options framework plugin to provide a few additional details such as telephone number etc. although could actually have added them to the page itself on second thoughts!

To do this I needed to do some admin menu modifications. I won’t go into great detail here as I have written before on altering the WordPress admin menus. Using the techniques outlined in that article I was able to add a menu titled content that went straight to my front page edit screen, remove some menus and add some others such as Menus which just went straight to the WordPress menu management page usually found under appearance. I was then left with this:

A new WordPress admin menu for a 1 page site.

The final thing to do was to make it so that when the user logged in, they were taken straight to the page edit screen for the front page as this is where most of the content for the site is. This can be done easily by utilising the login_redirect filter and setting the location of the redirect to the same link as the new content menu.

This all works very well but there is one more thing to do and that resolves around capabilities. Normally next to the “Edit Page” title on the page edit screen there is an “Add New” link. This would allow the user to add new pages. However we don’t want them adding new pages and causing confusion. Therefore we can utilise WordPress’s capabilities and remove the capability of adding new pages.

To do this in my example I used the filters included in my WP Basis plugin, however you can do this using the user_has_cap filter. The capability to remove is the edit_pages capability. This will ensure that the add new link is removed.

So there we have it a better front and back-end experience for not much extra work. I would love to hear your thoughts and comments about how you do something similar.

Altering WordPress Admin Menus

Over the last few months I have worked on a number of projects that have required some modifications to the WordPress admin screens. Sometimes it was just to make things easier for the client and others I needed to add different menus and admin pages for various reasons. One task I undertook required me to move WordPress admin menus around, and have them display under different top level menus. Here is how I managed to add, remove and edit the WordPress menus.

WordPress core provides us with a lot of tools and functions for editing both the WordPress admin and the WordPress admin menu items.

Adding Top Level Menu Items

The WordPress admin menu is two-tiered. By that, I mean there can be two levels of menu items. Top level menus such as Appearance can have sub level menus beneath them such as Widgets. You can add top level menus really easily by using the following code in your own plugin (or theme functions file but I would not recommend that).

You will see the function takes 6 arguments which are needed. Lets take a look at what these are:

  1. Page title – this is the text that is added to the pages <title> tags in the head of the page
  2. Menu title – this is the label given to the menu in the WordPress admin. This is what the user sees in the admin.
  3. Capability – this sets what capability a user needs in order to be able to see and have access to this menu
  4. Menu slug – this is a unique slug to which this menu items if referenced by
  5. Callback function – the callback function is the function used to output the pages content once the menu item is clicked
  6. Icon – this is the icon that displays next to the menu title. You can pass a dashicon string here or pass div which can then be styled with an admin stylesheet.
  7. Position – this sets where your menu items will appear in the list of menu items. Take a look here for what the position of each core menu is

Notice how the function we build, which includes the call to add_menu_page() is added to WordPress using the admin_menu action hook.

This code will now add your menu to WordPress. However when you click on your menu you will get an error. The reason for this is that WordPress is trying to find a function with the name we gave to the callback arg in the function, in order to display the pages content. However we have yet to create this.

The next step then is to create this callback function which would be something like this. Obviously you would add your pages content to this function depending on what you wanted to output.

Adding Sub Level Menu Items

We call also add a menu as a child of another menu. This is handy for adding plugin settings and the like as you would and probably should be adding this under the Settings or Tools menus. The code below would enable you to add a sub menu under tools.

Again this function takes 6 arguments so lets take a look at what these are:

  1. Parent Slug – this is the menu slug of the parent item you wish to add your submenu item to. Here we use tools.php to have it display on the tools menu. We could also use a slug that we previously declared in our function above, to have our sub menu item display under a top level menu we created.
  2. Page Title –┬áthis is the text that is added to the pages┬á<title>┬átags in the head of the page
  3. Menu Title –┬áthis is the label given to the menu in the WordPress admin. This is what the user sees in the admin.
  4. Capability –┬á┬áthis sets what capability a user needs in order to be able to see and have access to this menu
  5. Menu Slug –┬áthis is a unique slug to which this menu items if referenced by
  6. Callback Function –┬áhe callback function is the function used to output the pages content once the menu item is clicked

The callback function works in the same way as for adding a top level menu.

Moving Existing WordPress Menu Items

As part of the work I was doing it required moving top level menus underneath other top level menus to make them a sub menu item. This can be done it two parts. The first part is to remove the original top level menu from the WordPress admin menu and the second is to add it in again as a sub menu item.

Lets start be removing the top level menu item for Posts.

The only argument passed to the remove_menu_page() function is the slug of the top level page you want to remove. Passing edit.php removes the posts item.

Now we have removed the posts menu item we want to add it back in as a sub menu of our top level menu we added above. If you remember the slug we gave to this menu item was wpmark_admin_menu which we need when adding posts back in.

We can use the following function in order to add the posts menu as a sub menu item.

You will notice that the menu slug we have passed above is edit.php which is the slug of the posts top level page. We could have passed a final arg which would be a callback function, but as the posts page already exists we don’t need to.

Correcting Menu Hierarchy

One thing I have come across when working with menu items is that you also need to alter the menu hierarchy. For example if we move posts into another menu it works fine, however when we now click on the posts sub menu item, it closes the top level item we were in because the posts parent file is not set, as originally it was a top level menu item. We can correct this using the parent_file filter.

This will now keep the top level page open when on the sub page of posts. There are one or two strange goings on with this filter that sometimes prevent this from working. I found in particular moving pages to a sub level menu this caused problems on. This trac ticket offered a fix.

Remove Dashboard Menus for Specific Users

For a while now I have been using some simple code to remove the dashboard menus in WordPress, primarily so that clients can’t change certain settings and ‘break’ their sites. However the code I was using also removed those items for me too. This meant I had to memorise the admin URLs and visit them manually which is not ideal. Today I have managed to solve this problem by hiding WordPress dashboard menus for all except specified users.

The trick is to wrap your code around an if statement that first checks who the user is. The code I am using is below:

Basically the code grabs the current users user ID and then compares it to a list of allowed users. If is matches the function returns nothing, if it doesn’t match then it removes the specified menus in the WordPress admin areas.

In this example users with the ID 1 and 2 can see all menus, however the WordPress links menu will be removed for all other users. It is important to note that this code only removes the menus from view and doesn’t stop users from actually viewing these pages. If they know the URLs they will still load.