Jason Conroy of _FindingSimple emailed me today to ask if I knew how to allow site admins to edit the profiles of other users.
I hadn’t even realised administrators couldn’t edit users!
That’s because it relates only to WordPress networks. In a WordPress 3.x Network, the Super Admin role is the only role allowed to edit users.
Diagnosing the Problem
As a solution for Jason, my first thought was to simply assign the edit_users capability to the admin role.
I used Justin Tadlock’s Members plugin to check that the admin roles no longer had the edit_users & related user capabilities. However, despite not being able to edit users, admins do have the edit_users capability. In my opinion, that’s a bug in 3.1 or at very least a quirk. If a user has the edit_users capability, they should be able to edit users.
The only hope then was to enter the dark depths of the map_meta_cap function found in capabilities.php.
Around line 816 of that file, within map_meta_cap I found this bit of code:
case 'edit_users': // If multisite these caps are allowed only for super admins. if ( is_multisite() && !is_super_admin( $user_id ) ) $caps[] = 'do_not_allow'; else $caps[] = 'edit_users'; // Explicit due to primitive fall through break;
And there it is. The master override that is preventing any role other than Super Admin from editing other users.
Solution
Fortunately, as is the wonder of WP, the $caps array is passed through a filter before being returned:
return apply_filters('map_meta_cap', $caps, $cap, $user_id, $args);
So the trick then is to use the map_meta_cap filter to turn that do_not_allow capability in the $caps array into either edit_users, delete_users or create_users.
function mc_admin_users_caps( $caps, $cap, $user_id, $args ){ foreach( $caps as $key => $capability ){ if( $capability != 'do_not_allow' ) continue; switch( $cap ) { case 'edit_user': case 'edit_users': $caps[$key] = 'edit_users'; break; case 'delete_user': case 'delete_users': $caps[$key] = 'delete_users'; break; case 'create_users': $caps[$key] = $cap; break; } } return $caps; } add_filter( 'map_meta_cap', 'mc_admin_users_caps', 10, 4 );
This restores the edit_users, delete_users and create_users capabilities to their former glory.
If a user has the admin role, or has been manually assigned any of these capabilities, they will then be able to edit users.
— Update 21 May 2012 —
A few important updates to get the code to work with WordPress 3.3 and to prevent admin users being able to edit super admin accounts and accounts of users not on their site.
Thanks to everyone in the comments, especially for those comments made by Andrew Cafourek, Peter Edwards & Morty Dot.
function mc_admin_users_caps( $caps, $cap, $user_id, $args ){ foreach( $caps as $key => $capability ){ if( $capability != 'do_not_allow' ) continue; switch( $cap ) { case 'edit_user': case 'edit_users': $caps[$key] = 'edit_users'; break; case 'delete_user': case 'delete_users': $caps[$key] = 'delete_users'; break; case 'create_users': $caps[$key] = $cap; break; } } return $caps; } add_filter( 'map_meta_cap', 'mc_admin_users_caps', 1, 4 ); remove_all_filters( 'enable_edit_any_user_configuration' ); add_filter( 'enable_edit_any_user_configuration', '__return_true'); /** * Checks that both the editing user and the user being edited are * members of the blog and prevents the super admin being edited. */ function mc_edit_permission_check() { global $current_user, $profileuser; $screen = get_current_screen(); get_currentuserinfo(); if( ! is_super_admin( $current_user->ID ) && in_array( $screen->base, array( 'user-edit', 'user-edit-network' ) ) ) { // editing a user profile if ( is_super_admin( $profileuser->ID ) ) { // trying to edit a superadmin while less than a superadmin wp_die( __( 'You do not have permission to edit this user.' ) ); } elseif ( ! ( is_user_member_of_blog( $profileuser->ID, get_current_blog_id() ) && is_user_member_of_blog( $current_user->ID, get_current_blog_id() ) )) { // editing user and edited user aren't members of the same blog wp_die( __( 'You do not have permission to edit this user.' ) ); } } } add_filter( 'admin_head', 'mc_edit_permission_check', 1, 4 );
— Update 28 June 2012 —
Updated the mc_edit_permission_check()
to prevent a super admin form being deleted. Thanks again to Peter Edwards in the comments.
— Update 29 September 2012 —
Updated the mc_edit_permission_check()
to allow super admins to edit users again. Thanks to Scott Fennell in the comments.