-
-
Save johnpbloch/2028978 to your computer and use it in GitHub Desktop.
| <?php | |
| class JPB_User_Caps { | |
| /** | |
| * An array of all protected roles | |
| * @var array | |
| */ | |
| protected $protectedRoles = array( | |
| 'webmaster', | |
| ); | |
| /** | |
| * Add the necessary filters for filtering out editable roles and mapping meta caps. | |
| */ | |
| function __construct() { | |
| add_filter( 'editable_roles', array( $this, 'editable_roles' ), 20 ); | |
| add_filter( 'map_meta_cap', array( $this, 'map_meta_cap' ), 10, 4 ); | |
| } | |
| /** | |
| * Remove our protected roles from the list of editable roles if the current user doesn't have one of them. | |
| * | |
| * @param array $roles The list of editable roles. This is an associative array using the role slug as keys and the display names as values. | |
| * @return array The filtered list of roles | |
| */ | |
| function editable_roles( $roles ) { | |
| $userInProtectedRole = false; | |
| foreach( $this->protectedRoles as $k => $role ) { | |
| if( !isset( $roles[$role] ) ) { | |
| unset( $this->protectedRoles[$k] ); | |
| continue; | |
| } | |
| if( !current_user_can( $role ) ) | |
| continue; | |
| $userInProtectedRole = true; | |
| break; | |
| } | |
| $roles = array_diff_key( $roles, array_flip( $this->protectedRoles ) ); | |
| return $roles; | |
| } | |
| /** | |
| * If someone is trying to edit or delete a protected role and that user isn't in a protected role, don't allow it. | |
| * | |
| * For our purposes, $args[0] should be the ID of the user having something done to them (the user about to be | |
| * edited, deleted, promoted, etc.) | |
| * | |
| * @param array $caps The current list of required capabilities for this action | |
| * @param string $cap The capability we're checking (i.e., the one used in current_user_can() ) | |
| * @param int $user_id The ID of the user for whom we're checking capabilities | |
| * @param array $args Any extra arguments | |
| * @return array The final array of capabilities required for this action | |
| */ | |
| function map_meta_cap( $caps, $cap, $user_id, $args ) { | |
| switch( $cap ) { | |
| case 'edit_user': | |
| case 'remove_user': | |
| case 'promote_user': | |
| if( isset( $args[0] ) && $args[0] == $user_id ) | |
| break; | |
| elseif( !isset( $args[0] ) ) | |
| $caps[] = 'do_not_allow'; | |
| $other = new WP_User( absint( $args[0] ) ); | |
| $otherHasCap = $userHasCap = false; | |
| foreach( $this->protectedRoles as $role ) { | |
| $otherHasCap = $otherHasCap ? true : $other->has_cap( $role ); | |
| $userHasCap = $userHasCap ? true : current_user_can( $role ); | |
| } | |
| if( $otherHasCap && !$userHasCap ) { | |
| $caps[] = 'do_not_allow'; | |
| } | |
| break; | |
| case 'delete_user': | |
| case 'delete_users': | |
| if( !isset( $args[0] ) ) | |
| break; | |
| $other = new WP_User( absint( $args[0] ) ); | |
| $otherHasCap = $userHasCap = false; | |
| foreach( $this->protectedRoles as $role ) { | |
| $otherHasCap = $otherHasCap ? true : $other->has_cap( $role ); | |
| $userHasCap = $userHasCap ? true : current_user_can( $role ); | |
| } | |
| if( $otherHasCap && !$userHasCap ) { | |
| $caps[] = 'do_not_allow'; | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| return $caps; | |
| } | |
| } | |
| new JPB_User_Caps(); |
Hi, thanks for your code. I noticed if i protect the administrator user then any administrator is not allowed to create a new user with administrator role.
I then replaced:
function editable_roles( $roles ) {
$userInProtectedRole = false;
foreach( $this->protectedRoles as $k => $role ) {
if( !isset( $roles[$role] ) ) {
unset( $this->protectedRoles[$k] );
continue;
}
if( !current_user_can( $role ) )
continue;
$userInProtectedRole = true;
break;
}
$roles = array_diff_key( $roles, array_flip( $this->protectedRoles ) );
return $roles;
}
with:
function editable_roles( $roles ){
if( isset( $roles['administrator'] ) && !current_user_can('administrator') ){
unset( $roles['administrator']);
}
return $roles;
}
and it works fine.
@dademaru Maybe hiding the users of $protectedRoles in the users listing, can do the work.
Using one of the methods shown in this post: https://rudrastyh.com/wordpress/pre_user_query.html
Switch of the checkbox by adding a snippet of css code for each protected role. Something like this:
echo '<style type="text/css"> widefat th input[type=checkbox].administrator { visibility: hidden;}</style>';
It may not be super neat but it seems to do the trick and it is possible to make it more flexible.