4

I have a node display that shows about 20 different fields. One of the fields is a list of years (multiple values). Instead of printing the list of years I would like to just show the first and last year, for example "1999-2005".

Views has a great formatter for those situations but I don't want to use views for the node display.

4

You might want to test the following simple formatter I put together for one of my projects - named mvspan (multivalue span). Soon after I wrote it, the specs of my client changed and I did not need it anymore, therefore it may need some more tests, therefore please accept it in its "as-is" shape.

It works for simple text or integer types, not date or datestamps, unfortunately. Feel free to shape it for your own needs.

It has two modes: displaying first/last values or min/max values. Plus, it allows you to set the delimiter to glue up the values.

mvspan.info:

name = Multi-value Span
description = "Formats multi-value fields to show first/last or min/max value spans."
core = 7.x
files[] = mvspan.module

mvspan.module:

<?php
 /**
 * Implements hook_field_formatter_info().
 */
function mvspan_field_formatter_info() {
  return array(
    // the key must be unique, so it's best to prefix with your module's name.
    'mvspan_formatter' => array(
      'label' => t('Multi-value Span'),
      'field types' => array('text', 'number_integer'),
      'multiple values' => FIELD_BEHAVIOR_DEFAULT,
      'settings' => array(
        'delimiter' => '...',
        'mode' => 'minmax',
      )
    ),
  );
}

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

  $delimiter = check_plain($settings['delimiter']); // The delimiter string in the settings form

  switch($settings['mode']){
    case 'minmax':
      $minv = NULL;
      $maxv = NULL;

      foreach($items as $delta => $item) {
        if(is_null($minv) || $item['value'] < $minv){
          $minv = $item['value'];
        }
        if(is_null($maxv) || $item['value'] > $maxv){
          $maxv = $item['value'];
        }
      }

      if($minv === $maxv) {
        $element[0]['#markup'] = $minv;
      } else {
        $element[0]['#markup'] = implode($delimiter, array($minv, $maxv));
      }

      break;

    case 'firstlast':
      reset($items);
      $firstv = $items[key($items)]['value'];
      end($items);
      $lastv = $items[key($items)]['value'];

      $element[0]['#markup'] = implode($delimiter, array($firstv, $lastv));
      break;
  }
  return $element;
}

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

  // settings
  $element['delimiter'] = array(
    '#type' => 'textfield',
    '#title' => t('Delimiter'),
    '#description' => t('Delimiter string to be inserted between min and max values.'),
    '#default_value' => $settings['delimiter'],
  );
  $element['mode'] = array(
    '#type' => 'select',
    '#title' => t('Value handling'),
    '#description' => t('How multiple values will be managed: min/max or first/last'),
    '#default_value' => $settings['mode'],
    '#options' => array(
      'minmax' => t('Minimum/maximum'),
      'firstlast'  => t('First/last'),
    )
  );
  return $element;
}

/**
 * Implements hook_field_formatter_settings_summary().
 */
function mvspan_field_formatter_settings_summary($field, $instance, $view_mode) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];
  $summary = array();

  switch($settings['mode']){
    case 'minmax':
      $summary[] = t('<strong>Min/max</strong> values will be displayed');
      break;

    case 'firstlast':
      $summary[] = t('<strong>First/last</strong> values will be displayed');
      break;
  }
  $summary[] = t('using delimiter: "<strong>@delim</strong>"', array('@delim' => $settings['delimiter']));
  return implode('<br />', $summary);
}
2

I came across the theme_preprocess_field() function and got it working. But I feel it's not a slick solution:

function bartik_preprocess_field(&$variables) {
    if($variables['element']['#field_name'] == 'field_mc_years') {
        if(count($variables['items']) > 1) {    
            $to_year = end($variables['items']);
            $mc_years = $to_year['#markup'] . ' - '.$variables['items'][0]['#markup'];

            //destroy the array and just set the string to position 0
            unset($variables['items']);
            $variables['items']['0']['#markup'] = $mc_years;
        }
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.