Back in June I posted about tidying up the WordPress admin dashboard. Recently I got a comment on that article asking if the admin menu could be altered for different users in a similar way.
Here’s the question:
Can I lose the “add new” under Pages drop down for editors? I don’t want them to have the ability to create new pages.
I’ve played with the WordPress admin menu a bit before now. There are two global variables which allow you to add (although there are much better ways to do this) and more importantly remove items from the WordPress menu. These variables are $menu for top-level menu groups like “Posts”, “Media” and $submenu for managing the sub-level items like “Add New” or “Library”.
In this case, we only want to remove the “Add New” sub-menu item from the pages menu, so we only need to use $submenu. If you use var_dump or print_r to display the contents of $submenu you’ll see the part of the array for the “Pages” menu looks like the snippet below. It contains two entries: one for the “Pages” listing which allows you to edit pages, and one for the “Add New” link that we want to remove. Also note: for each sub-menu item there are three pieces of information: The text to show, the capability the user must have to see this link, and the relative URL for the menu item.
*Please note: all of the following will also work for posts. You will need to substitute the word “page(s)” for “post(s)” and follow the additional instructions. For other parts of the WordPress admin you’ll need to find the right URLs, sub menu items and capabilities. All code should be placed in your theme’s functions.php file. Full code example is here: functions.php [ZIP File]
'edit.php?post_type=page' =>
array
5 =>
array
0 => string 'Pages' (length=5)
1 => string 'edit_pages' (length=10)
2 => string 'edit.php?post_type=page' (length=23)
10 =>
array
0 => string 'Add New' (length=7)
1 => string 'publish_pages' (length=13)
2 => string 'post-new.php?post_type=page' (length=27)
With all this in mind, the simplest way to remove the “Add New” link from the pages menu, is to unset this part of the array before the menu is drawn. We can create a function to do this in the functions.php file, first declaring the $submenu global variable and then unsetting the bit that we don’t want. Finally we need to add our function to the admin_menu action hook so that it is called at the right time.
1 2 3 4 5 6 7 8 9 10 11 | // functions.php function modify_menu() { global $submenu; unset($submenu['edit.php?post_type=page'][10]); // for posts it should be: // unset($submenu['edit.php'][10]); } // call the function to modify the menu when the admin menu is drawn add_action('admin_menu','modify_menu'); |
At first glance we’ve now achieved what we set out to do – the “Add New” link is removed from the menu, however this doesn’t really solve the underlying problem. The url for adding a new page is post-new.php?post_type=page and because we haven’t changed the permissions of an editor they can still access the page. Furthermore, there is also an “Add New” link at the top of “Pages” list page – so they can also still find the page easily.
So what we really need to do, is change the capabilities of the “editor” role. In WordPress each role has a set of “capabilities” or permissions – things they are allowed to do. The capability that allows someone with the “editor” role to access the Add New Page screen is “edit_page”, however if we remove this capability we will lose the whole “Pages” menu and also stop them being able to edit pages.
There is no way to use capabilities to restrict access to the Add New Page screen without also restricting access to the Pages list & Edit page screen. However, we can stop people from being able to publish pages using the “publish_pages” capability – this means they can create pages but they won’t appear on the website. Although this isn’t a perfect solution, it seems like a good start.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // functions.php function modify_capabilities() { // get the role you want to change: editor, author, contributor, subscriber $editor_role = get_role('editor'); $editor_role->remove_cap('publish_pages'); // for posts it should be: // $editor_role->remove_cap('publish_posts'); // to add capabilities use add_cap() } add_action('admin_init','modify_capabilities'); |
The above snippet shows a function which gets the “editor” role and removes the “publish_pages” capability. This is hooked into “admin_init” so that it is run on each admin page. Now when editors go to the Add New Page screen they will only be able to “Submit for review” not publish the page. So now we know how to both actually stop users from creating pages AND remove the sub-menu item.
Now that we’re working with capabilities, we can change our modify_menu function to do the same. Instead of completely unsetting the menu item, we can set the capability so that it only works if the user has the capability “publish_pages”. This is just a slightly nicer way to hide the menu item – you could grant one specific editor user the “publish_pages” capability and they would still be able to access the menu item.
1 2 3 4 5 6 7 8 9 10 | // functions.php function modify_menu() { global $submenu; $submenu['edit.php?post_type=page'][10][1] = 'publish_pages'; // for posts it should be: // $submenu['edit.php'][10][1] = 'publish_posts'; } add_action('admin_menu','modify_menu'); |
Next let’s get rid of that pesky “Add New” button on the Pages list screen. There doesn’t seem to be a hook we can use to do this, so instead I’ve used good ol’ fashioned CSS. We check if we are on the “edit-page” screen using the $current_screen global variable and if the user has the “publish_pages” capability using the current_user_can method. Then we spit out some CSS to hide the button and hook this into admin_head to the CSS is output in a sensible place.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // functions.php function hide_buttons() { global $current_screen; if($current_screen->id == 'edit-page' && !current_user_can('publish_pages')) { echo '<style>.add-new-h2{display: none;}</style>'; } // for posts the if statement would be: // if($current_screen->id == 'edit-post' && !current_user_can('publish_posts')) } add_action('admin_head','hide_buttons'); |
Now we have editors which cannot see the “Add New” link in the Pages menu, or the button on the Pages screen, so there’s no easy way for them to get there. Even if they are clever enough to figure out the URL they won’t actually be able to publish their pages. However if we want to go the whole hog, we can add a bit more code to redirect them from the Add New Page screen and show them an error message.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // functions.php function permissions_admin_redirect() { $result = stripos($_SERVER['REQUEST_URI'], 'post-new.php?post_type=page'); // for posts result should be: // $result = stripos($_SERVER['REQUEST_URI'], 'post-new.php'); if ($result!==false && !current_user_can('publish_pages')) { wp_redirect(get_option('siteurl') . '/wp-admin/index.php?permissions_error=true'); } // for posts the if statement should be: // if ($result!==false && !current_user_can('publish_posts')) { } add_action('admin_menu','permissions_admin_redirect'); |
The above is an additional function to test the current request URI. If it matches the Add New Page screen AND the user doesn’t have the “publish_page” capability we redirect them to the admin dashboard. The dashboard URL is /wp-admin/index.php, but I’ve added permissions_error=true so that WordPress will know to show an error message.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // functions.php function permissions_admin_notice() { // use the class "error" for red notices, and "update" for yellow notices echo "<div id='permissions-warning' class='error fade'><p><strong>".__('You do not have permission to access that page.')."</strong></p></div>"; } function permissions_show_notice() { if($_GET['permissions_error']) { add_action('admin_notices', 'permissions_admin_notice'); } } add_action('admin_init','permissions_show_notice'); |
Finally, two more functions and one more action hook. The first to draw an error message / warning to the user, and the second which checks the “permissions_error” parameter and shows the error message if it is set. Now there is absolutely no way for an editor to get to the Add New Page screen, instead they will be redirected to the dashboard and shown an error.
So this all turned out to be ever-so-slightly more complicated that I expected because there is no way to distinguish between the permission to edit and the permission to add a page or post. However, like most things in WordPress with a bit of graft it’s usually possible! I hope this has been useful, if you got lost or something doesn’t make sense or you know of a better way to do this please let me know via the comments.
Code Example: All code should go into your theme’s functions.php file. You can download the complete code sample with comments right here: functions.php [ZIP File]




