[SPIP] ~2.1.12 -->2.1.25
[velocampus/web/www.git] / www / ecrire / public / balises.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2014 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
12
13 // Ce fichier regroupe la quasi totalite des definitions de #BALISES de spip
14 // Pour chaque balise, il est possible de surcharger, dans mes_fonctions,
15 // la fonction balise_TOTO_dist par une fonction balise_TOTO() respectant la
16 // meme API :
17 // elle recoit en entree un objet de classe CHAMP, le modifie et le retourne.
18 // Cette classe est definie dans public/interfaces
19
20 if (!defined('_ECRIRE_INC_VERSION')) return;
21
22 // http://doc.spip.org/@interprete_argument_balise
23 function interprete_argument_balise($n,$p) {
24 if (($p->param) && (!$p->param[0][0]) && (count($p->param[0])>$n))
25 return calculer_liste($p->param[0][$n],
26 $p->descr,
27 $p->boucles,
28 $p->id_boucle);
29 else
30 return NULL;
31 }
32 //
33 // Definition des balises
34 //
35 // http://doc.spip.org/@balise_NOM_SITE_SPIP_dist
36 function balise_NOM_SITE_SPIP_dist($p) {
37 $p->code = "\$GLOBALS['meta']['nom_site']";
38 #$p->interdire_scripts = true;
39 return $p;
40 }
41
42 // http://doc.spip.org/@balise_EMAIL_WEBMASTER_dist
43 function balise_EMAIL_WEBMASTER_dist($p) {
44 $p->code = "\$GLOBALS['meta']['email_webmaster']";
45 #$p->interdire_scripts = true;
46 return $p;
47 }
48
49 // http://doc.spip.org/@balise_DESCRIPTIF_SITE_SPIP_dist
50 function balise_DESCRIPTIF_SITE_SPIP_dist($p) {
51 $p->code = "\$GLOBALS['meta']['descriptif_site']";
52 #$p->interdire_scripts = true;
53 return $p;
54 }
55
56 // http://doc.spip.org/@balise_CHARSET_dist
57 function balise_CHARSET_dist($p) {
58 $p->code = "\$GLOBALS['meta']['charset']";
59 #$p->interdire_scripts = true;
60 return $p;
61 }
62
63 // http://doc.spip.org/@balise_LANG_LEFT_dist
64 function balise_LANG_LEFT_dist($p) {
65 $_lang = champ_sql('lang', $p);
66 $p->code = "lang_dir($_lang, 'left','right')";
67 $p->interdire_scripts = false;
68 return $p;
69 }
70
71 // http://doc.spip.org/@balise_LANG_RIGHT_dist
72 function balise_LANG_RIGHT_dist($p) {
73 $_lang = champ_sql('lang', $p);
74 $p->code = "lang_dir($_lang, 'right','left')";
75 $p->interdire_scripts = false;
76 return $p;
77 }
78
79 // http://doc.spip.org/@balise_LANG_DIR_dist
80 function balise_LANG_DIR_dist($p) {
81 $_lang = champ_sql('lang', $p);
82 $p->code = "lang_dir($_lang, 'ltr','rtl')";
83 $p->interdire_scripts = false;
84 return $p;
85 }
86
87 // http://doc.spip.org/@balise_PUCE_dist
88 function balise_PUCE_dist($p) {
89 $p->code = "definir_puce()";
90 $p->interdire_scripts = false;
91 return $p;
92 }
93
94 // #DATE
95 // Cette fonction sait aller chercher dans le contexte general
96 // quand #DATE est en dehors des boucles
97 // http://www.spip.net/fr_article1971.html
98 // http://doc.spip.org/@balise_DATE_dist
99 function balise_DATE_dist ($p) {
100 $d = champ_sql('date', $p);
101 # if ($d === "@\$Pile[0]['date']")
102 # $d = "isset(\$Pile[0]['date']) ? $d : time()";
103 $p->code = $d;
104 return $p;
105 }
106
107 // #DATE_REDAC
108 // http://www.spip.net/fr_article1971.html
109 // http://doc.spip.org/@balise_DATE_REDAC_dist
110 function balise_DATE_REDAC_dist ($p) {
111 $d = champ_sql('date_redac', $p);
112 # if ($d === "@\$Pile[0]['date_redac']")
113 # $d = "isset(\$Pile[0]['date_redac']) ? $d : time()";
114 $p->code = $d;
115 $p->interdire_scripts = false;
116 return $p;
117 }
118
119 // #DATE_MODIF
120 // http://www.spip.net/fr_article1971.html
121 // http://doc.spip.org/@balise_DATE_MODIF_dist
122 function balise_DATE_MODIF_dist ($p) {
123 $p->code = champ_sql('date_modif', $p);
124 $p->interdire_scripts = false;
125 return $p;
126 }
127
128 // #DATE_NOUVEAUTES
129 // http://www.spip.net/fr_article1971.html
130 // http://doc.spip.org/@balise_DATE_NOUVEAUTES_dist
131 function balise_DATE_NOUVEAUTES_dist($p) {
132 $p->code = "((\$GLOBALS['meta']['quoi_de_neuf'] == 'oui'
133 AND @is_readable(_DIR_TMP . 'mail.lock')) ?
134 @filemtime(_DIR_TMP . 'mail.lock') :
135 \"'0000-00-00'\")";
136 $p->interdire_scripts = false;
137 return $p;
138 }
139
140 // http://doc.spip.org/@balise_DOSSIER_SQUELETTE_dist
141 function balise_DOSSIER_SQUELETTE_dist($p) {
142 $code = substr(addslashes(dirname($p->descr['sourcefile'])), strlen(_DIR_RACINE));
143 $p->code = "_DIR_RACINE . '$code'" .
144 $p->interdire_scripts = false;
145 return $p;
146 }
147
148 // http://doc.spip.org/@balise_SQUELETTE_dist
149 function balise_SQUELETTE_dist($p) {
150 $code = addslashes($p->descr['sourcefile']);
151 $p->code = "'$code'" .
152 $p->interdire_scripts = false;
153 return $p;
154 }
155
156 // http://doc.spip.org/@balise_SPIP_VERSION_dist
157 function balise_SPIP_VERSION_dist($p) {
158 $p->code = "spip_version()";
159 $p->interdire_scripts = false;
160 return $p;
161 }
162
163
164 // #NOM_SITE affiche le nom du site, ou sinon l'URL ou le titre de l'objet
165 // http://doc.spip.org/@balise_NOM_SITE_dist
166 function balise_NOM_SITE_dist($p) {
167 if (!$p->etoile) {
168 $p->code = "supprimer_numero(calculer_url(" .
169 champ_sql('url_site',$p) ."," .
170 champ_sql('nom_site',$p) .
171 ", 'titre', \$connect))";
172 } else
173 $p->code = champ_sql('nom_site',$p);
174
175 $p->interdire_scripts = true;
176 return $p;
177 }
178
179 // http://doc.spip.org/@balise_NOTES_dist
180 function balise_NOTES_dist($p) {
181 // Recuperer les notes
182 $p->code = 'calculer_notes()';
183 #$p->interdire_scripts = true;
184 return $p;
185 }
186
187 // http://doc.spip.org/@balise_RECHERCHE_dist
188 function balise_RECHERCHE_dist($p) {
189 $p->code = 'entites_html(_request("recherche"))';
190 $p->interdire_scripts = false;
191 return $p;
192 }
193
194 // http://doc.spip.org/@balise_COMPTEUR_BOUCLE_dist
195 function balise_COMPTEUR_BOUCLE_dist($p) {
196 $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
197 if ($b === '') {
198 $msg = array('zbug_champ_hors_boucle',
199 array('champ' => '#COMPTEUR_BOUCLE')
200 );
201 erreur_squelette($msg, $p);
202 } else {
203 $p->code = "\$Numrows['$b']['compteur_boucle']";
204 $p->boucles[$b]->cptrows = true;
205 $p->interdire_scripts = false;
206 return $p;
207 }
208 }
209
210 // http://doc.spip.org/@balise_TOTAL_BOUCLE_dist
211 function balise_TOTAL_BOUCLE_dist($p) {
212 $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
213 if ($b === '' || !isset($p->boucles[$b])) {
214 $msg = array('zbug_champ_hors_boucle',
215 array('champ' => "#$b" . 'TOTAL_BOUCLE')
216 );
217 erreur_squelette($msg, $p);
218 } else {
219 $p->code = "\$Numrows['$b']['total']";
220 $p->boucles[$b]->numrows = true;
221 $p->interdire_scripts = false;
222 }
223 return $p;
224 }
225
226 // Si on est hors d'une boucle {recherche}, ne pas "prendre" cette balise
227 // http://doc.spip.org/@balise_POINTS_dist
228 function balise_POINTS_dist($p) {
229 return rindex_pile($p, 'points', 'recherche');
230 }
231
232 // http://doc.spip.org/@balise_POPULARITE_ABSOLUE_dist
233 function balise_POPULARITE_ABSOLUE_dist($p) {
234 $p->code = 'ceil(' .
235 champ_sql('popularite', $p) .
236 ')';
237 $p->interdire_scripts = false;
238 return $p;
239 }
240
241 // http://doc.spip.org/@balise_POPULARITE_SITE_dist
242 function balise_POPULARITE_SITE_dist($p) {
243 $p->code = 'ceil($GLOBALS["meta"][\'popularite_total\'])';
244 $p->interdire_scripts = false;
245 return $p;
246 }
247
248 // http://doc.spip.org/@balise_POPULARITE_MAX_dist
249 function balise_POPULARITE_MAX_dist($p) {
250 $p->code = 'ceil($GLOBALS["meta"][\'popularite_max\'])';
251 $p->interdire_scripts = false;
252 return $p;
253 }
254
255 // http://doc.spip.org/@balise_EXPOSE_dist
256 function balise_EXPOSE_dist($p) {
257 $on = "'on'";
258 $off= "''";
259 if (($v = interprete_argument_balise(1,$p))!==NULL){
260 $on = $v;
261 if (($v = interprete_argument_balise(2,$p))!==NULL)
262 $off = $v;
263
264 }
265 return calculer_balise_expose($p, $on, $off);
266 }
267
268 // http://doc.spip.org/@calculer_balise_expose
269 function calculer_balise_expose($p, $on, $off)
270 {
271 $b = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle;
272 $key = $p->boucles[$b]->primary;
273 $type = $p->boucles[$p->id_boucle]->primary;
274 $desc = $p->boucles[$b]->show;
275 $connect = sql_quote($p->boucles[$b]->sql_serveur);
276
277 if (!$key) {
278 $msg = array('zbug_champ_hors_boucle', array('champ' => '#EXPOSER'));
279 erreur_squelette($msg, $p);
280 }
281
282 // Ne pas utiliser champ_sql, on jongle avec le nom boucle explicite
283 $c = index_pile($p->id_boucle, $type, $p->boucles);
284
285 if (isset($desc['field']['id_parent'])) {
286 $parent = 0; // pour if (!$parent) dans calculer_expose
287 } elseif (isset($desc['field']['id_rubrique'])) {
288 $parent = index_pile($p->id_boucle, 'id_rubrique', $p->boucles, $b);
289 } elseif (isset($desc['field']['id_groupe'])) {
290 $parent = index_pile($p->id_boucle, 'id_groupe', $p->boucles, $b);
291 } else $parent = "''";
292
293 $p->code = "(calcul_exposer($c, '$type', \$Pile[0], $parent, '$key', $connect) ? $on : $off)";
294
295 $p->interdire_scripts = false;
296 return $p;
297 }
298
299
300 // Debut et fin de surlignage auto des mots de la recherche
301 // on insere une balise Span avec une classe sans spec:
302 // c'est transparent s'il n'y a pas de recherche,
303 // sinon elles seront remplacees par les fontions de inc_surligne
304
305 // http://doc.spip.org/@balise_DEBUT_SURLIGNE_dist
306 function balise_DEBUT_SURLIGNE_dist($p) {
307 include_spip('inc/surligne');
308 $p->code = "'<!-- " . MARQUEUR_SURLIGNE . " -->'";
309 return $p;
310 }
311 // http://doc.spip.org/@balise_FIN_SURLIGNE_dist
312 function balise_FIN_SURLIGNE_dist($p) {
313 include_spip('inc/surligne');
314 $p->code = "'<!-- " . MARQUEUR_FSURLIGNE . "-->'";
315 return $p;
316 }
317
318
319 // #SPIP_CRON
320 // a documenter
321 // insere un <div> avec un lien background-image vers les taches de fond.
322 // Si cette balise est presente sur la page de sommaire, le site ne devrait
323 // quasiment jamais se trouver ralenti par des taches de fond un peu lentes
324 // http://doc.spip.org/@balise_SPIP_CRON_dist
325 function balise_SPIP_CRON_dist ($p) {
326 $p->code = '"<!-- SPIP-CRON --><div style=\"background-image: url(\'' .
327 generer_url_action('cron') .
328 '\');\"></div>"';
329 $p->interdire_scripts = false;
330 return $p;
331 }
332
333 // #INTRODUCTION
334 // #INTRODUCTION{longueur}
335 // http://www.spip.net/@introduction
336 // http://doc.spip.org/@balise_INTRODUCTION_dist
337 function balise_INTRODUCTION_dist($p) {
338
339 $type = $p->type_requete;
340
341 $_texte = champ_sql('texte', $p);
342 $_descriptif = ($type == 'articles' OR $type == 'rubriques') ? champ_sql('descriptif', $p) : "''";
343
344 if ($type == 'articles') {
345 $_chapo = champ_sql('chapo', $p);
346 $_texte = "(strlen($_descriptif) OR chapo_redirigetil($_chapo))
347 ? ''
348 : $_chapo . \"\\n\\n\" . $_texte";
349 }
350
351 // longueur en parametre, ou valeur par defaut
352 if (($v = interprete_argument_balise(1,$p))!==NULL) {
353 $longueur = 'intval('.$v.')';
354 } else {
355 switch ($type) {
356 case 'articles':
357 $longueur = '500';
358 break;
359 case 'breves':
360 $longueur = '300';
361 break;
362 case 'rubriques':
363 default:
364 $longueur = '600';
365 break;
366 }
367 }
368
369 $f = chercher_filtre('introduction');
370 $p->code = "$f($_descriptif, $_texte, $longueur, \$connect)";
371
372 #$p->interdire_scripts = true;
373 $p->etoile = '*'; // propre est deja fait dans le calcul de l'intro
374 return $p;
375 }
376
377
378 // #LANG
379 // affiche la langue de l'objet (ou superieure), et a defaut la langue courante
380 // (celle du site ou celle qui a ete passee dans l'URL par le visiteur)
381 // #LANG* n'affiche rien si aucune langue n'est trouvee dans le sql/le contexte
382 // http://doc.spip.org/@balise_LANG_dist
383 function balise_LANG_dist ($p) {
384 $_lang = champ_sql('lang', $p);
385 if (!$p->etoile)
386 $p->code = "htmlentities($_lang ? $_lang : \$GLOBALS['spip_lang'])";
387 else
388 $p->code = "htmlentities($_lang)";
389 $p->interdire_scripts = false;
390 return $p;
391 }
392
393 // http://doc.spip.org/@balise_CHAPO_dist
394 function balise_CHAPO_dist ($p) {
395 $_chapo = champ_sql('chapo', $p);
396 if (($p->etoile) OR (strpos($_chapo, '$Pile[$SP') === false))
397 $p->code = $_chapo;
398 else
399 $p->code = "nettoyer_chapo($_chapo)";
400 $p->interdire_scripts = true;
401 return $p;
402 }
403 // #LESAUTEURS
404 // les auteurs d'un article (ou d'un article syndique)
405 // http://www.spip.net/fr_article902.html
406 // http://www.spip.net/fr_article911.html
407 // http://doc.spip.org/@balise_LESAUTEURS_dist
408 function balise_LESAUTEURS_dist ($p) {
409 // Cherche le champ 'lesauteurs' dans la pile
410 $_lesauteurs = champ_sql('lesauteurs', $p);
411
412 // Si le champ n'existe pas (cas de spip_articles), on applique
413 // le modele lesauteurs.html en passant id_article dans le contexte;
414 // dans le cas contraire on prend le champ 'lesauteurs' (cas de
415 // spip_syndic_articles)
416 if ($_lesauteurs
417 AND $_lesauteurs != '@$Pile[0][\'lesauteurs\']') {
418 $p->code = "safehtml($_lesauteurs)";
419 // $p->interdire_scripts = true;
420 } else {
421 $connect = !$p->id_boucle ? ''
422 : $p->boucles[$p->id_boucle]->sql_serveur;
423
424 $c = memoriser_contexte_compil($p);
425
426 $p->code = sprintf(CODE_RECUPERER_FOND, "'modeles/lesauteurs'",
427 "array('id_article' => ".champ_sql('id_article', $p) .")",
428 "'trim'=>true, 'compil'=>array($c)",
429 _q($connect));
430 $p->interdire_scripts = false; // securite apposee par recuperer_fond()
431 }
432
433 return $p;
434 }
435
436
437 // #RANG
438 // affiche le "numero de l'article" quand on l'a titre '1. Premier article';
439 // ceci est transitoire afin de preparer une migration vers un vrai systeme de
440 // tri des articles dans une rubrique (et plus si affinites)
441 // http://doc.spip.org/@balise_RANG_dist
442 function balise_RANG_dist ($p) {
443 $_titre = champ_sql('titre', $p);
444 $_rang = champ_sql('rang', $p);
445 $p->code = "(($_rang)?($_rang):recuperer_numero($_titre))";
446 $p->interdire_scripts = false;
447 return $p;
448 }
449
450
451 // #PETITION
452 // retourne '' si l'article courant n'a pas de petition
453 // le texte de celle-ci sinon (et ' ' si il est vide)
454 // cf FORMULAIRE_PETITION
455
456 // http://doc.spip.org/@balise_PETITION_dist
457 function balise_PETITION_dist ($p) {
458 $nom = $p->id_boucle;
459 $p->code = "quete_petitions(" .
460 champ_sql('id_article', $p) .
461 ",'" .
462 $p->boucles[$nom]->type_requete .
463 "','" .
464 $nom .
465 "','" .
466 $p->boucles[$nom]->sql_serveur .
467 "', \$Cache)";
468 $p->interdire_scripts = false;
469 return $p;
470 }
471
472
473 // #POPULARITE
474 // http://www.spip.net/fr_article1846.html
475 // http://doc.spip.org/@balise_POPULARITE_dist
476 function balise_POPULARITE_dist ($p) {
477 $_popularite = champ_sql('popularite', $p);
478 $p->code = "(ceil(min(100, 100 * $_popularite
479 / max(1 , 0 + \$GLOBALS['meta']['popularite_max']))))";
480 $p->interdire_scripts = false;
481 return $p;
482 }
483
484 // #PAGINATION
485 // Le code produit est trompeur, car les modeles ne fournissent pas Pile[0].
486 // On produit un appel a _request si on ne l'a pas, mais c'est inexact:
487 // l'absence peut etre due a une faute de frappe dans le contexte inclus.
488
489 define('CODE_PAGINATION',
490 '%s($Numrows["%s"]["grand_total"],
491 %s,
492 isset($Pile[0][%4$s])?$Pile[0][%4$s]:intval(_request(%4$s)),
493 %5$s, %6$s, %7$s, %8$s, array(%9$s))');
494
495 // http://www.spip.net/fr_article3367.html
496 // http://doc.spip.org/@balise_PAGINATION_dist
497 function balise_PAGINATION_dist($p, $liste='true') {
498 $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
499
500 // s'il n'y a pas de nom de boucle, on ne peut pas paginer
501 if ($b === '') {
502 $msg = array('zbug_champ_hors_boucle',
503 array('champ' => $liste ? 'PAGINATION' : 'ANCRE_PAGINATION')
504 );
505 erreur_squelette($msg, $p);
506 return $p;
507 }
508
509 // s'il n'y a pas de mode_partie, c'est qu'on se trouve
510 // dans un boucle recursive ou qu'on a oublie le critere {pagination}
511 if (!$p->boucles[$b]->mode_partie) {
512 if (!$p->boucles[$b]->table_optionnelle) {
513 $msg = array('zbug_pagination_sans_critere',
514 array('champ' => '#PAGINATION')
515 );
516 erreur_squelette($msg, $p);
517 }
518 return $p;
519 }
520
521 $__modele = interprete_argument_balise(1,$p);
522 if ($p->param) {
523 $params = $p->param;
524 array_shift($params);
525 // a priori true
526 // si false, le compilo va bloquer sur des syntaxes avec un filtre sans argument qui suit la balise
527 // si true, les arguments simples (sans truc=chose) vont degager
528 $code_contexte = argumenter_inclure($params, true, $p, $p->boucles, $p->id_boucle, false);
529 $code_contexte = implode(',',$code_contexte);
530 } else $code_contexte = '';
531
532 $connect = $p->boucles[$b]->sql_serveur;
533 $pas = $p->boucles[$b]->total_parties;
534 $f_pagination = chercher_filtre('pagination');
535 $type = $p->boucles[$b]->modificateur['debut_nom'];
536 $modif = ($type[0]!=="'") ? "'debut'.$type"
537 : ("'debut" .substr($type,1));
538
539 $p->code = sprintf(CODE_PAGINATION, $f_pagination,$b, $type, $modif, $pas, $liste, ($__modele ? $__modele : "''"), _q($connect), $code_contexte);
540
541 $p->boucles[$b]->numrows = true;
542 $p->interdire_scripts = false;
543 return $p;
544 }
545
546
547 // N'afficher que l'ancre de la pagination (au-dessus, par exemple, alors
548 // qu'on mettra les liens en-dessous de la liste paginee)
549 // http://doc.spip.org/@balise_ANCRE_PAGINATION_dist
550 function balise_ANCRE_PAGINATION_dist($p) {
551 if ($f = charger_fonction('PAGINATION', 'balise', true))
552 return $f($p, $liste='false');
553 else return NULL; // ou une erreur ?
554 }
555
556 // equivalent a #TOTAL_BOUCLE sauf pour les boucles paginees, ou elle
557 // indique le nombre total d'articles repondant aux criteres hors pagination
558 // http://doc.spip.org/@balise_GRAND_TOTAL_dist
559 function balise_GRAND_TOTAL_dist($p) {
560 $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
561 if ($b === '' || !isset($p->boucles[$b])) {
562 $msg = array('zbug_champ_hors_boucle',
563 array('champ' => "#$b" . 'TOTAL_BOUCLE')
564 );
565 erreur_squelette($msg, $p);
566 } else {
567 $p->code = "(isset(\$Numrows['$b']['grand_total'])
568 ? \$Numrows['$b']['grand_total'] : \$Numrows['$b']['total'])";
569 $p->boucles[$b]->numrows = true;
570 $p->interdire_scripts = false;
571 }
572 return $p;
573 }
574
575
576 //
577 // Parametres de reponse a un forum
578 //
579
580 // http://doc.spip.org/@balise_PARAMETRES_FORUM_dist
581 function balise_PARAMETRES_FORUM_dist($p) {
582 $_id_article = champ_sql('id_article', $p);
583 $p->code = '
584 // refus des forums ?
585 (quete_accepter_forum('.$_id_article.')=="non" OR
586 ($GLOBALS["meta"]["forums_publics"] == "non"
587 AND quete_accepter_forum('.$_id_article.') == ""))
588 ? "" : // sinon:
589 ';
590 // pas de calculs superflus si le site est monolingue
591 $lang = strpos($GLOBALS['meta']['langues_utilisees'], ',');
592 $idb = $p->id_boucle;
593 switch (!isset($p->boucles[$idb])? '' : $p->boucles[$idb]->type_requete) {
594 case 'articles':
595 $c = '"id_article=".' . champ_sql('id_article', $p);
596 if ($lang) $lang = champ_sql('lang', $p);
597 break;
598 case 'breves':
599 $c = '"id_breve=".' . champ_sql('id_breve', $p);
600 if ($lang) $lang = champ_sql('lang', $p);
601 break;
602 case 'rubriques':
603 $c = '"id_rubrique=".' . champ_sql('id_rubrique', $p);
604 if ($lang) $lang = champ_sql('lang', $p);
605 break;
606 case 'syndication':
607 case 'syndic':
608 // passer par la rubrique pour avoir un champ Lang
609 // la table syndic n'en ayant pas
610 $c = '"id_syndic=".' . champ_sql('id_syndic', $p);
611 if ($lang) $lang = 'sql_getfetsel("lang", "spip_rubriques", ("id_rubrique=" . intval("' . champ_sql('id_rubrique', $p) . '")))';
612 break;
613 case 'forums':
614 default:
615 // ATTENTION mettre 'id_rubrique' avant 'id_syndic':
616 // a l'execution lang_parametres_forum
617 // y cherchera l'identifiant donnant la langue
618 // et pour id_syndic c'est id_rubrique car sa table n'en a pas
619
620 $liste_table = array ("article","breve","rubrique","syndic","forum");
621 $c = '';
622 $tables = array();
623 foreach ($liste_table as $t) {
624 $champ = 'id_' . $t;
625 $x = champ_sql($champ, $p);
626 $c .= (($c) ? ".\n" : "") . "((!$x) ? '' : ('&$champ='.$x))";
627 if ($lang AND $t!='forum') $tables[]=
628 "'$champ' => '" . table_objet_sql($t) . "'";
629 }
630 $c = "substr($c,1)";
631
632 if ($lang)
633 $lang = "array(" . join(",",$tables) .")";
634 break;
635 }
636
637 if ($lang) $c = "lang_parametres_forum($c,$lang)";
638
639 // Syntaxe [(#PARAMETRES_FORUM{#SELF})] pour fixer le retour du forum
640 # note : ce bloc qui sert a recuperer des arguments calcules pourrait
641 # porter un nom et faire partie de l'API.
642 $retour = interprete_argument_balise(1,$p);
643 if ($retour===NULL)
644 $retour = "''";
645
646 // Attention un eventuel &retour=xxx dans l'URL est prioritaire
647 $c .= '.
648 (($lien = (_request("retour") ? _request("retour") : str_replace("&amp;", "&", '.$retour.'))) ? "&retour=".rawurlencode($lien) : "")';
649
650 // Ajouter le code d'invalideur specifique a cette balise
651 include_spip('inc/invalideur');
652 if (function_exists($i = 'code_invalideur_forums'))
653 $p->code .= $i($p, '('.$c.')');
654
655 $p->interdire_scripts = false;
656 return $p;
657 }
658
659 // Reference a l'URL de la page courante
660 // Attention dans un INCLURE() ou une balise dynamique on n'a pas le droit de
661 // mettre en cache #SELF car il peut correspondre a une autre page (attaque XSS)
662 // (Dans ce cas faire <INCLURE{self=#SELF}> pour differencier les caches.)
663 // http://www.spip.net/@self
664 // http://doc.spip.org/@balise_SELF_dist
665 function balise_SELF_dist($p) {
666 $p->code = 'self()';
667 $p->interdire_scripts = false;
668 return $p;
669 }
670
671 //
672 // #CHEMIN{fichier} -> find_in_path(fichier)
673 //
674 // http://doc.spip.org/@balise_CHEMIN_dist
675 function balise_CHEMIN_dist($p) {
676 $arg = interprete_argument_balise(1,$p);
677 if (!$arg) {
678 $msg = array('zbug_balise_sans_argument', array('balise' => ' CHEMIN'));
679 erreur_squelette($msg, $p);
680 } else
681 $p->code = 'find_in_path(' . $arg .')';
682
683 #$p->interdire_scripts = true;
684 return $p;
685 }
686
687 function balise_CHEMIN_IMAGE_dist($p) {
688 $arg = interprete_argument_balise(1,$p);
689 if (!$arg) {
690 $msg = array('zbug_balise_sans_argument', array('balise' => ' CHEMIN_IMAGE'));
691 erreur_squelette($msg, $p);
692 } else $p->code = 'chemin_image(' . $arg .')';
693
694 #$p->interdire_scripts = true;
695 return $p;
696 }
697
698 //
699 // #ENV
700 // l'"environnement", id est le $contexte (ou $contexte_inclus)
701 //
702 // en standard on applique |entites_html, mais si vous utilisez
703 // [(#ENV*{toto})] il *faut* vous assurer vous-memes de la securite
704 // anti-javascript (par exemple en filtrant avec |safehtml)
705 //
706 // La syntaxe #ENV{toto, rempl} renverra 'rempl' si $toto est vide
707 //
708 // Si le tableau est vide on renvoie '' (utile pour #SESSION)
709 //
710 // http://doc.spip.org/@balise_ENV_dist
711 function balise_ENV_dist($p, $src = NULL) {
712 // le tableau de base de la balise (cf #META ci-dessous)
713
714 $_nom = interprete_argument_balise(1,$p);
715 $_sinon = interprete_argument_balise(2,$p);
716
717 if (!$_nom) {
718 // cas de #ENV sans argument : on retourne le serialize() du tableau
719 // une belle fonction [(#ENV|affiche_env)] serait pratique
720 $p->code = $src
721 ? ('(is_array($a = ('.$src.')) ? serialize($a) : "")')
722 : '@serialize($Pile[0])';
723 } else {
724 // admet deux arguments : nom de variable, valeur par defaut si vide
725 $p->code = $src
726 ? ('is_array($a = ('.$src.')) ? $a['.$_nom.'] : ""')
727 : ('@$Pile[0][' . $_nom . ']');
728 if ($_sinon)
729 $p->code = 'sinon('.
730 $p->code.",$_sinon)";
731 else
732 $p->code = '('.$p->code.')';
733 }
734 #$p->interdire_scripts = true;
735
736 return $p;
737 }
738
739 //
740 // #CONFIG
741 // les reglages du site
742 //
743 // Par exemple #CONFIG{gerer_trad} donne 'oui' ou 'non' selon le reglage
744 // Attention c'est brut de decoffrage de la table spip_meta
745 //
746 // La balise fonctionne exactement comme #ENV (ci-dessus)
747 //
748 // http://doc.spip.org/@balise_CONFIG_dist
749 function balise_CONFIG_dist($p) {
750 if(function_exists('balise_ENV'))
751 return balise_ENV($p, '$GLOBALS["meta"]');
752 else
753 return balise_ENV_dist($p, '$GLOBALS["meta"]');
754 }
755
756 // http://doc.spip.org/@balise_CONNECT_dist
757 function balise_CONNECT_dist($p) {
758 $p->code = '($connect ? $connect : NULL)';
759 $p->interdire_scripts = false;
760 return $p;
761 }
762
763 //
764 // #SESSION
765 // Cette balise est un tableau des donnees du visiteur (nom, email etc)
766 // Si elle est invoquee, elle leve un drapeau dans le fichier cache, qui
767 // permet a public/cacher d'invalider le cache si le visiteur suivant n'a
768 // pas la meme session
769 // http://doc.spip.org/@balise_SESSION_dist
770 function balise_SESSION_dist($p) {
771 $p->descr['session'] = true;
772
773 $f = function_exists('balise_ENV')
774 ? 'balise_ENV'
775 : 'balise_ENV_dist';
776
777 $p = $f($p, '$GLOBALS["visiteur_session"]');
778 return $p;
779 }
780
781 //
782 // #SESSION_SET{x,y}
783 // Ajoute x=y dans la session du visiteur
784 // http://doc.spip.org/@balise_SESSION_SET_dist
785 function balise_SESSION_SET_dist($p) {
786 $_nom = interprete_argument_balise(1,$p);
787 $_val = interprete_argument_balise(2,$p);
788 if (!$_nom OR !$_val) {
789 $err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'SESSION_SET'));
790 erreur_squelette($err_b_s_a, $p);
791 } else $p->code = '(include_spip("inc/session") AND session_set('.$_nom.','.$_val.'))';
792
793 $p->interdire_scripts = false;
794
795 return $p;
796 }
797
798
799
800
801 //
802 // #EVAL{...}
803 // evalue un code php ; a utiliser avec precaution :-)
804 //
805 // rq: #EVAL{code} produit eval('return code;')
806 // mais si le code est une expression sans balise, on se dispense
807 // de passer par une construction si compliquee, et le code est
808 // passe tel quel (entre parentheses, et protege par interdire_scripts)
809 // Exemples : #EVAL**{6+9} #EVAL**{_DIR_IMG_PACK} #EVAL{'date("Y-m-d")'}
810 // #EVAL{'str_replace("r","z", "roger")'} (attention les "'" sont interdits)
811 // http://doc.spip.org/@balise_EVAL_dist
812 function balise_EVAL_dist($p) {
813 $php = interprete_argument_balise(1,$p);
814 if ($php) {
815 # optimisation sur les #EVAL{une expression sans #BALISE}
816 # attention au commentaire "// x signes" qui precede
817 if (preg_match(",^([[:space:]]*//[^\n]*\n)'([^']+)'$,ms",
818 $php,$r))
819 $p->code = /* $r[1]. */'('.$r[2].')';
820 else
821 $p->code = "eval('return '.$php.';')";
822 } else {
823 $msg = array('zbug_balise_sans_argument', array('balise' => ' EVAL'));
824 erreur_squelette($msg, $p);
825 }
826
827 #$p->interdire_scripts = true;
828
829 return $p;
830 }
831
832 // #CHAMP_SQL{x} renvoie la valeur du champ sql 'x'
833 // permet de recuperer par exemple un champ notes dans une table sql externe
834 // (impossible via #NOTES qui est une balise calculee)
835 // ne permet pas de passer une expression pour x qui ne peut etre qu'un texte statique !
836 // http://doc.spip.org/@balise_CHAMP_SQL_dist
837 function balise_CHAMP_SQL_dist($p){
838
839 if ($p->param
840 AND isset($p->param[0][1][0])
841 AND $champ = ($p->param[0][1][0]->texte))
842 $p->code = champ_sql($champ, $p);
843 else {
844 $err_b_s_a = array('zbug_balise_sans_argument', array('balise' => ' URL_'));
845 erreur_squelette($err_b_s_a, $p);
846 }
847 #$p->interdire_scripts = true;
848 return $p;
849 }
850
851 // #VAL{x} renvoie 'x' (permet d'appliquer un filtre a une chaine)
852 // Attention #VAL{1,2} renvoie '1', indiquer #VAL{'1,2'}
853 // http://doc.spip.org/@balise_VAL_dist
854 function balise_VAL_dist($p){
855 $p->code = interprete_argument_balise(1,$p);
856 if (!strlen($p->code))
857 $p->code = "''";
858 $p->interdire_scripts = false;
859 return $p;
860 }
861 // #NOOP est un alias pour regler #948, ne pas documenter
862 // http://doc.spip.org/@balise_NOOP_dist
863 function balise_NOOP_dist($p) { return balise_VAL_dist($p); }
864
865 //
866 // #REM
867 // pour les remarques : renvoie toujours ''
868 //
869 // http://doc.spip.org/@balise_REM_dist
870 function balise_REM_dist($p) {
871 $p->code="''";
872 $p->interdire_scripts = false;
873 return $p;
874 }
875
876
877 //
878 // #HTTP_HEADER
879 // pour les entetes de retour http
880 // Ne fonctionne pas sur les INCLURE !
881 // #HTTP_HEADER{Content-Type: text/css}
882 //
883 // http://doc.spip.org/@balise_HTTP_HEADER_dist
884 function balise_HTTP_HEADER_dist($p) {
885
886 $header = interprete_argument_balise(1,$p);
887 if (!$header) {
888 $err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'HTTP_HEADER'));
889 erreur_squelette($err_b_s_a, $p);
890 } else $p->code = "'<'.'?php header(\"' . "
891 . $header
892 . " . '\"); ?'.'>'";
893 $p->interdire_scripts = false;
894 return $p;
895 }
896
897 // Filtre a appliquer a l'ensemble de la page une fois calculee
898 // (filtrage fait au niveau du squelette, et sans s'appliquer aux <INCLURE>)
899 // http://doc.spip.org/@balise_FILTRE_dist
900 function balise_FILTRE_dist($p) {
901 if ($p->param) {
902 $args = array();
903 foreach ($p->param as $i => $ignore)
904 $args[] = interprete_argument_balise($i+1,$p);
905 $p->code = "'<' . '"
906 .'?php header("X-Spip-Filtre: \'.'
907 .join('.\'|\'.', $args)
908 . " . '\"); ?'.'>'";
909
910 $p->interdire_scripts = false;
911 return $p;
912 }
913 }
914
915 //
916 // #CACHE
917 // definit la duree de vie ($delais) du squelette
918 // #CACHE{24*3600}
919 // parametre(s) supplementaire(s) :
920 // #CACHE{24*3600, cache-client} autorise gestion du IF_MODIFIED_SINCE
921 // #CACHE{24*3600, statique} ne respecte pas l'invalidation par modif de la base
922 // (mais s'invalide tout de meme a l'expiration du delai)
923 // par defaut cache-client => statique
924 // cf. ecrire/public/cacher.php
925 // http://doc.spip.org/@balise_CACHE_dist
926 function balise_CACHE_dist($p) {
927
928 if ($p->param) {
929 $duree = valeur_numerique($p->param[0][1][0]->texte);
930
931 // noter la duree du cache dans un entete proprietaire
932
933 $code = '\'<'.'?php header("X-Spip-Cache: '
934 . $duree
935 . '"); ?'.'>\'';
936
937 // Remplir le header Cache-Control
938 // cas #CACHE{0}
939 if ($duree == 0)
940 $code .= '.\'<'
941 .'?php header("Cache-Control: no-store, no-cache, must-revalidate"); ?'
942 .'><'
943 .'?php header("Pragma: no-cache"); ?'
944 .'>\'';
945
946 // recuperer les parametres suivants
947 $i = 1;
948 while (isset($p->param[0][++$i])) {
949 $pa = ($p->param[0][$i][0]->texte);
950
951 if ($pa == 'cache-client'
952 AND $duree > 0) {
953 $code .= '.\'<'.'?php header("Cache-Control: max-age='
954 . $duree
955 . '"); ?'.'>\'';
956 // il semble logique, si on cache-client, de ne pas invalider
957 $pa = 'statique';
958 }
959
960 if ($pa == 'statique'
961 AND $duree > 0)
962 $code .= '.\'<'.'?php header("X-Spip-Statique: oui"); ?'.'>\'';
963 }
964 } else $code = "''";
965 $p->code = $code;
966 $p->interdire_scripts = false;
967 return $p;
968 }
969
970 //
971 // #INSERT_HEAD
972 // pour permettre aux plugins d'inserer des styles, js ou autre
973 // dans l'entete sans modification du squelette
974 // les css doivent etre inserees de preference par #INSERT_HEAD_CSS
975 // pour en faciliter la surcharge
976 //
977 // http://doc.spip.org/@balise_INSERT_HEAD_dist
978 function balise_INSERT_HEAD_dist($p) {
979 $p->code = "insert_head_css().pipeline('insert_head','<!-- insert_head -->')";
980 $p->code .= '. \'<'
981 .'?php header("X-Spip-Filtre: \'.'
982 .'\'compacte_head\''
983 . " . '\"); ?'.'>'";
984 $p->interdire_scripts = false;
985 return $p;
986 }
987
988 // http://doc.spip.org/@balise_INSERT_HEAD_CSS_dist
989 function balise_INSERT_HEAD_CSS_dist($p) {
990 $p->code = "insert_head_css()";
991 $p->interdire_scripts = false;
992 return $p;
993 }
994
995 //
996 // #INCLURE statique
997 // l'inclusion est realisee au calcul du squelette, pas au service
998 // ainsi le produit du squelette peut etre utilise en entree de filtres a suivre
999 // on peut faire un #INCLURE{fichier} sans squelette
1000 // (Incompatible avec les balises dynamiques)
1001 // http://doc.spip.org/@balise_INCLUDE_dist
1002 function balise_INCLUDE_dist($p) {
1003 if(function_exists('balise_INCLURE'))
1004 return balise_INCLURE($p);
1005 else
1006 return balise_INCLURE_dist($p);
1007 }
1008 // http://doc.spip.org/@balise_INCLURE_dist
1009 function balise_INCLURE_dist($p) {
1010 $id_boucle = $p->id_boucle;
1011 // la lang n'est pas passe de facon automatique par argumenter
1012 // mais le sera pas recuperer_fond, sauf si etoile=>true est passe
1013 // en option
1014
1015 $_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $id_boucle, false, false);
1016
1017 // erreur de syntaxe = fond absent
1018 // (2 messages d'erreur SPIP pour le prix d'un, mais pas d'erreur PHP
1019 if (!$_contexte) $contexte = array();
1020
1021 if (isset($_contexte['fond'])) {
1022
1023 $f = $_contexte['fond'];
1024 // toujours vrai :
1025 if (preg_match('/^.fond.\s*=>(.*)$/s', $f, $r)) {
1026 $f = $r[1];
1027 unset($_contexte['fond']);
1028 } else spip_log("compilation de #INCLURE a revoir");
1029
1030 // #INCLURE{doublons}
1031 if (isset($_contexte['doublons'])) {
1032 $_contexte['doublons'] = "'doublons' => \$doublons";
1033 }
1034
1035 // Critere d'inclusion {env} (et {self} pour compatibilite ascendante)
1036 if (isset($_contexte['env'])
1037 || isset($_contexte['self'])
1038 ) {
1039 $flag_env = true;
1040 unset($_contexte['env']);
1041 } else $flag_env = false;
1042
1043 $_options = array();
1044 if (isset($_contexte['ajax'])) {
1045 $_options[] = "'ajax'=>true";
1046 unset($_contexte['ajax']);
1047 }
1048 if ($p->etoile) $_options[] = "'etoile'=>true";
1049 $_options[] = "'compil'=>array(" . memoriser_contexte_compil($p) .")";
1050
1051 $_l = 'array(' . join(",\n\t", $_contexte) .')';
1052 if ($flag_env) $_l = "array_merge(\$Pile[0],$_l)";
1053
1054 $p->code = sprintf(CODE_RECUPERER_FOND, $f, $_l, join(',',$_options),"''");
1055
1056 } elseif (!isset($_contexte[1])) {
1057 $msg = array('zbug_balise_sans_argument', array('balise' => ' INCLURE'));
1058 erreur_squelette($msg, $p);
1059 } else $p->code = '(($c = find_in_path(' . $_contexte[1] . ')) ? spip_file_get_contents($c) : "")';
1060
1061 $p->interdire_scripts = false; // la securite est assuree par recuperer_fond
1062 return $p;
1063 }
1064
1065 // Inclure un modele : #MODELE{modele, params}
1066 // http://doc.spip.org/@balise_MODELE_dist
1067 function balise_MODELE_dist($p) {
1068
1069 $_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $p->id_boucle, false);
1070
1071 // erreur de syntaxe = fond absent
1072 // (2 messages d'erreur SPIP pour le prix d'un, mais pas d'erreur PHP
1073 if (!$_contexte) $contexte = array();
1074
1075 if (!isset($_contexte[1])) {
1076 $msg = array('zbug_balise_sans_argument', array('balise' => ' MODELE'));
1077 erreur_squelette($msg, $p);
1078 } else {
1079 $nom = $_contexte[1];
1080 unset($_contexte[1]);
1081
1082 if (preg_match("/^\s*'[^']*'/s", $nom))
1083 $nom = "'modeles/" . substr($nom,1);
1084 else $nom = "'modeles/' . $nom";
1085
1086 // Incoherence dans la syntaxe du contexte. A revoir.
1087 // Reserver la cle primaire de la boucle courante si elle existe
1088 if (isset($p->boucles[$p->id_boucle]->primary)) {
1089 $primary = $p->boucles[$p->id_boucle]->primary;
1090 if (!strpos($primary,',')) {
1091 $id = champ_sql($primary, $p);
1092 $_contexte[] = "'$primary'=>".$id;
1093 $_contexte[] = "'id'=>".$id;
1094 }
1095 }
1096 $_contexte[] = "'recurs'=>(++\$recurs)";
1097 $connect = '';
1098 if (isset($p->boucles[$p->id_boucle]))
1099 $connect = $p->boucles[$p->id_boucle]->sql_serveur;
1100
1101 $_options = memoriser_contexte_compil($p);
1102 $_options = "'compil'=>array($_options), 'trim'=>true"
1103 . (isset($_contexte['ajax'])?", 'ajax'=>true":'');
1104
1105 $page = sprintf(CODE_RECUPERER_FOND, $nom, 'array(' . join(',', $_contexte) .')', $_options, _q($connect));
1106
1107 $p->code = "\n\t(((\$recurs=(isset(\$Pile[0]['recurs'])?\$Pile[0]['recurs']:0))>=5)? '' :\n\t$page)\n";
1108
1109 $p->interdire_scripts = false; // securite assuree par le squelette
1110 }
1111
1112 return $p;
1113 }
1114
1115 //
1116 // #SET
1117 // Affecte une variable locale au squelette
1118 // #SET{nom,valeur}
1119 // la balise renvoie la valeur
1120 // http://doc.spip.org/@balise_SET_dist
1121 function balise_SET_dist($p){
1122 $_nom = interprete_argument_balise(1,$p);
1123 $_val = interprete_argument_balise(2,$p);
1124
1125 if (!$_nom OR !$_val) {
1126 $err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'SET'));
1127 erreur_squelette($err_b_s_a, $p);
1128 } else $p->code = "vide(\$Pile['vars'][$_nom] = $_val)";
1129
1130 $p->interdire_scripts = false; // la balise ne renvoie rien
1131 return $p;
1132 }
1133
1134 //
1135 // #GET
1136 // Recupere une variable locale au squelette
1137 // #GET{nom,defaut} renvoie defaut si la variable nom n'a pas ete affectee
1138 //
1139 // http://doc.spip.org/@balise_GET_dist
1140 function balise_GET_dist($p) {
1141 $p->interdire_scripts = false; // le contenu vient de #SET, donc il est de confiance
1142 if (function_exists('balise_ENV'))
1143 return balise_ENV($p, '$Pile["vars"]');
1144 else
1145 return balise_ENV_dist($p, '$Pile["vars"]');
1146 }
1147
1148
1149 // #DOUBLONS{mots} ou #DOUBLONS{mots,famille}
1150 // donne l'etat des doublons (MOTS) a cet endroit
1151 // sous forme de tableau d'id_mot array(1,2,3,...)
1152 // #DOUBLONS tout seul donne la liste brute de tous les doublons
1153 // #DOUBLONS*{mots} donne la chaine brute ",1,2,3,..."
1154 // (changera si la gestion des doublons evolue)
1155 //
1156 // http://doc.spip.org/@balise_DOUBLONS_dist
1157 function balise_DOUBLONS_dist($p) {
1158 if ($type = interprete_argument_balise(1,$p)) {
1159 if ($famille = interprete_argument_balise(2,$p))
1160 $type .= '.' . $famille;
1161 $p->code = '$doublons['.$type.']';
1162 if (!$p->etoile)
1163 $p->code = 'array_filter(array_map("intval",explode(",",'
1164 . $p->code . ')))';
1165 }
1166 else
1167 $p->code = '$doublons';
1168
1169 $p->interdire_scripts = false;
1170
1171 return $p;
1172 }
1173
1174
1175 //
1176 // #PIPELINE
1177 // pour permettre aux plugins d'inserer des sorties de pipeline dans un squelette
1178 // #PIPELINE{insert_body}
1179 // #PIPELINE{insert_body,flux}
1180 //
1181 // http://doc.spip.org/@balise_PIPELINE_dist
1182 function balise_PIPELINE_dist($p) {
1183 $_pipe = interprete_argument_balise(1,$p);
1184 if (!$_pipe) {
1185 $err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'PIPELINE'));
1186 erreur_squelette($err_b_s_a, $p);
1187 } else {
1188 $_flux = interprete_argument_balise(2,$p);
1189 $_flux = $_flux?$_flux:"''";
1190 $p->code = "pipeline( $_pipe , $_flux )";
1191 $p->interdire_scripts = false;
1192 }
1193 return $p;
1194 }
1195
1196 //
1197 // #EDIT
1198 // une balise qui ne fait rien, pour surcharge par le plugin widgets
1199 //
1200 // http://doc.spip.org/@balise_EDIT_dist
1201 function balise_EDIT_dist($p) {
1202 $p->code = "''";
1203 $p->interdire_scripts = false;
1204 return $p;
1205 }
1206
1207
1208 //
1209 // #TOTAL_UNIQUE
1210 // pour recuperer le nombre d'elements affiches par l'intermediaire du filtre
1211 // |unique
1212 // usage:
1213 // #TOTAL_UNIQUE afiche le nombre de #BALISE|unique
1214 // #TOTAL_UNIQUE{famille} afiche le nombre de #BALISE|unique{famille}
1215 //
1216 // http://doc.spip.org/@balise_TOTAL_UNIQUE_dist
1217 function balise_TOTAL_UNIQUE_dist($p) {
1218 $_famille = interprete_argument_balise(1,$p);
1219 $_famille = $_famille ? $_famille : "''";
1220 $p->code = "unique('', $_famille, true)";
1221 return $p;
1222 }
1223
1224 //
1225 // #ARRAY
1226 // pour creer un array php a partir d'arguments calcules
1227 // #ARRAY{key1,val1,key2,val2 ...} retourne array(key1=>val1,...)
1228 //
1229 // http://doc.spip.org/@balise_ARRAY_dist
1230 function balise_ARRAY_dist($p) {
1231 $_code = array();
1232 $n=1;
1233 do {
1234 $_key = interprete_argument_balise($n++,$p);
1235 $_val = interprete_argument_balise($n++,$p);
1236 if ($_key AND $_val) $_code[] = "$_key => $_val";
1237 } while ($_key && $_val);
1238 $p->code = 'array(' . join(', ',$_code).')';
1239 $p->interdire_scripts = false;
1240 return $p;
1241 }
1242
1243 //#FOREACH
1244 //
1245 // http://doc.spip.org/@balise_FOREACH_dist
1246 function balise_FOREACH_dist($p) {
1247 $_tableau = interprete_argument_balise(1,$p);
1248 $_tableau = str_replace("'", "", strtoupper($_tableau));
1249 $_tableau = sinon($_tableau, 'ENV');
1250 $f = 'balise_'.$_tableau;
1251 $balise = function_exists($f) ? $f : (function_exists($g = $f.'_dist') ? $g : '');
1252
1253 if($balise) {
1254 $_modele = interprete_argument_balise(2,$p);
1255 $_modele = str_replace("'", "", strtolower($_modele));
1256 $__modele = 'foreach_'.strtolower($_tableau);
1257 $_modele = (!$_modele AND trouve_modele($__modele)) ?
1258 $__modele :
1259 ($_modele ? $_modele : 'foreach');
1260
1261 // on passe a la balise seulement les parametres
1262 // mais on enleve les 2 deja utilise
1263 // [(#FOREACH{CONFIG,'',suivants}|filtre)]
1264 $p->param[0] = array_merge(array(""),array_slice($p->param[0],3));
1265 $p = $balise($p);
1266 $filtre = chercher_filtre('foreach');
1267 $p->code = $filtre . "(unserialize(" . $p->code . "), '" . $_modele . "')";
1268 }
1269 //On a pas trouve la balise correspondant au tableau a traiter
1270 else {
1271 $msg = array('zbug_balise_inexistante',array('from'=>'#FOREACH','balise'=>$_tableau));
1272 erreur_squelette($msg, $p);
1273 }
1274 return $p;
1275 }
1276
1277 // Appelle la fonction autoriser et renvoie ' ' si OK, '' si niet
1278 // A noter : la priorite des operateurs exige && plutot que AND
1279 // Cette balise cree un cache par session
1280 // http://doc.spip.org/@balise_AUTORISER_dist
1281 function balise_AUTORISER_dist($p) {
1282 $_code = array();
1283 $p->descr['session'] = true; // faire un cache par session
1284
1285 $n=1;
1286 while ($_v = interprete_argument_balise($n++,$p))
1287 $_code[] = $_v;
1288
1289 $p->code = '(include_spip("inc/autoriser")&&autoriser(' . join(', ',$_code).')?" ":"")';
1290 $p->interdire_scripts = false;
1291 return $p;
1292 }
1293
1294 // Appelle la fonction info_plugin
1295 // Afficher des informations sur les plugins dans le site public
1296 // http://doc.spip.org/@balise_PLUGIN_dist
1297 function balise_PLUGIN_dist($p) {
1298 $plugin = interprete_argument_balise(1,$p);
1299 $plugin = isset($plugin) ? str_replace('\'', '"', $plugin) : '""';
1300 $type_info = interprete_argument_balise(2,$p);
1301 $type_info = isset($type_info) ? str_replace('\'', '"', $type_info) : '"est_actif"';
1302
1303 $f = chercher_filtre('info_plugin');
1304 $p->code = $f.'('.$plugin.', '.$type_info.')';
1305 return $p;
1306 }
1307
1308 // Appelle la fonction inc_aider_dist
1309 // http://doc.spip.org/@balise_AIDER_dist
1310 function balise_AIDER_dist($p) {
1311 $_motif = interprete_argument_balise(1,$p);
1312 $s = "'" . addslashes($p->descr['sourcefile']) . "'";
1313 $aider = charger_fonction('aider','inc');
1314 $p->code = "((\$aider=charger_fonction('aider','inc'))?\$aider($_motif,$s, \$Pile[0]):'')";
1315 return $p;
1316 }
1317
1318 // Insertion du contexte des formulaires charger/verifier/traiter
1319 // avec les hidden de l'url d'action
1320 // http://doc.spip.org/@balise_ACTION_FORMULAIRE
1321 function balise_ACTION_FORMULAIRE($p){
1322 if (!$_url = interprete_argument_balise(1,$p))
1323 $_url = "@\$Pile[0]['action']";
1324 if (!$_form = interprete_argument_balise(2,$p))
1325 $_form = "@\$Pile[0]['form']";
1326
1327 // envoyer le nom du formulaire que l'on traite
1328 // transmettre les eventuels args de la balise formulaire
1329 $p->code = " '<div>' .
1330 form_hidden($_url) .
1331 '<input name=\'formulaire_action\' type=\'hidden\'
1332 value=\'' . $_form . '\' />' .
1333 '<input name=\'formulaire_action_args\' type=\'hidden\'
1334 value=\'' . @\$Pile[0]['formulaire_args']. '\' />' .
1335 (@\$Pile[0]['_hidden']?@\$Pile[0]['_hidden']:'') .
1336 '</div>'";
1337
1338 $p->interdire_scripts = false;
1339 return $p;
1340 }
1341
1342
1343 /**
1344 * Generer un bouton d'action en post, ajaxable
1345 * a utiliser a la place des liens action_auteur, sous la forme
1346 * #BOUTON_ACTION{libelle,url}
1347 * ou
1348 * #BOUTON_ACTION{libelle,url,ajax} pour que l'action soit ajax comme un lien class='ajax'
1349 * ou
1350 * #BOUTON_ACTION{libelle,url,ajax,message_confirmation} pour utiliser un message de confirmation
1351 *
1352 * @param unknown_type $p
1353 * @return unknown
1354 */
1355 function balise_BOUTON_ACTION_dist($p){
1356
1357 $_label = interprete_argument_balise(1,$p);
1358 if (!$_label) $_label="''";
1359
1360 $_url = interprete_argument_balise(2,$p);
1361 if (!$_url) $_url="''";
1362
1363 $_class = interprete_argument_balise(3,$p);
1364 if (!$_class) $_class="''";
1365
1366 $_confirm = interprete_argument_balise(4,$p);
1367 if (!$_confirm) $_confirm="''";
1368
1369 $_title = interprete_argument_balise(5,$p);
1370 if (!$_title) $_title="''";
1371
1372 $p->code = "bouton_action($_label, $_url, $_class, $_confirm, $_title)";
1373 $p->interdire_scripts = false;
1374 return $p;
1375 }
1376
1377 ?>