# pre_delete_term : empêcher la suppression de termes de taxonomie stratégiques

> Bloquer par code la suppression accidentelle d'une catégorie dont dépend une logique métier entière, avant qu'un clic malheureux ne casse tout un site.

- Auteur : Clément Hadrot
- Publié le : 2022-04-04
- Mis à jour le : 2022-04-04
- Catégorie : Tips
- URL : https://wpmoderne.dev.wordpress-developpement.fr/tips/pre-delete-term-empecher-suppression-termes-strategiques/

## L’essentiel

- pre_delete_term intercepte la suppression avant qu'elle ait lieu
- Renvoyer un WP_Error bloque l'action proprement
- Utile pour les termes liés à une logique métier codée en dur

Un site associatif que nous maintenons affiche différemment sa page d'accueil selon qu'un article appartient à la catégorie « Actualité urgente » ou non : logique codée en dur dans le thème, avec l'identifiant du terme directement référencé dans plusieurs endroits. Un jour, un nouveau bénévole formé à la va-vite a supprimé cette catégorie en pensant faire du ménage. Résultat : plusieurs blocs d'affichage silencieusement cassés, sans aucun message d'erreur visible, découverts seulement plusieurs jours plus tard.

Ce genre d'incident se prévient facilement en interceptant la suppression avant qu'elle n'ait lieu, grâce au hook `pre_delete_term`, introduit en WordPress 4.9. Il permet de refuser explicitement la suppression d'un terme identifié comme stratégique.

## Le fonctionnement de pre_delete_term

Ce filtre reçoit une valeur par défaut, un identifiant de terme et une taxonomie. En renvoyant un objet `WP_Error` plutôt que la valeur reçue, on interrompt la suppression : WordPress annule l'opération et transmet le message d'erreur à l'écran d'administration.

> L'essentiel à retenir : pre_delete_term intercepte la suppression avant qu'elle ait lieu ; Renvoyer un WP_Error bloque l'action proprement ; Utile pour les termes liés à une logique métier codée en dur

## Protéger un terme précis par son identifiant

```
function asso_proteger_terme_strategique( $delete, $term_id, $taxonomy ) {
    $termes_proteges = array(
        12 => 'category', // Actualité urgente
        45 => 'category', // Appels aux dons
    );

    if ( isset( $termes_proteges[ $term_id ] ) && $termes_proteges[ $term_id ] === $taxonomy ) {
        return new WP_Error(
            'terme_protege',
            'Ce terme est utilisé par une logique du site et ne peut pas être supprimé.'
        );
    }

    return $delete;
}
add_filter( 'pre_delete_term', 'asso_proteger_terme_strategique', 10, 3 );
```

Repérer les identifiants numériques directement dans le code source reste fragile d'un environnement à l'autre : mieux vaut, quand c'est possible, protéger un terme par son `slug`, stable entre la production et un environnement de recette, plutôt que par son identifiant numérique, qui peut varier :

```
function asso_proteger_par_slug( $delete, $term_id, $taxonomy ) {
    if ( 'category' !== $taxonomy ) {
        return $delete;
    }

    $term = get_term( $term_id, $taxonomy );
    $slugs_proteges = array( 'actualite-urgente', 'appels-aux-dons' );

    if ( $term && in_array( $term->slug, $slugs_proteges, true ) ) {
        return new WP_Error(
            'terme_protege',
            sprintf( 'Le terme « %s » est protégé et ne peut pas être supprimé.', $term->name )
        );
    }

    return $delete;
}
add_filter( 'pre_delete_term', 'asso_proteger_par_slug', 10, 3 );
```

## Le message affiché côté administration

WordPress affiche automatiquement le message de l'objet `WP_Error` dans un encart d'alerte au-dessus de la liste des termes après la tentative bloquée. Il n'y a rien de plus à faire côté affichage : la simple présence de l'erreur suffit à déclencher ce retour visuel standard.

## Aller plus loin : masquer aussi le lien de suppression

Bloquer la suppression au niveau serveur reste indispensable, mais laisser visible un lien « Supprimer » qui échoue systématiquement crée de la confusion. Le filtre `{taxonomy}_row_actions` permet de retirer ce lien directement dans la liste pour les termes protégés :

```
function asso_retirer_lien_suppression( $actions, $term ) {
    $slugs_proteges = array( 'actualite-urgente', 'appels-aux-dons' );

    if ( in_array( $term->slug, $slugs_proteges, true ) ) {
        unset( $actions['delete'] );
    }

    return $actions;
}
add_filter( 'category_row_actions', 'asso_retirer_lien_suppression', 10, 2 );
```

## Ce que cette protection ne couvre pas

- La suppression via WP-CLI reste possible si l'appel passe par une fonction bas niveau qui ignore ce filtre : une vérification manuelle reste recommandée avant toute opération en masse.
- Le renommage ou le changement de slug d'un terme protégé n'est pas concerné par ce filtre, qui ne cible que la suppression proprement dite.
- Cette protection ne remplace pas une gestion fine des rôles et capacités personnalisés, qui agit en amont sur qui a même le droit de voir l'écran de gestion des termes.

> Sur un projet où la logique métier dépend d'identifiants de taxonomie codés en dur, documenter clairement ces dépendances dans le code, en commentaire à côté de chaque identifiant utilisé, reste tout aussi important que la protection technique elle-même.

## En résumé

`pre_delete_term` offre une protection simple et ciblée contre un risque bien réel : la suppression accidentelle d'un terme dont dépend le fonctionnement du site. Quelques lignes suffisent à transformer un clic malheureux en message d'erreur explicite plutôt qu'en incident silencieux découvert des jours plus tard.
