home | career | drupal | java | mac | mysql | perl | php | scala | uml | unix

Drupal example source code file (date.module)

This example Drupal source code file (date.module) is included in the DevDaily.com "Drupal Source Code Warehouse" project. The intent of this project is to help you "Learn Drupal by Example".

PHP - Drupal tags/keywords

array, date, dates, empty, entity, entity_type, field, format, function, if, null, php, return

The date.module Drupal example source code

<?php

/**
 * @file
 * Defines date/time field types for the Content Construction Kit (CCK).
 */

module_load_include('theme', 'date', 'date');
module_load_include('inc', 'date', '/date.field');
module_load_include('inc', 'date', '/date_elements');

/**
 * Implements hook_menu().
 */
function date_menu() {
  $items = array();
  // Repeat dates tab on entity
  if (!module_exists('date_repeat')) {
    return $items;
  }
  $items['node/%node/repeats'] = array(
    'title' => 'Repeats',
    'page callback' => 'date_repeat_page',
    'page arguments' => array(1, 'node'),
    'access callback' => 'date_repeat_entity',
    'access arguments' => array(1, 'node'),
    'type' => MENU_LOCAL_TASK,
  );

  return $items;
}

function date_permission() {
  return array('view date repeats' => array(
    'title' => t('View Repeating Dates'),
    'description' => t('Allow user to see a tab with all the times this date repeats.'),
  ));
}

/**
 * See if the user can access repeat date
 * info on this entity.
 */
function date_repeat_entity($entity, $entity_type = 'node') {
  if (date_repeat_type($entity, $entity_type = 'node')) {
    return user_access('view date repeats');
  }
  return FALSE;
}

/**
 * See if there is a date field in this instance.
 *
 * Field type is not in the $field array we get from
 * field_info_instances(), we need to call
 * field_info_field() to find that.
 */
function date_repeat_type($entity, $entity_type = 'node') {
  $bundle = '';
  switch ($entity_type) {
    case 'node':
      $bundle = $entity->type;
      break;
  }
  $type = field_info_instances($entity_type, $bundle);
  foreach ($type as $field_name => $field) {
    $field = field_info_field($field_name);
    if (in_array($field['type'], array('date', 'datestamp', 'datetime')) && $field['settings']['repeat']) {
      return TRUE;
    }
  }
  return FALSE;
}

function date_repeat_fields($entity, $entity_type = 'node') {
  $bundle = '';
  switch ($entity_type) {
    case 'node':
      $bundle = $entity->type;
      break;
  }
  $type = field_info_instances($entity_type, $bundle);
  $fields = array();
  foreach ($type as $field_name => $field) {
    $field = field_info_field($field_name);
    if (in_array($field['type'], array('date', 'datestamp', 'datetime')) && $field['settings']['repeat']) {
      $fields[] = $field_name;
    }
  }
  return $fields;
}

function date_repeat_page($entity, $entity_type = 'node') {
  drupal_set_title($entity->title);
  $entity->date_repeat_show_all = TRUE;
  $entity->content = array();
  $field_names = date_repeat_fields($entity, $entity_type);
  $output = '';
  foreach ($field_names as $field_name) {
    $output .= drupal_render(field_view_field($entity_type, $entity, $field_name, 'full'));
  }
  return $output;
}

function date_is_repeat_field($field, $instance) {
  $repeat_widgets = array(
    'date_select_repeat',
    'date_text_repeat',
    'date_popup_repeat',
    );
  if (in_array($instance['widget']['type'], $repeat_widgets)) {
    return TRUE;
  }
  elseif (in_array($instance['widget']['type']['#value'], $repeat_widgets)) {
    return TRUE;
  }
  return FALSE;
}

function date_default_format($type) {
  if (stristr($type, 'date_popup') && module_exists('date_popup')) {
    $formats = date_popup_formats();
    $default_format = array_shift($formats);
  }
  else {
    // example input formats must show all possible date parts, so add seconds.
    $default_format = str_replace('i', 'i:s', variable_get('date_format_short', 'm/d/Y - H:i'));
  }
  return $default_format;
}

function date_input_date($field, $instance, $element, $input) {
  switch ($instance['widget']['type']) {
    case 'date_text':
    case 'date_text_repeat':
      $function = 'date_text_input_date';
      break;
    case 'date_popup':
    case 'date_popup_repeat':
      $function = 'date_popup_input_date';
      break;
    default:
      $function = 'date_select_input_date';
  }
  return $function($element, $input);
}

/**
 * Implements hook_theme().
 */
