Projet

Général

Profil

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

root / drupal7 / sites / all / modules / date / date_views / date_views.module @ 7fe061e8

1 85ad3d82 Assos Assos
<?php
2
3 b720ea3e Assos Assos
/**
4
 * @file
5
 * Date Views module.
6
 */
7 db9ffd17 Assos Assos
8
/**
9
 * Implements hook_menu().
10
 */
11
function date_views_menu() {
12
  // Used to import files from a local filesystem into Drupal.
13
  $items['admin/config/regional/date-time/date-views'] = array(
14
    'title' => 'Date views',
15
    'description' => 'Configure settings for date views.',
16
    'page callback' => 'drupal_get_form',
17
    'page arguments' => array('date_views_settings'),
18 b720ea3e Assos Assos
    'access arguments' => array('administer site configuration'),
19 db9ffd17 Assos Assos
    'type' => MENU_LOCAL_TASK,
20
  );
21
22
  return $items;
23
}
24
25
/**
26
 * Form callback for date views settings.
27
 */
28
function date_views_settings($form, &$form_state) {
29
30
  $form['date_views_month_format_with_year'] = array(
31
    '#type' => 'textfield',
32
    '#title' => t('Date views month format with year'),
33
    '#size' => 10,
34
    '#default_value' => variable_get('date_views_month_format_with_year', 'F Y'),
35
    '#description' => t('Date views month format with year, default value : F Y'),
36
  );
37
38
  $form['date_views_month_format_without_year'] = array(
39
    '#type' => 'textfield',
40
    '#title' => t('Date views month format without year'),
41
    '#size' => 10,
42
    '#default_value' => variable_get('date_views_month_format_without_year', 'F'),
43
    '#description' => t('Date views month format without year, default value : F'),
44
  );
45
46
  $form['date_views_day_format_with_year'] = array(
47
    '#type' => 'textfield',
48
    '#title' => t('Date views day format with year'),
49
    '#size' => 10,
50
    '#default_value' => variable_get('date_views_day_format_with_year', 'l, F j, Y'),
51
    '#description' => t('Date views day format with year, default value : l, F j, Y'),
52
  );
53
54
  $form['date_views_day_format_without_year'] = array(
55
    '#type' => 'textfield',
56
    '#title' => t('Date views day format without year'),
57
    '#size' => 10,
58
    '#default_value' => variable_get('date_views_day_format_without_year', 'l, F j'),
59
    '#description' => t('Date views day format without year, default value : l, F j'),
60
  );
61
62
  $form['date_views_week_format_with_year'] = array(
63
    '#type' => 'textfield',
64
    '#title' => t('Date views week format with year'),
65
    '#size' => 10,
66
    '#default_value' => variable_get('date_views_week_format_with_year', 'F j, Y'),
67
    '#description' => t('Date views week format with year, default value : F j, Y'),
68
  );
69
70
  $form['date_views_week_format_without_year'] = array(
71
    '#type' => 'textfield',
72
    '#title' => t('Date views week format without year'),
73
    '#size' => 10,
74
    '#default_value' => variable_get('date_views_week_format_without_year', 'F j'),
75
    '#description' => t('Date views week format without year, default value : F j'),
76
  );
77
78
  return system_settings_form($form);
79
80
}
81
82 85ad3d82 Assos Assos
/**
83
 * Implements hook_views_api().
84
 *
85
 * This one is used as the base to reduce errors when updating.
86
 */
87
function date_views_theme() {
88
  $path = drupal_get_path('module', 'date_views');
89
  $base = array(
90
    'file' => 'theme.inc',
91
    'path' => "$path/theme",
92
  );
93
94 b720ea3e Assos Assos
  return array(
95
    'date_nav_title' => $base + array(
96
      'variables' => array(
97
        'granularity' => NULL,
98
        'view' => NULL,
99
        'link' => NULL,
100
        'format' => NULL,
101
      ),
102
    ),
103
    'date_views_filter_form' => $base + array(
104
      'template' => 'date-views-filter-form',
105
      'render element' => 'form',
106
    ),
107
    'date_calendar_day' => $base + array(
108
      'variables' => array(
109
        'date' => NULL,
110
      ),
111
    ),
112 85ad3d82 Assos Assos
    'date_views_pager' => $base + array(
113 b720ea3e Assos Assos
      'variables' => array(
114
        'plugin' => NULL,
115
        'input' => NULL,
116
      ),
117 85ad3d82 Assos Assos
      // Register a pattern so that it can work like all views templates.
118
      'pattern' => 'date_views_pager__',
119
      'template' => 'date-views-pager',
120
    ),
121
  );
122
}
123
124 b720ea3e Assos Assos
/**
125
 * Implements hook_views_api().
126
 */
