Révision 599a39cd
Ajouté par Assos Assos il y a environ 3 ans
drupal7/sites/all/modules/date/date_views/includes/date_views_plugin_pager.inc | ||
---|---|---|
1 | 1 |
<?php |
2 |
|
|
2 | 3 |
/** |
3 | 4 |
* @file |
4 | 5 |
* Date pager. |
5 |
* Works with a Date argument, the argument filters |
|
6 |
* the view and the pager provides back/next navigation. |
|
6 |
* |
|
7 |
* Works with a Date argument, the argument filters the view and the pager |
|
8 |
* provides back/next navigation. |
|
7 | 9 |
* |
8 | 10 |
* USER NOTES: |
9 | 11 |
* |
10 | 12 |
* To use this, add a pager to a view, and choose the option to 'Page by date'. |
11 | 13 |
* There are several settings: |
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. |
|
14 |
* - The pager id: Set an id to be used as the identifier in the URL for pager |
|
15 |
* values, defaults to 'date'. |
|
16 |
* - Pager position: Choose whether to display the date pager above, below, or |
|
17 |
* both above and below the content. |
|
18 |
* - Link format: Choose whether the pager links will be in the simple |
|
19 |
* 'calendar/2011-12' format or the more complex 'calendar/?date=2011-12' |
|
20 |
* pager format. The second one is more likely to work correctly if the pager |
|
21 |
* is used in blocks and panels. |
|
21 | 22 |
* |
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 |
|
30 |
* argument that uses the date argument handler. |
|
23 |
* The pager works in combination with a Date argument and it will use the date |
|
24 |
* fields and granularity set in that argument to create its back/next links. If |
|
25 |
* the view has no Date argument, the pager can do nothing. The argument can |
|
26 |
* either be a 'Date' argument that lets you select one or more date fields in |
|
27 |
* the argument, or the simple 'Content' argument for an individual date field. |
|
28 |
* It must be an argument that uses the date argument handler. |
|
31 | 29 |
* |
32 | 30 |
* DEVELOPER NOTES |
33 | 31 |
* |
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. |
|
32 |
* The pager could technically create a query of its own rather than depending |
|
33 |
* on the date argument to set the query, but it has only a limited set of tools |
|
34 |
* to work with because it is a plugin, not a handler: it has no knowledge about |
|
35 |
* relationships, it cannot use the ensure_my_table() function, plugins are not |
|
36 |
* even invoked in pre_query(), so can't do anything there. |
|
41 | 37 |
* |
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 |
|
48 |
* date argument, the pager will do nothing. |
|
38 |
* My conclusion was that the date pager simply is not powerful enough to create |
|
39 |
* its own queries for date fields, which require very complex queries. Instead, |
|
40 |
* we can combine this with a date argument and let the argument create the |
|
41 |
* query and let the pager just provide the back/next links. If there is no date |
|
42 |
* argument, the pager will do nothing. |
|
49 | 43 |
* |
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. |
|
44 |
* There are still other problems. The pager is not even initialized until after |
|
45 |
* all the handlers have created their queries, so it has no chance to alter |
|
46 |
* values ahead of that. And the argument has no knowledge of the pager, so it |
|
47 |
* can't check for pager values before the query is created. |
|
56 | 48 |
* |
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. |
|
49 |
* The solution used here is to let the argument create the original query. The |
|
50 |
* pager query runs after that, so the pager checks to see if there is a pager |
|
51 |
* value that needs to be used in the query. The date argument has identified |
|
52 |
* the placeholders it used in the query. So if a change is needed, we can swap |
|
53 |
* the pager value into the query created by the date argument and adjust the |
|
54 |
* $view->date_info values set by the argument accordingly so the theme will |
|
55 |
* pick up the new information. |
|
67 | 56 |
*/ |
68 | 57 |
|
69 | 58 |
/** |
70 |
* Example plugin to handle paging by month.
|
|
59 |
* Views pager plugin to page by month.
|
|
71 | 60 |
*/ |
72 |
// @codingStandardsIgnoreStart |
|
73 | 61 |
class date_views_plugin_pager extends views_plugin_pager { |
74 | 62 |
|
75 | 63 |
/** |
76 |
* This kind of pager does not need to count the number of records.
|
|
64 |
* {@inheritdoc}
|
|
77 | 65 |
*/ |
78 | 66 |
function use_count_query() { |
79 | 67 |
return FALSE; |
80 | 68 |
} |
81 | 69 |
|
82 | 70 |
/** |
83 |
* Because we don't know how many pages there are, we never believe there are more records.
|
|
71 |
* {@inheritdoc}
|
|
84 | 72 |
*/ |
85 | 73 |
function has_more_records() { |
86 | 74 |
return FALSE; |
87 | 75 |
} |
88 | 76 |
|
89 |
/* |
|
90 |
* Tell Views what this pager's setting is.
|
|
77 |
/**
|
|
78 |
* {@inheritdoc}
|
|
91 | 79 |
*/ |
92 | 80 |
function summary_title() { |
93 | 81 |
return t("Position: @position, format: @format.", array('@position' => $this->options['pager_position'], '@format' => $this->options['link_format'])); |
94 | 82 |
} |
95 | 83 |
|
96 | 84 |
/** |
97 |
* Tell Views what options this plugin can store.
|
|
85 |
* {@inheritdoc}
|
|
98 | 86 |
*/ |
99 | 87 |
function option_definition() { |
100 | 88 |
$options = parent::option_definition(); |
... | ... | |
107 | 95 |
return $options; |
108 | 96 |
} |
109 | 97 |
|
110 |
/* |
|
111 |
* Provide the form for setting options.
|
|
98 |
/**
|
|
99 |
* {@inheritdoc}
|
|
112 | 100 |
*/ |
113 | 101 |
function options_form(&$form, &$form_state) { |
114 | 102 |
$form['markup']['#markup'] = t('This pager works together with a Date or Content date field contextual filter. If a Date filter has been added to the view, this pager will provide back/next paging to match the granularity of that filter (i.e. paging by year, month, week, or day). The filter must also be configured to use a DATE default value. If there is no Date contextual filter on this view, or if it has not been set to use a default date, the pager will not appear.'); |
... | ... | |
148 | 136 |
} |
149 | 137 |
|
150 | 138 |
/** |
151 |
* Transfer date information from the argument to the view so the pager theme can use it |
|
152 |
* and update the date argument value to whatever is set by the pager. |
|
139 |
* {@inheritdoc} |
|
153 | 140 |
*/ |
154 | 141 |
function query() { |
155 |
|
|
156 |
// By fetching our data from the exposed input, it is possible to |
|
157 |
// feed pager data through some method other than $_GET. |
|
142 |
// By fetching our data from the exposed input, it is possible to feed |
|
143 |
// pager data through some method other than $_GET. |
|
158 | 144 |
$input = $this->view->get_exposed_input(); |
159 | 145 |
$value = NULL; |
160 | 146 |
if (!empty($input) && !empty($input[$this->options['date_id']])) { |
... | ... | |
166 | 152 |
foreach ($this->view->argument as $id => &$argument) { |
167 | 153 |
if (date_views_handler_is_date($argument, 'argument')) { |
168 | 154 |
|
169 |
// If the argument is empty, nothing to do. This could be from |
|
170 |
// an argument that does not set a default value.
|
|
155 |
// If the argument is empty, nothing to do. This could be from an
|
|
156 |
// argument that does not set a default value. |
|
171 | 157 |
if (empty($argument->argument) || empty($argument->date_handler)) { |
172 | 158 |
continue; |
173 | 159 |
} |
174 | 160 |
|
175 |
// Storing this information in the pager so it's available for summary info.
|
|
176 |
// The view argument information is not otherwise accessible to the pager.
|
|
177 |
// Not working right yet, tho. |
|
161 |
// Storing this information in the pager so it's available for summary |
|
162 |
// info. The view argument information is not otherwise accessible to
|
|
163 |
// the pager. Not working right yet, tho.
|
|
178 | 164 |
$date_handler = $argument->date_handler; |
179 | 165 |
$this->options['date_argument'] = $id; |
180 | 166 |
$this->options['granularity'] = $argument->date_handler->granularity; |
... | ... | |
189 | 175 |
$this->view->build_info['fail'] = TRUE; |
190 | 176 |
return; |
191 | 177 |
} |
192 |
// Write date_info to store information to be used |
|
193 |
// in the theming functions. |
|
178 |
|
|
179 |
// Write date_info to store information to be used in the theming |
|
180 |
// functions. |
|
194 | 181 |
if (empty($this->view->date_info)) { |
195 | 182 |
$this->view->date_info = new stdClass(); |
196 | 183 |
} |
... | ... | |
205 | 192 |
$this->view->date_info->date_pager_position = $this->options['pager_position']; |
206 | 193 |
$this->view->date_info->date_pager_format = $this->options['link_format']; |
207 | 194 |
$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. |
|
195 |
|
|
196 |
// Execute two additional queries to find the previous and next page |
|
197 |
// with values. |
|
210 | 198 |
if ($this->view->date_info->skip_empty_pages) { |
211 | 199 |
$q = clone $argument->query; |
212 | 200 |
$field = $argument->table_alias . '.' . $argument->real_field; |
... | ... | |
217 | 205 |
$q->set_distinct(TRUE, TRUE); |
218 | 206 |
// Date limits of this argument. |
219 | 207 |
$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.
|
|
208 |
// Find the first two dates between the minimum date and the upper
|
|
209 |
// bound of the current value. |
|
222 | 210 |
$q->add_orderby(NULL, $fieldsql, 'DESC', 'date'); |
223 | 211 |
$this->set_argument_placeholders($this->view->date_info->placeholders, $datelimits[0], $argument->max_date, $q, $format); |
224 | 212 |
|
... | ... | |
243 | 231 |
// Set the default value of the query to $prevfirst or $nextfirst |
244 | 232 |
// when there is no value and $prevsecond or $nextsecond is set. |
245 | 233 |
if (empty($value)) { |
246 |
// @Todo find out which of $prevdate or $nextdate is closest to the
|
|
234 |
// @todo find out which of $prevdate or $nextdate is closest to the
|
|
247 | 235 |
// default argument date value and choose that one. |
248 | 236 |
if ($prevdate && $prevdatealt) { |
249 | 237 |
$this->set_argument_value($argument, $prevdate); |
... | ... | |
269 | 257 |
} |
270 | 258 |
} |
271 | 259 |
else { |
272 |
// $prevdate and $nextdate are the same as $value, so move to |
|
273 |
// the next values.
|
|
260 |
// $prevdate and $nextdate are the same as $value, so move to the
|
|
261 |
// next values. |
|
274 | 262 |
$prevdate = $prevdatealt; |
275 | 263 |
$nextdate = $nextdatealt; |
276 | 264 |
} |
... | ... | |
279 | 267 |
$this->view->date_info->next_date = $nextdate ? new DateObject($nextdate, NULL, $format) : NULL; |
280 | 268 |
} |
281 | 269 |
else { |
282 |
$this->view->date_info->prev_date = clone($argument->min_date);
|
|
270 |
$this->view->date_info->prev_date = clone $argument->min_date;
|
|
283 | 271 |
date_modify($this->view->date_info->prev_date, '-1 ' . $argument->date_handler->granularity); |
284 |
$this->view->date_info->next_date = clone($argument->min_date);
|
|
272 |
$this->view->date_info->next_date = clone $argument->min_date;
|
|
285 | 273 |
date_modify($this->view->date_info->next_date, '+1 ' . $argument->date_handler->granularity); |
286 | 274 |
} |
287 | 275 |
// Write the date_info properties that depend on the current value. |
... | ... | |
296 | 284 |
$i++; |
297 | 285 |
} |
298 | 286 |
|
299 |
// Is this a view that needs to be altered based on a pager value? |
|
300 |
// If there is pager input and the argument has set the placeholders,
|
|
301 |
// swap the pager value in for the placeholder set by the argument.
|
|
287 |
// Is this a view that needs to be altered based on a pager value? If there
|
|
288 |
// is pager input and the argument has set the placeholders, swap the pager
|
|
289 |
// value in for the placeholder set by the argument. |
|
302 | 290 |
if (!empty($value) && !empty($this->view->date_info->placeholders)) { |
303 | 291 |
$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 | 292 |
} |
305 | 293 |
} |
306 | 294 |
|
295 |
/** |
|
296 |
* {@inheritdoc} |
|
297 |
*/ |
|
307 | 298 |
function set_argument_value($argument, $value) { |
308 | 299 |
$argument->argument = $value; |
309 | 300 |
$argument->date_range = $argument->date_handler->arg_range($value); |
... | ... | |
314 | 305 |
$argument->is_default = FALSE; |
315 | 306 |
} |
316 | 307 |
|
308 |
/** |
|
309 |
* {@inheritdoc} |
|
310 |
*/ |
|
317 | 311 |
function set_argument_placeholders($placeholders, $mindate, $maxdate, $query, $format) { |
318 | 312 |
$count = count($placeholders); |
319 | 313 |
foreach ($query->where as $group => $data) { |
... | ... | |
321 | 315 |
if (array_key_exists('value', $condition) && is_array($condition['value'])) { |
322 | 316 |
foreach ($condition['value'] as $placeholder => $placeholder_value) { |
323 | 317 |
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. |
|
318 |
// If we didn't get a match, this is a > $min < $max query that |
|
319 |
// uses the view min and max dates as placeholders.
|
|
326 | 320 |
$date = ($count == 2) ? $mindate : $maxdate; |
327 | 321 |
$next_placeholder = array_shift($placeholders); |
328 | 322 |
$query->where[$group]['conditions'][$delta]['value'][$placeholder] = $date->format($format); |
... | ... | |
335 | 329 |
} |
336 | 330 |
|
337 | 331 |
/** |
338 |
* Add a callback to determine if we have moved outside the valid date range for this argument.
|
|
332 |
* Determine if we have moved outside the valid date range for this argument.
|
|
339 | 333 |
*/ |
340 | 334 |
function date_forbid($argument) { |
341 | 335 |
// See if we're outside the allowed date range for our argument. |
... | ... | |
346 | 340 |
return FALSE; |
347 | 341 |
} |
348 | 342 |
|
343 |
/** |
|
344 |
* {@inheritdoc} |
|
345 |
*/ |
|
346 |
function pre_render(&$result) { |
|
347 |
// Load theme functions for the pager. |
|
348 |
module_load_include('inc', 'date_views', 'theme/theme'); |
|
349 |
} |
|
349 | 350 |
|
351 |
/** |
|
352 |
* {@inheritdoc} |
|
353 |
*/ |
|
350 | 354 |
function render($input) { |
351 |
// This adds all of our template suggestions based upon the view name and display id. |
|
355 |
// This adds all of our template suggestions based upon the view name and |
|
356 |
// display id. |
|
352 | 357 |
$pager_theme = views_theme_functions('date_views_pager', $this->view, $this->display); |
353 | 358 |
return theme($pager_theme, array('plugin' => $this, 'input' => $input)); |
354 | 359 |
} |
360 |
|
|
355 | 361 |
} |
356 |
// @codingStandardsIgnoreEnd |
Formats disponibles : Unified diff
Weekly update of contrib modules