upgrade to OpenPublish 7.x-1.0-alpha9
[eupraxis:fsrn.git] / openpublish / profiles / openpublish / modules / contrib / date / date.module
1 <?php
2
3 /**
4  * @file
5  * Defines date/time field types.
6  */
7
8 module_load_include('theme', 'date', 'date');
9 module_load_include('inc', 'date', 'date.field');
10 module_load_include('inc', 'date', 'date_elements');
11
12 /**
13  * Helper function to figure out the bundle name for an entity.
14  */
15 function date_get_entity_bundle($entity_type, $entity) {
16   switch ($entity_type) {
17     case 'field_collection_item':
18       $bundle = $entity->field_name;
19       break;
20     default:
21       $bundle = field_extract_bundle($entity_type, $entity);
22       break;
23   }
24   // If there is no bundle name, field_info() uses the entity name as the bundle
25   // name in its arrays.
26   if (empty($bundle)) {
27     $bundle = $entity_type;
28   }
29   return $bundle;
30 }
31
32 /**
33  * Gets the default date format for the given field widget.
34  */
35 function date_default_format($type) {
36   // Example input formats must show all possible date parts, so add seconds.
37   $default_format = str_replace('i', 'i:s', variable_get('date_format_short', 'm/d/Y - H:i'));
38   return $default_format;
39 }
40
41 /**
42  * Wrapper function around each of the widget types for creating a date object.
43  */
44 function date_input_date($field, $instance, $element, $input) {
45   switch ($instance['widget']['type']) {
46     case 'date_text':
47       $function = 'date_text_input_date';
48       break;
49     case 'date_popup':
50       $function = 'date_popup_input_date';
51       break;
52     default:
53       $function = 'date_select_input_date';
54   }
55   return $function($element, $input);
56 }
57
58 /**
59  * Implements hook_theme().
60  */
61 function date_theme() {
62   $path = drupal_get_path('module', 'date');
63   module_load_include('theme', 'date', 'date');
64
65   $base = array(
66     'file' => 'date.theme',
67     'path' => "$path",
68   );
69   $themes = array(
70     'date_combo' => $base + array('render element' => 'element'),
71     'date_text_parts' => $base + array('render element' => 'element'),
72     'date' => $base + array('render element' => 'element'),
73     'date_display_single' => $base + array(
74       'variables' => array(
75         'date' => NULL,
76         'timezone' => NULL,
77         'dates' => NULL,
78         'attributes' => array(),
79         'rdf_mapping' => NULL,
80         'add_rdf' => NULL,
81       ),
82     ),
83     'date_display_range' => $base + array(
84       'variables' => array(
85         'date1' => NULL,
86         'date2' => NULL,
87         'timezone' => NULL,
88         'dates' => NULL,
89         // HTML attributes that will be applied to both the start and end dates
90         // (unless overridden).
91         'attributes' => array(),
92         // HTML attributes that will be applied to the start date only.
93         'attributes_start' => array(),
94         // HTML attributes that will be applied to the end date only.
95         'attributes_end' => array(),
96         'rdf_mapping' => NULL,
97         'add_rdf' => NULL,
98     )),
99     'date_display_combination' => $base + array(
100       'variables' => array(
101         'entity_type' => NULL,
102         'entity' => NULL,
103         'field' => NULL,
104         'instance' => NULL,
105         'langcode' => NULL,
106         'item' => NULL,
107         'delta' => NULL,
108         'display' => NULL,
109         'dates' => NULL,
110         'attributes' => array(),
111         'rdf_mapping' => NULL,
112         'add_rdf' => NULL,
113       ),
114     ),
115     'date_display_interval' => $base + array(
116       'variables' => array(
117         'entity_type' => NULL,
118         'entity' => NULL,
119         'field' => NULL,
120         'instance' => NULL,
121         'langcode' => NULL,
122         'item' => NULL,
123         'delta' => NULL,
124         'display' => NULL,
125         'dates' => NULL,
126         'attributes' => array(),
127         'rdf_mapping' => NULL,
128         'add_rdf' => NULL,
129        ),
130     ),
131   );
132
133   return $themes;
134 }
135
136 /**
137  * Implements hook_element_info().
138  *
139  * date_combo will create a 'start' and optional 'end' date, along with
140  * an optional 'timezone' column for date-specific timezones. Each
141  * 'start' and 'end' date will be constructed from date_select or date_text.
142  */
143 function date_element_info() {
144   $type = array();
145   $type['date_combo'] = array(
146     '#input' => TRUE,
147     '#delta' => 0,
148     '#columns' => array('value', 'value2', 'timezone', 'offset', 'offset2'),
149     '#process' => array('date_combo_element_process'),
150     '#element_validate' => array('date_combo_validate'),
151     '#theme_wrappers' => array('date_combo'),
152   );
153   if (module_exists('ctools')) {
154     $type['date_combo']['#pre_render'] = array('ctools_dependent_pre_render');
155   }
156   return $type;
157 }
158
159 /**
160  * Helper function for creating formatted date arrays from a formatter.
161  *
162  * Use the Date API to get an object representation of a date field.
163  *
164  * @param string $formatter
165  *   The date formatter.
166  * @param string $entity_type
167  *   The entity_type for the instance
168  * @param object $entity
169  *   The entity object.
170  * @param array $field
171  *   The field info array.
172  * @param array $instance
173  *   The field instance array.
174  * @param string $langcode
175  *   The language code used by this field.
176  * @param array $item
177  *   An entity field item, like $entity->myfield[0].
178  * @param array $display
179  *   The instance display settings.
180  *
181  * @return array
182  *   An array that holds the Start and End date objects.
183  *   Each date object looks like:
184  *     date [value] => array (
185  *       [db] => array (  // the value stored in the database
186  *         [object] => the datetime object
187  *         [datetime] => 2007-02-15 20:00:00
188  *       )
189  *       [local] => array (  // the local representation of that value
190  *         [object] => the datetime object
191  *         [datetime] => 2007-02-15 14:00:00
192  *         [timezone] => US/Central
193  *         [offset] => -21600
194  *       )
195  *     )
196  */
197 function date_formatter_process($formatter, $entity_type, $entity, $field, $instance, $langcode, $item, $display) {
198   $dates = array();
199   $timezone = date_default_timezone();
200   if (empty($timezone)) {
201     return $dates;
202   }
203
204   $granularity = date_granularity($field);
205   $settings = $display['settings'];
206   $field_name = $field['field_name'];
207   $format = date_formatter_format($formatter, $settings, $granularity, $langcode);
208   $timezone = isset($item['timezone']) ? $item['timezone'] : '';
209   $timezone = date_get_timezone($field['settings']['tz_handling'], $timezone);
210   $timezone_db = date_get_timezone_db($field['settings']['tz_handling']);
211   $db_format = date_type_format($field['type']);
212   $process = date_process_values($field);
213   foreach ($process as $processed) {
214     if (empty($item[$processed])) {
215       $dates[$processed] = NULL;
216     }
217     else {
218       // Create a date object with a GMT timezone from the database value.
219       $dates[$processed] = array();
220
221       // Check to see if this date was already created by date_field_load().
222       if (isset($item['db'][$processed])) {
223         $date = $item['db'][$processed];
224       }
225       else {
226         $date = new DateObject($item[$processed], $timezone_db, $db_format);
227         $date->limitGranularity($field['settings']['granularity']);
228       }
229
230       $dates[$processed]['db']['object'] = $date;
231       $dates[$processed]['db']['datetime'] = date_format($date, DATE_FORMAT_DATETIME);
232
233       date_timezone_set($date, timezone_open($timezone));
234       $dates[$processed]['local']['object'] = $date;
235       $dates[$processed]['local']['datetime'] = date_format($date, DATE_FORMAT_DATETIME);
236       $dates[$processed]['local']['timezone'] = $timezone;
237       $dates[$processed]['local']['offset'] = date_offset_get($date);
238
239       // Format the date, special casing the 'interval' format which doesn't
240       // need to be processed.
241       $dates[$processed]['formatted'] = '';
242       $dates[$processed]['formatted_iso'] = date_format_date($date, 'custom', 'c');
243       if (is_object($date)) {
244         if ($format == 'format_interval') {
245            $dates[$processed]['interval'] = date_format_interval($date);
246         }
247         elseif ($format == 'format_calendar_day') {
248            $dates[$processed]['calendar_day'] = date_format_calendar_day($date);
249         }
250         elseif ($format == 'U') {
251           $dates[$processed]['formatted'] = date_format_date($date, 'custom', $format);
252           $dates[$processed]['formatted_date'] = date_format_date($date, 'custom', $format);
253           $dates[$processed]['formatted_time'] = '';
254           $dates[$processed]['formatted_timezone'] = '';
255         }
256         elseif (!empty($format)) {
257           $dates[$processed]['formatted'] = date_format_date($date, 'custom', $format);
258           $dates[$processed]['formatted_date'] = date_format_date($date, 'custom', date_limit_format($format, array('year', 'month', 'day')));
259           $dates[$processed]['formatted_time'] = date_format_date($date, 'custom', date_limit_format($format, array('hour', 'minute', 'second')));
260           $dates[$processed]['formatted_timezone'] = date_format_date($date, 'custom', date_limit_format($format, array('timezone')));
261         }
262       }
263     }
264   }
265
266   if (empty($dates['value2'])) {
267     $dates['value2'] = $dates['value'];
268   }
269
270   // Allow other modules to alter the date values.
271   $context = array(
272     'field' => $field,
273     'instance' => $instance,
274     'format' => $format,
275     'entity_type' => $entity_type,
276     'entity' => $entity,
277     'langcode' => $langcode,
278     'item' => $item,
279     'display' => $display,
280   );
281   drupal_alter('date_formatter_dates', $dates, $context);
282
283   $dates['format'] = $format;
284   return $dates;
285 }
286
287 /**
288  * Retrieves the granularity for a field.
289  *
290  * $field['settings']['granularity'] will contain an array like
291  * ('hour' => 'hour', 'month' => 0) where the values turned on return their own
292  * names and the values turned off return a zero need to reconfigure this into
293  * simple array of the turned on values
294  *
295  * @param array $field
296  *   The field array.
297  */
298 function date_granularity($field) {
299   if (!is_array($field) || !is_array($field['settings']['granularity'])) {
300     $field['settings']['granularity'] = drupal_map_assoc(array('year', 'month', 'day'));
301   }
302   return array_values(array_filter($field['settings']['granularity']));
303 }
304
305 /**
306  * Helper function to create an array of the date values in a
307  * field that need to be processed.
308  */
309 function date_process_values($field) {
310   return $field['settings']['todate'] ? array('value', 'value2') : array('value');
311 }
312
313 /**
314  * Implements hook_form_FORM_ID_alter() for field_ui_field_edit_form().
315  */
316 function date_form_field_ui_field_edit_form_alter(&$form, &$form_state, $form_id) {
317   $field = $form['#field'];
318   $instance = $form['#instance'];
319
320   if (!in_array($field['type'], array('date', 'datetime', 'datestamp'))) {
321     return;
322   }
323
324   // Reorganize the instance settings and widget settings sections into a more
325   // intuitive combined fieldset.
326   $form['instance']['defaults'] = array(
327     '#type' => 'fieldset',
328     '#title' => t('More settings and values'),
329     '#collapsible' => TRUE,
330     '#collapsed' => TRUE,
331   );
332   $form['instance']['date_format'] = array(
333     '#type' => 'fieldset',
334     '#title' => t('Date entry'),
335     '#collapsible' => TRUE,
336     '#collapsed' => FALSE,
337   );
338   $form['instance']['default_values'] = array(
339     '#type' => 'fieldset',
340     '#title' => t('Default values'),
341     '#collapsible' => TRUE,
342     '#collapsed' => FALSE,
343   );
344   $form['instance']['years_back_and_forward'] = array(
345     '#type' => 'fieldset',
346     '#title' => t('Starting and ending year'),
347     '#collapsible' => TRUE,
348     '#collapsed' => FALSE,
349   );
350
351   $form['instance']['#pre_render'][] = 'date_field_ui_field_edit_form_pre_render';
352 }
353
354 /**
355  * Rearrange form elements into fieldsets for presentation only.
356  */
357 function date_field_ui_field_edit_form_pre_render($form) {
358   foreach ($form as $name => $element) {
359     if (is_array($element) && isset($element['#fieldset'])) {
360       $fieldset = $element['#fieldset'];
361       $form[$fieldset][$name] = $element;
362       unset($form[$name]);
363     }
364   }
365   foreach (array('date_format', 'default_values', 'years_back_and_forward') as $name) {
366     if (element_children($form[$name])) {
367       // Force the items in the fieldset to be resorted now that the instance
368       // and widget settings are combined.
369       $form[$name]['#sorted'] = FALSE;
370       $form['defaults'][$name] = $form[$name];
371     }
372     unset($form[$name]);
373   }
374   return $form;
375 }
376
377 /**
378  * Implements hook_field_widget_error().
379  */
380 function date_field_widget_error($element, $error, $form, &$form_state) {
381   form_error($element[$error['error']], $error['message']);
382 }
383
384 /**
385  * Retrieve a date format string from formatter settings.
386  */
387 function date_formatter_format($formatter, $settings, $granularity = array(), $langcode = NULL) {
388   $format_type = !empty($settings['format_type']) ? $settings['format_type'] : 'format_interval';
389
390   switch ($formatter) {
391     case 'format_interval':
392       return 'format_interval';
393       break;
394     case 'date_plain':
395       return 'date_plain';
396       break;
397     default:
398       $format = date_format_type_format($format_type, $langcode);
399       break;
400   }
401
402   // A selected format might include timezone information.
403   array_push($granularity, 'timezone');
404   return date_limit_format($format, $granularity);
405 }
406
407 /**
408  * Helper function to get the right format for a format type.
409  * Checks for locale-based format first.
410  */
411 function date_format_type_format($format_type, $langcode = NULL) {
412   $static = &drupal_static(__FUNCTION__);
413   if (!isset($static[$langcode][$format_type])) {
414     $format = system_date_format_locale($langcode, $format_type);
415
416     // If locale enabled and $format_type inexistent in {date_format_locale}
417     // we receive (due to inconsistency of core api) an array of all (other)
418     // formats available for $langcode in locale table.
419     // However there's no guarantee that the key $format_type exists.
420     // See http://drupal.org/node/1302358.
421     if (!is_string($format)) {
422       // If the configuration page at admin/config/regional/date-time was
423       // never saved, the default core date format variables
424       // ('date_format_short', 'date_format_medium', and 'date_format_long')
425       // will not be stored in the database, so we have to define their
426       // expected defaults here.
427       switch ($format_type) {
428         case 'short':
429           $default = 'm/d/Y - H:i';
430           break;
431         case 'long':
432           $default = 'l, F j, Y - H:i';
433           break;
434         // If it's not one of the core date types and isn't stored in the
435         // database, we'll fall back on using the same default format as the
436         // 'medium' type.
437         case 'medium':
438         default:
439           // @todo: If a non-core module provides a date type and does not
440           //   variable_set() a default for it, the default assumed here may
441           //   not be correct (since the default format used by 'medium' may
442           //   not even be one of the allowed formats for the date type in
443           //   question). To fix this properly, we should really call
444           //   system_get_date_formats($format_type) and take the first
445           //   format from that list as the default. However, this function
446           //   is called often (on many different page requests), so calling
447           //   system_get_date_formats() from here would be a performance hit
448           //   since that function writes several records to the database
449           //   during each page request that calls it.
450           $default = 'D, m/d/Y - H:i';
451           break;
452       }
453       $format = variable_get('date_format_' . $format_type, $default);
454     }
455     $static[$langcode][$format_type] = $format;
456   }
457   return $static[$langcode][$format_type];
458 }
459
460 /**
461  * Helper function to adapt entity date fields to formatter settings.
462  */
463 function date_prepare_entity($formatter, $entity_type, $entity, $field, $instance, $langcode, $item, $display) {
464   // If there are options to limit multiple values,
465   // alter the entity values to match.
466   $field_name = $field['field_name'];
467   $options = $display['settings'];
468   $max_count = $options['multiple_number'];
469
470   // If no results should be shown, empty the values and return.
471   if (is_numeric($max_count) && $max_count == 0) {
472     $entity->{$field_name} = array();
473     return $entity;
474   }
475
476   // Otherwise removed values that should not be displayed.
477   if (!empty($options['multiple_from']) || !empty($options['multiple_to']) || !empty($max_count)) {
478     $format = date_type_format($field['type']);
479     include_once drupal_get_path('module', 'date_api') . '/date_api_sql.inc';
480     $date_handler = new date_sql_handler($field);
481     $arg0 = !empty($options['multiple_from']) ? $date_handler->arg_replace($options['multiple_from']) : variable_get('date_min_year', 100) . '-01-01T00:00:00';
482     $arg1 = !empty($options['multiple_to']) ? $date_handler->arg_replace($options['multiple_to']) : variable_get('date_max_year', 4000) . '-12-31T23:59:59';
483     if (!empty($arg0) && !empty($arg1)) {
484       $arg = $arg0 . '--' . $arg1;
485     }
486     elseif (!empty($arg0)) {
487       $arg = $arg0;
488     }
489     elseif (!empty($arg1)) {
490       $arg = $arg1;
491     }
492     if (!empty($arg)) {
493       $range = $date_handler->arg_range($arg);
494       $start = date_format($range[0], $format);
495       $end = date_format($range[1], $format);
496       // Empty out values we don't want to see.
497       $count = 0;
498       foreach ($entity->{$field_name}[$langcode] as $delta => $value) {
499         if (!empty($entity->date_repeat_show_all)) {
500           break;
501         }
502         elseif ((!empty($max_count) && is_numeric($max_count) && $count >= $max_count) ||
503           (!empty($value['value'])  && $value['value'] < $start) ||
504           (!empty($value['value2']) && $value['value2'] > $end)) {
505             unset($entity->{$field_name}[$langcode][$delta]);
506         }
507         else {
508           $count++;
509         }
510       }
511     }
512   }
513
514   return $entity;
515 }
516
517 /**
518  * Callback to alter the property info of date fields.
519  *
520  * @see date_field_info()
521  */
522 function date_entity_metadata_property_info_alter(&$info, $entity_type, $field, $instance, $field_type) {
523   $name = $field['field_name'];
524   $property = &$info[$entity_type]['bundles'][$instance['bundle']]['properties'][$name];
525
526   if ($field['type'] != 'datestamp' || $field['settings']['timezone_db'] != 'UTC') {
527     // Add a getter callback to convert the date into the right format.
528     $property['getter callback'] = 'date_entity_metadata_field_getter';
529     $property['setter callback'] = 'date_entity_metadata_field_setter';
530     unset($property['query callback']);
531   }
532   if (!empty($field['settings']['todate'])) {
533     // Define a simple data structure containing both dates.
534     $property['type'] = ($field['cardinality'] != 1) ? 'list<struct>' : 'struct';
535     $property['getter callback'] = 'entity_metadata_field_verbatim_get';
536     $property['setter callback'] = 'entity_metadata_field_verbatim_set';
537     $property['property info'] = array(
538       'value' => array(
539         'type' => 'date',
540         'label' => t('Start date'),
541         'getter callback' => 'date_entity_metadata_struct_getter',
542         'setter callback' => 'date_entity_metadata_struct_setter',
543         // The getter and setter callbacks for 'value' and 'value2'
544         // will not provide the field name as $name, we'll add it to $info.
545         'field_name' => $field['field_name'],
546       ),
547       'value2' => array(
548         'type' => 'date',
549         'label' => t('End date'),
550         'getter callback' => 'date_entity_metadata_struct_getter',
551         'setter callback' => 'date_entity_metadata_struct_setter',
552         // The getter and setter callbacks for 'value' and 'value2'
553         // will not provide the field name as $name, we'll add it to $info.
554         'field_name' => $field['field_name'],
555       ),
556       'duration' => array(
557         'type' => 'duration',
558         'label' => t('Duration'),
559         'desription' => t('The duration of the time period given by the dates.'),
560         'getter callback' => 'date_entity_metadata_duration_getter',
561         // No setter callback for duration.
562         // The getter callback for duration will not provide the field name
563         // as $name, we'll add it to $info.
564         'field_name' => $field['field_name'],
565       ),
566     );
567     unset($property['query callback']);
568   }
569 }
570
571 /**
572  * Getter callback to return date values as datestamp in UTC from the field.
573  */
574 function date_entity_metadata_field_getter($entity, array $options, $name, $entity_type, &$context) {
575   $return = entity_metadata_field_verbatim_get($entity, $options, $name, $entity_type, $context);
576   $items = ($context['field']['cardinality'] == 1) ? array($return) : $return;
577   foreach ($items as $key => $item) {
578     $items[$key] = date_entity_metadata_struct_getter($item, $options, 'value', 'struct', $context);
579   }
580   return ($context['field']['cardinality'] == 1) ? $items[0] : $items;
581 }
582
583 /**
584  * Getter callback to return date values as datestamp in UTC.
585  */
586 function date_entity_metadata_struct_getter($item, array $options, $name, $type, $info) {
587   $value = trim($item[$name]);
588   if (empty($value)) {
589     return NULL;
590   }
591
592   $timezone_db = !empty($item['timezone_db']) ? $item['timezone_db'] : 'UTC';
593   $date = new DateObject($value, $timezone_db);
594   return !empty($date) ? date_format_date($date, 'custom', 'U') : NULL;
595 }
596
597 /**
598  * Getter callback to return the duration of the time period given by the dates.
599  */
600 function date_entity_metadata_duration_getter($item, array $options, $name, $type, $info) {
601   $value = date_entity_metadata_struct_getter($item, $options, 'value', 'struct', $info);
602   $value2 = date_entity_metadata_struct_getter($item, $options, 'value2', 'struct', $info);
603   if ($value && $value2) {
604     return $value2 - $value;
605   }
606 }
607
608 /**
609  * Callback for setting field property values.
610  *
611  * Based on entity_metadata_field_property_set(), the original property setter,
612  * adapted to transform non-timestamp date values to timestamps.
613  */
614 function date_entity_metadata_field_setter(&$entity, $name, $value, $langcode, $entity_type, $info) {
615   $field = field_info_field($name);
616   if (!isset($langcode)) {
617     // Try to figure out the default language used by the entity.
618     // @todo: Update once http://drupal.org/node/1260640 has been fixed.
619     $langcode = isset($entity->language) ? $entity->language : LANGUAGE_NONE;
620   }
621   $values = $field['cardinality'] == 1 ? array($value) : (array) $value;
622
623   $items = array();
624   foreach ($values as $delta => $value) {
625     // Make use of the struct setter to convert the date back to a timestamp.
626     $info['field_name'] = $name;
627     date_entity_metadata_struct_setter($items[$delta], 'value', $value, $langcode, 'struct', $info);
628   }
629   $entity->{$name}[$langcode] = $items;
630   // Empty the static field language cache, so the field system picks up any
631   // possible new languages.
632   drupal_static_reset('field_language');
633 }
634
635 /**
636  * Callback for setting an individual field value if a to-date may be there too.
637  * Based on entity_property_verbatim_set().
638  *
639  * The passed in unix timestamp (UTC) is converted to the right value and
640  * format dependent on the field.
641  *
642  * $name is either 'value' or 'value2'.
643  */
644 function date_entity_metadata_struct_setter(&$item, $name, $value, $langcode, $type, $info) {
645   if (!isset($value)) {
646     $item[$name] = NULL;
647   }
648   else {
649     $field = field_info_field($info['field_name']);
650     $format = date_type_format($field['type']);
651     $timezone_db = date_get_timezone_db($field['settings']['tz_handling']);
652
653     $date = new DateObject($value, 'UTC');
654     if ($timezone_db != 'UTC') {
655       date_timezone_set($date, timezone_open($timezone_db));
656     }
657     $item[$name] = $date->format($format);
658   }
659 }
660
661 /**
662  * Duplicate functionality of what is now date_all_day_field() in
663  * the Date All Day module. Copy left here to avoid breaking other
664  * modules that use this function.
665  *
666  * DEPRECATED!, will be removed at some time in the future.
667  */
668 function date_field_all_day($field, $instance, $date1, $date2 = NULL) {
669   if (empty($date1) || !is_object($date1)) {
670     return FALSE;
671   }
672   elseif (!date_has_time($field['settings']['granularity'])) {
673     return TRUE;
674   }
675   if (empty($date2)) {
676     $date2 = $date1;
677   }
678
679   $granularity = date_granularity_precision($field['settings']['granularity']);
680   $increment = isset($instance['widget']['settings']['increment']) ? $instance['widget']['settings']['increment'] : 1;
681   return date_is_all_day(date_format($date1, DATE_FORMAT_DATETIME), date_format($date2, DATE_FORMAT_DATETIME), $granularity, $increment);
682 }
683
684 /**
685  * Generates a Date API SQL handler for the given date field.
686  *
687  * The handler will be set up to make the correct timezone adjustments
688  * for the field settings.
689  *
690  * @param array $field
691  *   The $field array.
692  * @param string $compare_tz
693  *   The timezone used for comparison values in the SQL.
694  *
695  * DEPRECATED!, will be removed at some time in the future.
696  */
697 function date_field_get_sql_handler($field, $compare_tz = NULL) {
698   module_load_include('inc', 'date_api', 'date_api_sql');
699
700   $db_info = date_api_database_info($field);
701
702   // Create a DateAPI SQL handler class for this field type.
703   $handler = new date_sql_handler($field['type']);
704
705   // If this date field stores a timezone in the DB, tell the handler about it.
706   if ($field['settings']['tz_handling'] == 'date') {
707     $handler->db_timezone_field = $db_info['columns']['timezone']['column'];
708   }
709   else {
710     $handler->db_timezone = date_get_timezone_db($field['settings']['tz_handling']);
711   }
712
713   if (empty($compare_tz)) {
714     $compare_tz = date_get_timezone($field['settings']['tz_handling']);
715   }
716   $handler->local_timezone = $compare_tz;
717
718   // Now that the handler is properly initialized, force the DB
719   // to use UTC so no timezone conversions get added to things like
720   // NOW() or FROM_UNIXTIME().
721   $handler->set_db_timezone();
722
723   return $handler;
724 }
725
726 /**
727  * Implements hook_field_widget_properties_alter().
728  *
729  * Alters the widget properties of a field instance before it gets displayed.
730  * Used here to flag new entities so we can later tell if they need default values.
731  */
732 function date_field_widget_properties_alter(&$widget, $context) {
733   if (in_array($widget['type'], array('date_select', 'date_text', 'date_popup'))) {
734     $entity_type = $context['entity_type'];
735     $entity = $context['entity'];
736     $info = entity_get_info($entity_type);
737     $id = $info['entity keys']['id'];
738     $widget['is_new']= FALSE;
739     if (empty($entity->$id)) {
740       $widget['is_new'] = TRUE;
741     }
742   }
743 }