# Notifications d’administration persistantes, propres à chaque utilisateur

> Une notice masquée par un administrateur ne devrait pas disparaître pour tous les autres. Voici comment stocker cet état correctement, en user meta.

- Auteur : Clément Hadrot
- Publié le : 2024-07-23
- Mis à jour le : 2024-07-23
- Catégorie : Extensions
- URL : https://wpmoderne.dev.wordpress-developpement.fr/extensions/notifications-administration-persistantes-utilisateur/

## L’essentiel

- Une option globale masque la notice pour tout le monde d'un coup
- Le user meta isole l'état vu ou masqué par personne
- Un bouton de fermeture doit appeler l'admin-ajax dédié, pas un simple CSS

Sur un site associatif géré par cinq administrateurs différents, une extension de gestion des adhésions affichait une notice recommandant de configurer une clé d'API manquante. Le premier administrateur à la fermer l'a fait disparaître pour tout le monde, y compris pour les quatre autres, qui n'avaient jamais vu ce message et qui ignoraient donc que la configuration restait incomplète. La clé d'API n'a été renseignée que trois semaines plus tard, après un incident lié à son absence.

Ce problème vient d'un choix de stockage anodin en apparence : la notice utilisait une option globale, partagée par l'ensemble du site, pour retenir si elle avait déjà été vue. Le bon réflexe consiste à isoler cet état par utilisateur, avec le user meta, qui existe précisément pour ce genre de préférence individuelle.

## Le mauvais réflexe : une option globale

Voici, simplifié, le code d'origine de cette extension :

```
add_action( 'admin_notices', function() {
    if ( get_option( 'adhesions_notice_api_masquee' ) ) {
        return;
    }
    echo '<div class="notice notice-warning is-dismissible">';
    echo '<p>Configurez votre clé API pour activer la synchronisation.</p>';
    echo '</div>';
} );
```

La classe CSS `is-dismissible` fournie par WordPress masque visuellement la notice au clic, côté navigateur uniquement, via un script déjà présent dans l'administration. Sans code additionnel, cette fermeture ne persiste nulle part : elle réapparaît au rechargement suivant. L'extension avait donc ajouté un appel Ajax qui écrivait dans une option globale, ce qui masquait certes la notice de façon persistante, mais pour tous les comptes du site à la fois.

## La bonne isolation : user meta

Le user meta est justement prévu pour stocker un état propre à chaque compte, sans configuration supplémentaire ni table dédiée. La réécriture complète tient en peu de code :

> L'essentiel à retenir : Une option globale masque la notice pour tout le monde d'un coup ; Le user meta isole l'état vu ou masqué par personne ; Un bouton de fermeture doit appeler l'admin-ajax dédié, pas un simple CSS

```
add_action( 'admin_notices', function() {
    $user_id = get_current_user_id();

    if ( get_user_meta( $user_id, 'adhesions_notice_api_vue', true ) ) {
        return;
    }

    echo '<div class="notice notice-warning is-dismissible" data-notice="adhesions-api">';
    echo '<p>Configurez votre clé API pour activer la synchronisation.</p>';
    echo '</div>';
} );

add_action( 'wp_ajax_adhesions_masquer_notice_api', function() {
    check_ajax_referer( 'adhesions_masquer_notice', 'nonce' );
    update_user_meta( get_current_user_id(), 'adhesions_notice_api_vue', 1 );
    wp_send_json_success();
} );
```

Côté script, il suffit d'intercepter l'événement de fermeture propre aux notices `is-dismissible`, déclenché par WordPress lui-même au clic sur la croix, et d'appeler cette action Ajax à ce moment précis :

```
jQuery( document ).on( 'click', '[data-notice="adhesions-api"] .notice-dismiss', function() {
    jQuery.post( ajaxurl, {
        action: 'adhesions_masquer_notice_api',
        nonce: adhesionsNoticeData.nonce,
    } );
} );
```

Résultat : chaque administrateur ferme la notice pour lui-même, sans influencer les autres comptes. Celui qui n'a pas encore vu le message continue de le voir jusqu'à ce qu'il le ferme à son tour, ou jusqu'à ce que la clé API soit réellement configurée.

## Quand une notice doit rester globale malgré tout

Toutes les notices ne doivent pas suivre ce principe d'isolation. Une alerte annonçant qu'une mise à jour de base de données est requise avant de continuer à utiliser l'extension concerne réellement tout le monde, et masquer cet état par utilisateur créerait un faux sentiment de sécurité pour les comptes qui ne l'auraient pas vue. Le choix entre option globale et user meta dépend donc de la nature de l'information, pas d'une préférence de code par défaut.

- Option globale : état réellement partagé, comme une migration de base non terminée ou une licence expirée pour tout le site.
- User meta : préférence d'affichage individuelle, comme un message d'astuce, une nouveauté de version, ou un avertissement que chacun doit traiter à son rythme.
- Toujours prévoir un moyen de réafficher une notice masquée, par exemple lors d'une mise à jour majeure de l'extension, en changeant la clé de meta utilisée plutôt qu'en réinitialisant l'ancienne.

### Gérer la réapparition après une nouvelle version

Un piège fréquent consiste à vouloir réafficher une notice déjà masquée après la sortie d'une nouvelle version de l'extension, sans vouloir purger le user meta de tous les comptes existants. La solution la plus simple reste de versionner la clé de meta elle-même, par exemple `adhesions_notice_api_vue_v2`, ce qui revient à considérer qu'il s'agit d'une notice différente, sans toucher à l'historique des comptes qui avaient masqué la précédente.

> Une règle que nous appliquons désormais systématiquement : avant d'écrire une notice d'administration, se demander qui, précisément, doit la revoir la prochaine fois qu'elle disparaît. Si la réponse dépend de la personne connectée, ce n'est jamais à une option globale de porter cet état.

## En résumé

Le choix entre option globale et user meta pour une notice d'administration semble un détail d'implémentation, mais il détermine directement si l'information atteint réellement les bonnes personnes. Sur un site à plusieurs administrateurs, ignorer cette distinction revient à masquer un message important pour des comptes qui ne l'ont jamais vu, sans que personne ne s'en aperçoive avant qu'un incident ne le révèle.
