# « TypeError: Argument must be of type array » sur un filtre wp_kses personnalisé mal typé

> Un fatal PHP surgit après l'ajout d'un filtre sur les balises autorisées. La cause tient à la structure exacte attendue par wp_kses, pas au choix des balises.

- Auteur : WordPress Développement
- Publié le : 2023-03-03
- Mis à jour le : 2023-03-03
- Catégorie : Sécurité
- URL : https://www.wpmoderne.fr/securite/typeerror-wp-kses-tableau-mal-type/

## L’essentiel

- wp_kses attend un tableau associatif, pas une simple liste
- Un tableau vide désactive tout, contrairement à ce qu'on croit
- Toujours tester le filtre isolément avant de l'activer globalement

`Fatal error: Uncaught TypeError: wp_kses(): Argument #2 ($allowed_html) must be of type array, string given`. Ce message apparaît généralement juste après l'ajout d'un filtre sur `wp_kses_allowed_html`, souvent lors d'une tentative rapide d'ajuster la liste des balises autorisées pour un rôle particulier. Le code semble correct à première lecture, la fonction plante pourtant dès qu'un contenu passe par le filtrage.

Ce type d'erreur touche presque toujours le même point : la structure du tableau passé en second argument à `wp_kses()`, ou renvoyé par un filtre sur `wp_kses_allowed_html`, ne correspond pas à ce que la fonction attend réellement.

## Symptôme : le fatal apparaît à l'enregistrement d'un contenu

Le code fautif ressemble typiquement à ceci :

```
add_filter( 'wp_kses_allowed_html', function ( $tags, $context ) {
    if ( $context === 'post' ) {
        $tags = 'p,strong,em';
    }
    return $tags;
}, 10, 2 );
```

L'intention est claire : autoriser trois balises pour le contexte `post`. Le résultat l'est moins : dès qu'un article est enregistré, WordPress appelle en interne `wp_kses_post()`, qui transmet cette valeur à `wp_kses()`. Comme `$tags` est devenu une chaîne de caractères au lieu d'un tableau, PHP 8 lève un `TypeError` strict au lieu de tenter une conversion silencieuse comme le faisaient d'anciennes versions de PHP.

## Diagnostic : la structure attendue par wp_kses

`wp_kses_allowed_html` doit renvoyer un tableau dont chaque clé est le nom d'une balise en minuscules, et chaque valeur un tableau associatif des attributs autorisés pour cette balise (la valeur peut être un tableau vide si aucun attribut n'est autorisé, mais jamais une chaîne).

> L'essentiel à retenir : wp_kses attend un tableau associatif, pas une simple liste ; Un tableau vide désactive tout, contrairement à ce qu'on croit ; Toujours tester le filtre isolément avant de l'activer globalement

La forme correcte pour l'exemple précédent est la suivante :

```
add_filter( 'wp_kses_allowed_html', function ( $tags, $context ) {
    if ( $context === 'post' ) {
        $tags = array(
            'p'      => array(),
            'strong' => array(),
            'em'     => array(),
        );
    }
    return $tags;
}, 10, 2 );
```

Un piège voisin, plus discret, consiste à écraser `$tags` plutôt que de le compléter. Le filtre reçoit en premier argument la liste déjà construite pour le contexte demandé ; l'écraser entièrement supprime toutes les balises normalement autorisées par WordPress pour ce contexte, y compris des balises basiques comme `a` ou `br` qui ne figuraient pas dans la nouvelle liste.

## Un tableau vide n'est pas un tableau permissif

Autre confusion fréquente : penser qu'un tableau vide (`array()`) autorise tout. C'est l'inverse — un tableau vide en retour de `wp_kses_allowed_html` signifie qu'aucune balise n'est autorisée, et tout le HTML du contenu sera dépouillé à l'enregistrement, y compris des balises légitimes ajoutées par l'éditeur de blocs. Ce comportement, correct du point de vue de `wp_kses`, surprend souvent parce que l'erreur ne se manifeste pas par un fatal mais par une perte silencieuse de mise en forme.

### Cas particulier : fusionner plutôt qu'écraser

```
add_filter( 'wp_kses_allowed_html', function ( $tags, $context ) {
    if ( $context === 'post' ) {
        $tags['figure'] = array( 'class' => true );
        $tags['figcaption'] = array();
    }
    return $tags;
}, 10, 2 );
```

Cette version ajoute deux balises à la liste existante sans en supprimer aucune, ce qui évite l'effet de bord constaté avec l'écrasement complet.

## Prévention : isoler le filtre avant de le déployer

1. Tester le filtre seul, sur un post de test, en vérifiant le rendu avant et après activation
2. Utiliser `var_export( apply_filters( 'wp_kses_allowed_html', array(), 'post' ) )` dans un script WP-CLI ponctuel pour inspecter la structure réellement renvoyée
3. Ne jamais retourner directement une variable qui pourrait provenir d'une source externe (option, champ personnalisé) sans vérifier son type avec `is_array()`

Un contrôle défensif simple, ajouté en tête du filtre, évite que ce type de fatal ne remonte en production :

```
add_filter( 'wp_kses_allowed_html', function ( $tags, $context ) {
    if ( ! is_array( $tags ) ) {
        return $tags;
    }
    // ... logique de fusion ici
    return $tags;
}, 10, 2 );
```

## Prévention à long terme

Ce fatal illustre un principe plus large valable pour tous les filtres qui transitent par des fonctions internes de WordPress : le nom du filtre ne dit rien de la structure exacte attendue, et seule la documentation de la fonction consommatrice (ici `wp_kses()`, documentée sur developer.wordpress.org) fait foi. Vérifier cette signature avant d'écrire le filtre évite la majorité des erreurs de ce type.

## En résumé

Le message d'erreur pointe un problème de typage, mais la cause réelle est presque toujours une confusion sur la forme attendue par `wp_kses_allowed_html` : un tableau associatif balise → attributs, jamais une chaîne, et une fusion plutôt qu'un écrasement de la liste existante. Une fois cette structure respectée, le filtre fonctionne sans effet de bord sur les autres balises du contexte.
