You are here

entityreference_multiple.module in Entity reference multiple display 7

Extend entity reference formatter with an option to separate elements display with specific view_modes.

File

entityreference_multiple.module
View source
<?php

/**
 * @file
 * Extend entity reference formatter with an option to separate elements
 * display with specific view_modes.
 */

/**
 * Implements hook_field_formatter_info().
 */
function entityreference_multiple_field_formatter_info() {
  return array(
    'entityreference_entity_multiple_view' => array(
      'label' => t('Rendered entity with different view modes'),
      'description' => t('Display the referenced entities rendered by entity_view() with different view modes.'),
      'field types' => array(
        'entityreference',
      ),
      'settings' => array(
        'view_mode_number' => 2,
        'view_mode_multiple' => array(
          'view_mode_1' => 'full',
          'view_mode_1_number' => '1',
          'view_mode_1_links' => TRUE,
          'view_mode_2' => 'teaser',
          'view_mode_2_number' => '#',
          'view_mode_2_links' => TRUE,
        ),
      ),
    ),
  );
}

/**
 * Implements hook_field_formatter_settings_form().
 */
function entityreference_multiple_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];

  // do not interfer with entityreference
  if ($display['type'] == 'entityreference_entity_multiple_view') {
    $entity_info = entity_get_info($field['settings']['target_type']);
    $options = array();
    if (!empty($entity_info['view modes'])) {
      foreach ($entity_info['view modes'] as $view_mode => $view_mode_settings) {
        $options[$view_mode] = $view_mode_settings['label'];
      }
    }
    if (count($options) > 1) {

      // Build settings form
      $element['view_mode_number'] = array(
        '#type' => 'select',
        '#options' => drupal_map_assoc(range(1, 10)),
        '#title' => t('Number of groups'),
        '#default_value' => $settings['view_mode_number'],
        '#ajax' => array(
          'callback' => 'entityreference_multiple_callback',
          'wrapper' => 'view_mode_multiple_' . $field['field_name'],
          'method' => 'replace',
          'effect' => 'fade',
        ),
        '#attributes' => array(
          // add rel to get field name for ajax callback
          'rel' => $field['field_name'],
          'alt' => t('Enter a number of group to split display.'),
          'title' => t('Enter a number of group to split display.'),
        ),
      );

      // container needed for ajax call
      $element['view_mode_multiple'] = array(
        '#type' => 'container',
        '#attributes' => array(
          'id' => array(
            'view_mode_multiple_' . $field['field_name'],
          ),
        ),
      );

      // Ajax logic: if a values is set we need to handle it
      if (isset($form_state['values']['fields'][$field['field_name']]['settings_edit_form']['settings']['view_mode_number'])) {
        $group_number = $form_state['values']['fields'][$field['field_name']]['settings_edit_form']['settings']['view_mode_number'];
      }
      else {
        $group_number = $settings['view_mode_number'];
      }

      // Build settings for each group
      for ($i = 1; $i <= $group_number; $i++) {
        $element['view_mode_multiple']['view_mode_' . $i] = array(
          '#type' => 'select',
          '#options' => $options,
          '#title' => t('View mode group !num', array(
            '!num' => $i,
          )),
          '#default_value' => $settings['view_mode_multiple']['view_mode_' . $i],
          '#prefix' => '<div class="limit-float">',
          '#suffix' => '</div>',
        );
        $element['view_mode_multiple']['view_mode_' . $i . '_number'] = array(
          '#type' => 'textfield',
          '#title' => t('Elements'),
          '#size' => 2,
          '#maxlength' => 2,
          '#default_value' => $settings['view_mode_multiple']['view_mode_' . $i . '_number'],
          '#required' => TRUE,
          '#element_validate' => array(
            'entityreference_multiple_number_validate',
          ),
          '#prefix' => '<div class="limit-float">',
          '#suffix' => '</div><div class="clearfix"></div>',
          '#attributes' => array(
            'alt' => t('Enter a number to limit the number of items concerned by this mode, fill # for all items left, so it should be used only for the last group.'),
            'title' => t('Enter a number to limit the number of items concerned by this mode, fill # for all items left, so it should be used only for the last group.'),
          ),
        );
        $element['view_mode_multiple']['view_mode_' . $i . '_links'] = array(
          '#type' => 'checkbox',
          '#title' => t('Show links'),
          '#default_value' => $settings['view_mode_multiple']['view_mode_' . $i . '_links'],
        );
      }
    }
    return $element;
  }
}

/**
 * Ajax callback for the field formatter settings form.
 */
function entityreference_multiple_callback($form, $form_state) {
  $field_name = $form_state['triggering_element']['#attributes']['rel'];
  return $form['fields'][$field_name]['format']['settings_edit_form']['settings']['view_mode_multiple'];
}

/**
* Form element validation handler for positive integer elements.
*/
function entityreference_multiple_number_validate($element, &$form_state, $form) {
  $value = $element['#value'];
  if ($value != '#' && (!is_numeric($value) || intval($value) != $value || $value <= 0)) {
    form_error($element, t('%name must be a positive integer.', array(
      '%name' => $element['#title'],
    )));
  }
}

