Intéressons-nous à deux des types d’éléments offerts par le language utilisé dans les squelettes de SPIP :
- les boucles (qui déterminent les objets desquels seront extraites les données)
- les balises (qui retournent les données particulières).
La syntaxe extrêmement simple de ces balises, pour la plupart notées #BALISE, masque leur puissance, leur flexibilité et la simplicité avec laquelle il est possible de les utiliser pour étendre SPIP en lui ajoutant de nouvelle fonctionnalités ou en l’interfaçant avec d’autres applications PHP.
Dans cet article, nous allons décrire comment créer nos propres balises statiques SPIP.
Avant de lire cet article, vous devez être familier avec SPIP, ses squelettes et la programmation en PHP.
Une balise SPIP est utilisée pour retourner une valeur.
- La plupart des balises tirent cette valeur du contexte dans lequel elles sont appelées : le titre de l’article « courant », ou le logo de la brève « courante » par exemple.
- Certaines retournent des valeurs globales comme le nom du site, ou la version du logiciel.
- D’autres encore permettent aux utilisateurs d’interagir avec le site (par exemple
#LOGIN_PUBLICqui affiche un formulaire de connexion et en lance le processus). - Quelques-unes enfin (comme
#SETet#GET) offrent les possibilités d’un langage de programmation et l’on pourrait ne voir leur capacité à afficher des valeurs que comme un effet secondaire.
Toutes ces possibilité sont offertes en utilisant une même syntaxe, relativement simple, et un même mécanisme.
Les balises peuvent être rangées dans deux groupes en fonction de leur comportement :
- les balises statiques sont celles qui retournent une valeur statique, qui ne changera pas d’une évaluation à l’autre. Le titre d’un article, par exemple, n’a pas nécessairement besoin d’être différent d’une page à l’autre ; il peut l’être, certes, mais pas nécessairement.
- Les balises dynamiques sont celles qui génèrent des valeurs dynamiques qui, elles, doivent nécessairement changer entre les différents appels ; la date et l’heure, par exemple.
les balises statiques
Les balises statiques génèrent un contenu « statique » ; c’est à dire une valeur qui ne devrait pas changer sur une période donnée.
Cela signifie que SPIP peut évaluer une balise statique une fois, en cacher le résultat et le réutiliser plus tard à l’occasion de demandes ultérieures.
Une balise (désormais dans cet article nous utiliserons « balise » pour « balise statique ») renvoie à une fonction [1] portant un nom particulier : le nom de la balise accolé au préfixe « balise_ ».
Par exemple, une balise nommée #TRUC sera exécutée par une fonction appelée function balise_TRUC().
Ces fonctions, comme un grand nombre de celles utilisées par SPIP, peuvent être surchargées par des plugins, ou d’autres fichiers spécifiques au site. En effet, quand il voit une balise #TRUC, SPIP va d’abord rechercher la fonction balise_TRUC puis, s’il ne la trouve pas, la fonction balise_TRUC_dist puis, enfin, considèrera que la dite balise n’existe pas.
Mais commençons par un exemple trivial : la balise #BONJOUR_VOUS.
Cette balise affichera tout simplement la phrase : « Bonjour tout le monde ! » (Pour utiliser ce code, il suffit de copier la fonction dans votre fichier mes_fonctions.php de votre installation SPIP) :
<?php
function balise_BONJOUR_VOUS ($p) {
$p->code = "'Bonjour tout le monde !'";
return $p;
}
?>
Comme vous pouvez le voir il y a quelques détails en plus du nom ; à savoir : ce $p quelque chose.
Ce paramètre $p de la fonction qui met en œuvre la balise est une référence au nœud de l’arbre de syntaxe abstraite correspondant pour cette balise. Ce paramètre $p contient toutes les informations que SPIP possède sur la balise : les filtres qui lui sont passés, les parenthèses qui l’entourent, le contexte, etc. Tout ce qui manque, c’est la valeur elle-même, et c’est là que notre fonction entre en scène.
Une fois que SPIP a analysé les squelettes et manipulé tout ce qu’il peut, il appelle donc la fonction associée à chaque balise pour remplir les trous.
Il y a un grand nombre de champs dans l’objet Champ (la classe est définie dans ecrire/public/interfaces.php mais sa lecture n’est pas particulièrement édifiante), et la plupart sont peu documentés :
| type | la chaîne de caractères décrivant le type de nœud AST. Devrait être « champ » pour les balises. |
| nom_champ | le nom de la balise sans le « # » |
| nom_boucle | le nom de la boucle. Les balises n’étant pas des boucles, il sera donc vide dans notre exemple. |
| avant | la liste des nœuds précédents qui sont subordonnés à celui-ci. |
| apres | la liste des nœuds suivants subordonnés à celui-ci. |
| etoile | la balise appelée par « #BONJOUR_VOUS* » renverrait un résultat brut, sa valeur n’étant pas sécurisée pour un affichage HTML. |
| param | la liste des paramètres et des filtres associés à l’appel de la balise. C’est un peu compliqué. |
| fonctions | semblable à param mais structuré différemment. |
| id_boucle | le nom de la boucle au sein de laquelle apparait la balise. |
| boucles | le tableau des nœuds AST pour les boucles du squelette. |
| type_requete | aucune idée. [2] |
| code | le code PHP, qui, lors de eval()d, génère la valeur de la balise. |
| interdire_scripts | autorise ou non l’interprétation de "scripts". [3] |
| descr | le tableau des valeurs décrivant le nœud AST, le fichier dont il est issu, etc. |
| ligne | le numéro de la ligne d’où la balise est appelée dans le squelette. |
Exemple :
si l’on remplaçait le contenu de squelettes-dist/sommaire.html par :
[d'abord (#BONJOUR_VOUS{arg1}|strtoupper) ensuite]
cela devrait se traduire par l’AST suivant, transmis donc à la fonction balise_BONJOUR_VOUS :
| type | => | "champ" |
| nom_champ | => | "BONJOUR_VOUS" |
| avant | => | le (ou les) nœud pour "d’abord", ... |
| apres | => | le (ou les) nœud pour "ensuite", ... |
| etoile | => | |
| param | => | [
0 => "arg1" est là, ... 1 => "strtoupper" est là, ... ] |
| fonctions | => | [
0 => arg1" est aussi ici, ... 1 => strtoupper" est aussi ici, ... ] |
Heureusement, vous pouvez ignorer la quasi-totalité de ceci.
La fonction interprete_argument_balise
Cette fonction (détaillée ici) est particulièrement utile :
interprete_argument_balise(1, $p) retourne le premier argument du nœud AST $p.
Avec ce que nous avons décrit jusqu’ici, nous en savons assez pour écrire notre balise #BONJOUR qui affichera le message « Bonjour nom » s’il y a un nom (#BONJOUR{Marcel}) et « Bonjour le monde ! » sinon (code à placer dans mes_fonctions.php ) :
<?php
function balise_BONJOUR ($p) {
$name = interprete_argument_balise (1, $p);
if (!$name) {
$name = "le monde !";
}
$p->code = "'Bonjour $name '";
return $p;
}
?>
Comme il y a bien des raisons d’écrire ses propres balises statiques, il faut être assuré (comme pour tout le reste, d’ailleurs) qu’elles prendront bien en charge les traductions, surtout si vous envisagez de distribuer votre travail.
- Cela est relativement facile à l’aide de la fonction
_T(voir le détail ici) et des fichiers de langue. - Tout comme il est aisé d’obtenir des données à partir d’une boucle (titres d’article, identifiants de rubriques, etc) avec la fonction
champ_sql(voir le détail ici).
Pour encore plus d’exemples, n’hésitez pas à jeter un œil sur le code de certaines des balises de SPIP dans le fichier ecrire/public/balises.php.
Et si vous regardez attentivement le code source de SPIP, vous verrez que beaucoup de balises ne tirent pas leur résultat du mécanisme détaillé ci-dessus, mais l’extraient des colonnes de même nom de la base de données.
Si vous modifiez ou complétez votre base de données vous pourrez ainsi en tirer parti.
