Projet

Général

Profil

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

root / drupal7 / sites / all / modules / date / date_views / includes / date_views_argument_handler_simple.inc @ b720ea3e

1 85ad3d82 Assos Assos
<?php
2
/**
3
 * @file
4
 * Date API views argument handler.
5
 */
6
7
/**
8
 * Date API argument handler.
9
 */
10 b720ea3e Assos Assos
// @codingStandardsIgnoreStart
11 85ad3d82 Assos Assos
class date_views_argument_handler_simple extends views_handler_argument_date {
12
13
  /**
14 b720ea3e Assos Assos
   * Get granularity.
15
   *
16
   * Use it to create the formula and a format for the results.
17 85ad3d82 Assos Assos
   */
18
  function init(&$view, &$options) {
19
    parent::init($view, $options);
20
21
    // Add a date handler.
22
    module_load_include('inc', 'date_api', 'date_api_sql');
23
    $this->date_handler = new date_sql_handler(DATE_UNIX);
24
    if (!empty($this->definition['field_name'])) {
25
      $field = field_info_field($this->definition['field_name']);
26
      if (!empty($field) && !empty($field['type'])) {
27
        $this->date_handler->date_type = $field['type'];
28
        $this->original_table = $this->definition['table'];
29
      }
30
      $this->date_handler->db_timezone = date_get_timezone_db($field['settings']['tz_handling']);
31
      $this->date_handler->local_timezone = date_get_timezone($field['settings']['tz_handling']);
32
    }
33
    $this->date_handler->granularity = $this->options['granularity'];
34 b720ea3e Assos Assos
    // This value needs to be initialized so
35
    // it exists even if the query doesn't run.
36 85ad3d82 Assos Assos
    $this->date_handler->placeholders = array();
37
38
    $this->format = $this->date_handler->views_formats($this->date_handler->granularity, 'display');
39
    $this->sql_format = $this->date_handler->views_formats($this->date_handler->granularity, 'sql');
40 b720ea3e Assos Assos
    // $this->arg_format is the format the parent date
41
    // handler will use to create a default argument.
42 85ad3d82 Assos Assos
    $this->arg_format = $this->format();
43
44
    // Identify the base table for this field.
45
    // It will be used to call for the right query field options.
46
    $this->base_table = $this->table;
47
48
  }
49
50 b720ea3e Assos Assos
  /**
51
   * {@inheritdoc}
52
   */
53 85ad3d82 Assos Assos
  function format() {
54
    if (!empty($this->options['granularity'])) {
55
      return $this->date_handler->views_formats($this->options['granularity']);
56
    }
57
    else {
58
      return !empty($this->options[$this->option_name]) ? $this->options[$this->option_name] : 'Y-m';
59
    }
60
  }
61
62
  /**
63 b720ea3e Assos Assos
   * Set the empty argument value to the current date.
64
   *
65
   * Formatted appropriately for this argument.
66 85ad3d82 Assos Assos
   */
67
  function get_default_argument($raw = FALSE) {
68
    $is_default = FALSE;
69
70
    if (!$raw && $this->options['default_argument_type'] == 'date') {
71
      $granularity = $this->options['granularity'];
72
      if ($granularity == 'week') {
73
        $now = date_now();
74
        $week = date_week(date_format($now, 'Y-m-d'));
75 db9ffd17 Assos Assos
        $value = date_format($now, 'o') . '-W' . date_pad($week);
76 85ad3d82 Assos Assos
      }
77
      else {
78
        $value = date($this->arg_format, REQUEST_TIME);
79
      }
80
      drupal_alter('date_default_argument', $this, $value);
81
82
      return $value;
83
    }
84
85
    // Let the parent argument handle options like node created date.
86
    return parent::get_default_argument($raw);
87
  }
88
89
  /**
90
   * Default value for the date_fields option.
91
   */
92
  function option_definition() {
93
    $options = parent::option_definition();
94
    $options['year_range'] = array('default' => '-3:+3');
95
    $options['granularity'] = array('default' => 'month');
96 b720ea3e Assos Assos
    $options['granularity_reset'] = array('default' => FALSE);
97 85ad3d82 Assos Assos
    $options['default_argument_type']['default'] = 'date';
98
    $options['add_delta'] = array('default' => '');
99
    $options['use_fromto'] = array('default' => '');
100
    $options['title_format'] = array('default' => '');
101
    $options['title_format_custom'] = array('default' => '');
102
    return $options;
103
  }
104
105
  /**
106
   * Add a form element to select date_fields for this argument.
107
   */
108
  function options_form(&$form, &$form_state) {
109
    parent::options_form($form, $form_state);
110
111
    // Add an option to control the format of the summary.
112
    $options = array(
113
      '' => t('Default format'),
114
      'custom' => t('Custom format'),
115
    );
116
    $example_month = date_format_date(date_example_date(), 'custom', $this->date_handler->views_formats('month', 'display'));
117
    $example_day = date_format_date(date_example_date(), 'custom', $this->date_handler->views_formats('day', 'display'));
118
119
    $form['title_format'] = array(
120
      '#type' => 'select',
121
      '#title' => t('Date format options'),
122
      '#default_value' => $this->options['title_format'],
123
      '#options' => $options,
124
      '#description' => t('The date format used in titles and summary links for this argument. The default format is based on the granularity of the filter, i.e. month: @example_month, day: @example_day.', array('@example_month' => $example_month, '@example_day' => $example_day)),
125
      '#attributes' => array('class' => array('dependent-options')),
126
      '#states' => array(
127
        'visible' => array(
128 b720ea3e Assos Assos
          ':input[name="options[default_action]"]' => array(
129
            'value' => 'summary',
130
          ),
131 85ad3d82 Assos Assos
        ),
132
      ),
133
    );
134
135
    $form['title_format_custom'] = array(
136
      '#type' => 'textfield',
137
      '#title' => t('Custom summary date format'),
138
      '#default_value' => $this->options['title_format_custom'],
139
      '#description' => t("A custom format for the title and summary date format. Define a php date format string like 'm-d-Y H:i' (see <a href=\"@link\">http://php.net/date</a> for more details).", array('@link' => 'http://php.net/date')),
140
      '#attributes' => array('class' => array('dependent-options')),
141
      '#states' => array(
142
        'visible' => array(
143 b720ea3e Assos Assos
          ':input[name="options[title_format]"]' => array(
144
            'value' => 'custom',
145
          ),
146 85ad3d82 Assos Assos
        ),
147
      ),
148
    );
149
150 b720ea3e Assos Assos
    // Get default granularity options
151 85ad3d82 Assos Assos
    $options = $this->date_handler->date_parts();
152 b720ea3e Assos Assos
    // Add the 'week' option.
153
    $options += array(
154
      'week' => t('Week', array(), array(
155
        'context' => 'datetime',
156
      )),
157
    );
158
159 85ad3d82 Assos Assos
    $form['granularity'] = array(
160
      '#title' => t('Granularity'),
161
      '#type' => 'radios',
162
      '#options' => $options,
163
      '#default_value' => $this->options['granularity'],
164
      '#description' => t("Select the type of date value to be used in defaults, summaries, and navigation. For example, a granularity of 'month' will set the default date to the current month, summarize by month in summary views, and link to the next and previous month when using date navigation."),
165
    );
166
167 b720ea3e Assos Assos
    $form['granularity_reset'] = array(
168
      '#title' => t('Use granularity from argument value'),
169
      '#type' => 'checkbox',
170
      '#default_value' => $this->options['granularity_reset'],
171
      '#description' => t("If the granularity of argument value is different from selected, use it from argument value."),
172
    );
173
174 85ad3d82 Assos Assos
    $form['year_range'] = array(
175
      '#title' => t('Date year range'),
176
      '#type' => 'textfield',
177
      '#default_value' => $this->options['year_range'],
178
      '#description' => t("Set the allowable minimum and maximum year range for this argument, either a -X:+X offset from the current year, like '-3:+3' or an absolute minimum and maximum year, like '2005:2010' . When the argument is set to a date outside the range, the page will be returned as 'Page not found (404)' ."),
179
    );
180
181
    $form['use_fromto'] = array(
182
      '#type' => 'radios',
183
      '#title' => t('Dates to compare'),
184
      '#default_value' => $this->options['use_fromto'],
185
      '#options' => array('' => t('Start/End date range'), 'no' => t('Only this field')),
186
      '#description' => t("If selected the view will check if any value starting with the 'Start' date and ending with the 'End' date matches the view criteria. Otherwise the view will be limited to the specifically selected fields. Comparing to the whole Start/End range is the recommended setting when using this filter in a Calendar. When using the Start/End option, it is not necessary to add both the Start and End fields to the filter, either one will do."),
187
    );
188
189
    $access = TRUE;
190
    if (!empty($this->definition['field_name'])) {
191
      $field = field_info_field($this->definition['field_name']);
192
      $access = $field['cardinality'] != 1;
193
    }
194
    $form['add_delta'] = array(
195
      '#type' => 'radios',
196
      '#title' => t('Add multiple value identifier'),
197
      '#default_value' => $this->options['add_delta'],
198
      '#options' => array('' => t('No'), 'yes' => t('Yes')),
199
      '#description' => t('Add an identifier to the view to show which multiple value date fields meet the filter criteria. Note: This option may introduce duplicate values into the view. Required when using multiple value fields in a Calendar or any time you want the node view of multiple value dates to display only the values that match the view filters.'),
200 b720ea3e Assos Assos
      // Only let mere mortals tweak this setting for multi-value fields.
201 85ad3d82 Assos Assos
      '#access' => $access,
202
    );
203
  }
204
205 b720ea3e Assos Assos
  /**
206
   * {@inheritdoc}
207
   */
208 85ad3d82 Assos Assos
  function options_validate(&$form, &$form_state) {
209
    // It is very important to call the parent function here:
210
    parent::options_validate($form, $form_state);
211 b720ea3e Assos Assos
    if (!preg_match('/^(?:\-[0-9]{1,4}|[0-9]{4}):(?:[\+\-][0-9]{1,4}|[0-9]{4})$/', $form_state['values']['options']['year_range'])) {
212 85ad3d82 Assos Assos
      form_error($form['year_range'], t('Date year range must be in the format -9:+9, 2005:2010, -9:2010, or 2005:+9'));
213
    }
214
  }
215
216
  /**
217
   * Provide a link to the next level of the view from the summary.
218
   */
219
  function summary_name($data) {
220
    $value = $data->{$this->name_alias};
221
    if (empty($value) && !empty($this->definition['empty field name'])) {
222
      return $this->definition['empty field name'];
223
    }
224
    elseif (empty($value)) {
225
      return $this->options['wildcard_substitution'];
226
    }
227
    $format = !empty($this->options['title_format_custom']) && !empty($this->options['title_format_custom']) ? $this->options['title_format_custom'] : $this->date_handler->views_formats($this->options['granularity'], 'display');
228
    $range = $this->date_handler->arg_range($value);
229
    return date_format_date($range[0], 'custom', $format);
230
  }
231
232
  /**
233
   * Provide a title for the view based on the argument value.
234
   */
235
  function title() {
236
    $format = !empty($this->options['title_format_custom']) && !empty($this->options['title_format_custom']) ? $this->options['title_format_custom'] : $this->date_handler->views_formats($this->options['granularity'], 'display');
237
    $range = $this->date_handler->arg_range($this->argument);
238
    return date_format_date($range[0], 'custom', $format);
239 b720ea3e Assos Assos
  }
240 85ad3d82 Assos Assos
241
  /**
242 b720ea3e Assos Assos
   * Provide the argument to use to link from the summary to the next level.
243
   *
244
   * This will be called once per row of a summary, and used as part of
245 85ad3d82 Assos Assos
   * $view->get_url().
246
   *
247 b720ea3e Assos Assos
   * @param object $data
248 85ad3d82 Assos Assos
   *   The query results for the row.
249
   */
250
  function summary_argument($data) {
251
    $format = $this->date_handler->views_formats($this->options['granularity'], 'sql');
252
    $value = $data->{$this->name_alias};
253
    if (empty($value)) {
254
      return $this->options['exception']['value'];
255
    }
256
    $range = $this->date_handler->arg_range($value);
257
    return date_format_date($range[0], 'custom', $format);
258
  }
259
260
  /**
261
   * Inject a test for valid date range before the summary query.
262
   */
263
  function summary_query() {
264
265 b720ea3e Assos Assos
    // @TODO The summary values are computed by the database.
266
    // Unless the database has built-in timezone handling it will use
267
    // a fixed offset, which will not be right for all dates.
268
    // The only way I can see to make this work right is to store the offset
269
    // for each date in the database so it can be added to the base
270 85ad3d82 Assos Assos
    // date value before the database formats the result. Because this is a huge
271
    // architectural change, it won't go in until we start a new branch.
272
    $this->formula = $this->date_handler->sql_format($this->sql_format, $this->date_handler->sql_field("***table***.$this->real_field"));
273
    $this->ensure_my_table();
274
    // Now that our table is secure, get our formula.
275
    $formula = $this->get_formula();
276
277 b720ea3e Assos Assos
    // Add the field, give it an alias that does NOT match the actual
278
    // field name or grouping won't work right.
279 85ad3d82 Assos Assos
    $this->base_alias = $this->name_alias = $this->query->add_field(NULL, $formula, $this->field . '_summary');
280
    $this->query->set_count_field(NULL, $formula, $this->field);
281
282
    return $this->summary_basics(FALSE);
283
  }
284
285
  /**
286
   * Inject a test for valid date range before the regular query.
287 b720ea3e Assos Assos
   *
288 85ad3d82 Assos Assos
   * Override the parent query to be able to control the $group.
289
   */
290
  function query($group_by = FALSE) {
291
292 b720ea3e Assos Assos
    // @TODO Not doing anything with $group_by yet,
293
    // need to figure out what has to be done.
294 85ad3d82 Assos Assos
295
    if ($this->date_forbid()) {
296
      return;
297
    }
298
299
    // See if we need to reset granularity based on an argument value.
300 b720ea3e Assos Assos
    // Make sure we don't try to reset to some bogus value if someone has
301
    // typed in an unexpected argument.
302
    if ($this->options['granularity_reset'] && $granularity = $this->date_handler->arg_granularity($this->argument)) {
303 85ad3d82 Assos Assos
      $this->date_handler->granularity = $granularity;
304
      $this->format = $this->date_handler->views_formats($this->date_handler->granularity, 'display');
305
      $this->sql_format = $this->date_handler->views_formats($this->date_handler->granularity, 'sql');
306
    }
307
    $this->granularity = $this->date_handler->granularity;
308
    $this->ensure_my_table();
309
    $group = !empty($this->options['date_group']) ? $this->options['date_group'] : 0;
310
311 b720ea3e Assos Assos
    // If requested, add the delta field to the view so
312
    // we can later find the value that matched our query.
313 85ad3d82 Assos Assos
    if (!empty($this->options['add_delta']) && (substr($this->real_field, -6) == '_value' || substr($this->real_field, -7) == '_value2')) {
314
      $this->query->add_field($this->table_alias, 'delta');
315
      $real_field_name = str_replace(array('_value', '_value2'), '', $this->real_field);
316
      $this->query->add_field($this->table_alias, 'entity_id', 'date_id_' . $real_field_name);
317
      $this->query->add_field($this->table_alias, 'delta', 'date_delta_' . $real_field_name);
318
    }
319
320
    $format = $this->date_handler->granularity == 'week' ? DATE_FORMAT_DATETIME : $this->sql_format;
321
    $view_min = date_format($this->min_date, $format);
322
    $view_max = date_format($this->max_date, $format);
323
    $view_min_placeholder = $this->placeholder();
324
    $view_max_placeholder = $this->placeholder();
325
    $this->date_handler->placeholders = array($view_min_placeholder => $view_min, $view_max_placeholder => $view_max);
326
327 b720ea3e Assos Assos
    // Are we comparing this field only or the Start/End date range
328
    // to the view criteria?
329 85ad3d82 Assos Assos
    if (!empty($this->options['use_fromto'])) {
330
331
      // The simple case, match the field to the view range.
332
      $field = $this->date_handler->sql_field($this->table_alias . '.' . $this->real_field, NULL, $this->min_date);
333
      $field = $this->date_handler->sql_format($format, $field);
334
      $this->query->add_where_expression($group, "$field >= $view_min_placeholder AND $field <= $view_max_placeholder", array($view_min_placeholder => $view_min, $view_max_placeholder => $view_max));
335
336
    }
337
    else {
338
339 b720ea3e Assos Assos
      // Look for the intersection of the range
340
      // of the date field with the range of the view.
341
      // Get the Start/End values for this field.
342
      // Retrieve using the original table name.
343
      // Swap the current table name (adjusted for relationships)
344
      // into the query.
345
      // @TODO We may be able to use Views substitutions here,
346
      // investigate that later.
347 85ad3d82 Assos Assos
      $fields = date_views_fields($this->base_table);
348
      $fields = $fields['name'];
349
      $fromto = $fields[$this->original_table . '.' . $this->real_field]['fromto'];
350
351
      $value_min = str_replace($this->original_table, $this->table_alias, $fromto[0]);
352
      $value_max = str_replace($this->original_table, $this->table_alias, $fromto[1]);
353
      $field_min = $this->date_handler->sql_field($value_min, NULL, $this->min_date);
354
      $field_min = $this->date_handler->sql_format($format, $field_min);
355
      $field_max = $this->date_handler->sql_field($value_max, NULL, $this->max_date);
356
      $field_max = $this->date_handler->sql_format($format, $field_max);
357
      $this->query->add_where_expression($group, "$field_max >= $view_min_placeholder AND $field_min <= $view_max_placeholder", array($view_min_placeholder => $view_min, $view_max_placeholder => $view_max));
358
    }
359
  }
360
361
  /**
362 b720ea3e Assos Assos
   * Add a callback.
363
   *
364
   * To determine if we have moved outside
365
   * the valid date range for this argument.
366 85ad3d82 Assos Assos
   */
367
  function date_forbid() {
368
    if (empty($this->argument)) {
369
      return TRUE;
370
    }
371
    $this->date_range = $this->date_handler->arg_range($this->argument);
372
    $this->min_date = $this->date_range[0];
373
    $this->max_date = $this->date_range[1];
374
    $this->limit = date_range_years($this->options['year_range']);
375
    $group = !empty($this->options['date_group']) ? $this->options['date_group'] : 0;
376
377
    // See if we're outside the allowed date range for our argument.
378
    if (date_format($this->min_date, 'Y') < $this->limit[0] || date_format($this->max_date, 'Y') > $this->limit[1]) {
379
      $this->forbid = TRUE;
380
      $this->view->build_info['fail'] = TRUE;
381
      return TRUE;
382
    }
383
    return FALSE;
384
  }
385
386
}
387 b720ea3e Assos Assos
// @codingStandardsIgnoreEnd