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

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

Création du paquet.xml de table des matières

Nécessite de renommer table_matieres.php en tablematieres_fonctions.php

Version 2.0.3

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