127 85ad3d82 Assos Assos
function date_views_views_api() {
128
  return array(
129
    'api' => 3,
130
    'path' => drupal_get_path('module', 'date_views') . '/includes',
131
  );
132
}
133
134
/**
135
 * Wrapper function to make sure this function will always work.
136
 */
137
function date_views_views_fetch_fields($base, $type) {
138
  if (!module_exists('views')) {
139
    return array();
140
  }
141
  module_load_include('inc', 'views', 'includes/admin');
142
  return views_fetch_fields($base, $type);
143
}
144
145
/**
146 b720ea3e Assos Assos
 * Identify all potential date/timestamp fields and cache the data.
147 85ad3d82 Assos Assos
 */
148
function date_views_fields($base = 'node', $reset = FALSE) {
149
  static $fields = array();
150
  $empty = array('name' => array(), 'alias' => array());
151
  module_load_include('inc', 'date_views', 'includes/date_views_fields');
152
153
  if (empty($fields[$base]) || $reset) {
154
    $cid = 'date_views_fields_' . $base;
155
    if (!$reset && $cached = cache_get($cid, 'cache_views')) {
156
      $fields[$base] = $cached->data;
157
    }
158
    else {
159
      $fields[$base] = _date_views_fields($base);
160
    }
161
  }
162
  // Make sure that empty values will be arrays in he expected format.
163
  return !empty($fields) && !empty($fields[$base]) ? $fields[$base] : $empty;
164
}
165
166
/**
167
 * Implements hook_date_views_entities().
168 b720ea3e Assos Assos
 *
169
 * Map extra Views tables to the entity that holds its date fields, needed for Views tables other than the primary tables identified in entity_info().
170 85ad3d82 Assos Assos
 */
171
function date_views_date_views_extra_tables() {
172
  return array(
173
    'node_revision' => 'node',
174
  );
175
}
176
177
/**
178 b720ea3e Assos Assos
 * Helper function to map entity types to the Views base table they use, to make it easier to infer the entity type from a base table.
179
 *
180
 * Views has a new handler called views_handler_field_entity() that loads entities.
181 85ad3d82 Assos Assos
 *
182 b720ea3e Assos Assos
 * And you can use something like the following to get the entity type from a view, but not all our base tables contain the entity information we need, (i.e. revisions).
183
 *
184
 * So it won't work here and we resort to creating information from entity_get_info().
185 85ad3d82 Assos Assos
 *
186
 *   // A method to get the entity type for a base table.
187
 *   $table_data = views_fetch_data($base_table);
188
 *   if (!isset($table_data['table']['base']['entity type'])) {
189
 *     return FALSE;
190
 *   }
191
 *   $entity_type = $table_data['table']['base']['entity type'];
192
 */
193
function date_views_base_tables() {
194
  $base_tables = &drupal_static(__FILE__, array());
195
196
  if (empty($base_tables)) {
197
198
    // First we get the base tables we can learn about from entity_info.
199
    $entity_info = entity_get_info();
200
    foreach ($entity_info as $entity_type => $info) {
201
      if (!empty($info['base table'])) {
202
        $base_tables[$info['base table']] = $entity_type;
203
      }
204
      if (!empty($info['revision table'])) {
205
        $base_tables[$info['revision table']] = $entity_type;
206
      }
207
    }
208
209
    // Then we let other modules tell us about other entity tables that hold date fields.
210
    $base_tables += module_invoke_all('date_views_extra_tables');
211
  }
212
213
  return $base_tables;
214
}
215
216
/**
217
 * Implements hook_date_views_fields().
218
 *
219 b720ea3e Assos Assos
 * All modules that create custom fields that use the 'views_handler_field_date' handler can provide additional information here about the type of date they create so the date can be used by the Date API views date argument and date filter.
220 85ad3d82 Assos Assos
 */
221
function date_views_date_views_fields($field) {
222
  $values = array(
223
    // The type of date: DATE_UNIX, DATE_ISO, DATE_DATETIME.
224
    'sql_type' => DATE_UNIX,
225
    // Timezone handling options: 'none', 'site', 'date', 'utc' .
226
    'tz_handling' => 'site',
227
    // Needed only for dates that use 'date' tz_handling.
228
    'timezone_field' => '',
229
    // Needed only for dates that use 'date' tz_handling.
230
    'offset_field' => '',
231
    // Array of "table.field" values for related fields that should be
232
    // loaded automatically in the Views SQL.
233
    'related_fields' => array(),
234
    // Granularity of this date field's db data.
235
    'granularity' => array('year', 'month', 'day', 'hour', 'minute', 'second'),
236
  );
237
238
  switch ($field) {
239
    case 'users.created':
240
    case 'users.access':
241
    case 'users.login':
242
    case 'node.created':
243
    case 'node.changed':
244
    case 'node_revision.timestamp':
245
    case 'file_managed.timestamp':
246
    case 'comment.timestamp':
247
      return $values;
248
  }
249
}
250
251
/**
252
 * A version of date_real_url that formats links correctly for the new Date pager.
253
 */
