You are here

elf.module in External Links Filter 5.3

File

elf.module
View source
<?php

/**
 * Implementation of hook_menu().
 */
function elf_menu($may_cache) {
  if ($may_cache) {
    $items[] = array(
      'path' => 'admin/settings/elf',
      'title' => t('External links filter'),
      'description' => t('Configure external links filter'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'elf_settings',
      ),
      'access' => user_access('administer site configuration'),
    );
  }
  else {
    drupal_add_css(drupal_get_path('module', 'elf') . '/elf.css');
  }
  return $items;
}

/**
 * Implementation of hook_filter().
 */
function elf_filter($op, $delta = 0, $format = -1, $text = '') {
  switch ($op) {
    case 'list':
      return array(
        0 => t('External links filter'),
      );
    case 'description':
      return t('Adds a CSS class to all 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('Spam link deterrent'),
        '#description' => t('Add !code to external links, as a measure to reduce the effectiveness of spam links. Note: this will also prevent valid links from being followed by search engines, therefore it is likely most effective when enabled for anonymous users.', array(
          '!code' => '<code>rel="nofollow"</code>',
        )),
        '#default_value' => variable_get("elf_nofollow{$format}", FALSE),
      );
      return $form;
    default:
      return $text;
  }
}

/**
 * Admin settings form.
 *
 * @see elf_settings_submit()
 */
function elf_settings() {
  $form['#submit'] = array(
    'system_settings_form_submit' => array(),
    'elf_settings_submit' => array(),
  );
  $form['elf_domains'] = array(
    '#type' => 'textarea',
    '#default_value' => implode("\n", variable_get('elf_domains', array())),
    '#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.', array(
      '!example_right' => '<code>http://example.com</code>',
      '!example_wrong' => '<code>example.com</code>',
    )),
  );
  return system_settings_form($form);
}

/**
 * Form submission handler for elf_settings().
 *
 * @see elf_settings()
 */
function elf_settings_submit($form_id, $form_values) {
  $domains = array();
  $values = explode("\n", $form_values['elf_domains']);
  foreach ($values as $url) {

    // Remove trailing slashes, because not all users will use those for their
    // links.
    $url = rtrim(preg_replace('#/$#', '', $url));
    if (strlen($url)) {
      $domains[] = $url;
    }
  }
  variable_set('elf_domains', $domains);
}

/**
 * Return an array of all domains that are considered internal.
 *
 * @return array
 */
function elf_domains() {
  global $base_url;
  $domains = variable_get('elf_domains', array());
  $domains[] = $base_url;
  return $domains;
}

/**
 * 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 = NULL) {
  $doc = new DOMDocument();

  // We are using a wrapper to prevent tags from being added automatically.
  $text = '<div>' . $text . '</div>';
  $doc
    ->loadHTML($text);
  $as = $doc
    ->getElementsByTagName('a');
  foreach ($as as $a) {
    $href = $a
      ->getAttribute('href');

    // The link is absolute, and does not point to the site itself.
    if (elf_url_external($href)) {
      $class = ' elf-external';
      $class .= $a
        ->getElementsByTagName('img')->length > 0 ? ' elf-img' : NULL;
      $a
        ->setAttribute('class', $a
        ->getAttribute('class') . $class);
      $nofollow = $format ? variable_get("elf_nofollow_{$format}", FALSE) : FALSE;
      if ($nofollow) {
        $a
          ->setAttribute('rel', $a
          ->getAttribute('rel') . ' nofollow');
      }
    }
    else {
      if (strpos($href, 'mailto:') === 0) {
        $a
          ->setAttribute('class', $a
          ->getAttribute('class') . ' elf-mailto');
      }
    }
  }
  return substr($doc
    ->saveXML($doc
    ->getElementsByTagName('div')
    ->item(0)), 5, -6);
}

/**
 * Test if a URL is external
 *
 * @param $url string
 */
function elf_url_external($url) {
  $protocols = array(
    'http',
    'https',
    'ftp',
  );
  $protocol = drupal_substr($url, 0, strpos($url, ':'));
  if (in_array($protocol, $protocols)) {
    $external = TRUE;
    $domains = elf_domains();
    foreach ($domains as $domain) {
      if (strpos($url, $domain) !== FALSE) {
        $external = FALSE;
      }
    }
    return $external;
  }
  return FALSE;
}

Functions

Namesort descending Description
elf_domains Return an array of all domains that are considered internal.
elf_filter Implementation of hook_filter().
elf_menu Implementation of hook_menu().
elf_replace Add classes to external or mailto links in a text.
elf_settings Admin settings form.
elf_settings_submit Form submission handler for elf_settings().
elf_url_external Test if a URL is external