web-dev-qa-db-fra.com

Empêcher la suppression d'un rôle d'utilisateur mais d'un abonné

Dans l'administration de mon blog, je voudrais empêcher quiconque (administrateur inclus) de supprimer un utilisateur, à moins que ce ne soit un simple abonné.

En gros, dans la section "utilisateurs" de l'administration, je souhaiterais que l'option "supprimer" ne soit visible que sous les abonnés, pas sous les administrateurs, les éditeurs, les auteurs ou les contributeurs.

Comment puis-je faire cela dans mon fichier functions.php (un plugin ne m'intéresse pas)?

J'ai essayé la fonction "remove_cap ('delete_users')", mais sa portée est trop grande car elle empêche de supprimer tout utilisateur alors que je voudrais empêcher de supprimer tout utilisateur MAIS les abonnés.

Merci de votre aide.

3
Baylock

Si vous entendez le bouton Supprimer de la liste d'utilisateurs à /wp-admin/users.php, il est créé par la WP_Users_List_Table classe autour (actuellement) ligne 256 . Si vous regardez un peu plus bas, quelques lignes, vous verrez un filtre appelé user_row_actions. Vous pouvez l'utiliser pour masquer le lien "supprimer".

add_filter(
  'user_row_actions',
  function($actions, $user_object) {
    if (1 >= count($user_object->roles) && 'subscriber' !== $user_object->roles[0]) {
      unset($actions['delete']);
    }
    return $actions;
  },
  1,2
);

Testé au minimum, mais je pense que cette logique est correcte. Vous devriez voir le lien "supprimer" pour les abonnés mais pas pour les utilisateurs ayant un autre rôle, y compris les utilisateurs avec "abonné" et un autre rôle au cas où vous auriez ce configuration étrange.

Si vous regardez attentivement et avez un esprit malicieux, vous remarquerez que vous pouvez toujours supprimer tout utilisateur souhaité en manipulant l'ID utilisateur dans l'URL. Regarde attentivement:

/wp-admin/users.php?action=delete&user=9&_wpnonce=8059e669c1

Le filtre ci-dessus ne fait que masquer le lien. Cela n'empêche pas l'accès à l'écran de suppression. Pour ce faire, nous aurons besoin de plus de code:

add_action(
  'load-users.php',
  function() {
    if (isset($_GET['action']) && 'delete' === $_GET['action']) {
      if (isset($_GET['user'])) {
        $user_object = get_userdata($_GET['user']);
        if (1 >= count($user_object->roles) && 'subscriber' !== $user_object->roles[0]) {
          wp_die('This user cannot be deleted');
        }
      }
    }
  }
);

Même avec cela en place, un utilisateur intelligentpourraitsera toujours capable de transmettre les bonnes valeurs POST et de supprimer un utilisateur de toute façon. Vous souhaiterez donc peut-être également un droit de sécurité final avant la suppression de l'utilisateur.

add_action(
  'delete_user', 
  function($id) {
    $user_object = get_userdata($id);
    if (1 >= count($user_object->roles) && 'subscriber' !== $user_object->roles[0]) {
      wp_die('This user cannot be deleted');
    }
  }
);

Remarque: ce code a été testé dans un fichier MU-Plugin. Je pense que cela devrait probablement fonctionner à partir de functions.php mais assurez-vous de le vérifier. En outre, dans la pratique, j'essaierais probablement d'extraire une partie de cette logique pour qu'elle soit réutilisable. Ces rappels sont dangereusement proches des répétitions.

5
s_ha_dum

Ok, s_ha_dum, je l’ai fait fonctionner avec quelques changements:

le "compte" semble ruiner la fonction mais comme ça, ça a fonctionné comme un charme:

function test($actions, $user_object) 
{
    if ( 'subscriber' !== $user_object->roles[0]) {unset($actions['delete']);}
    return $actions;
}
add_filter('user_row_actions','test',1,2);

Merci pour votre aide précieuse!

1
Baylock

Oui, nous pouvons y arriver en suivant.

add_filter( 'user_row_actions', 'custom_action_function', 1, 2 );
function custom_action_function($actions, $user_object) {
    if ( 1 >= count( $user_object->roles ) && 'subscriber' !== $user_object->roles[0] ) {
      unset( $actions['delete'] );
    }
    return $actions;
}
0
webtechie