995773076f4acc3bd9132defb51481f13b84fce3
[lhc/web/www.git] / www / plugins / saisies / balise / saisie.php
1 <?php
2
3 /**
4 * Déclaration de la classe `Pile` et de la balise `#SAISIE`
5 *
6 * @package SPIP\Saisies\Balises
7 **/
8
9 if (!defined('_ECRIRE_INC_VERSION')) {
10 return;
11 }
12
13 // pour ne pas interferer avec d'eventuelles futures fonctions du core
14 // on met le tout dans une classe ; les fonctions sont autonomes.
15
16 /**
17 * Conteneur pour modifier les arguments d'une balise SPIP (de classe Champ) à compiler
18 *
19 * @note
20 * Ces fonctions visent à modifier l'AST (Arbre de Syntaxe Abstraite) issues
21 * de l'analyse du squelette. Très utile pour créer des balises qui
22 * transmettent des arguments supplémentaires automatiquement, à des balises
23 * déjà existantes.
24 * Voir un exemple d'utilisation dans `balise_SAISIE_dist()`.
25 *
26 * @note
27 * Les arguments sont stockés sont dans l'entree 0 de la propriété `param`
28 * dans l'objet Champ (représenté par `$p`), donc dans `$p->param[0]`.
29 *
30 * `param[0][0]` vaut toujours '' (ou presque ?)
31 *
32 * @see balise_SAISIE_dist() Pour un exemple d'utilisation
33 **/
34 class Pile {
35 /**
36 * Récupère un argument de balise
37 *
38 * @param int $pos
39 * @param Champ $p
40 * @return mixed|null Élément de l'AST représentant l'argument s'il existe
41 **/
42 static function recuperer_argument_balise($pos, $p) {
43 if (!isset($p->param[0])) {
44 return null;
45 }
46 if (!isset($p->param[0][$pos])) {
47 return null;
48 }
49 return $p->param[0][$pos];
50 }
51
52 /**
53 * Supprime un argument de balise
54 *
55 * @param int $pos
56 * @param Champ $p
57 * @return Champ
58 **/
59 static function supprimer_argument_balise($pos, $p) {
60 if (!isset($p->param[0])) {
61 return null;
62 }
63 if (!isset($p->param[0][$pos])) {
64 return null;
65 }
66 if ($pos == 0) {
67 array_shift($p->param[0]);
68 } else {
69 $debut = array_slice($p->param[0], 0, $pos);
70 $fin = array_slice($p->param[0], $pos+1);
71 $p->param[0] = array_merge($debut, $fin);
72 }
73 return $p;
74 }
75
76
77 /**
78 * Retourne un argument de balise, et le supprime de la liste des arguments
79 *
80 * @uses Pile::recuperer_argument_balise()
81 * @uses Pile::supprimer_argument_balise()
82 *
83 * @param int $pos
84 * @param Champ $p
85 * @return mixed|null Élément de l'AST représentant l'argument s'il existe
86 **/
87 static function recuperer_et_supprimer_argument_balise($pos, &$p) {
88 $arg = Pile::recuperer_argument_balise($pos, $p);
89 $p = Pile::supprimer_argument_balise($pos, $p);
90 return $arg;
91 }
92
93
94 /**
95 * Ajoute un argument de balise
96 *
97 * Empile l'argument à la suite des arguments déjà existants pour la balise
98 *
99 * @param mixed $element Élément de l'AST représentant l'argument à ajouter
100 * @param Champ $p
101 * @return Champ
102 **/
103 static function ajouter_argument_balise($element, $p) {
104
105 // Toujours un parametre 0 vide s'il n'existe pas.
106 if (!isset($p->param[0][0])) {
107 if (!isset($p->param[0])) {
108 $p->param[0] = array();
109 }
110 $p->param[0][0] = '';
111 }
112
113 $zero = array_shift($p->param[0]);
114 array_unshift($p->param[0], $element);
115 array_unshift($p->param[0], $zero);
116
117 return $p;
118 }
119
120
121 /**
122 * Crée l'élément de l'AST représentant un argument de balise.
123 *
124 * @example
125 * ```
126 * $nom = Pile::creer_argument_balise(nom); // {nom}
127 * $nom = Pile::creer_argument_balise(nom, 'coucou'); // {nom=coucou}
128 *
129 * $balise = Pile::creer_balise('BALISE');
130 * $nom = Pile::creer_argument_balise(nom, $balise); // {nom=#BALISE}
131 * ```
132 *
133 * @param string $nom
134 * Nom de l'argument
135 * @param string|object $valeur
136 * Valeur de l'argument. Peut être une chaîne de caractère ou un autre élément d'AST
137 * @return array
138 **/
139 static function creer_argument_balise($nom, $valeur = null) {
140 include_spip('public/interfaces');
141 $s = new Texte;
142 $s->texte = $nom;
143 $s->ligne=0;
144
145 // si #BALISE cree avec Pile::creer_balise(), le mettre en array, comme les autres
146 if (is_object($valeur)) {
147 $valeur = array($valeur);
148 }
149
150 $res = null;
151
152 // {nom}
153 if (is_null($valeur)) {
154 $res = array($s);
155 } elseif (is_string($valeur)) {
156 // {nom=coucou}
157 $s->texte .= "=$valeur";
158 $res = array($s);
159 } elseif (is_array($valeur)) {
160 // {nom=#BALISE}
161 $s->texte .= '='; // /!\ sans cette toute petite chose, ça ne fait pas d'egalite :)
162 $res = array_merge(array($s), $valeur);
163 }
164
165 return $res;
166 }
167
168
169 /**
170 * Crée et ajoute un argument à une balise
171 *
172 * @uses Pile::creer_argument_balise()
173 * @uses Pile::ajouter_argument_balise()
174 *
175 * @param Champ $p
176 * @param string $nom
177 * Nom de l'argument
178 * @param string|object $valeur
179 * Valeur de l'argument. Peut être une chaîne de caractère ou un autre élément d'AST
180 * @return Champ
181 **/
182 static function creer_et_ajouter_argument_balise($p, $nom, $valeur = null) {
183 $new = Pile::creer_argument_balise($nom, $valeur);
184 return Pile::ajouter_argument_balise($new, $p);
185 }
186
187
188
189 /**
190 * Crée l'AST d'une balise
191 *
192 * @example
193 * ```
194 * // Crée : #ENV*{titre}
195 * $titre = Pile::recuperer_argument_balise(1, $p); // $titre, 1er argument de la balise actuelle
196 * $env = Pile::creer_balise('ENV', array('param' => array($titre), 'etoile' => '*'));
197 * ```
198 *
199 * @param string $nom
200 * Nom de la balise
201 * @param array $opt
202 * Options (remplira les propriétés correspondantes de l'objet Champ)
203 * @return Champ
204 **/
205 static function creer_balise($nom, $opt = array()) {
206 include_spip('public/interfaces');
207 $b = new Champ;
208 $b->nom_champ = strtoupper($nom);
209 foreach ($opt as $o => $val) {
210 if (property_exists($b, $o)) {
211 if ($o == 'param') {
212 array_unshift($val, '');
213 $b->$o = array($val);
214 } else {
215 $b->$o = $val;
216 }
217 }
218 }
219 return $b;
220 }
221 }
222
223
224
225 /**
226 * Compile la balise `#SAISIE` qui retourne le code HTML de la saisie de formulaire indiquée.
227 *
228 * Cette balise incluera le squelette `saisies/_base.html` et lui-même `saisies/{type}.html`
229 *
230 * La balise `#SAISIE` est un raccourci pour une écriture plus compliquée de la balise `#INCLURE`.
231 * La balise calcule une série de paramètre récupérer et à transmettre à `#INCLURE`,
232 * en fonction des valeurs des 2 premiers paramètres transmis.
233 *
234 * Les autres arguments sont transmis tels quels à la balise `#INCLURE`.
235 *
236 * Ainsi `#SAISIE{input,nom,label=Nom,...}` exécutera l'équivalent de
237 * `#INCLURE{nom=nom,valeur=#ENV{nom},type_saisie=input,erreurs,fond=saisies/_base,label=Nom,...}`
238 *
239 * @syntaxe `#SAISIE{type,nom[,option=xx,...]}`
240 *
241 * @uses Pile::recuperer_et_supprimer_argument_balise()
242 * @uses Pile::creer_balise()
243 * @uses Pile::creer_et_ajouter_argument_balise()
244 * @see balise_INCLURE_dist()
245 *
246 * @param Champ $p
247 * @return Champ
248 */
249 function balise_SAISIE_dist($p) {
250
251 // on recupere les parametres sans les traduire en code d'execution php
252 $type_saisie = Pile::recuperer_et_supprimer_argument_balise(1, $p); // $type
253 $titre = Pile::recuperer_et_supprimer_argument_balise(1, $p); // $titre
254
255 // creer #ENV*{$titre} (* pour les cas de tableau serialises par exemple, que l'on veut reutiliser)
256 $env_titre = Pile::creer_balise('ENV', array('param' => array($titre), 'etoile' => '*')); // #ENV*{titre}
257
258 // on modifie $p pour ajouter des arguments
259 // {nom=$titre, valeur=#ENV{$titre}, erreurs, type_saisie=$type, fond=saisies/_base}
260 $p = Pile::creer_et_ajouter_argument_balise($p, 'nom', $titre);
261 $p = Pile::creer_et_ajouter_argument_balise($p, 'valeur', $env_titre);
262 $p = Pile::creer_et_ajouter_argument_balise($p, 'type_saisie', $type_saisie);
263 $p = Pile::creer_et_ajouter_argument_balise($p, 'erreurs');
264 $p = Pile::creer_et_ajouter_argument_balise($p, 'fond', 'saisies/_base');
265
266 // on appelle la balise #INCLURE
267 // avec les arguments ajoutes
268 if (function_exists('balise_INCLURE')) {
269 return balise_INCLURE($p);
270 } else {
271 return balise_INCLURE_dist($p);
272 }
273 }