Projet

Général

Profil

Révision b720ea3e

Ajouté par Assos Assos il y a plus de 8 ans

Weekly update of contrib modules

Voir les différences:

drupal7/sites/all/modules/date/date_views/includes/date_views_plugin_pager.inc
2 2
/**
3 3
 * @file
4 4
 * Date pager.
5
 * Works with a Date argument, the argument filters the view and the pager provides back/next navigation.
5
 * Works with a Date argument, the argument filters
6
 * the view and the pager provides back/next navigation.
6 7
 *
7 8
 * USER NOTES:
8 9
 *
9 10
 * To use this, add a pager to a view, and choose the option to 'Page by date'.
10 11
 * There are several settings:
11
 * - The pager id: Set an id to be used as the identifier in the url for pager values, defaults to 'date'.
12
 * - Pager position: Choose whether to display the date pager above, below, or both above and below the content.
13
 * - Link format: Choose whether the pager links will be in the simple 'calendar/2011-12' format or the
14
 *   more complex 'calendar/?date=2011-12' pager format. The second one is more likely to work correctly
15
 *   if the pager is used in blocks and panels.
12
 * - The pager id: Set an id to be used as the identifier
13
 *    in the url for pager values, defaults to 'date'.
14
 * - Pager position: Choose whether to display the date
15
 *    pager above, below, or both above and below the content.
16
 * - Link format: Choose whether the pager links will be in t
17
 *    he simple 'calendar/2011-12' format or the
18
 *    more complex 'calendar/?date=2011-12' pager format.
19
 *    The second one is more likely to work correctly
20
 *    if the pager is used in blocks and panels.
16 21
 *
17
 * The pager works in combination with a Date argument and it will use the date fields and granularity
18
 * set in that argument to create its back/next links. If the view has no Date argument, the pager can
19
 * do nothing. The argument can either be a 'Date' argument that lets you select one or more date fields
20
 * in the argument, or the simple 'Content' argument for an individual date field. It must be an
22
 * The pager works in combination with a Date argument
23
 * and it will use the date fields and granularity
24
 * set in that argument to create its back/next links.
25
 * If the view has no Date argument, the pager can
26
 * do nothing. The argument can either be a 'Date' argument
27
 * that lets you select one or more date fields
28
 * in the argument, or the simple 'Content' argument for an
29
 * individual date field. It must be an
21 30
 * argument that uses the date argument handler.
22 31
 *
23 32
 * DEVELOPER NOTES
24 33
 *
25
 * The pager could technically create a query of its own rather than depending on the date argument to
26
 * set the query, but it has only a limited set of tools to work with because it is a plugin, not a handler:
27
 * it has no knowledge about relationships, it cannot use the ensure_my_table() function,
28
 * plugins are not even invoked in pre_query(), so can't do anything there.
34
 * The pager could technically create a query of its own rather
35
 * than depending on the date argument to
36
 * set the query, but it has only a limited set of tools to work
37
 * with because it is a plugin, not a handler:
38
 * it has no knowledge about relationships, it cannot use the
39
 * ensure_my_table() function, plugins are not even invoked in pre_query(),
40
 * so can't do anything there.
29 41
 *
30
 * My conclusion was that the date pager simply is not powerful enough to create its own queries for
31
 * date fields, which require very complex queries. Instead, we can combine this with a date argument and
32
 * let the argument create the query and let the pager just provide the back/next links. If there is no
42
 * My conclusion was that the date pager simply
43
 * is not powerful enough to create its own queries for
44
 * date fields, which require very complex queries.
45
 * Instead, we can combine this with a date argument and
46
 * let the argument create the query and let the pager
47
 * just provide the back/next links. If there is no
33 48
 * date argument, the pager will do nothing.
34 49
 *
35
 * There are still other problems. The pager is not even initialized until after all the handlers
36
 * have created their queries, so it has no chance to alter values ahead of that. And the argument
37
 * has no knowledge of the pager, so it can't check for pager values before the query is created.
50
 * There are still other problems. The pager is not even
51
 * initialized until after all the handlers
52
 * have created their queries, so it has no chance
53
 * to alter values ahead of that. And the argument
54
 * has no knowledge of the pager, so it can't check
55
 * for pager values before the query is created.
38 56
 *
39
 * The solution used here is to let the argument create the original query. The pager query
40
 * runs after that, so the pager checks to see if there is a pager value that needs to be used in the query.
41
 * The date argument has identified the placeholders it used in the query. So if a change is needed,
42
 * we can swap the pager value into the query created by the date argument and adjust the
43
 * $view->date_info values set by the argument accordingly so the theme will pick up the new information.
57
 * The solution used here is to let the argument create
58
 * the original query. The pager query
59
 * runs after that, so the pager checks to see
60
 * if there is a pager value that needs to be used in the query.
61
 * The date argument has identified the placeholders
62
 * it used in the query. So if a change is needed,
63
 * we can swap the pager value into the query created
64
 * by the date argument and adjust the
65
 * $view->date_info values set by the argument accordingly
66
 * so the theme will pick up the new information.
44 67
 */
