notes.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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. if (!defined("_ECRIRE_INC_VERSION")) return;
  12. //
  13. // Notes de bas de page
  14. //
  15. if (!defined('_NOTES_OUVRE_REF')) define('_NOTES_OUVRE_REF','<span class="spip_note_ref">&nbsp;[');
  16. if (!defined('_NOTES_FERME_REF')) define('_NOTES_FERME_REF',']</span>');
  17. if (!defined('_NOTES_OUVRE_NOTE')) define('_NOTES_OUVRE_NOTE','<span class="spip_note_ref">[');
  18. if (!defined('_NOTES_FERME_NOTE')) define('_NOTES_FERME_NOTE',']&nbsp;</span>');
  19. if (!defined('_NOTES_RACCOURCI')) define('_NOTES_RACCOURCI', ',\[\[(\s*(<([^>\'"]*)>)?(.*?))\]\],msS');
  20. // argument = true: empiler l'etat courant, initialiser un nouvel etat
  21. // argument = false: restaurer l'etat precedent, denonce un etat courant perdu
  22. // argument chaine, on y recherche les notes et on les renvoie en tableau
  23. // argument tableau, texte de notes a rajouter dans ce qu'on a deja
  24. // le dernier cas retourne la composition totale
  25. // en particulier, envoyer un tableau vide permet de tout recuperer
  26. // C'est stocke dans la globale $les_notes, mais pas besoin de le savoir
  27. function inc_notes_dist($arg,$operation='traiter', $ignorer_autobr=false)
  28. {
  29. static $pile = array();
  30. static $next_marqueur = 1;
  31. static $marqueur = 1;
  32. global $les_notes, $compt_note, $notes_vues;
  33. switch ($operation){
  34. case 'traiter':
  35. if (is_array($arg)) return traiter_les_notes($arg,$ignorer_autobr);
  36. else
  37. return traiter_raccourci_notes($arg, $marqueur>1?$marqueur:'');
  38. break;
  39. case 'empiler':
  40. if ($compt_note==0)
  41. // si le marqueur n'a pas encore ete utilise, on le recycle dans la pile courante
  42. array_push($pile, array(@$les_notes, @$compt_note, $notes_vues,0));
  43. else {
  44. // sinon on le stocke au chaud, et on en cree un nouveau
  45. array_push($pile, array(@$les_notes, @$compt_note, $notes_vues,$marqueur));
  46. $next_marqueur++; // chaque fois qu'on rempile on incremente le marqueur general
  47. $marqueur = $next_marqueur; // et on le prend comme marqueur courant
  48. }
  49. $les_notes = '';
  50. $compt_note = 0;
  51. break;
  52. case 'depiler':
  53. #$prev_notes = $les_notes;
  54. if (strlen($les_notes)) spip_log("notes perdues");
  55. // si le marqueur n'a pas servi, le liberer
  56. if (!strlen($les_notes) AND $marqueur==$next_marqueur)
  57. $next_marqueur--;
  58. // on redepile tout suite a une fin d'inclusion ou d'un affichage des notes
  59. list($les_notes, $compt_note, $notes_vues, $marqueur) = array_pop($pile);
  60. #$les_notes .= $prev_notes;
  61. // si pas de marqueur attribue, on le fait
  62. if (!$marqueur){
  63. $next_marqueur++; // chaque fois qu'on rempile on incremente le marqueur general
  64. $marqueur = $next_marqueur; // et on le prend comme marqueur courant
  65. }
  66. break;
  67. case 'sauver_etat':
  68. if ($compt_note OR $marqueur>1 OR $next_marqueur>1)
  69. return array($les_notes, $compt_note, $notes_vues, $marqueur,$next_marqueur);
  70. else
  71. return ''; // rien a sauver
  72. break;
  73. case 'restaurer_etat':
  74. if ($arg AND is_array($arg)) // si qqchose a restaurer
  75. list($les_notes, $compt_note, $notes_vues, $marqueur,$next_marqueur) = $arg;
  76. break;
  77. case 'contexter_cache':
  78. if ($compt_note OR $marqueur>1 OR $next_marqueur>1)
  79. return array("$compt_note:$marqueur:$next_marqueur");
  80. else
  81. return '';
  82. break;
  83. case 'reset_all': // a n'utiliser qu'a fins de test
  84. if (strlen($les_notes)) spip_log("notes perdues [reset_all]");
  85. $pile = array();
  86. $next_marqueur = 1;
  87. $marqueur = 1;
  88. $les_notes = '';
  89. $compt_note = 0;
  90. $notes_vues = array();
  91. break;
  92. }
  93. }
  94. function traiter_raccourci_notes($letexte, $marqueur_notes)
  95. {
  96. global $compt_note, $notes_vues;
  97. if (strpos($letexte, '[[') === false
  98. OR !preg_match_all(_NOTES_RACCOURCI, $letexte, $m, PREG_SET_ORDER))
  99. return array($letexte, array());
  100. // quand il y a plusieurs series de notes sur une meme page
  101. $mn = !$marqueur_notes ? '' : ($marqueur_notes.'-');
  102. $mes_notes = array();
  103. foreach ($m as $r) {
  104. list($note_source, $note_all, $ref, $nom, $note_texte) = $r;
  105. // reperer une note nommee, i.e. entre chevrons
  106. // On leve la Confusion avec une balise en regardant
  107. // si la balise fermante correspondante existe
  108. // Cas pathologique: [[ <a> <a href="x">x</a>]]
  109. if (!(isset($nom) AND $ref
  110. AND ((strpos($note_texte, '</' . $nom .'>') === false)
  111. OR preg_match(",<$nom\W.*</$nom>,", $note_texte)))) {
  112. $nom = ++$compt_note;
  113. $note_texte = $note_all;
  114. }
  115. // eliminer '%' pour l'attribut id
  116. $ancre = $mn . str_replace('%','_', rawurlencode($nom));
  117. // ne mettre qu'une ancre par appel de note (XHTML)
  118. $att = ($notes_vues[$ancre]++) ? '' : " id='nh$ancre'";
  119. // creer le popup 'title' sur l'appel de note
  120. // propre est couteux => nettoyer_raccourcis_typo
  121. if ($title = supprimer_tags(nettoyer_raccourcis_typo($note_texte))) {
  122. $title = " title='" . couper($title,80) . "'";
  123. }
  124. // ajouter la note aux notes precedentes
  125. if ($note_texte) {
  126. $mes_notes[]= array($ancre, $nom, $note_texte);
  127. }
  128. // dans le texte, mettre l'appel de note a la place de la note
  129. if ($nom) $nom = _NOTES_OUVRE_REF."<a href='#nb$ancre' class='spip_note' rel='footnote'$title$att>$nom</a>"._NOTES_FERME_REF;
  130. $pos = strpos($letexte, $note_source);
  131. // supprimer les ' ' ou 'nbsp;' avant un appel de note
  132. $avant = preg_replace(',( |&nbsp;|'.chr(194).chr(160).')+$,S', '', substr($letexte, 0, $pos));
  133. $letexte = $avant
  134. . code_echappement($nom)
  135. . substr($letexte, $pos + strlen($note_source));
  136. }
  137. return array($letexte, $mes_notes);
  138. }
  139. // http://code.spip.net/@traiter_les_notes
  140. function traiter_les_notes($notes,$ignorer_autobr) {
  141. $mes_notes = '';
  142. if ($notes) {
  143. $title = _T('info_notes');
  144. foreach ($notes as $r) {
  145. list($ancre, $nom, $texte) = $r;
  146. $atts = " href='#nh$ancre' class='spip_note' title='$title $ancre' rev='footnote'";
  147. $mes_notes .= "\n\n"
  148. . "<div id='nb$ancre'><p". ($GLOBALS['class_spip'] ? " class='spip_note'" : "") .">"
  149. . code_echappement($nom
  150. ? _NOTES_OUVRE_NOTE."<a".$atts.">$nom</a>"._NOTES_FERME_NOTE
  151. : '')
  152. . trim($texte)
  153. .'</div>';
  154. }
  155. if ($ignorer_autobr)
  156. $mes_notes = _AUTOBR_IGNORER.$mes_notes;
  157. $mes_notes = propre($mes_notes);
  158. }
  159. return ($GLOBALS['les_notes'] .= $mes_notes);
  160. }
  161. ?>