-
-
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.