I do so adore WordPress; with its endless flexibility, ease of use and shiny, greyish good looks, it fulfills all of my requirements as both a designer and developer, and fulfills my clients' requirements as a straightforward, simple content management system.

However, I did make some sloppy decisions with no forethought for the consequences in my perilous youth (which is to say, about 3 years ago) - I would often develop a site in WordPress and then hand over the administrator login details to the client with a happy wave, safe in the knowledge that the lovingly-crafted site would be safely managed and cared for by its new owners. And then things would start to happen.

SEO plugins and 'add a smiley to every paragraph!' plugins would start to appear; the navigation would mysteriously change from four or five items to over a dozen, breaking the layout; the title of the site would suddenly change from the company name to 'GOOGLE YAHOO MSN' (this, unfortunately, actually happened). What was going on?

Usually these changes were followed by harried emails and phone calls from the self-same clients whose sites had been affected. Obviously all clients are wonderful, beautiful people who have only good in their hearts, but sometimes they can become a little bit carried away tinkering with their shiny new toy website. Which, of course, they are completely entitled to do! But often the effects of this poking and prodding are unintentional and need to be fixed. What would be great is if we could limit all of that tinker-potential in the first place.

My solution is the neat little function below, which I drop into my theme's functions.php file:

function remove_menus() {
 global $menu;

 // The default menu:
 // array(__('Dashboard'), __('Posts'), __('Media'), __('Links'), __('Pages'), __('Appearance'), __('Tools'), __('Users'), __('Settings'), __('Comments'), __('Plugins'));

 $restrictedMenu = array(__('Appearance'), __('Tools'), __('Users'), __('Plugins'), __('Settings'));
 end ($menu);

 global $current_user;
 get_currentuserinfo();

 if ($current_user->ID != 1) { // ID 1 is the main, primary admin
  while (prev($menu)) {
   $value = explode(' ',$menu[key($menu)][0]);
   
   if (in_array($value[0] != NULL ? $value[0]: "" , $restrictedMenu)) {
    unset($menu[key($menu)]);
   }
  }
 }
}

add_action('admin_menu', 'remove_menus');

So exactly how does this work? Well, when you install WordPress, a default administrator account is created. That account's ID is, predictably, 1. What this function does is add a hook to admin_menu (add_action('admin_menu', 'remove_menus');) that checks the ID of the user currently logged in to the back end and, if their user ID is not equal to 1, it then loops through the global $menu array and removes any menu items that are defined in the $restrictedMenu array. With this function in place, all we have to do is create another Administrator-level user, and the function takes care of everything else.

As you can see, in the above code block I've left in a comment:

 // The default menu:
 // array(__('Dashboard'), __('Posts'), __('Media'), __('Links'), __('Pages'), __('Appearance'), __('Tools'), __('Users'), __('Settings'), __('Comments'), __('Plugins'));

That is an array of the default menu items in WP admin that I use it for reference, as every time I drop this in, it might need tweaking slightly. In the above example, I'm removing the Appearance, Tools, Users, Plugins, & Settings menus. This will stop any another admin-level user from messing about with the theme, adding extraneous plugins or botching the site's main settings, amongst other things.

It's worth noting that there is also Shine PHP's excellent User Role Editor, which provides much more infinitesimal control over user-level privileges and even allows you to create new user roles. However, in most cases we're only adding one or two additional users, and this particular blunt hammer is more than adequate for making our sparkly new site tinker-proof.


  • Trishah

    Neat function! Just a suggestion… It would be better to be able to specify the id number of the admin who is allowed full access. This is because it’s become pretty standard to remove or change admin id=1 for security purposes.

    • http://blog.gaijindesign.com/ Lawrie Malen

      Thanks Trishah. This is function is made for dropping directly into the functions.php file, so obviously users are free to make any changes to it they wish, even making it specific to a username:

      if ($current_user->user_login != ‘actualAdministrator’) {

      }

  • Sharon Murphy

    This is great for hiding the links, however I’m still able to access admin menus if I know the full link. How do I restrict those without having to edit user roles?

    • http://blog.gaijindesign.com/ Lawrie Malen

      This is a little trickier, but you could do something like this:

          function filterAdminPages() {
              global $pagenow;
              global $current_user;
             
              get_currentuserinfo();
             
              $restrictedPagesArray = array(
                  'tools.php',
                  'edit.php'
              );
             
              if (in_array($pagenow, $restrictedPagesArray)) {
                  if ($current_user->ID != 1) {
                      wp_redirect(admin_url());
                      exit;
                  }
              }
          }

          add_filter('admin_init', 'filterAdminPages');

      This checks the current page (based on the global $pagenow variable) against an array of restricted page names, and if there’s a match, boom – you’re redirected to the dashboard. It could definitely do with some refinement, but it works in a pinch.

  • Cypherinfo

    To limit the access to admin dashboard on a user not role base (I mean to an admin or group of them only) would be great as implemented as plugin.

    Why don’t you create it? :D Thank you.