Projet

Général

Profil

Paste
Télécharger (14,9 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / date / date_all_day / date_all_day.module @ 599a39cd

1
<?php
2

    
3
/**
4
 * @file
5
 * Adds All Day functionality to the Date field.
6
 *
7
 * This module implements a number of hooks in the Date field and Date API
8
 * element processing and to add an All Day checkbox to date widgets, and also
9
 * adds an All Day theme and All Day information to the formatting.
10
 *
11
 * Keep in mind that the process hooks are fired from the top down, first
12
 * date_combo, then the date_select or date_popup.
13
 *
14
 * Validation fires from the bottom up, first date_select and date_popup, then
15
 * date_combo.
16
 */
17

    
18
/**
19
 * Implements hook_theme().
20
 */
21
function date_all_day_theme() {
22
  $themes = array(
23
    'date_all_day' => array(
24
      'variables' => array(
25
        'field' => NULL,
26
        'instance' => NULL,
27
        'which' => NULL,
28
        'date1' => NULL,
29
        'date2' => NULL,
30
        'format' => NULL,
31
        'entity_type' => NULL,
32
        'entity' => NULL,
33
        'view' => NULL,
34
      ),
35
    ),
36
    'date_all_day_label' => array(
37
      'variables' => array(),
38
    ),
39
  );
40

    
41
  return $themes;
42
}
43

    
44
/**
45
 * Implements hook_date_formatter_dates_alter().
46
 */
47
function date_all_day_date_formatter_dates_alter(&$dates, $context) {
48
  // This allows us to alter the $dates array created by date_formatter_process.
49
  $field = $context['field'];
50
  $instance = $context['instance'];
51
  $format = $context['format'];
52
  $entity_type = $context['entity_type'];
53
  $entity = $context['entity'];
54
  $date1 = $dates['value']['local']['object'];
55
  $date2 = $dates['value2']['local']['object'];
56
  $is_all_day = date_all_day_field($field, $instance, $date1, $date2);
57

    
58
  $all_day1 = '';
59
  $all_day2 = '';
60
  if ($format != 'format_interval' && $is_all_day) {
61
    $all_day1 = theme('date_all_day', array(
62
      'field' => $field,
63
      'instance' => $instance,
64
      'which' => 'date1',
65
      'date1' => $date1,
66
      'date2' => $date2,
67
      'format' => $format,
68
      'entity_type' => $entity_type,
69
      'entity' => $entity,
70
    ));
71
    $all_day2 = theme('date_all_day', array(
72
      'field' => $field,
73
      'instance' => $instance,
74
      'which' => 'date2',
75
      'date1' => $date1,
76
      'date2' => $date2,
77
      'format' => $format,
78
      'entity_type' => $entity_type,
79
      'entity' => $entity,
80
    ));
81
    $dates['value']['formatted_time'] = theme('date_all_day_label');
82
    $dates['value2']['formatted_time'] = theme('date_all_day_label');
83
    $dates['value']['formatted'] = $all_day1;
84
    $dates['value2']['formatted'] = $all_day2;
85
  }
86
}
87

    
88
/**
89
 * Adjust start/end date format to account for 'all day' .
90
 *
91
 * @param array $field
92
 *   The field definition for this date field.
93
 * @param string $which
94
 *   Which value to return, 'date1' or 'date2'.
95
 * @param object $date1
96
 *   A date/time object for the 'start' date.
97
 * @param object $date2
98
 *   A date/time object for the 'end' date.
99
 * @param string $format
100
 *   A date/time format.
101
 * @param object $entity
102
 *   The node this date comes from (may be incomplete, always contains nid).
103
 * @param object $view
104
 *   The view this node comes from, if applicable.
105
 *
106
 * @return string|null
107
 *   Formatted date.
108
 */
109
function theme_date_all_day($vars) {
110
  $field = $vars['field'];
111
  $instance = $vars['instance'];
112
  $which = $vars['which'];
113
  $date1 = $vars['date1'];
114
  $date2 = $vars['date2'];
115
  $format = $vars['format'];
116
  $entity = $vars['entity'];
117
  $view = !empty($vars['view']) ? $vars['view'] : NULL;
118

    
119
  if (empty($date1) || !is_object($date1) || $format == 'format_interval') {
120
    return;
121
  }
122
  if (empty($date2)) {
123
    $date2 = $date1;
124
  }
125

    
126
  $suffix = '';
127
  if (!date_has_time($field['settings']['granularity'])) {
128
    $format = date_limit_format($format, array('year', 'month', 'day'));
129
  }
130
  else {
131
    $format_granularity = date_format_order($format);
132
    $format_has_time = FALSE;
133
    if (in_array('hour', $format_granularity)) {
134
      $format_has_time = TRUE;
135
    }
136
    $all_day = date_all_day_field($field, $instance, $date1, $date2);
137
    if ($all_day && $format_has_time) {
138
      $format = date_limit_format($format, array('year', 'month', 'day'));
139
      $suffix = ' ' . theme('date_all_day_label');
140
    }
141
  }
142

    
143
  return trim(date_format_date($$which, 'custom', $format) . $suffix);
144
}
145

    
146
/**
147
 * Theme the way an 'all day' label will look.
148
 */
149
function theme_date_all_day_label() {
150
  return t('(All day)', array(), array('context' => 'datetime'));
151
}
152

    
153
/**
154
 * Determine if a Start/End date combination qualify as 'All day'.
155
 *
156
 * @param array $field
157
 *   The field definition for this date field.
158
 * @param array $instance
159
 *   The field instance for this date field.
160
 * @param object $date1
161
 *   A date/time object for the 'Start' date.
162
 * @param object $date2
163
 *   A date/time object for the 'End' date.
164
 *
165
 * @return bool
166
 *   TRUE or FALSE.
167
 */
168
function date_all_day_field(array $field, array $instance, $date1, $date2 = NULL) {
169
  if (empty($date1) || !is_object($date1)) {
170
    return FALSE;
171
  }
172
  elseif (!date_has_time($field['settings']['granularity'])) {
173
    return FALSE;
174
  }
175
  // The master setting for the 'all day' functionality.
176
  elseif (empty($instance['widget']['settings']['display_all_day'])) {
177
    return FALSE;
178
  }
179

    
180
  if (empty($date2)) {
181
    $date2 = $date1;
182
  }
183

    
184
  // Several scenarios result in the two date values being the same, e.g.
185
  // date_formatter_process().
186
  if ($date1 == $date2) {
187
    // Clone the date object so that changes made to the object won't affect
188
    // both variables.
189
    $date1 = clone $date2;
190

    
191
    // Set the time to midnight so that the two variables can be properly
192
    // compared later in date_is_all_day().
193
    $date1->setTime(0, 0, 0);
194
  }
195

    
196
  // Use central logic for determining the granularity.
197
  $granularity = date_granularity_precision($field['settings']['granularity']);
198

    
199
  // The increment is 1 by default, but it can be overridden.
200
  $increment = 1;
201
  if (isset($instance['widget']['settings']['increment'])) {
202
    $increment = $instance['widget']['settings']['increment'];
203
  }
204

    
205
  return date_is_all_day(date_format($date1, DATE_FORMAT_DATETIME), date_format($date2, DATE_FORMAT_DATETIME), $granularity, $increment);
206
}
207

    
208
/**
209
 * Implements hook_date_combo_process_alter().
210
 */
211
function date_all_day_date_combo_process_alter(&$element, &$form_state, $context) {
212
  // This hook lets us make changes to the date_combo element.
213
  $field = $context['field'];
214
  $instance = $context['instance'];
215

    
216
  // Add the all_day checkbox to the combo element.
217
  if (!empty($instance['widget']['settings']['display_all_day'])) {
218

    
219
    $parents = $element['#parents'];
220
    $first_parent = array_shift($parents);
221
    $all_day_id = $first_parent . '[' . implode('][', $parents) . '][all_day]';;
222
    foreach (array('value', 'value2') as $key) {
223
      if (array_key_exists($key, $element)) {
224
        $element[$key]['#date_all_day_id'] = $all_day_id;
225
      }
226
    }
227

    
228
    $from = $element['#default_value']['value'];
229
    $to = !empty($element['#default_value']['value2']) ? $element['#default_value']['value2'] : $element['#default_value']['value'];
230
    $granularity = date_granularity_precision($context['field']['settings']['granularity']);
231
    $increment = isset($context['instance']['widget']['settings']['increment']) ? $context['instance']['widget']['settings']['increment'] : 1;
232
    $date_is_all_day = date_is_all_day($from, $to, $granularity, $increment);
233
    $all_day = !empty($form_state['values']['all_day']) || $date_is_all_day;
234
    $element['all_day'] = array(
235
      '#title' => t('All Day'),
236
      '#type' => 'checkbox',
237
      '#default_value' => $all_day,
238
      '#weight' => -21,
239
      '#prefix' => '<div class="date-float">',
240
      '#suffix' => '</div>',
241
    );
242
  }
243

    
244
  // Set all_day to 0 for all other date fields.
245
  else {
246
    $form['all_day']['#type'] = 'hidden';
247
    $form['all_day']['#value'] = 0;
248
  }
249
}
250

    
251
/**
252
 * Implements hook_date_text_process_alter().
253
 */
254
function date_all_day_date_text_process_alter(&$element, &$form_state, $context) {
255
  // This hook lets us make changes to the date_select widget.
256
  $all_day_id = !empty($element['#date_all_day_id']) ? $element['#date_all_day_id'] : '';
257
  if ($all_day_id != '') {
258
    // All Day handling on text dates works only if the user leaves the time
259
    // out of the input value. There is no element to hide or show.
260
  }
261
}
262

    
263
/**
264
 * Implements hook_date_select_process_alter().
265
 */
266
function date_all_day_date_select_process_alter(&$element, &$form_state, $context) {
267
  // This hook lets us make changes to the date_select widget. Hide or show
268
  // this element in reaction to the all_day status for this element.
269
  $all_day_id = !empty($element['#date_all_day_id']) ? $element['#date_all_day_id'] : '';
270
  if ($all_day_id != '') {
271
    foreach (array('hour', 'minute', 'second', 'ampm') as $field) {
272
      if (array_key_exists($field, $element)) {
273
        $element[$field]['#states'] = array(
274
          'visible' => array(
275
            'input[name="' . $all_day_id . '"]' => array('checked' => FALSE),
276
          ),
277
        );
278
      }
279
    }
280
  }
281
}
282

    
283
/**
284
 * Implements hook_date_popup_process_alter().
285
 */
286
function date_all_day_date_popup_process_alter(&$element, &$form_state, $context) {
287
  // This hook lets us make changes to the date_popup element. Hide or show
288
  // this element in reaction to the all_day status for this element.
289
  $all_day_id = !empty($element['#date_all_day_id']) ? $element['#date_all_day_id'] : '';
290
  if ($all_day_id != '' && array_key_exists('time', $element)) {
291
    $element['time']['#states'] = array(
292
      'visible' => array(
293
        'input[name="' . $all_day_id . '"]' => array('checked' => FALSE),
294
      ),
295
    );
296
  }
297
}
298

    
299
/**
300
 * Implements hook_date_select_pre_validate_alter().
301
 */
302
function date_all_day_date_text_pre_validate_alter(&$element, &$form_state, &$input) {
303
  // This hook lets us alter the element or the form_state before the rest of
304
  // the date_select validation gets fired. Let Date module massage the format
305
  // for all day values so they will pass validation. The All day flag, if
306
  // used, actually exists on the parent element.
307
  date_all_day_value($element, $form_state);
308
}
309

    
310
/**
311
 * Implements hook_date_select_pre_validate_alter().
312
 */
313
function date_all_day_date_select_pre_validate_alter(&$element, &$form_state, &$input) {
314
  // This hook lets us alter the element or the form_state before the rest of
315
  // the date_select validation gets fired. Let Date module massage the format
316
  // for all day values so they will pass validation. The All day flag, if
317
  // used, actually exists on the parent element.
318
  date_all_day_value($element, $form_state);
319
}
320

    
321
/**
322
 * Implements hook_date_select_pre_validate_alter().
323
 */
324
function date_all_day_date_popup_pre_validate_alter(&$element, &$form_state, &$input) {
325
  // This hook lets us alter the element or the form_state before the rest of
326
  // the date_popup validation gets fired. Let Date module massage the format
327
  // for all day values so they will pass validation. The All day flag, if
328
  // used, actually exists on the parent element.
329
  date_all_day_value($element, $form_state);
330
}
331

    
332
/**
333
 * A helper function date_all_day_value().
334
 */
335
function date_all_day_value(&$element, $form_state) {
336
  // To check if the all day flag is set on the parent of an element, and
337
  // adjust the date_format accordingly so the missing time will not cause
338
  // validation errors.
339
  if (!empty($element['#date_all_day_id'])) {
340
    $parents = $element['#parents'];
341
    array_pop($parents);
342
    $parent_element = drupal_array_get_nested_value($form_state['values'], $parents);
343
    if (!empty($parent_element) && !empty($parent_element['all_day'])) {
344
      $element['#date_format'] = date_part_format('date', $element['#date_format']);
345
      return $parent_element['all_day'];
346
    }
347
  }
348
  return FALSE;
349
}
350

    
351
/**
352
 * Implements hook_date_combo_pre_validate_alter().
353
 */
354
function date_all_day_date_combo_pre_validate_alter(&$element, &$form_state, $context) {
355
  // This hook lets us alter the element or the form_state before the rest of
356
  // the date_combo validation gets fired.
357
  if (!empty($context['item']['all_day'])) {
358
    $field = $context['field'];
359

    
360
    // If we have an all day flag on this date and the time is empty,
361
    // change the format to match the input value
362
    // so we don't get validation errors.
363
    $element['#date_is_all_day'] = TRUE;
364
    $element['value']['#date_format'] = date_part_format('date', $element['value']['#date_format']);
365
    if (!empty($field['settings']['todate'])) {
366
      $element['value2']['#date_format'] = date_part_format('date', $element['value2']['#date_format']);
367
    }
368
  }
369
}
370

    
371
/**
372
 * Implements hook_date_combo_validate_date_start_alter().
373
 */
374
function date_all_day_date_combo_validate_date_start_alter(&$date, &$form_state, $context) {
375
  // This hook lets us alter the local date objects created by the date_combo
376
  // validation before they are converted back to the database timezone and
377
  // stored. If this is an 'All day' value, set the time to midnight.
378
  if (!empty($context['element']['#date_is_all_day'])) {
379
    $date->setTime(0, 0, 0);
380
  }
381
}
382

    
383
/**
384
 * Implements hook_date_combo_validate_date_end_alter().
385
 */
386
function date_all_day_date_combo_validate_date_end_alter(&$date, &$form_state, $context) {
387
  // This hook lets us alter the local date objects created by the date_combo
388
  // validation before they are converted back to the database timezone and
389
  // stored. If this is an 'All day' value, set the time as close to midnight as
390
  // possible.
391
  if (!empty($context['element']['#date_is_all_day'])) {
392
    $increment = isset($context['instance']['widget']['settings']['increment']) ? $context['instance']['widget']['settings']['increment'] : 1;
393
    // @todo Should this reduce by an additional 1 minute if the increment is
394
    // more than 1? For example, if the increment is 15 should the upper value
395
    // be 23:45:59 or 23:44:59?
396
    $date->setTime(23, 60 - $increment, 59);
397
  }
398
}
399

    
400
/**
401
 * Implements hook_field_widget_info_alter().
402
 */
403
function date_all_day_field_widget_info_alter(&$info) {
404
  // This Field API hook lets us add a new setting to the widgets.
405
  // Add a setting to a widget type.
406
  $info['date_select']['settings'] += array(
407
    'display_all_day' => 0,
408
  );
409
  $info['date_text']['settings'] += array(
410
    'display_all_day' => 0,
411
  );
412
  if (module_exists('date_popup')) {
413
    $info['date_popup']['settings'] += array(
414
      'display_all_day' => 0,
415
    );
416
  }
417
}
418

    
419
/**
420
 * Implements hook_date_field_widget_settings_form_alter().
421
 */
422
function date_all_day_date_field_widget_settings_form_alter(&$form, $context) {
423
  // This hook lets us alter the field settings form by adding a place to set
424
  // the value added above.
425
  $field = $context['field'];
426
  $instance = $context['instance'];
427

    
428
  $settings = $instance['widget']['settings'];
429

    
430
  $form['display_all_day'] = array(
431
    '#type' => 'checkbox',
432
    '#title' => t('Display all day checkbox'),
433
    '#default_value' => $settings['display_all_day'],
434
    '#description' => t("Determines whether to display the 'All Day' checkbox to the user."),
435
    '#weight' => 8,
436
    '#fieldset' => 'date_format',
437
  );
438

    
439
  // Hide the option to use the all day checkbox for dates with no time.
440
  if (!date_has_time($field['settings']['granularity'])) {
441
    $form['display_all_day']['#type'] = 'hidden';
442
    $form['display_all_day']['#value'] = 0;
443
  }
444
}