You are here

field_multiple_limit.module in Field multiple limit 7

Same filename and directory in other branches
  1. 8 field_multiple_limit.module

Provides formatter settings for limiting the number of values to display on multi-value fields.

Based on Field Delimiter module (http://drupal.org/project/field_delimiter).

File

field_multiple_limit.module
View source
<?php

/**
 * @file
 * Provides formatter settings for limiting the number of values to display on
 * multi-value fields.
 *
 * Based on Field Delimiter module (http://drupal.org/project/field_delimiter).
 */
define('FIELD_MULTIPLE_LIMIT_ALL', -1);
define('FIELD_MULTIPLE_LIMIT_ORDER_ORIGINAL', 0);
define('FIELD_MULTIPLE_LIMIT_ORDER_REVERSE', 1);
define('FIELD_MULTIPLE_LIMIT_ORDER_RANDOM', 2);

/**
 * Returns a list of formatters to skip because they already do this.
 */
function _field_multiple_limit_skip() {
  return array(
    'date_default',
    'format_interval',
  );
}

/**
 * Implements hook_field_formatter_info_alter().
 */
function field_multiple_limit_field_formatter_info_alter(&$info) {

  // Added to all formatters, except ones marked for skipping.
  $skip = _field_multiple_limit_skip();
  foreach ($info as $formatter_key => &$formatter) {
    if (!in_array($formatter_key, $skip)) {
      $formatter['settings']['field_multiple_limit'] = FIELD_MULTIPLE_LIMIT_ALL;
      $formatter['settings']['field_multiple_limit_offset'] = 0;
      $formatter['settings']['field_multiple_limit_order'] = FIELD_MULTIPLE_LIMIT_ORDER_ORIGINAL;
    }
  }
}

/**
 * Implements hook_field_formatter_settings_summary_alter().
 */
function field_multiple_limit_field_formatter_settings_summary_alter(&$summary, $context) {
  $skip = _field_multiple_limit_skip();
  if (in_array($context['instance']['display'][$context['view_mode']]['type'], $skip)) {
    return;
  }
  if (!empty($context['field']['cardinality']) && ($context['field']['cardinality'] > 1 || $context['field']['cardinality'] == FIELD_CARDINALITY_UNLIMITED)) {
    $settings = $context['instance']['display'][$context['view_mode']]['settings'];
    if (!empty($summary)) {
      $summary .= '<br />';
    }
    if (!empty($settings['field_multiple_limit']) && $settings['field_multiple_limit'] != FIELD_MULTIPLE_LIMIT_ALL) {
      $summary .= t('Displaying @limit values', array(
        '@limit' => $settings['field_multiple_limit'],
      ));
    }
    else {
      $summary .= t('Displaying all values');
    }
    if (!empty($settings['field_multiple_limit_offset'])) {
      $summary .= '<br />' . t('Skipping the first @offset values', array(
        '@offset' => $settings['field_multiple_limit_offset'],
      ));
    }
    $limit_order = isset($settings['field_multiple_limit_order']) ? $settings['field_multiple_limit_order'] : FIELD_MULTIPLE_LIMIT_ORDER_ORIGINAL;
    switch ($limit_order) {
      case FIELD_MULTIPLE_LIMIT_ORDER_REVERSE:
        $summary .= '<br/>' . t('Reverse Order');
        break;
      case FIELD_MULTIPLE_LIMIT_ORDER_RANDOM:
        $summary .= '<br/>' . t('Random Order');
        break;
      default:
        break;
    }
  }
}

/**
 * Implements hook_field_formatter_settings_form_alter().
 */
function field_multiple_limit_field_formatter_settings_form_alter(&$settings_form, $context) {
  $skip = _field_multiple_limit_skip();
  if (in_array($context['instance']['display'][$context['view_mode']]['type'], $skip)) {
    return;
  }
  if (!empty($context['field']['cardinality']) && ($context['field']['cardinality'] > 1 || $context['field']['cardinality'] == FIELD_CARDINALITY_UNLIMITED)) {
    $settings = $context['instance']['display'][$context['view_mode']]['settings'];

    // Omit the two settings for view field settings only.
    $form_state = $context['form_state'];
    if (!array_key_exists('view', $form_state)) {
      $settings_form['field_multiple_limit'] = array(
        '#type' => 'select',
        '#title' => t('Number of values to display'),
        '#options' => array(
          FIELD_MULTIPLE_LIMIT_ALL => t('All'),
        ) + drupal_map_assoc(range(1, 10)),
        '#default_value' => $settings['field_multiple_limit'],
      );
      $settings_form['field_multiple_limit_offset'] = array(
        '#type' => 'select',
        '#title' => t('Number of values to skip'),
        '#options' => drupal_map_assoc(range(0, 10)),
        '#default_value' => $settings['field_multiple_limit_offset'],
      );
      $settings_form['field_multiple_limit_order'] = array(
        '#type' => 'radios',
        '#title' => t('Change order'),
        '#options' => array(
          0 => t('Original'),
          1 => t('Reverse'),
          2 => t('Random'),
        ),
        '#default_value' => $settings['field_multiple_limit_order'] ? $settings['field_multiple_limit_order'] : 0,
      );
    }
  }
}

/**
 * Implements hook_field_attach_view_alter().
 */
function field_multiple_limit_field_attach_view_alter(&$output, $context) {
  foreach (element_children($output) as $field_name) {
    $entity_type = $output[$field_name]['#entity_type'];
    $bundle = $output[$field_name]['#bundle'];
    $view_mode = $output[$field_name]['#view_mode'];
    $skip = _field_multiple_limit_skip();
    if (in_array($output[$field_name]['#formatter'], $skip)) {
      return;
    }
    $info = field_formatter_settings_get_instance_display_settings($entity_type, $field_name, $bundle, $view_mode);
    $limit = empty($info['field_multiple_limit']) ? FIELD_MULTIPLE_LIMIT_ALL : $info['field_multiple_limit'];
    $offset = empty($info['field_multiple_limit_offset']) ? 0 : $info['field_multiple_limit_offset'];
    $order = empty($info['field_multiple_limit_order']) ? FIELD_MULTIPLE_LIMIT_ORDER_ORIGINAL : $info['field_multiple_limit_order'];
    $element =& $output[$field_name];

    // Re-ordering comes before limiting.
    switch ($order) {
      case FIELD_MULTIPLE_LIMIT_ORDER_ORIGINAL:
        break;
      case FIELD_MULTIPLE_LIMIT_ORDER_REVERSE:

        // Cannot use #weight here, so just rearrange the rows by key.
        $resorted_items = array();
        foreach (element_children($element) as $element_child_id) {
          $element[$element_child_id]['#weight'] = -1 * $element_child_id;
          array_unshift($resorted_items, $element[$element_child_id]);
          unset($element[$element_child_id]);
        }
        $element += $resorted_items;
        break;
      case FIELD_MULTIPLE_LIMIT_ORDER_RANDOM:
        $shuffled = element_children($element);
        shuffle($shuffled);
        $resorted_items = array();
        foreach (element_children($element) as $element_child_id) {
          $resorted_items[$shuffled[$element_child_id]] = $element[$element_child_id];
          $resorted_items[$shuffled[$element_child_id]]['#weight'] = $shuffled[$element_child_id];
          unset($element[$element_child_id]);
        }
        $element += $resorted_items;
        break;
    }
    if ($offset > 0 || $limit != FIELD_MULTIPLE_LIMIT_ALL && $output[$field_name]['#items'] > $limit) {
      $count = 1;
      foreach ($element['#items'] as $delta => $item) {
        if ($delta < $offset) {
          unset($element[$delta]);
          continue;
        }
        if ($limit != FIELD_MULTIPLE_LIMIT_ALL && $count > $limit) {
          unset($element[$delta]);
        }
        $count++;
      }
      if (count(element_children($element)) == 0) {
        $element['#access'] = FALSE;
      }
    }
  }
}