source: spip-zone/_plugins_/couteau_suisse/outils/sommaire_fonctions.php @ 85650

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

Sommaire automatique : résolution du passage au niveau n à n-2 ou n+2

File size: 10.2 KB
Line 
1<?php
2
3@define('_sommaire_NB_TITRES_MINI', 2);
4@define('_sommaire_SANS_FOND', '[!fond]');
5
6// aide le Couteau Suisse à calculer la balise #INTRODUCTION
7$GLOBALS['cs_introduire'][] = 'sommaire_nettoyer_raccourcis';
8
9// renvoie l'url utilisée par le sommaire
10function sommaire_self() {
11        static $self = NULL; 
12        return isset($self) ? $self : 
13                $self = str_replace('&', '&amp;', nettoyer_uri());//self();//$GLOBALS['REQUEST_URI'];
14}
15
16// filtre de remplacement de l'url par défaut (si par exemple #CS_SOMMAIRE est placé dans une boucle d'articles)
17function sommaire_url($texte, $url) {
18        return str_replace(sommaire_self(), $url, $texte);
19}
20
21// renvoie le sommaire d'une page d'article
22// $page=false reinitialise le compteur interne des ancres
23function sommaire_d_une_page(&$texte, &$nbh3, $page=0, $num_pages=0) {
24        static $index = 0;
25        if($page===false) { $index = 0; return; }
26        // trouver quel <hx> est utilise
27        include_spip('outils/sommaire');
28        $root = $niveau = $match = sommaire_niveau_intertitres();
29        @define('_sommaire_NB_CARACTERES', 30);
30        @define('_sommaire_PROFONDEUR', 1);
31        if(_sommaire_PROFONDEUR>1)
32                $match = $match .'-' . ($match+_sommaire_PROFONDEUR-1);
33        // traitement des intertitres <hx>
34        preg_match_all(",(<h([$match])[^>]*)>(.*)</h\\2>,Umsi", $texte, $regs);
35        $nbh3 += count($regs[0]);
36        $pos = 0; $sommaire = '';
37        // calcul de la page
38        $self = sommaire_self();
39        $fct_lien_retour = function_exists('sommaire_lien_retour')?'sommaire_lien_retour':'sommaire_lien_retour_dist';
40        $fct_id_ancre = defined('_sommaire_JOLIES_ANCRES')?'sommaire_id_ancre_ex'
41                :(function_exists('sommaire_id_ancre')?'sommaire_id_ancre':'sommaire_id_ancre_dist');
42        $nb = count($regs[0]);
43        for($i=0;$i<$nb;$i++,$index++){
44                $w = &$regs[0][$i]; $h = &$regs[1][$i]; $n = &$regs[2][$i];
45                if (($pos2 = strpos($texte, $w, $pos))!==false) {
46                        $t = $regs[3][$i];
47                        // calcul de l'ancre, $t peut etre modifie
48                        $ancre = $fct_id_ancre($index, $t, $n);
49                        $id = " id=\"$ancre\">";
50                        //$titre = preg_replace(',^<p[^>]*>(.*)</p>$,Umsi', '\\1', trim($t));
51                        // ancre 'retour au sommaire', sauf :
52                        // si on imprime, ou si les blocs depliables utilisent h{$n}...
53                        $titre = (defined('_CS_PRINT') OR (strpos($w, 'blocs_titre')!==false))
54                                ?$t//$titre
55                                :$fct_lien_retour($self, $t);//$titre);
56                        $texte = substr($texte, 0, $pos2) . $h . $id . $titre
57                                . substr($texte, $pos2 + strlen($h)+1 + strlen($regs[3][$i]));
58                        $pos = $pos2 + strlen($id) + strlen($w);
59                        $brut = sommaire_nettoyer_titre($t);
60                        // pas trop long quand meme...
61                        $lien = cs_propre(couper($brut, _sommaire_NB_CARACTERES));
62                        // eviter une ponctuation a la fin, surtout si la page est precisee
63                        $lien = preg_replace('/(&nbsp;|\s)*'.($page?'[!?,;.:]+$/':'[,;.:]+$/'), '', $lien);
64                        $titre = attribut_html(couper($brut, 100));
65                        // si la decoupe en page est active...
66                        $artpage = (function_exists('decoupe_url') && (strlen(_request('artpage')) || $page>1) )
67                                ?decoupe_url($self, $page, $num_pages):$self;
68                        $artpage = "<a $st title=\"$titre\" href=\"{$artpage}#$ancre\">$lien</a>";
69                        $artpage = "\n<li>" . ( function_exists('sommaire_id_page')
70                                ?sommaire_id_page($artpage, $page):sommaire_id_page_dist($artpage, $page) );
71                        if($niveau==$n) $sommaire .= ($sommaire?'</li>':'').$artpage;
72                        elseif($niveau<$n) $sommaire .= "\n<ul>".str_repeat('<li><ul>',$n-$niveau-1).$artpage;
73                        else $sommaire .= '</li>'.str_repeat('</ul></li>',$niveau-$n).$artpage;
74                        $niveau = $n;
75                }
76        }
77        return $sommaire?$sommaire.'</li>'.($niveau!=$root?'</ul>':''):'';
78}
79
80function sommaire_nettoyer_titre($t) {
81        // pas de notes
82        $brut = preg_replace(',\[<a href=["\']#nb.*?</a>\],','', echappe_retour($t,'CS'));
83        // pas de glossaire
84        if(function_exists('cs_retire_glossaire')) $brut = cs_retire_glossaire($brut);
85        // texte brut
86        $brut2 = trim(preg_replace(',[\n\r]+,',' ',textebrut($brut)));
87        // cas des intertitres en image_typo
88        if(!strlen($brut2)) $brut2 = trim(extraire_attribut($brut, 'alt'));
89        return $brut2;
90}
91
92/*
93 Fonction surchargeable qui reconstruit les titres de la page
94 en ajoutant une ancre de retour au sommaire.
95 La fonction de surcharge a placer dans config/mes_options.php est :
96   sommaire_lien_retour($self, $titre)
97 Exemple sans lien de retour :
98   function sommaire_lien_retour($self, $titre) { return $titre; }
99*/
100function sommaire_lien_retour_dist($self, $titre) {
101        static $haut = NULL;
102        if(!isset($haut)) 
103                $haut = '<a title="'._T('couteau:sommaire_titre').'" href="'.$self.'#outil_sommaire" class="sommaire_ancre">&nbsp;</a>';
104        return $haut . $titre;
105}
106
107/*
108 Fonction surchargeable qui ajoute au sommaire l'information d'une page en cas de decoupe
109 Exemple : "<a ...>Mon titre</a>, page 4"
110 La fonction de surcharge a placer dans config/mes_options.php est :
111   sommaire_id_page($element, $page)
112 $element est le lien cliquable du sommaire
113*/
114function sommaire_id_page_dist($element, $page) {
115        return $page ? $element . _T('couteau:sommaire_page', array('page'=>$page)) : $element;
116}
117
118/*
119 Fonction surchargeable qui calcule l'ancre d'un intertitre
120 La fonction de surcharge a placer dans config/mes_options.php est :
121   sommaire_id_ancre($index, &$titre, $hn)
122 $titre peut etre modifie par cette fonction : utile pour traiter le format {{{Mon titre<mon_ancre>}}}
123*/
124function sommaire_id_ancre_dist($index, &$titre, $hn) {
125        return 'outil_sommaire_'.$index;
126}
127
128// Surcharge compatible avec les intertitres en image : jolies ancres
129function sommaire_id_ancre_ex($index, &$titre, $hn) {
130        // traiter le format {{{Mon titre<mon_ancre>}}} (ou alt='Mon titre&lt;mon_ancre&gt;')
131        if(preg_match(',<(\w+)>$,', $titre, $r) || preg_match(',&lt;(\w+)&gt;(?=\'),', $titre, $r)) {
132                $titre = str_replace($r[0], '', $titre);
133                return $r[1];
134        }
135        // calculer les ancres d'apres le titre
136        $a = strtolower(translitteration(sommaire_nettoyer_titre($titre)));
137        $a = trim(preg_replace(',[^a-z0-9_]+,', '_', $a), '_');
138        return strlen($a)>2?$a:"sommaire_$index";
139}
140
141// fonction appellee sur les parties du textes non comprises entre les balises : html|code|cadre|frame|script|acronym|cite|onglets|table
142// $sommaire_seul = true ou 1 : retour du sommaire seul, fond complet
143// $sommaire_seul = 2 : retour du sommaire seul sous forme de liste <li></li>
144// $sommaire_seul = false : insertion du sommaire automatique dans le texte si la balise #CS_SOMMAIRE est inactive
145// $sommaire_seul = 0 : insertion du sommaire automatique dans le texte, balise #CS_SOMMAIRE active ou non
146function sommaire_d_article_rempl($texte0, $sommaire_seul=false) {
147        // pour sommaire_nettoyer_raccourcis()
148        include_spip('outils/sommaire');
149        // si le sommaire est malvenu ou s'il n'y a pas de balise <hx>, alors on laisse tomber
150        $inserer_sommaire =  defined('_sommaire_AUTOMATIQUE')
151                ?strpos($texte0, _CS_SANS_SOMMAIRE)===false
152                :strpos($texte0, _CS_AVEC_SOMMAIRE)!==false;
153        if (!$inserer_sommaire || strpos($texte0, '<h')===false) 
154                return $sommaire_seul?'':sommaire_nettoyer_raccourcis($texte0);
155        // on retire les raccourcis du texte
156        $texte = sommaire_nettoyer_raccourcis($texte0);
157        // on masque les onglets s'il y en a
158        if(defined('_onglets_FIN'))
159                $texte = preg_replace_callback(',<div class="onglets_bloc_initial.*'._onglets_FIN.',Ums',
160                        create_function('$matches','return cs_code_echappement($matches[0], \'SOMM\');'), $texte);
161        // et la, on y va...
162        $sommaire = ''; $i = 1; $nbh3 = 0;
163        // reinitialisation de l'index interne de la fonction
164        sommaire_d_une_page($texte, $nbh3, false);
165        // couplage avec l'outil 'decoupe_article'
166        if(defined('_decoupe_SEPARATEUR') && !defined('_CS_PRINT')) {
167                $pages = explode(_decoupe_SEPARATEUR, $texte);
168                if (($num_page=count($pages)) == 1) $sommaire = sommaire_d_une_page($texte, $nbh3);
169                else {
170                        foreach($pages as $p=>$page) { $sommaire .= sommaire_d_une_page($page, $nbh3, $i++, $num_page); $pages[$p] = $page; }
171                        $texte = join(_decoupe_SEPARATEUR, $pages);
172                }
173        } else $sommaire = sommaire_d_une_page($texte, $nbh3);
174        if(!strlen($sommaire) || $nbh3<_sommaire_NB_TITRES_MINI)
175                return $sommaire_seul?'':sommaire_nettoyer_raccourcis($texte0);
176
177        // on ne veut que la liste <li></li> du sommaire ?
178        if($sommaire_seul===2) return $sommaire;
179       
180        // contexte du sommaire : on passe aussi les id_objet disponibles
181        $temp = array(
182                'sommaire' => $sommaire,
183                'fond_css' => strpos($texte0, _sommaire_SANS_FOND)===false ?'avec':'sans',
184        );
185        if(!defined('_SPIP30000') && test_espace_prive() && !empty($_GET)) // SPIP < 3.0 : partie privee non squelettisee
186                foreach($_GET as $i=>$v) if(strncmp($i,'id_',3)==0) $temp[$i] = $v;
187        if(is_array($GLOBALS['contexte'])) foreach($GLOBALS['contexte'] as $i=>$v) if(strncmp($i,'id_',3)==0) $temp[$i] = $v;
188        // calcul du sommaire
189        include_spip('public/assembler');
190        $sommaire = recuperer_fond('fonds/sommaire', $temp);
191
192        // si on ne veut que le sommaire, on renvoie le sommaire
193        // sinon, on n'insere ce sommaire en tete de texte que si la balise #CS_SOMMAIRE n'est pas activee
194        if($sommaire_seul) return $sommaire;
195        if(defined('_onglets_FIN')) $texte = echappe_retour($texte, 'SOMM');
196        if(defined('_sommaire_BALISE') && $sommaire_seul===false) return $texte;
197        return _sommaire_REM.$sommaire._sommaire_REM.$texte;
198}
199
200// fonction/filtre appelee par le traitement de #TEXTE/articles
201function sommaire_d_article($texte, $sommaire_seul=false) {
202        // s'il n'y a aucun intertitre, on ne fait rien
203        // si la balise est utilisee, il faut quand meme inserer les ancres de retour
204        if((strpos($texte, '<h')===false)) return $texte;
205        return cs_echappe_balises('html|code|cadre|frame|script|acronym|cite|onglets|table', 'sommaire_d_article_rempl', $texte, $sommaire_seul);
206}
207
208// fonction appelee par le traitement post_propre de #CS_SOMMAIRE
209function sommaire_d_article_balise($texte) {
210        // si la balise n'est pas utilisee ou s'il n'y a aucun intertitre, on ne fait rien
211        if(!defined('_sommaire_BALISE') || (strpos($texte, '<h')===false)) return '';
212        return cs_echappe_balises('html|code|cadre|frame|script|acronym|cite|onglets|table', 'sommaire_d_article_rempl', $texte, true);
213}
214
215// si on veut la balise #CS_SOMMAIRE
216if (defined('_sommaire_BALISE')) {
217        // fonction traitant la balise
218        function balise_CS_SOMMAIRE_dist($p) {
219                // id de l'article a trouver pour retourner son texte
220                $texte = ($v = interprete_argument_balise(1,$p))!==NULL ? 'cs_champ_sql('.$v.')' : champ_sql('texte', $p);
221                if ($p->type_requete == 'articles' || $v!==NULL) {
222                        $p->code = 'cs_supprime_notes('.$texte.')';
223                } else {
224                        $p->code = "''";
225                }
226                $p->interdire_scripts = true;
227                return $p;
228        }
229}
230?>
Note: See TracBrowser for help on using the repository browser.