L’analyse du squelette

Lorsque le phraseur (le parseur) de SPIP analyse un squelette, il traduit la syntaxe en un vocabulaire connu et compris du compilateur. On peut donc dire que le phraseur traduit une langue particulière (la syntaxe SPIP) qu’on nomme « syntaxe concrète » en une langue précise qu’on nomme « syntaxe abstraite ». Elle est définie par des objets PHP dans le fichier ecrire/puclic/interfaces.php

De cette analyse de la page, le phraseur crée un tableau la décrivant, séquentiellement et récursivement, en utilisant le vocabulaire compris du compilateur (les objets Texte, Champ, Boucle, Critere, Idiome, Inclure, Polyglotte).

Pour bien comprendre, observons quel tableau est généré par des petits exemples de squelettes.

Un texte

Squelette :

Texte simple

Tableau généré : (issu d’un print_r)

array (
  0 =>
  Texte::__set_state(array(
     'type' => 'texte',
     'texte' => 'Texte simple
'
,
     'avant' => NULL,
     'apres' => '',
     'ligne' => 1,
  )),
)

Le tableau indique que la premier élément lu sur la page (clé 0) est un élément « Texte », débutant sur la ligne 1, et possédant le texte "Texte simple".

Une balise

Squelette :

[avant(#VAL)après]

On peut comprendre du tableau ci-dessous, que le premier élément lu de la page est un Champ (une balise), que son nom est « VAL », qu’il n’est pas dans une boucle (sinon id_boucle serait défini), que ce qui est dans la partie optionnelle avant la balise est un élément « Texte » dont le texte est « avant ».

Tableau généré :

array (
  0 =>
  Champ::__set_state(array(
     'type' => 'champ',
     'nom_champ' => 'VAL',
     'nom_boucle' => '',
     'avant' =>
    array (
      0 =>
      Texte::__set_state(array(
         'type' => 'texte',
         'texte' => 'avant',
         'avant' => NULL,
         'apres' => '',
         'ligne' => 1,
      )),
    ),
     'apres' =>
    array (
      0 =>
      Texte::__set_state(array(
         'type' => 'texte',
         'texte' => 'après',
         'avant' => NULL,
         'apres' => '',
         'ligne' => 1,
      )),
    ),
     'etoile' => '',
     'param' =>
    array (
    ),
     'fonctions' =>
    array (
    ),
     'id_boucle' => NULL,
     'boucles' => NULL,
     'type_requete' => NULL,
     'code' => NULL,
     'interdire_scripts' => true,
     'descr' =>
    array (
    ),
     'ligne' => 1,
  )),
  1 =>
  Texte::__set_state(array(
     'type' => 'texte',
     'texte' => '
'
,
     'avant' => NULL,
     'apres' => '',
     'ligne' => 1,
  )),
)

Une boucle

Prenons un dernier exemple d’une boucle avec une balise, plus compliqué car il induit une référence circulaire dans le tableau généré. Observons :

Squelette :

<BOUCLE_a(ARTICLES){id_article=3}>
#TITRE
</BOUCLE_a>

Cette boucle sélectionne l’article 3 et devrait afficher le titre de l’article. Le tableau de la page si on tente de l’afficher finit par générer une erreur de récursion. L’observation montre que le second élément lu dans la boucle est un Champ (balise) nommé "TITRE". Ce champ contient une référence vers la boucle dans laquelle il est ('boucles'=>array(...)). Cette boucle contenant la balise qui appartient à la boucle contenant la balise qui appartient à ...

Tableau généré partiel

array (
  0 =>
  Boucle::__set_state(array(
     'type' => 'boucle',
     'id_boucle' => '_a',
     'id_parent' => '',
     'avant' =>
    array (
    ),
     'milieu' =>
    array (
      0 =>
      Texte::__set_state(array(
         'type' => 'texte',
         'texte' => '
'
,
         'avant' => NULL,
         'apres' => '',
         'ligne' => 1,
      )),
      1 =>
      Champ::__set_state(array(
         'type' => 'champ',
         'nom_champ' => 'TITRE',
         'nom_boucle' => '',
         'avant' => NULL,
         'apres' => NULL,
         'etoile' => '',
         'param' =>
        array (
        ),
         'fonctions' =>
        array (
        ),
         'id_boucle' => '_a',
         'boucles' =>
        array (
          '_a' =>
          Boucle::__set_state(array(
             'type' => 'boucle',
             'id_boucle' => '_a',
             'id_parent' => '',
             'avant' =>
            array (
            ),
             'milieu' =>
            array (
              0 =>
              Texte::__set_state(array(
                 'type' => 'texte',
                 'texte' => '
'
,
                 'avant' => NULL,
                 'apres' => '',
                 'ligne' => 1,
              )),
              1 =>
              Champ::__set_state(array(
                 'type' => 'champ',
                 'nom_champ' => 'TITRE',
                 'nom_boucle' => '',
                 'avant' => NULL,
                 'apres' => NULL,
                 'etoile' => '',
                 'param' =>
                array (
                ),
                 'fonctions' =>
                array (
                ),
                 'id_boucle' => '_a',
                 'boucles' =>
                array (
                  '_a' =>
                  Boucle::__set_state(array(
...

Pourquoi de telles références ?

Tout simplement parce qu’elles servent ensuite dans le calcul des balises. Lorsqu’une balise est calculée, une partie de ce tableau lui est passée en paramètre (le fameux $p que l’on recroisera). Cette partie concerne simplement les informations de la balise. Pour obtenir des informations de sa boucle englobante, il suffit, grâce à cette référence, d’appeler le paramètre $p->boucles[$p->id_boucle].

Publié le : Mis à jour : 12/05/17

Traductions : English, français