[SPIP] ~maj 3.0.10 --> 3.0.14
[lhc/web/www.git] / www / plugins-dist / textwheel / inc / lien.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2014 *
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 if (!defined('_ECRIRE_INC_VERSION')) return;
14
15 include_spip('base/abstract_sql');
16
17 //
18 // Production de la balise A+href a partir des raccourcis [xxx->url] etc.
19 // Note : complique car c'est ici qu'on applique typo(),
20 // et en plus on veut pouvoir les passer en pipeline
21 //
22
23 function inc_lien_dist($lien, $texte='', $class='', $title='', $hlang='', $rel='', $connect='', $env=array()) {
24 static $u=null;
25 if (!$u) $u=url_de_base();
26 $typo = false;
27
28 // Si une langue est demandee sur un raccourci d'article, chercher
29 // la traduction ;
30 // - [{en}->art2] => traduction anglaise de l'article 2, sinon art 2
31 // - [{}->art2] => traduction en langue courante de l'art 2, sinon art 2
32 // s'applique a tout objet traduit
33 if ($hlang
34 AND $match = typer_raccourci($lien)) {
35 @list($type,,$id,,$args,,$ancre) = $match;
36 $trouver_table = charger_fonction('trouver_table', 'base');
37 $desc = $trouver_table(table_objet($type, $connect),$connect);
38 if ($desc
39 AND $id_table_objet = $desc['key']['PRIMARY KEY']) {
40 $table_objet_sql = $desc['table'];
41 if ($row=sql_fetsel('*', $table_objet_sql, "$id_table_objet=".intval($id))
42 AND isset($row['id_trad'])
43 AND isset($row['lang'])
44 AND $id_dest = sql_getfetsel($id_table_objet, $table_objet_sql,"id_trad=".intval($row['id_trad'])." AND lang=" . sql_quote($hlang))
45 AND objet_test_si_publie($type,$id_dest)
46 )
47 $lien = "$type$id_dest";
48 else
49 $hlang = '';
50 }
51 else
52 $hlang = '';
53 }
54
55 $mode = ($texte AND $class) ? 'url' : 'tout';
56 $lien = calculer_url($lien, $texte, $mode, $connect);
57 if ($mode === 'tout') {
58 $texte = $lien['titre'];
59 if (!$class AND isset($lien['class'])) $class = $lien['class'];
60 $lang = isset($lien['lang']) ?$lien['lang'] : '';
61 $mime = isset($lien['mime']) ? " type='".$lien['mime']."'" : "";
62 $lien = $lien['url'];
63 }
64
65 $lien = trim($lien);
66 if (strncmp($lien,"#",1) == 0) # ancres pures (internes a la page)
67 $class = 'spip_ancre';
68 elseif (strncasecmp($lien,'mailto:',7)==0) # pseudo URL de mail
69 $class = "spip_mail";
70 elseif (strncmp($texte,'<html>',6)==0) # cf traiter_lien_explicite
71 $class = "spip_url spip_out";
72 elseif (!$class) $class = "spip_out"; # si pas spip_in|spip_glossaire
73
74 // Si l'objet n'est pas de la langue courante, on ajoute hreflang
75 if (!$hlang AND $lang!==$GLOBALS['spip_lang'])
76 $hlang = $lang;
77
78 $lang = ($hlang ? " hreflang='$hlang'" : '');
79
80 if ($title)
81 $title = ' title="'.attribut_html($title).'"';
82 else
83 $title = ''; // $title peut etre 'false'
84 // rel=external pour les liens externes
85 if ((strncmp($lien,'http://',7)==0 OR strncmp($lien,'https://',8)==0)
86 AND strncmp("$lien/", $u ,strlen($u))!=0)
87 $rel = trim("$rel external");
88 if ($rel) $rel = " rel='$rel'";
89
90 // si pas de modele dans le texte du lien, on peut juste passer typo sur le texte, c'est plus rapide
91 // les rares cas de lien qui encapsule un modele passe en dessous, c'est plus lent
92 if (traiter_modeles($texte, false, '', $connect, null, $env)==$texte){
93 $texte = typo($texte, true, $connect, $env);
94 $lien = "<a href=\"".str_replace('"', '&quot;', $lien)."\" class='$class'$lang$title$rel".(isset($mime)?$mime:'').">$texte</a>";
95 return $lien;
96 }
97 # ceci s'execute heureusement avant les tableaux et leur "|".
98 # Attention, le texte initial est deja echappe mais pas forcement
99 # celui retourne par calculer_url.
100 # Penser au cas [<imgXX|right>->URL], qui exige typo('<a>...</a>')
101 $lien = "<a href=\"".str_replace('"', '&quot;', $lien)."\" class='$class'$lang$title$rel$mime>$texte</a>";
102 $res = typo($lien, true, $connect, $env);
103 // dans ce cas, echapons le resultat du modele pour que propre etc ne viennent pas pouicher le html
104 $res = echappe_html("<html>$res</html>");
105 return $res;
106 }
107
108 // Regexp des raccourcis, aussi utilisee pour la fusion de sauvegarde Spip
109 // Laisser passer des paires de crochets pour la balise multi
110 // mais refuser plus d'imbrications ou de mauvaises imbrications
111 // sinon les crochets ne peuvent plus servir qu'a ce type de raccourci
112 define('_RACCOURCI_LIEN', "/\[([^][]*?([[][^]>-]*[]][^][]*)*)->(>?)([^]]*)\]/msS");
113
114 // http://doc.spip.org/@expanser_liens
115 function expanser_liens($t, $connect='', $env=array())
116 {
117
118 $t = pipeline('pre_liens', $t);
119
120 expanser_un_lien($connect,'init', $env);
121
122 if (strpos($t, '->') !== false)
123 $t = preg_replace_callback (_RACCOURCI_LIEN, 'expanser_un_lien',$t);
124
125 // on passe a traiter_modeles la liste des liens reperes pour lui permettre
126 // de remettre le texte d'origine dans les parametres du modele
127 $t = traiter_modeles($t, false, false, $connect, expanser_un_lien('','sources'), $env);
128
129 $t = corriger_typo($t);
130
131 $t = expanser_un_lien($t,'reinsert');
132
133 return $t;
134 }
135
136
137 function expanser_un_lien($reg, $quoi='echappe', $env=null){
138 static $pile = array();
139 static $inserts;
140 static $sources;
141 static $regs;
142 static $k = 0;
143 static $lien;
144 static $connect='';
145 static $contexte = array();
146
147 switch ($quoi){
148 case 'init':
149 if (!$lien) $lien = charger_fonction('lien', 'inc');
150 if (!is_null($env))
151 $contexte = $env;
152 array_push($pile,array($inserts,$sources,$regs,$connect,$k));
153 $inserts = $sources = $regs = array();
154 $connect = $reg; // stocker le $connect pour les appels a inc_lien_dist
155 $k=0;
156 return;
157 break;
158 case 'echappe':
159 $inserts[$k] = '@@SPIP_ECHAPPE_LIEN_' . $k . '@@';
160 $sources[$k] = $reg[0];
161
162 #$titre=$reg[1];
163 list($titre, $bulle, $hlang) = traiter_raccourci_lien_atts($reg[1]);
164 $r = end($reg);
165 // la mise en lien automatique est passee par la a tort !
166 // corrigeons pour eviter d'avoir un <a...> dans un href...
167 if (strncmp($r,'<a',2)==0){
168 $href = extraire_attribut($r, 'href');
169 // remplacons dans la source qui peut etre reinjectee dans les arguments
170 // d'un modele
171 $sources[$k] = str_replace($r,$href,$sources[$k]);
172 // et prenons le href comme la vraie url a linker
173 $r = $href;
174 }
175 $regs[$k] = $lien($r, $titre, '', $bulle, $hlang, '', $connect, $contexte);
176 return $inserts[$k++];
177 break;
178 case 'reinsert':
179 if (count($inserts))
180 $reg = str_replace($inserts, $regs, $reg);
181 list($inserts,$sources,$regs,$connect,$k) = array_pop($pile);
182 return $reg;
183 break;
184 case 'sources':
185 return array($inserts, $sources);
186 break;
187 }
188 }
189
190 // Meme analyse mais pour eliminer les liens
191 // et ne laisser que leur titre, a expliciter si ce n'est fait
192 // http://doc.spip.org/@nettoyer_raccourcis_typo
193 function nettoyer_raccourcis_typo($texte, $connect='')
194 {
195 $texte = pipeline('nettoyer_raccourcis_typo',$texte);
196
197 if (preg_match_all(_RACCOURCI_LIEN, $texte, $regs, PREG_SET_ORDER))
198 include_spip('inc/texte');
199 foreach ($regs as $reg) {
200 list ($titre,,)= traiter_raccourci_lien_atts($reg[1]);
201 if (!$titre) {
202 $match = typer_raccourci($reg[count($reg)-1]);
203 @list($type,,$id,,,,) = $match;
204 if ($type) {
205 $url = generer_url_entite($id,$type,'','',true);
206 if (is_array($url)) list($type, $id) = $url;
207 $titre = traiter_raccourci_titre($id, $type, $connect);
208 }
209 $titre = $titre ? $titre['titre'] : $match[0];
210 }
211 $titre = corriger_typo(supprimer_tags($titre));
212 $texte = str_replace($reg[0], $titre, $texte);
213 }
214
215 // supprimer les ancres
216 $texte = preg_replace(_RACCOURCI_ANCRE,"",$texte);
217
218 // supprimer les notes
219 $texte = preg_replace(",[[][[]([^]]|[]][^]])*[]][]],UimsS","",$texte);
220
221 // supprimer les codes typos
222 $texte = str_replace(array('}','{'), '', $texte);
223
224 // supprimer les tableaux
225 $texte = preg_replace(",(^|\r)\|.*\|\r,s", "\r", $texte);
226
227 return $texte;
228 }
229
230
231
232 // Repere dans la partie texte d'un raccourci [texte->...]
233 // la langue et la bulle eventuelles : [texte|title{lang}->...]
234 // accepte un niveau de paire de crochets dans le texte :
235 // [texte[]|title{lang}->...]
236 // mais refuse
237 // [texte[|title{lang}->...]
238 // pour ne pas confondre avec un autre raccourci
239 define('_RACCOURCI_ATTRIBUTS', '/^((?:[^[]*?(?:\[[^]]*\])?)*?)([|]([^<>]*?))?([{]([a-z_]*)[}])?$/');
240
241 // http://doc.spip.org/@traiter_raccourci_lien_atts
242 function traiter_raccourci_lien_atts($texte) {
243
244 $bulle = $hlang = false;
245 // title et hreflang donnes par le raccourci ?
246 if (strpbrk($texte, "|{") !== false AND
247 preg_match(_RACCOURCI_ATTRIBUTS, $texte, $m)) {
248
249 $n =count($m);
250 // |infobulle ?
251 if ($n > 2) {
252 $bulle = $m[3];
253 // {hreflang} ?
254 if ($n > 4) {
255 // si c'est un code de langue connu, on met un hreflang
256 if (traduire_nom_langue($m[5]) <> $m[5]) {
257 $hlang = $m[5];
258 } elseif (!$m[5]) {
259 $hlang = test_espace_prive() ?
260 $GLOBALS['lang_objet'] : $GLOBALS['spip_lang'];
261 // sinon c'est un italique
262 } else {
263 $m[1] .= $m[4];
264 }
265
266 // S'il n'y a pas de hreflang sous la forme {}, ce qui suit le |
267 // est peut-etre une langue
268 } else if (preg_match('/^[a-z_]+$/', $m[3])) {
269 // si c'est un code de langue connu, on met un hreflang
270 // mais on laisse le title (c'est arbitraire tout ca...)
271 if (traduire_nom_langue($m[3]) <> $m[3]) {
272 $hlang = $m[3];
273 }
274 }
275 }
276 $texte = $m[1];
277 }
278
279 return array(trim($texte), $bulle, $hlang);
280 }
281
282 define('_EXTRAIRE_DOMAINE', '/^(?:(?:[^\W_]((?:[^\W_]|-){0,61}[^\W_,])?\.)+[a-z0-9]{2,6}|localhost)\b/Si');
283
284 define('_RACCOURCI_CHAPO', '/^(\W*)(\W*)(\w*\d+([?#].*)?)$/');
285 /**
286 * Fonction pour les champs virtuels de redirection qui peut etre:
287 * 1. un raccourci Spip habituel (premier If) [texte->TYPEnnn]
288 * 2. un ultra raccourci TYPEnnn voire nnn (article) (deuxieme If)
289 * 3. une URL std
290 *
291 * renvoie l'url reelle de redirection si le $url=true,
292 * l'url brute contenue dans le chapo sinon
293 *
294 * http://doc.spip.org/@chapo_redirige
295 *
296 * @param string $virtuel
297 * @param bool $url
298 * @return string
299 */
300 function virtuel_redirige($virtuel, $url=false){
301 if (!strlen($virtuel)) return '';
302 if (!preg_match(_RACCOURCI_LIEN, $virtuel, $m))
303 if (!preg_match(_RACCOURCI_CHAPO, $virtuel, $m))
304 return $virtuel;
305
306 return !$url ? $m[3] : traiter_lien_implicite($m[3]);
307 }
308
309
310 // Cherche un lien du type [->raccourci 123]
311 // associe a une fonction generer_url_raccourci() definie explicitement
312 // ou implicitement par le jeu de type_urls courant.
313 //
314 // Valeur retournee selon le parametre $pour:
315 // 'tout' : tableau d'index url,class,titre,lang (vise <a href="U" class='C' hreflang='L'>T</a>)
316 // 'titre': seulement T ci-dessus (i.e. le TITRE ci-dessus ou dans table SQL)
317 // 'url': seulement U (i.e. generer_url_RACCOURCI)
318
319 // http://doc.spip.org/@calculer_url
320 function calculer_url ($ref, $texte='', $pour='url', $connect='', $echappe_typo = true) {
321 $r = traiter_lien_implicite($ref, $texte, $pour, $connect, $echappe_typo);
322 $r = ($r ? $r : traiter_lien_explicite($ref, $texte, $pour, $connect, $echappe_typo));
323 return $r;
324 }
325
326 define('_EXTRAIRE_LIEN', ",^\s*(http:?/?/?|mailto:?)\s*$,iS");
327
328 // http://doc.spip.org/@traiter_lien_explicite
329 function traiter_lien_explicite ($ref, $texte='', $pour='url', $connect='', $echappe_typo = true)
330 {
331 if (preg_match(_EXTRAIRE_LIEN, $ref))
332 return ($pour != 'tout') ? '' : array('','','','');
333
334 $lien = entites_html(trim($ref));
335
336 // Liens explicites
337 if (!$texte) {
338 $texte = str_replace('"', '', $lien);
339 static $lien_court;
340 // evite l'affichage de trop longues urls.
341 if (!$lien_court)
342 $lien_court = charger_fonction('lien_court', 'inc');
343 $texte = $lien_court($texte);
344 if ($echappe_typo){
345 $texte = "<html>".quote_amp($texte)."</html>";
346 }
347 }
348
349 // petites corrections d'URL
350 if (preg_match('/^www\.[^@]+$/S',$lien))
351 $lien = "http://".$lien;
352 else if (strpos($lien, "@") && email_valide($lien)) {
353 if (!$texte) $texte = $lien;
354 $lien = "mailto:".$lien;
355 }
356
357 if ($pour == 'url') return $lien;
358
359 if ($pour == 'titre') return $texte;
360
361 return array('url' => $lien, 'titre' => $texte);
362 }
363
364 function liens_implicite_glose_dist($texte,$id,$type,$args,$ancre,$connect=''){
365 if (function_exists($f = 'glossaire_' . $ancre))
366 $url = $f($texte, $id);
367 else
368 $url = glossaire_std($texte);
369 return $url;
370 }
371
372 /**
373 * Transformer un lien raccourci art23 en son URL
374 * Par defaut la fonction produit une url prive si on est dans le prive
375 * ou publique si on est dans le public.
376 * La globale lien_implicite_cible_public permet de forcer un cas ou l'autre :
377 * $GLOBALS['lien_implicite_cible_public'] = true;
378 * => tous les liens raccourcis pointent vers le public
379 * $GLOBALS['lien_implicite_cible_public'] = false;
380 * => tous les liens raccourcis pointent vers le prive
381 * unset($GLOBALS['lien_implicite_cible_public']);
382 * => retablit le comportement automatique
383 *
384 * http://doc.spip.org/@traiter_lien_implicite
385 *
386 * @param string $ref
387 * @param string $texte
388 * @param string $pour
389 * @param string $connect
390 * @return array|bool|string
391 */
392 function traiter_lien_implicite ($ref, $texte='', $pour='url', $connect='')
393 {
394 $cible = ($connect ? $connect : (isset($GLOBALS['lien_implicite_cible_public'])?$GLOBALS['lien_implicite_cible_public']:null));
395 if (!($match = typer_raccourci($ref))) return false;
396 @list($type,,$id,,$args,,$ancre) = $match;
397 # attention dans le cas des sites le lien doit pointer non pas sur
398 # la page locale du site, mais directement sur le site lui-meme
399 $url = '';
400 if ($f = charger_fonction("implicite_$type","liens",true))
401 $url = $f($texte,$id,$type,$args,$ancre,$connect);
402 if (!$url)
403 $url = generer_url_entite($id,$type,$args,$ancre,$cible);
404 if (!$url) return false;
405 if (is_array($url)) {
406 @list($type,$id) = $url;
407 $url = generer_url_entite($id,$type,$args,$ancre,$cible);
408 }
409 if ($pour === 'url') return $url;
410 $r = traiter_raccourci_titre($id, $type, $connect);
411 if ($r) $r['class'] = ($type == 'site')?'spip_out':'spip_in';
412 if ($texte = trim($texte)) $r['titre'] = $texte;
413 if (!@$r['titre']) $r['titre'] = _T($type) . " $id";
414 if ($pour=='titre') return $r['titre'];
415 $r['url'] = $url;
416
417 // dans le cas d'un lien vers un doc, ajouter le type='mime/type'
418 if ($type == 'document'
419 AND $mime = sql_getfetsel('mime_type', 'spip_types_documents',
420 "extension IN (SELECT extension FROM spip_documents where id_document =".intval($id).")",
421 '','','','',$connect)
422 )
423 $r['mime'] = $mime;
424
425 return $r;
426 }
427
428 // analyse des raccourcis issus de [TITRE->RACCOURCInnn] et connexes
429
430 define('_RACCOURCI_URL', '/^\s*(\w*?)\s*(\d+)(\?(.*?))?(#([^\s]*))?\s*$/S');
431
432 // http://doc.spip.org/@typer_raccourci
433 function typer_raccourci ($lien) {
434 if (!preg_match(_RACCOURCI_URL, $lien, $match)) return array();
435 $f = $match[1];
436 // valeur par defaut et alias historiques
437 if (!$f) $f = 'article';
438 else if ($f == 'art') $f = 'article';
439 else if ($f == 'br') $f = 'breve';
440 else if ($f == 'rub') $f = 'rubrique';
441 else if ($f == 'aut') $f = 'auteur';
442 else if ($f == 'doc' OR $f == 'im' OR $f == 'img' OR $f == 'image' OR $f == 'emb')
443 $f = 'document';
444 else if (preg_match('/^br..?ve$/S', $f)) $f = 'breve'; # accents :(
445 $match[0] = $f;
446 return $match;
447 }
448
449 // Retourne le champ textuel associe a une cle primaire, et sa langue
450 function traiter_raccourci_titre($id, $type, $connect=NULL)
451 {
452 $trouver_table = charger_fonction('trouver_table', 'base');
453 $desc = $trouver_table(table_objet($type));
454 if (!($desc AND $s = $desc['titre'])) return array();
455 $_id = $desc['key']['PRIMARY KEY'];
456 $r = sql_fetsel($s, $desc['table'], "$_id=$id", '','','','',$connect);
457 if (!$r) return array();
458 $r['titre'] = supprimer_numero($r['titre']);
459 if (!$r['titre']) $r['titre'] = $r['surnom'];
460 if (!isset($r['lang'])) $r['lang'] = '';
461 return $r;
462 }
463
464 // traite les modeles (dans la fonction typo), en remplacant
465 // le raccourci <modeleN|parametres> par la page calculee a
466 // partir du squelette modeles/modele.html
467 // Le nom du modele doit faire au moins trois caracteres (evite <h2>)
468 // Si $doublons==true, on repere les documents sans calculer les modeles
469 // mais on renvoie les params (pour l'indexation par le moteur de recherche)
470 // http://doc.spip.org/@traiter_modeles
471 define('_PREG_MODELE',
472 '(<([a-z_-]{3,})' # <modele
473 .'\s*([0-9]*)\s*' # id
474 .'([|](?:<[^<>]*>|[^>])*?)?' # |arguments (y compris des tags <...>)
475 .'\s*/?'.'>)' # fin du modele >
476 );
477
478 define('_RACCOURCI_MODELE',
479 _PREG_MODELE
480 .'\s*(<\/a>)?' # eventuel </a>
481 );
482
483 define('_RACCOURCI_MODELE_DEBUT', '@^' . _RACCOURCI_MODELE .'@isS');
484
485 // http://doc.spip.org/@traiter_modeles
486 function traiter_modeles($texte, $doublons=false, $echap='', $connect='', $liens = null, $env = array()) {
487 // preserver la compatibilite : true = recherche des documents
488 if ($doublons===true)
489 $doublons = array('documents'=>array('doc','emb','img'));
490 // detecter les modeles (rapide)
491 if (strpos($texte,"<")!==false AND
492 preg_match_all('/<[a-z_-]{3,}\s*[0-9|]+/iS', $texte, $matches, PREG_SET_ORDER)) {
493 include_spip('public/assembler');
494 foreach ($matches as $match) {
495 // Recuperer l'appel complet (y compris un eventuel lien)
496
497 $a = strpos($texte,$match[0]);
498 preg_match(_RACCOURCI_MODELE_DEBUT,
499 substr($texte, $a), $regs);
500 while(count($regs) < 6) $regs[] = ""; // s'assurer qu'il y a toujours un 5e arg, eventuellement vide
501 list(,$mod, $type, $id, $params, $fin) = $regs;
502 if ($fin AND
503 preg_match('/<a\s[^<>]*>\s*$/i',
504 substr($texte, 0, $a), $r)) {
505 $lien = array(
506 'href' => extraire_attribut($r[0],'href'),
507 'class' => extraire_attribut($r[0],'class'),
508 'mime' => extraire_attribut($r[0],'type')
509 );
510 $n = strlen($r[0]);
511 $a -= $n;
512 $cherche = $n + strlen($regs[0]);
513 } else {
514 $lien = false;
515 $cherche = strlen($mod);
516 }
517
518 // calculer le modele
519 # hack indexation
520 if ($doublons)
521 $texte .= preg_replace(',[|][^|=]*,s',' ',$params);
522 # version normale
523 else {
524 // si un tableau de liens a ete passe, reinjecter le contenu d'origine
525 // dans les parametres, plutot que les liens echappes
526 if (!is_null($liens))
527 $params = str_replace($liens[0], $liens[1], $params);
528 $modele = inclure_modele($type, $id, $params, $lien, $connect, $env);
529 // en cas d'echec,
530 // si l'objet demande a une url,
531 // creer un petit encadre vers elle
532 if ($modele === false) {
533 $modele = substr($texte,$a,$cherche);
534 if (!is_null($liens))
535 $modele = str_replace($liens[0], $liens[1], $modele);
536 $contexte = array_merge($env,array('id'=>$id,'type'=>$type,'modele'=>$modele));
537 if ($lien) {
538 # un eventuel guillemet (") sera reechappe par #ENV
539 $contexte['lien'] = str_replace("&quot;",'"', $lien['href']);
540 $contexte['lien_class'] = $lien['class'];
541 $contexte['lien_mime'] = $lien['mime'];
542 }
543 $modele = recuperer_fond("modeles/dist", $contexte, array(), $connect);
544 }
545 // le remplacer dans le texte
546 if ($modele !== false) {
547 $modele = protege_js_modeles($modele);
548 $rempl = code_echappement($modele, $echap);
549 $texte = substr($texte, 0, $a)
550 . $rempl
551 . substr($texte, $a+$cherche);
552 }
553 }
554
555 // hack pour tout l'espace prive
556 if (((!_DIR_RESTREINT) OR ($doublons)) AND ($id)){
557 foreach($doublons?$doublons:array('documents'=>array('doc','emb','img')) as $quoi=>$modeles)
558 if (in_array($type,$modeles))
559 $GLOBALS["doublons_{$quoi}_inclus"][] = $id;
560 }
561 }
562 }
563
564 return $texte;
565 }
566
567 //
568 // Raccourcis ancre [#ancre<-]
569 //
570
571 define('_RACCOURCI_ANCRE', "/\[#?([^][]*)<-\]/S");
572
573 // http://doc.spip.org/@traiter_raccourci_ancre
574 function traiter_raccourci_ancre($letexte)
575 {
576 if (preg_match_all(_RACCOURCI_ANCRE, $letexte, $m, PREG_SET_ORDER))
577 foreach ($m as $regs)
578 $letexte = str_replace($regs[0],
579 '<a name="'.entites_html($regs[1]).'"></a>', $letexte);
580 return $letexte;
581 }
582
583 //
584 // Raccourcis automatiques [?SPIP] vers un glossaire
585 // Wikipedia par defaut, avec ses contraintes techniques
586 // cf. http://fr.wikipedia.org/wiki/Wikip%C3%A9dia:Conventions_sur_les_titres
587
588 define('_RACCOURCI_GLOSSAIRE', "/\[\?+\s*([^][<>]+)\]/S");
589 define('_RACCOURCI_GLOSES', '/^([^|#{]*\w[^|#{]*)([^#]*)(#([^|{}]*))?(.*)$/S');
590
591 // http://doc.spip.org/@traiter_raccourci_glossaire
592 function traiter_raccourci_glossaire($texte)
593 {
594 if (!preg_match_all(_RACCOURCI_GLOSSAIRE,
595 $texte, $matches, PREG_SET_ORDER))
596 return $texte;
597
598 include_spip('inc/charsets');
599 $lien = charger_fonction('lien', 'inc');
600
601 foreach ($matches as $regs) {
602 // Eviter les cas particulier genre "[?!?]"
603 // et isoler le lexeme a gloser de ses accessoires
604 // (#:url du glossaire, | bulle d'aide, {} hreflang)
605 // Transformation en pseudo-raccourci pour passer dans inc_lien
606 if (preg_match(_RACCOURCI_GLOSES, $regs[1], $r)) {
607 preg_match('/^(.*?)(\d*)$/', $r[4], $m);
608 $_n = intval($m[2]);
609 $gloss = $m[1] ? ('#' . $m[1]) : '';
610 $t = $r[1] . $r[2] . $r[5];
611 list($t, $bulle, $hlang) = traiter_raccourci_lien_atts($t);
612 if ($bulle===false) $bulle = $m[1];
613 $t = unicode2charset(charset2unicode($t), 'utf-8');
614 $ref = $lien("glose$_n$gloss", $t, 'spip_glossaire', $bulle, $hlang);
615 $texte = str_replace($regs[0], $ref, $texte);
616 }
617 }
618 return $texte;
619 }
620
621 // http://doc.spip.org/@glossaire_std
622 function glossaire_std($terme)
623 {
624 global $url_glossaire_externe;
625 static $pcre = NULL;
626
627 if ($pcre === NULL) {
628 $pcre = isset($GLOBALS['meta']['pcre_u'])
629 ? $GLOBALS['meta']['pcre_u']
630 : '';
631 if (strpos($url_glossaire_externe, "%s") === false)
632 $url_glossaire_externe .= '%s';
633 }
634
635 $glosateur = str_replace("@lang@",
636 $GLOBALS['spip_lang'],
637 $GLOBALS['url_glossaire_externe']);
638
639 $terme = rawurlencode(preg_replace(',\s+,'.$pcre, '_', $terme));
640
641 return str_replace("%s", $terme, $glosateur);
642 }
643
644 ?>