Révision 599a39cd
Ajouté par Assos Assos il y a environ 3 ans
drupal7/sites/all/modules/date/date_elements.inc | ||
---|---|---|
1 | 1 |
<?php |
2 |
|
|
2 | 3 |
/** |
3 | 4 |
* @file |
4 | 5 |
* Date forms and form themes and validation. |
... | ... | |
42 | 43 |
* the local timezone, are converted back to their UTC values and stored. |
43 | 44 |
*/ |
44 | 45 |
function date_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $base) { |
45 |
|
|
46 | 46 |
$element = $base; |
47 | 47 |
$field_name = $field['field_name']; |
48 | 48 |
$entity_type = $instance['entity_type']; |
49 | 49 |
|
50 | 50 |
// If this is a new entity, populate the field with the right default values. |
51 |
// This happens early so even fields later hidden with #access get those values.
|
|
52 |
// We should only add default values to new entities, to avoid over-writing
|
|
53 |
// a value that has already been set. This means we can't just check to see
|
|
54 |
// if $items is empty, because it might have been set that way on purpose.
|
|
55 |
// @see date_field_widget_properties_alter() where we flagged if this is a new entity.
|
|
56 |
|
|
57 |
// We check !isset($items[$delta]['value']) because entity translation may create
|
|
58 |
// a new translation entity for an existing entity and we don't want to clobber
|
|
59 |
// values that were already set in that case.
|
|
51 |
// This happens early so even fields later hidden with #access get those |
|
52 |
// values. We should only add default values to new entities, to avoid
|
|
53 |
// over-writing a value that has already been set. This means we can't just
|
|
54 |
// check to see if $items is empty, because it might have been set that way
|
|
55 |
// on purpose. In date_field_widget_properties_alter() this is flagged if
|
|
56 |
// this is a new entity. Check !isset($items[$delta]['value']) because entity |
|
57 |
// translation may create a new translation entity for an existing entity and
|
|
58 |
// we don't want to clobber values that were already set in that case.
|
|
59 |
// @see date_field_widget_properties_alter()
|
|
60 | 60 |
// @see http://drupal.org/node/1478848. |
61 |
|
|
62 | 61 |
$is_default = FALSE; |
63 |
if (!empty($instance['widget']['is_new']) && !isset($items[$delta]['value'])) { |
|
64 |
$items = date_default_value($field, $instance, $langcode); |
|
65 |
$is_default = TRUE; |
|
62 |
if (!isset($items[$delta]['value'])) { |
|
63 |
if (!empty($instance['widget']['is_new'])) { |
|
64 |
// New entity; use default values defined on instance. |
|
65 |
$items = date_default_value($field, $instance, $langcode); |
|
66 |
$is_default = TRUE; |
|
67 |
} |
|
68 |
else { |
|
69 |
// Date is empty; create array structure for value keys. |
|
70 |
$keys = date_process_values($field); |
|
71 |
$items[$delta] = array_fill_keys($keys, ''); |
|
72 |
} |
|
66 | 73 |
} |
67 | 74 |
|
68 |
// @TODO Repeating dates should probably be made into their own field type and completely separated out. |
|
69 |
// That will have to wait for a new branch since it may break other things, including other modules |
|
70 |
// that have an expectation of what the date field types are. |
|
71 |
|
|
72 |
// Since repeating dates cannot use the default Add more button, we have to handle our own behaviors here. |
|
73 |
// Return only the first multiple value for repeating dates, then clean up the 'Add more' bits in #after_build. |
|
74 |
// The repeating values will be re-generated when the repeat widget form is validated. |
|
75 |
// At this point we can't tell if this form element is going to be hidden by #access, and we're going to |
|
76 |
// lose all but the first value by doing this, so store the original values in case we need to replace them later. |
|
75 |
// @todo Repeating dates should probably be made into their own field type |
|
76 |
// and completely separated out. That will have to wait for a new branch |
|
77 |
// since it may break other things, including other modules that have an |
|
78 |
// expectation of what the date field types are. Since repeating dates cannot |
|
79 |
// use the default Add more button, we have to handle our own behaviors here. |
|
80 |
// Return only the first multiple value for repeating dates, then clean up |
|
81 |
// the 'Add more' bits in #after_build. The repeating values will be |
|
82 |
// re-generated when the repeat widget form is validated. At this point we |
|
83 |
// can't tell if this form element is going to be hidden by #access, and |
|
84 |
// we're going to lose all but the first value by doing this, so store the |
|
85 |
// original values in case we need to replace them later. |
|
77 | 86 |
if (!empty($field['settings']['repeat']) && module_exists('date_repeat_field')) { |
78 | 87 |
if ($delta == 0) { |
79 | 88 |
$form['#after_build'][] = 'date_repeat_after_build'; |
... | ... | |
101 | 110 |
'#type' => 'date_combo', |
102 | 111 |
'#theme_wrappers' => array('date_combo'), |
103 | 112 |
'#weight' => $delta, |
104 |
'#default_value' => isset($items[$delta]) ? $items[$delta] : '',
|
|
113 |
'#default_value' => isset($items[$delta]) ? $items[$delta] : array(),
|
|
105 | 114 |
'#date_timezone' => $timezone, |
106 | 115 |
'#element_validate' => array('date_combo_validate'), |
107 | 116 |
'#date_is_default' => $is_default, |
108 | 117 |
|
109 | 118 |
// Store the original values, for use with disabled and hidden fields. |
110 |
'#date_items' => isset($items[$delta]) ? $items[$delta] : '',
|
|
119 |
'#date_items' => isset($items[$delta]) ? $items[$delta] : array(),
|
|
111 | 120 |
); |
112 | 121 |
|
113 | 122 |
$element['#title'] = $instance['label']; |
... | ... | |
126 | 135 |
|
127 | 136 |
// Make changes if instance is set to be rendered as a regular field. |
128 | 137 |
if (!empty($instance['widget']['settings']['no_fieldset'])) { |
129 |
$element['#title'] = check_plain($instance['label']); |
|
130 |
$element['#theme_wrappers'] = ($field['cardinality'] == 1) ? array('date_form_element') : array(); |
|
138 |
$element['#title'] = check_plain($instance['label']);
|
|
139 |
$element['#theme_wrappers'] = ($field['cardinality'] == 1) ? array('date_form_element') : array();
|
|
131 | 140 |
} |
132 | 141 |
|
133 | 142 |
return $element; |
... | ... | |
136 | 145 |
/** |
137 | 146 |
* Create local date object. |
138 | 147 |
* |
139 |
* Create a date object set to local time from the field and |
|
140 |
* widget settings and item values. Default values for new entities
|
|
141 |
* are set by the default value callback, so don't need to be accounted for here.
|
|
148 |
* Create a date object set to local time from the field and widget settings and
|
|
149 |
* item values. Default values for new entities are set by the default value
|
|
150 |
* callback, so don't need to be accounted for here. |
|
142 | 151 |
*/ |
143 | 152 |
function date_local_date($item, $timezone, $field, $instance, $part = 'value') { |
144 |
|
|
145 | 153 |
$value = $item[$part]; |
146 | 154 |
|
147 | 155 |
// If the value is empty, don't try to create a date object because it will |
... | ... | |
150 | 158 |
return NULL; |
151 | 159 |
} |
152 | 160 |
|
153 |
// @TODO Figure out how to replace date_fuzzy_datetime() function.
|
|
161 |
// @todo Figure out how to replace date_fuzzy_datetime() function.
|
|
154 | 162 |
// Special case for ISO dates to create a valid date object for formatting. |
155 | 163 |
// Is this still needed? |
156 | 164 |
// @codingStandardsIgnoreStart |
... | ... | |
200 | 208 |
} |
201 | 209 |
|
202 | 210 |
/** |
203 |
* Helper function for the date default value callback to set either 'value' or 'value2' to its default value.
|
|
211 |
* Default value callback to set either 'value', 'value2' to its default value.
|
|
204 | 212 |
*/ |
205 | 213 |
function date_default_value_part($item, $field, $instance, $langcode, $part = 'value') { |
206 | 214 |
$timezone = date_get_timezone($field['settings']['tz_handling']); |
... | ... | |
225 | 233 |
return NULL; |
226 | 234 |
} |
227 | 235 |
else { |
228 |
// The date stored in 'value' has already been switched to the db timezone. |
|
236 |
// The date stored in 'value' has already been switched to the db |
|
237 |
// timezone. |
|
229 | 238 |
$date = new DateObject($item[0]['value'], $timezone_db, DATE_FORMAT_DATETIME); |
230 | 239 |
} |
231 | 240 |
} |
232 |
// Special case for 'now' when using dates with no timezone, |
|
233 |
// make sure 'now' isn't adjusted to UTC value of 'now' .
|
|
241 |
// Special case for 'now' when using dates with no timezone, make sure 'now'
|
|
242 |
// isn't adjusted to UTC value of 'now'.
|
|
234 | 243 |
elseif ($field['settings']['tz_handling'] == 'none') { |
235 | 244 |
$date = date_now(); |
236 | 245 |
} |
... | ... | |
266 | 275 |
$field = field_widget_field($element, $form_state); |
267 | 276 |
$instance = field_widget_instance($element, $form_state); |
268 | 277 |
|
269 |
// Figure out how many items are in the form, including new ones added by ajax. |
|
278 |
// Figure out how many items are in the form, including new ones added by |
|
279 |
// ajax. |
|
270 | 280 |
$field_state = field_form_get_state($element['#field_parents'], $field_name, $element['#language'], $form_state); |
271 | 281 |
$items_count = $field_state['items_count']; |
272 | 282 |
|
... | ... | |
280 | 290 |
$offset_field = 'offset'; |
281 | 291 |
$offset_field2 = 'offset2'; |
282 | 292 |
|
283 |
// Convert UTC dates to their local values in DATETIME format, |
|
284 |
// and adjust the default values as specified in the field settings. |
|
285 |
|
|
286 |
// It would seem to make sense to do this conversion when the data |
|
287 |
// is loaded instead of when the form is created, but the loaded |
|
288 |
// field data is cached and we can't cache dates that have been converted |
|
289 |
// to the timezone of an individual user, so we cache the UTC values |
|
290 |
// instead and do our conversion to local dates in the form and |
|
291 |
// in the formatters. |
|
293 |
// Convert UTC dates to their local values in DATETIME format, and adjust the |
|
294 |
// default values as specified in the field settings. It would seem to make |
|
295 |
// sense to do this conversion when the data is loaded instead of when the |
|
296 |
// form is created, but the loaded field data is cached and we can't cache |
|
297 |
// dates that have been converted to the timezone of an individual user, so |
|
298 |
// we cache the UTC values instead and do our conversion to local dates in |
|
299 |
// the form and in the formatters. |
|
292 | 300 |
$process = date_process_values($field, $instance); |
293 | 301 |
foreach ($process as $processed) { |
294 | 302 |
if (!isset($element['#default_value'][$processed])) { |
303 |
if (empty($element['#default_value']) || !is_array($element['#default_value'])) { |
|
304 |
$element['#default_value'] = array(); |
|
305 |
} |
|
295 | 306 |
$element['#default_value'][$processed] = ''; |
296 | 307 |
} |
297 | 308 |
$date = date_local_date($element['#default_value'], $element['#date_timezone'], $field, $instance, $processed); |
... | ... | |
299 | 310 |
} |
300 | 311 |
|
301 | 312 |
// Blank out the end date for optional end dates that match the start date, |
302 |
// except when this is a new node that has default values that should be honored. |
|
313 |
// except when this is a new node that has default values that should be |
|
314 |
// honored. |
|
303 | 315 |
if (!$date_is_default && $field['settings']['todate'] != 'required' |
304 |
&& is_array($element['#default_value']) |
|
305 |
&& !empty($element['#default_value'][$to_field]) |
|
306 |
&& $element['#default_value'][$to_field] == $element['#default_value'][$from_field]) { |
|
316 |
&& is_array($element['#default_value'])
|
|
317 |
&& !empty($element['#default_value'][$to_field])
|
|
318 |
&& $element['#default_value'][$to_field] == $element['#default_value'][$from_field]) {
|
|
307 | 319 |
unset($element['#default_value'][$to_field]); |
308 | 320 |
} |
309 | 321 |
|
... | ... | |
343 | 355 |
$element['#description'] = $element['value']['#instance']['description']; |
344 | 356 |
} |
345 | 357 |
|
346 |
// Give this element the right type, using a Date API |
|
347 |
// or a Date Popup element type.
|
|
358 |
// Give this element the right type, using a Date API or a Date Popup element
|
|
359 |
// type. |
|
348 | 360 |
$element[$from_field]['#attributes'] = array('class' => array('date-clear')); |
349 | 361 |
$element[$from_field]['#wrapper_attributes'] = array('class' => array()); |
350 | 362 |
$element[$from_field]['#wrapper_attributes']['class'][] = 'date-no-float'; |
... | ... | |
360 | 372 |
case 'date_popup': |
361 | 373 |
$element[$from_field]['#type'] = 'date_popup'; |
362 | 374 |
$element[$from_field]['#theme_wrappers'] = array('date_popup'); |
375 |
// Disable autocomplete in browsers. |
|
376 |
// @see https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion |
|
377 |
$element[$from_field]['#attributes']['autocomplete'] = 'off'; |
|
363 | 378 |
$element[$from_field]['#ajax'] = !empty($element['#ajax']) ? $element['#ajax'] : FALSE; |
364 | 379 |
break; |
365 | 380 |
|
... | ... | |
367 | 382 |
$element[$from_field]['#type'] = 'date_text'; |
368 | 383 |
$element[$from_field]['#theme_wrappers'] = array('date_text'); |
369 | 384 |
$element[$from_field]['#ajax'] = !empty($element['#ajax']) ? $element['#ajax'] : FALSE; |
370 |
break; |
|
371 | 385 |
} |
372 | 386 |
|
373 |
// If this field uses the 'End', add matching element |
|
374 |
// for the 'End' date, and adapt titles to make it clear which |
|
375 |
// is the 'Start' and which is the 'End' . |
|
376 |
|
|
387 |
// If this field uses the 'End', add matching element for the 'End' date, and |
|
388 |
// adapt titles to make it clear which is the 'Start' and which is the 'End' . |
|
377 | 389 |
if (!empty($field['settings']['todate'])) { |
378 | 390 |
$element[$to_field] = $element[$from_field]; |
379 | 391 |
$element[$from_field]['#title_display'] = 'none'; |
... | ... | |
423 | 435 |
} |
424 | 436 |
|
425 | 437 |
$context = array( |
426 |
'field' => $field,
|
|
427 |
'instance' => $instance,
|
|
428 |
'form' => $form,
|
|
438 |
'field' => $field, |
|
439 |
'instance' => $instance, |
|
440 |
'form' => $form, |
|
429 | 441 |
); |
430 | 442 |
drupal_alter('date_combo_process', $element, $form_state, $context); |
431 | 443 |
|
... | ... | |
438 | 450 |
function date_element_empty($element, &$form_state) { |
439 | 451 |
$item = array(); |
440 | 452 |
$item['value'] = NULL; |
441 |
$item['value2'] = NULL;
|
|
442 |
$item['timezone'] = NULL;
|
|
453 |
$item['value2'] = NULL; |
|
454 |
$item['timezone'] = NULL; |
|
443 | 455 |
$item['offset'] = NULL; |
444 | 456 |
$item['offset2'] = NULL; |
445 | 457 |
$item['rrule'] = NULL; |
... | ... | |
453 | 465 |
* Don't try this if there were errors before reaching this point. |
454 | 466 |
*/ |
455 | 467 |
function date_combo_validate($element, &$form_state) { |
456 |
|
|
457 |
// Disabled and hidden elements won't have any input and don't need validation, |
|
458 |
// we just need to re-save the original values, from before they were processed into |
|
459 |
// widget arrays and timezone-adjusted. |
|
468 |
// Disabled and hidden elements won't have any input and don't need |
|
469 |
// validation, we just need to re-save the original values, from before they |
|
470 |
// were processed into widget arrays and timezone-adjusted. |
|
460 | 471 |
if (date_hidden_element($element) || !empty($element['#disabled'])) { |
461 | 472 |
form_set_value($element, $element['#date_items'], $form_state); |
462 | 473 |
return; |
... | ... | |
504 | 515 |
$offset_field = 'offset'; |
505 | 516 |
$offset_field2 = 'offset2'; |
506 | 517 |
|
507 |
// Check for empty 'Start date', which could either be an empty |
|
508 |
// value or an array of empty values, depending on the widget.
|
|
518 |
// Check for empty 'Start date', which could either be an empty value or an
|
|
519 |
// array of empty values, depending on the widget. |
|
509 | 520 |
$empty = TRUE; |
510 | 521 |
if (!empty($item[$from_field])) { |
511 | 522 |
if (!is_array($item[$from_field])) { |
... | ... | |
567 | 578 |
|
568 | 579 |
// Neither the start date nor the end date should be empty at this point |
569 | 580 |
// unless they held values that couldn't be evaluated. |
570 |
|
|
571 | 581 |
if (!$instance['required'] && (!date_is_date($from_date) || !date_is_date($to_date))) { |
572 | 582 |
$item = date_element_empty($element, $form_state); |
573 | 583 |
$errors[] = t('The dates are invalid.'); |
... | ... | |
577 | 587 |
$errors[] = t('The End date must be greater than the Start date.'); |
578 | 588 |
} |
579 | 589 |
else { |
580 |
// Convert input dates back to their UTC values and re-format to ISO |
|
581 |
// or UNIX instead of the DATETIME format used in element processing.
|
|
590 |
// Convert input dates back to their UTC values and re-format to ISO or
|
|
591 |
// UNIX instead of the DATETIME format used in element processing. |
|
582 | 592 |
$item[$tz_field] = $timezone; |
583 | 593 |
|
584 | 594 |
// Update the context for changes in the $item, and allow other modules to |
... | ... | |
587 | 597 |
// We can only pass two additional values to drupal_alter, so $element |
588 | 598 |
// needs to be included in $context. |
589 | 599 |
$context['element'] = $element; |
600 |
|
|
601 |
// Trigger hook_date_combo_validate_date_start_alter(). |
|
590 | 602 |
drupal_alter('date_combo_validate_date_start', $from_date, $form_state, $context); |
603 |
|
|
604 |
// Trigger hook_date_combo_validate_date_end_alter(). |
|
591 | 605 |
drupal_alter('date_combo_validate_date_end', $to_date, $form_state, $context); |
592 | 606 |
|
593 | 607 |
$item[$offset_field] = date_offset_get($from_date); |
... | ... | |
604 | 618 |
$item['rrule'] = $form_values[$field['field_name']]['rrule']; |
605 | 619 |
} |
606 | 620 |
|
607 |
// If the db timezone is not the same as the display timezone |
|
608 |
// and we are using a date with time granularity, |
|
609 |
// test a roundtrip back to the original timezone to catch |
|
610 |
// invalid dates, like 2AM on the day that spring daylight savings |
|
611 |
// time begins in the US. |
|
621 |
// If the db timezone is not the same as the display timezone and we are |
|
622 |
// using a date with time granularity, test a roundtrip back to the |
|
623 |
// original timezone to catch invalid dates, like 2AM on the day that |
|
624 |
// spring daylight savings time begins in the US. |
|
612 | 625 |
$granularity = date_format_order($element[$from_field]['#date_format']); |
613 | 626 |
if ($timezone != $timezone_db && date_has_time($granularity)) { |
614 | 627 |
date_timezone_set($from_date, timezone_open($timezone)); |
... | ... | |
626 | 639 |
} |
627 | 640 |
} |
628 | 641 |
} |
629 |
// Don't show further errors if errors are already flagged |
|
630 |
// because otherwise we'll show errors on the nested elements
|
|
631 |
// more than once. |
|
642 |
|
|
643 |
// Don't show further errors if errors are already flagged because otherwise
|
|
644 |
// we'll show errors on the nested elements more than once.
|
|
632 | 645 |
if (!form_get_errors() && !empty($errors)) { |
633 | 646 |
if ($field['cardinality']) { |
634 | 647 |
form_error($element, t('There are errors in @field_name value #@delta:', array('@field_name' => $instance['label'], '@delta' => $delta + 1)) . theme('item_list', array('items' => $errors))); |
... | ... | |
652 | 665 |
return variable_get('date_format_short', 'm/d/Y - H:i'); |
653 | 666 |
} |
654 | 667 |
|
655 |
|
|
656 | 668 |
/** |
657 | 669 |
* Implements hook_date_select_pre_validate_alter(). |
658 | 670 |
*/ |
... | ... | |
678 | 690 |
* Helper function to clear out end date when not being used. |
679 | 691 |
*/ |
680 | 692 |
function date_empty_end_date(&$element, &$form_state, &$input) { |
681 |
// If this is the end date and the option to show an end date has not been selected, |
|
682 |
// empty the end date to surpress validation errors and stop further processing. |
|
693 |
// If this is the end date and the option to show an end date has not been |
|
694 |
// selected, empty the end date to surpress validation errors and stop |
|
695 |
// further processing. |
|
683 | 696 |
$parents = $element['#parents']; |
684 | 697 |
$parent = array_pop($parents); |
685 | 698 |
if ($parent == 'value2') { |
Formats disponibles : Unified diff
Weekly update of contrib modules