| Project: | freelinking |
| Version: | 4.7.x-1.0 |
| Component: | Code |
| Category: | bug report |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | closed (fixed) |
Issue Summary
Related to and also resolves: http://drupal.org/node/128816
The issue I was having was related to links of this form:
[[Some CamelCase Here|Link Name]]
I mentioned this http://drupal.org/node/48326 and was told it was nightmarish. Which I agree, it can be. But I thought I'd give the solution a shot anyway. It involves splitting the filter into two passes. The first handles bracketed links, and the second the CamelCase links. Here is the modified _freelinking_do_filtering function:
function _freelinking_do_filtering($text, $store = FALSE) {
// First pass. Only bracketed links
$freelinkingregexp = '/\[\[.+]]/U'; // this finds [[ links like this]], un-greedily
preg_match_all($freelinkingregexp, $text, $flmatches);
$wikiwords = $flmatches[0];
$tokens = $phrases = $replacements = array();
foreach (array_unique($wikiwords) as $wikiword) {
if (substr($wikiword, 0, 2) == '[[') { // if it's a freelink, the expressions are different
$phrase = substr($wikiword, 2, -2);
$freelink = $phrase;
$barpos = strpos($phrase, '|');
$pattern = '/\[\[' . preg_quote($phrase, '/') . ']]/';
if ($barpos) {
$freelink = substr($freelink, 0, $barpos);
$phrase = substr($phrase, $barpos + 1);
}
if (preg_match('/^(http|mailto|https|ftp):/', $freelink)) {
$replacement = '<a class="freelinking external" href="' . $freelink . '">' . $phrase . '</a>';
}
else {
$replacement = l($phrase, 'freelinking/' . rawurlencode($freelink), array('class' => 'freelinking'));
}
}
$index = count($tokens);
$token = '::TOKEN'.$index.'::';
$tokens[$index] = '/'.$token.'/';
$phrases[$index] = $phrase;
$replacements[$index] = $replacement;
$text = preg_replace($pattern, $token, $text);
} // foreach wikiword
// Second pass. CamelCase links (if required).
$allowcamelcase = variable_get("freelinking_camelcase", TRUE);
$cctokens = $ccphrases = $ccreplacements = array();
if ($allowcamelcase) {
$camelcaseregexp = '/\b([[:upper:]][[:lower:][:digit:]]+){2,}\b/'; // this gets us close, but is not perfect. Example: ThisIsACamelCaseWord won't match
preg_match_all($camelcaseregexp, $text, $ccmatches);
$wikiwords = $ccmatches[0];
foreach (array_unique($wikiwords) as $wikiword) {
$pattern = '/\b' . $wikiword . '\b(?![^<]*>)/';
$phrase = $wikiword; // consistency for the db
$freelink = $wikiword; // also for the db
$replacement = l($wikiword, 'freelinking/' . urlencode($wikiword));
$index = count($cctokens);
$token = '::CCTOKEN'.$index.'::';
$cctokens[$index] = '/'.$token.'/';
$ccphrases[$index] = $phrase;
$ccreplacements[$index] = $replacement;
$text = preg_replace($pattern, $token, $text);
} // foreach wikiword
}
// Replace the tokens
ksort($tokens);
ksort($replacements);
$text = preg_replace($tokens, $replacements, $text);
ksort($cctokens);
ksort($ccreplacements);
$text = preg_replace($cctokens, $ccreplacements, $text, variable_get("freelinking_onceonly", 0) ? 1 : -1);
if ($store) {
ksort($phrases);
foreach ($phrases as $key => $phrase) {
_freelinking_store($phrases[$key], $replacements[$key]);
}
if ($allowcamelcase) {
ksort($ccphrases);
foreach ($ccphrases as $key => $phrase) {
_freelinking_store($ccphrases[$key], $ccreplacements[$key]);
}
}
}
return $text;
} // endfunction _freelinking_do_filteringThe filter runs in three passes: the first for bracketed links; the second for CamelCase links. These two replaces the links with a token. In the final pass, the tokens will be replaced with the actual links.
Should work for:
[[Some CamelCase Here|Link Text]]
[[CamelCase|Link Text]]
CamelCase
I would appreciate any feedback for this patch. It seems to do what is expected, but there may be cases I have not considered.
Comments
#1
Interesting idea. Care to make this a real patch? http://drupal.org/patch/create
#2
Attached. :)
Let me know if there're any problems with it.
#3
Tweaked. It now correctly supports "Only link first occurance" for CamelCase.
#4
Subscribing. (Turned off CamelCase to get around this.)
#5
Fixed in freelinking-6.x-1.7. Please verify and close.
#6
Automatically closed -- issue fixed for two weeks with no activity.