function date_theme() {
  $path = drupal_get_path('module', 'date');
  module_load_include('theme', 'date', 'date');

  $base = array(
    'file' => 'date.theme',
    'path' => "$path",
  );
  $themes = array(
    'date_combo' => $base + array('render element' => 'element'),
    'date_text_parts' => $base + array('render element' => 'element'),
    'date' => $base + array('render element' => 'element'),
    'date_all_day' => $base + array(
      'variables' => array(
        'field' => NULL,
        'instance' => NULL,
        'which' => NULL,
        'date1' => NULL,
        'date2' => NULL,
        'format' => NULL,
        'entity_type' => NULL,
        'entity' => NULL,
        'view' => NULL
      )
    ),
    'date_all_day_label' => $base + array('variables' => array()),
    'date_display_single' => $base + array('variables' => array(
        'date' => NULL,
        'timezone' => NULL
    )),
    'date_display_range' => $base + array(
      'variables' => array(
        'date1' => NULL,
        'date2' => NULL,
        'timezone' => NULL
    )),
    'date_repeat_display' => $base + array(
      'variables' => array(
        'field' => NULL,
        'item' => NULL,
        'entity_type' => NULL,
        'entity' => NULL,
        'dates' => NULL
      ),
      'function' => 'theme_date_repeat_display',
      ),
     'date_display_combination' => $base + array(
       'variables' => array(
         'entity_type' => NULL,
         'entity' => NULL,
         'field' => NULL,
         'instance' => NULL,
         'langcode' => NULL,
         'item' => NULL,
         'delta' => NULL,
         'display' => NULL,
         'dates' => NULL,
        ),
     ),
     'date_display_interval' => $base + array(
       'variables' => array(
         'entity_type' => NULL,
         'entity' => NULL,
         'field' => NULL,
         'instance' => NULL,
         'langcode' => NULL,
         'item' => NULL,
         'delta' => NULL,
         'display' => NULL,
         'dates' => NULL,
        ),
     ),
  );

  return $themes;
}

/**
 * Implements hook_element_info().
 *
 * date_combo will create a 'from' and optional 'to' date, along with
 * an optional 'timezone' column for date-specific timezones. Each
 * 'from' and 'to' date will be constructed from date_select or date_text.
 */
function date_element_info() {
  $type = array();
  $type['date_combo'] = array(
    '#input' => TRUE,
    '#delta' => 0,
    '#columns' => array('value', 'value2', 'timezone', 'offset', 'offset2'),
    '#process' => array('date_combo_element_process'),
    '#element_validate' => array('date_combo_validate'),
    '#value_callback' => 'date_combo_value_callback',
    '#theme_wrappers' => array('date_combo'),
    );
  return $type;
}

/**
 * Helper function for creating formatted date arrays from a formatter.
 *
 * Use the Date API to get an object representation of a date field
 *
 * @param array $field
 * @param array $item - a entity field item, like $entity->myfield[0]
 *
 * @return array that holds the From and To date objects
 *  Each date object looks like:
 *       date [value] => array (
 *         [db] => array (  // the value stored in the database
 *           [object] => the datetime object
 *           [datetime] => 2007-02-15 20:00:00
 *         )
 *         [local] => array (  // the local representation of that value
 *           [object] => the datetime object
 *           [datetime] => 2007-02-15 14:00:00
 *           [timezone] => US/Central
 *           [offset] => -21600
 *         )
 *      )
 */
