Fonctionnement technique de la vérification des affichages conditionnels des saisies

La présente documentation est une documentation technique, qui explique comment, concrètement, le plugin Saisies vérifie les affichages conditionnels des saisies.

Elle est valable à partir de la version 3.51.0 du plugin.

Préambule

On lira au préalable les deux documents de référence :

Vocabulaire

Nous distinguons par la suite :

  • saisie conditionnée : celle qui reçoit un test afficher_si;
  • saisie conditionnante : celles qui sont évaluées dans les afficher_si.

L’affichage d’une saisie conditionnée dépend de la valeur d’une (ou plusieurs) saisies conditionnantes.

Un test peut être simple (@a@ == 'b') ou complexe. Un test complexe est composé de plusieurs tests simples liés par des opérateurs booléens/des parenthèses (@a@ == 'b' || @a@ == 'c' ).

Le problème

Les conditions d’affichage des saisies doivent être testées :

  • à la volée, en JavaScript, à chaque fois qu’une saisie est modifiée
  • une fois le formulaire posté, en PHP, pour ne pas tenir compte des saisies vides parce que non affichées à cause d’une condition non remplie.

Il faut donc convertir un pseudo langage (celui défini dans l’article “Affichage conditionnel de saisie : syntaxe des tests”) en deux langages, javascript et PHP, en s’assurant de la cohérence.

Les éléments communs

Le fichier inc/saisies_afficher_si_commun.php contient les fonctions communes pour la vérification.

La fonction de base est saisies_parser_condition_afficher_si().

Elle reçoit une condition de type afficher_si et retourne un tableau listant l’ensemble des tests simples de cette condition. Ce tableau ne se préoccupe ni des parenthèses ni des opérateurs booléens (à l’exception de la négation !).

Pour chaque test simple, le tableau décrit :

  • le test complet ;
  • chacun de ses composants : champ, opérateur, valeur à tester, type de guillemets, négateurs, etc.

Ajouter un nouveau type de test se fait donc d’abord en modifiant cette fonction.

Les fonctions de conversion des conditions afficher_si en PHP/JS :

  • prennent la condition ($condition);
  • l’analysent via saisies_parser_condition_afficher_si();
  • à partir de cette analyse, remplacent l’ensemble des tests simples par leur équivalent PHP/JS.

Une autre fonction à utiliser : saisies_afficher_si_verifier_syntaxe(). Elle prend deux paramètres :

  • la condition afficher_si;
  • le résultat de saisies_parser_condition_afficher_si()

Cette fonction retourne false s’il y a un problème dans la syntaxe du afficher_si. C’est à dire :

  1. Autres choses que des tests simples, des parenthèses et des opérateurs booléens. En effet, si tel est le cas, cela signifie que la condition afficher_si contient un code arbitraire, ce qui peut être problématique en termes de sécurité. Ce premier test est très rigoureux.
  2. Des problèmes dans l’enchaînement des opérateurs et des parenthèses : nombre non appareillé des parenthèses ouvrantes/fermantes ; opérateurs booléens sans rien à gauche ou à droite ; etc. Ce second test n’est pas exhaustif. En effet, si un faux positif passe, cela n’implique pas l’exécution de code arbitraire, mais juste un échec à effectuer le test.

Côté JavaScript

L’attribut data-afficher_si

Cet attribut se trouve dans le fichier saisies/_base.html, pour la plupart des saisies.

Pour les saisies “autonomes”, qui n’utilisent pas ce fichier, il faut l’insérer dans le squelette, au niveau du conteneur de saisie, de la manière suivante :

[ data-afficher_si="(#ENV*{afficher_si}|saisies_afficher_si_js{#ENV{_saisies}})"]

La valeur de cet attribut un bout de code JavaScript qui effectue un test et retourne true ou false. Elle est calculée via la fonction saisies_afficher_si_js() qui reçoit le test afficher_si et la liste des saisies du formulaire courant.

La fonction saisies_afficher_si_js()

Cette fonction détermine la valeur de data-afficher_si en fonction du type des saisies conditionnantes.

Pour ce faire elle va charger la fonction saisies_afficher_si_js_<type_de_saisies>() dans le fichier saisies_afficher_si_js/<type_de_saisie.php. Si cette fonction n’est pas trouvable, elle se rabat sur saisies_afficher_si_js_defaut() dans le fichier saisies_afficher_si_js/defaut.php. En général, il n’est pas nécessaire de définir sa propre fonction, car la fonction par défaut suffit. Au 10 mars 2021, seul le plugin CVT-UPLOAD définit une fonction spécifique saisies_afficher_si_js_fichiers().