254
function date_pager_url($view, $date_type = NULL, $date_arg = NULL, $force_view_url = FALSE, $absolute = TRUE) {
255
256
  // If someone adds a pager without a matching argument, there is not date information to work with.
257
  if (empty($view->date_info) || !isset($view->date_info->date_arg_pos)) {
258
    return '';
259
  }
260
261
  $args = $view->args;
262
  $pos = $view->date_info->date_arg_pos;
263
264
  // The View arguments array is indexed numerically but is not necessarily
265
  // in numerical order. Sort the arguments to ensure the correct order.
266
  ksort($args);
267
268
  // If there are empty arguments before the date argument,
269
  // pad them with the wildcard so the date argument will be in
270
  // the right position.
271
  if (count($args) < $pos) {
272
    foreach ($view->argument as $name => $argument) {
273
      if ($argument->position == $pos) {
274
        break;
275
      }
276
      $args[] = $argument->options['exception']['value'];
277
    }
278
  }
279
280
  if (!empty($date_type)) {
281
    switch ($date_type) {
282
      case 'year':
283
        $args[$pos] = date_pad($view->date_info->year, 4);
284
        break;
285 b720ea3e Assos Assos
286 85ad3d82 Assos Assos
      case 'week':
287
        $args[$pos] = date_pad($view->date_info->year, 4) . '-W' . date_pad($view->date_info->week);
288
        break;
289 b720ea3e Assos Assos
290 85ad3d82 Assos Assos
      case 'day':
291
        $args[$pos] = date_pad($view->date_info->year, 4) . '-' . date_pad($view->date_info->month) . '-' . date_pad($view->date_info->day);
292
        break;
293 b720ea3e Assos Assos
294 85ad3d82 Assos Assos
      default:
295
        $args[$pos] = date_pad($view->date_info->year, 4) . '-' . date_pad($view->date_info->month);
296
        break;
297
    }
298
  }
299
  elseif (!empty($date_arg)) {
300
    $args[$pos] = $date_arg;
301
  }
302
  else {
303
    $args = $view->args;
304
  }
305
  // Is this an embedded or a block view?
306
  // Return the pager query value.
307
  if (!$force_view_url &&
308
  (!empty($view->preview) || !empty($view->date_info->block_identifier))) {
309
310
    $url = $args[$pos];
311
    $key = date_block_identifier($view);
312
    if (!empty($key)) {
313
      return url($_GET['q'], array(
314
        'query' => date_views_querystring($view, array($key => $url)),
315
        'absolute' => $absolute));
316
    }
317
  }
318
319
  // Normal views may need querystrings appended to them
320
  // if they use exposed filters.
321
  return url($view->get_url($args), array(
322
    'query' => date_views_querystring($view),
323 b720ea3e Assos Assos
    'absolute' => $absolute,
324
    )
325
  );
326 85ad3d82 Assos Assos
}
327
328 b720ea3e Assos Assos
/**
329
 * Identifier of a date block.
330
 */
331 85ad3d82 Assos Assos
function date_block_identifier($view) {
332
  if (!empty($view->block_identifier)) {
333
    return $view->block_identifier;
334
  }
335
  return isset($view->date_info->block_identifier) ? $view->date_info->block_identifier : NULL;
336
}
337
338
/**
339
 * Implements hook_field_views_data_alter().
340
 *
341 b720ea3e Assos Assos
 * Create a Views field for each date column we care about to supplement the generic 'entity_id' and 'revision_id' fields that are automatically created.
342 85ad3d82 Assos Assos
 *
343 b720ea3e Assos Assos
 * Also use friendlier labels to distinguish the start date and end date in listings (for fields that use both).
344 85ad3d82 Assos Assos
 */
