source: spip-zone/_core_/plugins/textwheel/inc/notes.php

Last change on this file was 113294, checked in by spip.franck@…, 4 months ago

Il parait que le futur c'est maintenant :-D

File size: 7.5 KB
Line 
1<?php
2
3/***************************************************************************\
4 *  SPIP, Systeme de publication pour l'internet                           *
5 *                                                                         *
6 *  Copyright (c) 2001-2019                                                *
7 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
8 *                                                                         *
9 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
10 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
11\***************************************************************************/
12
13/**
14 * Gestion des notes de bas de page
15 *
16 * @package SPIP\Textwheel\Notes
17 **/
18
19if (!defined("_ECRIRE_INC_VERSION")) {
20        return;
21}
22
23//
24// Notes de bas de page
25//
26if (!defined('_NOTES_OUVRE_REF')) {
27        define('_NOTES_OUVRE_REF', '<span class="spip_note_ref">&nbsp;[');
28}
29if (!defined('_NOTES_FERME_REF')) {
30        define('_NOTES_FERME_REF', ']</span>');
31}
32if (!defined('_NOTES_OUVRE_NOTE')) {
33        define('_NOTES_OUVRE_NOTE', '<span class="spip_note_ref">[');
34}
35if (!defined('_NOTES_FERME_NOTE')) {
36        define('_NOTES_FERME_NOTE', ']&nbsp;</span>');
37}
38if (!defined('_NOTES_RACCOURCI')) {
39        define('_NOTES_RACCOURCI', ',\[\[(\s*(<([^>\'"]*)>)?(.*?))\]\],msS');
40}
41
42
43/**
44 * Empile ou dépile des notes de bas de page
45 *
46 * Point d'entrée pour la gestion des notes.
47 *
48 * @note
49 *     C'est stocké dans la globale `$les_notes`, mais pas besoin de le savoir
50 * @param bool|string|array $arg
51 *     Argument :
52 *
53 *     - true : empiler l'etat courant, initialiser un nouvel état
54 *     - false : restaurer l'état précédent, dénonce un état courant perdu
55 *     - chaîne : on y recherche les notes et on les renvoie en tableau
56 *     - tableau : texte de notes à rajouter dans ce qu'on a déjà
57 *
58 *     Ce dernier cas retourne la composition totale, en particulier,
59 *     envoyer un tableau vide permet de tout récupérer.
60 * @param string $operation
61 *     En complément du format attendu dans `$arg`, on indique ici
62 *     le type d'oopétation à réaliser (traiter | empiler | depiler |
63 *     sauver_etat | restaurer_etat | contexter_cache)
64 * @param bool $ignorer_autobr
65 *     True pour ne pas prendre en compte les retours à la ligne comme
66 *     des tags br (mais 2 à la suite font un paragraphe tout de même).
67 * @return string|array
68 **/
69function inc_notes_dist($arg, $operation = 'traiter', $ignorer_autobr = false) {
70        static $pile = array();
71        static $next_marqueur = 1;
72        static $marqueur = 1;
73        global $les_notes, $compt_note, $notes_vues;
74        switch ($operation) {
75                case 'traiter':
76                        if (is_array($arg)) {
77                                return traiter_les_notes($arg, $ignorer_autobr);
78                        } else {
79                                return traiter_raccourci_notes($arg, $marqueur > 1 ? $marqueur : '');
80                        }
81                        break;
82                case 'empiler':
83                        if ($compt_note == 0) // si le marqueur n'a pas encore ete utilise, on le recycle dans la pile courante
84                        {
85                                array_push($pile, array(@$les_notes, @$compt_note, $notes_vues, 0));
86                        } else {
87                                // sinon on le stocke au chaud, et on en cree un nouveau
88                                array_push($pile, array(@$les_notes, @$compt_note, $notes_vues, $marqueur));
89                                $next_marqueur++; // chaque fois qu'on rempile on incremente le marqueur general
90                                $marqueur = $next_marqueur; // et on le prend comme marqueur courant
91                        }
92                        $les_notes = '';
93                        $compt_note = 0;
94                        break;
95                case 'depiler':
96                        #$prev_notes = $les_notes;
97                        if (strlen($les_notes)) {
98                                spip_log("notes perdues");
99                        }
100                        // si le marqueur n'a pas servi, le liberer
101                        if (!strlen($les_notes) and $marqueur == $next_marqueur) {
102                                $next_marqueur--;
103                        }
104                        // on redepile tout suite a une fin d'inclusion ou d'un affichage des notes
105                        list($les_notes, $compt_note, $notes_vues, $marqueur) = array_pop($pile);
106                        #$les_notes .= $prev_notes;
107                        // si pas de marqueur attribue, on le fait
108                        if (!$marqueur) {
109                                $next_marqueur++; // chaque fois qu'on rempile on incremente le marqueur general
110                                $marqueur = $next_marqueur; // et on le prend comme marqueur courant
111                        }
112                        break;
113                case 'sauver_etat':
114                        if ($compt_note or $marqueur > 1 or $next_marqueur > 1) {
115                                return array($les_notes, $compt_note, $notes_vues, $marqueur, $next_marqueur);
116                        } else {
117                                return '';
118                        } // rien a sauver
119                        break;
120                case 'restaurer_etat':
121                        if ($arg and is_array($arg)) // si qqchose a restaurer
122                        {
123                                list($les_notes, $compt_note, $notes_vues, $marqueur, $next_marqueur) = $arg;
124                        }
125                        break;
126                case 'contexter_cache':
127                        if ($compt_note or $marqueur > 1 or $next_marqueur > 1) {
128                                return array("$compt_note:$marqueur:$next_marqueur");
129                        } else {
130                                return '';
131                        }
132                        break;
133                case 'reset_all': // a n'utiliser qu'a fins de test
134                        if (strlen($les_notes)) {
135                                spip_log("notes perdues [reset_all]");
136                        }
137                        $pile = array();
138                        $next_marqueur = 1;
139                        $marqueur = 1;
140                        $les_notes = '';
141                        $compt_note = 0;
142                        $notes_vues = array();
143                        break;
144        }
145}
146
147
148function traiter_raccourci_notes($letexte, $marqueur_notes) {
149        global $compt_note, $notes_vues;
150
151        if (strpos($letexte, '[[') === false
152                or !preg_match_all(_NOTES_RACCOURCI, $letexte, $m, PREG_SET_ORDER)
153        ) {
154                return array($letexte, array());
155        }
156
157        // quand il y a plusieurs series de notes sur une meme page
158        $mn = !$marqueur_notes ? '' : ($marqueur_notes . '-');
159        $mes_notes = array();
160        foreach ($m as $r) {
161                list($note_source, $note_all, $ref, $nom, $note_texte) = $r;
162
163                // reperer une note nommee, i.e. entre chevrons
164                // On leve la Confusion avec une balise en regardant
165                // si la balise fermante correspondante existe
166                // Cas pathologique:   [[ <a> <a href="x">x</a>]]
167
168                if (!(isset($nom) and $ref
169                        and ((strpos($note_texte, '</' . $nom . '>') === false)
170                                or preg_match(",<$nom\W.*</$nom>,", $note_texte)))
171                ) {
172                        $nom = ++$compt_note;
173                        $note_texte = $note_all;
174                }
175
176                // eliminer '%' pour l'attribut id
177                $ancre = $mn . str_replace('%', '_', rawurlencode($nom));
178
179                // ne mettre qu'une ancre par appel de note (XHTML)
180                if (!isset($notes_vues[$ancre])) {
181                        $notes_vues[$ancre] = 0;
182                }
183                $att = ($notes_vues[$ancre]++) ? '' : " id='nh$ancre'";
184
185                // creer le popup 'title' sur l'appel de note
186                // propre est couteux => nettoyer_raccourcis_typo
187                if ($title = supprimer_tags(nettoyer_raccourcis_typo($note_texte))) {
188                        $title = " title='" . couper($title, 80) . "'";
189                }
190
191                // ajouter la note aux notes precedentes
192                if ($note_texte) {
193                        $mes_notes[] = array($ancre, $nom, $note_texte);
194                }
195
196                // dans le texte, mettre l'appel de note a la place de la note
197                if ($nom) {
198                        $nom = _NOTES_OUVRE_REF . "<a href='#nb$ancre' class='spip_note' rel='appendix'$title$att>$nom</a>" . _NOTES_FERME_REF;
199                }
200
201                $pos = strpos($letexte, $note_source);
202                $letexte = rtrim(substr($letexte, 0, $pos), ' ')
203                        . code_echappement($nom)
204                        . substr($letexte, $pos + strlen($note_source));
205
206        }
207
208        return array($letexte, $mes_notes);
209}
210
211
212// https://code.spip.net/@traiter_les_notes
213function traiter_les_notes($notes, $ignorer_autobr) {
214        $mes_notes = '';
215        if ($notes) {
216                $title = _T('info_notes');
217                foreach ($notes as $r) {
218                        list($ancre, $nom, $texte) = $r;
219                        $atts = " href='#nh$ancre' class='spip_note' title='$title $ancre' rev='appendix'";
220                        $mes_notes .= "\n\n"
221                                . "<div id='nb$ancre'><p" . ($GLOBALS['class_spip'] ? " class='spip_note'" : "") . ">"
222                                . code_echappement($nom
223                                        ? _NOTES_OUVRE_NOTE . "<a" . $atts . ">$nom</a>" . _NOTES_FERME_NOTE
224                                        : '')
225                                . trim($texte)
226                                . '</div>';
227                }
228                if ($ignorer_autobr) {
229                        $mes_notes = _AUTOBR_IGNORER . $mes_notes;
230                }
231                $mes_notes = propre($mes_notes);
232        }
233
234        return ($GLOBALS['les_notes'] .= $mes_notes);
235}
Note: See TracBrowser for help on using the repository browser.