function date_formatter_process($formatter, $entity_type, $entity, $field, $instance, $langcode, $item, $display) {
  $dates = array();
  $timezone = date_default_timezone();    
  if (empty($timezone)) {
    return $dates;
  }

  $granularity = date_granularity($field);
  $settings = $display['settings'];
  $field_name = $field['field_name'];
  $format = date_formatter_format($formatter, $settings, $granularity, $langcode);
  $timezone = isset($item['timezone']) ? $item['timezone'] : '';
  $timezone = date_get_timezone($field['settings']['tz_handling'], $timezone);
  $timezone_db = date_get_timezone_db($field['settings']['tz_handling']);
  $process = date_process_values($field);
  foreach ($process as $processed) {
    if (empty($item[$processed])) {
      $dates[$processed] = NULL;
    }
    else {
      // create a date object with a gmt timezone from the database value
      $value = $item[$processed];
      // @TODO Figure out how to replace date_fuzzy_datetime() function.
      if ($field['type'] == DATE_ISO) {
        //$value = str_replace(' ', 'T', date_fuzzy_datetime($value));
      }
      $date = new DateObject($value, $timezone_db);
      $date->limitGranularity($field['settings']['granularity']);

      $dates[$processed] = array();
      $dates[$processed]['db']['object'] = $date;
      $dates[$processed]['db']['datetime'] = date_format($date, DATE_FORMAT_DATETIME);

      date_timezone_set($date, timezone_open($timezone));
      $dates[$processed]['local']['object'] = $date;
      $dates[$processed]['local']['datetime'] = date_format($date, DATE_FORMAT_DATETIME);
      $dates[$processed]['local']['timezone'] = $timezone;
      $dates[$processed]['local']['offset'] = date_offset_get($date);

      //format the date, special casing the 'interval' format which doesn't need to be processed
      $dates[$processed]['formatted'] = '';
      if (is_object($date)) {
        if ($format == 'format_interval') {
           $dates[$processed]['interval'] = date_format_interval($date);
        }
        elseif ($format == 'format_calendar_day') {
           $dates[$processed]['calendar_day'] = date_format_calendar_day($date);
        }
        elseif ($format == 'U') {
          $dates[$processed]['formatted'] = date_format_date($date, 'custom', $format);
          $dates[$processed]['formatted_date'] = date_format_date($date, 'custom', $format);
          $dates[$processed]['formatted_time'] = '';
          $dates[$processed]['formatted_timezone'] = '';
        }
        elseif (!empty($format)) {
          $dates[$processed]['formatted'] = date_format_date($date, 'custom', $format);
          $dates[$processed]['formatted_date'] = date_format_date($date, 'custom', date_limit_format($format, array('year', 'month', 'day')));
          $dates[$processed]['formatted_time'] = date_format_date($date, 'custom', date_limit_format($format, array('hour', 'minute', 'second')));
          $dates[$processed]['formatted_timezone'] = date_format_date($date, 'custom', date_limit_format($format, array('timezone')));
        }
      }
    }
  }
  if (empty($dates['value2'])) {
    $dates['value2'] = $dates['value'];
  }
  $date1 = $dates['value']['local']['object'];
  $date2 = $dates['value2']['local']['object'];

  $all_day = '';
  $all_day2 = '';
  if ($format != 'format_interval') {
    $all_day1 = theme('date_all_day', array(
      'field' => $field,
      'which' => 'date1',
      'date1' => $date1,
      'date2' => $date2,
      'format' => $format,
      'entity_type' => $entity_type,
      'entity' => $entity));
    $all_day2 = theme('date_all_day', array(
      'field' => $field,
      'which' => 'date2',
      'date1' => $date1,
      'date2' => $date2,
      'format' => $format,
      'entity_type' => $entity_type,
      'entity' => $entity));
  }
  if ((!empty($all_day1) && $all_day1 != $dates['value']['formatted'])
  || (!empty($all_day2) && $all_day2 != $dates['value2']['formatted'])) {
    $dates['value']['formatted_time'] = theme('date_all_day_label');
    $dates['value2']['formatted_time'] = theme('date_all_day_label');
    $dates['value']['formatted'] = $all_day1;
    $dates['value2']['formatted'] = $all_day2;
  }
  $dates['format'] = $format;
  return $dates;
}

/**
 * $field['settings']['granularity'] will contain an array like ('hour' => 'hour', 'month' => 0)
 * where the values turned on return their own names and the values turned off return a zero
 * need to reconfigure this into a simple array of the turned on values
 */
function date_granularity($field) {
  if (!is_array($field) || !is_array($field['settings']['granularity'])) {
    $field['settings']['granularity'] = drupal_map_assoc(array('year', 'month', 'day'));
  }
  return array_values(array_filter($field['settings']['granularity']));
}

/**
 * Helper function to create an array of the date values in a
 * field that need to be processed.
 */
function date_process_values($field) {
  return $field['settings']['todate'] ? array('value', 'value2') : array('value');
}

/**
 * Implement hook_help().
 */
function date_help($path, $arg) {
  switch ($path) {
    case 'admin/help#date':
      return '<p>' . t('Complete documentation for the Date and Date API modules is available at <a href="@link">http://drupal.org/node/92460</a>.', array('@link' => 'http://drupal.org/node/92460')) . '</p>';
      break;
  }
}

/**
 * Implements hook_form_alter().
 * Make sure date information gets updated.
 */
function date_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'field_ui_field_edit_form') {
    $field = $form['field'];
    $instance = $form['instance'];
    // If adding a repeat, override the Content module's handling of the multiple values option.
    if (module_exists('date_repeat') && date_is_repeat_field($field, $instance)) {
      $form['field']['cardinality'] = array('#type' => 'hidden', '#value' => FIELD_CARDINALITY_UNLIMITED);
    }
  }
}

