A collection of Custom Formatters for various field types.

Field Type:


Date Formatters

D8: Date Range

The default presentation for a start/end date is:

Friday, June 9, 2018 - 10:00 - Sunday, June 11, 2018 - 11:30

The Date Range Formatter provides an abbreviated format that consolidates days, months and years if they are identical:

June 9, 2018
June 9 - June 10, 2018
June 9, 2018 - January 10, 2019


// Breaks days, months and years out if different
// June 9, 2018
// June 9 - June 10, 2018 
// June 9, 2018 - January 10, 2019 

  $element = array();
  $date_string_start = $items
    ->first()
    ->getValue()['value'];
  $date_string_end = $items
    ->first()
    ->getValue()['end_value'];
  if (!empty($date_string_start) && !empty($date_string_end)) {
    // Create new datetime objects from the start and end dates.
    $datetime_start = new DateTime($date_string_start, new DateTimeZone('UTC'));
    $datetime_end = new DateTime($date_string_end, new DateTimeZone('UTC'));
    $drupal_time_zone = date_default_timezone_get();
    // Time is stored in UTC - convert to local site timezone.
    $datetime_start->setTimezone(new DateTimeZone($drupal_time_zone));
    $datetime_end->setTimezone(new DateTimeZone($drupal_time_zone));
    // Format date elements to properly render the date.
    $event_date_start = $datetime_start->format('Y-m-d');
    $event_date_end = $datetime_end->format('Y-m-d');
    $event_start_day = $datetime_start->format('d');
    $event_end_day = $datetime_end->format('d');
    $event_start_month = $datetime_start->format('F');
    $event_end_month = $datetime_end->format('F');
    $event_start_year = $datetime_start->format('Y');
    $event_end_year = $datetime_end->format('Y');
    // Check if this is a one day event and print out one day with time.
    if ($event_date_start == $event_date_end) {
      $element = "$event_start_month $event_start_day, $event_end_year";
    }
    // Check if it is at least in the same year.
    elseif ($event_start_year == $event_end_year) {
      // And check if it is in the same month
      if ($event_start_month == $event_end_month) {
        $element = "$event_start_month $event_start_day" . '–' . "$event_end_day, $event_end_year";
        // If this is not in the same month but is in the same year, print
        // both months.
      }
      else {
        $element = "$event_start_month $event_start_day" . '–' . "$event_end_month $event_end_day, $event_end_year";
      }
    }
    // Well this is annoying, it's an event that runs between two different
    // years, two different months and different days so print all that madness.
    else {
      $element = "$event_start_month $event_start_day, $event_start_year" . '–' . "$event_end_month $event_end_day,  $event_end_year";
      }
      return $element;
  }

D7: Natural Date Format

The default presentation for a start/end date is:

Sunday, December 1, 2013 - 10:00 - Sunday, December 1, 2013 - 11:30

The Natural Data Formatter gives you more natural formats, such as (depending on field values):

Tuesday, June 9, 2015
Tuesday, June 9, 2015 at 12:00 p.m.
Tuesday, June 9, 2015 at 12:00 p.m. - 1:00 p.m.
Tuesday, June 9, 2015 - Wednesday, June 10, 2015
Tuesday, June 9, 2015 - Wednesday, June 10, 12:00 p.m. - 1:00 p.m.
(Multiple date fields will be broken into multiple lines with <br /> tags)

// Natural Date Formatter
// Displays as (depending on field values): 
//   Tuesday, June 9, 2015 
//   Tuesday, June 9, 2015 at 12:00 p.m.
//   Tuesday, June 9, 2015 at 12:00 p.m. - 1:00 p.m.
//   Tuesday, June 9, 2015 - Wednesday, June 10
//   Tuesday, June 9, 2015 - Wednesday, June 10, 2015, 12:00 p.m. - 1:00 p.m.
//   (Multiple date fields will be broken into multiple lines with <br /> tags

// Get all dates
$dates = $variables['#items'];

// Cycle through all dates (if more than one)
foreach ($dates as $index => $date) {
  $timezone = $date['timezone'];
  $timezone_db = $date['timezone_db'];
  $date1 = strtotime($date['value'] . ' ' . $timezone_db);
  $date2 = strtotime($date['value2'] . ' ' . $timezone_db);
  $rrule = $date['rrule'];

  // Get the start and end date for the current date
  $display = array('settings' => array('format_type' => 'medium'));
  $d1 = format_date($date1, 'custom', 'l, F j, Y', $timezone);
  $d2 = format_date($date2, 'custom', 'l, F j, Y', $timezone);
  $t1 = format_date($date1, 'custom', 'g:i a', $timezone);
  $t2 = format_date($date2, 'custom', 'g:i a', $timezone);

  // Change am to a.m. (add periods) and pm to p.m.
  $t1 = str_replace( array('am', 'pm'), array('a.m.', 'p.m.'), $t1 );
  $t2 = str_replace( array('am', 'pm'), array('a.m.', 'p.m.'), $t2 );

  // Print single date or a range (dash-separated)
  if (empty($d2) or $d1 == $d2) {
    $str = "$d1";
  } else {
    $str = "$d1 - $d2";
  }

  // If time is specified, print it (if time is blank or the same, print it once, otherwise print the range)
  if (empty($t1) && empty($t2)) {
    $str .= '';
  } elseif (empty($t2) || $t1 == $t2) {
    $str .= " at $t1";
  } else {
    $str .= ", $t1 - $t2";
  }
  $output[] = $str;
}

