# Extension compatible multisite : la checklist avant publication

> Une extension qui fonctionne parfaitement en installation simple peut échouer discrètement sur un réseau multisite. Neuf points à vérifier avant de dire qu'elle est vraiment compatible.

- Auteur : Clément Hadrot
- Publié le : 2021-12-16
- Mis à jour le : 2021-12-16
- Catégorie : Extensions
- URL : https://wpmoderne.dev.wordpress-developpement.fr/extensions/extension-compatible-multisite-checklist-publication/

## L’essentiel

- L'activation réseau transmet un paramètre distinct que le hook standard n'expose pas
- switch_to_blog change le contexte de requête mais pas toujours le cache d'objets
- Les capacités super admin ne se testent jamais avec current_user_can seul

Un réseau de neuf sites vitrines pour une franchise de salles de sport a mis en évidence, avec une extension de réservation de cours collectifs à peine terminée, un lot de bugs qui n'apparaissaient jamais en installation simple. Chaque site du réseau avait ses propres cours, mais un tableau de bord centralisé, réservé au super administrateur, devait agréger les réservations de tous les sites. Voici la checklist qui s'est progressivement construite en corrigeant ces bugs un par un.

## 1. Vérifier le paramètre d'activation réseau

Le hook `register_activation_hook` reçoit un second paramètre, `$network_wide`, ignoré par la majorité des tutoriels d'introduction. Sans le traiter, une activation réseau ne crée les tables et options nécessaires que pour le site sur lequel l'administrateur se trouvait au moment du clic.

```
function fitness_activer( $network_wide ) {
    if ( is_multisite() && $network_wide ) {
        foreach ( get_sites( array( 'fields' => 'ids' ) ) as $site_id ) {
            switch_to_blog( $site_id );
            fitness_creer_tables_site();
            restore_current_blog();
        }
    } else {
        fitness_creer_tables_site();
    }
}
register_activation_hook( __FILE__, 'fitness_activer' );
```

## 2. Gérer l'ajout d'un nouveau site après coup

Un réseau grandit rarement une seule fois : un dixième site peut être créé des mois après l'activation réseau initiale de l'extension. Le hook `wp_initialize_site` permet d'exécuter la même routine d'initialisation pour tout nouveau site rejoignant le réseau.

```
add_action( 'wp_initialize_site', function ( $new_site ) {
    switch_to_blog( $new_site->blog_id );
    fitness_creer_tables_site();
    restore_current_blog();
}, 10, 1 );
```

## 3. Choisir entre options de site et options de réseau

> L'essentiel à retenir : L'activation réseau transmet un paramètre distinct que le hook standard n'expose pas ; switch_to_blog change le contexte de requête mais pas toujours le cache d'objets ; Les capacités super admin ne se testent jamais avec current_user_can seul

Une donnée propre à chaque salle de sport (ses horaires, ses coachs) relève de `get_option` / `update_option`, propres à chaque site. Une donnée partagée par tout le réseau (une clé d'API commune, un tarif de licence global) relève de `get_site_option` / `update_site_option`, stockées une seule fois pour l'ensemble du réseau.

- Confondre les deux est l'erreur la plus fréquente : une clé d'API stockée avec `update_option` devrait être ressaisie sur chacun des neuf sites, alors qu'elle est identique partout
- `get_site_option` retombe automatiquement sur les valeurs du réseau principal si aucune valeur spécifique n'est enregistrée
- Les tables personnalisées, elles, doivent généralement être dupliquées par site (avec le préfixe propre à chaque blog) sauf choix architectural explicite d'une table réseau unique

## 4. Parcourir les sites avec switch_to_blog correctement

Le tableau de bord centralisé de réservations devait interroger, tour à tour, chacun des neuf sites. `switch_to_blog()` change le contexte de `$wpdb` et de la plupart des fonctions de contenu, mais pas systématiquement tout le reste de l'environnement.

```
foreach ( get_sites( array( 'fields' => 'ids' ) ) as $site_id ) {
    switch_to_blog( $site_id );

    $reservations = get_posts( array(
        'post_type'      => 'reservation',
        'posts_per_page' => -1,
    ) );

    fitness_agreger_reservations( $site_id, $reservations );

    restore_current_blog();
}
```

Toujours appeler `restore_current_blog()` après chaque `switch_to_blog()`, y compris en cas de sortie anticipée d'une fonction (via un `return` précoce en cas d'erreur) : un oubli laisse le contexte de requête basculé sur le mauvais site pour tout le reste de l'exécution de la page.

## 5. Distinguer capacité globale et capacité par site

Un utilisateur peut être administrateur d'un site du réseau sans être super administrateur du réseau lui-même. Vérifier uniquement `current_user_can( 'manage_options' )` pour autoriser l'accès au tableau de bord centralisé aurait exposé les données des neuf salles à n'importe quel administrateur local d'un seul site.

```
if ( ! is_super_admin() ) {
    wp_die( 'Accès réservé au réseau.' );
}
```

`is_super_admin()` reste la fonction correcte pour ce cas précis, distincte de toute vérification de capacité classique, elle-même toujours relative au site courant.

## Les points restants de la checklist

1. Tester la désactivation et la désinstallation en contexte réseau, pas uniquement l'activation
2. Vérifier qu'aucun chemin de fichier n'est codé en dur avec l'hypothèse d'un unique répertoire d'uploads (chaque site multisite a son propre sous-répertoire)
3. S'assurer qu'un cache d'objets persistant partagé entre sites ne mélange pas les clés de cache d'un site à l'autre (préfixer les clés avec l'identifiant du site si nécessaire)
4. Documenter clairement, dans le fichier readme, si l'extension nécessite une activation réseau ou site par site

## En résumé

Une extension réellement compatible multisite ne se contente pas de « ne pas planter » sur un réseau : elle distingue consciemment ce qui relève du réseau et ce qui relève de chaque site, gère l'ajout tardif de nouveaux sites, et sépare rigoureusement les capacités globales des capacités locales. Cette checklist, née de bugs bien réels sur ce projet de salles de sport, reste celle que je reprends systématiquement avant toute publication destinée à un client multisite.
