# map_meta_cap pour faire correspondre une capacité WordPress à un scope d’API

> Comment le filtre map_meta_cap, présent depuis les premières versions de WordPress, permet de dériver une logique de scopes d'API proche d'OAuth.

- Auteur : Clément Hadrot
- Publié le : 2025-10-10
- Mis à jour le : 2025-10-10
- Catégorie : Headless &amp; API
- URL : https://wpmoderne.dev.wordpress-developpement.fr/headless/map-meta-cap-capacite-scope-api/

## L’essentiel

- Une capacité méta dépend du contenu ciblé
- Le filtre reçoit l'ID de l'objet concerné
- Base solide pour des scopes granulaires

Depuis WordPress 2.0, le système de rôles et capacités repose sur une distinction que beaucoup de développeurs découvrent tardivement : les capacités « primitives » comme `edit_posts`, attribuées globalement à un rôle, et les capacités « méta » comme `edit_post` (au singulier), qui dépendent du contenu précis visé. C'est le filtre `map_meta_cap` qui fait le lien entre les deux, en traduisant une vérification méta en une ou plusieurs capacités primitives réellement testées.

Pour un projet headless qui cherche à exposer une API avec des permissions plus fines que le simple « authentifié ou non », comprendre ce mécanisme ouvre une voie naturelle vers une logique de scopes, sans avoir à réinventer un système de permissions parallèle à celui de WordPress.

## Comment fonctionne map_meta_cap

Lorsqu'une vérification comme `current_user_can( 'edit_post', 42 )` est appelée, WordPress ne se contente pas de vérifier si l'utilisateur possède une capacité nommée `edit_post` (elle n'existe d'ailleurs dans aucun rôle par défaut). Le cœur de WordPress appelle `map_meta_cap()`, qui reçoit la capacité demandée, l'identifiant de l'utilisateur, et l'identifiant de l'objet concerné (ici l'article 42), puis retourne un tableau de capacités primitives à vérifier réellement, en tenant compte du contexte : l'article appartient-il à l'utilisateur ? Est-il déjà publié ? L'utilisateur a-t-il la capacité générique `edit_others_posts` ?

```
add_filter( 'map_meta_cap', function( $capacites_requises, $capacite, $user_id, $args ) {
    if ( 'edit_post' === $capacite ) {
        $post = get_post( $args[0] );
        if ( $post && (int) $post->post_author !== $user_id ) {
            $capacites_requises[] = 'edit_others_posts';
        }
    }
    return $capacites_requises;
}, 10, 4 );
```

## Dériver un scope d'API à partir de ce mécanisme

Une API à scopes façon OAuth (lecture seule, écriture limitée à ses propres contenus, écriture globale) peut sembler exiger un système entièrement nouveau. En réalité, la logique de `map_meta_cap` couvre déjà une bonne partie du besoin : un jeton d'application WordPress reste associé à un utilisateur, et cet utilisateur porte des rôles et capacités classiques. Ajouter un scope revient alors à filtrer `map_meta_cap` pour restreindre davantage les capacités effectives selon le contexte de la requête REST en cours, sans dupliquer la logique métier déjà présente dans le cœur de WordPress.

> L'essentiel à retenir : Une capacité méta dépend du contenu ciblé ; Le filtre reçoit l'ID de l'objet concerné ; Base solide pour des scopes granulaires

## Un exemple appliqué à une route personnalisée

Imaginez une route REST qui permet à un utilisateur authentifié par mot de passe d'application de modifier uniquement les articles dont il est l'auteur, jamais ceux des autres, même s'il possède par ailleurs la capacité `edit_others_posts` via son rôle. Ce comportement, qui ressemble à un scope restreint, se code en interceptant `map_meta_cap` et en vérifiant un marqueur propre à la requête en cours :

```
add_filter( 'map_meta_cap', function( $capacites_requises, $capacite, $user_id, $args ) {
    if ( 'edit_post' === $capacite && defined( 'REQUETE_SCOPE_LIMITE' ) && REQUETE_SCOPE_LIMITE ) {
        $post = get_post( $args[0] );
        if ( $post && (int) $post->post_author !== $user_id ) {
            return array( 'do_not_allow' );
        }
    }
    return $capacites_requises;
}, 10, 4 );
```

La capacité fictive `do_not_allow` est la convention WordPress pour refuser explicitement une action, quel que soit le rôle de l'utilisateur.

## Les limites de l'approche

Ce mécanisme reste attaché au système de capacités de WordPress, pensé pour un petit nombre de rôles fixes. Pour une API qui doit gérer de nombreux scopes fins et combinables (lecture des commentaires, écriture des médias, accès aux commandes), une table de correspondance dédiée entre jetons et scopes, consultée en amont de `map_meta_cap`, apporte plus de clarté qu'un empilement de conditions dans un seul filtre. `map_meta_cap` reste alors le point d'exécution final, pas le seul lieu de décision.

- Convient bien à des scopes simples, proches des capacités WordPress existantes.
- Devient difficile à maintenir au-delà de quelques règles conditionnelles empilées dans le même filtre.
- Ne remplace pas un vrai système de jetons à durée de vie et à portée limitée pour une API exposée publiquement à des applications tierces.

## Pour aller plus loin

La documentation officielle sur developer.wordpress.org détaille l'ensemble des capacités méta reconnues par défaut (`edit_post`, `delete_post`, `read_post`, et leurs équivalents pour les pages et types personnalisés). S'appuyer sur `map_meta_cap` pour construire une logique de scopes évite de dupliquer un système de permissions parallèle, tout en restant compatible avec les extensions qui, elles aussi, s'appuient sur ce même filtre pour leurs propres vérifications.