30th Aug
Laura says:
Wicked. Bookmarked. Finding these ways to hide certain admin functions very useful for when you’re dealing with non web-savvy (or fidgety!) clients :)
30th Aug
ErisDS says:
Yeah they can be really useful! Also if you’re trying to customise the admin, login or register pages, or the emails sent then the Register Plus plugin is really good.
30th Aug
Laura says:
Oooh, handy. Ta!
6th Sep
Laurent says:
Hi,
Waou this is very clear and thank you for the coding of functions. I only have a small issue : where do I inject this ? I tried in the functions.php of wp-includes folder but got WSOD ?
Thank you ErisDS ;)
6th Sep
ErisDS says:
Apologies for the lack of clarity.
You need to place the code in the functions.php of your theme e.g. in wp-content/themes/your-theme-name/functions.php
I hope this helps?
Eris
1st Oct
gary says:
Too bad this doesn’t work. I love it and its exactly what I need, but when I add it to the functions file in my theme under WP 3.01 nothing happens. What do i do to get this working?
1st Oct
ErisDS says:
You should be able to copy the code from the download into your functions.php file and have it work. Is that what you have done?
5th Oct
nikesh says:
well, thanks a very helpful code , but i was wondering what we could hide the whole thing,and both posts and pages they dont appear at all , what change is needed in the code
5th Oct
ErisDS says:
Am I right in my understanding, you want to know how to completely remove both the Posts and Pages menus?
8th Nov
Dion says:
ErisDS,
This is by far the most logical, easy-to-follow, concise, COMPLETE description I’ve seen of this process, and I’ve been searching for days.
Here’s the question I have: how can I modify the CSS “remove the button” module to wipe out the deactivate links in the plugins menu?
Assuming that only administrators can edit themes, I’m guessing the code change for this particular section would look like this:
2
3
4
5
6
7
8
9
10
11
12
function hide_deactivate_plugins()
{
global $current_screen;
if($current_screen->id == 'plugins' && !current_user_can('edit_themes'))
{
echo '<style>.deactivate{display: none;}</style>';
}
}
add_action('admin_head','hide_deactivate_plugins');
Is that about right?
Basically, I want to allow my clients or virtual assistants — who will not have administrator roles, but a custom role called Manager that does not include theme editing capability — the ability to do everything BUT deactivate plugins in general, or even better, specifically the “User Role Editor” and “Adminimize” plugins I use together to effectively hide and protect my administrator user account, roles and capabilities.
Or do you know of another way to create a role or assign capabilities that enable everything except modifying or deleting my administrator account? I tried the Members plugin by Justin Tadlock, but for some reason, the user I assigned with the custom role of Manager would not show up in the Author drop-down list in the Pages or Posts “Write” panels.
Thanks for any insights you have!
8th Nov
Dion says:
ErisDS, I tried the deactivate hiding code above and it worked brilliantly! Thanks again for this article.
I also leveraged the suggestions you recommended and built a redirect from the Settings link in User Role Editor, which works perfectly, here:
2
3
4
5
6
7
8
9
10
$result = stripos($_SERVER['REQUEST_URI'], 'users.php?page=user-role-editor.php');
if ($result!==false && !current_user_can('edit_themes')) {
wp_redirect(get_option('siteurl') . '/wp-admin/index.php?permissions_error=true');
}
}
add_action('admin_menu','permissions_user_role_editor_redirect');
The problem is, I copied the exact same code and filled in the variables for Adminimize, but it doesn’t work. I think the redirect is failing because of something to do with Adminimize coming from the options-general.php page, as shown:
2
3
4
5
6
7
8
9
10
$result = stripos($_SERVER['REQUEST_URI'], 'options-general.php?page=adminimize/adminimize.php');
if ($result!==false && !current_user_can('edit_themes')) {
wp_redirect(get_option('siteurl') . '/wp-admin/index.php?permissions_error=true');
}
}
add_action('admin_menu','permissions_adminimize_redirect');
Any ideas? Also, rather than create two complete functions for two things that are doing nearly the exact same thing, is there a way to combine the two into a single function? I’m unafraid to experiment, but really at the bottom of it, I’m still pretty much a complete newbie to programming in php and javascript.
Thanks again.
22nd Dec
Peliculas Online says:
Thanks for the information =D
3rd Feb
Paolo says:
Hi Miss ErisDS,
Me really love your post.
I don’t know if I miss something cause unfortunately it doesn’t work for me. :(
I tried following it and manually putting codes.
function modify_capabilities() – “Submit for review” does not appear, still Publish button.
2
3
4
5
6
7
8
9
{
global $submenu;
$submenu['edit.php?post_type=page'][10][1] = 'publish_pages';
// for posts it should be:
// $submenu['edit.php'][10][1] = 'publish_posts';
}
add_action('admin_menu','modify_menu');
I got Fatal error: Cannot redeclare modify_menu() previously declared on disabling the “Add New” in Pages Submenu.
function hide_buttons() – I still see Add New link in the page menu.
I tried downloading the function.php and copy paste on my theme’s function.php file still no luck. It does not do anything.
Any idea?
27th Jun
James Riter says:
Thank You!!
I have been making a site for a client and am trying to give him the freedom to edit pages but not allow him to add pages and this just what I needed.
From the design he wants adding pages would hurt the design and this saves me from having to log-in to the site every time he wants a change!
Thank you again!
9th Sep
brook says:
SWEEEEEET!!…..ive been trying to get rid of this “add new” button for the last day, and cause there no hooks into or anything i was finding it dificult….i just wanted to remove the button from the main administrator roll for my client because i dont use roles or anything, maybe i should im guessing it would be alot easier for updates etc…
But anyway i managed to change a little and BAM!!, sweet, thanks for this tutorial and very well explained, website bookedmarked.
28th Sep
Chase Adams says:
Great post and VERY thorough!
One thought: Won’t the $_GET['permissions_error'] throw an error because it isn’t defined if they haven’t been redirected? I always check to see if Get & Post values are set by using isset(…) first.
2nd Oct
Diego says:
Very nice post, the most complete about this issue, no doubt!
just one question: how get rid of the “add new” button when editing a post/page/cpt?
3rd Oct
ErisDS says:
The 3rd from bottom code block explains how to do this, although you might need to tweak it for different pages.
There have been lots of interesting comments and additions to this, I’ll have a go at updating this tutorial & checking it all still works/there’s no easier way in the latest WP soon.
22nd Nov
oxfordian3 says:
Oops, I read this article in more detail and see that it already contains the same info as my reference.
Still — WP should offer a way to catch the insert-post event so that it can be thoroughly firewalled.
5th Mar
Bradley Flood says:
Thank you very much!
17th Apr
Did says:
Great Tutorial !!! bookmarked
I manage to get rid of everything else using other plugins and snippet except the add new page link in wp-admin/edit.php?post_type=page
I mean the button next to “Pages”
Do you a snippet for it ?
thanx a million
22nd Sep
Ravinder Singh Rawat says:
Redirect user if they tries to edit the post.
2
3
4
5
6
7
8
9
10
11
12
13
{
global $post_type, $current_screen;
if( $current_screen->id == 'ecommercesaleslog' && isset($_GET['action']) && $_GET['action'] == 'edit' )
{
wp_redirect(get_option('siteurl') . '/wp-admin/index.php?permissions_error=true');
}
if( $post_type == 'ecommercesaleslog' ) {
echo '<style type="text/css">#view-post-btn,#post-preview{display: none;} .add-new-h2{display: none;}</style>';
}
}