function _lexicon_insertlink in Lexicon 6
Same name and namespace in other branches
- 7 lexicon.module \_lexicon_insertlink()
Insert lexicon links to $text after every matching $terms[i]['synonyms'] that is not inside a blocking tag. $terms[i]['ins_before'] is prepended to the matches, $terms[i]['ins_after'] is appended to them. Match type and replace mode all depend on user settings. The text is scanned once for all blocking tags and matches, then those 'events' are sorted and handled one by one.
1 call to _lexicon_insertlink()
- _lexicon_filter_process in ./
lexicon.module - Mark lexicon vocabulary terms in the body text.
File
- ./
lexicon.module, line 615 - Lexicon is used to create lists of terms and definitions to use on a website and optionally mark them in the content with an indicator.
Code
function _lexicon_insertlink(&$text, &$terms) {
$multibyte_enabled = extension_loaded('mbstring');
if ($multibyte_enabled) {
$mb_prefix = 'mb_';
}
else {
$mb_prefix = NULL;
}
$case_sensitive = variable_get("lexicon_case", '1');
$findfunc = $mb_prefix . 'strpos';
$findtagfunc = $mb_prefix . 'strpos';
$replaceall = variable_get("lexicon_replace_all", 0);
$events = array();
// Find blocking tags.
$open_tags = array(
'[no-lexicon]',
'<',
'<a ',
'[code',
);
$close_tags = array(
'[/no-lexicon]',
'>',
'</a>',
'[/code]',
);
$user_tags = explode(' ', variable_get("lexicon_blocking_tags", 'abbr acronym'));
foreach ($user_tags as $tag) {
if (!empty($tag)) {
if (ctype_alnum($tag)) {
$open_tags[] = "<{$tag}";
$close_tags[] = "</{$tag}>";
}
elseif ($tag[0] == '.') {
$open_tags[] = '<span class="' . drupal_substr($tag, 1);
$close_tags[] = "</span>";
}
}
}
$searchtext = $case_sensitive ? $text : drupal_strtolower($text);
foreach ($open_tags as $i => $tag) {
$offset = 0;
while (($offset = $findtagfunc($searchtext, $tag, $offset)) !== FALSE) {
// Longer tags will override shorter '<' on the same offset.
$events[$offset] = array(
'type' => 'open',
'which' => $i,
);
$offset += drupal_strlen($tag);
}
}
// Find match candidates.
foreach ($terms as $i => $term) {
foreach ($term['synonyms'] as $synonym) {
if (!$case_sensitive) {
$synonym = drupal_strtolower($synonym);
}
$offset = 0;
$first_match_found = FALSE;
while (($offset = $findfunc($searchtext, $synonym, $offset)) !== FALSE) {
$len = drupal_strlen($synonym);
$match = drupal_substr($text, $offset, $len);
// Only longer matches override shorter ones.
if (!isset($events[$offset]) || drupal_strlen($events[$offset]['match']) < drupal_strlen($match)) {
// Get synonym with case as in text.
$events[$offset] = array(
'type' => 'match',
'which' => $i,
'match' => $match,
);
if (!$replaceall) {
$first_match_found = TRUE;
break;
}
}
$offset += $len;
}
if ($first_match_found && !$replaceall) {
break;
}
}
}
ksort($events);
$newtext = '';
$parsed = 0;
// Text was parsed from chars 0 to $parsed (exclusive).
foreach ($events as $place => $event) {
// Skip events inside blocking tag (they're already copied as is).
if ($place < $parsed) {
continue;
}
// Copy plain text (with no events).
$newtext .= drupal_substr($text, $parsed, $place - $parsed);
$parsed = $place;
// If a blocking tag is opened, skip to closing tag.
if ($event['type'] == 'open') {
$skip = $findtagfunc($text, $close_tags[$event['which']], $place);
if ($skip === FALSE) {
$skip = drupal_strlen($text);
}
// If the tag is [no-lexicon] - remove it with the closing tag (by incrementing $parsed without copying).
if ($event['which'] == 0) {
$parsed += drupal_strlen($open_tags[$event['which']]);
$newtext .= drupal_substr($text, $parsed, $skip - $parsed);
$parsed = $skip + drupal_strlen($close_tags[$event['which']]);
}
else {
$newtext .= drupal_substr($text, $parsed, $skip - $parsed);
$parsed = $skip;
}
}
if ($event['type'] == 'match') {
$matchlen = drupal_strlen($event['match']);
$proper_match = FALSE;
switch (variable_get("lexicon_match", 'b')) {
case 'lr':
// Require word break left or right.
$proper_match = _lexicon_is_boundary(drupal_substr($text, $place - 1, 1)) || _lexicon_is_boundary(drupal_substr($text, $place + $matchlen, 1));
break;
case 'b':
// Require word break left and right.
$proper_match = _lexicon_is_boundary(drupal_substr($text, $place - 1, 1)) && _lexicon_is_boundary(drupal_substr($text, $place + $matchlen, 1));
break;
case 'l':
// Require word break left.
$proper_match = _lexicon_is_boundary(drupal_substr($text, $place - 1, 1));
break;
case 'r':
// Require word break right.
$proper_match = _lexicon_is_boundary(drupal_substr($text, $place + $matchlen, 1));
break;
case 's':
// Match any substring.
default:
$proper_match = TRUE;
break;
}
if ($proper_match) {
$newtext .= $terms[$event['which']]['ins_before'] . $event['match'] . $terms[$event['which']]['ins_after'];
$parsed += $matchlen;
}
}
}
// Append remaining part.
return $newtext . drupal_substr($text, $parsed);
}