Le WordPress d'aujourd'hui, décodé pour les développeurs

Sécurité

« 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.

Par WordPress Développement • 3 mars 2023 • 4 min de lecture • Aucun commentaire
« TypeError: Argument must be of type array » sur un filtre wp_kses personnalisé mal typé

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.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi