How to block WordPress admin menu item

Remove Admin Menu Item

Remove Admin Menu Item

Suppose you don’t wish your blog registered users see some menu items in WordPress admin back-end and it is not the user role capabilities management subject. That is no such capability exists which you can use. For example, if you need to block just user profile editor and nothing more. It can be useful if you wish to allow for the group of volunteers to use the only user budget for all of them to make some task at your blog. In this case it is important that no one from that users group can edit user password and other user profile details. So you should to block WordPress admin menu items and URLs related to the user profile editor execution.
I will show you how to make it in this post. We just add a little piece of code to your theme functions.php file. Let’s go.

Open your blog current theme functions.php file. And put into begin of it following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// block profile menu for users with role subscriber
if ( is_user_logged_in() ) {
	$userRole = ($current_user->data->wp_capabilities);
	$role = key($userRole);
	unset($userRole);
  if ($role=='subscriber') {
    function remove_profile_submenu() {
      global $submenu;
      //remove Your profile submenu item
      unset($submenu['profile.php'][5]);
    }
    add_action('admin_head', 'remove_profile_submenu');
 
    function remove_profile_menu() {
      global $menu;
// remove Profile top level menu
      unset($menu[70]);
    }
    add_action('admin_head', 'remove_profile_menu');
 
 
    function profile_redirect() {
      $result = stripos($_SERVER['REQUEST_URI'], 'profile.php');
      if ($result!==false) {
        wp_redirect(get_option('siteurl') . '/wp-admin/index.php');
      }
    }
 
    add_action('admin_menu', 'profile_redirect');
  }
}
// end of block profile menu for users with role

That’s it. This code snippet blocks user profile editor for all users with subscriber role. I use subscriber role just for example. It can be any another role including your own custom made one. To create your own user role and fill it with capabilities as you and only you wish, use User Role Editor plugin.
Let’s look inside the code.
1st, at lines 3-6 we check what role current logged-in user has. At line 3

3
$userRole = ($current_user->data->wp_capabilities);

you should change wp_ to your own WordPress database prefix if it is different than a default one.
To check another role than subscriber, change role name to that you wish at line 6:

6
if ($role=='role_you_wish_name') {

Then lines 7-12 removes ‘Your profile’ submenu item.
Lines 14-19 removes ‘Profile’ top level menu.
Is it enough and can we finish here? No. We just hide menu items from user. But he/she still can call wp-admin/profile.php directly from the browser. At lines 22-29 we redirect user to admin back-end dashboard if he/she tries to call profile.php script.

To block another menu item than “Profile” look into wp-admin/menu.php file from WordPress core and select one you like more :) .
The code I wrote above is tested against WordPress 2.9.2.

Thanks to Clay for general idea and useful post Remove WordPress Admin Menu Without Affecting WordPress Core System which was written directly on discussed subject.

Tags: Security, User Role, WordPress

  • roland

    tried it got: Fatal error: Call to undefined function is_user_logged_in()

  • http://shinephp.com Vladimir Garagulya

    Check your WordPress version. It is possible that this function did not exist in the earlier versions of WordPress. This code definitely work with WordPress 2.9.2. I test it with that version only.
    It could depend of the place where you put the code you test also.
    is_user_logged_in() is the small function and lives at wp-include/pluggable.php


    if ( !function_exists('is_user_logged_in') ) :
    /**
    * Checks if the current visitor is a logged in user.
    *
    * @since 2.0.0
    *
    * @return bool True if user is logged in, false if not logged in.
    */
    function is_user_logged_in() {
    $user = wp_get_current_user();

    if ( $user->id == 0 )
    return false;

    return true;
    }
    endif;

    It is available from theme functions.php file. I checked it again just now :) . If you tries to call it from the plugin and it is not available just include pluggable.php file into your code with require_once directive or place the code above there in order to get it.

  • Matt

    Hi,

    Thanks for the code, very useful. I already had the menus removed from views but I took this part to block access:

    function profile_redirect() {
    $result = stripos($_SERVER['REQUEST_URI'], 'profile.php');
    if ($result!==false) {
    wp_redirect(get_option('siteurl') . '/wp-admin/index.php');
    }
    }

    add_action('admin_menu', 'profile_redirect');

    My question is, is it possible to redirect multiple items e.g. my-sites.php, upload.php, themes.php? If so what is the easiest way to do this?

    Thanks again!

  • http://shinephp.com Vladimir Garagulya

    Hi,
    try this modified version:

    function profile_redirect() {
    $result = false;
    $linksToBlock = array('profile.php', 'my-sites.php', 'upload.php','themes.php');
    foreach ($linksToBlock as $key=>$value) {
    $result = stripos($_SERVER['REQUEST_URI'], $value);
    if ($result!==false) {
    break;
    }

    }
    if ($result!==false) {
    wp_redirect(get_option('siteurl') . '/wp-admin/index.php');
    }
    }
    I did not test this modification, please let me know the result.

  • Matt

    Hi Vladimir,

    Thanks very much. I used the following code:

    function profile_redirect() {
    $result = false;
    $linksToBlock = array('profile.php', 'my-sites.php', 'upload.php', 'themes.php');
    foreach ($linksToBlock as $key=>$value) {
    $result = stripos($_SERVER['REQUEST_URI'], $value);
    if ($result!==false) {
    break;
    }

    }
    if ($result!==false) {
    wp_redirect(get_option('siteurl') . '/wp-admin/index.php');
    }
    }

    add_action('admin_menu', 'profile_redirect');

    Strangely, it seems to block all of the php files succesfully apart from upload.php. Any ideas?

    Many thanks.

  • http://shinephp.com Vladimir Garagulya

    You are right, Matt. It is really strange. I checked how code works with PHP debugger for 'upload.php' and see that code goes through wp_redirect(), but redirection doesn't occur for unknown reason. The subject needs additional investigation. I will return with an idea if I have something…

  • http://www.viktorix.com/ Viktor Nagornyy

    There's an easier way to block top level menus without requesting URI. This is what I'm using:
    <?php
    function remove_menus () {
    global $menu;
    global $current_user;
    get_currentuserinfo();
    if ($current_user->user_level < 3){
    $restricted = array(__('Tools'),__('Contact'),__('Comments'));
    end ($menu);
    while (prev($menu)){
    $value = explode(' ',$menu[key($menu)][0]);
    if(in_array($value[0] != NULL?$value[0]:”" , $restricted)){unset($menu[key($menu)]);}
    }
    }
    }
    add_action('admin_menu', 'remove_menus');?>

  • Gunu

    The above code “// block profile menu for users with role subscriber” works perfect in WP 3

    Many Thanks, also for the “Use Role Editor” plugin!

  • Gunu

    This is nice and easier for more menu-items but…… The Profile’ top level menu still working and we still can call wp-admin/tools.php (etc.) directly from the browser.

  • Chris

    This worked great for me. I was using the Hide Dashboard plugin to keep users out of the backend but it was still allowing the profile editor to be visible. So, I put your function together with the Hide Dashboard plugin. Then I changed line 6 to
    if ($role != ‘administrator’) {
    Now, only admins can see the backend. Perfect solution for what I was trying to accomplish. Thanks!!

blog comments powered by Disqus