Un gérant de commerce qui administre seul son site vitrine WordPress avait, un jour, supprimé par erreur son propre compte administrateur en pensant nettoyer un compte de test créé lors de la mise en ligne initiale. Sans autre compte administrateur, il s’est retrouvé bloqué hors de son propre tableau de bord, une situation résolue uniquement grâce à un accès direct à la base de données par son hébergeur.
Sur les sites gérés par une seule personne ou une petite équipe, ce scénario n’est pas si rare : un ménage de comptes obsolètes qui va un cran trop loin. La parade consiste à intercepter la capacité de suppression au niveau le plus bas possible, avant même que l’écran de confirmation ne s’affiche, pour empêcher techniquement la suppression du dernier compte administrateur du site.
Le bon point d’interception : map_meta_cap
Le filtre map_meta_cap transforme une capacité « méta » (comme delete_user, appliquée à un utilisateur précis) en capacités concrètes vérifiées ensuite par WordPress. C’est le bon endroit pour retirer la capacité effective de suppression quand la cible est le dernier administrateur restant, plutôt que d’intercepter après coup une action déjà entamée :
add_filter( 'map_meta_cap', function ( $capacites, $cap, $id_utilisateur_courant, $args ) {
if ( 'delete_user' !== $cap && 'delete_users' !== $cap ) {
return $capacites;
}
$id_cible = $args[0] ?? 0;
if ( commerce_est_dernier_administrateur( $id_cible ) ) {
$capacites[] = 'do_not_allow';
}
return $capacites;
}, 10, 4 );
Ajouter la pseudo-capacité do_not_allow à la liste retournée fait échouer toute vérification ultérieure de current_user_can() sur cette action précise, quelle que soit par ailleurs la capacité réelle de la personne qui tente la suppression — y compris un autre administrateur, ce qui est le comportement recherché ici.
Déterminer si la cible est le dernier administrateur

function commerce_est_dernier_administrateur( int $id_utilisateur ) {
$utilisateur = get_userdata( $id_utilisateur );
if ( ! $utilisateur || ! in_array( 'administrator', (array) $utilisateur->roles, true ) ) {
return false;
}
$comptage = count_users();
$nombre_administrateurs = $comptage['avail_roles']['administrator'] ?? 0;
return $nombre_administrateurs <= 1;
}
La fonction native count_users() renvoie un tableau détaillé du nombre d’utilisateurs par rôle, sans qu’il soit nécessaire de lancer une requête personnalisée sur la table des utilisateurs. Le test <= 1 plutôt que === 1 couvre par prudence un cas limite où le comptage serait à zéro, bien que ce cas ne devrait normalement jamais se produire sur un site fonctionnel.
Couvrir aussi la suppression groupée
L’écran Utilisateurs propose une action groupée de suppression, qui appelle la même capacité delete_users mais sur plusieurs identifiants à la fois. Le filtre ci-dessus la couvre déjà, puisque map_meta_cap est invoqué pour chaque utilisateur ciblé individuellement par WordPress en interne lors du traitement d’une action groupée — un point qui mérite tout de même d’être vérifié par un test manuel, les comportements internes pouvant varier selon la version du cœur utilisée.
Afficher un message clair plutôt qu’un blocage muet
Sans message explicite, la ligne du compte concerné disparaîtrait simplement des cases sélectionnables sans qu’aucune explication ne soit donnée, ce qui pourrait sembler être un bug. Un message d’avertissement directement sur la ligne du compte protégé clarifie la situation :
add_filter( 'user_row_actions', function ( $actions, WP_User $utilisateur ) {
if ( commerce_est_dernier_administrateur( $utilisateur->ID ) ) {
unset( $actions['delete'] );
$actions['protection'] = '<span style="color:#8a6d1e;">Dernier administrateur, suppression désactivée</span>';
}
return $actions;
}, 10, 2 );
Et si l’on veut vraiment supprimer ce compte ?
Le blocage ne doit jamais être permanent et absolu : un gérant qui change réellement de prestataire technique doit pouvoir transférer son rôle d’administrateur avant suppression. La bonne pratique reste de toujours créer et vérifier un second compte administrateur au préalable — cette protection empêche justement de sauter cette étape par erreur, elle n’empêche jamais une suppression légitime une fois un second administrateur en place.
- Ne comptez que les comptes réellement actifs (pas ceux placés en attente d’activation), sous peine de faux positifs sur le comptage.
- Testez le comportement avec un compte super-administrateur sur un réseau multisite, où la logique de rôles diffère légèrement.
- Documentez cette protection dans la documentation interne du site, pour qu’un futur développeur ne la découvre pas par surprise en cherchant pourquoi une suppression échoue silencieusement.
Sur tous les sites gérés par une seule personne, je recommande systématiquement ce type de garde-fou technique en complément d’une bonne pratique organisationnelle : la vigilance humaine finit toujours par faillir un jour, un blocage au niveau du code ne connaît pas la fatigue de fin de journée.
Ce qu’il faut retenir
Ce garde-fou tient en quelques lignes, s’appuie entièrement sur des fonctions natives de WordPress, et élimine un risque précis mais aux conséquences potentiellement lourdes : la perte d’accès complète à son propre site faute d’un second compte administrateur disponible. C’est le genre de protection qui ne coûte presque rien et qu’on regrette systématiquement de ne pas avoir mise en place avant l’incident.