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