Newer
Older
Karen Stevenson
committed
<?php
Karen Stevenson
committed
/**
* @file
* Field hooks to implement a date field.
*/
/**
* Implements hook_field_formatter_info().
*/
function date_field_formatter_info() {
$formatters = array(
'date_default' => array(
Arlin Sandbulte
committed
'label' => t('Date and time'),
Karen Stevenson
committed
'field types' => array('date', 'datestamp', 'datetime'),
'settings' => array(
'format_type' => 'long',
'multiple_number' => '',
'multiple_from' => '',
'multiple_to' => '',
'fromto' => 'both',
),
),
'format_interval' => array(
Arlin Sandbulte
committed
'label' => t('Time ago'),
Karen Stevenson
committed
'field types' => array('date', 'datestamp', 'datetime'),
'settings' => array(
'interval' => 2,
),
),
Karen Stevenson
committed
'date_plain' => array(
'label' => t('Plain'),
'field types' => array('date', 'datestamp', 'datetime'),
),
Karen Stevenson
committed
);
return $formatters;
}
/**
* Implements hook_field_formatter_settings_form().
*/
function date_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
$display = $instance['display'][$view_mode];
$formatter = $display['type'];
module_load_include('inc', 'date', 'date_admin');
switch ($formatter) {
case 'format_interval':
$form = date_interval_formatter_settings_form($field, $instance, $view_mode, $form, $form_state);
Karen Stevenson
committed
break;
Karen Stevenson
committed
default:
$form = date_default_formatter_settings_form($field, $instance, $view_mode, $form, $form_state);
Karen Stevenson
committed
break;
Karen Stevenson
committed
}
$context = array(
'field' => $field,
'instance' => $instance,
'view_mode' => $view_mode,
);
drupal_alter('date_field_formatter_settings_form', $form, $form_state, $context);
return $form;
Karen Stevenson
committed
}
Karen Stevenson
committed
/**
* Implements hook_field_formatter_settings_summary().
*/
function date_field_formatter_settings_summary($field, $instance, $view_mode) {
$display = $instance['display'][$view_mode];
$formatter = $display['type'];
module_load_include('inc', 'date', 'date_admin');
switch ($formatter) {
case 'format_interval':
$summary = date_interval_formatter_settings_summary($field, $instance, $view_mode);
Karen Stevenson
committed
default:
$summary = date_default_formatter_settings_summary($field, $instance, $view_mode);
Karen Stevenson
committed
}
$context = array(
'field' => $field,
'instance' => $instance,
'view_mode' => $view_mode,
);
drupal_alter('date_field_formatter_settings_summary', $summary, $context);
return implode('<br />', $summary);
Karen Stevenson
committed
}
/**
* Implements hook_field_formatter_view().
*
* Useful values:
*
* $entity->date_id
* If set, this will show only an individual date on a field with
* multiple dates. The value should be a string that contains
Karen Stevenson
committed
* the following values, separated with periods:
Karen Stevenson
committed
* - module name of the module adding the item
* - node nid
* - field name
* - delta value of the field to be displayed
* - other information the module's custom theme might need
*
* Used by the calendar module and available for other uses.
* example: 'date:217:field_date:3:test'
*
* $entity->date_repeat_show
* If true, tells the theme to show all the computed values
* of a repeating date. If not true or not set, only the
* start date and the repeat rule will be displayed.
*/
function date_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
$settings = $display['settings'];
$formatter = $display['type'];
$variables = array(
Karen Stevenson
committed
'entity' => $entity,
'entity_type' => $entity_type,
'field' => $field,
'instance' => $instance,
'langcode' => $langcode,
'items' => $items,
'display' => $display,
'dates' => array(),
'attributes' => array(),
'rdf_mapping' => array(),
'add_rdf' => module_exists('rdf'),
Karen Stevenson
committed
);
// If there is an RDf mapping for this date field, pass it down to the theme.
$rdf_mapping = array();
if (!empty($entity->rdf_mapping) && function_exists('rdf_rdfa_attributes')) {
if (!empty($entity->rdf_mapping[$field['field_name']])) {
$variables['rdf_mapping'] = $rdf_mapping = $entity->rdf_mapping[$field['field_name']];
}
}
Karen Stevenson
committed
// See if we are only supposed to display a selected
// item from multiple value date fields.
$selected_deltas = array();
if (!empty($entity->date_id)) {
foreach ((array) $entity->date_id as $key => $id) {
Karen Stevenson
committed
list($module, $nid, $field_name, $selected_delta, $other) = explode('.', $id . '.');
Karen Stevenson
committed
if ($field_name == $field['field_name']) {
$selected_deltas[] = $selected_delta;
}
}
}
Karen Stevenson
committed
switch ($display['type']) {
Karen Stevenson
committed
case 'date_plain':
foreach ($items as $delta => $item) {
if (!empty($entity->date_id) && !in_array($delta, $selected_deltas)) {
continue;
}
else {
if (empty($item['value2']) || $item['value'] == $item['value2']) {
$element[$delta] = array('#markup' => $item['value']);
}
else {
$element[$delta] = array('#markup' => t('!start-date to !end-date', array('!start-date' => $item['value'], '!end-date' => $item['value2'])));
}
}
}
break;
Karen Stevenson
committed
case 'format_interval':
foreach ($items as $delta => $item) {
if (!empty($entity->date_id) && !in_array($delta, $selected_deltas)) {
continue;
}
else {
$variables['delta'] = $delta;
$variables['item'] = $item;
$variables['dates'] = date_formatter_process($formatter, $entity_type, $entity, $field, $instance, $langcode, $item, $display);
$variables['attributes'] = !empty($rdf_mapping) ? rdf_rdfa_attributes($rdf_mapping, $item['value']) : array();
$element[$delta] = array('#markup' => theme('date_display_interval', $variables));
Karen Stevenson
committed
}
}
break;
default:
foreach ($items as $delta => $item) {
if (!empty($entity->date_id) && !in_array($delta, $selected_deltas)) {
continue;
}
else {
$variables['delta'] = $delta;
$variables['item'] = $item;
$variables['dates'] = date_formatter_process($formatter, $entity_type, $entity, $field, $instance, $langcode, $item, $display);
$variables['attributes'] = !empty($rdf_mapping) ? rdf_rdfa_attributes($rdf_mapping, $item['value']) : array();
$output = theme('date_display_combination', $variables);
Karen Stevenson
committed
if (!empty($output)) {
Karen Stevenson
committed
$element[$delta] = array('#markup' => $output);
Karen Stevenson
committed
}
Karen Stevenson
committed
}
}
break;
}
return $element;
}
/**
* Implements hook_field_is_empty().
*/
function date_field_is_empty($item, $field) {
// Sometimes a $item is a date object.
// Coming from repeating dates. Why??
Karen Stevenson
committed
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
if (!is_array($item)) {
return FALSE;
}
if (empty($item['value'])) {
return TRUE;
}
elseif ($field['settings']['todate'] == 'required' && empty($item['value2'])) {
return TRUE;
}
return FALSE;
}
/**
* Implements hook_field_info().
*/
function date_field_info() {
$settings = array(
'settings' => array(
'todate' => '',
'granularity' => drupal_map_assoc(array('year', 'month', 'day', 'hour', 'minute')),
'tz_handling' => 'site',
'timezone_db' => 'UTC',
),
'instance_settings' => array(
'default_value' => 'now',
'default_value_code' => '',
Karen Stevenson
committed
'default_value2' => 'same',
Karen Stevenson
committed
'default_value_code2' => '',
),
// Integrate with the Entity Metadata module.
'property_type' => 'date',
'property_callbacks' => array('date_entity_metadata_property_info_alter'),
);
return array(
Karen Stevenson
committed
'datetime' => array(
Karen Stevenson
committed
'label' => 'Date',
Karen Stevenson
committed
'description' => t('Store a date in the database as a datetime field, recommended for complete dates and times that may need timezone conversion.'),
Karen Stevenson
committed
'default_widget' => 'date_select',
'default_formatter' => 'date_default',
Karen Stevenson
committed
'default_token_formatter' => 'date_plain',
Karen Stevenson
committed
) + $settings,
Karen Stevenson
committed
'date' => array(
'label' => 'Date (ISO format)',
'description' => t('Store a date in the database as an ISO date, recommended for historical or partial dates.'),
Karen Stevenson
committed
'default_widget' => 'date_select',
'default_formatter' => 'date_default',
Karen Stevenson
committed
'default_token_formatter' => 'date_plain',
Karen Stevenson
committed
) + $settings,
Karen Stevenson
committed
'datestamp' => array(
'label' => 'Date (Unix timestamp)',
'description' => t('Store a date in the database as a timestamp, deprecated format to support legacy data.'),
Karen Stevenson
committed
'default_widget' => 'date_select',
'default_formatter' => 'date_default',
Karen Stevenson
committed
'default_token_formatter' => 'date_plain',
Karen Stevenson
committed
) + $settings,
);
}
/**
* Implements hook_field_widget_info().
*/
function date_field_widget_info() {
$settings = array(
'settings' => array(
'input_format' => date_default_format('date_select'),
'input_format_custom' => '',
Karen Stevenson
committed
'increment' => 15,
Karen Stevenson
committed
'text_parts' => array(),
'year_range' => '-3:+3',
'label_position' => 'above',
),
'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
Karen Stevenson
committed
'default value' => FIELD_BEHAVIOR_NONE,
Karen Stevenson
committed
),
);
Karen Stevenson
committed
$info = array(
'date_select' => array(
Karen Stevenson
committed
'label' => t('Select list'),
Karen Stevenson
committed
'field types' => array('date', 'datestamp', 'datetime'),
) + $settings,
'date_text' => array(
Karen Stevenson
committed
'label' => t('Text field'),
Karen Stevenson
committed
'field types' => array('date', 'datestamp', 'datetime'),
) + $settings,
);
if (module_exists('date_popup')) {
$info['date_popup'] = array(
Karen Stevenson
committed
'label' => t('Pop-up calendar'),
Karen Stevenson
committed
'field types' => array('date', 'datestamp', 'datetime'),
) + $settings;
}
return $info;
}
/**
* Implements hook_field_load().
*/
function date_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
Tim Plunkett
committed
$timezone_db = date_get_timezone_db($field['settings']['tz_handling']);
$db_format = date_type_format($field['type']);
$process = date_process_values($field);
Karen Stevenson
committed
foreach ($entities as $id => $entity) {
Karen Stevenson
committed
foreach ($items[$id] as $delta => &$item) {
Karen Stevenson
committed
// If the file does not exist, mark the entire item as empty.
if (is_array($item)) {
Karen Stevenson
committed
$timezone = isset($item['timezone']) ? $item['timezone'] : '';
$item['timezone'] = date_get_timezone($field['settings']['tz_handling'], $timezone);
Tim Plunkett
committed
$item['timezone_db'] = $timezone_db;
Karen Stevenson
committed
$item['date_type'] = $field['type'];
Tim Plunkett
committed
if (!empty($field['settings']['cache_enabled']) && ($delta < $field['settings']['cache_count'] || $field['settings']['cache_count'] == 0)) {
foreach ($process as $processed) {
if (!empty($item[$processed])) {
$date = new DateObject($item[$processed], $item['timezone_db'], $db_format);
$date->limitGranularity($field['settings']['granularity']);
$item['db'][$processed] = $date;
}
}
if (!empty($item['db']['value']) && empty($item['db']['value2'])) {
$item['db']['value2'] = $item['db']['value'];
Karen Stevenson
committed
}
}
Karen Stevenson
committed
}
}
}
}
/**
* Implements hook_field_validate().
*/
function date_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
$field_name = $field['field_name'];
$flexible = 0;
Karen Stevenson
committed
// Don't try to validate if there were any errors before this point
// since the element won't have been munged back into a date.
if (!form_get_errors()) {
foreach ($items as $delta => $item) {
if (is_array($item) && isset($item['value'])) {
Karen Stevenson
committed
$process = date_process_values($field, $instance);
$date1 = new DateObject($item['value'], $item['timezone'], date_type_format($field['type']));
Karen Stevenson
committed
if (count($process) == 1 || (empty($item['value2']) && $item['value2'] !== 0)) {
Karen Stevenson
committed
$date2 = clone($date1);
}
else {
$date2 = new DateObject($item['value2'], $item['timezone'], date_type_format($field['type']));
}
$valid1 = $date1->validGranularity($field['settings']['granularity'], $flexible);
$valid2 = $date2->validGranularity($field['settings']['granularity'], $flexible);
Karen Stevenson
committed
foreach ($process as $processed) {
if ($processed == 'value' && $field['settings']['todate'] && !$valid1 && $valid2) {
$errors[$field['field_name']][$langcode][$delta][] = array(
'error' => 'value',
'message' => t("A 'Start date' date is required for field %field #%delta.", array('%delta' => $field['cardinality'] ? intval($delta + 1) : '', '%field' => $instance['label'])),
Karen Stevenson
committed
);
}
if ($processed == 'value2' && $field['settings']['todate'] == 'required' && ($instance['required'] && $valid1 && !$valid2)) {
$errors[$field['field_name']][$langcode][$delta][] = array(
'error' => 'value2',
'message' => t("An 'End date' is required for field %field #%delta.", array('%delta' => $field['cardinality'] ? intval($delta + 1) : '', '%field' => $instance['label'])),
Karen Stevenson
committed
);
Karen Stevenson
committed
}
}
}
}
/**
* Implements hook_field_insert().
*/
function date_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
Karen Stevenson
committed
date_field_update_helper($entity_type, $entity, $field, $instance, $langcode, $items);
$context = array(
'entity_type' => $entity_type,
'entity' => $entity,
'field' => $field,
'instance' => $instance,
'langcode' => $langcode,
);
drupal_alter('date_field_insert', $items, $context);
Karen Stevenson
committed
}
/**
* Implements hook_field_update().
*/
function date_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) {
Karen Stevenson
committed
date_field_update_helper($entity_type, $entity, $field, $instance, $langcode, $items);
$context = array(
'entity_type' => $entity_type,
'entity' => $entity,
'field' => $field,
'instance' => $instance,
'langcode' => $langcode,
);
drupal_alter('date_field_update', $items, $context);
}
/**
* A helper function for the code that needs to happen in both
* inserts and updates.
*/
function date_field_update_helper($entity_type, $entity, $field, $instance, $langcode, &$items) {
Karen Stevenson
committed
$field_name = $field['field_name'];
if (empty($items)) {
return;
}
// Add some information needed to interpret token values.
$values = $items;
foreach ($values as $delta => $item) {
$timezone = isset($item['timezone']) ? $item['timezone'] : '';
if (is_array($item)) {
$items[$delta]['timezone'] = date_get_timezone($field['settings']['tz_handling'], $timezone);
$items[$delta]['timezone_db'] = date_get_timezone_db($field['settings']['tz_handling']);
$items[$delta]['date_type'] = $field['type'];
Karen Stevenson
committed
$entity->{$field['field_name']}[$langcode] = $items;
// @TODO Decide how to replace the date_limit_value() function.
/*
Karen Stevenson
committed
foreach ($values as $delta => $item) {
if (is_array($item)) {
// Special case for ISO dates which may have been given artificial values
// for some date parts to make them into valid dates.
Karen Stevenson
committed
if (!empty($item['value']) && $field['type'] == DATE_ISO) {
$items[$delta]['value'] = date_limit_value($items[$delta]['value'], date_granularity($field), $field['type']);
Karen Stevenson
committed
if ($field['settings']['todate']) {
$items[$delta]['value2'] = date_limit_value($items[$delta]['value2'], date_granularity($field), $field['type']);
Karen Stevenson
committed
}
Karen Stevenson
committed
}
}
Karen Stevenson
committed
$entity->{$field['field_name']}[$langcode] = $items;
}
/**
* Implements hook_field_instance_settings_form().
*
* Wrapper functions for date administration, included only when processing
* field settings.
Karen Stevenson
committed
*/
function date_field_instance_settings_form($field, $instance) {
module_load_include('inc', 'date', 'date_admin');
return _date_field_instance_settings_form($field, $instance);
}
/**
* Implements hook_field_widget_settings_form().
*/
Karen Stevenson
committed
function date_field_widget_settings_form($field, $instance) {
module_load_include('inc', 'date', 'date_admin');
return _date_field_widget_settings_form($field, $instance);
}
/**
* Implements hook_field_settings_form().
*/
Karen Stevenson
committed
function date_field_settings_form($field, $instance, $has_data) {
module_load_include('inc', 'date', 'date_admin');
return _date_field_settings_form($field, $instance, $has_data);
}
/**
* Implements hook_content_migrate_field_alter().
* Use this to tweak the conversion of field settings from the D6 style to the
* D7 style for specific situations not handled by basic conversion, as when
* field types or settings are changed.
* $field_value['widget_type'] is available to see what widget type was
* originally used.
Karen Stevenson
committed
*/
Karen Stevenson
committed
function date_content_migrate_field_alter(&$field_value, $instance_value) {
Karen Stevenson
committed
switch ($field_value['module']) {
case 'date':
// Those settings do not exist anymore, or have been moved to the instance
// level.
unset($field_value['settings']['default_format']);
unset($field_value['settings']['repeat_collapsed']);
Karen Stevenson
committed
}
}
/**
* Implements hook_content_migrate_instance_alter().
* Use this to tweak the conversion of instance or widget settings from the D6
* style to the D7 style for specific situations not handled by basic
* conversion, as when formatter or widget names or settings are changed.
Karen Stevenson
committed
*/
Karen Stevenson
committed
function date_content_migrate_instance_alter(&$instance_value, $field_value) {
switch ($instance_value['widget']['module']) {
Karen Stevenson
committed
case 'date':
Karen Stevenson
committed
// Some settings have been moved from field to instance.
$instance_value['widget']['settings']['repeat_collapsed'] = $field_value['settings']['repeat_collapsed'];
Karen Stevenson
committed
// Some settings were moved from widget settings to instance settings.
Karen Stevenson
committed
$instance_value['settings']['default_value'] = $instance_value['default_value'];
unset($instance_value['default_value']);
$instance_value['settings']['default_value_code'] = $instance_value['widget']['settings']['default_value_code'];
unset($instance_value['widget']['settings']['default_value_code']);
$instance_value['settings']['default_value2'] = $instance_value['widget']['settings']['default_value2'];
unset($instance_value['widget']['settings']['default_value2']);
$instance_value['settings']['default_value_code2'] = $instance_value['widget']['settings']['default_value_code2'];
unset($instance_value['widget']['settings']['default_value_code2']);
// We need to retrieve formatter settings from the variables and store
// them in the instance.
foreach ($instance_value['display'] as $context => &$display) {
if ($display['type'] != 'format_interval') {
$old_settings = date_old_formatter_get_settings($instance_value['field_name'], $instance_value['bundle'], $context);
$display['settings'] = array_merge($display['settings'], $old_settings);
// If the formatter was the 'default', then use the old
// 'default_format' field property.
$format = ($display['type'] == 'default') ? $field_value['settings']['default_format'] : $display['type'];
$display['settings']['format_type'] = $format;
$display['type'] = 'date_default';
Karen Stevenson
committed
}
}
break;
}
}
/**
* Constructs an array of old formatter settings.
*/
Karen Stevenson
committed
function date_old_formatter_get_settings($field_name, $type_name, $context) {
$options = array();
$value = 'date:' . $type_name . ':' . $context . ':' . $field_name;
$options['show_repeat_rule'] = variable_get($value . '_show_repeat_rule', 'show');
$options['multiple_number'] = variable_get($value . '_multiple_number', '');
$options['multiple_from'] = variable_get($value . '_multiple_from', '');
$options['multiple_to'] = variable_get($value . '_multiple_to', '');
$options['fromto'] = variable_get($value . '_fromto', 'both');
Karen Stevenson
committed
return $options;
}