Editorul poate crea orice utilizator nou, cu excepția administratorului
Am configurat un site WordPress pentru un client. Clientul are rolul de Editor, însă am instalat pluginul Members și i-am acordat clientului capacitatea de a adăuga utilizatori noi în administrarea WordPress. Acest lucru funcționează foarte bine.
Întrebarea mea este că aș dori ca clientul să aibă posibilitatea de a crea utilizatori noi cu rolurile de Contributor, Subscriber, Editor și Author, dar NU Administrator. Utilizatorii noi pe care îi creează clientul nu ar trebui să aibă rolul de Administrator. Este posibil să ascund cumva această opțiune?
Mulțumesc Vayu
Este de fapt destul de ușor. Trebuie să filtrezi în map_meta_caps
și să împiedici editorii să creeze/editeze administratori, precum și să elimini rolul de administrator din array-ul 'editable roles'. Această clasă, ca un plugin sau în fișierul functions.php al temei tale, ar face asta:
class JPB_User_Caps {
// Adăugăm filtrele noastre
function __construct(){
add_filter( 'editable_roles', array($this, 'editable_roles'));
add_filter( 'map_meta_cap', array($this, 'map_meta_cap'), 10, 4);
}
// Elimină 'Administrator' din lista de roluri dacă utilizatorul curent nu este admin
function editable_roles( $roles ){
if( isset( $roles['administrator'] ) && !current_user_can('administrator') ){
unset( $roles['administrator']);
}
return $roles;
}
// Dacă cineva încearcă să editeze sau să șteargă un admin și acel utilizator nu este admin, nu permite
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]) );
if( $other->has_cap( 'administrator' ) ){
if(!current_user_can('administrator')){
$caps[] = 'do_not_allow';
}
}
break;
case 'delete_user':
case 'delete_users':
if( !isset($args[0]) )
break;
$other = new WP_User( absint($args[0]) );
if( $other->has_cap( 'administrator' ) ){
if(!current_user_can('administrator')){
$caps[] = 'do_not_allow';
}
}
break;
default:
break;
}
return $caps;
}
}
$jpb_user_caps = new JPB_User_Caps();
EDITARE
Ok, am analizat de ce permitea ștergerea utilizatorilor. Se pare că delete_user este tratat ușor diferit față de edit_user; am modificat metoda map_meta_cap pentru a rezolva acest lucru. Am testat pe versiunea 3.0.3 și acest cod va împiedica pe oricine, în afară de administratori, să șteargă, editeze sau creeze un administrator.
EDITARE 2
Am actualizat codul pentru a reflecta răspunsul lui @bugnumber9 de mai jos. Te rog să îi dai un upvote acelui răspuns!

Poate cineva să verifice dacă acest cod împiedică ștergerea administratorilor de către alții? Nu reușesc să reproduc acest comportament. Împiedică editarea, dar link-ul de "ștergere" apare la hover, iar WP permite utilizatorului să finalizeze ștergerea...

@somatic - ai avut perfectă dreptate. Mulțumesc pentru observație. Problema este rezolvată acum.

Am nevoie să fac și eu asta, dar nu sunt sigur unde să pun acest cod! În functions.php? Dacă nu, cum ar putea fi făcut să funcționeze din functions.php? Cu stimă, Dc

dacă cineva dorește să restrângă roluri suplimentare, trebuie doar să adăugați o linie suplimentară pentru fiecare rol sub această linie: unset( $roles['administrator']);
... deci după această linie puteți adăuga de exemplu: unset( $roles['editor']);

Funcționează perfect în 3.4.1, mulțumesc! Asigurați-vă că adăugați capabilități pentru create_users, delete_users, add_users, remove_users, edit_users, list_users și promote_users

Cod excelent. Pentru cei care folosesc acest lucru, asigurați-vă că vedeți mica ajustare de mai jos de la @bugnumber9. (Poate John P Block își va edita codul?)

În ciuda faptului că are aproximativ 7 ani, acest fir de discuție poate fi găsit ușor prin Google și încă oferă o soluție funcțională. Mă refer la codul furnizat de @John P Bloch.
Totuși, sub PHP 7, acesta produce o eroare necritică (PHP Deprecated) după cum urmează:
PHP Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; JPB_User_Caps has a deprecated constructor in ...
Pentru a remedia această problemă, pur și simplu înlocuiți acest fragment:
// Add our filters
function JPB_User_Caps(){
add_filter( 'editable_roles', array(&$this, 'editable_roles'));
add_filter( 'map_meta_cap', array(&$this, 'map_meta_cap'),10,4);
}
cu acesta:
// Add our filters
function __construct() {
add_filter( 'editable_roles', array(&$this, 'editable_roles') );
add_filter( 'map_meta_cap', array(&$this, 'map_meta_cap'), 10, 4 );
}
Aceasta va rezolva problema.

