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

Accessibilité

Le typage strict PHP empêche une valeur ARIA invalide de partir en production

Un attribut ARIA généré dynamiquement accepte n'importe quelle chaîne en entrée. Un type énuméré et declare(strict_types=1) suffisent à bloquer une valeur invalide avant l'exécution.

Par WordPress Développement • 7 septembre 2023 • 5 min de lecture • Aucun commentaire
Le typage strict PHP empêche une valeur ARIA invalide de partir en production

declare(strict_types=1); — cette ligne, placée en tête d’un fichier PHP, change la donne dès qu’une fonction reçoit un argument d’un type inattendu : au lieu d’une conversion silencieuse, PHP lève une TypeError immédiate. Sur un plugin maison qui génère des attributs ARIA pour un tableau de données triable, cette rigueur a permis d’intercepter, dès le développement, une valeur d’attribut qui aurait autrement fini par s’afficher, invalide, en production.

Cette recette construit une fonction de génération d’attribut aria-sort, validée à l’écriture plutôt qu’a posteriori, pour un tableau de résultats généré dynamiquement par un plugin interne. Elle ne traite pas de la validation côté navigateur, qui reste de toute façon incapable de rattraper une valeur mal formée envoyée depuis le serveur.

Le problème posé

L’attribut aria-sort, posé sur un en-tête de colonne de tableau triable, n’accepte qu’un nombre limité de valeurs définies par la spécification ARIA : ascending, descending, none et other. Une fonction PHP qui génère cet attribut à partir d’un paramètre de requête, sans validation, peut très bien recevoir n’importe quelle chaîne arbitraire, y compris une faute de frappe ou une valeur héritée d’un ancien format :

function wpm_attribut_aria_sort( string $direction ): string {
    return 'aria-sort="' . $direction . '"';
}

echo wpm_attribut_aria_sort( $_GET['tri'] ?? 'none' );

Si le paramètre tri vaut, par exemple, decroissant au lieu de descending — une confusion facile entre le français utilisé côté interface et l’anglais attendu par la spécification ARIA — l’attribut généré devient aria-sort="decroissant", une valeur non reconnue par les technologies d’assistance, qui l’ignoreront silencieusement sans qu’aucune erreur ne se manifeste visuellement.

Étape 1 : restreindre le type accepté

PHP ne propose pas nativement de type énuméré de chaînes littérales comme certains langages, mais il permet depuis longtemps de restreindre les valeurs via une énumération native, disponible depuis PHP 8.1, ou plus simplement via une validation explicite combinée au typage strict :

declare(strict_types=1);

function wpm_attribut_aria_sort( string $direction ): string {
    $valeurs_autorisees = array( 'ascending', 'descending', 'none', 'other' );

    if ( ! in_array( $direction, $valeurs_autorisees, true ) ) {
        throw new \InvalidArgumentException(
            sprintf( 'Valeur aria-sort invalide : "%s". Attendu : %s.', $direction, implode( ', ', $valeurs_autorisees ) )
        );
    }

    return 'aria-sort="' . $direction . '"';
}

La déclaration declare(strict_types=1) en tête de fichier interdit toute conversion implicite de type sur les arguments typés : un appel avec un entier ou un tableau à la place d’une chaîne lève immédiatement une TypeError, plutôt que de tenter une conversion approximative qui masquerait l’erreur de programmation à l’origine du problème.

L'essentiel à retenir : declare(strict_types=1) refuse une conversion de type implicite ; Une union de littéraux de chaîne restreint les valeurs acceptées ; L'erreur remonte au développement, jamais en production

Étape 2 : traduire les valeurs françaises côté interface

Puisque l’interface d’administration du plugin utilise des libellés en français pour rester cohérente avec le reste de l’écran de configuration, une fonction de correspondance explicite fait le lien entre le vocabulaire affiché et le vocabulaire attendu par la spécification ARIA, plutôt que de laisser un paramètre français fuiter jusqu’à la fonction de génération :

function wpm_normaliser_direction_tri( string $valeur_interface ): string {
    $correspondances = array(
        'croissant'  => 'ascending',
        'decroissant' => 'descending',
        'aucun'      => 'none',
    );

    return $correspondances[ $valeur_interface ] ?? 'none';
}

$direction = wpm_normaliser_direction_tri( $_GET['tri'] ?? 'aucun' );
echo wpm_attribut_aria_sort( $direction );

Cette séparation isole clairement les responsabilités : la fonction de normalisation gère la traduction depuis le vocabulaire de l’interface, tandis que la fonction de génération d’attribut ne reçoit et ne valide plus que le vocabulaire technique attendu par la spécification ARIA.

Étape 3 : couvrir le cas par un test

Un test unitaire simple confirme que la fonction rejette bien toute valeur hors de la liste autorisée, ce qui documente également, pour la suite du projet, le comportement attendu en cas d’entrée invalide :

public function test_valeur_invalide_leve_une_exception(): void {
    $this->expectException( \InvalidArgumentException::class );
    wpm_attribut_aria_sort( 'decroissant' );
}

public function test_valeur_valide_generate_l_attribut(): void {
    $this->assertSame( 'aria-sort="descending"', wpm_attribut_aria_sort( 'descending' ) );
}

Conseil maison : sur tout attribut ARIA dont la spécification n’accepte qu’un nombre fini de valeurs, valider explicitement l’entrée dans la fonction de génération elle-même, plutôt que de faire confiance à l’appelant, évite qu’une confusion de vocabulaire ne se propage jusqu’au navigateur.

Variantes

Pour un plugin qui multiplie ce type d’attributs à valeurs restreintes — aria-current, aria-live, aria-orientation — une classe utilitaire centralisant les listes de valeurs autorisées, une par attribut, évite de dupliquer la logique de validation à chaque nouvelle fonction de génération. Une énumération native PHP 8.1, une par attribut concerné, offre une alternative plus proche du typage natif du langage, au prix d’une verbosité un peu plus importante pour un jeu de valeurs aussi restreint.

En résumé

Le typage strict, combiné à une validation explicite des valeurs autorisées, transforme une faute de frappe silencieuse en erreur détectée dès le développement, avant qu’un attribut ARIA mal formé ne parte en production. Sur un plugin qui génère ce type d’attribut à partir d’une entrée utilisateur ou d’un paramètre de requête, ce garde-fou coûte quelques lignes de code et évite un bug invisible côté navigateur, qui aurait autrement fallu détecter a posteriori par un audit externe.

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