Dieses SPIP Filter unterlegt in einem Text vorkommende Schlagworte automatisch mit einem Link zur Definition. Entworfen wurde es für http://www.apotheke-scheibbs.at. Es wird ebenfalls auf dieser Site verwendet (siehe unten für eine Funktionsbeschreibung).
Installation: untenstehenden Code in mes_fonctions.php einfügen und Squelette entsprechend anpassen.
/***********************************************************/
// autolink keywords in articles (version 5):
// webmaster (at) iapetus.ch or webmaster (at) apotheke-scheibbs.at
// site: http://www.iapetus.ch or http://www.apotheke-scheibbs.at
// usage : [(#TEXTE*|liens_mots|propre)]
// or : [(#TEXTE*|liens_mots{4}|propre)]
// or : [(#TEXTE*|liens_mots{4,en}|propre)]
// to only replace the 4 first occurences of each keyword, set to -1 to replace all
function liens_mots($texte, $count = -1,$lang='') {
global $traduc_hash_lang;
$query_liens_autos = "SELECT id_mot, titre, type FROM spip_mots ".
"as liens ORDER BY CHAR_LENGTH(titre) DESC";
$result_liens_autos = spip_query($query_liens_autos);
$regexp_echap = "/(<html>.*?<\/html>|<code>.*?<\/code>|<cadre>.*?<\/cadre>)/si";
$elements = preg_split($regexp_echap,$texte,-1,PREG_SPLIT_DELIM_CAPTURE);
foreach (array_keys($elements) as $key) {
$block =& $elements[$key];
if ($lang == '') { //
$lang = $GLOBALS['spip_lang'];
}
if (!preg_match($regexp_echap, $block)) {
$block .= '['; // append a delimiter to simplify the pattern
mysql_data_seek($result_liens_autos, 0);
while($row_liens = mysql_fetch_array($result_liens_autos)) {
$lang_mot = extraire_alphanumero($row_liens["type"]);
if (($lang=='tous') || ($lang_mot == $lang) || (strlen($lang_mot) == 0)) {
if (!$countdown[$row_liens["titre"]]) $countdown[$row_liens["titre"]] = $count;
$regexp_search = '/\\b'.preg_quote($row_liens["titre"],'/').'\\b(?=[^\\]]*?\\[)/';
$regexp_replace = '[' . $row_liens["titre"].'-> mot'.$row_liens["id_mot"].']';
if ($count != -1) {
$delta = preg_match_all($regexp_search,$block,$matches);
$block = preg_replace($regexp_search, $regexp_replace, $block, $countdown[$row_liens["titre"]]);
$countdown[$row_liens["titre"]] = max(0, $countdown[$row_liens["titre"]]-$delta);
}
else
$block=preg_replace($regexp_search,$regexp_replace,$block);
}
}
$block = substr($block, 0, -1); // remove [ - delimiter
}
}
return implode($elements);
}
/***********************************************************/
Funktionsbeschreibung
Zuerst wird $texte in code, html und sonstige Textblöcke aufgeteilt. code und html-Blöcke werden nicht modifiziert. Alle anderen Blöcke werden nach zu ersetzenden Schlagwörtern durchsucht.
Das Regex-Pattern matcht Wörter aus der Liste $row_lines in $block, die sich nicht zwischen eckigen Klammern befinden. preg_replace ersetzt diese Wörter durch einen SPIP-Link auf die Definition des Wortes.
Das Pattern sieht ohne PHP-String-Escaping so aus:
/ : Patternanfang
\b : Wortgrenze \
wort : der Suchbegriff ¦- wird durch [wort->mot21]-Link ersetzt
\b : Wortgrenze /
(?= : Lock Ahead Match Anfang
[^\]]*? : so viele Zeichen wie möglich ohne ] ,
weil sonst wäre der Suchbegriff innerhalb []
\[ : abschliessendes [, entweder der Anfang
vom nächsten Klammernpaar oder das [ -Zeichen
am Stringende
) : Ende Lock Ahead
/ : Patternende
Da der Suchbegriff direkt in das Pattern eingesetzt wird (anstelle von wort), muss er ’patternkompatibel’ mit preg_quote escaped werden - sonst ergeben Sonderzeichen und / oder \ im Suchbegriff einen Syntaxfehler im Pattern.
Weil das Pattern als String in PHP verwendet wird, muss es noch PHP-String-Escaped werden (d.h. alle \ verdoppeln und ’ duch \’ ersetzen), was zusammen mit preg_quote folgendes ergibt:
'/\\b'.preg_quote($row_liens["titre"],'/').'\\b(?=[^\\]]*?\\[)/'
Alle Matches werden dann von preg_replace durch
'[' . $row_liens["titre"].'-> mot'.$row_liens["id_mot"].']'
ersetzt.
Das Pattern funktioniert nur, wenn mindestens eine öffnende eckige Klammer im Text vorkommt (sonst funktioniert der Lock Ahead Match nicht). Die Funktion wird garantiert, indem vor dem Matching eine öffnende eckige Klammer am Ende angefügt wird. Dieser Delimiter wird nachher wieder entfernt.
Zum Schluss werden alle Blöcke (modifizierte und nicht modifizierte) wieder zusammengefügt.