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