45 68

  
46 69
/**
47 70
 * Example plugin to handle paging by month.
48 71
 */
72
// @codingStandardsIgnoreStart
49 73
class date_views_plugin_pager extends views_plugin_pager {
50 74

  
51 75
  /**
......
79 103
    $options['link_format'] = array('default' => 'pager');
80 104
    $options['date_argument'] = array('default' => 'Unknown');
81 105
    $options['granularity'] = array('default' => 'Unknown');
106
    $options['skip_empty_pages'] = array('default' => FALSE);
82 107
    return $options;
83 108
  }
84 109

  
......
110 135
      '#default_value' => $this->options['link_format'],
111 136
      '#required' => TRUE,
112 137
    );
138
    $form['skip_empty_pages'] = array(
139
      '#title' => t('Skip empty pages'),
140
      '#type' => 'checkbox',
141
      '#description' => t('When selected, the pager will not display pages with no result for the given date. This causes a slight performance degradation because two additional queries need to be executed.'),
142
      '#default_value' => $this->options['skip_empty_pages'],
143
    );
113 144
    $form['date_argument']['#type'] = 'hidden';
114 145
    $form['date_argument']['#value'] = $this->options['date_argument'];
115 146
    $form['granularity']['#type'] = 'hidden';
......
150 181

  
151 182
        // Reset values set by argument if pager requires it.
152 183
        if (!empty($value)) {
153
          $argument->argument = $value;
154
          $argument->date_range = $argument->date_handler->arg_range($value);
155
          $argument->min_date = $argument->date_range[0];
156
          $argument->max_date = $argument->date_range[1];
157
          // $argument->is_default works correctly for normal arguments, but does not
158
          // work correctly if we are swapping in a new value from the pager.
159
          $argument->is_default = FALSE;
184
          $this->set_argument_value($argument, $value);
160 185
        }
161 186

  
162 187
        // The pager value might move us into a forbidden range, so test it.
......
164 189
          $this->view->build_info['fail'] = TRUE;
165 190
          return;
166 191
        }
167

  
168
        if (empty($this->view->date_info)) $this->view->date_info = new stdClass();
192
        // Write date_info to store information to be used
193
        // in the theming functions.
194
        if (empty($this->view->date_info)) {
195
          $this->view->date_info = new stdClass();
196
        }
169 197
        $this->view->date_info->granularity = $argument->date_handler->granularity;
170 198
        $format = $this->view->date_info->granularity == 'week' ? DATE_FORMAT_DATETIME : $argument->sql_format;
171 199
        $this->view->date_info->placeholders = isset($argument->placeholders) ? $argument->placeholders : $argument->date_handler->placeholders;
172 200
        $this->view->date_info->date_arg = $argument->argument;
173 201
        $this->view->date_info->date_arg_pos = $i;
202
        $this->view->date_info->limit = $argument->limit;
203
        $this->view->date_info->url = $this->view->get_url();
204
        $this->view->date_info->pager_id = $this->options['date_id'];
205
        $this->view->date_info->date_pager_position = $this->options['pager_position'];
206
        $this->view->date_info->date_pager_format = $this->options['link_format'];
207
        $this->view->date_info->skip_empty_pages = $this->options['skip_empty_pages'] == 1;
208
        // Execute two additional queries to find
209
        // the previous and next page with values.
210
        if ($this->view->date_info->skip_empty_pages) {
211
          $q = clone $argument->query;
212
          $field = $argument->table_alias . '.' . $argument->real_field;
213
          $fieldsql = $date_handler->sql_field($field);
214
          $fieldsql = $date_handler->sql_format($format, $fieldsql);
215
          $q->clear_fields();
216
          $q->orderby = array();
217
          $q->set_distinct(TRUE, TRUE);
218
          // Date limits of this argument.
219
          $datelimits = $argument->date_handler->arg_range($argument->limit[0] . '--' . $argument->limit[1]);
220
          // Find the first two dates between the minimum date
221
          // and the upper bound of the current value.
222
          $q->add_orderby(NULL, $fieldsql, 'DESC', 'date');
223
          $this->set_argument_placeholders($this->view->date_info->placeholders, $datelimits[0], $argument->max_date, $q, $format);
224

  
225
          $compiledquery = $q->query();
226
          $compiledquery->range(0, 2);
227
          $results = $compiledquery->execute()->fetchCol(0);
228

  
229
          $prevdate = array_shift($results);
230
          $prevdatealt = array_shift($results);
231
          // Find the first two dates between the lower bound
232
          // of the current value and the maximum date.
233
          $q->add_orderby(NULL, $fieldsql, 'ASC', 'date');
234
          $this->set_argument_placeholders($this->view->date_info->placeholders, $argument->min_date, $datelimits[1], $q, $format);
235

  
236
          $compiledquery = $q->query();
237
          $compiledquery->range(0, 2);
238
          $results = $compiledquery->execute()->fetchCol(0);
239

  
240
          $nextdate = array_shift($results);
241
          $nextdatealt = array_shift($results);
242

  
243
          // Set the default value of the query to $prevfirst or $nextfirst
244
          // when there is no value and $prevsecond or $nextsecond is set.
245
          if (empty($value)) {
246
            // @Todo find out which of $prevdate or $nextdate is closest to the
247
            // default argument date value and choose that one.
248
            if ($prevdate && $prevdatealt) {
249
              $this->set_argument_value($argument, $prevdate);
250
              $value = $prevdate;
251
              $prevdate = $prevdatealt;
252
              // If the first next date is the same as the first previous date,
253
              // move to the following next date.
254
              if ($value == $nextdate) {
255
                $nextdate = $nextdatealt;
256
                $nextdatealt = NULL;
257
              }
258
            }
259
            elseif ($nextdate && $nextdatealt) {
260
              $this->set_argument_value($argument, $nextdate);
261
              $value = $nextdate;
262
              $nextdate = $nextdatealt;
263
              // If the first previous date is the same as the first next date,
264
              // move to the following previous date.
265
              if ($value == $prevdate) {
266
                $prevdate = $prevdatealt;
267
                $prevdatealt = NULL;
268
              }
269
            }
270
          }
271
          else {
272
            // $prevdate and $nextdate are the same as $value, so move to
273
            // the next values.
274
            $prevdate = $prevdatealt;
275
            $nextdate = $nextdatealt;
276
          }
277

  
278
          $this->view->date_info->prev_date = $prevdate ? new DateObject($prevdate, NULL, $format) : NULL;
279
          $this->view->date_info->next_date = $nextdate ? new DateObject($nextdate, NULL, $format) : NULL;
280
        }
281
        else {
282
          $this->view->date_info->prev_date = clone($argument->min_date);
283
          date_modify($this->view->date_info->prev_date, '-1 ' . $argument->date_handler->granularity);
284
          $this->view->date_info->next_date = clone($argument->max_date);
285
          date_modify($this->view->date_info->next_date, '+1 ' . $argument->date_handler->granularity);
286
        }
287
        // Write the date_info properties that depend on the current value.
174 288
        $this->view->date_info->year = date_format($argument->min_date, 'Y');
175 289
        $this->view->date_info->month = date_format($argument->min_date, 'n');;
176 290
        $this->view->date_info->day = date_format($argument->min_date, 'j');
......
178 292
        $this->view->date_info->date_range = $argument->date_range;
179 293
        $this->view->date_info->min_date = $argument->min_date;
180 294
        $this->view->date_info->max_date = $argument->max_date;
181
        $this->view->date_info->limit = $argument->limit;
182
        $this->view->date_info->url = $this->view->get_url();
183
        $this->view->date_info->pager_id = $this->options['date_id'];
184
        $this->view->date_info->date_pager_position = $this->options['pager_position'];
185
        $this->view->date_info->date_pager_format = $this->options['link_format'];
186 295
      }
187 296
      $i++;
188 297
    }
......
191 300
    // If there is pager input and the argument has set the placeholders,
192 301
    // swap the pager value in for the placeholder set by the argument.
193 302
    if (!empty($value) && !empty($this->view->date_info->placeholders)) {
194
      $placeholders = $this->view->date_info->placeholders;
195
      $count = count($placeholders);
196
      foreach ($this->view->query->where as $group => $data) {
197
        foreach ($data['conditions'] as $delta => $condition) {
198
          if (array_key_exists('value', $condition) && is_array($condition['value'])) {
199
            foreach ($condition['value'] as $placeholder => $placeholder_value) {
200
              if (array_key_exists($placeholder, $placeholders)) {
201
                // If we didn't get a match, this is a > $min < $max query that uses the view
202
                // min and max dates as placeholders.
203
                $date = ($count == 2) ? $this->view->date_info->min_date : $this->view->date_info->max_date;
204
                $next_placeholder = array_shift($placeholders);
205
                $this->view->query->where[$group]['conditions'][$delta]['value'][$placeholder] = $date->format($format);
206
                $count--;
207
              }
303
      $this->set_argument_placeholders($this->view->date_info->placeholders, $this->view->date_info->min_date, $this->view->date_info->max_date, $this->view->query, $format);
304
    }
305
  }
306

  
307
  function set_argument_value($argument, $value) {
308
    $argument->argument = $value;
309
    $argument->date_range = $argument->date_handler->arg_range($value);
310
    $argument->min_date = $argument->date_range[0];
311
    $argument->max_date = $argument->date_range[1];
312
    // $argument->is_default works correctly for normal arguments, but does not
313
    // work correctly if we are swapping in a new value from the pager.
314
    $argument->is_default = FALSE;
315
  }
316

  
317
  function set_argument_placeholders($placeholders, $mindate, $maxdate, $query, $format) {
318
    $count = count($placeholders);
319
    foreach ($query->where as $group => $data) {
320
      foreach ($data['conditions'] as $delta => $condition) {
321
        if (array_key_exists('value', $condition) && is_array($condition['value'])) {
322
          foreach ($condition['value'] as $placeholder => $placeholder_value) {
323
            if (array_key_exists($placeholder, $placeholders)) {
324
              // If we didn't get a match, this is a > $min < $max query that uses the view
325
              // min and max dates as placeholders.
326
              $date = ($count == 2) ? $mindate : $maxdate;
327
              $next_placeholder = array_shift($placeholders);
328
              $query->where[$group]['conditions'][$delta]['value'][$placeholder] = $date->format($format);
329
              $count--;
208 330
            }
209 331
          }
210 332
        }
......
230 352
    $pager_theme = views_theme_functions('date_views_pager', $this->view, $this->display);
231 353
    return theme($pager_theme, array('plugin' => $this, 'input' => $input));
232 354
  }
233
}
355
}
356
// @codingStandardsIgnoreEnd

Formats disponibles : Unified diff