/**
 * Implements hook_field_widget_error().
 */
function date_field_widget_error($element, $error, $form, &$form_state) {
  form_error($element[$error['error']], $error['message']);
}

/**
 * Retrieve a date format string from formatter settings.
 */
function date_formatter_format($formatter, $settings, $granularity = NULL, $langcode = NULL) {
  $default = variable_get('date_format_medium',  'D, m/d/Y - H:i');
  $format_type = !empty($settings['format_type']) ? $settings['format_type'] : 'format_interval';

  switch ($formatter) {
    case 'format_interval':
      return 'format_interval';
      break;
    case 'date_default':
      $format = system_date_format_locale($langcode, $format_type);
      if (empty($format)) {
        $format = variable_get('date_format_'. $format_type, $default);
      }      
      break; 
    default:
      $type = str_replace('date_', '', $formatter);
      $format = system_date_format_locale($langcode, $type);
      if (empty($format)) {
        $format = variable_get('date_format_'. $type, $default);
      }
      break;
  }

  // A selected format might include timezone information.
  array_push($granularity, 'timezone');
  return date_limit_format($format, $granularity);
}

/**
 * Helper function to adapt entity date fields to formatter settings.
 */
function date_prepare_entity($formatter, $entity_type, $entity, $field, $instance, $langcode, $item, $display) {

  // If there are options to limit multiple values,
  // alter the entity values to match.
  $field_name = $field['field_name'];
  $options = $display['settings'];
  $max_count = $options['multiple_number'];

  // If no results should be shown, empty the values and return.
  if (is_numeric($max_count) && $max_count == 0) {
    $entity->{$field_name} = array();
    return $entity;
  }

  // Otherwise removed values that should not be displayed.
  if (!empty($options['multiple_from']) || !empty($options['multiple_to']) || !empty($max_count)) {
    $format = date_type_format($field['type']);
    include_once(drupal_get_path('module', 'date_api') . '/date_api_sql.inc');
    $date_handler = new date_sql_handler($field);
    $arg0 = !empty($options['multiple_from']) ? $date_handler->arg_replace($options['multiple_from']) : variable_get('date_min_year', 100) . '-01-01T00:00:00';
    $arg1 = !empty($options['multiple_to']) ? $date_handler->arg_replace($options['multiple_to']) : variable_get('date_max_year', 4000) . '-12-31T23:59:59';
    if (!empty($arg0) && !empty($arg1)) {
      $arg = $arg0 . '--' . $arg1;
    }
    elseif (!empty($arg0)) {
      $arg = $arg0;
    }
    elseif (!empty($arg1)) {
      $arg = $arg1;
    }
    if (!empty($arg)) {
      $range = $date_handler->arg_range($arg);
      $start = date_format($range[0], $format);
      $end = date_format($range[1], $format);
      // Empty out values we don't want to see.
      $count = 0;
      foreach ($entity->{$field_name}[$langcode] as $delta => $value) {
        if (!empty($entity->date_repeat_show_all)) {
          break;
        }
        elseif ((!empty($max_count) && is_numeric($max_count) && $count >= $max_count) ||
          (!empty($value['value'])  && $value['value'] < $start) ||
          (!empty($value['value2']) && $value['value2'] > $end)) {
            unset($entity->{$field_name}[$langcode][$delta]);
        }
        else {
          $count++;
        }  
      }
    }
  }

  return $entity;
}

/**
 * Generate a DateAPI SQL handler for the given CCK date field.
 *
 * The handler will be set up to make the correct timezone adjustments
 * for the field settings.
 *
 * @param $field
 *  - a $field array.
 * @param $compare_tz
 *  - the timezone used for comparison values in the SQL.
 */
 function date_field_get_sql_handler($field, $compare_tz = NULL) {
   module_load_include('inc', 'date_api', 'date_api_sql');

   $db_info = date_api_database_info($field);

   // Create a DateAPI SQL handler class for this field type.
   $handler = new date_sql_handler();
   $handler->construct($field['type']);

   // If this date field stores a timezone in the DB, tell the handler about it.
   if ($field['settings']['tz_handling'] == 'date') {
     $handler->db_timezone_field = $db_info['columns']['timezone']['column'];
   }
   else {
     $handler->db_timezone = date_get_timezone_db($field['settings']['tz_handling']);
   }

   if (empty($compare_tz)) {
     $compare_tz = date_get_timezone($field['settings']['tz_handling']);
   }
   $handler->local_timezone = $compare_tz;

  // Now that the handler is properly initialized, force the DB
  // to use UTC so no timezone conversions get added to things like
  // NOW() or FROM_UNIXTIME().
  $handler->set_db_timezone();

  return $handler;
}

