elf.module in External Links Filter 6.3
Same filename and directory in other branches
Adds an icon to external and mailto links.
File
elf.moduleView source
<?php
/**
* @file
* Adds an icon to external and mailto links.
*/
/**
* Implementation of hook_init().
*/
function elf_init() {
require_once 'includes/common.inc';
$path = drupal_get_path('module', 'elf');
drupal_add_css("{$path}/css/elf.css");
if (variable_get('elf_window', FALSE)) {
drupal_add_js("{$path}/js/elf.js");
}
}
/**
* Implementation of hook_menu().
*/
function elf_menu() {
$items['admin/settings/filters/elf'] = array(
'title' => 'External Links Filter',
'description' => 'Configure the external links filter.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'elf_form_settings',
),
'access arguments' => array(
'administer site configuration',
),
'type' => MENU_NORMAL_ITEM,
);
$items['elf/go'] = array(
'page callback' => 'elf_redirect',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Implementation of hook_filter().
*/
function elf_filter($op, $delta = 0, $format = -1, $text = '', $cache_id = 0) {
switch ($op) {
case 'list':
return array(
0 => t('Add an icon to external and mailto links'),
);
case 'process':
return elf_replace($text, $format);
case 'settings':
$form['elf'] = array(
'#type' => 'fieldset',
'#title' => t('External links filter'),
'#collapsible' => TRUE,
);
$form['elf']["elf_nofollow_{$format}"] = array(
'#type' => 'checkbox',
'#title' => t('Add !nofollow to external links', array(
'!nofollow' => '<code>rel="nofollow"</code>',
)),
'#default_value' => variable_get("elf_nofollow_{$format}", FALSE),
);
return $form;
default:
return $text;
}
}
/**
* Admin settings form.
*
* @see elf_form_settings_submit()
*/
function elf_form_settings(array &$form_state) {
$domains = variable_get('elf_domains', array());
$form['elf_domains'] = array(
'#type' => 'textarea',
'#default_value' => implode("\n", $domains),
'#title' => t('Internal domains'),
'#description' => t('If your site spans multiple domains, specify each of them on a new line to prevent them from being seen as external sites. Make sure to include the right protocol; !example_right, and not !example_wrong, for instance. Asterisks are wildcards.', array(
'!example_right' => '<code>http://example.com</code>',
'!example_wrong' => '<code>example.com</code>',
)),
);
$form['elf_window'] = array(
'#type' => 'checkbox',
'#default_value' => variable_get('elf_window', FALSE),
'#title' => t('Use JavaScript to open external links in a new window'),
);
$form['elf_redirect'] = array(
'#type' => 'checkbox',
'#default_value' => variable_get('elf_redirect', FALSE),
'#title' => t('Redirect users to external websites via !url_path.', array(
'!url_path' => '<code>/elf/go</code>',
)),
);
return system_settings_form($form);
}
/**
* Form validation handler for elf_form_settings().
*
* @see elf_form_settings()
*/
function elf_form_settings_validate(array $form, array &$form_state) {
$values = preg_split('#\\s#', $form_state['values']['elf_domains']);
$domains = array();
$errors = array();
foreach ($values as $value) {
// Remove trailing slashes, because not all users will use those for their links.
$value = trim($value, '/');
if (strlen($value)) {
if (!menu_path_is_external($value)) {
$errors[] = $value;
}
$domains[] = $value;
}
}
if ($errors) {
form_set_error('elf_domains', format_plural(count($errors), '%domain is not a valid external domain.', '%domain are no valid external domains', array(
'%domain' => implode(', ', $errors),
)));
}
else {
form_set_value($form['elf_domains'], array_unique($domains), $form_state);
}
}
/**
* Add classes to external or mailto links in a text.
*
* @param $text string
* The text to filter.
*
* @return string
* The (filtered) text.
*/
function elf_replace($text, $format) {
$document = elf_filter_dom_load($text);
$links = $document
->getElementsByTagName('a');
foreach ($links as $a) {
if ($href = $a
->getAttribute('href')) {
// This is a mailto link.
if (strpos($href, 'mailto:') === 0) {
$a
->setAttribute('class', $a
->getAttribute('class') ? $a
->getAttribute('class') . ' elf-mailto elf-icon' : 'elf-mailto elf-icon');
}
elseif (elf_url_external($href)) {
// Add external class.
$a
->setAttribute('class', $a
->getAttribute('class') ? $a
->getAttribute('class') . ' elf-external elf-icon' : 'elf-external elf-icon');
if ($a
->getElementsByTagName('img')->length > 0) {
$a
->setAttribute('class', $a
->getAttribute('class') ? $a
->getAttribute('class') . ' elf-img' : 'elf-img');
}
// Add nofollow.
$nofollow = variable_get("filter_html_nofollow_{$format}", FALSE);
if ($nofollow) {
$rel = array_filter(explode(' ', $a
->getAttribute('rel')));
if (!in_array('nofollow', $rel)) {
$rel[] = 'nofollow';
$a
->setAttribute('rel', implode(' ', $rel));
}
}
// Add redirect.
if (variable_get('elf_redirect', FALSE)) {
$a
->setAttribute('href', url('elf/go', array(
'query' => array(
'url' => $a
->getAttribute('href'),
),
)));
}
}
}
}
return elf_filter_dom_serialize($document);
}
/**
* Test if a URL is external
*
* @param $url string
*/
function elf_url_external($url) {
global $base_url;
static $pattern = NULL;
// Statically store internal domains as a PCRE pattern.
if (!$pattern) {
$domains = array();
foreach (array_merge(variable_get('elf_domains', array()), array(
$base_url,
)) as $domain) {
$domains[] = preg_quote($domain, '#');
}
$pattern = '#^(' . str_replace('\\*', '.*', implode('|', $domains)) . ')#';
}
return preg_match($pattern, $url) ? FALSE : menu_path_is_external($url);
}
/**
* Redirect the browser to the external URL from $_GET['url'].
*/
function elf_redirect() {
drupal_goto($_GET['url']);
}
/**
* Using Drupal 7's filter_dom_load function which is not available in d6.
*/
function elf_filter_dom_load($text) {
$dom_document = new DOMDocument();
// Ignore warnings during HTML soup loading.
@$dom_document
->loadHTML('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>' . $text . '</body></html>');
return $dom_document;
}
/**
* Using Drupal 7's filter_dom_serialize function which is not available in d6.
*/
function elf_filter_dom_serialize($dom_document) {
$body_node = $dom_document
->getElementsByTagName('body')
->item(0);
$body_content = '';
foreach ($body_node
->getElementsByTagName('script') as $node) {
elf_filter_dom_serialize_escape_cdata_element($dom_document, $node);
}
foreach ($body_node
->getElementsByTagName('style') as $node) {
elf_filter_dom_serialize_escape_cdata_element($dom_document, $node, '/*', '*/');
}
foreach ($body_node->childNodes as $child_node) {
$body_content .= $dom_document
->saveXML($child_node);
}
return preg_replace('|<([^> ]*)/>|i', '<$1 />', $body_content);
}
/**
* Using Drupal 7's filter_dom_serialize_escape_cdata_element function which is not available in d6.
*/
function elf_filter_dom_serialize_escape_cdata_element($dom_document, $dom_element, $comment_start = '//', $comment_end = '') {
foreach ($dom_element->childNodes as $node) {
if (get_class($node) == 'DOMCdataSection') {
$embed_prefix = "\n<!--{$comment_start}--><![CDATA[{$comment_start} ><!--{$comment_end}\n";
$embed_suffix = "\n{$comment_start}--><!]]>{$comment_end}\n";
$data = str_replace(']]>', ']]]]><![CDATA[>', $node->data);
$fragment = $dom_document
->createDocumentFragment();
$fragment
->appendXML($embed_prefix . $data . $embed_suffix);
$dom_element
->appendChild($fragment);
$dom_element
->removeChild($node);
}
}
}
Functions
Name | Description |
---|---|
elf_filter | Implementation of hook_filter(). |
elf_filter_dom_load | Using Drupal 7's filter_dom_load function which is not available in d6. |
elf_filter_dom_serialize | Using Drupal 7's filter_dom_serialize function which is not available in d6. |
elf_filter_dom_serialize_escape_cdata_element | Using Drupal 7's filter_dom_serialize_escape_cdata_element function which is not available in d6. |
elf_form_settings | Admin settings form. |
elf_form_settings_validate | Form validation handler for elf_form_settings(). |
elf_init | Implementation of hook_init(). |
elf_menu | Implementation of hook_menu(). |
elf_redirect | Redirect the browser to the external URL from $_GET['url']. |
elf_replace | Add classes to external or mailto links in a text. |
elf_url_external | Test if a URL is external |