Căutam o soluție prin care Editorul să poată edita doar meniuri ȘI să poată crea/edita utilizatori fără a avea nevoie de un plugin. Așa că am realizat acest cod pentru cei care sunt interesați.
// Personalizează rolul de 'Editor' pentru a avea capacitatea de a modifica meniuri, adăuga utilizatori noi
// și altele.
class Custom_Admin {
// Adaugă filtrele noastre
public function __construct(){
// Permite editorului să editeze opțiunile temei (ex. Meniu)
add_action('init', array($this, 'init'));
add_filter('editable_roles', array($this, 'editable_roles'));
add_filter('map_meta_cap', array($this, 'map_meta_cap'), 10, 4);
}
public function init() {
if ($this->is_client_admin()) {
// Dezactivează accesul la paginile de teme/widget-uri dacă nu e admin
add_action('admin_head', array($this, 'modify_menus'));
add_action('load-themes.php', array($this, 'wp_die'));
add_action('load-widgets.php', array($this, 'wp_die'));
add_action('load-customize.php', array($this, 'wp_die'));
add_filter('user_has_cap', array($this, 'user_has_cap'));
}
}
public function wp_die() {
_default_wp_die_handler(__('Nu aveți permisiuni suficiente pentru a accesa această pagină.'));
}
public function modify_menus()
{
remove_submenu_page( 'themes.php', 'themes.php' ); // ascunde submeniul de selectare teme
remove_submenu_page( 'themes.php', 'widgets.php' ); // ascunde submeniul de widget-uri
// Meniul Aspect
global $menu;
global $submenu;
if (isset($menu[60][0])) {
$menu[60][0] = "Meniuri"; // Redenumește Aspect în Meniuri
}
unset($submenu['themes.php'][6]); // Personalizează
}
// Elimină 'Administrator' din lista de roluri dacă utilizatorul curent nu este admin
public function editable_roles( $roles ){
if( isset( $roles['administrator'] ) && !current_user_can('administrator') ){
unset( $roles['administrator']);
}
return $roles;
}
public function user_has_cap( $caps ){
$caps['list_users'] = true;
$caps['create_users'] = true;
$caps['edit_users'] = true;
$caps['promote_users'] = true;
$caps['delete_users'] = true;
$caps['remove_users'] = true;
$caps['edit_theme_options'] = true;
return $caps;
}
// Dacă cineva încearcă să editeze sau să șteargă un admin și acel utilizator nu este admin, nu permite
public function map_meta_cap( $caps, $cap, $user_id, $args ){
// $args[0] == other_user_id
foreach($caps as $key => $capability)
{
switch ($cap)
{
case 'edit_user':
case 'remove_user':
case 'promote_user':
if(isset($args[0]) && $args[0] == $user_id) {
break;
}
else if(!isset($args[0])) {
$caps[] = 'do_not_allow';
}
// Nu permite non-admin să editeze admin
$other = new WP_User( absint($args[0]) );
if( $other->has_cap( 'administrator' ) ){
if(!current_user_can('administrator')){
$caps[] = 'do_not_allow';
}
}
break;
case 'delete_user':
case 'delete_users':
if( !isset($args[0])) {
break;
}
// Nu permite non-admin să șteargă admin
$other = new WP_User(absint($args[0]));
if( $other->has_cap( 'administrator' ) ){
if(!current_user_can('administrator')){
$caps[] = 'do_not_allow';
}
}
break;
break;
}
}
return $caps;
}
// Dacă utilizatorul curent se numește admin sau administrative și este editor
protected function is_client_admin() {
$current_user = wp_get_current_user();
$is_editor = isset($current_user->caps['editor']) ? $current_user->caps['editor'] : false;
return ($is_editor);
}
}
new Custom_Admin();

Soluția lui @John P Bloch încă funcționează bine, dar am vrut să adaug și eu micul meu filtru pentru 'map_meta_cap'. Doar un pic mai scurt și mai curat, cel puțin pentru ochii mei ;)
function my_map_meta_cap( $caps, $cap, $user_id, $args ) {
$check_caps = [
'edit_user',
'remove_user',
'promote_user',
'delete_user',
'delete_users'
];
if( !in_array( $cap, $check_caps ) || current_user_can('administrator') ) {
return $caps;
}
$other = get_user_by( 'id', $args[0] ?? false ); // Verificare PHP 7 pentru variabilă în $args...
if( $other && $other->has_cap('administrator') ) {
$caps[] = 'do_not_allow';
}
return $caps;
}
add_filter('map_meta_cap', 'my_map_meta_cap', 10, 4 );