La fonction saisies_afficher_si_js_defaut(), utilisée donc dans 99% des cas, se contente de remplacer les tests simples par un appel à la fonction JS afficher_si, qui reçoit en argument un tableau décrivant les composantes du test simple.

Le code Javascript proprement dit

Le script javascript/saisies_afficher_si.js, chargé dans l’entête des pages web :

  • est à l’affût des changements sur les saisies du formulaire (.change());
  • si un changement a lieu sur une saisie conditionnante, recherche les saisies conditionnées, en regardant les attributs data-afficher_si;
  • stocke la valeur courante de l’ensemble des champs dans un tableau afficher_si_current_data;
  • execute (via eval()) le test de data-afficher_si, qui dans la plupart des cas appelle la fonction afficher_si();
  • en fonction du résultat, affiche ou masque la saisie conditionnante et modifie la classe entre afficher_si_visible et afficher_si_masque, règle également les attributs aria-hidden;
  • pour les saisies conditionnées définies comme obligatoires, bascule, si besoin, l’attribut required. En effet, si la saisie est masquée, il faut supprimer l’attribut, pour que les navigateurs ne disent pas qu’un champ masqué est obligatoire. Mais il faut le rétablir lorsque la saisie est reaffichée. Un drapeau data-afficher-si-required est utilisé pour conserver en mémoire l’information;
  • en outre, au chargement du formulaire, le script teste l’ensemble des data-afficher_si et masque le cas échéant les saisies, tout en ajoutant la classe afficher_si_masque_chargement.

Ainsi, lors d’un changement dans le formulaire, seules les saisies conditionnées par la saisie conditionnante modifiée sont testées. Un seul script est chargé pour l’ensemble des formulaires [1].

Pour tenir compte des constantes _SAISIES_AFFICHER_SI_JS_SHOW et _SAISIES_AFFICHER_SI_JS_HIDE, des fonctions sont définies dans l’entête de la page.

Côté PHP

La fonction saisies_verifier_afficher_si()

La fonction saisies_verifier_afficher_si() prend la description des saisies d’un formulaire en premier paramètre. En second paramètre, elle peut recevoir un tableau comprenant les valeurs associés à chaque saisies (utilisée pour la balise #VOIR_SAISIES). À défaut, la fonction ira chercher les valeurs dans $_REQUEST.

Pour les saisies conditionnées dont la condition n’est pas remplie :

  • Si le second paramètre n’est pas fourni, modifie $_REQUEST pour mettre la valeur de la saisie à '' (chaine vide).
  • Dans tous les cas, ajoute la saisie masquée dans une liste interne. On peut ainsi retrouver toutes les saisies masquées en appelant la fonction saisies_afficher_si_liste_masquees().

La fonction retourne la liste des saisies qu’elle a reçu en entrée, à l’exception des saisies masquées.

À noter que l’on ne considère pas qu’une saisie est masquée :
-  si l’option globale afficher_si_avec_post du tableau de saisies est activée;
-  si, pour une saisie donnée, l’option afficher_si_avec_post, est activée.

Comment sont évalués les tests côté PHP

saisies_verifier_afficher_si() appelle la fonction saisies_evaluer_afficher_si(), qui reçoit la condition de la saisie conditionnée, et les paramètres d’environnement.

Cette dernière fonction, appelle saisies_transformer_condition_afficher_si(), laquelle en s’appuyant sur la fonction saisies_parser_condition_afficher_si() transforme la condition afficher_si en une condition PHP évaluable (via eval).

saisies_transformer_condition_afficher_si() fait elle-même appelle à d’autres fonctions selon le type de saisie conditionnante à tester, selon les opérateurs, etc.

Compléments

Si vous créez vos saisies ou surchargés vos saisies, il est nécessaire de lire les paragraphes suivants de l’article “Créer ses propres saisies” :

Footnotes

[1Ces deux points n’étaient pas vrais avant la version 3.26.0 du plugin, qui générait un JavaScript spécifique par formulaire.

Discussion

No discussion

Add a comment

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite / PostgreSQL
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparait.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Who are you?
[Log in]

To show your avatar with your message, register it first on gravatar.com (free et painless) and don’t forget to indicate your Email addresse here.

Enter your comment here

This form accepts SPIP shortcuts {{bold}} {italic} -*list [text->url] <quote> <code> and HTML code <q> <del> <ins>. To create paragraphs, just leave empty lines.

Add a document

Follow the comments: RSS 2.0 | Atom