You are here

function _link_sanitize in Link 7

Same name and namespace in other branches
  1. 6.2 link.inc \_link_sanitize()
  2. 6 link.module \_link_sanitize()

Clean up user-entered values for a link field according to field settings.

Note: this cannot be properly unit tested as it checks for certain entity values.

@todo Rewrite so that the logic can be unit tested.

@codingStandardsIgnoreStart

Parameters

array $item: A single link item, usually containing url, title, and attributes.

int $delta: The delta value if this field is one of multiple fields.

array $field: The CCK field definition.

object $entity: The entity containing this link.

10 calls to _link_sanitize()
LinkSanitizeTest::testAbsoluteHash in tests/LinkSanitizeTest.test
Test that relative hash URLs can be turned into absolute URLs.
LinkSanitizeTest::testAbsoluteQuery in tests/LinkSanitizeTest.test
Test that query URLs can be turned into absolute URLs.
LinkSanitizeTest::testBlankTitle in tests/LinkSanitizeTest.test
Test that query URLs can be turned into absolute URLs.
LinkSanitizeTest::testBlankTitleWithFragment in tests/LinkSanitizeTest.test
Test that query URLs can be turned into absolute URLs.
LinkSanitizeTest::testBlankTitleWithMultipleQueries in tests/LinkSanitizeTest.test
Test that multiple query URLs can be turned into absolute URLs.

... See full list

File

./link.module, line 636
Defines simple link field types.

Code

