PageRenderTime 62ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/ecrire/public/balises.php

https://gitlab.com/danielquisbert/SPIP
PHP | 2730 lines | 1019 code | 223 blank | 1488 comment | 119 complexity | ad518b176113eae9b5d556cb937931ff MD5 | raw file
  1. <?php
  2. /***************************************************************************\
  3. * SPIP, Systeme de publication pour l'internet *
  4. * *
  5. * Copyright (c) 2001-2014 *
  6. * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
  7. * *
  8. * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
  9. * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
  10. \***************************************************************************/
  11. /**
  12. * Ce fichier regroupe la quasi totalité des définitions de `#BALISES` de SPIP.
  13. *
  14. * Pour chaque balise, il est possible de surcharger, dans son fichier
  15. * mes_fonctions.php, la fonction `balise_TOTO_dist()` par une fonction
  16. * `balise_TOTO()` respectant la même API : elle reçoit en entrée un objet
  17. * de classe `Champ`, le modifie et le retourne. Cette classe est définie
  18. * dans public/interfaces.
  19. *
  20. * Des balises dites «dynamiques» sont également déclarées dans le
  21. * répertoire ecrire/balise/
  22. *
  23. * @package SPIP\Core\Compilateur\Balises
  24. **/
  25. if (!defined('_ECRIRE_INC_VERSION')) return;
  26. /**
  27. * Retourne le code PHP d'un argument de balise s'il est présent
  28. *
  29. * @uses calculer_liste()
  30. * @example
  31. * ```
  32. * // Retourne le premier argument de la balise
  33. * // #BALISE{premier,deuxieme}
  34. * $arg = interprete_argument_balise(1,$p);
  35. * ```
  36. *
  37. * @param int $n
  38. * Numéro de l'argument
  39. * @param Champ $p
  40. * Pile au niveau de la balise
  41. * @return string|null
  42. * Code PHP si cet argument est présent, sinon null
  43. **/
  44. function interprete_argument_balise($n,$p) {
  45. if (($p->param) && (!$p->param[0][0]) && (count($p->param[0])>$n))
  46. return calculer_liste($p->param[0][$n],
  47. $p->descr,
  48. $p->boucles,
  49. $p->id_boucle);
  50. else
  51. return NULL;
  52. }
  53. //
  54. // Définition des balises
  55. //
  56. /**
  57. * Compile la balise `#NOM_SITE_SPIP` retournant le nom du site
  58. *
  59. * @balise
  60. * @link http://www.spip.net/4622
  61. *
  62. * @param Champ $p
  63. * Pile au niveau de la balise
  64. * @return Champ
  65. * Pile complétée par le code à générer
  66. **/
  67. function balise_NOM_SITE_SPIP_dist($p) {
  68. $p->code = "\$GLOBALS['meta']['nom_site']";
  69. #$p->interdire_scripts = true;
  70. return $p;
  71. }
  72. /**
  73. * Compile la balise `#EMAIL_WEBMASTER` retournant l'adresse courriel
  74. * du webmestre
  75. *
  76. * @balise
  77. * @link http://www.spip.net/4586
  78. *
  79. * @param Champ $p
  80. * Pile au niveau de la balise
  81. * @return Champ
  82. * Pile complétée par le code à générer
  83. **/
  84. function balise_EMAIL_WEBMASTER_dist($p) {
  85. $p->code = "\$GLOBALS['meta']['email_webmaster']";
  86. #$p->interdire_scripts = true;
  87. return $p;
  88. }
  89. /**
  90. * Compile la balise `#DESCRIPTIF_SITE_SPIP` qui retourne le descriptif
  91. * du site !
  92. *
  93. * @balise
  94. * @link http://www.spip.net/4338
  95. *
  96. * @param Champ $p
  97. * Pile au niveau de la balise
  98. * @return Champ
  99. * Pile complétée par le code à générer
  100. **/
  101. function balise_DESCRIPTIF_SITE_SPIP_dist($p) {
  102. $p->code = "\$GLOBALS['meta']['descriptif_site']";
  103. #$p->interdire_scripts = true;
  104. return $p;
  105. }
  106. /**
  107. * Compile la balise `#CHARSET` qui retourne le nom du jeu de caractères
  108. * utilisé par le site tel que `utf-8`
  109. *
  110. * @balise
  111. * @link http://www.spip.net/4331
  112. * @example
  113. * ```
  114. * <meta http-equiv="Content-Type" content="text/html; charset=#CHARSET" />
  115. * ```
  116. *
  117. * @param Champ $p
  118. * Pile au niveau de la balise
  119. * @return Champ
  120. * Pile complétée par le code à générer
  121. **/
  122. function balise_CHARSET_dist($p) {
  123. $p->code = "\$GLOBALS['meta']['charset']";
  124. #$p->interdire_scripts = true;
  125. return $p;
  126. }
  127. /**
  128. * Compile la balise `#LANG_LEFT` retournant 'left' si la langue s'écrit
  129. * de gauche à droite, sinon 'right'
  130. *
  131. * @note
  132. * Peut servir à l'écriture de code CSS dans un squelette, mais
  133. * pour inclure un fichier css, il vaut mieux utiliser le filtre
  134. * `direction_css` si on le souhaite sensible à la langue utilisé.
  135. *
  136. * @balise
  137. * @link http://www.spip.net/4625
  138. * @see lang_dir()
  139. * @see balise_LANG_RIGHT_dist()
  140. * @see balise_LANG_DIR_dist()
  141. * @see direction_css()
  142. *
  143. * @param Champ $p
  144. * Pile au niveau de la balise
  145. * @return Champ
  146. * Pile complétée par le code à générer
  147. **/
  148. function balise_LANG_LEFT_dist($p) {
  149. $_lang = champ_sql('lang', $p);
  150. $p->code = "lang_dir($_lang, 'left','right')";
  151. $p->interdire_scripts = false;
  152. return $p;
  153. }
  154. /**
  155. * Compile la balise `#LANG_RIGHT` retournant 'right' si la langue s'écrit
  156. * de gauche à droite, sinon 'left'
  157. *
  158. * @balise
  159. * @link http://www.spip.net/4625
  160. * @see lang_dir()
  161. * @see balise_LANG_LEFT_dist()
  162. * @see balise_LANG_DIR_dist()
  163. * @see direction_css()
  164. *
  165. * @param Champ $p
  166. * Pile au niveau de la balise
  167. * @return Champ
  168. * Pile complétée par le code à générer
  169. **/
  170. function balise_LANG_RIGHT_dist($p) {
  171. $_lang = champ_sql('lang', $p);
  172. $p->code = "lang_dir($_lang, 'right','left')";
  173. $p->interdire_scripts = false;
  174. return $p;
  175. }
  176. /**
  177. * Compile la balise `#LANG_DIR` retournant 'ltr' si la langue s'écrit
  178. * de gauche à droite, sinon 'rtl'
  179. *
  180. * @balise
  181. * @link http://www.spip.net/4625
  182. * @see lang_dir()
  183. * @see balise_LANG_LEFT_dist()
  184. * @see balise_LANG_RIGHT_dist()
  185. * @example
  186. * ```
  187. * <html dir="#LANG_DIR" lang="#LANG"
  188. * xmlns="http://www.w3.org/1999/xhtml"
  189. * xml:lang="#LANG" class="[(#LANG_DIR)][ (#LANG)] no-js">
  190. * ```
  191. *
  192. * @param Champ $p
  193. * Pile au niveau de la balise
  194. * @return Champ
  195. * Pile complétée par le code à générer
  196. **/
  197. function balise_LANG_DIR_dist($p) {
  198. $_lang = champ_sql('lang', $p);
  199. $p->code = "lang_dir($_lang, 'ltr','rtl')";
  200. $p->interdire_scripts = false;
  201. return $p;
  202. }
  203. /**
  204. * Compile la balise `#PUCE` affichant une puce
  205. *
  206. * @balise
  207. * @link http://www.spip.net/4628
  208. * @see definir_puce()
  209. *
  210. * @param Champ $p
  211. * Pile au niveau de la balise
  212. * @return Champ
  213. * Pile complétée par le code à générer
  214. **/
  215. function balise_PUCE_dist($p) {
  216. $p->code = "definir_puce()";
  217. $p->interdire_scripts = false;
  218. return $p;
  219. }
  220. /**
  221. * Compile la balise `#DATE` qui retourne la date de mise en ligne
  222. *
  223. * Cette balise retourne soit le champ `date` d'une table si elle est
  224. * utilisée dans une boucle, sinon la date de calcul du squelette.
  225. *
  226. * @balise
  227. * @link http://www.spip.net/4336 Balise DATE
  228. * @link http://www.spip.net/1971 La gestion des dates
  229. * @example
  230. * ```
  231. * <td>[(#DATE|affdate_jourcourt)]</td>
  232. * ```
  233. *
  234. * @param Champ $p
  235. * Pile au niveau de la balise.
  236. * @return Champ
  237. * Pile completée du code PHP d'exécution de la balise
  238. */
  239. function balise_DATE_dist ($p) {
  240. $d = champ_sql('date', $p);
  241. # if ($d === "@\$Pile[0]['date']")
  242. # $d = "isset(\$Pile[0]['date']) ? $d : time()";
  243. $p->code = $d;
  244. return $p;
  245. }
  246. /**
  247. * Compile la balise `#DATE_REDAC` qui retourne la date de première publication
  248. *
  249. * Cette balise retourne le champ `date_redac` d'une table
  250. *
  251. * @balise
  252. * @link http://www.spip.net/3858 Balises DATE_MODIF et DATE_REDAC
  253. * @link http://www.spip.net/1971 La gestion des dates
  254. * @see balise_DATE_MODIF_dist()
  255. *
  256. * @param Champ $p
  257. * Pile au niveau de la balise.
  258. * @return Champ
  259. * Pile completée du code PHP d'exécution de la balise
  260. */
  261. function balise_DATE_REDAC_dist ($p) {
  262. $d = champ_sql('date_redac', $p);
  263. # if ($d === "@\$Pile[0]['date_redac']")
  264. # $d = "isset(\$Pile[0]['date_redac']) ? $d : time()";
  265. $p->code = $d;
  266. $p->interdire_scripts = false;
  267. return $p;
  268. }
  269. /**
  270. * Compile la balise `#DATE_MODIF` qui retourne la date de dernière modification
  271. *
  272. * Cette balise retourne le champ `date_modif` d'une table
  273. *
  274. * @balise
  275. * @link http://www.spip.net/3858 Balises DATE_MODIF et DATE_REDAC
  276. * @link http://www.spip.net/1971 La gestion des dates
  277. * @see balise_DATE_REDAC_dist()
  278. *
  279. * @param Champ $p
  280. * Pile au niveau de la balise.
  281. * @return Champ
  282. * Pile completée du code PHP d'exécution de la balise
  283. */
  284. function balise_DATE_MODIF_dist ($p) {
  285. $p->code = champ_sql('date_modif', $p);
  286. $p->interdire_scripts = false;
  287. return $p;
  288. }
  289. /**
  290. * Compile la balise `#DATE_NOUVEAUTES` indiquant la date de dernier envoi
  291. * du mail de nouveautés
  292. *
  293. * @balise
  294. * @link http://www.spip.net/4337 Balise DATE_NOUVEAUTES
  295. * @link http://www.spip.net/1971 La gestion des dates
  296. * @see balise_DATE_REDAC_dist()
  297. *
  298. * @param Champ $p
  299. * Pile au niveau de la balise.
  300. * @return Champ
  301. * Pile completée du code PHP d'exécution de la balise
  302. */
  303. function balise_DATE_NOUVEAUTES_dist($p) {
  304. $p->code = "((\$GLOBALS['meta']['quoi_de_neuf'] == 'oui'
  305. AND isset(\$GLOBALS['meta']['dernier_envoi_neuf'])) ?
  306. \$GLOBALS['meta']['dernier_envoi_neuf'] :
  307. \"'0000-00-00'\")";
  308. $p->interdire_scripts = false;
  309. return $p;
  310. }
  311. /**
  312. * Compile la balise `#DOSSIER_SQUELETTE` retournant le chemin vers le
  313. * répertoire de squelettes actuellement utilisé
  314. *
  315. * @balise
  316. * @deprecated Utiliser `#CHEMIN`
  317. * @link http://www.spip.net/4627
  318. * @see balise_CHEMIN_dist()
  319. *
  320. * @param Champ $p
  321. * Pile au niveau de la balise.
  322. * @return Champ
  323. * Pile completée du code PHP d'exécution de la balise
  324. */
  325. function balise_DOSSIER_SQUELETTE_dist($p) {
  326. $code = substr(addslashes(dirname($p->descr['sourcefile'])), strlen(_DIR_RACINE));
  327. $p->code = "_DIR_RACINE . '$code'" .
  328. $p->interdire_scripts = false;
  329. return $p;
  330. }
  331. /**
  332. * Compile la balise `#SQUELETTE` retournant le chemin du squelette courant
  333. *
  334. * @balise
  335. * @link http://www.spip.net/4027
  336. *
  337. * @param Champ $p
  338. * Pile au niveau de la balise.
  339. * @return Champ
  340. * Pile completée du code PHP d'exécution de la balise
  341. */
  342. function balise_SQUELETTE_dist($p) {
  343. $code = addslashes($p->descr['sourcefile']);
  344. $p->code = "'$code'" .
  345. $p->interdire_scripts = false;
  346. return $p;
  347. }
  348. /**
  349. * Compile la balise `#SPIP_VERSION` qui affiche la version de SPIP
  350. *
  351. * @balise
  352. * @see spip_version()
  353. * @example
  354. * ```
  355. * <meta name="generator" content="SPIP[ (#SPIP_VERSION)]" />
  356. * ```
  357. *
  358. * @param Champ $p
  359. * Pile au niveau de la balise.
  360. * @return Champ
  361. * Pile completée du code PHP d'exécution de la balise
  362. */
  363. function balise_SPIP_VERSION_dist($p) {
  364. $p->code = "spip_version()";
  365. $p->interdire_scripts = false;
  366. return $p;
  367. }
  368. /**
  369. * Compile la balise `#NOM_SITE` qui affiche le nom du site.
  370. *
  371. * Affiche le nom du site ou sinon l'URL ou le titre de l'objet
  372. * Utiliser `#NOM_SITE*` pour avoir le nom du site ou rien.
  373. *
  374. * Cette balise interroge les colonnes `nom_site` ou `url_site`
  375. * dans la boucle la plus proche.
  376. *
  377. * @balise
  378. * @see calculer_url()
  379. * @example
  380. * ```
  381. * <a href="#URL_SITE">#NOM_SITE</a>
  382. * ```
  383. *
  384. * @param Champ $p
  385. * Pile au niveau de la balise
  386. * @return Champ
  387. * Pile complétée par le code à générer
  388. **/
  389. function balise_NOM_SITE_dist($p) {
  390. if (!$p->etoile) {
  391. $p->code = "supprimer_numero(calculer_url(" .
  392. champ_sql('url_site',$p) ."," .
  393. champ_sql('nom_site',$p) .
  394. ", 'titre', \$connect, false))";
  395. } else
  396. $p->code = champ_sql('nom_site',$p);
  397. $p->interdire_scripts = true;
  398. return $p;
  399. }
  400. /**
  401. * Compile la balise `#NOTE` qui affiche les notes de bas de page
  402. *
  403. * @balise
  404. * @link http://www.spip.net/3964
  405. * @see calculer_notes()
  406. *
  407. * @param Champ $p
  408. * Pile au niveau de la balise
  409. * @return Champ
  410. * Pile complétée par le code à générer
  411. **/
  412. function balise_NOTES_dist($p) {
  413. // Recuperer les notes
  414. $p->code = 'calculer_notes()';
  415. #$p->interdire_scripts = true;
  416. return $p;
  417. }
  418. /**
  419. * Compile la balise `#RECHERCHE` qui retourne le terme de recherche demandé
  420. *
  421. * Retourne un terme demandé en recherche, en le prenant dans _request()
  422. * sous la clé `recherche`.
  423. *
  424. * @balise
  425. * @example
  426. * ```
  427. * <h3>Recherche de : #RECHERCHE</h3>
  428. * ```
  429. *
  430. * @param Champ $p
  431. * Pile au niveau de la balise
  432. * @return Champ
  433. * Pile complétée par le code à générer
  434. **/
  435. function balise_RECHERCHE_dist($p) {
  436. $p->code = 'entites_html(_request("recherche"))';
  437. $p->interdire_scripts = false;
  438. return $p;
  439. }
  440. /**
  441. * Compile la balise `#COMPTEUR_BOUCLE` qui retourne le numéro de l’itération
  442. * actuelle de la boucle
  443. *
  444. * @balise
  445. * @link http://www.spip.net/4333
  446. * @see balise_TOTAL_BOUCLE_dist()
  447. *
  448. * @param Champ $p
  449. * Pile au niveau de la balise
  450. * @return Champ
  451. * Pile complétée par le code à générer
  452. **/
  453. function balise_COMPTEUR_BOUCLE_dist($p) {
  454. $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
  455. if ($b === '') {
  456. $msg = array('zbug_champ_hors_boucle',
  457. array('champ' => '#COMPTEUR_BOUCLE')
  458. );
  459. erreur_squelette($msg, $p);
  460. } else {
  461. $p->code = "\$Numrows['$b']['compteur_boucle']";
  462. $p->boucles[$b]->cptrows = true;
  463. $p->interdire_scripts = false;
  464. return $p;
  465. }
  466. }
  467. /**
  468. * Compile la balise `#TOTAL_BOUCLE` qui retourne le nombre de résultats
  469. * affichés par la boucle
  470. *
  471. * @balise
  472. * @link http://www.spip.net/4334
  473. * @see balise_COMPTEUR_BOUCLE_dist()
  474. * @see balise_GRAND_TOTAL_dist()
  475. *
  476. * @param Champ $p
  477. * Pile au niveau de la balise
  478. * @return Champ
  479. * Pile complétée par le code à générer
  480. **/
  481. function balise_TOTAL_BOUCLE_dist($p) {
  482. $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
  483. if ($b === '' || !isset($p->boucles[$b])) {
  484. $msg = array('zbug_champ_hors_boucle',
  485. array('champ' => "#$b" . 'TOTAL_BOUCLE')
  486. );
  487. erreur_squelette($msg, $p);
  488. } else {
  489. $p->code = "\$Numrows['$b']['total']";
  490. $p->boucles[$b]->numrows = true;
  491. $p->interdire_scripts = false;
  492. }
  493. return $p;
  494. }
  495. /**
  496. * Compile la balise `#POINTS` qui affiche la pertinence des résultats
  497. *
  498. * Retourne le calcul `points` réalisé par le critère `recherche`.
  499. * Cette balise nécessite donc la présence de ce critère.
  500. *
  501. * @balise
  502. * @link http://www.spip.net/903 Boucles et balises de recherche
  503. * @see critere_recherche_dist()
  504. *
  505. * @param Champ $p
  506. * Pile au niveau de la balise
  507. * @return Champ
  508. * Pile complétée par le code à générer
  509. **/
  510. function balise_POINTS_dist($p) {
  511. return rindex_pile($p, 'points', 'recherche');
  512. }
  513. /**
  514. * Compile la balise `#POPULARITE_ABSOLUE` qui affiche la popularité absolue
  515. *
  516. * Cela correspond à la popularité quotidienne de l'article
  517. *
  518. * @balise
  519. * @link http://www.spip.net/1846 La popularité
  520. * @see balise_POPULARITE_dist()
  521. * @see balise_POPULARITE_MAX_dist()
  522. * @see balise_POPULARITE_SITE_dist()
  523. *
  524. * @param Champ $p
  525. * Pile au niveau de la balise
  526. * @return Champ
  527. * Pile complétée par le code à générer
  528. **/
  529. function balise_POPULARITE_ABSOLUE_dist($p) {
  530. $p->code = 'ceil(' .
  531. champ_sql('popularite', $p) .
  532. ')';
  533. $p->interdire_scripts = false;
  534. return $p;
  535. }
  536. /**
  537. * Compile la balise `#POPULARITE_SITE` qui affiche la popularité du site
  538. *
  539. * La popularité du site est la somme de toutes les popularités absolues.
  540. *
  541. * @balise
  542. * @link http://www.spip.net/1846 La popularité
  543. * @see balise_POPULARITE_ABSOLUE_dist()
  544. * @see balise_POPULARITE_dist()
  545. * @see balise_POPULARITE_MAX_dist()
  546. *
  547. * @param Champ $p
  548. * Pile au niveau de la balise
  549. * @return Champ
  550. * Pile complétée par le code à générer
  551. **/
  552. function balise_POPULARITE_SITE_dist($p) {
  553. $p->code = 'ceil($GLOBALS["meta"][\'popularite_total\'])';
  554. $p->interdire_scripts = false;
  555. return $p;
  556. }
  557. /**
  558. * Compile la balise `#POPULARITE_MAX` qui affiche la popularité maximum
  559. * parmis les popularités des articles
  560. *
  561. * Cela correspond à la popularité quotidienne de l'article
  562. *
  563. * @balise
  564. * @link http://www.spip.net/1846 La popularité
  565. * @see balise_POPULARITE_ABSOLUE_dist()
  566. * @see balise_POPULARITE_dist()
  567. * @see balise_POPULARITE_SITE_dist()
  568. *
  569. * @param Champ $p
  570. * Pile au niveau de la balise
  571. * @return Champ
  572. * Pile complétée par le code à générer
  573. **/
  574. function balise_POPULARITE_MAX_dist($p) {
  575. $p->code = 'ceil($GLOBALS["meta"][\'popularite_max\'])';
  576. $p->interdire_scripts = false;
  577. return $p;
  578. }
  579. /**
  580. * Compile la balise `#VALEUR` retournant le champ `valeur`
  581. *
  582. * Utile dans une boucle DATA pour retourner une valeur.
  583. *
  584. * @balise
  585. * @link http://www.spip.net/5546 #CLE et #VALEUR
  586. * @see table_valeur()
  587. * @example
  588. * ```
  589. * #VALEUR renvoie le champ valeur
  590. * #VALEUR{x} renvoie #VALEUR|table_valeur{x},
  591. * équivalent à #X (si X n'est pas une balise spéficique à SPIP)
  592. * #VALEUR{a/b} renvoie #VALEUR|table_valeur{a/b}
  593. * ```
  594. *
  595. * @param Champ $p
  596. * Pile au niveau de la balise
  597. * @return Champ
  598. * Pile complétée par le code à générer
  599. **/
  600. function balise_VALEUR_dist($p) {
  601. $b = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle;
  602. $p->code = index_pile($p->id_boucle, 'valeur', $p->boucles, $b);;
  603. if (($v = interprete_argument_balise(1,$p))!==NULL){
  604. $p->code = 'table_valeur('.$p->code.', '.$v.')';
  605. }
  606. $p->interdire_scripts = true;
  607. return $p;
  608. }
  609. /**
  610. * Compile la balise `#EXPOSE` qui met en évidence l'élément sur lequel
  611. * la page se trouve
  612. *
  613. * Expose dans une boucle l'élément de la page sur laquelle on se trouve,
  614. * en retournant `on` si l'élément correspond à la page, une chaîne vide sinon.
  615. *
  616. * On peut passer les paramètres à faire retourner par la balise.
  617. *
  618. * @example
  619. * ```
  620. * <a href="#URL_ARTICLE"[ class="(#EXPOSE)"]>
  621. * <a href="#URL_ARTICLE"[ class="(#EXPOSE{actif})"]>
  622. * <a href="#URL_ARTICLE"[ class="(#EXPOSE{on,off})"]>
  623. * ```
  624. *
  625. * @balise
  626. * @link http://www.spip.net/2319 Exposer un article
  627. * @uses calculer_balise_expose()
  628. *
  629. * @param Champ $p
  630. * Pile au niveau de la balise
  631. * @return Champ
  632. * Pile complétée par le code à générer
  633. **/
  634. function balise_EXPOSE_dist($p) {
  635. $on = "'on'";
  636. $off= "''";
  637. if (($v = interprete_argument_balise(1,$p))!==NULL){
  638. $on = $v;
  639. if (($v = interprete_argument_balise(2,$p))!==NULL)
  640. $off = $v;
  641. }
  642. return calculer_balise_expose($p, $on, $off);
  643. }
  644. /**
  645. * Calcul de la balise expose
  646. *
  647. * @see calcul_exposer()
  648. *
  649. * @param Champ $p
  650. * Pile au niveau de la balise
  651. * @param string $on
  652. * Texte à afficher si l'élément est exposé (code à écrire tel que "'on'")
  653. * @param string $off
  654. * Texte à afficher si l'élément n'est pas exposé (code à écrire tel que "''")
  655. * @return Champ
  656. * Pile complétée par le code à générer
  657. **/
  658. function calculer_balise_expose($p, $on, $off)
  659. {
  660. $b = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle;
  661. $key = $p->boucles[$b]->primary;
  662. $type = $p->boucles[$p->id_boucle]->primary;
  663. $desc = $p->boucles[$b]->show;
  664. $connect = sql_quote($p->boucles[$b]->sql_serveur);
  665. if (!$key) {
  666. $msg = array('zbug_champ_hors_boucle', array('champ' => '#EXPOSER'));
  667. erreur_squelette($msg, $p);
  668. }
  669. // Ne pas utiliser champ_sql, on jongle avec le nom boucle explicite
  670. $c = index_pile($p->id_boucle, $type, $p->boucles);
  671. if (isset($desc['field']['id_parent'])) {
  672. $parent = 0; // pour if (!$parent) dans calculer_expose
  673. } elseif (isset($desc['field']['id_rubrique'])) {
  674. $parent = index_pile($p->id_boucle, 'id_rubrique', $p->boucles, $b);
  675. } elseif (isset($desc['field']['id_groupe'])) {
  676. $parent = index_pile($p->id_boucle, 'id_groupe', $p->boucles, $b);
  677. } else $parent = "''";
  678. $p->code = "(calcul_exposer($c, '$type', \$Pile[0], $parent, '$key', $connect) ? $on : $off)";
  679. $p->interdire_scripts = false;
  680. return $p;
  681. }
  682. /**
  683. * Compile la balise `#DEBUT_SURLIGNE` qui permettait le surlignage
  684. * des mots d'une recherche
  685. *
  686. * @note
  687. * Cette balise n'a plus d'effet depuis r9343
  688. *
  689. * @balise
  690. * @see balise_FIN_SURLIGNE_dist()
  691. * @deprecated Utiliser les classes CSS `surlignable` ou `pas_surlignable`
  692. *
  693. * @param Champ $p
  694. * Pile au niveau de la balise
  695. * @return Champ
  696. * Pile complétée par le code à générer
  697. **/
  698. function balise_DEBUT_SURLIGNE_dist($p) {
  699. include_spip('inc/surligne');
  700. $p->code = "'<!-- " . MARQUEUR_SURLIGNE . " -->'";
  701. return $p;
  702. }
  703. /**
  704. * Compile la balise `#FIN_SURLIGNE` qui arrêtait le surlignage
  705. * des mots d'une recherche
  706. *
  707. * @note
  708. * Cette balise n'a plus d'effet depuis r9343
  709. *
  710. * @balise
  711. * @see balise_DEBUT_SURLIGNE_dist()
  712. * @deprecated Utiliser les classes CSS `surlignable` ou `pas_surlignable`
  713. *
  714. * @param Champ $p
  715. * Pile au niveau de la balise
  716. * @return Champ
  717. * Pile complétée par le code à générer
  718. **/
  719. function balise_FIN_SURLIGNE_dist($p) {
  720. include_spip('inc/surligne');
  721. $p->code = "'<!-- " . MARQUEUR_FSURLIGNE . "-->'";
  722. return $p;
  723. }
  724. /**
  725. * Compile la balise `#INTRODUCTION`
  726. *
  727. * Retourne une introduction d'un objet éditorial, c'est à dire les 600
  728. * premiers caractères environ du champ 'texte' de l'objet ou le contenu
  729. * indiqué entre `<intro>` et `</intro>` de ce même champ.
  730. *
  731. * Pour les articles, l'introduction utilisée est celle du champ `descriptif`
  732. * s'il est renseigné, sinon il est pris dans les champs `chapo` et `texte` et
  733. * est par défaut limité à 500 caractères.
  734. *
  735. * Pour les rubriques, l'introduction utilisée est celle du champ `descriptif`
  736. * s'il est renseigné, sinon du champ texte.
  737. *
  738. * La balise accèpte 1 paramètre indiquant la longueur en nombre de caractères
  739. * de l'introduction.
  740. *
  741. * @see filtre_introduction_dist()
  742. * @example
  743. * ```
  744. * #INTRODUCTION
  745. * #INTRODUCTION{300}
  746. * ```
  747. *
  748. * @balise
  749. * @link http://www.spip.net/@introduction
  750. *
  751. * @param Champ $p
  752. * Pile au niveau de la balise
  753. * @return Champ
  754. * Pile complétée par le code à générer
  755. **/
  756. function balise_INTRODUCTION_dist($p) {
  757. $type = $p->type_requete;
  758. $_texte = champ_sql('texte', $p);
  759. $_descriptif = ($type == 'articles' OR $type == 'rubriques') ? champ_sql('descriptif', $p) : "''";
  760. if ($type == 'articles') {
  761. $_chapo = champ_sql('chapo', $p);
  762. $_texte = "(strlen($_descriptif))
  763. ? ''
  764. : $_chapo . \"\\n\\n\" . $_texte";
  765. }
  766. // longueur en parametre, ou valeur par defaut
  767. $longueur_defaut = objet_info($type,'introduction_longueur');
  768. if (!$longueur_defaut)
  769. $longueur_defaut = 600;
  770. $_suite = 'null';
  771. $_longueur = $longueur_defaut;
  772. if (($v = interprete_argument_balise(1,$p))!==NULL) {
  773. $_longueur = 'is_numeric('.$v.')?intval('.$v.'):'.$longueur_defaut;
  774. $_suite = '!is_numeric('.$v.')?'.$v.':null';
  775. }
  776. if (($v2 = interprete_argument_balise(2,$p))!==NULL) {
  777. $_suite = $v2;
  778. }
  779. $f = chercher_filtre('introduction');
  780. $p->code = "$f($_descriptif, $_texte, $_longueur, \$connect, $_suite)";
  781. #$p->interdire_scripts = true;
  782. $p->etoile = '*'; // propre est deja fait dans le calcul de l'intro
  783. return $p;
  784. }
  785. /**
  786. * Compile la balise `#LANG` qui affiche la langue de l'objet (ou d'une boucle supérieure),
  787. * et à defaut la langue courante
  788. *
  789. * La langue courante est celle du site ou celle qui a été passée dans l'URL par le visiteur.
  790. * L'étoile `#LANG*` n'affiche rien si aucune langue n'est trouvée dans le SQL ou le contexte.
  791. *
  792. * @balise
  793. * @link http://www.spip.net/3864
  794. *
  795. * @param Champ $p
  796. * Pile au niveau de la balise
  797. * @return Champ
  798. * Pile complétée par le code à générer
  799. **/
  800. function balise_LANG_dist ($p) {
  801. $_lang = champ_sql('lang', $p);
  802. if (!$p->etoile)
  803. $p->code = "spip_htmlentities($_lang ? $_lang : \$GLOBALS['spip_lang'])";
  804. else
  805. $p->code = "spip_htmlentities($_lang)";
  806. $p->interdire_scripts = false;
  807. return $p;
  808. }
  809. /**
  810. * Compile la balise `#LESAUTEURS` chargée d'afficher la liste des auteurs d'un objet
  811. *
  812. * - Soit le champ `lesauteurs` existe dans la table et à ce moment là,
  813. * la balise retourne son contenu,
  814. * - soit la balise appelle le modele `lesauteurs.html` en lui passant
  815. * le couple `objet` et `id_objet` dans son environnement.
  816. *
  817. * @balise
  818. * @link http://www.spip.net/3966 Description de la balise
  819. * @link http://www.spip.net/902 Description de la boucle ARTICLES
  820. * @link http://www.spip.net/911 Description de la boucle SYNDIC_ARTICLES
  821. *
  822. * @param Champ $p
  823. * Pile au niveau de la balise
  824. * @return Champ
  825. * Pile complétée par le code à générer
  826. */
  827. function balise_LESAUTEURS_dist ($p) {
  828. // Cherche le champ 'lesauteurs' dans la pile
  829. $_lesauteurs = champ_sql('lesauteurs', $p, false);
  830. // Si le champ n'existe pas (cas de spip_articles), on applique
  831. // le modele lesauteurs.html en passant id_article dans le contexte;
  832. // dans le cas contraire on prend le champ 'lesauteurs'
  833. // (cf extension sites/)
  834. if ($_lesauteurs
  835. AND $_lesauteurs != '@$Pile[0][\'lesauteurs\']') {
  836. $p->code = "safehtml($_lesauteurs)";
  837. // $p->interdire_scripts = true;
  838. } else {
  839. if(!$p->id_boucle){
  840. $connect = '';
  841. $objet = 'article';
  842. $id_table_objet = 'id_article';
  843. }
  844. else{
  845. $b = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle;
  846. $connect = $p->boucles[$b]->sql_serveur;
  847. $type_boucle = $p->boucles[$b]->type_requete;
  848. $objet = objet_type($type_boucle);
  849. $id_table_objet = id_table_objet($type_boucle);
  850. }
  851. $c = memoriser_contexte_compil($p);
  852. $p->code = sprintf(CODE_RECUPERER_FOND, "'modeles/lesauteurs'",
  853. "array('objet'=>'".$objet.
  854. "','id_objet' => ".champ_sql($id_table_objet, $p) .
  855. ",'$id_table_objet' => ".champ_sql($id_table_objet, $p) .
  856. ($objet=='article'?"":",'id_article' => ".champ_sql('id_article', $p)).
  857. ")",
  858. "'trim'=>true, 'compil'=>array($c)",
  859. _q($connect));
  860. $p->interdire_scripts = false; // securite apposee par recuperer_fond()
  861. }
  862. return $p;
  863. }
  864. /**
  865. * Compile la balise `#RANG` chargée d'afficher le numéro de l'objet
  866. *
  867. * Affiche le « numero de l'objet ». Soit `1` quand on a un titre `1. Premier article`.
  868. *
  869. * Ceci est transitoire afin de préparer une migration vers un vrai système de
  870. * tri des articles dans une rubrique (et plus si affinités).
  871. * La balise permet d'extraire le numero masqué par le filtre `supprimer_numero`.
  872. *
  873. * La balise recupère le champ declaré dans la définition `table_titre`
  874. * de l'objet, ou à defaut du champ `titre`
  875. *
  876. * Si un champ `rang` existe, il est pris en priorité.
  877. *
  878. * @balise
  879. * @link http://www.spip.net/5495
  880. *
  881. * @param Champ $p
  882. * Pile au niveau de la balise
  883. * @return Champ
  884. * Pile complétée par le code à générer
  885. */
  886. function balise_RANG_dist($p) {
  887. $b = index_boucle($p);
  888. if ($b === '') {
  889. $msg = array('zbug_champ_hors_boucle',
  890. array('champ' => '#RANG')
  891. );
  892. erreur_squelette($msg, $p);
  893. }
  894. else {
  895. // chercher d'abord un champ sql rang (mais pas dans le env : defaut '' si on trouve pas de champ sql)
  896. // dans la boucle immediatement englobante uniquement
  897. // sinon on compose le champ calcule
  898. $_rang = champ_sql('rang', $p, '', false);
  899. // si pas trouve de champ sql rang :
  900. if (!$_rang OR $_rang == "''"){
  901. $boucle = &$p->boucles[$b];
  902. $trouver_table = charger_fonction('trouver_table','base');
  903. $desc = $trouver_table($boucle->id_table);
  904. $_titre = ''; # extraire le numero ?
  905. if (isset($desc['titre'])){
  906. $t=$desc['titre'];
  907. if (preg_match(';(^|,)([^,]*titre)(,|$);',$t,$m)){
  908. $m = preg_replace(",as\s+titre$,i","",$m[2]);
  909. $m = trim($m);
  910. if ($m!="''"){
  911. if (!preg_match(",\W,",$m))
  912. $m = $boucle->id_table . ".$m";
  913. $m .= " AS titre_rang";
  914. $boucle->select[] = $m;
  915. $_titre = '$Pile[$SP][\'titre_rang\']';
  916. }
  917. }
  918. }
  919. if (!$_titre)
  920. $_titre = champ_sql('titre', $p);
  921. $_rang = "recuperer_numero($_titre)";
  922. }
  923. $p->code = $_rang;
  924. $p->interdire_scripts = false;
  925. }
  926. return $p;
  927. }
  928. /**
  929. * Compile la balise `#POPULARITE` qui affiche la popularité relative.
  930. *
  931. * C'est à dire le pourcentage de la fréquentation de l'article
  932. * (la popularité absolue) par rapport à la popularité maximum.
  933. *
  934. * @balise
  935. * @link http://www.spip.net/1846 La popularité
  936. * @see balise_POPULARITE_ABSOLUE_dist()
  937. * @see balise_POPULARITE_MAX_dist()
  938. * @see balise_POPULARITE_SITE_dist()
  939. *
  940. * @param Champ $p
  941. * Pile au niveau de la balise
  942. * @return Champ
  943. * Pile complétée par le code à générer
  944. **/
  945. function balise_POPULARITE_dist ($p) {
  946. $_popularite = champ_sql('popularite', $p);
  947. $p->code = "(ceil(min(100, 100 * $_popularite
  948. / max(1 , 0 + \$GLOBALS['meta']['popularite_max']))))";
  949. $p->interdire_scripts = false;
  950. return $p;
  951. }
  952. /**
  953. * Code de compilation pour la balise `#PAGINATION`
  954. *
  955. * Le code produit est trompeur, car les modèles ne fournissent pas Pile[0].
  956. * On produit un appel à `_request` si on ne l'a pas, mais c'est inexact:
  957. * l'absence peut-être due à une faute de frappe dans le contexte inclus.
  958. */
  959. define('CODE_PAGINATION',
  960. '%s($Numrows["%s"]["grand_total"],
  961. %s,
  962. isset($Pile[0][%4$s])?$Pile[0][%4$s]:intval(_request(%4$s)),
  963. %5$s, %6$s, %7$s, %8$s, array(%9$s))');
  964. /**
  965. * Compile la balise `#PAGINATION` chargée d'afficher une pagination
  966. *
  967. * Elle charge le modèle `pagination.html` (par défaut), mais un paramètre
  968. * permet d'indiquer d'autres modèles. `#PAGINATION{nom}` utilisera le
  969. * modèle `pagination_nom.html`.
  970. *
  971. * Cette balise nécessite le critère `pagination` sur la boucle où elle
  972. * est utilisée.
  973. *
  974. * @balise
  975. * @link http://www.spip.net/3367 Le système de pagination
  976. * @see filtre_pagination_dist()
  977. * @see critere_pagination_dist()
  978. * @see balise_ANCRE_PAGINATION_dist()
  979. * @example
  980. * ```
  981. * [<p class="pagination">(#PAGINATION{prive})</p>]
  982. * ```
  983. *
  984. * @param Champ $p
  985. * Pile au niveau de la balise
  986. * @param string $liste
  987. * Afficher ou non les liens de pagination (variable de type `string`
  988. * car code à faire écrire au compilateur) :
  989. * - `true` pour les afficher
  990. * - `false` pour afficher uniquement l'ancre.
  991. * @return Champ
  992. * Pile complétée par le code à générer
  993. */
  994. function balise_PAGINATION_dist($p, $liste='true') {
  995. $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
  996. // s'il n'y a pas de nom de boucle, on ne peut pas paginer
  997. if ($b === '') {
  998. $msg = array('zbug_champ_hors_boucle',
  999. array('champ' => $liste ? 'PAGINATION' : 'ANCRE_PAGINATION')
  1000. );
  1001. erreur_squelette($msg, $p);
  1002. return $p;
  1003. }
  1004. // s'il n'y a pas de mode_partie, c'est qu'on se trouve
  1005. // dans un boucle recursive ou qu'on a oublie le critere {pagination}
  1006. if (!$p->boucles[$b]->mode_partie) {
  1007. if (!$p->boucles[$b]->table_optionnelle) {
  1008. $msg = array('zbug_pagination_sans_critere',
  1009. array('champ' => '#PAGINATION')
  1010. );
  1011. erreur_squelette($msg, $p);
  1012. }
  1013. return $p;
  1014. }
  1015. // a priori true
  1016. // si false, le compilo va bloquer sur des syntaxes avec un filtre sans argument qui suit la balise
  1017. // si true, les arguments simples (sans truc=chose) vont degager
  1018. $_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $p->id_boucle, false, false);
  1019. if (count($_contexte)){
  1020. list($key,$val) = each($_contexte);
  1021. if (is_numeric($key)){
  1022. array_shift($_contexte);
  1023. $__modele = interprete_argument_balise(1,$p);
  1024. }
  1025. }
  1026. if (count($_contexte)){
  1027. $code_contexte = implode(',',$_contexte);
  1028. }
  1029. else
  1030. $code_contexte = '';
  1031. $connect = $p->boucles[$b]->sql_serveur;
  1032. $pas = $p->boucles[$b]->total_parties;
  1033. $f_pagination = chercher_filtre('pagination');
  1034. $type = $p->boucles[$b]->modificateur['debut_nom'];
  1035. $modif = ($type[0]!=="'") ? "'debut'.$type"
  1036. : ("'debut" .substr($type,1));
  1037. $p->code = sprintf(CODE_PAGINATION, $f_pagination, $b, $type, $modif, $pas, $liste, ((isset($__modele) and $__modele) ? $__modele : "''"), _q($connect), $code_contexte);
  1038. $p->boucles[$b]->numrows = true;
  1039. $p->interdire_scripts = false;
  1040. return $p;
  1041. }
  1042. /**
  1043. * Compile la balise `#ANCRE_PAGINATION` chargée d'afficher l'ancre
  1044. * de la pagination
  1045. *
  1046. * Cette ancre peut ainsi être placée au-dessus la liste des éléments
  1047. * de la boucle alors qu'on mettra les liens de pagination en-dessous de
  1048. * cette liste paginée.
  1049. *
  1050. * Cette balise nécessite le critère `pagination` sur la boucle où elle
  1051. * est utilisée.
  1052. *
  1053. * @balise
  1054. * @link http://www.spip.net/3367 Le système de pagination
  1055. * @link http://www.spip.net/4328 Balise ANCRE_PAGINATION
  1056. * @see critere_pagination_dist()
  1057. * @see balise_PAGINATION_dist()
  1058. *
  1059. * @param Champ $p
  1060. * Pile au niveau de la balise
  1061. * @return Champ
  1062. * Pile complétée par le code à générer
  1063. **/
  1064. function balise_ANCRE_PAGINATION_dist($p) {
  1065. if ($f = charger_fonction('PAGINATION', 'balise', true))
  1066. return $f($p, $liste='false');
  1067. else return NULL; // ou une erreur ?
  1068. }
  1069. /**
  1070. * Compile la balise `#GRAND_TOTAL` qui retourne le nombre total de résultats
  1071. * d'une boucle
  1072. *
  1073. * Cette balise set équivalente à `#TOTAL_BOUCLE` sauf pour les boucles paginées.
  1074. * Dans ce cas elle indique le nombre total d'éléments répondant aux critères
  1075. * hors pagination.
  1076. *
  1077. * @balise
  1078. * @see balise_GRAND_TOTAL_dist()
  1079. *
  1080. * @param Champ $p
  1081. * Pile au niveau de la balise
  1082. * @return Champ
  1083. * Pile complétée par le code à générer
  1084. **/
  1085. function balise_GRAND_TOTAL_dist($p) {
  1086. $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
  1087. if ($b === '' || !isset($p->boucles[$b])) {
  1088. $msg = array('zbug_champ_hors_boucle',
  1089. array('champ' => "#$b" . 'TOTAL_BOUCLE')
  1090. );
  1091. erreur_squelette($msg, $p);
  1092. } else {
  1093. $p->code = "(isset(\$Numrows['$b']['grand_total'])
  1094. ? \$Numrows['$b']['grand_total'] : \$Numrows['$b']['total'])";
  1095. $p->boucles[$b]->numrows = true;
  1096. $p->interdire_scripts = false;
  1097. }
  1098. return $p;
  1099. }
  1100. /**
  1101. * Compile la balise `#SELF` qui retourne l’URL de la page appelée.
  1102. *
  1103. * Cette URL est nettoyée des variables propres à l’exécution de SPIP
  1104. * tel que `var_mode`.
  1105. *
  1106. * @note
  1107. * Attention dans un `INCLURE()` ou une balise dynamique, on n'a pas le droit de
  1108. * mettre en cache `#SELF` car il peut correspondre à une autre page (attaque XSS)
  1109. * (Dans ce cas faire <INCLURE{self=#SELF}> pour différencier les caches.)
  1110. *
  1111. * @balise
  1112. * @link http://www.spip.net/4574
  1113. * @example
  1114. * ```
  1115. * <a href="[(#SELF|parametre_url{id_mot,#ID_MOT})]">...
  1116. * ```
  1117. *
  1118. * @param Champ $p
  1119. * Pile au niveau de la balise
  1120. * @return Champ
  1121. * Pile complétée par le code à générer
  1122. **/
  1123. function balise_SELF_dist($p) {
  1124. $p->code = 'self()';
  1125. $p->interdire_scripts = false;
  1126. return $p;
  1127. }
  1128. /**
  1129. * Compile la balise `#CHEMIN` qui cherche un fichier dans les chemins
  1130. * connus de SPIP et retourne son chemin complet depuis la racine
  1131. *
  1132. * Signature : `#CHEMIN{chemin/vers/fichier.ext}`
  1133. *
  1134. * Retourne une chaîne vide si le fichier n'est pas trouvé.
  1135. *
  1136. * @balise
  1137. * @link http://www.spip.net/4332
  1138. * @see find_in_path() Recherche de chemin
  1139. * @example
  1140. * ```
  1141. * [<script type="text/javascript" src="(#CHEMIN{javascript/jquery.flot.js})"></script>]
  1142. * [<link rel="stylesheet" href="(#CHEMIN{css/perso.css}|direction_css)" type="text/css" />]
  1143. * ```
  1144. *
  1145. * @param Champ $p
  1146. * Pile au niveau de la balise
  1147. * @return Champ
  1148. * Pile complétée par le code à générer
  1149. **/
  1150. function balise_CHEMIN_dist($p) {
  1151. $arg = interprete_argument_balise(1,$p);
  1152. if (!$arg) {
  1153. $msg = array('zbug_balise_sans_argument', array('balise' => ' CHEMIN'));
  1154. erreur_squelette($msg, $p);
  1155. } else
  1156. $p->code = 'find_in_path(' . $arg .')';
  1157. $p->interdire_scripts = false;
  1158. return $p;
  1159. }
  1160. /**
  1161. * Compile la balise `#CHEMIN_IMAGE` qui cherche une image dans le thème
  1162. * de l'espace privé utilisé par SPIP et retourne son chemin complet depuis
  1163. * la racine
  1164. *
  1165. * Signature : `#CHEMIN_IMAGE{image.png}`
  1166. *
  1167. * Retourne une chaîne vide si le fichier n'est pas trouvé.
  1168. *
  1169. * @balise
  1170. * @see chemin_image()
  1171. * @example
  1172. * ```
  1173. * #CHEMIN_IMAGE{article-24.png}
  1174. * ```
  1175. *
  1176. * @param Champ $p
  1177. * Pile au niveau de la balise
  1178. * @return Champ
  1179. * Pile complétée par le code à générer
  1180. **/
  1181. function balise_CHEMIN_IMAGE_dist($p) {
  1182. $arg = interprete_argument_balise(1,$p);
  1183. if (!$arg) {
  1184. $msg = array('zbug_balise_sans_argument', array('balise' => ' CHEMIN_IMAGE'));
  1185. erreur_squelette($msg, $p);
  1186. } else $p->code = 'chemin_image(' . $arg .')';
  1187. #$p->interdire_scripts = true;
  1188. return $p;
  1189. }
  1190. /**
  1191. * Compile la balise `#ENV` qui permet de récupérer le contexte d'environnement
  1192. * transmis à un squelette.
  1193. *
  1194. * La syntaxe `#ENV{toto, valeur par defaut}`
  1195. * renverra `valeur par defaut` si `$toto` est vide.
  1196. *
  1197. * La recherche de la clé s'appuyant sur la fonction `table_valeur`
  1198. * il est possible de demander un sous élément d'un tableau :
  1199. * `#ENV{toto/sous/element, valeur par defaut}` retournera l'équivalent de
  1200. * `#ENV{toto}|table_valeur{sous/element}` c'est-à-dire en quelque sorte
  1201. * `$env['toto']['sous']['element']` s'il existe, sinon la valeur par défaut.
  1202. *
  1203. * Si le tableau est vide on renvoie `''` (utile pour `#SESSION`)
  1204. *
  1205. * Enfin, la balise utilisée seule `#ENV` retourne le tableau complet
  1206. * de l'environnement. À noter que ce tableau est retourné sérialisé.
  1207. *
  1208. * En standard est appliqué le filtre `entites_html`, mais si l'étoile est
  1209. * utilisée pour désactiver les filtres par défaut, par exemple avec
  1210. * `[(#ENV*{toto})]` , il *faut* s'assurer de la sécurité
  1211. * anti-javascript, par exemple en filtrant avec `safehtml` : `[(#ENV*{toto}|safehtml)]`
  1212. *
  1213. *
  1214. * @param Champ $p
  1215. * Pile ; arbre de syntaxe abstrait positionné au niveau de la balise.
  1216. * @param array $src
  1217. * Tableau dans lequel chercher la clé demandée en paramètre de la balise.
  1218. * Par defaut prend dans le contexte du squelette.
  1219. * @return Champ
  1220. * Pile completée du code PHP d'exécution de la balise
  1221. **/
  1222. function balise_ENV_dist($p, $src = NULL) {
  1223. // cle du tableau desiree
  1224. $_nom = interprete_argument_balise(1,$p);
  1225. // valeur par defaut
  1226. $_sinon = interprete_argument_balise(2,$p);
  1227. // $src est un tableau de donnees sources eventuellement transmis
  1228. // en absence, on utilise l'environnement du squelette $Pile[0]
  1229. if (!$_nom) {
  1230. // cas de #ENV sans argument : on retourne le serialize() du tableau
  1231. // une belle fonction [(#ENV|affiche_env)] serait pratique
  1232. if ($src) {
  1233. $p->code = '(is_array($a = ('.$src.')) ? serialize($a) : "")';
  1234. } else {
  1235. $p->code = '@serialize($Pile[0])';
  1236. }
  1237. } else {
  1238. if (!$src) {
  1239. $src = '@$Pile[0]';
  1240. }
  1241. if ($_sinon) {
  1242. $p->code = "sinon(table_valeur($src, (string)$_nom, null), $_sinon)";
  1243. } else {
  1244. $p->code = "table_valeur($src, (string)$_nom, null)";
  1245. }
  1246. }
  1247. #$p->interdire_scripts = true;
  1248. return $p;
  1249. }
  1250. /**
  1251. * Compile la balise `#CONFIG` qui retourne une valeur de configuration
  1252. *
  1253. * Cette balise appelle la fonction `lire_config()` pour obtenir les
  1254. * configurations du site.
  1255. *
  1256. * Par exemple `#CONFIG{gerer_trad}` donne 'oui ou 'non' selon le réglage.
  1257. *
  1258. * Le 3ème argument permet de contrôler la sérialisation du résultat
  1259. * (mais ne sert que pour le dépot `meta`) qui doit parfois désérialiser,
  1260. * par exemple avec `|in_array{#CONFIG{toto,#ARRAY,1}}`. Ceci n'affecte
  1261. * pas d'autres dépots et `|in_array{#CONFIG{toto/,#ARRAY}}` sera
  1262. * équivalent.
  1263. *
  1264. * Òn peut appeler d'autres tables que `spip_meta` avec un
  1265. * `#CONFIG{/infos/champ,defaut}` qui lit la valeur de `champ`
  1266. * dans une table des meta qui serait `spip_infos`
  1267. *
  1268. * @balise
  1269. * @link http://www.spip.net/4335
  1270. *
  1271. * @param Champ $p
  1272. * Pile au niveau de la balise.
  1273. * @return Champ
  1274. * Pile completée du code PHP d'exécution de la balise
  1275. */
  1276. function balise_CONFIG_dist($p) {
  1277. if (!$arg = interprete_argument_balise(1,$p)) {
  1278. $arg = "''";
  1279. }
  1280. $_sinon = interprete_argument_balise(2,$p);
  1281. $_unserialize = sinon(interprete_argument_balise(3,$p),"false");
  1282. $p->code = '(include_spip(\'inc/config\')?lire_config(' . $arg . ',' .
  1283. ($_sinon && $_sinon != "''" ? $_sinon : 'null') . ',' . $_unserialize . "):'')";
  1284. return $p;
  1285. }
  1286. /**
  1287. * Compile la balise `#CONNECT` qui retourne le nom du connecteur
  1288. * de base de données
  1289. *
  1290. * Retourne le nom du connecteur de base de données utilisé (le nom
  1291. * du fichier `config/xx.php` sans l'extension, utilisé pour calculer
  1292. * les données du squelette).
  1293. *
  1294. * Retourne `NULL` si le connecteur utilisé est celui par défaut de SPIP
  1295. * (connect.php), sinon retourne son nom.
  1296. *
  1297. * @balise
  1298. *
  1299. * @param Champ $p
  1300. * Pile au niveau de la balise.
  1301. * @return Champ
  1302. * Pile completée du code PHP d'exécution de la balise
  1303. */
  1304. function balise_CONNECT_dist($p) {
  1305. $p->code = '($connect ? $connect : NULL)';
  1306. $p->interdire_scripts = false;
  1307. return $p;
  1308. }
  1309. /**
  1310. * Compile la balise `#SESSION` qui permet d’accéder aux informations
  1311. * liées au visiteur authentifié et de différencier automatiquement
  1312. * le cache en fonction du visiteur.
  1313. *
  1314. * Cette balise est un tableau des données du visiteur (nom, email etc).
  1315. * Si elle est invoquée, elle lève un drapeau dans le fichier cache, qui
  1316. * permet à public/cacher de créer un cache différent par visiteur
  1317. *
  1318. * @balise
  1319. * @link http://www.spip.net/3979
  1320. * @see balise_AUTORISER_dist()
  1321. * @see balise_SESSION_SET_dist()
  1322. * @example
  1323. * ```
  1324. * #SESSION{nom}
  1325. * ```
  1326. *
  1327. * @param Champ $p
  1328. * Pile au niveau de la balise.
  1329. * @return Champ
  1330. * Pile completée du code PHP d'exécution de la balise
  1331. **/
  1332. function balise_SESSION_dist($p) {
  1333. $p->descr['session'] = true;
  1334. $f = function_exists('balise_ENV')
  1335. ? 'balise_ENV'
  1336. : 'balise_ENV_dist';
  1337. $p = $f($p, '$GLOBALS["visiteur_session"]');
  1338. return $p;
  1339. }
  1340. /**
  1341. * Compile la balise `#SESSION_SET` qui d’insérer dans la session
  1342. * des données supplémentaires
  1343. *
  1344. * @balise
  1345. * @link http://www.spip.net/3984
  1346. * @see balise_AUTORISER_dist()
  1347. * @see balise_SESSION_SET_dist()
  1348. * @example
  1349. * ```
  1350. * #SESSION_SET{x,y} ajoute x=y dans la session du visiteur
  1351. * ```
  1352. *
  1353. * @param Champ $p
  1354. * Pile au niveau de la balise.
  1355. * @return Champ
  1356. * Pile completée du code PHP d'exécution de la balise
  1357. **/
  1358. function balise_SESSION_SET_dist($p) {
  1359. $_nom = interprete_argument_balise(1,$p);
  1360. $_val = interprete_argument_balise(2,$p);
  1361. if (!$_nom OR !$_val) {
  1362. $err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'SESSION_SET'));
  1363. erreur_squelette($err_b_s_a, $p);
  1364. } else $p->code = '(include_spip("inc/session") AND session_set('.$_nom.','.$_val.'))';
  1365. $p->interdire_scripts = false;
  1366. return $p;
  1367. }
  1368. /**
  1369. * Compile la balise `#EVAL` qui évalue un code PHP
  1370. *
  1371. * À utiliser avec précautions !
  1372. *
  1373. * @balise
  1374. * @link http://www.spip.net/4587
  1375. * @example
  1376. * ```
  1377. * #EVAL{6+9}
  1378. * #EVAL{_DIR_IMG_PACK}
  1379. * #EVAL{'date("Y-m-d")'}
  1380. * #EVAL{$_SERVER['REQUEST_URI']}
  1381. * #EVAL{'str_replace("r","z", "roger")'} (attention les "'" sont interdits)
  1382. * ```
  1383. *
  1384. * @note
  1385. * `#EVAL{code}` produit `eval('return code;')`
  1386. * mais si le code est une expression sans balise, on se dispense
  1387. * de passer par une construction si compliquée, et le code est
  1388. * passé tel quel (entre parenthèses, et protégé par interdire_scripts)
  1389. *
  1390. * @param Champ $p
  1391. * Pile au niveau de la balise.
  1392. * @return Champ
  1393. * Pile completée du code PHP d'exécution de la balise
  1394. **/
  1395. function balise_EVAL_dist($p) {
  1396. $php = interprete_argument_balise(1,$p);
  1397. if ($php) {
  1398. # optimisation sur les #EVAL{une expression sans #BALISE}
  1399. # attention au commentaire "// x signes" qui precede
  1400. if (preg_match(",^([[:space:]]*//[^\n]*\n)'([^']+)'$,ms",
  1401. $php,$r))
  1402. $p->code = /* $r[1]. */'('.$r[2].')';
  1403. else
  1404. $p->code = "eval('return '.$php.';')";
  1405. } else {
  1406. $msg = array('zbug_balise_sans_argument', array('balise' => ' EVAL'));
  1407. erreur_squelette($msg, $p);
  1408. }
  1409. #$p->interdire_scripts = true;
  1410. return $p;
  1411. }
  1412. /**
  1413. * Compile la balise `#CHAMP_SQL` qui renvoie la valeur d'un champ SQL
  1414. *
  1415. * Signature : `#CHAMP_SQL{champ}`
  1416. *
  1417. * Cette balise permet de récupérer par exemple un champ `notes` dans une table
  1418. * SQL externe (impossible avec la balise `#NOTES` qui est une balise calculée).
  1419. *
  1420. * Ne permet pas de passer une expression comme argument, qui ne peut
  1421. * être qu'un texte statique !
  1422. *
  1423. * @balise
  1424. * @link http://www.spip.net/4041
  1425. * @see champ_sql()
  1426. * @example
  1427. * ```
  1428. * #CHAMP_SQL{notes}
  1429. * ```
  1430. *
  1431. * @param Champ $p
  1432. * Pile au niveau de la balise
  1433. * @return Champ
  1434. * Pile complétée par le code à générer
  1435. **/
  1436. function balise_CHAMP_SQL_dist($p){
  1437. if ($p->param
  1438. AND isset($p->param[0][1][0])
  1439. AND $champ = ($p->param[0][1][0]->texte))
  1440. $p->code = champ_sql($champ, $p);
  1441. else {
  1442. $err_b_s_a = array('zbug_balise_sans_argument', array('balise' => ' URL_'));
  1443. erreur_squelette($err_b_s_a, $p);
  1444. }
  1445. #$p->interdire_scripts = true;
  1446. return $p;
  1447. }
  1448. /**
  1449. * Compile la balise `#VAL` qui retourne simplement le premier argument
  1450. * qui lui est transmis
  1451. *
  1452. * Cela permet d'appliquer un filtre à une chaîne de caractère
  1453. *
  1454. * @balise
  1455. * @link http://www.spip.net/4026
  1456. * @example
  1457. * ```
  1458. * #VAL retourne ''
  1459. * #VAL{x} retourne 'x'
  1460. * #VAL{1,2} renvoie '1' (2 est considéré comme un autre paramètre)
  1461. * #VAL{'1,2'} renvoie '1,2'
  1462. * [(#VAL{a_suivre}|bouton_spip_rss)]
  1463. * ```
  1464. *
  1465. * @param Champ $p
  1466. * Pile au niveau de la balise
  1467. * @return Champ
  1468. * Pile complétée par le code à générer
  1469. **/
  1470. function balise_VAL_dist($p){
  1471. $p->code = interprete_argument_balise(1,$p);
  1472. if (!strlen($p->code))
  1473. $p->code = "''";
  1474. $p->interdire_scripts = false;
  1475. return $p;
  1476. }
  1477. /**
  1478. * Compile la balise `#NOOP`, alias (déprécié) de `#VAL`
  1479. *
  1480. * Alias pour regler #948. Ne plus utiliser.
  1481. *
  1482. * @balise
  1483. * @see balise_VAL_dist()
  1484. * @deprecated Utiliser #VAL
  1485. *
  1486. * @param Champ $p
  1487. * Pile au niveau de la balise
  1488. * @return Champ
  1489. * Pile complétée par le code à générer
  1490. **/
  1491. function balise_NOOP_dist($p) { return balise_VAL_dist($p); }
  1492. /**
  1493. * Compile la balise `#REM` servant à commenter du texte
  1494. *
  1495. * Retourne toujours une chaîne vide.
  1496. *
  1497. * @balise
  1498. * @link http://www.spip.net/4578
  1499. * @example
  1500. * ```
  1501. * [(#REM)
  1502. * Ceci est une remarque ou un commentaire,
  1503. * non affiché dans le code généré
  1504. * ]
  1505. * ```
  1506. *
  1507. * @note
  1508. * La balise `#REM` n'empêche pas l'exécution des balises SPIP contenues
  1509. * dedans (elle ne sert pas à commenter du code pour empêcher son
  1510. * exécution).
  1511. *
  1512. * @param Champ $p
  1513. * Pile au niveau de la balise
  1514. * @return Champ
  1515. * Pile complétée par le code à générer
  1516. **/
  1517. function balise_REM_dist($p) {
  1518. $p->code="''";
  1519. $p->interdire_scripts = false;
  1520. return $p;
  1521. }
  1522. /**
  1523. * Compile la balise `#HTTP_HEADER` envoyant des entêtes de retour HTTP
  1524. *
  1525. * Doit être placée en tête de fichier et ne fonctionne pas dans une
  1526. * inclusion.
  1527. *
  1528. * @balise
  1529. * @link http://www.spip.net/4631
  1530. * @example
  1531. * ```
  1532. * #HTTP_HEADER{Content-Type: text/csv; charset=#CHARSET}
  1533. * ```
  1534. *
  1535. * @param Champ $p
  1536. * Pile au niveau de la balise
  1537. * @return Champ
  1538. * Pile complétée par le code à générer
  1539. **/
  1540. function balise_HTTP_HEADER_dist($p) {
  1541. $header = interprete_argument_balise(1,$p);
  1542. if (!$header) {
  1543. $err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'HTTP_HEADER'));
  1544. erreur_squelette($err_b_s_a, $p);
  1545. } else $p->code = "'<'.'?php header(\"' . "
  1546. . $header
  1547. . " . '\"); ?'.'>'";
  1548. $p->interdire_scripts = false;
  1549. return $p;
  1550. }
  1551. /**
  1552. * Compile la balise `#FILTRE` qui exécute un filtre à l'ensemble du squelette
  1553. * une fois calculé.
  1554. *
  1555. * Le filtrage se fait au niveau du squelette, sans s'appliquer aux `<INCLURE>`.
  1556. * Plusieurs filtres peuvent être indiqués, séparés par des barres verticales `|`
  1557. *
  1558. * @balise
  1559. * @link http://www.spip.net/4894
  1560. * @example
  1561. * ```
  1562. * #FILTRE{compacte_head}
  1563. * #FILTRE{supprimer_tags|filtrer_entites|trim}
  1564. * ```
  1565. *
  1566. * @param Champ $p
  1567. * Pile au niveau de la balise
  1568. * @return Champ
  1569. * Pile complétée par le code à générer
  1570. **/
  1571. function balise_FILTRE_dist($p) {
  1572. if ($p->param) {
  1573. $args = array();
  1574. foreach ($p->param as $i => $ignore)
  1575. $args[] = interprete_argument_balise($i+1,$p);
  1576. $p->code = "'<' . '"
  1577. .'?php header("X-Spip-Filtre: \'.'
  1578. .join('.\'|\'.', $args)
  1579. . " . '\"); ?'.'>'";
  1580. $p->interdire_scripts = false;
  1581. return $p;
  1582. }
  1583. }
  1584. /**
  1585. * Compile la balise `#CACHE` definissant la durée de validité du cache du squelette
  1586. *
  1587. * Signature : `#CACHE{duree[,type]}`
  1588. *
  1589. * Le premier argument est la durée en seconde du cache. Le second
  1590. * (par défaut `statique`) indique le type de cache :
  1591. *
  1592. * - `cache-client` autorise gestion du IF_MODIFIED_SINCE
  1593. * - `statique` ne respecte pas l'invalidation par modif de la base
  1594. * (mais s'invalide tout de même à l'expiration du delai)
  1595. *
  1596. * @balise
  1597. * @see ecrire/public/cacher.php
  1598. * @link http://www.spip.net/4330
  1599. * @example
  1600. * ```
  1601. * #CACHE{24*3600}
  1602. * #CACHE{24*3600, cache-client}
  1603. * #CACHE{0} pas de cache
  1604. * ```
  1605. * @note
  1606. * En absence de cette balise la durée est du cache est donné
  1607. * par la constante `_DUREE_CACHE_DEFAUT`
  1608. *
  1609. * @param Champ $p
  1610. * Pile au niveau de la balise
  1611. * @return Champ
  1612. * Pile complétée par le code à générer
  1613. **/
  1614. function balise_CACHE_dist($p) {
  1615. if ($p->param) {
  1616. $duree = valeur_numerique($p->param[0][1][0]->texte);
  1617. // noter la duree du cache dans un entete proprietaire
  1618. $code = '\'<'.'?php header("X-Spip-Cache: '
  1619. . $duree
  1620. . '"); ?'.'>\'';
  1621. // Remplir le header Cache-Control
  1622. // cas #CACHE{0}
  1623. if ($duree == 0)
  1624. $code .= '.\'<'
  1625. .'?php header("Cache-Control: no-cache, must-revalidate"); ?'
  1626. .'><'
  1627. .'?php header("Pragma: no-cache"); ?'
  1628. .'>\'';
  1629. // recuperer les parametres suivants
  1630. $i = 1;
  1631. while (isset($p->param[0][++$i])) {
  1632. $pa = ($p->param[0][$i][0]->texte);
  1633. if ($pa == 'cache-client'
  1634. AND $duree > 0) {
  1635. $code .= '.\'<'.'?php header("Cache-Control: max-age='
  1636. . $duree
  1637. . '"); ?'.'>\'';
  1638. // il semble logique, si on cache-client, de ne pas invalider
  1639. $pa = 'statique';
  1640. }
  1641. if ($pa == 'statique'
  1642. AND $duree > 0)
  1643. $code .= '.\'<'.'?php header("X-Spip-Statique: oui"); ?'.'>\'';
  1644. }
  1645. } else $code = "''";
  1646. $p->code = $code;
  1647. $p->interdire_scripts = false;
  1648. return $p;
  1649. }
  1650. /**
  1651. * Compile la balise `#INSERT_HEAD` permettant d'insérer du contenu dans
  1652. * le `<head>` d'une page HTML
  1653. *
  1654. * La balise permet aux plugins d'insérer des styles, js ou autre
  1655. * dans l'entête sans modification du squelette.
  1656. * Les css doivent être inserées de préférence par `#INSERT_HEAD_CSS`
  1657. * pour en faciliter la surcharge.
  1658. *
  1659. * On insère ici aussi un morceau de PHP qui verifiera à l'exécution
  1660. * que le pipeline `insert_head_css` a bien été vu
  1661. * et dans le cas contraire l'appelera. Ceal permet de ne pas oublier
  1662. * les css de `#INSERT_HEAD_CSS` même si cette balise n'est pas presente.
  1663. *
  1664. * Il faut mettre ce php avant le `insert_head` car le compresseur y mets
  1665. * ensuite un php du meme type pour collecter
  1666. * CSS et JS, et on ne veut pas qu'il rate les css insérées en fallback
  1667. * par `insert_head_css_conditionnel`.
  1668. *
  1669. * @link http://www.spip.net/4629
  1670. * @see balise_INSERT_HEAD_CSS_dist()
  1671. *
  1672. * @param Champ $p
  1673. * Pile au niveau de la balise
  1674. * @return Champ
  1675. * Pile complétée par le code à générer
  1676. */
  1677. function balise_INSERT_HEAD_dist($p) {
  1678. $p->code = '\'<'
  1679. .'?php header("X-Spip-Filtre: \'.'
  1680. .'\'insert_head_css_conditionnel\''
  1681. . " . '\"); ?'.'>'";
  1682. $p->code .= ". pipeline('insert_head','<!-- insert_head -->')";
  1683. $p->interdire_scripts = false;
  1684. return $p;
  1685. }
  1686. /**
  1687. * Compile la balise `#INSERT_HEAD_CSS` homologue de `#INSERT_HEAD` pour les CSS
  1688. *
  1689. * Et par extension pour le JS inline qui doit préférentiellement
  1690. * être inséré avant les CSS car bloquant sinon.
  1691. *
  1692. * @link http://www.spip.net/4605
  1693. * @see balise_INSERT_HEAD_dist()
  1694. *
  1695. * @param Champ $p
  1696. * Pile au niveau de la balise
  1697. * @return Champ
  1698. * Pile complétée par le code à générer
  1699. */
  1700. function balise_INSERT_HEAD_CSS_dist($p) {
  1701. $p->code = "pipeline('insert_head_css','<!-- insert_head_css -->')";
  1702. $p->interdire_scripts = false;
  1703. return $p;
  1704. }
  1705. /**
  1706. * Compile la balise `#INCLUDE` alias de `#INCLURE`
  1707. *
  1708. * @balise
  1709. * @see balise_INCLURE_dist()
  1710. *
  1711. * @param Champ $p
  1712. * Pile au niveau de la balise
  1713. * @return Champ
  1714. * Pile complétée par le code à générer
  1715. **/
  1716. function balise_INCLUDE_dist($p) {
  1717. if(function_exists('balise_INCLURE'))
  1718. return balise_INCLURE($p);
  1719. else
  1720. return balise_INCLURE_dist($p);
  1721. }
  1722. /**
  1723. * Compile la balise `#INCLURE` qui inclut un résultat de squelette
  1724. *
  1725. * Signature : `[(#INCLURE{fond=nom_du_squelette, argument, argument=xx})]`
  1726. *
  1727. * L'argument `env` permet de transmettre tout l'environnement du squelette
  1728. * en cours au squelette inclus.
  1729. *
  1730. * On parle d’inclusion « statique » car le résultat de compilation est
  1731. * ajouté au squelette en cours, dans le même fichier de cache.
  1732. * Cette balise est donc différente d’une inclusion « dynamique » avec
  1733. * `<INCLURE.../>` qui, elle, crée un fichier de cache séparé
  1734. * (avec une durée de cache qui lui est propre).
  1735. *
  1736. * L'inclusion est realisée au calcul du squelette, pas au service
  1737. * ainsi le produit du squelette peut être utilisé en entrée de filtres
  1738. * à suivre. On peut faire un `#INCLURE{fichier}` sans squelette
  1739. * (Incompatible avec les balises dynamiques).
  1740. *
  1741. * @balise
  1742. * @example
  1743. * ```
  1744. * [(#INCLURE{fond=inclure/documents,id_article, env})]
  1745. * ```
  1746. *
  1747. * @param Champ $p
  1748. * Pile au niveau de la balise
  1749. * @return Champ
  1750. * Pile complétée par le code à générer
  1751. **/
  1752. function balise_INCLURE_dist($p) {
  1753. $id_boucle = $p->id_boucle;
  1754. // la lang n'est pas passe de facon automatique par argumenter
  1755. // mais le sera pas recuperer_fond, sauf si etoile=>true est passe
  1756. // en option
  1757. $_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $id_boucle, false, false);
  1758. // erreur de syntaxe = fond absent
  1759. // (2 messages d'erreur SPIP pour le prix d'un, mais pas d'erreur PHP
  1760. if (!$_contexte) $contexte = array();
  1761. if (isset($_contexte['fond'])) {
  1762. $f = $_contexte['fond'];
  1763. // toujours vrai :
  1764. if (preg_match('/^.fond.\s*=>(.*)$/s', $f, $r)) {
  1765. $f = $r[1];
  1766. unset($_contexte['fond']);
  1767. } else spip_log("compilation de #INCLURE a revoir");
  1768. // #INCLURE{doublons}
  1769. if (isset($_contexte['doublons'])) {
  1770. $_contexte['doublons'] = "'doublons' => \$doublons";
  1771. }
  1772. // Critere d'inclusion {env} (et {self} pour compatibilite ascendante)
  1773. $flag_env = false;
  1774. if (isset($_contexte['env']) OR isset($_contexte['self'])) {
  1775. $flag_env = true;
  1776. unset($_contexte['env']);
  1777. }
  1778. $_options = array();
  1779. if (isset($_contexte['ajax'])) {
  1780. $_options[] = preg_replace(",=>(.*)$,ims",'=> ($v=(\\1))?$v:true',$_contexte['ajax']);
  1781. unset($_contexte['ajax']);
  1782. }
  1783. if ($p->etoile) $_options[] = "'etoile'=>true";
  1784. $_options[] = "'compil'=>array(" . memoriser_contexte_compil($p) .")";
  1785. $_l = 'array(' . join(",\n\t", $_contexte) .')';
  1786. if ($flag_env) $_l = "array_merge(\$Pile[0],$_l)";
  1787. $p->code = sprintf(CODE_RECUPERER_FOND, $f, $_l, join(',',$_options),"_request('connect')");
  1788. }
  1789. elseif (!isset($_contexte[1])) {
  1790. $msg = array('zbug_balise_sans_argument', array('balise' => ' INCLURE'));
  1791. erreur_squelette($msg, $p);
  1792. }
  1793. else {
  1794. $p->code = 'charge_scripts(' . $_contexte[1] . ',false)';
  1795. }
  1796. $p->interdire_scripts = false; // la securite est assuree par recuperer_fond
  1797. return $p;
  1798. }
  1799. /**
  1800. * Compile la balise `#MODELE` qui inclut un résultat de squelette de modèle
  1801. *
  1802. * `#MODELE{nom}` insère le résultat d’un squelette contenu dans le
  1803. * répertoire `modeles/`. L’identifiant de la boucle parente est transmis
  1804. * par défaut avec le paramètre `id` à cette inclusion.
  1805. *
  1806. * Des arguments supplémentaires peuvent être transmis :
  1807. * `[(#MODELE{nom, argument=xx, argument})]`
  1808. *
  1809. * @balise
  1810. * @see balise_INCLURE_dist()
  1811. * @example
  1812. * ```
  1813. * #MODELE{article_traductions}
  1814. * ```
  1815. *
  1816. * @param Champ $p
  1817. * Pile au niveau de la balise
  1818. * @return Champ
  1819. * Pile complétée par le code à générer
  1820. **/
  1821. function balise_MODELE_dist($p) {
  1822. $_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $p->id_boucle, false);
  1823. // erreur de syntaxe = fond absent
  1824. // (2 messages d'erreur SPIP pour le prix d'un, mais pas d'erreur PHP
  1825. if (!$_contexte) $contexte = array();
  1826. if (!isset($_contexte[1])) {
  1827. $msg = array('zbug_balise_sans_argument', array('balise' => ' MODELE'));
  1828. erreur_squelette($msg, $p);
  1829. }
  1830. else {
  1831. $nom = $_contexte[1];
  1832. unset($_contexte[1]);
  1833. if (preg_match("/^\s*'[^']*'/s", $nom))
  1834. $nom = "'modeles/" . substr($nom,1);
  1835. else $nom = "'modeles/' . $nom";
  1836. $flag_env = false;
  1837. if (isset($_contexte['env'])){
  1838. $flag_env = true;
  1839. unset($_contexte['env']);
  1840. }
  1841. // Incoherence dans la syntaxe du contexte. A revoir.
  1842. // Reserver la cle primaire de la boucle courante si elle existe
  1843. if (isset($p->boucles[$p->id_boucle]->primary)) {
  1844. $primary = $p->boucles[$p->id_boucle]->primary;
  1845. if (!strpos($primary,',')) {
  1846. $id = champ_sql($primary, $p);
  1847. $_contexte[] = "'$primary'=>".$id;
  1848. $_contexte[] = "'id'=>".$id;
  1849. }
  1850. }
  1851. $_contexte[] = "'recurs'=>(++\$recurs)";
  1852. $connect = '';
  1853. if (isset($p->boucles[$p->id_boucle]))
  1854. $connect = $p->boucles[$p->id_boucle]->sql_serveur;
  1855. $_options = memoriser_contexte_compil($p);
  1856. $_options = "'compil'=>array($_options), 'trim'=>true";
  1857. if (isset($_contexte['ajax'])){
  1858. $_options .= ", ".preg_replace(",=>(.*)$,ims",'=> ($v=(\\1))?$v:true',$_contexte['ajax']);
  1859. unset($_contexte['ajax']);
  1860. }
  1861. $_l = 'array(' . join(",\n\t", $_contexte) .')';
  1862. if ($flag_env) $_l = "array_merge(\$Pile[0],$_l)";
  1863. $page = sprintf(CODE_RECUPERER_FOND, $nom, $_l , $_options, _q($connect));
  1864. $p->code = "\n\t(((\$recurs=(isset(\$Pile[0]['recurs'])?\$Pile[0]['recurs']:0))>=5)? '' :\n\t$page)\n";
  1865. $p->interdire_scripts = false; // securite assuree par le squelette
  1866. }
  1867. return $p;
  1868. }
  1869. /**
  1870. * Compile la balise `#SET` qui affecte une variable locale au squelette
  1871. *
  1872. * Signature : `#SET{cle,valeur}`
  1873. *
  1874. * @balise
  1875. * @link http://www.spip.net/3990 Balises #SET et #GET
  1876. * @see balise_GET_dist()
  1877. * @example
  1878. * ```
  1879. * #SET{nb,5}
  1880. * #GET{nb} // affiche 5
  1881. * ```
  1882. *
  1883. * @param Champ $p
  1884. * Pile au niveau de la balise
  1885. * @return Champ
  1886. * Pile complétée par le code à générer
  1887. **/
  1888. function balise_SET_dist($p){
  1889. $_nom = interprete_argument_balise(1,$p);
  1890. $_val = interprete_argument_balise(2,$p);
  1891. if (!$_nom OR !$_val) {
  1892. $err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'SET'));
  1893. erreur_squelette($err_b_s_a, $p);
  1894. }
  1895. // affectation $_zzz inutile, mais permet de contourner un bug OpCode cache sous PHP 5.5.4
  1896. // cf https://bugs.php.net/bug.php?id=65845
  1897. else $p->code = "vide(\$Pile['vars'][\$_zzz=(string)$_nom] = $_val)";
  1898. $p->interdire_scripts = false; // la balise ne renvoie rien
  1899. return $p;
  1900. }
  1901. /**
  1902. * Compile la balise `#GET` qui récupère une variable locale au squelette
  1903. *
  1904. * Signature : `#GET{cle[,defaut]}`
  1905. *
  1906. * La clé peut obtenir des sous clés séparés par des `/`
  1907. *
  1908. * @balise
  1909. * @link http://www.spip.net/3990 Balises #SET et #GET
  1910. * @see balise_SET_dist()
  1911. * @example
  1912. * ```
  1913. * #SET{nb,5}
  1914. * #GET{nb} affiche 5
  1915. * #GET{nb,3} affiche la valeur de nb, sinon 3
  1916. *
  1917. * #SET{nb,#ARRAY{boucles,3}}
  1918. * #GET{nb/boucles} affiche 3, équivalent à #GET{nb}|table_valeur{boucles}
  1919. * ```
  1920. *
  1921. * @param Champ $p
  1922. * Pile au niveau de la balise
  1923. * @return Champ
  1924. * Pile complétée par le code à générer
  1925. **/
  1926. function balise_GET_dist($p) {
  1927. $p->interdire_scripts = false; // le contenu vient de #SET, donc il est de confiance
  1928. if (function_exists('balise_ENV'))
  1929. return balise_ENV($p, '$Pile["vars"]');
  1930. else
  1931. return balise_ENV_dist($p, '$Pile["vars"]');
  1932. }
  1933. /**
  1934. * Compile la balise `#DOUBLONS` qui redonne les doublons enregistrés
  1935. *
  1936. * - `#DOUBLONS{mots}` ou `#DOUBLONS{mots,famille}`
  1937. * donne l'état des doublons `(MOTS)` à cet endroit
  1938. * sous forme de tableau d'id_mot comme `array(1,2,3,...)`
  1939. * - `#DOUBLONS` tout seul donne la liste brute de tous les doublons
  1940. * - `#DOUBLONS*{mots}` donne la chaine brute `,1,2,3,...`
  1941. * (changera si la gestion des doublons evolue)
  1942. *
  1943. * @balise
  1944. * @link http://www.spip.net/4123
  1945. *
  1946. * @param Champ $p
  1947. * Pile au niveau de la balise
  1948. * @return Champ
  1949. * Pile complétée par le code à générer
  1950. **/
  1951. function balise_DOUBLONS_dist($p) {
  1952. if ($type = interprete_argument_balise(1,$p)) {
  1953. if ($famille = interprete_argument_balise(2,$p))
  1954. $type .= '.' . $famille;
  1955. $p->code = '(isset($doublons['.$type.']) ? $doublons['.$type.'] : "")';
  1956. if (!$p->etoile)
  1957. $p->code = 'array_filter(array_map("intval",explode(",",'
  1958. . $p->code . ')))';
  1959. }
  1960. else
  1961. $p->code = '$doublons';
  1962. $p->interdire_scripts = false;
  1963. return $p;
  1964. }
  1965. /**
  1966. * Compile la balise `#PIPELINE` pour permettre d'insérer des sorties de
  1967. * pipeline dans un squelette
  1968. *
  1969. * @balise
  1970. * @see pipeline()
  1971. * @example
  1972. * ```
  1973. * #PIPELINE{nom}
  1974. * #PIPELINE{nom,données}
  1975. * #PIPELINE{boite_infos,#ARRAY{data,'',args,#ARRAY{type,rubrique,id,#ENV{id_rubrique}}}}
  1976. * ```
  1977. *
  1978. * @param Champ $p
  1979. * Pile au niveau de la balise
  1980. * @return Champ
  1981. * Pile complétée par le code à générer
  1982. **/
  1983. function balise_PIPELINE_dist($p) {
  1984. $_pipe = interprete_argument_balise(1,$p);
  1985. if (!$_pipe) {
  1986. $err_b_s_a = array('zbug_balise_sans_argument', array('balise' => 'PIPELINE'));
  1987. erreur_squelette($err_b_s_a, $p);
  1988. } else {
  1989. $_flux = interprete_argument_balise(2,$p);
  1990. $_flux = $_flux?$_flux:"''";
  1991. $p->code = "pipeline( $_pipe , $_flux )";
  1992. $p->interdire_scripts = false;
  1993. }
  1994. return $p;
  1995. }
  1996. /**
  1997. * Compile la balise `#EDIT` qui ne fait rien dans SPIP
  1998. *
  1999. * Cette balise ne retourne rien mais permet d'indiquer, pour certains plugins
  2000. * qui redéfinissent cette balise, le nom du champ SQL (ou le nom d'un contrôleur)
  2001. * correspondant à ce qui est édité. Cela sert particulièrement au plugin Crayons.
  2002. * Ainsi en absence du plugin, la balise est toujours reconnue (mais n'a aucune action).
  2003. *
  2004. * @balise
  2005. * @link http://www.spip.net/4584
  2006. * @example
  2007. * ```
  2008. * [<div class="#EDIT{texte} texte">(#TEXTE)</div>]
  2009. * ```
  2010. *
  2011. * @param Champ $p
  2012. * Pile au niveau de la balise
  2013. * @return Champ
  2014. * Pile complétée par le code à générer
  2015. **/
  2016. function balise_EDIT_dist($p) {
  2017. $p->code = "''";
  2018. $p->interdire_scripts = false;
  2019. return $p;
  2020. }
  2021. /**
  2022. * Compile la balise `#TOTAL_UNIQUE` qui récupère le nombre d'éléments
  2023. * différents affichés par le filtre `unique`
  2024. *
  2025. * @balise
  2026. * @link http://www.spip.net/4374
  2027. * @see unique()
  2028. * @example
  2029. * ```
  2030. * #TOTAL_UNIQUE affiche le nombre de #BALISE|unique
  2031. * #TOTAL_UNIQUE{famille} afiche le nombre de #BALISE|unique{famille}
  2032. * ```
  2033. *
  2034. * @param Champ $p
  2035. * Pile au niveau de la balise
  2036. * @return Champ
  2037. * Pile complétée par le code à générer
  2038. **/
  2039. function balise_TOTAL_UNIQUE_dist($p) {
  2040. $_famille = interprete_argument_balise(1,$p);
  2041. $_famille = $_famille ? $_famille : "''";
  2042. $p->code = "unique('', $_famille, true)";
  2043. return $p;
  2044. }
  2045. /**
  2046. * Compile la balise `#ARRAY` créant un tableau PHP associatif
  2047. *
  2048. * Crée un `array` PHP à partir d'arguments calculés.
  2049. * Chaque paire d'arguments représente la clé et la valeur du tableau.
  2050. *
  2051. * @balise
  2052. * @link http://www.spip.net/4009
  2053. * @example
  2054. * ```
  2055. * #ARRAY{key1,val1,key2,val2 ...} retourne
  2056. * array( key1 => val1, key2 => val2, ...)
  2057. * ```
  2058. *
  2059. * @param Champ $p
  2060. * Pile au niveau de la balise
  2061. * @return Champ
  2062. * Pile complétée par le code à générer
  2063. **/
  2064. function balise_ARRAY_dist($p) {
  2065. $_code = array();
  2066. $n=1;
  2067. do {
  2068. $_key = interprete_argument_balise($n++,$p);
  2069. $_val = interprete_argument_balise($n++,$p);
  2070. if ($_key AND $_val) $_code[] = "$_key => $_val";
  2071. } while ($_key && $_val);
  2072. $p->code = 'array(' . join(', ',$_code).')';
  2073. $p->interdire_scripts = false;
  2074. return $p;
  2075. }
  2076. /**
  2077. * Compile la balise `#LISTE` qui crée un tableau PHP avec les valeurs, sans préciser les clés
  2078. *
  2079. * @balise
  2080. * @link http://www.spip.net/5547
  2081. * @example
  2082. * ```
  2083. * #LISTE{a,b,c,d,e}
  2084. * ```
  2085. *
  2086. * @param Champ $p
  2087. * Pile au niveau de la balise
  2088. * @return Champ
  2089. * Pile complétée par le code à générer
  2090. */
  2091. function balise_LISTE_dist($p) {
  2092. $_code = array();
  2093. $n=1;
  2094. while ($_val = interprete_argument_balise($n++,$p))
  2095. $_code[] = $_val;
  2096. $p->code = 'array(' . join(', ',$_code).')';
  2097. $p->interdire_scripts = false;
  2098. return $p;
  2099. }
  2100. /**
  2101. * Compile la balise `#AUTORISER` qui teste une autorisation
  2102. *
  2103. * Appelle la fonction `autoriser()` avec les mêmes arguments,
  2104. * et renvoie un espace ' ' si OK (l'action est autorisée),
  2105. * sinon une chaine vide '' (l'action n'est pas autorisée).
  2106. *
  2107. * Cette balise créée un cache par session.
  2108. *
  2109. * Signature : `#AUTORISER{faire[,type[,id[,auteur[,options]]]}`
  2110. *
  2111. * @note
  2112. * La priorité des opérateurs exige && plutot que AND
  2113. *
  2114. * @balise
  2115. * @link http://www.spip.net/3896
  2116. * @see autoriser()
  2117. * @see sinon_interdire_acces()
  2118. * @example
  2119. * ```
  2120. * [(#AUTORISER{modifier,rubrique,#ID_RUBRIQUE}) ... ]
  2121. * [(#AUTORISER{voir,rubrique,#ID_RUBRIQUE}|sinon_interdire_acces)]
  2122. * ```
  2123. *
  2124. * @param Champ $p
  2125. * Pile au niveau de la balise
  2126. * @return Champ
  2127. * Pile complétée par le code à générer
  2128. **/
  2129. function balise_AUTORISER_dist($p) {
  2130. $_code = array();
  2131. $p->descr['session'] = true; // faire un cache par session
  2132. $n=1;
  2133. while ($_v = interprete_argument_balise($n++,$p))
  2134. $_code[] = $_v;
  2135. $p->code = '((function_exists("autoriser")||include_spip("inc/autoriser"))&&autoriser(' . join(', ',$_code).')?" ":"")';
  2136. $p->interdire_scripts = false;
  2137. return $p;
  2138. }
  2139. /**
  2140. * Compile la balise `#PLUGIN` qui permet d’afficher les informations d'un plugin actif
  2141. *
  2142. * @balise
  2143. * @see filtre_info_plugin_dist()
  2144. * @link http://www.spip.net/4591
  2145. * @example
  2146. * ```
  2147. * #PLUGIN Retourne la liste sérialisée des préfixes de plugins actifs
  2148. * #PLUGIN{prefixe} Renvoie true si le plugin avec ce préfixe est actif
  2149. * #PLUGIN{prefixe, x} Renvoie l'information x du plugin (s'il est actif)
  2150. * #PLUGIN{prefixe, tout} Renvoie toutes les informations du plugin (s'il est actif)
  2151. * ```
  2152. *
  2153. * @param Champ $p
  2154. * Pile au niveau de la balise
  2155. * @return Champ
  2156. * Pile complétée par le code à générer
  2157. **/
  2158. function balise_PLUGIN_dist($p) {
  2159. $plugin = interprete_argument_balise(1,$p);
  2160. $plugin = isset($plugin) ? str_replace('\'', '"', $plugin) : '""';
  2161. $type_info = interprete_argument_balise(2,$p);
  2162. $type_info = isset($type_info) ? str_replace('\'', '"', $type_info) : '"est_actif"';
  2163. $f = chercher_filtre('info_plugin');
  2164. $p->code = $f.'('.$plugin.', '.$type_info.')';
  2165. return $p;
  2166. }
  2167. /**
  2168. * Compile la balise `#AIDER` qui permet d’afficher l’icone de l’aide
  2169. * au sein des squelettes.
  2170. *
  2171. * @balise
  2172. * @see inc_aider_dist()
  2173. * @link http://www.spip.net/4733
  2174. * @example
  2175. * ```
  2176. * #AIDER{titre}
  2177. * ```
  2178. *
  2179. * @param Champ $p
  2180. * Pile au niveau de la balise
  2181. * @return Champ
  2182. * Pile complétée par le code à générer
  2183. **/
  2184. function balise_AIDER_dist($p) {
  2185. $_motif = interprete_argument_balise(1,$p);
  2186. $s = "'" . addslashes($p->descr['sourcefile']) . "'";
  2187. $aider = charger_fonction('aider','inc');
  2188. $p->code = "((\$aider=charger_fonction('aider','inc'))?\$aider($_motif,$s, \$Pile[0]):'')";
  2189. return $p;
  2190. }
  2191. /**
  2192. * Compile la balise `#ACTION_FORMULAIRE` qui insère le contexte
  2193. * des formulaires charger / vérifier / traiter avec les hidden de
  2194. * l'URL d'action
  2195. *
  2196. * @balise
  2197. * @see form_hidden()
  2198. * @example
  2199. * ```
  2200. * <form method='post' action='#ENV{action}'><div>
  2201. * #ACTION_FORMULAIRE{#ENV{action}}
  2202. * ```
  2203. *
  2204. * @param Champ $p
  2205. * Pile au niveau de la balise
  2206. * @return Champ
  2207. * Pile complétée par le code à générer
  2208. **/
  2209. function balise_ACTION_FORMULAIRE($p){
  2210. if (!$_url = interprete_argument_balise(1,$p))
  2211. $_url = "@\$Pile[0]['action']";
  2212. if (!$_form = interprete_argument_balise(2,$p))
  2213. $_form = "@\$Pile[0]['form']";
  2214. // envoyer le nom du formulaire que l'on traite
  2215. // transmettre les eventuels args de la balise formulaire
  2216. $p->code = " '<div>' .
  2217. form_hidden($_url) .
  2218. '<input name=\'formulaire_action\' type=\'hidden\'
  2219. value=\'' . $_form . '\' />' .
  2220. '<input name=\'formulaire_action_args\' type=\'hidden\'
  2221. value=\'' . @\$Pile[0]['formulaire_args']. '\' />' .
  2222. (@\$Pile[0]['_hidden']?@\$Pile[0]['_hidden']:'') .
  2223. '</div>'";
  2224. $p->interdire_scripts = false;
  2225. return $p;
  2226. }
  2227. /**
  2228. * Compile la balise `#BOUTON_ACTION` qui génère un bouton d'action en post, ajaxable
  2229. *
  2230. * Cette balise s'utilise à la place des liens `action_auteur`, sous la forme
  2231. *
  2232. * - `#BOUTON_ACTION{libelle,url}`
  2233. * - ou `#BOUTON_ACTION{libelle,url,ajax}` pour que l'action soit ajax comme un lien `class='ajax'`
  2234. * - ou `#BOUTON_ACTION{libelle,url,ajax,message_confirmation}` pour utiliser un message de confirmation
  2235. * - ou encore `#BOUTON_ACTION{libelle[,url[,ajax[,message_confirmation[,title[,callback]]]]]}`
  2236. *
  2237. * @balise
  2238. * @link http://www.spip.net/4583
  2239. * @example
  2240. * ```
  2241. * [(#AUTORISER{reparer,base})
  2242. * [(#BOUTON_ACTION{<:bouton_tenter_recuperation:>,#URL_ECRIRE{base_repair}})]
  2243. * ]
  2244. * ```
  2245. *
  2246. * @param Champ $p
  2247. * Pile au niveau de la balise
  2248. * @return Champ
  2249. * Pile complétée par le code à générer
  2250. */
  2251. function balise_BOUTON_ACTION_dist($p){
  2252. $args = array();
  2253. for ($k=1;$k<=6;$k++){
  2254. $_a = interprete_argument_balise($k,$p);
  2255. if (!$_a) $_a="''";
  2256. $args[] = $_a;
  2257. }
  2258. // supprimer les args vides
  2259. while(end($args)=="''" AND count($args)>2)
  2260. array_pop($args);
  2261. $args = implode(",",$args);
  2262. $bouton_action = chercher_filtre("bouton_action");
  2263. $p->code = "$bouton_action($args)";
  2264. $p->interdire_scripts = false;
  2265. return $p;
  2266. }
  2267. /**
  2268. * Compile la balise `#SLOGAN_SITE_SPIP` qui retourne le slogan du site
  2269. *
  2270. * @balise
  2271. * @example
  2272. * ```
  2273. * [<p id="slogan">(#SLOGAN_SITE_SPIP)</p>]
  2274. * ```
  2275. *
  2276. * @param Champ $p
  2277. * Pile au niveau de la balise
  2278. * @return Champ
  2279. * Pile complétée par le code à générer
  2280. */
  2281. function balise_SLOGAN_SITE_SPIP_dist($p) {
  2282. $p->code = "\$GLOBALS['meta']['slogan_site']";
  2283. #$p->interdire_scripts = true;
  2284. return $p;
  2285. }
  2286. /**
  2287. * Compile la balise `#HTML5` indiquant si l'espace public peut utiliser du HTML5
  2288. *
  2289. * Renvoie `' '` si le webmestre souhaite que SPIP génère du code (X)HTML5 sur
  2290. * le site public, et `''` si le code doit être strictement compatible HTML4
  2291. *
  2292. * @balise
  2293. * @uses html5_permis()
  2294. * @example
  2295. * ```
  2296. * [(#HTML5) required="required"]
  2297. * <input[ (#HTML5|?{type="email",type="text"})] ... />
  2298. * ```
  2299. *
  2300. * @param Champ $p
  2301. * Pile au niveau de la balise
  2302. * @return Champ
  2303. * Pile complétée par le code à générer
  2304. */
  2305. function balise_HTML5_dist($p) {
  2306. $p->code = html5_permis() ? "' '" : "''";
  2307. $p->interdire_scripts = false;
  2308. return $p;
  2309. }
  2310. /**
  2311. * Compile la balise `#TRI` permettant d'afficher un lien de changement d'ordre de tri
  2312. * d'une colonne de la boucle
  2313. *
  2314. * La balise `#TRI{champ[,libelle]}` champ prend `>` ou `<` pour afficher
  2315. * le lien de changement de sens croissant ou decroissant (`>` `<` indiquent
  2316. * un sens par une flèche)
  2317. *
  2318. * @balise
  2319. * @example
  2320. * ```
  2321. * <th>[(#TRI{titre,<:info_titre:>,ajax})]</th>
  2322. * ```
  2323. *
  2324. * @param Champ $p
  2325. * Pile au niveau de la balise
  2326. * @param string $liste
  2327. * Inutilisé
  2328. * @return Champ
  2329. * Pile complétée par le code à générer
  2330. */
  2331. function balise_TRI_dist($p, $liste='true') {
  2332. $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
  2333. // s'il n'y a pas de nom de boucle, on ne peut pas trier
  2334. if ($b === '') {
  2335. erreur_squelette(
  2336. _T('zbug_champ_hors_boucle',
  2337. array('champ' => '#TRI')
  2338. ), $p->id_boucle);
  2339. $p->code = "''";
  2340. return $p;
  2341. }
  2342. $boucle = $p->boucles[$b];
  2343. // s'il n'y a pas de tri_champ, c'est qu'on se trouve
  2344. // dans un boucle recursive ou qu'on a oublie le critere {tri}
  2345. if (!isset($boucle->modificateur['tri_champ'])) {
  2346. erreur_squelette(
  2347. _T('zbug_tri_sans_critere',
  2348. array('champ' => '#TRI')
  2349. ), $p->id_boucle);
  2350. $p->code = "''";
  2351. return $p;
  2352. }
  2353. $_champ = interprete_argument_balise(1,$p);
  2354. // si pas de champ, renvoyer le critere de tri utilise
  2355. if (!$_champ){
  2356. $p->code = $boucle->modificateur['tri_champ'];
  2357. return $p;
  2358. }
  2359. // forcer la jointure si besoin, et si le champ est statique
  2360. if (preg_match(",^'([\w.]+)'$,i",$_champ,$m)){
  2361. index_pile($b, $m[1], $p->boucles);
  2362. }
  2363. $_libelle = interprete_argument_balise(2,$p);
  2364. $_libelle = $_libelle?$_libelle:$_champ;
  2365. $_class = interprete_argument_balise(3,$p);
  2366. // si champ = ">" c'est un lien vers le tri croissant : de gauche a droite ==> 1
  2367. // si champ = "<" c'est un lien vers le tri decroissant : (sens inverse) == -1
  2368. $_issens = "in_array($_champ,array('>','<'))";
  2369. $_sens = "(strpos('< >',$_champ)-1)";
  2370. $_variable = "((\$s=$_issens)?'sens':'tri').".$boucle->modificateur['tri_nom'];
  2371. $_url = "parametre_url(self(),$_variable,\$s?$_sens:$_champ)";
  2372. $_url = "parametre_url($_url,'var_memotri',strncmp(".$boucle->modificateur['tri_nom'].",'session',7)==0?$_variable:'')";
  2373. $_on = "\$s?(".$boucle->modificateur['tri_sens']."==$_sens".'):('.$boucle->modificateur['tri_champ']."==$_champ)";
  2374. $p->code = "lien_ou_expose($_url,$_libelle,$_on".($_class?",$_class":"").")";
  2375. //$p->code = "''";
  2376. $p->interdire_scripts = false;
  2377. return $p;
  2378. }
  2379. /**
  2380. * Compile la balise `#SAUTER{n}` qui permet de sauter en avant n resultats dans une boucle
  2381. *
  2382. * La balise modifie le compteur courant de la boucle, mais pas les autres
  2383. * champs qui restent les valeurs de la boucle avant le saut. Il est donc
  2384. * preferable d'utiliser la balise juste avant la fermeture `</BOUCLE>`
  2385. *
  2386. * L'argument `n` doit être supérieur à zéro sinon la balise ne fait rien
  2387. *
  2388. * @balise
  2389. *
  2390. * @param Champ $p
  2391. * Pile au niveau de la balise
  2392. * @return Champ
  2393. * Pile complétée par le code à générer
  2394. */
  2395. function balise_SAUTER_dist($p){
  2396. $id_boucle = $p->id_boucle;
  2397. $boucle = $p->boucles[$id_boucle];
  2398. if (!$boucle) {
  2399. $msg = array('zbug_champ_hors_boucle', array('champ' => '#SAUTER'));
  2400. erreur_squelette($msg, $p);
  2401. }
  2402. else {
  2403. $_saut = interprete_argument_balise(1,$p);
  2404. $_compteur = "\$Numrows['$id_boucle']['compteur_boucle']";
  2405. $_total = "\$Numrows['$id_boucle']['total']";
  2406. $p->code = "vide($_compteur=\$iter->skip($_saut,$_total))";
  2407. }
  2408. $p->interdire_scripts = false;
  2409. return $p;
  2410. }
  2411. /**
  2412. * Compile la balise `#PUBLIE` qui indique si un objet est publié ou non
  2413. *
  2414. * @balise
  2415. * @link http://www.spip.net/5545
  2416. * @see objet_test_si_publie()
  2417. * @example
  2418. * ```
  2419. * #PUBLIE : porte sur la boucle en cours
  2420. * [(#PUBLIE{article, 3}|oui) ... ] : pour l'objet indiqué
  2421. * ```
  2422. *
  2423. * @param Champ $p
  2424. * Pile au niveau de la balise
  2425. * @return Champ
  2426. * Pile complétée par le code à générer
  2427. */
  2428. function balise_PUBLIE_dist($p) {
  2429. if (!$_type = interprete_argument_balise(1,$p)){
  2430. $_type = _q($p->type_requete);
  2431. $_id = champ_sql($p->boucles[$p->id_boucle]->primary,$p);
  2432. }
  2433. else
  2434. $_id = interprete_argument_balise(2,$p);
  2435. $connect = $p->boucles[$p->id_boucle]->sql_serveur;
  2436. $p->code = "(objet_test_si_publie(".$_type.",intval(".$_id."),"._q($connect).")?' ':'')";
  2437. $p->interdire_scripts = false;
  2438. return $p;
  2439. }
  2440. /**
  2441. * Compile la balise `#PRODUIRE` qui génère un fichier statique à partir
  2442. * d'un squelette SPIP
  2443. *
  2444. * Le format du fichier sera extrait de la pre-extension du squelette
  2445. * (typo.css.html, messcripts.js.html)
  2446. * ou par l'argument `format=css` ou `format=js` passé en argument.
  2447. *
  2448. * S'il n'y a pas de format détectable, on utilise `.html`, comme pour les squelettes.
  2449. *
  2450. * La syntaxe de la balise est la même que celle de `#INCLURE`.
  2451. *
  2452. * @balise
  2453. * @see balise_INCLURE_dist()
  2454. * @link http://www.spip.net/5505
  2455. * @example
  2456. * ```
  2457. * <link rel="stylesheet" type="text/css" href="#PRODUIRE{fond=css/macss.css,couleur=ffffff}" />
  2458. * ```
  2459. *
  2460. * @param Champ $p
  2461. * Pile au niveau de la balise
  2462. * @return Champ
  2463. * Pile complétée par le code à générer
  2464. */
  2465. function balise_PRODUIRE_dist($p){
  2466. $balise_inclure = charger_fonction('INCLURE','balise');
  2467. $p = $balise_inclure($p);
  2468. $p->code = str_replace('recuperer_fond(','produire_fond_statique(',$p->code);
  2469. return $p;
  2470. }
  2471. /**
  2472. * Compile la balise `#LARGEUR_ECRAN` qui définit la largeur d'écran
  2473. * dans l'espace privé
  2474. *
  2475. * @balise
  2476. * @example
  2477. * ```
  2478. * #LARGEUR_ECRAN{pleine_largeur}
  2479. * ```
  2480. *
  2481. * @param Champ $p
  2482. * Pile au niveau de la balise
  2483. * @return Champ
  2484. * Pile complétée par le code à générer
  2485. */
  2486. function balise_LARGEUR_ECRAN_dist($p){
  2487. $_class = interprete_argument_balise(1,$p);
  2488. if (!$_class) $_class='null';
  2489. $p->code = "(is_string($_class)?vide(\$GLOBALS['largeur_ecran']=$_class):(isset(\$GLOBALS['largeur_ecran'])?\$GLOBALS['largeur_ecran']:''))";
  2490. return $p;
  2491. }
  2492. ?>