PageRenderTime 60ms CodeModel.GetById 25ms RepoModel.GetById 0ms 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

Large files files are truncated, but you can click here to view the full 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 sur…

Large files files are truncated, but you can click here to view the full file