# Créer des rôles et capacités WordPress sur mesure pour vos clients

> Auteur, éditeur, administrateur : les rôles natifs ne collent pas toujours au fonctionnement réel d'une équipe. Voici comment en créer de nouveaux.

- Auteur : Clément Hadrot
- Publié le : 2021-10-05
- Mis à jour le : 2021-10-05
- Catégorie : Tips
- URL : https://wpmoderne.dev.wordpress-developpement.fr/tips/creer-roles-capacites-wordpress-sur-mesure/

## L’essentiel

- add_role crée un rôle à partir d'un tableau de capacités
- map_meta_cap affine les droits au cas par cas
- Toujours tester avec un compte du rôle concerné, jamais en admin

WordPress propose nativement cinq rôles pour un site simple (abonné, contributeur, auteur, éditeur, administrateur), et un sixième pour le réseau multisite (super administrateur). Ce découpage convient à un blog classique, mais devient vite rigide dès qu'une équipe éditoriale a des besoins plus spécifiques : un rédacteur qui peut publier uniquement dans une catégorie donnée, un community manager qui gère les réseaux sociaux mais ne doit jamais toucher aux réglages du site, un partenaire externe limité à un seul type de contenu.

Plutôt que de bricoler avec les rôles existants ou de donner un accès administrateur par facilité, WordPress permet de créer des rôles sur mesure, composés exactement des capacités nécessaires.

## Comprendre la différence entre rôle et capacité

Un rôle (comme « éditeur ») n'est qu'un ensemble nommé de capacités (comme `edit_others_posts` ou `publish_posts`). C'est la capacité qui est vérifiée dans le code, jamais le rôle directement. Une bonne pratique consiste d'ailleurs à toujours tester une capacité plutôt qu'un rôle :

```
// À éviter
if ( 'editor' === wp_get_current_user()->roles[0] ) { }

// À privilégier
if ( current_user_can( 'edit_others_posts' ) ) { }
```

Cette approche reste valable même si le rôle exact change de nom ou de structure par la suite : le code continue de fonctionner tant que la capacité est correctement attribuée.

## Créer un rôle personnalisé

La fonction `add_role()` crée un rôle à partir d'un identifiant, d'un libellé affiché, et d'un tableau de capacités. Elle doit être appelée une seule fois, typiquement lors de l'activation d'un plugin, car elle enregistre le rôle de façon persistante en base de données :

```
register_activation_hook( __FILE__, function() {
    add_role( 'community_manager', 'Community manager', array(
        'read'                   => true,
        'edit_posts'             => true,
        'edit_published_posts'   => true,
        'publish_posts'          => true,
        'upload_files'           => true,
        'edit_others_posts'      => false,
        'delete_posts'           => false,
        'manage_options'         => false,
    ) );
} );
```

À la désactivation du plugin, il est tout aussi important de retirer le rôle, pour ne pas laisser un rôle « orphelin » actif alors que sa logique associée a disparu :

```
register_deactivation_hook( __FILE__, function() {
    remove_role( 'community_manager' );
} );
```

> L'essentiel à retenir : add_role crée un rôle à partir d'un tableau de capacités ; map_meta_cap affine les droits au cas par cas ; Toujours tester avec un compte du rôle concerné, jamais en admin

## Ajouter une capacité personnalisée

Au-delà des capacités natives, il est possible de créer des capacités propres au projet, pour contrôler l'accès à une fonctionnalité spécifique développée sur mesure (un export de données, un module de statistiques interne) :

```
$role = get_role( 'editor' );
$role->add_cap( 'exporter_statistiques', true );
```

Cette capacité peut ensuite être vérifiée exactement comme une capacité native, dans le code du plugin ou du thème :

```
if ( current_user_can( 'exporter_statistiques' ) ) {
    // Afficher le bouton d'export
}
```

## Affiner les droits avec map_meta_cap

Certains besoins ne se résolvent pas avec une simple capacité globale : par exemple, autoriser un rôle à modifier uniquement les articles d'une catégorie précise. Le filtre `map_meta_cap` permet cette granularité, en interceptant la vérification au niveau du contenu concerné :

```
add_filter( 'map_meta_cap', function( $caps, $cap, $user_id, $args ) {
    if ( 'edit_post' === $cap && isset( $args[0] ) ) {
        $post = get_post( $args[0] );
        if ( $post && has_term( 'partenaires', 'category', $post ) ) {
            $user = get_userdata( $user_id );
            if ( ! in_array( 'community_manager', (array) $user->roles, true ) ) {
                return array( 'do_not_allow' );
            }
        }
    }
    return $caps;
}, 10, 4 );
```

Ce type de filtre demande de la rigueur : une condition mal posée peut bloquer un administrateur légitime ou, à l'inverse, laisser passer un accès qui aurait dû être refusé.

## Lister les rôles et capacités existants

Avant de créer un nouveau rôle, il est utile d'inspecter ce qui existe déjà, pour éviter les doublons ou les incohérences. WP-CLI propose une commande dédiée :

```
wp role list
wp role list --fields=role,name
wp cap list editor
```

## Bonnes pratiques pour la gestion des rôles

- Toujours tester avec un compte réellement attribué au rôle concerné, jamais en restant connecté en administrateur
- Documenter les capacités personnalisées ajoutées, dans un fichier dédié ou en commentaire du plugin
- Retirer proprement les rôles et capacités à la désinstallation d'un plugin
- Éviter d'accorder `manage_options` par facilité : cette capacité donne accès à l'ensemble des réglages du site

> Donner un accès administrateur complet à un collaborateur qui n'a besoin que de publier des articles n'est jamais une solution : c'est une dette qui se paie tôt ou tard, souvent au pire moment.

## En résumé

Le système de rôles et capacités de WordPress est bien plus flexible qu'il n'y paraît au premier abord. `add_role()` permet de composer des profils sur mesure, `map_meta_cap` d'affiner les droits jusqu'au niveau d'un contenu individuel. Un peu de temps passé à bien définir ces rôles en amont d'un projet évite ensuite bien des arbitrages délicats une fois l'équipe cliente en place sur le site.
