Create New Item
×
Item Type
File
Folder
Item Name
×
Search file in folder and subfolders...
File Manager
/
tmp
/
couteau-suisse
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php // Code d'inclusion pour le plugin 'Couteau Suisse' isset($GLOBALS['cs_fonctions'])?$GLOBALS['cs_fonctions']++:$GLOBALS['cs_fonctions']=1; // Ce fichier contient des fonctions toujours compilees dans tmp/couteau-suisse/mes_fonctions.php if (!defined("_ECRIRE_INC_VERSION")) return; // compatibilite SPIP < 2.00 if(!defined('_SPIP19300')) { // #VAL{x} renvoie 'x' (permet d'appliquer un filtre a une chaine) // Attention #VAL{1,2} renvoie '1', indiquer #VAL{'1,2'} function balise_VAL($p){ $p->code = interprete_argument_balise(1,$p); if (!strlen($p->code)) $p->code = "''"; $p->interdire_scripts = false; return $p; } if(!function_exists('oui')) { function oui($code) { return $code?' ':''; } } if(!function_exists('non')) { function non($code) { return $code?'':' '; } } } function balise_CHR_dist($p) { if (($v = interprete_argument_balise(1,$p))!==NULL){ $p->code = "chr(intval($v))"; $p->type = 'php'; } return $p; } function balise_DEFINED_dist($p) { if (($v = interprete_argument_balise(1,$p))!==NULL){ $p->code = "defined($v)"; $p->type = 'php'; } return $p; } // compatibilite SPIP < 3.20 if(!defined('_SPIP30200')) { function balise_CONST_dist($p) { $_const = interprete_argument_balise(1, $p); if (!strlen($_const)) $p->code = "''"; else $p->code = "(defined($_const)?constant($_const):'')"; $p->interdire_scripts = false; return $p; } } // fonction appelant une liste de fonctions qui permettent de nettoyer un texte original de ses raccourcis indesirables function cs_introduire($texte) { // liste de filtres qui sert a la balise #INTRODUCTION if(!isset($GLOBALS['cs_introduire']) || !is_array($GLOBALS['cs_introduire'])) return $texte; $liste = array_unique($GLOBALS['cs_introduire']); foreach($liste as $f) if (function_exists($f)) $texte = $f($texte); return $texte; } // filtre pour ajouter un <span> autour d'un texte function cs_span($texte, $attr='') { return "<span $attr>$texte</span>"; } // raccourci pour afficher le statut d'un auteur function cs_auteur_statut($row) { $puce_statut = charger_fonction('puce_statut', 'inc'); return $puce_statut(0, $row['statut'], 0, 'auteur'); } // Controle (basique!) des 3 balises usuelles p|div|span eventuellement coupees // Attention : simple traitement pour des balises non imbriquees function cs_safebalises($texte) { $texte = trim($texte); // ouvre/supprime la premiere balise trouvee fermee (attention aux modeles SPIP) if(preg_match(',^(.*)</([a-z]+)>,Ums', $texte, $m) && !preg_match(",<$m[2][ >],", $m[1])) $texte = strlen($m[1])?"<$m[2]>$texte":trim(substr($texte, strlen($m[2])+3)); // referme/supprime la derniere balise laissee ouverte (attention aux modeles SPIP) if(preg_match(',^(.*)[ >]([a-z]+)<,Ums', $rev = strrev($texte), $m) && !preg_match(",>$m[2]/<,", $m[1])) $texte = strrev(strlen($m[1])?">$m[2]/<$rev":trim(substr($rev, strlen($m[2])+2))); // balises <p|span|div> a traiter foreach(array('span', 'div', 'p') as $b) { // ouvrante manquante if(($fin = strpos($texte, "</$b>")) !== false) if(!preg_match(",<{$b}[ >],", substr($texte, 0, $fin))) $texte = "<$b>$texte"; // fermante manquante $texte = strrev($texte); if(preg_match(',[ >]'.strrev("<{$b}").',', $texte, $reg)) { $fin = strpos(substr($texte, 0, $deb = strpos($texte, $reg[0])), strrev("</$b>")); if($fin===false || $fin>$deb) $texte = strrev("</$b>").$texte; } $texte = strrev($texte); } return $texte; } // fonction de suppression de notes. Utile pour #CS_SOMMAIRE ou #CS_DECOUPE function cs_supprime_notes($texte) { return preg_replace(', *\[\[(.*?)\]\],msS', '', $texte); } // filtre appliquant les traitements SPIP d'un champ (et eventuellement d'un type d'objet) sur un texte // (voir la fonction champs_traitements($p) dans : public/references.php) // => permet d'utiliser les balises etoilees : #TEXTE*|mon_filtre|cs_traitements{TEXTE,articles} // ce mecanisme est a preferer au traditionnel #TEXTE*|mon_filtre|propre // cs_traitements() consulte simplement la globale $table_des_traitements et applique le traitement adequat // $exclusions est une chaine ou un tableau de filtres a exclure du traitement function cs_traitements($texte, $nom_champ='NULL', $type_objet='NULL', $exclusions=NULL) { global $table_des_traitements; if(!isset($table_des_traitements[$nom_champ])) return $texte; $ps = $table_des_traitements[$nom_champ]; if(is_array($ps)) $ps = $ps[isset($ps[$type_objet]) ? $type_objet : 0]; if(!$ps) return $texte; // retirer les filtres a exclure if($exclusions!==NULL) $ps = str_replace($exclusions, 'cs_noop', $ps); // remplacer le placeholder %s par le texte fourni eval('$texte=' . str_replace('%s', '$texte', $ps) . ';'); return $texte; } function cs_noop($t='',$a=NULL,$b=NULL,$c=NULL) { return $t; } // renvoie un champ d'un objet en base function cs_champ_sql($id, $champ='texte', $objet='article') { // Utiliser la bonne requete en fonction de la version de SPIP if(function_exists('sql_getfetsel')) { // SPIP >= 2.0 // TODO : fonctions SPIP pour trouver la table et l'id_objet if($r = sql_getfetsel($champ, 'spip_'.$objet.'s', 'id_'.$objet.'='.intval($id))) return $r; } else { // SPIP 1.92 if($r = spip_query('SELECT '.$champ.' FROM spip_'.$objet.'s WHERE id_'.$objet.'='.intval($id))) // s'il existe un champ, on le retourne if($row = spip_fetch_array($r)) return $row[$champ]; } // sinon rien ! return ''; } // recaler un contenu de fond. Exemple : #FILTRE{cs_impossible} function cs_impossible($chaine='') { return _T('avis_operation_impossible'); } @define('_decoupe_NB_CARACTERES', 60); define('_onglets_CONTENU', '<div class="onglets_contenu"><h2 class="cs_onglet"><a href="#">'); define('_onglets_CONTENU2', '</a></h2>'); // sans le </div> ! define('_onglets_DEBUT', '<div class="onglets_bloc_initial">'); define('_onglets_REGEXPR', ',<onglets([0-9]*)>(.*?)</onglets\1>,ms'); // aide le Couteau Suisse a calculer la balise #INTRODUCTION $GLOBALS['cs_introduire'][] = 'decoupe_nettoyer_raccourcis'; // filtre ajoutant 'artpage' a l'url function decoupe_url($url, $page, $num_pages) { return parametre_url($url, 'artpage',$page>1?"{$page}-{$num_pages}":''); } function onglets_callback($matches) { // cas des onglets imbriques if (strpos($matches[2], '<onglets')!==false) $matches[2] = preg_replace_callback(_onglets_REGEXPR, 'onglets_callback', $matches[2]); // nettoyage apres les separateurs $matches[2] = preg_replace(','.preg_quote(_decoupe_SEPARATEUR,',').'\s+,', _decoupe_SEPARATEUR, $matches[2]); // au cas ou on ne veuille pas d'onglets, on remplace les '++++' par un filet et on entoure d'une classe. if (defined('_CS_PRINT')) { @define(_decoupe_FILET, '<p style="border-bottom:1px dashed #666; padding:0; margin:1em 20%; font-size:4pt;" > </p>'); $t = preg_split(',(\n\n|\r\n\r\n|\r\r),', $matches[2], 2); $texte = preg_replace(','.preg_quote(_decoupe_SEPARATEUR, ',').'(.*?)(\n\n|\r\n\r\n|\r\r),ms', _decoupe_FILET."<h4>$1</h4>\n\n", $t[1]); // on sait jamais... str_replace(_decoupe_SEPARATEUR, _decoupe_FILET, $texte); return '<div class="onglets_print"><h4>' . textebrut(echappe_retour($t[0],'CS')) . "</h4>\n\n$texte\n\n</div>"; } $onglets = $contenus = array(); $pages = explode(_decoupe_SEPARATEUR, $matches[2]); foreach ($pages as $p) { $t = preg_split(',(\n\n|\r\n\r\n|\r\r),', $p, 2); $t = array(trim(textebrut(nettoyer_raccourcis_typo(extraire_multi(echappe_retour($t[0],'CS'))))), cs_safebalises($t[1])); if(strlen($t[0].$t[1])) $contenus[] = _onglets_CONTENU.$t[0]._onglets_CONTENU2."<div>\n\n".$t[1]."\n\n</div></div>"; } return _onglets_DEBUT . implode('', $contenus) . '</div>' . _onglets_FIN; } // fonction appellee sur les parties du texte non comprises entre les balises : html|code|cadre|frame|script|cite|acronym function decouper_en_onglets_rempl(&$texte) { // compatibilite avec la syntaxe de Pierre Troll if (strpos($texte, '<onglet|')!==false) { $texte = str_replace('<onglet|fin>', '</onglets>', $texte); $texte = preg_replace(',<onglet\|debut[^>]*\|titre=([^>]*)>\s*,', "<onglets>\\1\n\n", $texte); $texte = preg_replace(',\s*<onglet\|titre=([^>]*)>\s*,', "\n\n++++\\1\n\n", $texte); } // il faut un callback pour analyser l'interieur du texte return preg_replace_callback(_onglets_REGEXPR, 'onglets_callback', $texte); } // fonction appellee sur les parties du textes non comprises entre les balises : html|code|cadre|frame|script|cite|acronym function decouper_en_pages_rempl($texte, $pagination_seule=false) { // un seul id par page... static $id_decoupe = ''; // si pas de separateur, on sort if (strpos($texte, _decoupe_SEPARATEUR)===false) return $pagination_seule?'':$texte; // au cas ou on ne veuille pas de decoupe, on remplace les '++++' par un filet. if (defined('_CS_PRINT') && !$pagination_seule) { @define(_decoupe_FILET, '<p style="border-bottom:1px dashed #666; padding:0; margin:1em 20%; font-size:4pt;" > </p>'); return str_replace(_decoupe_SEPARATEUR, _decoupe_FILET, $texte); } // recherche du sommaire s'il existe if (defined('_sommaire_REM') && (substr_count($texte, _sommaire_REM)==2)) { $pages = explode(_sommaire_REM, $texte); $sommaire = $pages[0].$pages[1]; $texte = $pages[2]; } else $sommaire = ''; // traitement des pages $pages = explode(_decoupe_SEPARATEUR, $texte); $num_pages = count($pages); if ($num_pages == 1) return $pagination_seule?'':$texte; $artpage = max(intval(artpage()), 1); $artpage = min($artpage, $num_pages); /* // si numero illegal ou si var_recherche existe, alors renvoyer toutes les pages, separees par une ligne <hr/>. // la surbrillance pourra alors fonctionner correctement. if (strlen($_GET['var_recherche']) || $artpage < 1 || $artpage > $num_pages) return implode("<hr/>", $pages); */ // si la balise #CS_DECOUPE est utilisee on renvoie le texte sans pagination if (!$pagination_seule) { // page demandee $page = cs_safebalises($pages[$artpage-1]); if (isset($_GET['decoupe_recherche'])) { include_spip('inc/surligne'); $page = surligner_mots($page, $_GET['decoupe_recherche']); } if (defined('_decoupe_BALISE')) return $sommaire.$page; } $self = nettoyer_uri();//self();//$GLOBALS['REQUEST_URI']; // liens des differentes pages sous forme : 1 2 3 4 $milieu = ''; for ($i = 1; $i <= $num_pages; $i++) { $page_ = supprimer_tags(cs_safebalises(cs_introduire(echappe_retour($pages[$i-1],'CS')))); $title = preg_split("/[\r\n]+/", trim($page_), 2); $title = attribut_html(/*propre*/(couper($title[0], _decoupe_NB_CARACTERES)));//.' (...)'; $milieu .= recuperer_fond('fonds/decoupe_item', array( 'page'=>$i, 'artpage'=>$artpage, 'derniere_page'=>$num_pages, 'title_page'=>_T('couteau:page_lien', array('page' => $i, 'title' => $title)), 'self' =>$self, )); } // pagination finale $pagination = recuperer_fond('fonds/decoupe', array( 'artpage'=>$artpage, 'derniere_page'=>$num_pages, 'items'=>$milieu, 'self' =>$self, )); if ($pagination_seule) { if(trim($pagination)=="") return ""; $pagination = "<div id='decoupe_balise$id_decoupe' class='pagination decoupe_balise'>\n$pagination\n</div>\n"; return $pagination; } // ici $pagination_seule est false, $page est definie $pagination1 = "<div id='decoupe_haut$id_decoupe' class='pagination decoupe_haut'>\n$pagination\n</div>\n"; $pagination2 = "<div id='decoupe_bas$id_decoupe' class='pagination decoupe_bas'>\n$pagination\n</div>\n"; $id_decoupe++; return $sommaire.$pagination1.$page.$pagination2; } // supprime les notes devenues orphelines function decoupe_notes_orphelines(&$texte) { if($GLOBALS['les_notes']=='') return; $notes = $GLOBALS['les_notes']; $appel = ",<div id=[\"']nb([0-9]+)[\"']>.*?<a [^>]*class=[\"']spip_note[\"'][^>]+>[^<]+</a>.*?</div>,s"; preg_match_all($appel, $GLOBALS['les_notes'], $tableau); for($i=0;$i<count($tableau[0]);$i++) { if (!preg_match(",<a href=[\"']#nb{$tableau[1][$i]}[\"'],",$texte)) $notes = str_replace($tableau[0][$i], '', $notes); } $GLOBALS['les_notes'] = trim($notes); } function cs_decoupe_compat($texte){ // surcharge possible de _decoupe_SEPARATEUR par _decoupe_COMPATIBILITE $rempl = ',\s*(' . preg_quote(_decoupe_SEPARATEUR,',') . (defined('_decoupe_COMPATIBILITE')?'|'.preg_quote(_decoupe_COMPATIBILITE,','):'') . ')\s*,'; // mise au clair des separateurs : pour les onglets ET la decoupe en page $texte = preg_replace($rempl, "\n\n"._decoupe_SEPARATEUR."\n\n", $texte); // si pas d'onglets ou pagination seule demandee, on sort if (strpos($texte, '<onglet')===false) return $texte; // traitement des onglets return decouper_en_onglets_rempl($texte); } // ici on est en pre_propre, tests de compatibilite requis, puis traitement des onglets function cs_onglets($texte){ return cs_echappe_balises('|cite|jeux', 'cs_decoupe_compat', $texte); } // ici on est en post_propre, tests de compatibilite effectues function cs_decoupe($texte, $pagination_seule=false){ // si pas de separateur, on sort if (strpos($texte, _decoupe_SEPARATEUR)===false) return $pagination_seule?'':$texte; $texte = cs_echappe_balises('|cite|table|jeux', 'decouper_en_pages_rempl', $texte, $pagination_seule); if (!$pagination_seule) decoupe_notes_orphelines($texte); return $texte; } // Compatibilite function decouper_en_pages($texte){ return cs_decoupe($texte); } // Balises pour des onglets en squelette function balise_ONGLETS_DEBUT($p) { $arg = sinon(interprete_argument_balise(1,$p),'??'); $p->code = "calcul_balise_onglet($arg,1)"; $p->interdire_scripts = false; return $p; } function balise_ONGLETS_TITRE($p) { $arg = sinon(interprete_argument_balise(1,$p),'??'); $p->code = "calcul_balise_onglet($arg,2)"; $p->interdire_scripts = false; return $p; } function balise_ONGLETS_FIN($p) { $p->code = "calcul_balise_onglet('',3)"; $p->interdire_scripts = false; return $p; } function calcul_balise_onglet($arg, $type) { /* dans un onglet principal (non imbrique), on peut omettre #ONGLETS_DEBUT : pratique a l'interieur d'une boucle Sinon il faut jouer avec #COMPTEUR_BOUCLE : <BOUCLE_sites(SITES)> [(#COMPTEUR_BOUCLE|=={1}|?{' '})#ONGLETS_DEBUT{#NOM_SITE}] [(#COMPTEUR_BOUCLE|>{1}|?{' '})#ONGLETS_TITRE{#NOM_SITE}] (...) </BOUCLE_sites> */ static $onglets_stade; if($type==2 && !isset($onglets_stade)) $type = 1; switch($type) { // #ONGLETS_DEBUT case 1:$onglets_stade=1; return _onglets_DEBUT._onglets_CONTENU.$arg._onglets_CONTENU2; // #ONGLETS_TITRE case 2:$onglets_stade=1; return '</div>'._onglets_CONTENU.$arg._onglets_CONTENU2; // #ONGLETS_FIN case 3:unset($onglets_stade); return '</div></div>'; } } // decode le parametre artpage=page-total // attention, artpage n'est pas toujours present function artpage($t=false, $index=0) { if($t===false) $t=_request('artpage'); $t=strlen($t)?explode('-', $t, 2):array('1','0'); return $t[$index]; } function artpage_fin($t=false) { if($t===false) $t=_request('artpage'); $t=strlen($t)?explode('-', $t, 2):array('1','0'); return $t[0]>0 && $t[0]==$t[1]; } function artpage_debut($t=false) { return artpage($t)==1; } // si on veut la balise #CS_DECOUPE (pagination uniquement) if (defined('_decoupe_BALISE')) { function balise_CS_DECOUPE_dist($p) { // id de l'article a trouver pour retourner son texte $texte = ($v = interprete_argument_balise(1,$p))!==NULL ? 'cs_champ_sql('.$v.')' : champ_sql('texte', $p); if ($p->type_requete == 'articles' || $v!==NULL) { $p->code = 'cs_decoupe(propre(cs_onglets(cs_supprime_notes('.$texte.'))), true)'; } else { $p->code = "''"; } $p->interdire_scripts = true; return $p; } } /* filtre |decoupe_type_pagination qui renvoie : 1 si le nombre doit etre affiche 2 si le nombre ne doit pas etre affiche 3 s'il faut afficher '...' voir le modele : modeles/decoupe_item.html */ function decoupe_type_pagination($page, $artpage, $page_fin, $rayon=4, $extremes=2) { $diametre = $rayon*2; if($page_fin<=$diametre+$extremes+1 || $page<=$extremes || $page>$page_fin-$extremes) return 1; $depart = max(1, $artpage - $rayon); $arrivee = $artpage + $rayon; if($arrivee-$depart<$diametre) $arrivee=$depart+$diametre; if($arrivee>$page_fin) $arrivee = $page_fin; if($arrivee-$depart<$diametre) $depart=$arrivee-$diametre; if($depart<=$extremes+1) $depart = 1; if($arrivee>=$page_fin-$extremes) $arrivee = $page_fin; if($page<$depart-1 || $page>$arrivee+1) return 2; if($page==$depart-1 || $page==$arrivee+1) return 3; return 1; } // aide le Couteau Suisse à calculer la balise #INTRODUCTION $GLOBALS['cs_introduire'][] = 'sommaire_nettoyer_raccourcis'; // renvoie l'url utilisée par le sommaire function sommaire_self() { static $self = NULL; return isset($self) ? $self : $self = str_replace('&', '&', nettoyer_uri());//self();//$GLOBALS['REQUEST_URI']; } // filtre de remplacement de l'url par défaut (si par exemple #CS_SOMMAIRE est placé dans une boucle d'articles) function sommaire_url($texte, $url) { return str_replace(sommaire_self(), $url, $texte); } // renvoie le sommaire d'une page d'article // $page=false reinitialise le compteur interne des ancres function sommaire_d_une_page(&$texte, &$nbh3, $page=0, $num_pages=0) { static $index = 0; if($page===false) { $index = 0; return; } // trouver quel <hx> est utilise include_spip('outils/sommaire'); $root = $niveau = $match = cs_niveau_intertitres(); defined('_sommaire_NB_CARACTERES') || define('_sommaire_NB_CARACTERES', 30); defined('_sommaire_PROFONDEUR') || define('_sommaire_PROFONDEUR', 1); if(_sommaire_PROFONDEUR>1) $match = $match .'-' . ($match+_sommaire_PROFONDEUR-1); // traitement des intertitres <hx> preg_match_all(",(<h([$match])[^>]*)>(.*)</h\\2>,Umsi", $texte, $regs); $nbh3 += count($regs[0]); $pos = 0; $sommaire = ''; // calcul de la page $self = sommaire_self(); $fct_lien_retour = function_exists('sommaire_lien_retour')?'sommaire_lien_retour':'sommaire_lien_retour_dist'; $fct_id_ancre = defined('_sommaire_JOLIES_ANCRES')?'sommaire_id_ancre_ex' :(function_exists('sommaire_id_ancre')?'sommaire_id_ancre':'sommaire_id_ancre_dist'); $nb = count($regs[0]); for($i=0;$i<$nb;$i++,$index++){ $w = &$regs[0][$i]; $h = &$regs[1][$i]; $n = &$regs[2][$i]; if (($pos2 = strpos($texte, $w, $pos))!==false) { $t = $regs[3][$i]; // calcul de l'ancre, $t peut etre modifie $ancre = $fct_id_ancre($index, $t, $n); $id = " id=\"$ancre\">"; //$titre = preg_replace(',^<p[^>]*>(.*)</p>$,Umsi', '\\1', trim($t)); // ancre 'retour au sommaire', sauf : // si on imprime, ou si les blocs depliables utilisent h{$n}... $titre = (defined('_CS_PRINT') OR (strpos($w, 'blocs_titre')!==false)) ?$t//$titre :$fct_lien_retour($self, $t);//$titre); $texte = substr($texte, 0, $pos2) . $h . $id . $titre . substr($texte, $pos2 + strlen($h)+1 + strlen($regs[3][$i])); $pos = $pos2 + strlen($id) + strlen($w); $brut = sommaire_nettoyer_titre($t); // pas trop long quand meme... $lien = cs_propre(couper($brut, _sommaire_NB_CARACTERES)); // eviter une ponctuation a la fin, surtout si la page est precisee $lien = preg_replace('/( |\s)*'.($page?'[!?,;.:]+$/':'[,;.:]+$/'), '', $lien); $titre = attribut_html(couper($brut, 100)); // si la decoupe en page est active... $artpage = (function_exists('decoupe_url') && (strlen(_request('artpage')) || $page>1) ) ?decoupe_url($self, $page, $num_pages):$self; $artpage = "<a title=\"$titre\" href=\"{$artpage}#$ancre\">$lien</a>"; $artpage = "\n<li>" . ( function_exists('sommaire_id_page') ?sommaire_id_page($artpage, $page):sommaire_id_page_dist($artpage, $page) ); if($niveau==$n) $sommaire .= ($sommaire?'</li>':'') . $artpage; elseif($niveau<$n) $sommaire .= "\n<ul>".str_repeat('<li><ul>',$n-$niveau-1) . $artpage; else $sommaire .= '</li>'.str_repeat('</ul></li>',$niveau-$n) . $artpage; $niveau = $n; } } return $sommaire?$sommaire.'</li>'.($niveau!=$root?'</ul>':''):''; } function sommaire_nettoyer_titre($t) { // pas de notes $brut = preg_replace(',\[<a href=["\']#nb.*?</a>\],','', echappe_retour($t,'CS')); // pas de glossaire if(function_exists('cs_retire_glossaire')) $brut = cs_retire_glossaire($brut); // texte brut $brut2 = trim(preg_replace(',[\n\r]+,',' ',textebrut($brut))); // cas des intertitres en image_typo if(!strlen($brut2)) $brut2 = trim(extraire_attribut($brut, 'alt')); return $brut2; } /* Fonction surchargeable qui reconstruit les titres de la page en ajoutant une ancre de retour au sommaire. La fonction de surcharge a placer dans config/mes_options.php est : sommaire_lien_retour($self, $titre) Exemple sans lien de retour : function sommaire_lien_retour($self, $titre) { return $titre; } */ function sommaire_lien_retour_dist($self, $titre) { static $haut = NULL; if(!isset($haut)) $haut = '<a title="'._T('couteau:sommaire_titre').'" href="'.$self.'#outil_sommaire" class="sommaire_ancre"> </a>'; return $haut . $titre; } /* Fonction surchargeable qui ajoute au sommaire l'information d'une page en cas de decoupe Exemple : "<a ...>Mon titre</a>, page 4" La fonction de surcharge a placer dans config/mes_options.php est : sommaire_id_page($element, $page) $element est le lien cliquable du sommaire */ function sommaire_id_page_dist($element, $page) { return $page ? $element . _T('couteau:sommaire_page', array('page'=>$page)) : $element; } /* Fonction surchargeable qui calcule l'ancre d'un intertitre La fonction de surcharge a placer dans config/mes_options.php est : sommaire_id_ancre($index, &$titre, $hn) $titre peut etre modifie par cette fonction : utile pour traiter le format {{{Mon titre<mon_ancre>}}} */ function sommaire_id_ancre_dist($index, &$titre, $hn) { return 'outil_sommaire_'.$index; } // Surcharge compatible avec les intertitres en image : jolies ancres function sommaire_id_ancre_ex($index, &$titre, $hn) { // traiter le format {{{Mon titre<mon_ancre>}}} (ou alt='Mon titre<mon_ancre>') if(preg_match(',<(\w+)>$,', $titre, $r) || preg_match(',<(\w+)>(?=\'),', $titre, $r)) { $titre = str_replace($r[0], '', $titre); return $r[1]; } // calculer les ancres d'apres le titre $a = strtolower(translitteration(sommaire_nettoyer_titre($titre))); $a = trim(preg_replace(',[^a-z0-9_]+,', '_', $a), '_'); return strlen($a)>2?$a:"sommaire_$index"; } function sommaire_echappe_balises_callback($matches) { return cs_code_echappement($matches[0], 'SOMM'); } // fonction appellee sur les parties du textes non comprises entre les balises : html|code|cadre|frame|script|cite|acronym|onglets|table // $sommaire_seul = true ou 1 : retour du sommaire seul, fond complet // $sommaire_seul = 2 : retour du sommaire seul sous forme de liste <li></li> // $sommaire_seul = false : insertion du sommaire automatique dans le texte si la balise #CS_SOMMAIRE est inactive // $sommaire_seul = 0 : insertion du sommaire automatique dans le texte, balise #CS_SOMMAIRE active ou non function sommaire_d_article_rempl($texte0, $sommaire_seul=false) { // pour sommaire_nettoyer_raccourcis() include_spip('outils/sommaire'); // si le sommaire est malvenu ou s'il n'y a pas de balise <hx>, alors on laisse tomber $inserer_sommaire = defined('_sommaire_AUTOMATIQUE') ? strpos($texte0, _CS_SANS_SOMMAIRE)===false : strpos($texte0, _CS_AVEC_SOMMAIRE)!==false; if (!$inserer_sommaire || strpos($texte0, '<h')===false) return $sommaire_seul?'':sommaire_nettoyer_raccourcis($texte0); // on retire les raccourcis du texte $texte = sommaire_nettoyer_raccourcis($texte0); // on masque les onglets s'il y en a if(defined('_onglets_FIN')) $texte = preg_replace_callback(',<div class="onglets_bloc_initial.*'._onglets_FIN.',Ums', 'sommaire_echappe_balises_callback', $texte); // et la, on y va... $sommaire = ''; $i = 1; $nbh3 = 0; // reinitialisation de l'index interne de la fonction sommaire_d_une_page($texte, $nbh3, false); // couplage avec l'outil 'decoupe_article' if(defined('_decoupe_SEPARATEUR') && !defined('_CS_PRINT')) { $pages = explode(_decoupe_SEPARATEUR, $texte); if (($num_page=count($pages)) == 1) $sommaire = sommaire_d_une_page($texte, $nbh3); else { foreach($pages as $p=>$page) { $sommaire .= sommaire_d_une_page($page, $nbh3, $i++, $num_page); $pages[$p] = $page; } $texte = implode(_decoupe_SEPARATEUR, $pages); } } else $sommaire = sommaire_d_une_page($texte, $nbh3); defined('_sommaire_NB_TITRES_MINI') || define('_sommaire_NB_TITRES_MINI', 2); if(!strlen($sommaire) || $nbh3<_sommaire_NB_TITRES_MINI) return $sommaire_seul ? '' : sommaire_nettoyer_raccourcis($texte0); // on ne veut que la liste <li></li> du sommaire ? if($sommaire_seul===2) return $sommaire; // contexte du sommaire : on passe aussi les id_objet disponibles $temp = array( 'sommaire' => $sommaire, 'fond_css' => strpos($texte0, _sommaire_SANS_FOND)===false ?'avec':'sans', ); if(!defined('_SPIP30000') && test_espace_prive() && !empty($_GET)) // SPIP < 3.0 : partie privee non squelettisee foreach($_GET as $i=>$v) if(strncmp($i,'id_',3)==0) $temp[$i] = $v; if(isset($GLOBALS['contexte']) && is_array($GLOBALS['contexte'])) foreach($GLOBALS['contexte'] as $i=>$v) if(strncmp($i,'id_',3)==0) $temp[$i] = $v; // calcul du sommaire include_spip('public/assembler'); $sommaire = recuperer_fond('fonds/sommaire', $temp); // si on ne veut que le sommaire, on renvoie le sommaire // sinon, on n'insere ce sommaire en tete de texte que si la balise #CS_SOMMAIRE n'est pas activee if($sommaire_seul) return $sommaire; if(defined('_onglets_FIN')) $texte = echappe_retour($texte, 'SOMM'); if(defined('_sommaire_BALISE') && $sommaire_seul===false) return $texte; return _sommaire_REM.$sommaire._sommaire_REM.$texte; } // fonction/filtre appelee par le traitement de #TEXTE/articles function sommaire_d_article($texte, $sommaire_seul=false) { // s'il n'y a aucun intertitre, on ne fait rien // si la balise est utilisee, il faut quand meme inserer les ancres de retour if((strpos($texte, '<h')===false)) return $texte; return cs_echappe_balises('|cite|acronym|onglets|table', 'sommaire_d_article_rempl', $texte, $sommaire_seul); } // fonction appelee par le traitement post_propre de #CS_SOMMAIRE function sommaire_d_article_balise($texte) { // si la balise n'est pas utilisee ou s'il n'y a aucun intertitre, on ne fait rien if(!defined('_sommaire_BALISE') || (strpos($texte, '<h')===false)) return ''; return cs_echappe_balises('|cite|acronym|onglets|table', 'sommaire_d_article_rempl', $texte, true); } // si on veut la balise #CS_SOMMAIRE if (defined('_sommaire_BALISE')) { // fonction traitant la balise function balise_CS_SOMMAIRE_dist($p) { // id de l'article a trouver pour retourner son texte $texte = ($v = interprete_argument_balise(1,$p))!==NULL ? 'cs_champ_sql('.$v.')' : champ_sql('texte', $p); if ($p->type_requete == 'articles' || $v!==NULL) { $p->code = 'cs_supprime_notes('.$texte.')'; } else { $p->code = "''"; } $p->interdire_scripts = true; return $p; } } // aide le Couteau Suisse a calculer la balise #INTRODUCTION include_spip('outils/couleurs'); $GLOBALS['cs_introduire'][] = 'couleurs_nettoyer_raccourcis'; /* Liens orphelins - Code & integration 2007 : Patrice Vanneufville Toutes les infos sur : https://contrib.spip.net/?article2443 */ include_spip('outils/inc_cs_liens'); // Traitement de la balise #EMAIL function liens_orphelins_email($email){ return test_espace_prive()?$email:expanser_liens(liens_orphelins($email)); } function liens_orphelins($texte){ // deja, on s'en va si pas de point... if ($GLOBALS["liens_orphelins"]<0 || strpos($texte, '.')===false) return $texte; // prudence 1 : on protege TOUTES les balises <a></a> pour eviter les doublons if (strpos($texte, '<a')!==false) $texte = preg_replace_callback(',<a\s*[^<]+</a>,Ums', 'cs_liens_echappe_callback', $texte); // prudence 2 : on protege TOUS les raccourcis de liens Spip, au cas ou... if (strpos($texte, '[')!==false) $texte = preg_replace_callback(',\[([^][]*)->(>?)([^]]*)\],msS', 'cs_liens_echappe_callback', $texte); // prudence 3 : on protege TOUTES les balises contenant des points et <form/>, histoire de voir plus clair if (strpos($texte, '<')!==false) $texte = preg_replace_callback(',<(?:form|[^>]+\.)[^>]*>,Ums', 'cs_liens_echappe_callback', $texte); // encore ici, on s'en va si pas de point... if (strpos($texte, '.')===false) return echappe_retour($texte, 'LIENS'); // trouve et protege : protocole://qqchose $texte = preg_replace_callback(_cs_liens_HTTP, 'cs_liens_raccourcis_callback', $texte); // trouve et protege : www.lieu.qqchose ou ftp.lieu.qqchose $texte = preg_replace_callback(_cs_liens_WWW, 'cs_liens_raccourcis_callback', $texte); // trouve : mailto:qqchose ou news:qqchose if($GLOBALS['liens_orphelins']>0) { $texte = preg_replace_callback(_cs_liens_NEWS, 'cs_liens_raccourcis_callback', $texte); $texte = preg_replace_callback(_cs_liens_MAILS, 'cs_liens_email_callback', $texte); } return echappe_retour($texte, 'LIENS'); } // Outil SMILEYS - 25 decembre 2006 // balise #SMILEYS : Patrice Vanneufville, 2007 // Toutes les infos sur : https://contrib.spip.net/?article1561 // dessin des frimousses : Sylvain Michel [http://www.guaph.net/] function balise_SMILEYS_dist($p) { // Fonctions abandonnees par le plugin Porte Plume $js_compat = !defined('_DIR_PLUGIN_PORTE_PLUME')?"":"<script type=\"text/javascript\">/*<![CDATA[*/ // From SPIP 2.0 (spip_barre.js) if(typeof barre_inserer!='function') { function barre_inserer(text,champ) { var txtarea = champ; if(document.selection){ txtarea.focus(); var r = document.selection.createRange(); if (r == null) { txtarea.selectionStart = txtarea.value.length; txtarea.selectionEnd = txtarea.selectionStart; } else { var re = txtarea.createTextRange(); var rc = re.duplicate(); re.moveToBookmark(r.getBookmark()); rc.setEndPoint('EndToStart', re); txtarea.selectionStart = rc.text.length; txtarea.selectionEnd = rc.text.length + r.text.length; } } mozWrap(txtarea, '', text); }} // From http://www.massless.org/mozedit/ if(typeof mozWrap!='function') { function mozWrap(txtarea, open, close) { var selLength = txtarea.textLength; var selStart = txtarea.selectionStart; var selEnd = txtarea.selectionEnd; if (selEnd == 1 || selEnd == 2) selEnd = selLength; var selTop = txtarea.scrollTop; // Raccourcir la selection par double-clic si dernier caractere est espace if (selEnd - selStart > 0 && (txtarea.value).substring(selEnd-1,selEnd) == ' ') selEnd = selEnd-1; var s1 = (txtarea.value).substring(0,selStart); var s2 = (txtarea.value).substring(selStart, selEnd) var s3 = (txtarea.value).substring(selEnd, selLength); txtarea.value = s1 + open + s2 + close + s3; selDeb = selStart + open.length; selFin = selEnd + close.length; window.setSelectionRange(txtarea, selDeb, selFin); txtarea.scrollTop = selTop; txtarea.focus(); return; }} /*]]>*/</script>\n"; // le tableau des smileys est present dans les metas $smileys = cs_lire_data_outil('smileys'); // valeurs par defaut $nb_col = 8; $titre = _T('couteau:smileys_dispos'); $head = ''; $liens = false; // traitement des arguments : [(#SMILEYS{arg1, arg2, ...})] $n=1; $arg = interprete_argument_balise($n++,$p); while ($arg){ // un nombre est le nombre de colonne if (preg_match(",'([0-9]+)',", $arg, $reg)) $nb_col = intval($reg[1]); // on veut un titre elseif ($arg=="'titre'") $head = "<thead><tr class=\"row_first\"><td colspan=\"$nb_col\">$titre</td></tr></thead>"; // on veut un lien d'insertion sur chaque smiley elseif ($arg=="'liens'") { $liens = true; include_spip('outils/smileys'); $smileys = smileys_uniques($smileys); } $arg = interprete_argument_balise($n++,$p); } $max = count($smileys[0]); if (!$nb_col) $nb_col = $max; $html = "<table summary=\"$titre\" class=\"spip cs_smileys smileys\">$head"; $l = 1; for ($i=0; $i<$max; $i++) { if ($i % $nb_col == 0) { $class = 'row_'.alterner($l++, 'even', 'odd'); $html .= "<tr class=\"$class\">"; } $html .= $liens ?"<td><a href=\"javascript:barre_inserer('{$smileys[0][$i]}',document.getElementById('".(defined('_SPIP19300')?'texte':'textarea_1')."'))\">{$smileys[1][$i]}</a></td>" :"<td>{$smileys[1][$i]}<br />{$smileys[0][$i]}</td>"; if ($i % $nb_col == $nb_col - 1) $html .= "</tr>\n"; } // on finit la ligne qd meme... if ($i = $max % $nb_col) $html .= str_repeat('<td> </td>', $nb_col - $i) . '</tr>'; // accessibilite : alt et title avec le smiley en texte $html = $js_compat . echappe_retour($html, 'SMILE'); $html = str_replace("'", "\'", $html); $p->code = "'$html\n</table>\n'"; $p->interdire_scripts = false; $p->type = 'html'; return $p; } /* Trois ou quatre balises pour creer des blocs depliables : #BLOC_TITRE / {une_URL} si ajax, {un_numero} si bloc numerote, {visible} si bloc deplie / Mon titre #BLOC_RESUME / facultatif / Mon resume qui disparait si on clique #BLOC_DEBUT Mon bloc depliable / qui est aussi l'emplacement pour l'Ajax si le fragment est donne / #BLOC_FIN */ if(!defined('_BLOC_TITRE_H')) define('_BLOC_TITRE_H', 'h4'); if(!function_exists('balise_BLOC_TITRE')) { // Pour la balise suivante, l'ordre des arguments importe peu // Un bloc replie, titre simple : #BLOC_TITRE // Un bloc replie AJAX : #BLOC_TITRE{fragment} (fragment est une URLs) // Un bloc replie numerote : #BLOC_TITRE{numero} (numero est un nombre entier) // Un bloc deplie ou replie : ajouter l'argument 'visible' ou 'invisible' : #BLOC_TITRE{visible} // Par defaut : les blocs sont replies function balise_BLOC_TITRE($p) { // Les arguments : 'visible' ou 'invisible', un numero, une URL $p->code = "blocs_balises('titre', array(".blocs_arguments($p).'))'; $p->interdire_scripts = false; return $p; } function blocs_arguments(&$p) { $i = 0; $args = array(); while(($a = interprete_argument_balise(++$i,$p)) != NULL) $args[] = $a; return implode(",", $args); } // 3 balises obsoletes function balise_BLOC_TITRE_NUM(&$p) {return balise_BLOC_TITRE($p);} function balise_BLOC_VISIBLE_TITRE_NUM(&$p) {return balise_BLOC_VISIBLE_TITRE($p);} function balise_BLOC_VISIBLE_TITRE(&$p) { // Produire le premier argument {visible} $texte = new Texte; $texte->type='texte'; $texte->texte='visible'; array_unshift($p->param, array(0=>NULL, 1=>array(0=>$texte))); return balise_BLOC_TITRE($p); } function balise_BLOC_RESUME($p) { $p->code = "blocs_balises('resume')"; $p->interdire_scripts = false; return $p; } function balise_BLOC_DEBUT($p) { $p->code = "blocs_balises('debut', array(".blocs_arguments($p).'))'; $p->interdire_scripts = false; return $p; } function balise_BLOC_FIN($p) { $p->code = "blocs_balises('fin')"; $p->interdire_scripts = false; return $p; } function balise_BLOC_TITRE_DEBUT($p) { $p->code = "blocs_balises('titre_debut', array(".blocs_arguments($p).'))'; $p->interdire_scripts = false; return $p; } function balise_BLOC_TITRE_FIN($p) { $p->code = "blocs_balises('titre_fin')"; $p->interdire_scripts = false; return $p; } // Renvoie un code JQuery pour deplier un bloc au chargement de la page. // Exemple pour deplier le 5eme bloc : #BLOC_DEPLIER{4} (l'index commence a zero) function balise_BLOC_DEPLIER($p) { $eq = interprete_argument_balise(1, $p); $p->code = "bloc_deplier_script(intval($eq))"; $p->interdire_scripts = false; return $p; } // Renvoie un code JQuery pour deplier un bloc numerote au chargement de la page. // Exemple pour deplier le bloc .cs_bloc4 : #BLOC_DEPLIER_NUM{4} function balise_BLOC_DEPLIER_NUM($p) { $eq = interprete_argument_balise(1, $p); $p->code = "bloc_num_deplier_script(intval($eq))"; $p->interdire_scripts = false; return $p; } // Renvoie un code JQuery pour courcuiter la variable configurant les blocs uniques // Argument : oui/non ou 0/1 function balise_BLOC_UNIQUE($p) { $arg = interprete_argument_balise(1, $p); $p->code = "bloc_unique_script($arg)"; $p->interdire_scripts = false; return $p; } // fonction (SPIP>=2.0) pour le calcul de la balise #BLOC_DEPLIER function bloc_deplier_script($num=0) { return $num<0?'':http_script("jQuery(document).ready(function() { jQuery('"._BLOC_TITRE_H.".blocs_titre').eq($num).click(); });"); } // fonction (SPIP>=2.0) pour le calcul de la balise #BLOC_DEPLIER_NUM function bloc_num_deplier_script($num=-1) { return $num<0?'':http_script("jQuery(document).ready(function() { jQuery('div.cs_bloc$num').children('.blocs_titre').eq(0).click(); });"); } // fonction (SPIP>=2.0) pour le calcul de la balise #BLOC_UNIQUE function bloc_unique_script($num=1) { $num = ($num==='oui' || intval($num)>0)?1:0; return http_script("var blocs_replier_tout = $num;"); } // fonction pour le calcul des balises de type #BLOC_XXX // $args ne sert que pour #BLOC_TITRE et contient les arguments de la balise sous forme de tableau function blocs_balises($type, $args = array()) { // statut binaire : bit1=ajax bit2=titre bit3=resume bit4=debut // 2 = ajax (20 si distant) ; 1 = titre pas d'ajax (10 si distant); idem negatif = bloc visible static $bloc_stade; $k = isset($bloc_stade)?count($bloc_stade):0; $stade = $k?abs($bloc_stade[--$k]):0; $distant = $replie = 1; $id = $numero = ''; switch($type) { case 'titre_debut': // id pour le bloc distant $id = ' id="cs_bloc_id_' . reset($args) . '"'; $distant = 10; case 'titre': foreach($args as $a) { if(is_numeric($a = trim($a))) $numero = ' cs_bloc'.$a.'" id="deplier_num'.$a; elseif($a=='visible') $replie = -1; elseif($a=='invisible') $replie = 1; elseif(strlen($a)) $fragment = $a; } if (isset($fragment)){ $ajax = ' blocs_ajax '; $bloc_stade[] = 2*$distant*$replie; } else { $fragment = "javascript:;"; $ajax = ''; $bloc_stade[] = 1*$distant*$replie; } $replie = $replie>0?' blocs_replie':''; return "<div class=\"cs_blocs$numero\"><"._BLOC_TITRE_H." class=\"blocs_titre$replie$ajax\"$id><a href=\"$fragment\">"; case 'resume': $class = $bloc_stade[$k]>0?'':' blocs_invisible blocs_slide'; if($stade<1 || $stade>2) // on DOIT arriver de titre die("Erreur : #BLOC_RESUME sans #BLOC_TITRE ($stade)"); $bloc_stade[$k] = $bloc_stade[$k]>0?3:-3; // 3 = resume return "</a></"._BLOC_TITRE_H."><div class=\"blocs_resume$class\">"; case 'debut': if(count($args)) { // debut d'un bloc depliable a distance foreach($args as $a) { if($a=='visible') $replie = -1; elseif($a=='invisible') $replie = 1; elseif(strlen($a)) $id = " cs_bloc_id_$a"; } $bloc_stade[]=11; $class = $replie>0?' blocs_invisible blocs_slide':''; return "<div class=\"blocs_destination$class$id\">"; } $class = $bloc_stade[$k]<0?'':' blocs_invisible blocs_slide'; $bloc_stade[$k]=$bloc_stade[$k]>0?4:-4; // 4=debut if($stade == 3) // on arrive du resume, fermer la div resume seulement return "</div><div class=\"blocs_destination$class\">"; else { if($stade<1 || $stade>2) // on DOIT arriver de titre die("Erreur : #BLOC_DEBUT sans #BLOC_TITRE ($stade)"); return '</a></'._BLOC_TITRE_H."><div class=\"blocs_destination$class\">"; } case 'titre_fin': $k = isset($bloc_stade)?abs(array_pop($bloc_stade)):0; if($k==10 || $k==20) // on DOIT arriver de #BLOC_TITRE_DEBUT return '</a></'._BLOC_TITRE_H.'></div>'; die("Erreur : #BLOC_TITRE_FIN sans #BLOC_TITRE_DEBUT ($k)"); case 'fin': $k = isset($bloc_stade)?abs(array_pop($bloc_stade)):0; switch($k) { case 4: return "</div></div>"; case 11: return "</div>"; default: die("Erreur : #BLOC_FIN sans #BLOC_DEBUT ($k)"); } } } } // if(!function_exists('balise_BLOC_TITRE')) ?>