Projet

Général

Profil

Paste
Télécharger (26,6 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / date / date.module @ db9ffd17

1
<?php
2
/**
3
 * @file
4
 * Defines date/time field types.
5
 */
6
module_load_include('theme', 'date', 'date');
7
module_load_include('inc', 'date', 'date.field');
8
module_load_include('inc', 'date', 'date_elements');
9

    
10
/**
11
 * Helper function to figure out the bundle name for an entity.
12
 */
13
function date_get_entity_bundle($entity_type, $entity) {
14
  switch ($entity_type) {
15
    case 'field_collection_item':
16
      $bundle = $entity->field_name;
17
      break;
18
    default:
19
      $bundle = field_extract_bundle($entity_type, $entity);
20
      break;
21
  }
22
  // If there is no bundle name, field_info() uses the entity name as the bundle
23
  // name in its arrays.
24
  if (empty($bundle)) {
25
    $bundle = $entity_type;
26
  }
27
  return $bundle;
28
}
29

    
30
/**
31
 * Gets the default date format for the given field widget.
32
 */
33
function date_default_format($type) {
34
  // Example input formats must show all possible date parts, so add seconds.
35
  $default_format = str_replace('i', 'i:s', variable_get('date_format_short', 'm/d/Y - H:i'));
36
  return $default_format;
37
}
38

    
39
/**
40
 * Wrapper function around each of the widget types for creating a date object.
41
 */
42
function date_input_date($field, $instance, $element, $input) {
43
  switch ($instance['widget']['type']) {
44
    case 'date_text':
45
      $function = 'date_text_input_date';
46
      break;
47
    case 'date_popup':
48
      $function = 'date_popup_input_date';
49
      break;
50
    default:
51
      $function = 'date_select_input_date';
52
  }
53
  return $function($element, $input);
54
}
55

    
56
/**
57
 * Implements hook_theme().
58
 */
59
function date_theme() {
60
  $path = drupal_get_path('module', 'date');
61
  module_load_include('theme', 'date', 'date');
62

    
63
  $base = array(
64
    'file' => 'date.theme',
65
    'path' => "$path",
66
  );
67
  $themes = array(
68
    'date_combo' => $base + array('render element' => 'element'),
69
    'date_text_parts' => $base + array('render element' => 'element'),
70
    'date' => $base + array('render element' => 'element'),
71
    'date_display_single' => $base + array(
72
      'variables' => array(
73
        'date' => NULL,
74
        'timezone' => NULL,
75
        'dates' => NULL,
76
        'attributes' => array(),
77
        'rdf_mapping' => NULL,
78
        'add_rdf' => NULL,
79
        'microdata' => NULL,
80
        'add_microdata' => 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
        'microdata' => NULL,
99
        'add_microdata' => NULL,
100
    )),
101
    'date_display_combination' => $base + array(
102
      'variables' => array(
103
        'entity_type' => NULL,
104
        'entity' => NULL,
105
        'field' => NULL,
106
        'instance' => NULL,
107
        'langcode' => NULL,
108
        'item' => NULL,
109
        'delta' => NULL,
110
        'display' => NULL,
111
        'dates' => NULL,
112
        'attributes' => array(),
113
        'rdf_mapping' => NULL,
114
        'add_rdf' => NULL,
115
        'microdata' => NULL,
116
        'add_microdata' => NULL,
117
      ),
118
    ),
119
    'date_display_interval' => $base + array(
120
      'variables' => array(
121
        'entity_type' => NULL,
122
        'entity' => NULL,
123
        'field' => NULL,
124
        'instance' => NULL,
125
        'langcode' => NULL,
126
        'item' => NULL,
127
        'delta' => NULL,
128
        'display' => NULL,
129
        'dates' => NULL,
130
        'attributes' => array(),
131
        'rdf_mapping' => NULL,
132
        'add_rdf' => NULL,
133
       ),
134
    ),
135
  );
136

    
137
  return $themes;
138
}
139

    
140
/**
141
 * Implements hook_element_info().
142
 *
143
 * date_combo will create a 'start' and optional 'end' date, along with
144
 * an optional 'timezone' column for date-specific timezones. Each
145
 * 'start' and 'end' date will be constructed from date_select or date_text.
146
 */
147
function date_element_info() {
148
  $type = array();
149
  $type['date_combo'] = array(
150
    '#input' => TRUE,
151
    '#delta' => 0,
152
    '#columns' => array('value', 'value2', 'timezone', 'offset', 'offset2'),
153
    '#process' => array('date_combo_element_process'),
154
    '#element_validate' => array('date_combo_validate'),
155
    '#theme_wrappers' => array('date_combo'),
156
  );
157
  if (module_exists('ctools')) {
158
    $type['date_combo']['#pre_render'] = array('ctools_dependent_pre_render');
159
  }
160
  return $type;
161
}
162

    
163
/**
164
 * Helper function for creating formatted date arrays from a formatter.
165
 *
166
 * Use the Date API to get an object representation of a date field.
167
 *
168
 * @param string $formatter
169
 *   The date formatter.
170
 * @param string $entity_type
171
 *   The entity_type for the instance
172
 * @param object $entity
173
 *   The entity object.
174
 * @param array $field
175
 *   The field info array.
176
 * @param array $instance
177
 *   The field instance array.
178
 * @param string $langcode
179
 *   The language code used by this field.
180
 * @param array $item
181
 *   An entity field item, like $entity->myfield[0].
182
 * @param array $display
183
 *   The instance display settings.
184
 *
185
 * @return array
186
 *   An array that holds the Start and End date objects.
187
 *   Each date object looks like:
188
 *     date [value] => array (
189
 *       [db] => array (  // the value stored in the database
190
 *         [object] => the datetime object
191
 *         [datetime] => 2007-02-15 20:00:00
192
 *       )
193
 *       [local] => array (  // the local representation of that value
194
 *         [object] => the datetime object
195
 *         [datetime] => 2007-02-15 14:00:00
196
 *         [timezone] => US/Central
197
 *         [offset] => -21600
198
 *       )
199
 *     )
200
 */
201
function date_formatter_process($formatter, $entity_type, $entity, $field, $instance, $langcode, $item, $display) {
202
  $dates = array();
203
  $timezone = date_default_timezone();
204
  if (empty($timezone)) {
205
    return $dates;
206
  }
207

    
208
  $granularity = date_granularity($field);
209
  $settings = $display['settings'];
210
  $field_name = $field['field_name'];
211
  $format = date_formatter_format($formatter, $settings, $granularity, $langcode);
212
  $timezone = isset($item['timezone']) ? $item['timezone'] : '';
213
  $timezone = date_get_timezone($field['settings']['tz_handling'], $timezone);
214
  $timezone_db = date_get_timezone_db($field['settings']['tz_handling']);
215
  $db_format = date_type_format($field['type']);
216
  $process = date_process_values($field);
217
  foreach ($process as $processed) {
218
    if (empty($item[$processed])) {
219
      $dates[$processed] = NULL;
220
    }
221
    else {
222
      // Create a date object with a GMT timezone from the database value.
223
      $dates[$processed] = array();
224

    
225
      // Check to see if this date was already created by date_field_load().
226
      if (isset($item['db'][$processed])) {
227
        $date = $item['db'][$processed];
228
      }
229
      else {
230
        $date = new DateObject($item[$processed], $timezone_db, $db_format);
231
        $date->limitGranularity($field['settings']['granularity']);
232
      }
233

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

    
237
      date_timezone_set($date, timezone_open($timezone));
238
      $dates[$processed]['local']['object'] = $date;
239
      $dates[$processed]['local']['datetime'] = date_format($date, DATE_FORMAT_DATETIME);
240
      $dates[$processed]['local']['timezone'] = $timezone;
241
      $dates[$processed]['local']['offset'] = date_offset_get($date);
242

    
243
      // Format the date, special casing the 'interval' format which doesn't
244
      // need to be processed.
245
      $dates[$processed]['formatted'] = '';
246
      $dates[$processed]['formatted_iso'] = date_format_date($date, 'custom', 'c');
247
      if (is_object($date)) {
248
        if ($format == 'format_interval') {
249
           $dates[$processed]['interval'] = date_format_interval($date);
250
        }
251
        elseif ($format == 'format_calendar_day') {
252
           $dates[$processed]['calendar_day'] = date_format_calendar_day($date);
253
        }
254
        elseif ($format == 'U' || $format == 'r' || $format == 'c') {
255
          $dates[$processed]['formatted'] = date_format_date($date, 'custom', $format);
256
          $dates[$processed]['formatted_date'] = date_format_date($date, 'custom', $format);
257
          $dates[$processed]['formatted_time'] = '';
258
          $dates[$processed]['formatted_timezone'] = '';
259
        }
260
        elseif (!empty($format)) {
261
          $dates[$processed]['formatted'] = date_format_date($date, 'custom', $format);
262
          $dates[$processed]['formatted_date'] = date_format_date($date, 'custom', date_limit_format($format, array('year', 'month', 'day')));
263
          $dates[$processed]['formatted_time'] = date_format_date($date, 'custom', date_limit_format($format, array('hour', 'minute', 'second')));
264
          $dates[$processed]['formatted_timezone'] = date_format_date($date, 'custom', date_limit_format($format, array('timezone')));
265
        }
266
      }
267
    }
268
  }
269

    
270
  if (empty($dates['value2'])) {
271
    $dates['value2'] = $dates['value'];
272
  }
273

    
274
  // Allow other modules to alter the date values.
275
  $context = array(
276
    'field' => $field,
277
    'instance' => $instance,
278
    'format' => $format,
279
    'entity_type' => $entity_type,
280
    'entity' => $entity,
281
    'langcode' => $langcode,
282
    'item' => $item,
283
    'display' => $display,
284
  );
285
  drupal_alter('date_formatter_dates', $dates, $context);
286

    
287
  $dates['format'] = $format;
288
  return $dates;
289
}
290

    
291
/**
292
 * Retrieves the granularity for a field.
293
 *
294
 * $field['settings']['granularity'] will contain an array like
295
 * ('hour' => 'hour', 'month' => 0) where the values turned on return their own
296
 * names and the values turned off return a zero need to reconfigure this into
297
 * simple array of the turned on values
298
 *
299
 * @param array $field
300
 *   The field array.
301
 */
302
function date_granularity($field) {
303
  if (!is_array($field) || !is_array($field['settings']['granularity'])) {
304
    $field['settings']['granularity'] = drupal_map_assoc(array('year', 'month', 'day'));
305
  }
306
  return array_values(array_filter($field['settings']['granularity']));
307
}
308

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

    
317
/**
318
 * Implements hook_form_FORM_ID_alter() for field_ui_field_edit_form().
319
 */
320
function date_form_field_ui_field_edit_form_alter(&$form, &$form_state, $form_id) {
321
  $field = $form['#field'];
322
  $instance = $form['#instance'];
323

    
324
  if (!in_array($field['type'], array('date', 'datetime', 'datestamp'))) {
325
    return;
326
  }
327

    
328
  // Reorganize the instance settings and widget settings sections into a more
329
  // intuitive combined fieldset.
330
  $form['instance']['defaults'] = array(
331
    '#type' => 'fieldset',
332
    '#title' => t('More settings and values'),
333
    '#collapsible' => TRUE,
334
    '#collapsed' => TRUE,
335
  );
336
  $form['instance']['date_format'] = array(
337
    '#type' => 'fieldset',
338
    '#title' => t('Date entry'),
339
    '#collapsible' => TRUE,
340
    '#collapsed' => FALSE,
341
  );
342
  $form['instance']['default_values'] = array(
343
    '#type' => 'fieldset',
344
    '#title' => t('Default values'),
345
    '#collapsible' => TRUE,
346
    '#collapsed' => FALSE,
347
  );
348
  $form['instance']['years_back_and_forward'] = array(
349
    '#type' => 'fieldset',
350
    '#title' => t('Starting and ending year'),
351
    '#collapsible' => TRUE,
352
    '#collapsed' => FALSE,
353
  );
354

    
355
  $form['instance']['#pre_render'][] = 'date_field_ui_field_edit_form_pre_render';
356
}
357

    
358
/**
359
 * Rearrange form elements into fieldsets for presentation only.
360
 */
361
function date_field_ui_field_edit_form_pre_render($form) {
362
  foreach ($form as $name => $element) {
363
    if (is_array($element) && isset($element['#fieldset'])) {
364
      $fieldset = $element['#fieldset'];
365
      $form[$fieldset][$name] = $element;
366
      unset($form[$name]);
367
    }
368
  }
369
  foreach (array('date_format', 'default_values', 'years_back_and_forward') as $name) {
370
    if (element_children($form[$name])) {
371
      // Force the items in the fieldset to be resorted now that the instance
372
      // and widget settings are combined.
373
      $form[$name]['#sorted'] = FALSE;
374
      $form['defaults'][$name] = $form[$name];
375
    }
376
    unset($form[$name]);
377
  }
378
  return $form;
379
}
380

    
381
/**
382
 * Implements hook_field_widget_error().
383
 */
384
function date_field_widget_error($element, $error, $form, &$form_state) {
385
  form_error($element[$error['error']], $error['message']);
386
}
387

    
388
/**
389
 * Retrieve a date format string from formatter settings.
390
 */
391
function date_formatter_format($formatter, $settings, $granularity = array(), $langcode = NULL) {
392
  $format_type = !empty($settings['format_type']) ? $settings['format_type'] : 'format_interval';
393

    
394
  switch ($formatter) {
395
    case 'format_interval':
396
      return 'format_interval';
397
      break;
398
    case 'date_plain':
399
      return 'date_plain';
400
      break;
401
    default:
402
      $format = date_format_type_format($format_type, $langcode);
403
      break;
404
  }
405

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

    
411
/**
412
 * Helper function to get the right format for a format type.
413
 * Checks for locale-based format first.
414
 */
415
function date_format_type_format($format_type, $langcode = NULL) {
416
  $static = &drupal_static(__FUNCTION__);
417
  if (!isset($static[$langcode][$format_type])) {
418
    $format = system_date_format_locale($langcode, $format_type);
419

    
420
    // If locale enabled and $format_type inexistent in {date_format_locale}
421
    // we receive (due to inconsistency of core api) an array of all (other)
422
    // formats available for $langcode in locale table.
423
    // However there's no guarantee that the key $format_type exists.
424
    // See http://drupal.org/node/1302358.
425
    if (!is_string($format)) {
426
      // If the configuration page at admin/config/regional/date-time was
427
      // never saved, the default core date format variables
428
      // ('date_format_short', 'date_format_medium', and 'date_format_long')
429
      // will not be stored in the database, so we have to define their
430
      // expected defaults here.
431
      switch ($format_type) {
432
        case 'short':
433
          $default = 'm/d/Y - H:i';
434
          break;
435
        case 'long':
436
          $default = 'l, F j, Y - H:i';
437
          break;
438
        // If it's not one of the core date types and isn't stored in the
439
        // database, we'll fall back on using the same default format as the
440
        // 'medium' type.
441
        case 'medium':
442
        default:
443
          // @todo: If a non-core module provides a date type and does not
444
          //   variable_set() a default for it, the default assumed here may
445
          //   not be correct (since the default format used by 'medium' may
446
          //   not even be one of the allowed formats for the date type in
447
          //   question). To fix this properly, we should really call
448
          //   system_get_date_formats($format_type) and take the first
449
          //   format from that list as the default. However, this function
450
          //   is called often (on many different page requests), so calling
451
          //   system_get_date_formats() from here would be a performance hit
452
          //   since that function writes several records to the database
453
          //   during each page request that calls it.
454
          $default = 'D, m/d/Y - H:i';
455
          break;
456
      }
457
      $format = variable_get('date_format_' . $format_type, $default);
458
    }
459
    $static[$langcode][$format_type] = $format;
460
  }
461
  return $static[$langcode][$format_type];
462
}
463

    
464
/**
465
 * Helper function to adapt entity date fields to formatter settings.
466
 */
467
function date_prepare_entity($formatter, $entity_type, $entity, $field, $instance, $langcode, $item, $display) {
468
  // If there are options to limit multiple values,
469
  // alter the entity values to match.
470
  $field_name = $field['field_name'];
471
  $options = $display['settings'];
472
  $max_count = $options['multiple_number'];
473

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

    
480
  // Otherwise removed values that should not be displayed.
481
  if (!empty($options['multiple_from']) || !empty($options['multiple_to']) || !empty($max_count)) {
482
    $format = date_type_format($field['type']);
483
    include_once drupal_get_path('module', 'date_api') . '/date_api_sql.inc';
484
    $date_handler = new date_sql_handler($field);
485
    $arg0 = !empty($options['multiple_from']) ? $date_handler->arg_replace($options['multiple_from']) : variable_get('date_min_year', 100) . '-01-01T00:00:00';
486
    $arg1 = !empty($options['multiple_to']) ? $date_handler->arg_replace($options['multiple_to']) : variable_get('date_max_year', 4000) . '-12-31T23:59:59';
487
    if (!empty($arg0) && !empty($arg1)) {
488
      $arg = $arg0 . '--' . $arg1;
489
    }
490
    elseif (!empty($arg0)) {
491
      $arg = $arg0;
492
    }
493
    elseif (!empty($arg1)) {
494
      $arg = $arg1;
495
    }
496
    if (!empty($arg)) {
497
      $range = $date_handler->arg_range($arg);
498
      $start = date_format($range[0], $format);
499
      $end = date_format($range[1], $format);
500
      // Empty out values we don't want to see.
501
      $count = 0;
502
      foreach ($entity->{$field_name}[$langcode] as $delta => $value) {
503
        if (!empty($entity->date_repeat_show_all)) {
504
          break;
505
        }
506
        elseif ((!empty($max_count) && is_numeric($max_count) && $count >= $max_count) ||
507
          (!empty($value['value'])  && $value['value'] < $start) ||
508
          (!empty($value['value2']) && $value['value2'] > $end)) {
509
            unset($entity->{$field_name}[$langcode][$delta]);
510
        }
511
        else {
512
          $count++;
513
        }
514
      }
515
    }
516
  }
517

    
518
  return $entity;
519
}
520

    
521
/**
522
 * Callback to alter the property info of date fields.
523
 *
524
 * @see date_field_info()
525
 */
526
function date_entity_metadata_property_info_alter(&$info, $entity_type, $field, $instance, $field_type) {
527
  $name = $field['field_name'];
528
  $property = &$info[$entity_type]['bundles'][$instance['bundle']]['properties'][$name];
529

    
530
  if ($field['type'] != 'datestamp' || $field['settings']['timezone_db'] != 'UTC') {
531
    // Add a getter callback to convert the date into the right format.
532
    $property['getter callback'] = 'date_entity_metadata_field_getter';
533
    $property['setter callback'] = 'date_entity_metadata_field_setter';
534
    unset($property['query callback']);
535
  }
536
  if (!empty($field['settings']['todate'])) {
537
    // Define a simple data structure containing both dates.
538
    $property['type'] = ($field['cardinality'] != 1) ? 'list<struct>' : 'struct';
539
    $property['auto creation'] = 'date_entity_metadata_struct_create';
540
    $property['getter callback'] = 'entity_metadata_field_verbatim_get';
541
    $property['setter callback'] = 'entity_metadata_field_verbatim_set';
542
    $property['property info'] = array(
543
      'value' => array(
544
        'type' => 'date',
545
        'label' => t('Start date'),
546
        'getter callback' => 'date_entity_metadata_struct_getter',
547
        'setter callback' => 'date_entity_metadata_struct_setter',
548
        // The getter and setter callbacks for 'value' and 'value2'
549
        // will not provide the field name as $name, we'll add it to $info.
550
        'field_name' => $field['field_name'],
551
        // Alert Microdata module that this value can be exposed in microdata.
552
        'microdata' => TRUE,
553
      ),
554
      'value2' => array(
555
        'type' => 'date',
556
        'label' => t('End date'),
557
        'getter callback' => 'date_entity_metadata_struct_getter',
558
        'setter callback' => 'date_entity_metadata_struct_setter',
559
        // The getter and setter callbacks for 'value' and 'value2'
560
        // will not provide the field name as $name, we'll add it to $info.
561
        'field_name' => $field['field_name'],
562
        // Alert Microdata module that this value can be exposed in microdata.
563
        'microdata' => TRUE,
564
      ),
565
      'duration' => array(
566
        'type' => 'duration',
567
        'label' => t('Duration'),
568
        'desription' => t('The duration of the time period given by the dates.'),
569
        'getter callback' => 'date_entity_metadata_duration_getter',
570
        // No setter callback for duration.
571
        // The getter callback for duration will not provide the field name
572
        // as $name, we'll add it to $info.
573
        'field_name' => $field['field_name'],
574
      ),
575
    );
576
    unset($property['query callback']);
577
  }
578
  else {
579
    // If this doesn't have a todate, it is handled as a date rather than a
580
    // struct. Enable microdata on the field itself rather than the properties.
581
    $property['microdata'] = TRUE;
582
  }
583
}
584

    
585
/**
586
 * Getter callback to return date values as datestamp in UTC from the field.
587
 */
588
function date_entity_metadata_field_getter($entity, array $options, $name, $entity_type, &$context) {
589
  $return = entity_metadata_field_verbatim_get($entity, $options, $name, $entity_type, $context);
590
  $items = ($context['field']['cardinality'] == 1) ? array($return) : $return;
591
  foreach ($items as $key => $item) {
592
    $items[$key] = date_entity_metadata_struct_getter($item, $options, 'value', 'struct', $context);
593
  }
594
  return ($context['field']['cardinality'] == 1) ? $items[0] : $items;
595
}
596

    
597
/**
598
 * Getter callback to return date values as datestamp in UTC.
599
 */
600
function date_entity_metadata_struct_getter($item, array $options, $name, $type, $info) {
601
  $value = trim($item[$name]);
602
  if (empty($value)) {
603
    return NULL;
604
  }
605

    
606
  $timezone_db = !empty($item['timezone_db']) ? $item['timezone_db'] : 'UTC';
607
  $date = new DateObject($value, $timezone_db);
608
  return !empty($date) ? date_format_date($date, 'custom', 'U') : NULL;
609
}
610

    
611
/**
612
 * Getter callback to return the duration of the time period given by the dates.
613
 */
614
function date_entity_metadata_duration_getter($item, array $options, $name, $type, $info) {
615
  $value = date_entity_metadata_struct_getter($item, $options, 'value', 'struct', $info);
616
  $value2 = date_entity_metadata_struct_getter($item, $options, 'value2', 'struct', $info);
617
  if ($value && $value2) {
618
    return $value2 - $value;
619
  }
620
}
621

    
622
/**
623
 * Callback for setting field property values.
624
 *
625
 * Based on entity_metadata_field_property_set(), the original property setter,
626
 * adapted to transform non-timestamp date values to timestamps.
627
 */
628
function date_entity_metadata_field_setter(&$entity, $name, $value, $langcode, $entity_type, $info) {
629
  $field = field_info_field($name);
630
  if (!isset($langcode)) {
631
    // Try to figure out the default language used by the entity.
632
    // @todo: Update once http://drupal.org/node/1260640 has been fixed.
633
    $langcode = isset($entity->language) ? $entity->language : LANGUAGE_NONE;
634
  }
635
  $values = $field['cardinality'] == 1 ? array($value) : (array) $value;
636

    
637
  $items = array();
638
  foreach ($values as $delta => $value) {
639
    // Make use of the struct setter to convert the date back to a timestamp.
640
    $info['field_name'] = $name;
641
    date_entity_metadata_struct_setter($items[$delta], 'value', $value, $langcode, 'struct', $info);
642
  }
643
  $entity->{$name}[$langcode] = $items;
644
  // Empty the static field language cache, so the field system picks up any
645
  // possible new languages.
646
  drupal_static_reset('field_language');
647
}
648

    
649
/**
650
 * Auto creation callback for fields which contain two date values in one
651
 */
652
function date_entity_metadata_struct_create($name, $property_info) {
653
  return array(
654
    'date_type' => $property_info['field']['columns'][$name]['type'],
655
    'timezone_db' => $property_info['field']['settings']['timezone_db'],
656
  );
657
}
658

    
659
/**
660
 * Callback for setting an individual field value if a to-date may be there too.
661
 * Based on entity_property_verbatim_set().
662
 *
663
 * The passed in unix timestamp (UTC) is converted to the right value and
664
 * format dependent on the field.
665
 *
666
 * $name is either 'value' or 'value2'.
667
 */
668
function date_entity_metadata_struct_setter(&$item, $name, $value, $langcode, $type, $info) {
669
  if (!isset($value)) {
670
    $item[$name] = NULL;
671
  }
672
  else {
673
    $field = field_info_field($info['field_name']);
674
    $format = date_type_format($field['type']);
675
    $timezone_db = date_get_timezone_db($field['settings']['tz_handling']);
676

    
677
    $date = new DateObject($value, 'UTC');
678
    if ($timezone_db != 'UTC') {
679
      date_timezone_set($date, timezone_open($timezone_db));
680
    }
681
    $item[$name] = $date->format($format);
682
  }
683
}
684

    
685
/**
686
 * Duplicate functionality of what is now date_all_day_field() in
687
 * the Date All Day module. Copy left here to avoid breaking other
688
 * modules that use this function.
689
 *
690
 * DEPRECATED!, will be removed at some time in the future.
691
 */
692
function date_field_all_day($field, $instance, $date1, $date2 = NULL) {
693
  if (empty($date1) || !is_object($date1)) {
694
    return FALSE;
695
  }
696
  elseif (!date_has_time($field['settings']['granularity'])) {
697
    return TRUE;
698
  }
699
  if (empty($date2)) {
700
    $date2 = $date1;
701
  }
702

    
703
  $granularity = date_granularity_precision($field['settings']['granularity']);
704
  $increment = isset($instance['widget']['settings']['increment']) ? $instance['widget']['settings']['increment'] : 1;
705
  return date_is_all_day(date_format($date1, DATE_FORMAT_DATETIME), date_format($date2, DATE_FORMAT_DATETIME), $granularity, $increment);
706
}
707

    
708
/**
709
 * Generates a Date API SQL handler for the given date field.
710
 *
711
 * The handler will be set up to make the correct timezone adjustments
712
 * for the field settings.
713
 *
714
 * @param array $field
715
 *   The $field array.
716
 * @param string $compare_tz
717
 *   The timezone used for comparison values in the SQL.
718
 *
719
 * DEPRECATED!, will be removed at some time in the future.
720
 */
721
function date_field_get_sql_handler($field, $compare_tz = NULL) {
722
  module_load_include('inc', 'date_api', 'date_api_sql');
723

    
724
  $db_info = date_api_database_info($field);
725

    
726
  // Create a DateAPI SQL handler class for this field type.
727
  $handler = new date_sql_handler($field['type']);
728

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

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

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

    
747
  return $handler;
748
}
749

    
750
/**
751
 * Implements hook_field_widget_properties_alter().
752
 *
753
 * Alters the widget properties of a field instance before it gets displayed.
754
 * Used here to flag new entities so we can later tell if they need default values.
755
 */
756
function date_field_widget_properties_alter(&$widget, $context) {
757
  if (in_array($widget['type'], array('date_select', 'date_text', 'date_popup'))) {
758
    $entity_type = $context['entity_type'];
759
    $entity = $context['entity'];
760
    $info = entity_get_info($entity_type);
761
    $id = $info['entity keys']['id'];
762
    $widget['is_new']= FALSE;
763
    if (empty($entity->$id)) {
764
      $widget['is_new'] = TRUE;
765
    }
766
  }
767
}