elf.module in External Links Filter 7.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.
*/
/**
* Implement 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");
}
}
/**
* Implement hook_menu().
*/
function elf_menu() {
$items['admin/config/content/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;
}
/**
* Implement hook_filter().
*/
function elf_filter_info() {
$filters['elf'] = array(
'title' => t('Add an icon to external and mailto links'),
'settings callback' => 'elf_filter_settings',
'process callback' => 'elf_replace',
'default settings' => array(
'elf_nofollow' => FALSE,
),
);
return $filters;
}
/**
* Hook_filter_info() settings callback.
*
* @see elf_filter_info()
*/
function elf_filter_settings(array $form, array &$form_state, stdClass $filter, stdClass $format, array $defaults) {
$settings['elf_nofollow'] = array(
'#type' => 'checkbox',
'#title' => t('Add rel="nofollow" to all external links'),
'#default_value' => isset($filter->settings['elf_nofollow']) ? $filter->settings['elf_nofollow'] : $defaults['elf_nofollow'],
);
return $settings;
}
/**
* Admin settings form.
*
* @see elf_form_settings_submit()
*/
function elf_form_settings(array $form, 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, FALSE);
}
/**
* 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 (!url_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);
}
}
/**
* Hook_filter_info() process callback.
*
* @see elf_filter_info()
*/
function elf_replace($text, stdClass $filter) {
$document = 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 = $filter->settings['elf_nofollow'];
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)) {
$redirect_url = elf_get_redirect_url($a
->getAttribute('href'));
$a
->setAttribute('href', $redirect_url);
}
}
}
}
return 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 : url_is_external($url);
}
/**
* Redirect the browser to the external URL from $_GET['url'].
*/
function elf_redirect() {
$url = !empty($_GET['url']) ? $_GET['url'] : '';
$key = !empty($_GET['key']) ? $_GET['key'] : '';
if (!$url) {
elf_redirect_exit();
}
// Works as a broken link if no valid arguments found.
$parsed_url = drupal_parse_url(elf_get_redirect_url($url));
if ($key != $parsed_url['query']['key']) {
elf_redirect_exit();
}
// Perform the redirection to the external URL.
drupal_goto($url);
}
/**
* Deliver a "page not found" error to the browser and performs end-of-request tasks.
*/
function elf_redirect_exit() {
drupal_not_found();
drupal_exit();
}
/**
* Creates a safe internal URL that redirects to the an external one.
*
* @param string $external_url
* The target URL.
*
* @return string
* An internal URL that points to the ELF redirection route.
*/
function elf_get_redirect_url($external_url) {
$key = drupal_hmac_base64($external_url, drupal_get_private_key());
return url('elf/go', array(
'query' => array(
'url' => $external_url,
'key' => $key,
),
));
}
Functions
Name | Description |
---|---|
elf_filter_info | Implement hook_filter(). |
elf_filter_settings | Hook_filter_info() settings callback. |
elf_form_settings | Admin settings form. |
elf_form_settings_validate | Form validation handler for elf_form_settings(). |
elf_get_redirect_url | Creates a safe internal URL that redirects to the an external one. |
elf_init | Implement hook_init(). |
elf_menu | Implement hook_menu(). |
elf_redirect | Redirect the browser to the external URL from $_GET['url']. |
elf_redirect_exit | Deliver a "page not found" error to the browser and performs end-of-request tasks. |
elf_replace | Hook_filter_info() process callback. |
elf_url_external | Test if a URL is external |