/**
 * Callback to alter the property info of date fields.
 *
 * @see date_field_info()
 */
function date_entity_metadata_property_info_alter(&$info, $entity_type, $field, $instance, $field_type) {
  $name = $field['field_name'];
  $property = &$info[$entity_type]['bundles'][$instance['bundle']]['properties'][$name];
  if ($field['type'] != 'datestamp' || $field['settings']['timezone_db'] != 'UTC') {
    // Add a getter callback to convert the date into the right format.
    $property['getter callback'] = 'date_entity_metadata_field_getter';
    unset($property['query callback']);
    unset($property['setter callback']);
  }
  if (!empty($field['settings']['todate'])) {
    // Define a simple data structure containing both dates.
    $property['type'] = ($field['cardinality'] != 1) ? 'list<struct>' : 'struct';
    $property['getter callback'] = 'entity_metadata_field_verbatim_get';
    $property['property info'] = array(
      'value' => array(
        'type' => 'date',
        'label' => t('From date'),
        'getter callback' => 'date_entity_metadata_struct_getter',
      ),
      'value2' => array(
        'type' => 'date',
        'label' => t('To date'),
        'getter callback' => 'date_entity_metadata_struct_getter',
      ),
      'duration' => array(
        'type' => 'duration',
        'label' => t('Duration'),
        'desription' => t('The duration of the time period given by the dates.'),
        'getter callback' => 'date_entity_metadata_duration_getter',
      ),
    );
    unset($property['query callback']);
    unset($property['setter callback']);
  }
}

/**
 * Getter callback to return date values as datestamp in UTC from the field.
 */
function date_entity_metadata_field_getter($object, array $options, $name, $obj_type, &$context) {
  $return = entity_metadata_field_verbatim_get($object, $options, $name, $obj_type, $context);
  $items = ($context['field']['cardinality'] == 1) ? array($return) : $return;
  foreach ($items as $key => $item) {
    $items[$key] = date_entity_metadata_struct_getter($item, $options, 'value', 'struct');
  }
  return ($context['field']['cardinality'] == 1) ? $items[0] : $items;
}

/**
 * Getter callback to return date values as datestamp in UTC.
 */
function date_entity_metadata_struct_getter($item, array $options, $name, $type) {
  $value = trim($item[$name]);
  $timezone_db = !empty($item['timezone_db']) ? $item['timezone_db'] : 'UTC';
  $date = new DateObject($value, $timezone_db);
  return !empty($date) ? date_format_date($date, 'custom', 'U') : NULL;
}

/**
 * Getter callback to return the duration of the time period given by the dates.
 */
function date_entity_metadata_duration_getter($item, array $options, $name, $type) {
  $value = date_entity_metadata_struct_getter($item, $options, 'value', 'struct');
  $value2 = date_entity_metadata_struct_getter($item, $options, 'value2', 'struct');
  if ($value && $value2) {
    return $value2 - $value;
  }
}

/**
 * Determine if a from/to date combination qualify as 'All day'.
 *
 * @param array $field, the field definition for this date field.
 * @param object $date1, a date/time object for the 'from' date.
 * @param object $date2, a date/time object for the 'to' date.
 * @return TRUE or FALSE.
 */
function date_field_all_day($field, $instance, $date1, $date2 = NULL) {
  if (empty($date1) || !is_object($date1)) {
    return FALSE;
  }
  elseif (!date_has_time($field['settings']['granularity'])) {
    return FALSE;
  }
  if (empty($date2)) {
    $date2 = $date1;
  }

  $granularity = $field['settings']['granularity'];
  $granularity = array_pop($granularity);
  $increment = isset($instance['widget']['increment']) ? $instance['widget']['increment'] : 1;
  return date_is_all_day(date_format($date1, DATE_FORMAT_DATETIME), date_format($date1, DATE_FORMAT_DATETIME), $granularity, $increment);

}

Other Drupal examples (source code examples)

Here is a short list of links related to this Drupal date.module source code file:

new blog posts

"Drupal" is a registered trademark of Dries Buytaert.

my drupal tutorials and examples  

Copyright 1998-2016 Alvin Alexander, alvinalexander.com
All Rights Reserved.

Beginning in 2016, a portion of the proceeds from pages under the '/drupal-code-examples/' URI will be donated to charity.