function _link_sanitize(&$item, $delta, &$field, $instance, &$entity) {

  // @codingStandardsIgnoreEnd
  // As this function can be called multiple times and the item is changed by
  // reference we need to ensure that there's always the original data to
  // process otherwise processed data are processed again which might leads to
  // unexpected results.
  if (isset($item['_link_sanitized'])) {
    return;
  }

  // Store a flag to check in case of a second call.
  $item['_link_sanitized'] = TRUE;

  // Don't try to process empty links.
  if (empty($item['url']) && empty($item['title'])) {
    return;
  }
  if (empty($item['html'])) {
    $item['html'] = FALSE;
  }

  // Replace URL tokens.
  $entity_type = $instance['entity_type'];
  $entity_info = entity_get_info($entity_type);
  $property_id = $entity_info['entity keys']['id'];
  if (isset($entity_info['token type'])) {
    $entity_token_type = $entity_info['token type'];
  }
  elseif ($entity_type == 'taxonomy_term' || $entity_type == 'taxonomy_vocabulary') {
    $entity_token_type = str_replace('taxonomy_', '', $entity_type);
  }
  else {
    $entity_token_type = $entity_type;
  }
  if (isset($instance['settings']['enable_tokens']) && $instance['settings']['enable_tokens']) {
    $text_tokens = token_scan($item['url']);
    if (!empty($text_tokens)) {

      // Load the entity if necessary for entities in views.
      if (isset($entity->{$property_id})) {
        $entity_loaded = entity_load($entity_type, array(
          $entity->{$property_id},
        ));
        $entity_loaded = array_pop($entity_loaded);
      }
      else {
        $entity_loaded = $entity;
      }
      $item['url'] = token_replace($item['url'], array(
        $entity_token_type => $entity_loaded,
      ));
    }
  }
  $type = link_url_type($item['url']);

  // If the type of the URL cannot be determined and URL validation is disabled,
  // then assume LINK_EXTERNAL for later processing.
  if ($type == FALSE && $instance['settings']['validate_url'] === 0) {
    $type = LINK_EXTERNAL;
  }
  elseif ($type == LINK_FRAGMENT || $type == LINK_QUERY) {

    // Treat fragment or query-only links as external.
    if (!empty($instance['settings']['absolute_url'])) {
      $item['url'] = $_GET['q'] . $item['url'];
    }
    else {
      $item['external'] = TRUE;
    }
  }
  $url = link_cleanup_url($item['url'], variable_get('link_default_protocol', LINK_HTTP_PROTOCOL));
  $url_parts = _link_parse_url($url);
  if (!empty($url_parts['url'])) {
    $item = array(
      'url' => $url_parts['url'],
      'query' => isset($url_parts['query']) ? $url_parts['query'] : NULL,
      'fragment' => isset($url_parts['fragment']) ? $url_parts['fragment'] : NULL,
      'absolute' => !empty($instance['settings']['absolute_url']),
      'html' => TRUE,
    ) + $item;
  }

  // Create a shortened URL for display.
  if ($type == LINK_EMAIL) {
    $display_url = str_replace('mailto:', '', $url);
  }
  elseif ($type === LINK_EXTERNAL) {
    $display_url = url($url_parts['url'], array(
      'query' => isset($url_parts['query']) ? $url_parts['query'] : NULL,
      'fragment' => isset($url_parts['fragment']) ? $url_parts['fragment'] : NULL,
      'absolute' => TRUE,
    ));
  }
  elseif ($type == LINK_TEL) {
    $display_url = str_replace('tel:', '', $url);
  }
  else {
    $display_url = url($url_parts['url'], array(
      'query' => isset($url_parts['query']) ? $url_parts['query'] : NULL,
      'fragment' => isset($url_parts['fragment']) ? $url_parts['fragment'] : NULL,
      'absolute' => !empty($instance['settings']['absolute_url']),
    ));
  }
  if ($instance['settings']['display']['url_cutoff'] && strlen($display_url) > $instance['settings']['display']['url_cutoff']) {
    $display_url = substr($display_url, 0, $instance['settings']['display']['url_cutoff']) . "…";
  }
  $item['display_url'] = $display_url;

  // Use the title defined at the instance level.
  if ($instance['settings']['title'] == 'value' && strlen(trim($instance['settings']['title_value']))) {
    $title = $instance['settings']['title_value'];
    if (function_exists('i18n_string_translate')) {
      $i18n_string_name = "field:{$instance['field_name']}:{$instance['bundle']}:title_value";
      $title = i18n_string_translate($i18n_string_name, $title);
    }
  }
  elseif (isset($item['title']) && drupal_strlen(trim($item['title']))) {
    $title = $item['title'];
  }
  elseif ($instance['settings']['title'] == 'optional' && drupal_strlen(trim($instance['settings']['title_value']))) {
    $title = $instance['settings']['title_value'];
  }
  else {
    $title = '';
  }

  // Replace title tokens.
  if ($title && $instance['settings']['enable_tokens']) {
    $text_tokens = token_scan($title);
    if (!empty($text_tokens)) {

      // Load the entity if necessary for entities in views.
      if (isset($entity->{$property_id})) {
        $entity_loaded = entity_load($entity_type, array(
          $entity->{$property_id},
        ));
        $entity_loaded = array_pop($entity_loaded);
      }
      else {
        $entity_loaded = $entity;
      }
      $title = token_replace($title, array(
        $entity_token_type => $entity_loaded,
      ));
    }
  }
  if ($title && ($instance['settings']['title'] == 'value' || $instance['settings']['enable_tokens'])) {
    $title = filter_xss($title, array(
      'b',
      'br',
      'code',
      'em',
      'i',
      'img',
      'span',
      'strong',
      'sub',
      'sup',
      'tt',
      'u',
    ));
    $item['html'] = TRUE;
  }
  $item['title'] = empty($title) && $title !== '0' ? $item['display_url'] : $title;
  if (!isset($item['attributes'])) {
    $item['attributes'] = array();
  }

  // Unserialize attributtes array if it has not been unserialized yet.
  if (!is_array($item['attributes'])) {
    $item['attributes'] = (array) unserialize($item['attributes']);
  }

  // Add default attributes.
  if (!is_array($instance['settings']['attributes'])) {
    $instance['settings']['attributes'] = _link_default_attributes();
  }
  else {
    $instance['settings']['attributes'] += _link_default_attributes();
  }

  // Merge item attributes with attributes defined at the field level.
  $item['attributes'] += $instance['settings']['attributes'];

  // If user is not allowed to choose target attribute, use default defined at
  // field level.
  if ($instance['settings']['attributes']['target'] != LINK_TARGET_USER) {
    $item['attributes']['target'] = $instance['settings']['attributes']['target'];
  }
  elseif ($item['attributes']['target'] == LINK_TARGET_USER) {
    $item['attributes']['target'] = LINK_TARGET_DEFAULT;
  }

  // Remove the target attribute if the default (no target) is selected.
  if (empty($item['attributes']) || isset($item['attributes']['target']) && $item['attributes']['target'] == LINK_TARGET_DEFAULT) {
    unset($item['attributes']['target']);
  }

  // Remove rel attribute for internal or external links if selected.
  if (isset($item['attributes']['rel']) && isset($instance['settings']['rel_remove']) && $instance['settings']['rel_remove'] != 'default') {
    if ($instance['settings']['rel_remove'] != 'rel_remove_internal' && $type != LINK_INTERNAL || $instance['settings']['rel_remove'] != 'rel_remove_external' && $type != LINK_EXTERNAL) {
      unset($item['attributes']['rel']);
    }
  }

  // Handle "title" link attribute.
  if (!empty($item['attributes']['title']) && module_exists('token')) {
    $text_tokens = token_scan($item['attributes']['title']);
    if (!empty($text_tokens)) {

      // Load the entity (necessary for entities in views).
      if (isset($entity->{$property_id})) {
        $entity_loaded = entity_load($entity_type, array(
          $entity->{$property_id},
        ));
        $entity_loaded = array_pop($entity_loaded);
      }
      else {
        $entity_loaded = $entity;
      }
      $item['attributes']['title'] = token_replace($item['attributes']['title'], array(
        $entity_token_type => $entity_loaded,
      ), array(
        'clear' => TRUE,
      ));
    }
    $item['attributes']['title'] = filter_xss($item['attributes']['title'], array(
      'b',
      'br',
      'code',
      'em',
      'i',
      'img',
      'span',
      'strong',
      'sub',
      'sup',
      'tt',
      'u',
    ));
  }

  // Handle attribute classes.
  if (!empty($item['attributes']['class'])) {
    $classes = explode(' ', $item['attributes']['class']);
    foreach ($classes as &$class) {
      $class = drupal_clean_css_identifier($class);
    }
    $item['attributes']['class'] = implode(' ', $classes);
  }
  unset($item['attributes']['configurable_class']);

  // Remove title attribute if it's equal to link text.
  if (isset($item['attributes']['title']) && $item['attributes']['title'] == $item['title']) {
    unset($item['attributes']['title']);
  }
  unset($item['attributes']['configurable_title']);

  // Remove empty attributes.
  $item['attributes'] = array_filter($item['attributes']);
}