# Un plugin_action_links qui pointe à côté après un renommage de classe

> Un lien de réglages construit à partir du nom de classe plutôt que du slug de fichier casse silencieusement lors d'un refactoring interne.

- Auteur : Clément Hadrot
- Publié le : 2025-03-09
- Mis à jour le : 2025-03-09
- Catégorie : Extensions
- URL : https://wpmoderne.dev.wordpress-developpement.fr/extensions/plugin-action-links-pointe-a-cote-renommage-classe/

## L’essentiel

- Le filtre plugin_action_links_{$plugin_file} dépend du chemin du fichier principal, pas du nom de classe
- Construire l'URL à partir de get_class() casse dès qu'une classe est renommée
- Le correctif consiste à ancrer le lien sur le slug du plugin, jamais sur un nom de classe

`$ php -l extension-catalogue.php` ne révèle rien : le fichier est syntaxiquement valide, l'extension s'active sans erreur, et pourtant le lien « Réglages » qui apparaît sous son nom dans la liste des extensions renvoie vers une page blanche après un récent refactoring. Ce genre de régression ne casse rien de visible immédiatement, ce qui la rend particulièrement sournoise : elle attend qu'un administrateur clique sur ce lien précis pour se manifester.

Le contexte : une extension de gestion de catalogue produit avait vu sa classe principale renommée de `Catalogue_Plugin` à `Catalogue_Core` lors d'un nettoyage de nommage. Le fichier principal, lui, n'avait pas changé de nom. C'est précisément cette asymétrie qui a provoqué le problème.

## Symptôme : un lien qui pointait vers une page fantôme

Le lien de réglages ajouté via le filtre `plugin_action_links_{$plugin_file}` pointait vers `options-general.php?page=catalogue_plugin`, alors que la page de réglages réelle était désormais enregistrée sous le slug `catalogue_core`. Résultat : un clic sur « Réglages » menait vers l'écran général des réglages WordPress, sans message d'erreur, sans notice, juste une page qui n'était pas celle attendue.

## Diagnostic : l'URL construite à partir du nom de classe

> L'essentiel à retenir : Le filtre plugin_action_links_{$plugin_file} dépend du chemin du fichier principal, pas du nom de classe ; Construire l'URL à partir de get_class() casse dès qu'une classe est renommée ; Le correctif consiste à ancrer le lien sur le slug du plugin, jamais sur un nom de classe

Le code fautif construisait dynamiquement le slug de la page de réglages à partir du nom de la classe principale, via `get_class( $this )`, plutôt que d'utiliser une constante ou un slug fixe défini une fois pour toutes.

```
class Catalogue_Core {

    public function ajouter_lien_reglages( $liens ) {
        $slug = strtolower( get_class( $this ) ); // devient "catalogue_core" après renommage
        $url  = admin_url( 'options-general.php?page=' . $slug );

        $liens[] = '<a href="' . esc_url( $url ) . '">Réglages</a>';

        return $liens;
    }
}
```

Tant que la classe s'appelait `Catalogue_Plugin`, le slug calculé correspondait par coïncidence au slug réellement enregistré via `add_options_page()` ailleurs dans le code. Le renommage de la classe a rompu cette coïncidence, sans qu'aucun message d'erreur ne signale le décalage : PHP a simplement construit une URL syntaxiquement valide, mais fonctionnellement fausse.

## Pourquoi ce genre de bug reste invisible en test rapide

Un test superficiel de l'extension après le refactoring — activation, vérification que l'écran principal fonctionne — ne révèle rien, car l'écran de réglages reste accessible directement par son URL réelle. Seul le lien contextuel de la liste des extensions est cassé, un élément que peu de suites de tests automatisées vérifient.

## Correctif : ancrer le lien sur une constante de slug

La correction consiste à définir le slug de la page de réglages une seule fois, sous forme de constante ou de propriété de classe explicite, et à le réutiliser partout où il est nécessaire : à l'enregistrement de la page, et dans la construction du lien d'action.

```
class Catalogue_Core {

    const SLUG_REGLAGES = 'catalogue-reglages';

    public function enregistrer_page_reglages() {
        add_options_page(
            'Réglages du catalogue',
            'Catalogue',
            'manage_options',
            self::SLUG_REGLAGES,
            array( $this, 'afficher_page_reglages' )
        );
    }

    public function ajouter_lien_reglages( $liens ) {
        $url = admin_url( 'options-general.php?page=' . self::SLUG_REGLAGES );

        array_unshift( $liens, '<a href="' . esc_url( $url ) . '">Réglages</a>' );

        return $liens;
    }
}

register_activation_hook( __FILE__, array( 'Catalogue_Core', 'activer' ) );

add_filter(
    'plugin_action_links_' . plugin_basename( __FILE__ ),
    array( new Catalogue_Core(), 'ajouter_lien_reglages' )
);
```

Le hook `plugin_action_links_{$plugin_file}` dépend du chemin relatif du fichier principal de l'extension, obtenu via `plugin_basename( __FILE__ )`. Ce chemin ne change pas lors d'un simple renommage de classe interne, ce qui garantit la stabilité du filtre lui-même. Le vrai risque venait de la donnée dérivée à l'intérieur, pas du hook.

## Ce qu'il faut vérifier après tout renommage de classe

1. Rechercher dans tout le code les usages de `get_class()`, `__CLASS__` ou `static::class` employés pour construire une valeur fonctionnelle, et non un simple message de log.
2. Vérifier que chaque slug de page d'administration provient d'une constante unique, jamais recalculé à partir d'un nom de classe.
3. Cliquer manuellement sur chaque lien d'action de la liste des extensions après un refactoring de nommage, même mineur.

> Un nom de classe est un détail d'implémentation ; un slug d'URL est un contrat. Ne jamais dériver le second du premier.

## En résumé

Ce bug illustre un principe plus large : toute valeur qui doit rester stable dans le temps, comme un slug d'URL ou une clé d'option, doit être définie explicitement, jamais déduite d'un élément susceptible de changer lors d'un refactoring, comme un nom de classe ou de méthode.