345
function date_views_field_views_data_alter(&$result, $field, $module) {
346
  if ($module == 'date') {
347
    $has_end_date = !empty($field['settings']['todate']);
348
    if ($has_end_date) {
349
      $labels = field_views_field_label($field['field_name']);
350
      $label = array_shift($labels);
351
    }
352
    foreach ($result as $table => $data) {
353
      $additional = array();
354
      $field_name = $field['field_name'];
355
      foreach ($data as $column => $value) {
356
357
        // The old 'entity_id' and 'revision_id' values got rewritten in Views.
358
        // The old values are still there with a 'moved to' key, so ignore them.
359
        if (array_key_exists('field', $value) && !array_key_exists('moved to', $value['field'])) {
360
          $result[$table][$column]['field']['is date'] = TRUE;
361
          // Not sure yet if we still need a custom field handler in D7 now that custom formatters are available.
362
          // Might still need it to handle grouping of multiple value dates.
363 b720ea3e Assos Assos
          // $result[$table][$column]['field']['handler'] = 'date_handler_field_date';
364
          // $result[$table][$column]['field']['add fields to query'] = TRUE;
365 85ad3d82 Assos Assos
        }
366
367
        // For filters, arguments, and sorts, determine if this column is for
368
        // the start date ('value') or the end date ('value2').
369
        $this_column = NULL;
370
        foreach (array_keys($field['columns']) as $candidate_column) {
371
          if ($column == $field['field_name'] . '_' . $candidate_column) {
372
            $this_column = $candidate_column;
373
            break;
374
          }
375
        }
376
377
        // Only alter the date fields, not timezone, rrule, offset, etc.
378
        if ($this_column != 'value' && $this_column != 'value2') {
379
          continue;
380
        }
381
382
        // We will replace the label with a friendlier name in the case of
383
        // arguments, filters, and sorts (but only if this field uses an end
384
        // date).
385
        $replace_label = FALSE;
386
        if (array_key_exists('argument', $value)) {
387
          $result[$table][$column]['argument']['handler'] = 'date_views_argument_handler_simple';
388
          $result[$table][$column]['argument']['empty field name'] = t('Undated');
389
          $result[$table][$column]['argument']['is date'] = TRUE;
390
          $replace_label = $has_end_date;
391
        }
392
        if (array_key_exists('filter', $value)) {
393
          $result[$table][$column]['filter']['handler'] = 'date_views_filter_handler_simple';
394
          $result[$table][$column]['filter']['empty field name'] = t('Undated');
395
          $result[$table][$column]['filter']['is date'] = TRUE;
396
          $replace_label = $has_end_date;
397
        }
398
        if (array_key_exists('sort', $value)) {
399
          $result[$table][$column]['sort']['is date'] = TRUE;
400
          $replace_label = $has_end_date;
401
        }
402
        if ($replace_label) {
403
          // Determine if this column is for the start date ('value') or the
404
          // end date ('value2').
405
          $this_column = NULL;
406
          foreach (array_keys($field['columns']) as $candidate_column) {
407
            if ($column == $field['field_name'] . '_' . $candidate_column) {
408
              $this_column = $candidate_column;
409
              break;
410
            }
411
          }
412
          // Insert the phrase "start date" or "end date" after the label, so
413
          // users can distinguish them in listings (compared to the default
414
          // behavior of field_views_field_default_views_data(), which only
415
          // uses the 'value2' column name to distinguish them).
416
          switch ($this_column) {
417
            case 'value':
418
              // Insert a deliberate double space before 'start date' in the
419
              // translatable string. This is a hack to get it to appear right
420
              // before 'end date' in the listing (i.e., in a non-alphabetical,
421
              // but more user friendly, order).
422 b720ea3e Assos Assos
              $result[$table][$column]['title'] = t('@label -  start date (!name)', array(
423
                '@label' => $label,
424
                '!name' => $field['field_name'],
425
              ));
426
              $result[$table][$column]['title short'] = t('@label -  start date', array(
427
                '@label' => $label,
428
              ));
429 85ad3d82 Assos Assos
              break;
430 b720ea3e Assos Assos
431 85ad3d82 Assos Assos
            case 'value2':
432 b720ea3e Assos Assos
              $result[$table][$column]['title'] = t('@label - end date (!name:!column)', array(
433
                '@label' => $label,
434
                '!name' => $field['field_name'],
435
                '!column' => $this_column,
436
              ));
437
              $result[$table][$column]['title short'] = t('@label - end date:!column', array(
438
                '@label' => $label,
439
                '!column' => $this_column,
440
              ));
441 85ad3d82 Assos Assos
              break;
442
          }
443
        }
444
      }
445
    }
446
  }
447
}
448
449
/**
450
 * Implements hook_form_FORM_ID_alter() for views_ui_edit_form().
451
 */
