source: spip-zone/_plugins_/table_matieres/trunk/tablematieres_fonctions.php @ 72623

Last change on this file since 72623 was 72623, checked in by kent1@…, 7 years ago

On revient sur le commit http://zone.spip.org/trac/spip-zone/changeset/54326 qui comme le disait cedric posait des problèmes de cache : cf http://contrib.spip.net/Table-des-Matieres#forum464853

Par contre, résolution du problème des urls arbos en traitant en js les urls qui posaient problème à cause du base href

On passe tous les éléments js en dur dans un fichier js externe en évitant de casser les retours de crayons en SPIP 3.0.x à cause des document.write

On ajoute une option tdm_flottante dans le formulaire de configuration (cf : http://contrib.spip.net/Table-des-Matieres#forum467667) à tester

Version 2.2.0

File size: 8.4 KB
Line 
1<?php
2
3if (!defined("_ECRIRE_INC_VERSION")) return;
4
5// tester la presence de CFG
6$tm = @unserialize($GLOBALS['meta']['table_matieres']);
7
8define('_AUTO_ANCRE', isset($tm['auto']) ? $tm['auto'] : 'oui');
9define('_LG_ANCRE', isset($tm['lg']) ? $tm['lg'] : 35);
10define('_SEP_ANCRE', isset($tm['sep']) ? $tm['sep'] : '-');
11define('_MIN_ANCRE', isset($tm['min']) ? $tm['min'] : 3);
12define('_RETOUR_TDM', '<a href="#tdm" class="tdm"><img src="' .
13        find_in_path('images/tdm.png') . 
14        '" /></a>');
15
16/**
17 * Fonction d'API.
18 *
19 * Elle reçoit un texte ayant encore les raccourcis SPIP
20 * et donc les codes des éventuels intertitres tel que "{{{ intertitre }}}".
21 *
22 * Elle ajoute une table des matières en entête du texte (par défaut)
23 * Et retourne le texte avec les intertitres complétés d'un lien de retour
24 * vers le sommaire automatique.
25 *
26 * En option, on peut demander à la fonction de ne retourner
27 * QUE la table des matières.
28 *
29 * @param string $texte Texte en entrée
30 * @param string $retourner Retourner quoi ? (tout, tdm, texte)
31 * @return string       Texte avec une table des matières
32 */
33function table_matieres($texte, $retourner = 'tout') {
34        static $table_matieres = false;
35
36        if (!$texte) {
37                return $texte;
38        }
39        if (!$table_matieres) {
40                $table_matieres = charger_fonction('table_matieres', 'inc');
41        }
42        return $table_matieres($texte, $retourner);
43}
44
45/**
46 * Fonction principale du plugin
47 * cf. description sur la fonction d'appel table_matieres()
48 *
49 * @param string $texte Texte en entrée
50 * @param bool $retourner Retourner quoi ?
51 *              - 'tout' : tout (tdm + texte)
52 *              - 'tdm' : la table des matieres
53 *              - 'texte' : le texte (et les ancres)
54 * @return string       Texte avec une table des matières
55 */
56function inc_table_matieres_dist($texte, $retourner = 'tout') {
57
58        // sauvegarde pour ne pas calculer 2 fois les mêmes choses
59        static $textes = array();
60        $md5 = md5($texte);
61
62        if (!in_array($retourner, array('tout', 'tdm', 'texte'))) {
63                $retourner = 'tout';
64                spip_log("Erreur de parametre sur la fonction table_matieres.");
65        }
66       
67        // deja calculé ? on s'en retourne.
68        if (isset($textes[$md5])) {
69                if ($retourner == 'tout') {
70                        return $textes[$md5]['tdm'] . $textes[$md5]['texte'];
71                }
72                return $textes[$md5][$retourner];
73        }
74
75        // protection des expressions qui ne font pas partie de la table des matières
76        //
77        // le 3e à true pour ne pas utiliser les fonctions d'echappement predefinis
78        // et garder les textes tels quels (ex: <code><balise></code>)
79        // sinon la transformation est effectuee 2 fois.
80        $texte_protege = echappe_html($texte, 'TDM', true);
81
82        // vider les caches d'intertitres trouves
83        tdm_vider_intertitres();
84       
85        // dans un premier temps, on traverse le texte à la recherche d'intertitres.
86        // et pour chaque intertitre trouvé, on ajoute un marqueur qui
87        // permettra d'ajouter un lien de retour vers l'intertitre.
88        // On réalise l'opétation pour chaque type d'intertitre : {{{}}}, ===, {2{...
89        // si leurs définitions sont présentes.
90        foreach( tdm_remplacements_intertitres() as $regexp => $callback ) {
91                $texte_protege = preg_replace_callback($regexp, $callback, $texte_protege);
92        }
93
94        // si l'on a trouvé moins d'intertitres que le minimum vital (configurable)
95        // on rétablit le texte d'origine et on s'en va !
96        $intertitres = tdm_get_intertitres();
97        if ( count($intertitres) < _MIN_ANCRE ) {
98                $textes[$md5] = array(
99                        'tdm' => '',
100                        'texte' => $texte
101                );
102                if ($retourner == 'tout') {
103                        return $textes[$md5]['tdm'] . $textes[$md5]['texte'];
104                }
105                return $textes[$md5][$retourner];
106        }
107       
108        // dévérouillage des protections
109        $texte = echappe_retour($texte_protege, 'TDM');
110
111        // calculer la table des matières
112        $tdm = tdm_generer_table_des_matieres($intertitres);
113
114        // ajouter les icones de retour vers la table des matieres
115        $texte = tdm_ajouter_liens_retour_table_matieres($texte);
116
117        // sauver
118        $textes[$md5] = array(
119                'tdm' => $tdm,
120                'texte' => $texte
121        );
122
123        // c'est fini !
124        if ($retourner == 'tout') {
125                return $textes[$md5]['tdm'] . $textes[$md5]['texte'];
126        }
127        return $textes[$md5][$retourner];
128}
129
130/**
131 * Retourne la liste des raccourcis d'intertitres / fonction de remplacements
132 * pour la recherche d'intertitres.
133 *
134 * Cette fonction pourra être étendue
135 * par un pipeline ou une globale
136 *
137 * @return arrray  expression régulière / fonction de remplacement
138 */
139function tdm_remplacements_intertitres() {
140        return array(
141                "/{{{(.*)}}}/UmsS" => 'tdm_remplacement_raccourcis_standard_callback'
142        );
143}
144
145/**
146 * Intertitre en entrée.
147 * L'analyse, stocke l'information et retourne l'intertitre complété
148 *
149 * @param string $matches       Captures de l'expression régulière
150 * @return l'intertitre complété du code de lien de retour.
151 */
152function tdm_remplacement_raccourcis_standard_callback($matches) {
153        list($titre, $url) = tdm_calculer_titre( $matches[1] ); // intertitre dans /1
154        $url = tdm_stocker_intertitre($url, $titre);
155        return '{{{ [' . $url . '<-] ' . $matches[1] . ' @@RETOUR_TDM@@ }}}';
156}
157
158/**
159 * Calcule le titre et l'url de l'ancre
160 * a partir d'un intertitre donné
161 *
162 * @param string $intertitre
163 * @return array titre/url
164 */
165function tdm_calculer_titre($intertitre) {
166        $titre = supprimer_tags(typo($intertitre));
167        $titre = preg_replace(",\n[_\s]*,", " ", $titre);
168        $url = translitteration($titre);
169        $url = @preg_replace(',[[:punct:][:space:]]+,u', ' ', $url);
170
171        // S'il reste des caracteres non latins, utiliser l'id a la place
172        if (preg_match(",[^a-zA-Z0-9 ],", $url)) {
173                $url = "ancre$cId";
174        }
175        else {
176                $mots = explode(' ', $url);
177                $url = '';
178                foreach ($mots as $mot) {
179                        if (!$mot) continue;
180                        $url2 = $url._SEP_ANCRE.$mot;
181                        if (strlen($url2) > _LG_ANCRE) {
182                                break;
183                        }
184                        $url = $url2;
185                }
186                $url = substr($url, 1);
187                if (strlen($url) < 2) $url = "ancre$cId";
188        }
189
190        return array($titre, strtolower($url));
191}
192
193/**
194 * Remet à zéro la liste des intertitres trouvés
195 */
196function tdm_vider_intertitres() {
197        tdm_stocker_intertitre('', '', true);
198}
199
200/**
201 * Retourne la liste des intertitres trouvés
202 * @return array        Liste des intertitres (url/titre)
203 */
204function tdm_get_intertitres() {
205        return tdm_stocker_intertitre('');
206}
207
208/**
209 * Stocke les intertitres trouves.
210 * Si une url est deja presente, on identifie l'url d'un numero
211 *
212 * Passer une url vide pour recuperer le tableau.
213 *
214 * @param string $url   url de l'ancre
215 * @param string $titre titre de l'ancre
216 * @param bool $vider   effacer les sauvegarde ?
217 * @return
218 */
219function tdm_stocker_intertitre($url='', $titre='', $vider = false) {
220        static $table = array();
221        static $cpt = 0;
222        if($vider_table) return ($table = array());
223        if (!$url) return $table;
224        $cpt++;
225        $url = array_key_exists($url, $table) ? $url.$cpt : $url;
226        $table[$url] = $titre;
227        return $url;
228}
229
230/**
231 * Remplace les @@RETOUR_TDM@@ laissés par les callback de recherche d'intertitres
232 * par le lien de retour correspondant
233 *
234 * @param string $texte Texte d'entrée
235 * @return string Texte avec retours remplacés
236 */
237function tdm_ajouter_liens_retour_table_matieres($texte) {
238       
239        // prendre en compte la langue en cours
240        $_RETOUR_TDM = preg_replace(
241                ',<img,i',
242                '<img alt="' . _T('tdm:retour_table_matiere')
243                .'" title="' . _T('tdm:retour_table_matiere') . '"',
244                _RETOUR_TDM);
245
246        if (TDM_JAVASCRIPT AND !test_espace_prive() AND !_AJAX # crayons
247        ) {
248                $_RETOUR_TDM = '';
249        }
250        return str_replace('@@RETOUR_TDM@@', $_RETOUR_TDM, $texte);
251}
252
253/**
254 * Générer une table des matieres a partir du tableau
255 * d'intertitres donnes
256 *
257 * @param array couples liens/intertitres
258 * @return string       Code HTML de la table des matieres
259 */
260function tdm_generer_table_des_matieres($intertitres) {
261        // generer un code HTML
262        $code = "";
263        foreach ($intertitres as $url=>$titre) {
264                spip_log(self(),'test.'._LOG_ERREUR);
265                $code .= "<li><a href='#$url'>$titre</a></li>\n";
266        }
267
268        // code HTML de la table des matieres
269        $_table = recuperer_fond('modeles/table_matieres', array(
270                'code' => $code,
271                'tableau'=>$intertitres
272        ));
273
274        if (TDM_JAVASCRIPT AND $_table AND !test_espace_prive()
275        AND !_AJAX # crayons
276        ) {
277                $_table = inserer_attribut('<div class="encart"></div>',
278                        'rel', $_table);
279        }
280
281        return $_table;
282}
283
284/**
285 * Balise #TABLE_MATIERES
286 * Affiche la table des matieres à l'endroit indique
287 * A utiliser dans une boucle Articles
288 */
289function balise_TABLE_MATIERES_dist($p) {
290        $b = $p->nom_boucle ? $p->nom_boucle : $p->descr['id_mere'];
291        if ($b === '') {
292                erreur_squelette(
293                        _T('zbug_champ_hors_boucle',
294                                array('champ' => '#TABLE_MATIERES')
295                        ), $p->id_boucle);
296                $p->code = "''";
297        } else {
298                $_texte = champ_sql('texte', $p);
299                $p->code = "$_texte";
300        }
301        return $p;
302}
303
304?>
Note: See TracBrowser for help on using the repository browser.