return( implode( '<br />', $output) );


D7: Display Age in Years

$element = array();
foreach ($variables['#items'] as $delta => $item) {
  // Calculation based on http://ibndawood.com/2011/10/calculating-the-age-of-a-person-given-their-birthdate/
  $element[$delta] = array(
    '#markup' => floor((time() - strtotime($item['value'])) / (365.2425 * 60 * 60 * 24)),
  );
}
return $element;


Image Formatters


D7: Image with Link

Displays a thumbnail image linked to a large image.

// Formatter settings.
$settings = $variables['#display']['settings'];
foreach (element_children($variables['#items']) as $delta) {
  $item = $variables['#items'][$delta];
  $source = theme('image_style', array('style_name' => $settings['image_style_source'], 'path' => $item['uri']));
  $destination = image_style_path($settings['image_style_destination'], $item['uri']);
  return l($source, file_create_url($destination), array('html' => TRUE));
}


Taxonomy Term Formatters


D7: Display Top (root) Parent Term Name

Apply to taxonomy_term_reference fields and this will show the top-most parent term, or itself if it is a top-level term.

NOTE: If used in a sortable Views table, it will not sort the results by this name, it will sort by the original term's name.

$tid = $variables['#items'][0]['tid'];
$terms = taxonomy_get_parents_all($tid);
$terms = array_reverse($terms);  // Make the top-most term first in array
$top_term = $terms[0];
return $top_term->name;


Text Field Formatters

D8: Uppercase Text Field

This formatter will convert the text field to uppercase. (Based on Custom Formatters 8.x-3.0-alpha1)

namespace Drupal\Core\TypedData;
use Drupal\Component\Utility\Unicode;

$output=array();
foreach ($items as $delta => $item) {
  $output[$delta] = ['#markup' => Unicode::strtoupper($item->getString())];
}
return($output);

Comments

brooke_heaton’s picture


// Breaks days, months and years out if different
// June 9, 2018
// June 9 - June 10, 2018 
// June 9, 2018 - January 10, 2019 

  $element = array();
  $date_string_start = $items
    ->first()
    ->getValue()['value'];
  $date_string_end = $items
    ->first()
    ->getValue()['end_value'];
  if (!empty($date_string_start) && !empty($date_string_end)) {
    // Create new datetime objects from the start and end dates.
    $datetime_start = new DateTime($date_string_start, new DateTimeZone('UTC'));
    $datetime_end = new DateTime($date_string_end, new DateTimeZone('UTC'));
    $drupal_time_zone = date_default_timezone_get();
    // Time is stored in UTC - convert to local site timezone.
    $datetime_start->setTimezone(new DateTimeZone($drupal_time_zone));
    $datetime_end->setTimezone(new DateTimeZone($drupal_time_zone));
    // Format date elements to properly render the date.
    $event_date_start = $datetime_start->format('Y-m-d');
    $event_date_end = $datetime_end->format('Y-m-d');
    $event_start_day = $datetime_start->format('d');
    $event_end_day = $datetime_end->format('d');
    $event_start_month = $datetime_start->format('F');
    $event_end_month = $datetime_end->format('F');
    $event_start_year = $datetime_start->format('Y');
    $event_end_year = $datetime_end->format('Y');
    // Check if this is a one day event and print out one day with time.
    if ($event_date_start == $event_date_end) {
      $element = "$event_start_month $event_start_day, $event_end_year";
    }
    // Check if it is at least in the same year.
    elseif ($event_start_year == $event_end_year) {
      // And check if it is in the same month
      if ($event_start_month == $event_end_month) {
        $element = "$event_start_month $event_start_day" . '–' . "$event_end_day, $event_end_year";
        // If this is not in the same month but is in the same year, print
        // both months.
      }
      else {
        $element = "$event_start_month $event_start_day" . '–' . "$event_end_month $event_end_day, $event_end_year";
      }
    }
    // Well this is annoying, it's an event that runs between two different
    // years, two different months and different days so print all that madness.
    else {
      $element = "$event_start_month $event_start_day, $event_start_year" . '–' . "$event_end_month $event_end_day,  $event_end_year";
      }
      return $element;
  }
generalconsensus’s picture

Thanks!

C.E.A’s picture

i have the telephone field added to the article content type.

When viewing the article, i want to display the telephone number field in this format: (+1-###-###-3010) instead of (+1-541-754-3010)

I am using Drupal 8 with the telephone core module.

Any help on how to accomplish this with the custom formatter module