From 36ba537169b2e23c12562282d6f66df9ff899bf8 Mon Sep 17 00:00:00 2001 From: ElAlemanyo Date: Thu, 31 Jul 2014 17:13:04 +0200 Subject: [PATCH] Issue #1487700 by Jorrit: Added option to skip empty pages in Date Views pager. --- date_views/includes/date_views_plugin_pager.inc | 151 +++++++++++++++--- date_views/theme/theme.inc | 203 +++++++++++++----------- 2 files changed, 231 insertions(+), 123 deletions(-) diff --git a/date_views/includes/date_views_plugin_pager.inc b/date_views/includes/date_views_plugin_pager.inc index f9594a7..794a0fd 100644 --- a/date_views/includes/date_views_plugin_pager.inc +++ b/date_views/includes/date_views_plugin_pager.inc @@ -79,6 +79,7 @@ class date_views_plugin_pager extends views_plugin_pager { $options['link_format'] = array('default' => 'pager'); $options['date_argument'] = array('default' => 'Unknown'); $options['granularity'] = array('default' => 'Unknown'); + $options['skip_empty_pages'] = array('default' => FALSE); return $options; } @@ -110,6 +111,12 @@ class date_views_plugin_pager extends views_plugin_pager { '#default_value' => $this->options['link_format'], '#required' => TRUE, ); + $form['skip_empty_pages'] = array( + '#title' => t('Skip empty pages'), + '#type' => 'checkbox', + '#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.'), + '#default_value' => $this->options['skip_empty_pages'], + ); $form['date_argument']['#type'] = 'hidden'; $form['date_argument']['#value'] = $this->options['date_argument']; $form['granularity']['#type'] = 'hidden'; @@ -150,13 +157,7 @@ class date_views_plugin_pager extends views_plugin_pager { // Reset values set by argument if pager requires it. if (!empty($value)) { - $argument->argument = $value; - $argument->date_range = $argument->date_handler->arg_range($value); - $argument->min_date = $argument->date_range[0]; - $argument->max_date = $argument->date_range[1]; - // $argument->is_default works correctly for normal arguments, but does not - // work correctly if we are swapping in a new value from the pager. - $argument->is_default = FALSE; + $this->set_argument_value($argument, $value); } // The pager value might move us into a forbidden range, so test it. @@ -165,12 +166,102 @@ class date_views_plugin_pager extends views_plugin_pager { return; } + // Write date_info to store information to be used in the theming functions if (empty($this->view->date_info)) $this->view->date_info = new stdClass(); $this->view->date_info->granularity = $argument->date_handler->granularity; $format = $this->view->date_info->granularity == 'week' ? DATE_FORMAT_DATETIME : $argument->sql_format; $this->view->date_info->placeholders = isset($argument->placeholders) ? $argument->placeholders : $argument->date_handler->placeholders; $this->view->date_info->date_arg = $argument->argument; $this->view->date_info->date_arg_pos = $i; + $this->view->date_info->limit = $argument->limit; + $this->view->date_info->url = $this->view->get_url(); + $this->view->date_info->pager_id = $this->options['date_id']; + $this->view->date_info->date_pager_position = $this->options['pager_position']; + $this->view->date_info->date_pager_format = $this->options['link_format']; + $this->view->date_info->skip_empty_pages = $this->options['skip_empty_pages'] == 1; + + // Execute two additional queries to find the previous and next page with values + if ($this->view->date_info->skip_empty_pages) { + $q = clone $argument->query; + + $field = $argument->table_alias . '.' . $argument->real_field; + $fieldsql = $date_handler->sql_field($field); + $fieldsql = $date_handler->sql_format($format, $fieldsql); + $q->clear_fields(); + $q->orderby = array(); + $q->set_distinct(TRUE, TRUE); + + // Date limits of this argument + $datelimits = $argument->date_handler->arg_range($argument->limit[0] . '--' . $argument->limit[1]); + + // Find the first two dates between the minimum date and the upper bound of the current value + $q->add_orderby(NULL, $fieldsql, 'DESC', 'date'); + $this->set_argument_placeholders($this->view->date_info->placeholders, $datelimits[0], $argument->max_date, $q, $format); + + $compiledquery = $q->query(); + $compiledquery->range(0, 2); + $results = $compiledquery->execute()->fetchCol(0); + + $prevdate = array_shift($results); + $prevdatealt = array_shift($results); + + // Find the first two dates between the lower bound of the current value and the maximum date + $q->add_orderby(NULL, $fieldsql, 'ASC', 'date'); + $this->set_argument_placeholders($this->view->date_info->placeholders, $argument->min_date, $datelimits[1], $q, $format); + + $compiledquery = $q->query(); + $compiledquery->range(0, 2); + $results = $compiledquery->execute()->fetchCol(0); + + $nextdate = array_shift($results); + $nextdatealt = array_shift($results); + + // Set the default value of the query to $prevfirst or $nextfirst + // when there is no value and $prevsecond or $nextsecond is set. + if (empty($value)) { + // @todo find out which of $prevdate or $nextdate is closest to the + // default argument date value and choose that one. + if ($prevdate && $prevdatealt) { + $this->set_argument_value($argument, $prevdate); + $value = $prevdate; + $prevdate = $prevdatealt; + // If the first next date is the same as the first previous date, + // move to the following next date. + if ($value == $nextdate) { + $nextdate = $nextdatealt; + $nextdatealt = NULL; + } + } + elseif ($nextdate && $nextdatealt) { + $this->set_argument_value($argument, $nextdate); + $value = $nextdate; + $nextdate = $nextdatealt; + // If the first previous date is the same as the first next date, + // move to the following previous date. + if ($value == $prevdate) { + $prevdate = $prevdatealt; + $prevdatealt = NULL; + } + } + } + else { + // $prevdate and $nextdate are the same as $value, so move to + // the next values. + $prevdate = $prevdatealt; + $nextdate = $nextdatealt; + } + + $this->view->date_info->prev_date = $prevdate ? new DateObject($prevdate, NULL, $format) : NULL; + $this->view->date_info->next_date = $nextdate ? new DateObject($nextdate, NULL, $format) : NULL; + } + else { + $this->view->date_info->prev_date = clone($argument->min_date); + date_modify($this->view->date_info->prev_date, '-1 ' . $granularity); + $this->view->date_info->next_date = clone($argument->max_date); + date_modify($this->view->date_info->next_date, '+1 ' . $granularity); + } + + // Write the date_info properties that depend on the current value $this->view->date_info->year = date_format($argument->min_date, 'Y'); $this->view->date_info->month = date_format($argument->min_date, 'n');; $this->view->date_info->day = date_format($argument->min_date, 'j'); @@ -178,11 +269,6 @@ class date_views_plugin_pager extends views_plugin_pager { $this->view->date_info->date_range = $argument->date_range; $this->view->date_info->min_date = $argument->min_date; $this->view->date_info->max_date = $argument->max_date; - $this->view->date_info->limit = $argument->limit; - $this->view->date_info->url = $this->view->get_url(); - $this->view->date_info->pager_id = $this->options['date_id']; - $this->view->date_info->date_pager_position = $this->options['pager_position']; - $this->view->date_info->date_pager_format = $this->options['link_format']; } $i++; } @@ -191,20 +277,33 @@ class date_views_plugin_pager extends views_plugin_pager { // If there is pager input and the argument has set the placeholders, // swap the pager value in for the placeholder set by the argument. if (!empty($value) && !empty($this->view->date_info->placeholders)) { - $placeholders = $this->view->date_info->placeholders; - $count = count($placeholders); - foreach ($this->view->query->where as $group => $data) { - foreach ($data['conditions'] as $delta => $condition) { - if (array_key_exists('value', $condition) && is_array($condition['value'])) { - foreach ($condition['value'] as $placeholder => $placeholder_value) { - if (array_key_exists($placeholder, $placeholders)) { - // If we didn't get a match, this is a > $min < $max query that uses the view - // min and max dates as placeholders. - $date = ($count == 2) ? $this->view->date_info->min_date : $this->view->date_info->max_date; - $next_placeholder = array_shift($placeholders); - $this->view->query->where[$group]['conditions'][$delta]['value'][$placeholder] = $date->format($format); - $count--; - } + $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); + } + } + + function set_argument_value($argument, $value) { + $argument->argument = $value; + $argument->date_range = $argument->date_handler->arg_range($value); + $argument->min_date = $argument->date_range[0]; + $argument->max_date = $argument->date_range[1]; + // $argument->is_default works correctly for normal arguments, but does not + // work correctly if we are swapping in a new value from the pager. + $argument->is_default = FALSE; + } + + function set_argument_placeholders($placeholders, $mindate, $maxdate, $query, $format) { + $count = count($placeholders); + foreach ($query->where as $group => $data) { + foreach ($data['conditions'] as $delta => $condition) { + if (array_key_exists('value', $condition) && is_array($condition['value'])) { + foreach ($condition['value'] as $placeholder => $placeholder_value) { + if (array_key_exists($placeholder, $placeholders)) { + // If we didn't get a match, this is a > $min < $max query that uses the view + // min and max dates as placeholders. + $date = ($count == 2) ? $mindate : $maxdate; + $next_placeholder = array_shift($placeholders); + $query->where[$group]['conditions'][$delta]['value'][$placeholder] = $date->format($format); + $count--; } } } diff --git a/date_views/theme/theme.inc b/date_views/theme/theme.inc index 8c42a52..60f36d4 100644 --- a/date_views/theme/theme.inc +++ b/date_views/theme/theme.inc @@ -12,12 +12,12 @@ function date_views_preprocess_views_view(&$vars) { if (!empty($view->date_info) && !empty($view->date_info->date_pager_position)) { switch ($view->date_info->date_pager_position) { case 'top': - $vars['header'] .= $vars['pager']; - $vars['pager'] = ''; - break; + $vars['header'] .= $vars['pager']; + $vars['pager'] = ''; + break; case 'both': - $vars['header'] .= $vars['pager']; - break; + $vars['header'] .= $vars['pager']; + break; default: // Already on the bottom. } @@ -66,94 +66,103 @@ function template_preprocess_date_views_pager(&$vars) { } if (empty($date_info->hide_nav)) { - $prev_date = clone($min_date); - date_modify($prev_date, '-1 ' . $granularity); - $next_date = clone($min_date); - date_modify($next_date, '+1 ' . $granularity); - $format = array('year' => 'Y', 'month' => 'Y-m', 'day' => 'Y-m-d'); - switch ($granularity) { - case 'week': - $next_week = date_week(date_format($next_date, 'Y-m-d')); - $prev_week = date_week(date_format($prev_date, 'Y-m-d')); - $next_arg = date_format($next_date, 'o-\W') . date_pad($next_week); - $prev_arg = date_format($prev_date, 'o-\W') . date_pad($prev_week); - break; - default: - $next_arg = date_format($next_date, $format[$granularity]); - $prev_arg = date_format($prev_date, $format[$granularity]); - } - $next_path = str_replace($date_info->date_arg, $next_arg, $date_info->url); - $prev_path = str_replace($date_info->date_arg, $prev_arg, $date_info->url); - $next_args[$pos] = $next_arg; - $prev_args[$pos] = $prev_arg; - $vars['next_url'] = date_pager_url($view, NULL, $next_arg); - $vars['prev_url'] = date_pager_url($view, NULL, $prev_arg); - $vars['next_options'] = $vars['prev_options'] = array(); - } - else { - $next_path = ''; - $prev_path = ''; - $vars['next_url'] = ''; - $vars['prev_url'] = ''; - $vars['next_options'] = $vars['prev_options'] = array(); - } + $prev_date = $date_info->prev_date; + $next_date = $date_info->next_date; + + $format = array('year' => 'Y', 'month' => 'Y-m', 'day' => 'Y-m-d', 'hour' => 'Y-m-d\TH'); + if (!empty($prev_date)) { + switch ($granularity) { + case 'week': + $prev_week = date_week(date_format($prev_date, 'Y-m-d')); + $prev_arg = date_format($prev_date, 'Y-\W') . date_pad($prev_week); + break; + default: + $prev_arg = date_format($prev_date, $format[$granularity]); + } + $prev_path = str_replace($date_info->date_arg, $prev_arg, $date_info->url); + $prev_args[$pos] = $prev_arg; + $vars['prev_url'] = date_pager_url($view, NULL, $prev_arg); + } + if (!empty($next_date)) { + switch ($granularity) { + case 'week': + $next_week = date_week(date_format($next_date, 'Y-m-d')); + $next_arg = date_format($next_date, 'Y-\W') . date_pad($next_week); + break; + default: + $next_arg = date_format($next_date, $format[$granularity]); + } + $next_path = str_replace($date_info->date_arg, $next_arg, $date_info->url); + $next_args[$pos] = $next_arg; + $vars['next_url'] = date_pager_url($view, NULL, $next_arg); + } + + $vars['next_options'] = $vars['prev_options'] = array(); + } + else { + $next_path = ''; + $prev_path = ''; + $vars['next_url'] = ''; + $vars['prev_url'] = ''; + $vars['next_options'] = $vars['prev_options'] = array(); +} // Check whether navigation links would point to // a date outside the allowed range. - if (!empty($next_date) && !empty($vars['next_url']) && date_format($next_date, 'Y') > $date_info->limit[1]) { - $vars['next_url'] = ''; - } - if (!empty($prev_date) && !empty($vars['prev_url']) && date_format($prev_date, 'Y') < $date_info->limit[0]) { - $vars['prev_url'] = ''; - } - $vars['prev_options'] += array('attributes' => array()); - $vars['next_options'] += array('attributes' => array()); - $prev_title = ''; - $next_title = ''; +if (!empty($next_date) && !empty($vars['next_url']) && date_format($next_date, 'Y') > $date_info->limit[1]) { + $vars['next_url'] = ''; +} +if (!empty($prev_date) && !empty($vars['prev_url']) && date_format($prev_date, 'Y') < $date_info->limit[0]) { + $vars['prev_url'] = ''; +} +$vars['prev_options'] += array('attributes' => array()); +$vars['next_options'] += array('attributes' => array()); +$prev_title = ''; +$next_title = ''; // Build next/prev link titles. - switch ($granularity) { - case 'year': - $prev_title = t('Navigate to previous year'); - $next_title = t('Navigate to next year'); - break; - case 'month': - $prev_title = t('Navigate to previous month'); - $next_title = t('Navigate to next month'); - break; - case 'week': - $prev_title = t('Navigate to previous week'); - $next_title = t('Navigate to next week'); - break; - case 'day': - $prev_title = t('Navigate to previous day'); - $next_title = t('Navigate to next day'); - break; - } - $vars['prev_options']['attributes'] += array('title' => $prev_title); - $vars['next_options']['attributes'] += array('title' => $next_title); +switch ($granularity) { + case 'year': + $prev_title = t('Navigate to previous year'); + $next_title = t('Navigate to next year'); + break; + case 'month': + $prev_title = t('Navigate to previous month'); + $next_title = t('Navigate to next month'); + break; + case 'week': + $prev_title = t('Navigate to previous week'); + $next_title = t('Navigate to next week'); + break; + case 'day': + $prev_title = t('Navigate to previous day'); + $next_title = t('Navigate to next day'); + break; +} +$vars['prev_options']['attributes'] += array('title' => $prev_title); +$vars['next_options']['attributes'] += array('title' => $next_title); // Add nofollow for next/prev links. - $vars['prev_options']['attributes'] += array('rel' => 'nofollow'); - $vars['next_options']['attributes'] += array('rel' => 'nofollow'); +$vars['prev_options']['attributes'] += array('rel' => 'nofollow'); +$vars['next_options']['attributes'] += array('rel' => 'nofollow'); // Need this so we can use '«' or images in the links. - $vars['prev_options'] += array('html' => TRUE); - $vars['next_options'] += array('html' => TRUE); +$vars['prev_options'] += array('html' => TRUE); +$vars['next_options'] += array('html' => TRUE); - $link = FALSE; +$link = FALSE; // Month navigation titles are used as links in the block view. - if (!empty($date_info->mini) && $granularity == 'month') { - $link = TRUE; - } - $params = array( - 'granularity' => $granularity, - 'view' => $view, - 'link' => $link, +if (!empty($date_info->mini) && $granularity == 'month') { + $link = TRUE; +} +$params = array( + 'granularity' => $granularity, + 'view' => $view, + 'link' => $link, ); - $nav_title = theme('date_nav_title', $params); - $vars['nav_title'] = $nav_title; - $vars['mini'] = !empty($date_info->mini); +$nav_title = theme('date_nav_title', $params); +$vars['nav_title'] = $nav_title; +$vars['mini'] = !empty($date_info->mini); } /** @@ -169,24 +178,24 @@ function theme_date_nav_title($params) { $format_without_year = variable_get('date_views_' . $granularity . 'format_without_year', 'l, F j'); switch ($granularity) { case 'year': - $title = $date_info->year; - $date_arg = $date_info->year; - break; + $title = $date_info->year; + $date_arg = $date_info->year; + break; case 'month': - $format = !empty($format) ? $format : (empty($date_info->mini) ? $format_with_year : $format_without_year); - $title = date_format_date($date_info->min_date, 'custom', $format); - $date_arg = $date_info->year . '-' . date_pad($date_info->month); - break; + $format = !empty($format) ? $format : (empty($date_info->mini) ? $format_with_year : $format_without_year); + $title = date_format_date($date_info->min_date, 'custom', $format); + $date_arg = $date_info->year . '-' . date_pad($date_info->month); + break; case 'day': - $format = !empty($format) ? $format : (empty($date_info->mini) ? $format_with_year : $format_without_year); - $title = date_format_date($date_info->min_date, 'custom', $format); - $date_arg = $date_info->year . '-' . date_pad($date_info->month) . '-' . date_pad($date_info->day); - break; + $format = !empty($format) ? $format : (empty($date_info->mini) ? $format_with_year : $format_without_year); + $title = date_format_date($date_info->min_date, 'custom', $format); + $date_arg = $date_info->year . '-' . date_pad($date_info->month) . '-' . date_pad($date_info->day); + break; case 'week': - $format = !empty($format) ? $format : (empty($date_info->mini) ? $format_with_year : $format_without_year); - $title = t('Week of @date', array('@date' => date_format_date($date_info->min_date, 'custom', $format))); - $date_arg = $date_info->year . '-W' . date_pad($date_info->week); - break; + $format = !empty($format) ? $format : (empty($date_info->mini) ? $format_with_year : $format_without_year); + $title = t('Week of @date', array('@date' => date_format_date($date_info->min_date, 'custom', $format))); + $date_arg = $date_info->year . '-W' . date_pad($date_info->week); + break; } if (!empty($date_info->mini) || $link) { // Month navigation titles are used as links in the mini view. @@ -211,4 +220,4 @@ function template_preprocess_date_views_filter_form(&$vars) { $vars['minadjustment'] = drupal_render($form['minadjustment']); $vars['maxadjustment'] = drupal_render($form['maxadjustment']); $vars['description'] = drupal_render($form['description']) . drupal_render($form); -} +} \ No newline at end of file -- 1.9.1