_relatedlinks_filter(): Not quite right
| Project: | Related links |
| Version: | 5.x-2.2-beta |
| Component: | Code |
| Category: | bug report |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | active |
Jump to:
The code that generates the actual link for relatedlinks blocks reads as follows:
<?php
$urls[] = '<a href="'. check_url($link['url']) .'">'. check_plain($link['title']) .'</a>';
?>I can see why it uses check_url() instead of, say, url() or l(); the URL has to be derived from a single line and therefore may contain a query string, making it unsuitable for processing by those functions (which take query string as a separate parameter). Unfortunately this is a source of fail for manual links on a site that uses clean URLs, since it does not prepend base_path() - if your page has a url of 'node/1' and has a relatedlink of 'node/2' set, clicking on the link will take you to 'node/node/2'. It's interpreted as a relative link instead of absolute. (Also this doesn't use any path aliases that don't exist, though I'm aware this is listed as a "To Do" for the function.)
I think ideally we'd need to parse the URL at this stage and break it into path / query, and then run it through url() or l()[1] to get the fully-qualified, base_path() prepended, clean-or-not-clean path for proper internal/external use.
Unfortunately, I don't know (or have the time to work out) how to do that, so I've slapped together a quick fix for my own use. It's very rudimentary and does assume that you're using clean URLs but might be a starting point for somebody. It also includes some switching for external links (http://, https://) and tries to fetch an alias if appropriate. Finally I added another $url_cache line, so that both the aliased and un-aliased URLs get cached. I don't imagine a massive performance hit if the same URL gets cached twice, but I'd welcome suggestions regarding better ways of doing this.
<?php
function _relatedlinks_filter($links) {
$urls = array();
$url_cache = array();
foreach ($links as $link) {
if (!in_array($link['url'], $url_cache)) {
// Added this $url_cache line:
$url_cache[] = $link['url'];
if (empty($link['title'])) {
// URLs without a title display the URL.
$link['title'] = $link['url'];
}
// Added this IF clause:
if (strpos($link['url'], 'http://') !== 0 && strpos($link['url'], 'https://') !== 0) {
$link['url'] = drupal_get_path_alias($link['url']); // returns original path if path not found
if (strpos($link['url'], '/') !== 0) {
$link['url'] = base_path() . $link['url'];
}
}
// End of added code
$url_cache[] = $link['url'];
$urls[] = '<a href="'. check_url($link['url']) .'">'. check_plain($link['title']) .'</a>';
}
}
return $urls;
}
?>[1] ... Actually, what we really need to do is remove this HTML formatting from the _filter function, and shift it into the theme_relatedlinks function. But that would be a pretty fundamental shift in the way theme_relatedlinks works, rather than a straightforward fix to already existing functionality, so maybe that's outside the scope of this issue.

#1
Oh hey I guess I already came up against this last year - #313663: Bug when used with pathauto. FWIW, now I've thought about why clean_url is being used I kind of disagree with the change made in that patch.