You are here

function linked_field_field_attach_view_alter in Linked Field 7

Implements hook_field_attach_view_alter().

File

./linked_field.module, line 306
Main file of Linked Field module.

Code

function linked_field_field_attach_view_alter(&$output, $context) {
  foreach (element_children($output) as $field_name) {
    $element = $output[$field_name];
    if (empty($element['#entity_type']) || empty($element['#bundle'])) {
      continue;
    }
    $view_modes = field_view_mode_settings($element['#entity_type'], $element['#bundle']);

    // Check whether set view mode has custom settings.
    if (isset($view_modes[$context['view_mode']]) && !$view_modes[$context['view_mode']]['custom_settings']) {
      $context['view_mode'] = 'default';
    }
    $instance = field_info_instance($element['#entity_type'], $field_name, $element['#bundle']);

    // Check whether view mode exists in the field instance.
    if (isset($instance['display'][$context['view_mode']])) {
      $display = $instance['display'][$context['view_mode']];
    }
    elseif ($context['view_mode'] == '_custom' && is_array($context['display'])) {
      $display = $context['display'];
    }
    else {
      $display = $instance['display']['default'];
    }
    $settings = $display['settings'];

    // We need special behavior for Display Suite fields.
    if ($element['#field_type'] == 'ds') {
      $field_settings = ds_get_field_settings($element['#entity_type'], $element['#bundle'], $element['#view_mode']);
      $settings = isset($field_settings[$element['#field_name']]['formatter_settings']) ? $field_settings[$element['#field_name']]['formatter_settings'] : array();
    }

    // Continue to next if no Linked Field settings were found.
    if (empty($settings['linked_field']['linked'])) {
      continue;
    }

    // Some entities don't have a language so we need a fallback.
    $language = isset($element['#object']->language) ? $element['#object']->language : NULL;

    // We need special behavior for Display Suite fields.
    // @TODO: Where does this come from?
    if ($element['#field_type'] != 'ds') {
      $field_items = field_get_items($element['#entity_type'], $element['#object'], $field_name, $language);
    }
    foreach (element_children($element) as $delta) {

      // Parse the destination to get queries and fragments working.
      $destination_parsed = drupal_parse_url($settings['linked_field']['destination']);

      // Generate a correct link.
      $path = $destination_parsed['path'];
      unset($destination_parsed['path']);

      // Building an array which looks like the parameters you pass to l().
      $linked_field_settings = array(
        'linked' => $settings['linked_field']['linked'],
        'text' => $settings['linked_field']['advanced']['text'],
        'path' => $path,
        'options' => array(
          'attributes' => array(
            'title' => $settings['linked_field']['advanced']['title'],
            'target' => $settings['linked_field']['advanced']['target'],
            'class' => $settings['linked_field']['advanced']['class'],
            'rel' => $settings['linked_field']['advanced']['rel'],
          ),
        ) + $destination_parsed,
      );

      // Let other modules alter all the settings.
      drupal_alter('linked_field_settings', $linked_field_settings, $context);

      // If there is no destination or Linked Field is disabled continue.
      if (!$linked_field_settings['path'] || !$linked_field_settings['linked'] && $linked_field_settings['path']) {
        continue;
      }
      $replace_tokens = array(
        $element['#entity_type'] => $element['#object'],
      );

      // We need special behavior for Display Suite fields.
      // @TODO: Where does this come from?
      if (isset($field_items[$delta])) {

        // Get raw value of field.
        $field_raw_value = array_shift($field_items[$delta]);

        // Replace tokens and filter the value. The field tokens have to be
        // first in the array so they are processed first.
        $replace_tokens = array(
          'field-item' => array(
            'delta' => $delta,
            'raw' => $field_raw_value,
          ),
        ) + $replace_tokens;
      }
      $options = array();
      if ($context['language'] != LANGUAGE_NONE) {
        $languages = language_list();
        if (isset($languages[$context['language']])) {
          $options['language'] = $languages[$context['language']];
        }
      }

      /*
       * Replace all field tokens and then entity tokens. This allows field
       * tokens to be nested such as [comment:field-tags:[field:delta]:name].
       */
      foreach ($replace_tokens as $type => $data) {
        $replace_token = array(
          $type => $data,
        );
        if ($type == 'field-item') {

          // The tokens should not be cleared when replacing field item tokens.
          $options['clear'] = FALSE;
        }
        else {
          $options['clear'] = TRUE;
        }
        $linked_field_settings['path'] = token_replace($linked_field_settings['path'], $replace_token, $options);
        $linked_field_settings['options']['attributes']['title'] = $linked_field_settings['options']['attributes']['title'] ? filter_xss_admin(token_replace($linked_field_settings['options']['attributes']['title'], $replace_token, $options)) : '';
        $linked_field_settings['options']['attributes']['target'] = $linked_field_settings['options']['attributes']['target'] ? check_plain(token_replace($linked_field_settings['options']['attributes']['target'], $replace_token, $options)) : '';
        $linked_field_settings['options']['attributes']['class'] = $linked_field_settings['options']['attributes']['class'] ? check_plain(token_replace($linked_field_settings['options']['attributes']['class'], $replace_token, $options)) : '';
        $linked_field_settings['options']['attributes']['rel'] = $linked_field_settings['options']['attributes']['rel'] ? check_plain(token_replace($linked_field_settings['options']['attributes']['rel'], $replace_token, $options)) : '';

        // Would be better to have own set with allowed tags so that only
        // inline elements are allowed.
        $linked_field_settings['text'] = $linked_field_settings['text'] ? filter_xss_admin(token_replace($linked_field_settings['text'], $replace_token, $options)) : '';
      }

      // Continue to next field if destination is empty.
      if (!$linked_field_settings['path']) {
        continue;
      }

      // We need the destination as link attribute so let's move it.
      $linked_field_settings['options']['attributes']['href'] = url($linked_field_settings['path'], $linked_field_settings['options']);
      unset($linked_field_settings['path']);
      if (!$linked_field_settings['text']) {
        $rendered = drupal_render($element[$delta]);
      }
      else {
        $rendered = $linked_field_settings['text'];
      }

      // Convert HTML code to a DOMDocument object.
      $html_dom = filter_dom_load($rendered);

      // Getting the <body> element.
      $body = $html_dom
        ->getElementsByTagName('body');
      $nodes = $body
        ->item(0);

      // Recursively walk over the DOMDocument body and place the links.
      linked_field_link_field($nodes, $html_dom, $linked_field_settings['options']['attributes']);

      // Converting the DOMDocument object back to HTML code.
      $rendered = filter_dom_serialize($html_dom);
      $output[$field_name][$delta] = array(
        '#markup' => $rendered,
      );
    }
  }
}