452
function date_views_form_views_ui_edit_form_alter(&$form, &$form_state, $form_id) {
453
  // This CSS is needed for the configuration form provided by the Date filter
454
  // (date_views_filter_handler_simple), but we have to add it here so that
455
  // it's already on the edit form the first time a Date filter is being added
456
  // to the View. See http://drupal.org/node/1239228#comment-4885288.
457
  $form['#attached']['css'][] = drupal_get_path('module', 'date_views') . '/css/date_views.css';
458
}
459
460
/**
461 b720ea3e Assos Assos
 * The instanceof function makes this work for any handler that was derived from 'views_handler_filter_date' or 'views_handler_argument_date', which includes core date fields like the node updated field.
462 85ad3d82 Assos Assos
 *
463 b720ea3e Assos Assos
 * The test for $handler->min_date tells us that this is an argument that not only is derived from the views date handler but also has been processed by the Date Views filter or argument code.
464
 */
465 85ad3d82 Assos Assos
function date_views_handler_is_date($handler, $type = 'argument') {
466
  switch ($type) {
467
    case 'filter':
468
      return $handler instanceof views_handler_filter_date && !empty($handler->min_date);
469 b720ea3e Assos Assos
470 85ad3d82 Assos Assos
    case 'argument':
471
      return $handler instanceof views_handler_argument_date && !empty($handler->min_date);
472
  }
473
  return FALSE;
474
}
475
476
/**
477
 * Validation hook for exposed filters that use the select widget.
478 b720ea3e Assos Assos
 *
479
 * This is to ensure the the user completes all parts of the date not just some parts. Only needed for the select widget.
480 85ad3d82 Assos Assos
 */
481
function date_views_select_validate(&$form, &$form_state) {
482
  // If there are no values just return.
483
  if (empty($form['value']) && empty($form['min'])) {
484
    return;
485
  }
486
  $granularity = (!empty($form['min']['#date_format'])) ? date_format_order($form['min']['#date_format']) : date_format_order($form['value']['#date_format']);
487
  $filled = array();
488
  $value = drupal_array_get_nested_value($form_state['input'], $form['#parents']);
489
  foreach ($granularity as $part) {
490 b720ea3e Assos Assos
    if (isset($value['value']) && is_numeric($value['value'][$part])) {
491 85ad3d82 Assos Assos
      $filled[] = $part;
492
    }
493
  }
494
  if (!empty($filled) && count($filled) != count($granularity)) {
495
    $unfilled = array_diff($granularity, $filled);
496
    foreach ($unfilled as $part) {
497
      switch ($part) {
498
        case 'year':
499
          form_error($form['value'][$part], t('Please choose a year.'), $form_state);
500
          break;
501 b720ea3e Assos Assos
502 85ad3d82 Assos Assos
        case 'month':
503
          form_error($form['value'][$part], t('Please choose a month.'), $form_state);
504
          break;
505 b720ea3e Assos Assos
506 85ad3d82 Assos Assos
        case 'day':
507
          form_error($form['value'][$part], t('Please choose a day.'), $form_state);
508
          break;
509 b720ea3e Assos Assos
510 85ad3d82 Assos Assos
        case 'hour':
511
          form_error($form['value'][$part], t('Please choose an hour.'), $form_state);
512
          break;
513 b720ea3e Assos Assos
514 85ad3d82 Assos Assos
        case 'minute':
515
          form_error($form['value'][$part], t('Please choose a minute.'), $form_state);
516
          break;
517 b720ea3e Assos Assos
518 85ad3d82 Assos Assos
        case 'second':
519
          form_error($form['value'][$part], t('Please choose a second.'), $form_state);
520
          break;
521
      }
522
    }
523
  }
524
}
525
526
/**
527
 * Implements hook_date_formatter_view_alter().
528
 *
529 b720ea3e Assos Assos
 * If we are displaying a date from a view, see if we have information about which multiple value to display. If so, set the date_id in the entity.
530 85ad3d82 Assos Assos
 */
531
function date_views_date_formatter_pre_view_alter(&$entity, &$variables) {
532
  // Some views have no row index.
533
  if (!empty($entity->view) && isset($entity->view->row_index)) {
534
    $field = $variables['field'];
535
    $date_id = 'date_id_' . $field['field_name'];
536
    $date_delta = 'date_delta_' . $field['field_name'];
537
    $date_item = $entity->view->result[$entity->view->row_index];
538
    if (!empty($date_item->$date_id)) {
539
      $entity->date_id = 'date.' . $date_item->$date_id . '.' . $field['field_name'] . '.' . $date_item->$date_delta . '.0';
540
    }
541
  }
542 b720ea3e Assos Assos
}