/**
 * Implements hook_field_formatter_settings_summary().
 */
function entityreference_multiple_field_formatter_settings_summary($field, $instance, $view_mode) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];
  $summary = array();
  if ($display['type'] == 'entityreference_entity_multiple_view') {
    $entity_info = entity_get_info($field['settings']['target_type']);
    for ($i = 1; $i <= $settings['view_mode_number']; $i++) {
      $settings['view_mode_multiple']['view_mode_' . $i . '_number'] == '#' ? $num = t('all') : ($num = $settings['view_mode_multiple']['view_mode_' . $i . '_number']);
      if ($i > 1) {
        $num .= ' ' . t('next');
      }
      isset($entity_info['view modes'][$settings['view_mode_multiple']['view_mode_' . $i]]['label']) ? $mode = $entity_info['view modes'][$settings['view_mode_multiple']['view_mode_' . $i]]['label'] : ($mode = $entity_info['view modes']['full']['label']);
      if (!empty($settings['view_mode_multiple']['view_mode_' . $i . '_links'])) {
        $links = t('with');
      }
      else {
        $links = t('without');
      }
      $summary[] = t('Rendered !num as @mode @links links', array(
        '!num' => $num,
        '@mode' => $mode,
        '@links' => $links,
      ));
    }
  }
  return implode('<br />', $summary);
}

/**
 * Implements hook_field_formatter_prepare_view().
 * Code duplicate from entityreference.module to load entity for view.
 */
function entityreference_multiple_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays) {
  $target_ids = array();

  // Collect every possible entity attached to any of the entities.
  foreach ($entities as $id => $entity) {
    if (isset($displays[$id]['type']) && $displays[$id]['type'] == 'entityreference_entity_multiple_view') {
      foreach ($items[$id] as $delta => $item) {
        if (isset($item['target_id'])) {
          $target_ids[] = $item['target_id'];
        }
      }
    }
  }
  if ($target_ids) {
    $target_entities = entity_load($field['settings']['target_type'], $target_ids);
  }
  else {
    $target_entities = array();
  }

  // Iterate through the fieldable entities again to attach the loaded data.
  foreach ($entities as $id => $entity) {
    if (isset($displays[$id]['type']) && $displays[$id]['type'] == 'entityreference_entity_multiple_view') {
      $rekey = FALSE;
      foreach ($items[$id] as $delta => $item) {

        // Check whether the referenced entity could be loaded and that the user has access to it.
        if (isset($target_entities[$item['target_id']]) && entity_access('view', $field['settings']['target_type'], $target_entities[$item['target_id']])) {

          // Replace the instance value with the term data.
          $items[$id][$delta]['entity'] = $target_entities[$item['target_id']];
        }
        else {
          unset($items[$id][$delta]);
          $rekey = TRUE;
        }
      }
      if ($rekey) {

        // Rekey the items array.
        $items[$id] = array_values($items[$id]);
      }
    }
  }
}

/**
 * Implements hook_field_formatter_view().
 */
function entityreference_multiple_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $settings = $display['settings'];
  $result = $split = $test = array();

  // Initialize the var
  if ($display['type'] == 'entityreference_entity_multiple_view') {

    // we define number of elements by group
    $count = 0;
    for ($i = 1; $i <= $settings['view_mode_number']; $i++) {

      // We need to get number of last elements
      $count += $settings['view_mode_multiple']['view_mode_' . $i . '_number'];
      if ($settings['view_mode_multiple']['view_mode_' . $i . '_number'] == '#') {
        $settings['view_mode_multiple']['view_mode_' . $i . '_number'] = count($items) - $count;
      }

      // We create a reference to get the view mode for each element
      for ($j = 1; $j <= $settings['view_mode_multiple']['view_mode_' . $i . '_number']; $j++) {
        $split[] = array(
          'view_mode' => $settings['view_mode_multiple']['view_mode_' . $i],
          'links' => isset($settings['view_mode_multiple']['view_mode_' . $i . '_links']) ? $settings['view_mode_multiple']['view_mode_' . $i . '_links'] : '',
        );
      }
    }
    foreach ($items as $delta => $item) {

      // Protect ourselves from recursive rendering.
      static $depth = 0;
      $depth++;
      if ($depth > 20) {
        throw new EntityReferenceRecursiveRenderingException(t('Recursive rendering detected when rendering entity @entity_type(@entity_id). Aborting rendering.', array(
          '@entity_type' => $entity_type,
          '@entity_id' => $item['target_id'],
        )));
      }
      $entity = clone $item['entity'];
      unset($entity->content);

      // we render each element with the good view mode
      $result[$delta] = entity_view($field['settings']['target_type'], array(
        $item['target_id'] => $entity,
      ), $split[$delta]['view_mode'], $langcode, FALSE);
      if (empty($split[$delta]['links']) && isset($result[$delta][$field['settings']['target_type']][$item['target_id']]['links'])) {
        $result[$delta][$field['settings']['target_type']][$item['target_id']]['links']['#access'] = FALSE;
      }
      $depth = 0;
    }
  }
  return $result;
}