-
-
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(); |
Wow
but unfortunately it seems it's still possible to delete admin user by selecting the checkbox in first column and choose “Remove” from the Bulk Actions select menu.
Is it possible to remove the checkbox for the $protectedRoles?
Thanks
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.
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
Cool Class… Thanks :)