summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Wehner2010-02-06 13:29:48 (GMT)
committerDaniel Wehner2010-02-06 13:29:48 (GMT)
commitb7ace8621300df98ad51bb7862e974f18ebd0506 (patch)
treeafda621ff3a29be9e946a6fa697aa4c4b2cd78ad
parent4007ecf599514500cf396961a4e7fb5043a231ee (diff)
#586668: Pagers turned into plugins to allow all kinds of new fun stuff with paging.
#652712 by dagmar: Some pager settings were not getting properly stored with pluggable pagers.
-rw-r--r--CHANGELOG.txt2
-rw-r--r--handlers/views_handler_field_counter.inc6
-rw-r--r--includes/plugins.inc36
-rw-r--r--includes/view.inc47
-rw-r--r--plugins/views_plugin_cache.inc6
-rw-r--r--plugins/views_plugin_display.inc266
-rw-r--r--plugins/views_plugin_exposed_form.inc13
-rw-r--r--plugins/views_plugin_pager.inc173
-rw-r--r--plugins/views_plugin_pager_full.inc119
-rw-r--r--plugins/views_plugin_pager_mini.inc22
-rw-r--r--plugins/views_plugin_pager_none.inc62
-rw-r--r--plugins/views_plugin_pager_some.inc56
-rw-r--r--plugins/views_plugin_query.inc37
-rw-r--r--plugins/views_plugin_query_default.inc63
-rw-r--r--tests/views_pager.test212
-rw-r--r--theme/theme.inc15
-rw-r--r--views.info5
17 files changed, 941 insertions, 199 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 97c8b3c..14e0fd3 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -79,6 +79,8 @@ Views 3.x-7.x-dev
o #627402 by dereine: Aggregator description needed more controllable input filtering.
o #699200 by xgretsch: Non-static functions cause strict warning messages.
o #705668 by dereine: Fix glossary view, add tests for glossary view.
+ o #586668: Pagers turned into plugins to allow all kinds of new fun stuff with paging.
+ o #652712 by dagmar: Some pager settings were not getting properly stored with pluggable pagers.
Views 6.x-3.x-dev
o #396380 by merlinofchaos, dereine and dagmar: Initial support for GROUP BY queries!!!!!!!!!!!!
diff --git a/handlers/views_handler_field_counter.inc b/handlers/views_handler_field_counter.inc
index 01575c1..54b5995 100644
--- a/handlers/views_handler_field_counter.inc
+++ b/handlers/views_handler_field_counter.inc
@@ -29,10 +29,10 @@ class views_handler_field_counter extends views_handler_field {
// Note: 1 is subtracted from the counter start value below because the
// counter value is incremented by 1 at the end of this function.
$count = is_numeric($this->options['counter_start']) ? $this->options['counter_start'] - 1 : 0;
- $pager = $this->view->pager;
+ $pager = $this->view->query->pager;
// Get the base count of the pager.
- if ($pager['use_pager']) {
- $count += ($pager['items_per_page'] * $pager['current_page']) + $pager['offset'];
+ if ($pager->use_pager()) {
+ $count += ($pager->get_items_per_page() * $pager->get_current_page() + $pager->get_offset());
}
// Add the counter for the current site.
$count += $this->view->row_index + 1;
diff --git a/includes/plugins.inc b/includes/plugins.inc
index 468af3e..20769dc 100644
--- a/includes/plugins.inc
+++ b/includes/plugins.inc
@@ -259,6 +259,42 @@ function views_views_plugins() {
'help topic' => 'exposed-form-input-required',
),
),
+ 'pager' => array(
+ 'parent' => array(
+ 'no ui' => TRUE,
+ 'handler' => 'views_plugin_pager',
+ 'parent' => '',
+ ),
+ 'none' => array(
+ 'title' => t('Display all items'),
+ 'help' => t("Display all items that this view might find"),
+ 'handler' => 'views_plugin_pager_none',
+ 'help topic' => 'pager-none',
+ 'uses options' => TRUE,
+ ),
+ 'some' => array(
+ 'title' => t('Display a specified number of items'),
+ 'help' => t('Display a limited number items that this view might find.'),
+ 'handler' => 'views_plugin_pager_some',
+ 'help topic' => 'pager-some',
+ 'uses options' => TRUE,
+ ),
+ 'full' => array(
+ 'title' => t('Paged output, full pager'),
+ 'help' => t('Paged output, full Drupal style'),
+ 'handler' => 'views_plugin_pager_full',
+ 'help topic' => 'pager-full',
+ 'uses options' => TRUE,
+ ),
+ 'mini' => array(
+ 'title' => t('Paged output, mini pager'),
+ 'help' => t('Use the mini pager output.'),
+ 'handler' => 'views_plugin_pager_mini',
+ 'help topic' => 'pager-mini',
+ 'uses options' => TRUE,
+ 'parent' => 'full',
+ ),
+ ),
);
}
diff --git a/includes/view.inc b/includes/view.inc
index e1f2af2..e229c3a 100644
--- a/includes/view.inc
+++ b/includes/view.inc
@@ -32,14 +32,8 @@ class view extends views_db_object {
// Where the results of a query will go.
var $result = array();
- // pager variables
- var $pager = array(
- 'use_pager' => FALSE,
- 'items_per_page' => 10,
- 'element' => 0,
- 'offset' => 0,
- 'current_page' => 0,
- );
+ // May be used to override the current page number.
+ var $current_page = NULL;
// Places to put attached renderings:
var $attachment_before = '';
@@ -94,42 +88,37 @@ class view extends views_db_object {
}
/**
- * Set the page size for ranged or pager queries
- */
- function set_items_per_page($items_per_page) {
- $this->pager['items_per_page'] = $items_per_page;
- if (empty($items_per_page)) {
- $this->pager['use_pager'] = FALSE;
- }
- }
-
- /**
* Change/Set the current page for the pager.
*/
function set_current_page($page) {
- $this->pager['current_page'] = $page;
+ $this->current_page = $page;
}
/**
- * Whether or not the pager should be used.
+ * Get the current page from the pager.
*/
- function set_use_pager($use_pager) {
- $this->pager['use_pager'] = $use_pager;
+ function get_current_page() {
+ if (!empty($this->query->pager)) {
+ return $this->query->pager->get_current_page();
+ }
}
/**
- * The pager element id to use if use_apger is on
+ * Get the items per page from the pager.
*/
- function set_pager_element($pager_element) {
- $this->pager['element'] = $pager_element;
+ function get_items_per_page() {
+ if (!empty($this->query->pager)) {
+ return $this->query->pager->get_items_per_page();
+ }
}
/**
- * How many records to skip. This does not function if use_pager is
- * set.
+ * Get the pager offset from the pager.
*/
- function set_offset($offset) {
- $this->pager['offset'] = $offset;
+ function get_offset() {
+ if (!empty($this->query->pager)) {
+ return $this->query->pager->get_offset();
+ }
}
/**
diff --git a/plugins/views_plugin_cache.inc b/plugins/views_plugin_cache.inc
index 9031f98..4085b3c 100644
--- a/plugins/views_plugin_cache.inc
+++ b/plugins/views_plugin_cache.inc
@@ -68,7 +68,7 @@ class views_plugin_cache extends views_plugin {
$data = array(
'result' => $this->view->result,
'total_rows' => isset($this->view->total_rows) ? $this->view->total_rows : 0,
- 'pager' => $this->view->pager,
+ 'current_page' => $this->view->get_current_page(),
);
cache_set($this->get_results_key(), $data, $this->table);
break;
@@ -94,12 +94,12 @@ class views_plugin_cache extends views_plugin {
return FALSE;
case 'results':
// Values to set: $view->result, $view->total_rows, $view->execute_time,
- // $view->pager['current_page'].
+ // $view->current_page.
if ($cache = cache_get($this->get_results_key(), $this->table)) {
if (!$cutoff || $cache->created > $cutoff) {
$this->view->result = $cache->data['result'];
$this->view->total_rows = $cache->data['total_rows'];
- $this->view->pager = $cache->data['pager'];
+ $this->view->set_current_page = $cache->data['current_page'];
$this->view->execute_time = 0;
return TRUE;
}
diff --git a/plugins/views_plugin_display.inc b/plugins/views_plugin_display.inc
index d5e8536..3ba406a 100644
--- a/plugins/views_plugin_display.inc
+++ b/plugins/views_plugin_display.inc
@@ -41,6 +41,44 @@ class views_plugin_display extends views_plugin {
}
$this->unpack_options($this->options, $options);
+
+ // Translate changed settings:
+ // Check if any of the previous values now managed by
+ // pluggable pagers have been changed.
+ // If yes, perform the conversion
+ $items_per_page = $this->get_option('items_per_page');
+ $offset = $this->get_option('offset');
+ $type = $this->get_option('use_pager');
+ if ((!empty($items_per_page) && $items_per_page != 10) || !empty($offset) || !empty($type)) {
+ if (!$type) {
+ $type = $items_per_page ? 'some' : 'none';
+ }
+
+ if ($type == 1) {
+ $type = 'full';
+ }
+
+ $pager = array(
+ 'type' => $type,
+ 'options' => array(
+ 'offset' => $offset
+ ),
+ );
+
+ if ($items_per_page) {
+ $pager['options']['items_per_page'] = $items_per_page;
+ }
+ if ($id = $this->get_option('pager_element')) {
+ $pager['options']['id'] = $id;
+ }
+
+ // Unset the previous options
+ // After edit and save the view they will be erased
+ $this->set_option('items_per_page', NULL);
+ $this->set_option('offset', NULL);
+ $this->set_option('use_pager', NULL);
+ $this->set_option('pager', $pager);
+ }
}
function destroy() {
@@ -113,17 +151,10 @@ class views_plugin_display extends views_plugin {
* Does the display have a pager enabled?
*/
function use_pager() {
- if (!empty($this->definition['use pager'])) {
- return $this->get_option('use_pager');
+ $pager = $this->get_plugin('pager');
+ if ($pager) {
+ return $pager->use_pager();
}
- return FALSE;
- }
-
- /**
- * Does the display render the pager if it has it enabled?
- */
- function render_pager() {
- return $this->use_pager();
}
/**
@@ -189,7 +220,7 @@ class views_plugin_display extends views_plugin {
'empty' => array('empty', 'empty_format'),
'use_ajax' => array('use_ajax'),
'items_per_page' => array('items_per_page', 'offset', 'use_pager', 'pager_element'),
- 'use_pager' => array('items_per_page', 'offset', 'use_pager', 'pager_element'),
+ 'pager' => array('pager'),
'use_more' => array('use_more', 'use_more_always', 'use_more_text'),
'link_display' => array('link_display'),
'distinct' => array('distinct'),
@@ -261,9 +292,9 @@ class views_plugin_display extends views_plugin {
'use_ajax' => TRUE,
'items_per_page' => TRUE,
- 'offset' => TRUE,
'use_pager' => TRUE,
- 'pager_element' => TRUE,
+ 'offset' => TRUE,
+ 'pager' => TRUE,
'use_more' => TRUE,
'use_more_always' => TRUE,
'use_more_text' => TRUE,
@@ -333,9 +364,6 @@ class views_plugin_display extends views_plugin {
'default' => FALSE,
'bool' => TRUE,
),
- 'pager_element' => array(
- 'default' => 0,
- ),
'use_more' => array(
'default' => FALSE,
'bool' => TRUE,
@@ -384,6 +412,12 @@ class views_plugin_display extends views_plugin {
'options' => array('default' => array(), 'export' => FALSE),
),
),
+ 'pager' => array(
+ 'contains' => array(
+ 'type' => array('default' => 'none', 'export' => 'export_plugin'),
+ 'options' => array('default' => array(), 'export' => FALSE),
+ ),
+ ),
// Note that the styles have their options completely independent.
// Like access and cache above, this is a legacy pattern and
@@ -544,35 +578,42 @@ class views_plugin_display extends views_plugin {
* Get the display or row plugin, if it exists.
*/
function get_plugin($type = 'style', $name = NULL) {
- switch ($type) {
- case 'style':
- case 'row':
- $option_name = $type . '_plugin';
- $options = $this->get_option($type . '_options');
- if (!$name) {
- $name = $this->get_option($option_name);
- }
+ static $cache = array();
+ if (!isset($cache[$type][$name])) {
+ switch ($type) {
+ case 'style':
+ case 'row':
+ $option_name = $type . '_plugin';
+ $options = $this->get_option($type . '_options');
+ if (!$name) {
+ $name = $this->get_option($option_name);
+ }
- break;
- default:
- $option_name = $type;
- $options = $this->get_option($type);
- if (!$name) {
- $name = $options['type'];
- }
+ break;
+ default:
+ $option_name = $type;
+ $options = $this->get_option($type);
+ if (!$name) {
+ $name = $options['type'];
+ }
- // access & cache store their options as siblings with the
- // type; all others use an 'options' array.
- if ($type != 'access' && $type != 'cache') {
- $options = $options['options'];
- }
- }
+ // access & cache store their options as siblings with the
+ // type; all others use an 'options' array.
+ if ($type != 'access' && $type != 'cache') {
+ $options = $options['options'];
+ }
+ }
+
+ $plugin = views_get_plugin($type, $name);
+ if (!$plugin) {
+ return;
+ }
- $plugin = views_get_plugin($type, $name);
- if ($plugin) {
$plugin->init($this->view, $this->display, $options);
- return $plugin;
+ $cache[$type][$name] = $plugin;
}
+
+ return $cache[$type][$name];
}
/**
@@ -765,21 +806,26 @@ class views_plugin_display extends views_plugin {
}
if (!empty($this->definition['use pager'])) {
- $options['use_pager'] = array(
+
+ $pager_plugin = $this->get_plugin('pager');
+ if (!$pager_plugin) {
+ // default to the no pager plugin.
+ $pager_plugin = views_get_plugin('pager', 'none');
+ }
+
+ $pager_str = $pager_plugin->summary_title();
+
+ $options['pager'] = array(
'category' => 'basic',
'title' => t('Use pager'),
- 'value' => $this->get_option('use_pager') ? ($this->get_option('use_pager') === 'mini' ? t('Mini') : t('Yes')) : t('No'),
+ 'value' => $pager_str,
'desc' => t("Change this display's pager setting."),
);
}
- $items = intval($this->get_option('items_per_page'));
- $options['items_per_page'] = array(
- 'category' => 'basic',
- 'title' => $this->use_pager() ? t('Items per page') : t('Items to display'),
- 'value' => $items ? $items : t('Unlimited'),
- 'desc' => t('Change how many items to display.'),
- );
+ if (!empty($pager_plugin->definition['uses options'])) {
+ $options['pager']['links']['pager_options'] = t('Change settings for this pager type.');
+ }
if (!empty($this->definition['use more'])) {
$options['use_more'] = array(
@@ -845,6 +891,10 @@ class views_plugin_display extends views_plugin {
$options['cache']['links']['cache_options'] = t('Change settings for this caching type.');
}
+ if (!empty($access_plugin->definition['uses options'])) {
+ $options['access']['links']['access_options'] = t('Change settings for this access type.');
+ }
+
if ($this->uses_link_display()) {
// Only show the 'link display' if there is more than one option.
$count = 0;
@@ -988,35 +1038,6 @@ class views_plugin_display extends views_plugin {
'#default_value' => $this->get_option('use_ajax') ? 1 : 0,
);
break;
- case 'use_pager':
- $form['#title'] .= t('Use a pager for this view');
- $form['use_pager'] = array(
- '#type' => 'radios',
- '#options' => array(TRUE => t('Full pager'), 'mini' => t('Mini pager'), 0 => t('No')),
- '#default_value' => $this->get_option('use_pager'),
- );
- $form['pager_element'] = array(
- '#type' => 'textfield',
- '#title' => t('Pager element'),
- '#description' => t("Unless you're experiencing problems with pagers related to this view, you should leave this at 0. If using multiple pagers on one page you may need to set this number to a higher value so as not to conflict within the ?page= array. Large values will add a lot of commas to your URLs, so avoid if possible."),
- '#default_value' => intval($this->get_option('pager_element')),
- );
- break;
- case 'items_per_page':
- $form['#title'] .= $this->use_pager() ? t('Items per page') : t('Items to display');
-
- $form['items_per_page'] = array(
- '#type' => 'textfield',
- '#description' => t('The number of items to display per page. Enter 0 for no limit.'),
- '#default_value' => intval($this->get_option('items_per_page')),
- );
- $form['offset'] = array(
- '#type' => 'textfield',
- '#title' => t('Offset'),
- '#description' => t('The number of items to skip. For example, if this field is 3, the first 3 items will be skipped and not displayed. Offset can not be used if items to display is 0; instead use a very large number there.'),
- '#default_value' => intval($this->get_option('offset')),
- );
- break;
case 'use_more':
$form['#title'] .= t('Add a more link to the bottom of the display.');
$form['use_more'] = array(
@@ -1513,7 +1534,45 @@ class views_plugin_display extends views_plugin {
$plugin->options_form($form['exposed_form_options'], $form_state);
}
break;
+ case 'pager':
+ $form['#title'] .= t('Select which pager, if any, to use for this view');
+ $form['pager'] = array(
+ '#prefix' => '<div class="clear-block">',
+ '#suffix' => '</div>',
+ '#tree' => TRUE,
+ );
+
+ $pager = $this->get_option('pager');
+ $form['pager']['type'] = array(
+ '#type' => 'radios',
+ '#options' => views_fetch_plugin_names('pager'),
+ '#default_value' => $pager['type'],
+ );
+
+ $pager_plugin = views_fetch_plugin_data('pager', $pager['type']);
+ if (!empty($pager_plugin['uses options'])) {
+ $form['markup'] = array(
+ '#prefix' => '<div class="form-item description">',
+ '#suffix' => '</div>',
+ '#value' => t('You may also adjust the !settings for the currently selected pager by clicking on the icon.', array('!settings' => $this->option_link(t('settings'), 'pager_options'))),
+ );
+ }
+
+ break;
+ case 'pager_options':
+ $plugin = $this->get_plugin('pager');
+ $form['#title'] .= t('Pager options');
+ if ($plugin) {
+ $form['#help_topic'] = $plugin->definition['help topic'];
+
+ $form['pager_options'] = array(
+ '#tree' => TRUE,
+ );
+ $plugin->options_form($form['pager_options'], $form_state);
+ }
+ break;
}
+
}
/**
@@ -1594,6 +1653,12 @@ class views_plugin_display extends views_plugin {
$plugin->options_validate($form['exposed_form_options'], $form_state);
}
break;
+ case 'pager_options':
+ $plugin = $this->get_plugin('pager');
+ if ($plugin) {
+ $plugin->options_validate($form['pager_options'], $form_state);
+ }
+ break;
}
}
@@ -1664,17 +1729,6 @@ class views_plugin_display extends views_plugin {
case 'link_display':
$this->set_option($section, $form_state['values'][$section]);
break;
- case 'use_ajax':
- $this->set_option($section, (bool)$form_state['values'][$section]);
- break;
- case 'use_pager':
- $this->set_option($section, $form_state['values'][$section]);
- $this->set_option('pager_element', intval($form_state['values']['pager_element']));
- break;
- case 'items_per_page':
- $this->set_option($section, intval($form_state['values'][$section]));
- $this->set_option('offset', intval($form_state['values']['offset']));
- break;
case 'use_more':
$this->set_option($section, intval($form_state['values'][$section]));
$this->set_option('use_more_always', intval($form_state['values']['use_more_always']));
@@ -1761,6 +1815,33 @@ class views_plugin_display extends views_plugin {
$this->set_option('exposed_form', $exposed_form);
}
break;
+ case 'pager':
+ $pager = $this->get_option('pager');
+ if ($pager['type'] != $form_state['values']['pager']['type']) {
+ $plugin = views_get_plugin('pager', $form_state['values']['pager']['type']);
+ if ($plugin) {
+ // Because pagers have very similar options, let's allow pagers to
+ // try to carry the options over.
+ $plugin->init($this->view, $this->display, $pager['options']);
+
+ $pager = array('type' => $form_state['values']['pager']['type'], 'options' => $plugin->options);
+ $this->set_option('pager', $pager);
+ if (!empty($plugin->definition['uses options'])) {
+ views_ui_add_form_to_stack('display', $this->view, $this->display->id, array('pager_options'));
+ }
+ }
+ }
+
+ break;
+ case 'pager_options':
+ $plugin = $this->get_plugin('pager');
+ if ($plugin) {
+ $pager = $this->get_option('pager');
+ $plugin->options_submit($form['pager_options'], $form_state);
+ $pager['options'] = $form_state['values'][$section];
+ $this->set_option('pager', $pager);
+ }
+ break;
}
}
@@ -1868,7 +1949,7 @@ class views_plugin_display extends views_plugin {
* Render the 'more' link
*/
function render_more_link() {
- if ($this->use_more() && ($this->view->total_rows > $this->view->pager['items_per_page'] || $this->use_more_always())) {
+ if ($this->use_more() && ($this->use_more_always() || $this->view->query->pager->has_more_records())) {
$path = $this->get_path();
if ($path) {
$path = $this->view->get_url(NULL, $path);
@@ -1979,11 +2060,6 @@ class views_plugin_display extends views_plugin {
*/
function pre_execute() {
$this->view->set_use_ajax($this->use_ajax());
- // Copy pager information from the display.
- $this->view->set_use_pager($this->use_pager());
- $this->view->set_pager_element($this->get_option('pager_element'));
- $this->view->set_items_per_page($this->get_option('items_per_page'));
- $this->view->set_offset($this->get_option('offset'));
if ($this->use_more()) {
$this->view->get_total_rows = TRUE;
}
diff --git a/plugins/views_plugin_exposed_form.inc b/plugins/views_plugin_exposed_form.inc
index 3f64dae..8e8b31a 100644
--- a/plugins/views_plugin_exposed_form.inc
+++ b/plugins/views_plugin_exposed_form.inc
@@ -14,12 +14,11 @@ class views_plugin_exposed_form extends views_plugin {
* @param $display
* The display handler.
*/
- function init(&$view, &$display) {
+ function init(&$view, &$display, $options = array()) {
$this->view = &$view;
$this->display = &$display;
- $exposed_form = $display->handler->get_option('exposed_form');
- $this->unpack_options($this->options, $exposed_form['options']);
+ $this->unpack_options($this->options, $options);
}
/**
@@ -108,9 +107,9 @@ class views_plugin_exposed_form extends views_plugin {
);
}
}
-
+
function exposed_form_validate(&$form, &$form_state) { }
-
+
/**
* This function is executed when exposed form is submited.
*
@@ -119,9 +118,9 @@ class views_plugin_exposed_form extends views_plugin {
* @param $form_state
* A keyed array containing the current state of the form.
* @param $exclude
- * Nested array of keys to exclude of insert into
+ * Nested array of keys to exclude of insert into
* $view->exposed_raw_input
- */
+ */
function exposed_form_submit(&$form, &$form_state, &$exclude) {
if (isset($form_state['values']['op']) && $form_state['values']['op'] == t('Reset')) {
$this->reset_form($form, $form_state);
diff --git a/plugins/views_plugin_pager.inc b/plugins/views_plugin_pager.inc
new file mode 100644
index 0000000..03492b5
--- /dev/null
+++ b/plugins/views_plugin_pager.inc
@@ -0,0 +1,173 @@
+<?php
+// $Id$
+
+/**
+ * The base plugin to handle pager.
+ *
+ * @ingroup views_pager_plugins
+ */
+class views_plugin_pager extends views_plugin {
+ var $current_page = NULL;
+ var $total_items = 0;
+
+ /**
+ * Initialize the plugin.
+ *
+ * @param $view
+ * The view object.
+ * @param $display
+ * The display handler.
+ */
+ function init(&$view, &$display, $options = array()) {
+ $this->view = &$view;
+ $this->display = &$display;
+
+ $this->unpack_options($this->options, $options);
+ }
+
+ /**
+ * Get how many items per page this pager will display.
+ *
+ * All but the leanest pagers should probably return a value here, so
+ * most pagers will not need to override this method.
+ */
+ function get_items_per_page() {
+ return isset($this->options['items_per_page']) ? $this->options['items_per_page'] : 0;
+ }
+
+ /**
+ * Get the page offset, or how many items to skip.
+ *
+ * Even pagers that don't actually page can skip items at the beginning,
+ * so few pagers will need to override this method.
+ */
+ function get_offset() {
+ return isset($this->options['offset']) ? $this->options['offset'] : 0;
+ }
+
+ /**
+ * Get the current page.
+ *
+ * If NULL, we do not know what the current page is.
+ */
+ function get_current_page() {
+ return $this->current_page;
+ }
+
+ /**
+ * Set the current page.
+ *
+ * @param $number
+ * If provided, the page number will be set to this. If NOT provided,
+ * the page number will be set from the global page array.
+ */
+ function set_current_page($number = NULL) {
+ $this->current_page = $number;
+ }
+
+ /**
+ * Get the total number of items.
+ *
+ * If NULL, we do not yet know what the total number of items are.
+ */
+ function get_total_items() {
+ return $this->total_items;
+ }
+
+ /**
+ * Provide the default form form for validating options
+ */
+ function options_validate(&$form, &$form_state) { }
+
+ /**
+ * Provide the default form form for submitting options
+ */
+ function options_submit(&$form, &$form_state) { }
+
+ /**
+ * Return a string to display as the clickable title for the
+ * pager plugin.
+ */
+ function summary_title() {
+ return t('Unknown');
+ }
+
+ /**
+ * Determine if this pager actually uses a pager.
+ *
+ * Only a couple of very specific pagers will set this to false.
+ */
+ function use_pager() {
+ return TRUE;
+ }
+
+ /**
+ * Determine if a pager needs a count query.
+ *
+ * If a pager needs a count query, a simple query
+ */
+ function use_count_query() {
+ return TRUE;
+ }
+
+ /**
+ * Execute the count query, which will be done just prior to the query
+ * itself being executed.
+ */
+ function execute_count_query(&$count_query) {
+ $this->total_items = $count_query->execute();
+ if (!empty($this->options['offset'])) {
+ $this->total_items -= $this->options['offset'];
+ }
+
+ $this->update_page_info();
+ return $this->total_items;
+ }
+
+ /**
+ * If there are pagers that need global values set, this method can
+ * be used to set them. It will be called when the count query is run.
+ */
+ function update_page_info() {
+
+ }
+
+ /**
+ * Modify the query for paging
+ *
+ * This is called during the build phase and can directly modify the query.
+ */
+ function query() { }
+
+ /**
+ * Perform any needed actions just prior to the query executing.
+ */
+ function pre_execute(&$query) { }
+
+ /**
+ * Perform any needed actions just after the query executing.
+ */
+ function post_execute(&$result) { }
+
+ /**
+ * Render the pager.
+ *
+ * Called during the view render process, this will render the
+ * pager.
+ *
+ * @param $input
+ * Any extra GET parameters that should be retained, such as exposed
+ * input.
+ */
+ function render($input) { }
+
+ /**
+ * Determine if there are more records available.
+ *
+ * This is primarily used to control the display of a more link.
+ */
+ function has_more_records() {
+ return $this->get_items_per_page()
+ && $this->total_items > (intval($this->current_page) + 1) * $this->get_items_per_page();
+ }
+}
diff --git a/plugins/views_plugin_pager_full.inc b/plugins/views_plugin_pager_full.inc
new file mode 100644
index 0000000..60c66ad
--- /dev/null
+++ b/plugins/views_plugin_pager_full.inc
@@ -0,0 +1,119 @@
+<?php
+// $Id$
+
+/**
+ * The plugin to handle full pager.
+ *
+ * @ingroup views_pager_plugins
+ */
+class views_plugin_pager_full extends views_plugin_pager {
+ function summary_title() {
+ if (!empty($this->options['offset'])) {
+ return format_plural($this->options['items_per_page'], 'Paged, @count item, skip @skip', 'Paged, @count items, skip @skip', array('@count' => $this->options['items_per_page'], '@skip' => $this->options['offset']));
+ }
+ return format_plural($this->options['items_per_page'], 'Paged, @count item', 'Paged, @count items', array('@count' => $this->options['items_per_page']));
+ }
+
+ function option_definition() {
+ $options = parent::option_definition();
+ $options['items_per_page'] = array('default' => 10);
+ $options['offset'] = array('default' => 0);
+ $options['id'] = array('default' => 0);
+
+ return $options;
+ }
+
+ /**
+ * Provide the default form for setting options.
+ */
+ function options_form(&$form, &$form_state) {
+ $form['items_per_page'] = array(
+ '#title' => t('Items per page'),
+ '#type' => 'textfield',
+ '#description' => t('The number of items to display per page. Enter 0 for no limit.'),
+ '#default_value' => $this->options['items_per_page'],
+ );
+
+ $form['offset'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Offset'),
+ '#description' => t('The number of items to skip. For example, if this field is 3, the first 3 items will be skipped and not displayed.'),
+ '#default_value' => $this->options['offset'],
+ );
+
+ $form['id'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Pager ID'),
+ '#description' => t("Unless you're experiencing problems with pagers related to this view, you should leave this at 0. If using multiple pagers on one page you may need to set this number to a higher value so as not to conflict within the ?page= array. Large values will add a lot of commas to your URLs, so avoid if possible."),
+ '#default_value' => $this->options['id'],
+ );
+ }
+
+ function query() {
+ $this->view->query->set_limit($this->options['items_per_page']);
+ $this->view->query->set_offset($this->current_page * $this->options['items_per_page'] + $this->options['offset']);
+ }
+
+ function render($input) {
+ $pager_theme = views_theme_functions('pager', $this->view, $this->display);
+ $output = theme($pager_theme, array(
+ 'tags' => $input, 'quantity' => $this->options['items_per_page'], 'element' => $this->options['id']));
+ return $output;
+ }
+
+ /**
+ * Set the current page.
+ *
+ * @param $number
+ * If provided, the page number will be set to this. If NOT provided,
+ * the page number will be set from the global page array.
+ */
+ function set_current_page($number = NULL) {
+ if (isset($number)) {
+ $this->current_page = $number;
+ return;
+ }
+
+ // If the current page number was not prespecified, default to pulling it from 'page'
+ // based upon
+ global $pager_page_array;
+ // Extract the ['page'] info.
+ $pager_page_array = isset($_GET['page']) ? explode(',', $_GET['page']) : array();
+
+ $this->current_page = 0;
+ if (!empty($pager_page_array[$this->options['id']])) {
+ $this->current_page = intval($pager_page_array[$this->options['id']]);
+ }
+ }
+
+ /**
+ * Update global paging info.
+ *
+ * This is called after the count query has been run to set the total
+ * items available and to update the current page if the requested
+ * page is out of range.
+ */
+ function update_page_info() {
+ // Dump information about what we already know into the globals.
+ global $pager_page_array, $pager_total, $pager_total_items;
+
+ // Set the item count for the pager.
+ $pager_total_items[$this->options['id']] = $this->total_items;
+ // Calculate and set the count of available pages.
+ $pager_total[$this->options['id']] = ceil($pager_total_items[$this->options['id']] / $this->get_items_per_page());
+
+ // See if the requested page was within range:
+ if ($this->current_page < 0) {
+ $this->current_page = 0;
+ }
+ else if ($this->current_page >= $pager_total[$this->options['id']]) {
+ // Pages are numbered from 0 so if there are 10 pages, the last page is 9.
+ $this->current_page = $pager_total[$this->options['id']] - 1;
+ }
+
+ // Put this number in to guarantee that we do not generate notices when the pager
+ // goes to look for it later.
+ $pager_page_array[$this->options['id']] = $this->current_page;
+ }
+
+}
diff --git a/plugins/views_plugin_pager_mini.inc b/plugins/views_plugin_pager_mini.inc
new file mode 100644
index 0000000..30ee9e8
--- /dev/null
+++ b/plugins/views_plugin_pager_mini.inc
@@ -0,0 +1,22 @@
+<?php
+// $Id$
+
+/**
+ * The plugin to handle full pager.
+ *
+ * @ingroup views_pager_plugins
+ */
+class views_plugin_pager_mini extends views_plugin_pager_full {
+ function summary_title() {
+ if (!empty($this->options['offset'])) {
+ return format_plural($this->options['items_per_page'], 'Mini pager, @count item, skip @skip', 'Mini pager, @count items, skip @skip', array('@count' => $this->options['items_per_page'], '@skip' => $this->options['offset']));
+ }
+ return format_plural($this->options['items_per_page'], 'Mini pager, @count item', 'Mini pager, @count items', array('@count' => $this->options['items_per_page']));
+ }
+
+ function render($input) {
+ $pager_theme = views_theme_functions('views_mini_pager', $this->view, $this->display);
+ return theme($pager_theme, array(
+ 'tags' => $input, 'quantity' => $this->options['items_per_page'], 'element' => $this->options['id']));
+ }
+}
diff --git a/plugins/views_plugin_pager_none.inc b/plugins/views_plugin_pager_none.inc
new file mode 100644
index 0000000..3984e4d
--- /dev/null
+++ b/plugins/views_plugin_pager_none.inc
@@ -0,0 +1,62 @@
+<?php
+// $Id$
+
+/**
+ * Plugin for views without pagers.
+ *
+ * @ingroup views_pager_plugins
+ */
+class views_plugin_pager_none extends views_plugin_pager {
+ function summary_title() {
+ if (!empty($this->options['offset'])) {
+ return t('All items, skip @skip', array('@skip' => $this->options['offset']));
+ }
+ return t('All items');
+ }
+
+ function option_definition() {
+ $options = parent::option_definition();
+ $options['offset'] = array('default' => 0);
+
+ return $options;
+ }
+
+ /**
+ * Provide the default form for setting options.
+ */
+ function options_form(&$form, &$form_state) {
+ $form['offset'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Offset'),
+ '#description' => t('The number of items to skip. For example, if this field is 3, the first 3 items will be skipped and not displayed.'),
+ '#default_value' => $this->options['offset'],
+ );
+ }
+
+ function use_pager() {
+ return FALSE;
+ }
+
+ function use_count_query() {
+ return FALSE;
+ }
+
+ function get_items_per_page() {
+ return 0;
+ }
+
+ function execute_count_query(&$count_query) {
+ // If we are displaying all items, never count. But we can update the count in post_execute.
+ }
+
+ function post_execute($result) {
+ $this->total_items = count($result);
+ }
+
+ function query() {
+ // The only query modifications we might do are offsets.
+ if (!empty($this->options['offset'])) {
+ $this->view->query->set_offset($this->options['offset']);
+ }
+ }
+}
diff --git a/plugins/views_plugin_pager_some.inc b/plugins/views_plugin_pager_some.inc
new file mode 100644
index 0000000..2079946
--- /dev/null
+++ b/plugins/views_plugin_pager_some.inc
@@ -0,0 +1,56 @@
+<?php
+// $Id$
+
+/**
+ * Plugin for views without pagers.
+ *
+ * @ingroup views_pager_plugins
+ */
+class views_plugin_pager_some extends views_plugin_pager {
+ function summary_title() {
+ if (!empty($this->options['offset'])) {
+ return format_plural($this->options['items_per_page'], '@count item, skip @skip', '@count items, skip @skip', array('@count' => $this->options['items_per_page'], '@skip' => $this->options['offset']));
+ }
+ return format_plural($this->options['items_per_page'], '@count item', '@count items', array('@count' => $this->options['items_per_page']));
+ }
+
+ function option_definition() {
+ $options = parent::option_definition();
+ $options['items_per_page'] = array('default' => 10);
+ $options['offset'] = array('default' => 0);
+
+ return $options;
+ }
+
+ /**
+ * Provide the default form for setting options.
+ */
+ function options_form(&$form, &$form_state) {
+ $form['items_per_page'] = array(
+ '#title' => t('Items to display'),
+ '#type' => 'textfield',
+ '#description' => t('The number of items to display per page. Enter 0 for no limit.'),
+ '#default_value' => $this->options['items_per_page'],
+ );
+
+ $form['offset'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Offset'),
+ '#description' => t('The number of items to skip. For example, if this field is 3, the first 3 items will be skipped and not displayed.'),
+ '#default_value' => $this->options['offset'],
+ );
+ }
+
+ function use_pager() {
+ return FALSE;
+ }
+
+ function use_count_query() {
+ return FALSE;
+ }
+
+ function query() {
+ $this->view->query->set_limit($this->options['items_per_page']);
+ $this->view->query->set_offset($this->options['offset']);
+ }
+}
diff --git a/plugins/views_plugin_query.inc b/plugins/views_plugin_query.inc
index 183c002..4aa7535 100644
--- a/plugins/views_plugin_query.inc
+++ b/plugins/views_plugin_query.inc
@@ -9,6 +9,10 @@
* Object used to create a SELECT query.
*/
class views_plugin_query extends views_plugin {
+ /**
+ * A pager plugin that should be provided by the display.
+ */
+ var $pager = NULL;
/**
* Constructor; Create the basic query object and fill with default values.
@@ -57,4 +61,37 @@ class views_plugin_query extends views_plugin {
* If NULL, aggregation is not allowed.
*/
function get_aggregation_info() { }
+
+ /**
+ * Set a LIMIT on the query, specifying a maximum number of results.
+ */
+ function set_limit($limit) {
+ $this->limit = $limit;
+ }
+
+ /**
+ * Set an OFFSET on the query, specifying a number of results to skip
+ */
+ function set_offset($offset) {
+ $this->offset = $offset;
+ }
+
+ function init_pager(&$view) {
+ // @todo -- probably this should be a method on the display rather than directly calling
+ // get plugin?
+ $this->pager = $view->display_handler->get_plugin('pager');
+ }
+
+ /**
+ * Render the pager, if necessary.
+ */
+ function render_pager() {
+ if (!empty($this->pager) && $this->pager->use_pager()) {
+ $exposed_input = isset($this->view->exposed_data_raw) ? $this->view->exposed_data_raw : NULL;
+ return $this->pager->render($exposed_input);
+ }
+ return '';
+ }
+
+
}
diff --git a/plugins/views_plugin_query_default.inc b/plugins/views_plugin_query_default.inc
index 83dee82..16555a5 100644
--- a/plugins/views_plugin_query_default.inc
+++ b/plugins/views_plugin_query_default.inc
@@ -1058,6 +1058,14 @@ class views_plugin_query_default extends views_plugin_query {
* Builds the necessary info to execute the query.
*/
function build(&$view) {
+ $this->init_pager($view);
+ if ($this->pager->use_pager()) {
+ $this->pager->set_current_page($view->current_page);
+ }
+
+ // Let the pager modify the query to add limits.
+ $this->pager->query();
+
$view->build_info['query'] = $this->query();
$view->build_info['count_query'] = $this->query(TRUE);
}
@@ -1067,7 +1075,7 @@ class views_plugin_query_default extends views_plugin_query {
* values.
*
* Values to set: $view->result, $view->total_rows, $view->execute_time,
- * $view->pager['current_page'].
+ * $view->current_page.
*/
function execute(&$view) {
$external = FALSE; // Whether this query will run against an external database.
@@ -1080,6 +1088,9 @@ class views_plugin_query_default extends views_plugin_query {
// We have already build a working count query. Views optimeses it automatically.
//$count_query = $count_query->countQuery();
+ // against strict problems
+ $args = array();
+
// Add additional arguments as a fake condition.
// XXX: this doesn't work... because PDO mandates that all bound arguments
// are used on the query. TODO: Find a better way to do this.
@@ -1095,39 +1106,19 @@ class views_plugin_query_default extends views_plugin_query {
}
$start = microtime(TRUE);
- if (!empty($view->pager['items_per_page'])) {
- // We no longer use pager_query() here because pager_query() does not
- // support an offset. This is fine as we don't actually need pager
- // query; we've already been doing most of what it does, and we
- // just need to do a little more playing with globals.
- if (!empty($view->pager['use_pager']) || !empty($view->get_total_rows)) {
- $view->total_rows = $count_query->execute()->fetchField() - $view->pager['offset'];
- }
- if (!empty($view->pager['use_pager'])) {
- // Dump information about what we already know into the globals.
- global $pager_page_array, $pager_total, $pager_total_items;
- // Set the item count for the pager.
- $pager_total_items[$view->pager['element']] = $view->total_rows;
- // Calculate and set the count of available pages.
- $pager_total[$view->pager['element']] = ceil($pager_total_items[$view->pager['element']] / $view->pager['items_per_page']);
-
- // What page was requested:
- $pager_page_array = isset($_GET['page']) ? explode(',', $_GET['page']) : array();
-
- // If the requested page was within range. $view->pager['current_page']
- // defaults to 0 so we don't need to set it in an out-of-range condition.
- if (!empty($pager_page_array[$view->pager['element']])) {
- $page = intval($pager_page_array[$view->pager['element']]);
- if ($page > 0 && $page < $pager_total[$view->pager['element']]) {
- $view->pager['current_page'] = $page;
- }
- }
- $pager_page_array[$view->pager['element']] = $view->pager['current_page'];
- }
+ if ($this->pager->use_count_query() || !empty($view->get_total_rows)) {
+ $this->pager->execute_count_query($count_query, $args);
+ }
- $offset = $view->pager['current_page'] * $view->pager['items_per_page'] + $view->pager['offset'];
- $query->range($offset, $view->pager['items_per_page']);
+ // Let the pager modify the query to add limits.
+ $this->pager->pre_execute($query, $args);
+
+ if (!empty($this->limit) || !empty($this->offset)) {
+ // We can't have an offset without a limit, so provide a very large limit instead.
+ $limit = intval(!empty($this->limit) ? $this->limit : 999999);
+ $offset = intval(!empty($this->offset) ? $this->offset : 0);
+ $query->range($offset, $limit);
}
try {
@@ -1138,10 +1129,10 @@ class views_plugin_query_default extends views_plugin_query {
$view->result[] = $item;
}
- // If we already know how many items we have even if we did not run the
- // count query, go ahead and set that value:
- if (empty($this->pager['items_per_page'])) {
- $this->total_rows = count($view->result);
+ $this->pager->post_execute($view->result);
+
+ if ($this->pager->use_pager()) {
+ $view->total_rows = $this->pager->get_total_items();
}
}
catch (Exception $e) {
diff --git a/tests/views_pager.test b/tests/views_pager.test
index ea8d638..1c4d575 100644
--- a/tests/views_pager.test
+++ b/tests/views_pager.test
@@ -28,13 +28,13 @@ class ViewsPagerTest extends DrupalWebTestCase {
$this->drupalLogin($admin_user);
// Test behaviour described in http://drupal.org/node/652712#comment-2354918.
- $this->drupalGet('admin/build/views/edit/frontpage');
+ $this->drupalGet('admin/structure/views/edit/frontpage');
$edit = array(
'pager_options[items_per_page]' => 20,
);
- $this->drupalPost('admin/build/views/nojs/display/frontpage/default/pager_options', $edit, t('Update'));
+ $this->drupalPost('admin/structure/views/nojs/display/frontpage/default/pager_options', $edit, t('Update'));
$this->assertText('20 items');
// Change type and check whether the type is new type is stored.
@@ -42,7 +42,8 @@ class ViewsPagerTest extends DrupalWebTestCase {
$edit = array(
'pager[type]' => 'mini',
);
- $this->drupalPost('admin/build/views/nojs/display/frontpage/default/pager', $edit, t('Update'));
+ $this->drupalPost('admin/structure/views/nojs/display/frontpage/default/pager', $edit, t('Update'));
+ $this->drupalGet('admin/structure/views/edit/frontpage');
$this->assertText('Mini pager', 'Changed pager plugin, should change some text');
// Test behaviour described in http://drupal.org/node/652712#comment-2354400
@@ -50,19 +51,20 @@ class ViewsPagerTest extends DrupalWebTestCase {
// Make it editable in the admin interface.
$view->save();
- $this->drupalGet('admin/build/views/test_store_pager_settings');
+ $this->drupalGet('admin/structure/views/test_store_pager_settings');
$edit = array();
$edit = array(
'pager[type]' => 'full',
);
- $this->drupalPost('admin/build/views/nojs/display/test_store_pager_settings/default/pager', $edit, t('Update'));
- $this->assert('Paged');
+ $this->drupalPost('admin/structure/views/nojs/display/test_store_pager_settings/default/pager', $edit, t('Update'));
+ $this->drupalGet('admin/structure/views/edit/test_store_pager_settings');
+ $this->assertText('Paged');
$edit = array(
'pager_options[items_per_page]' => 20,
);
- $this->drupalPost('admin/build/views/nojs/display/test_store_pager_settings/default/pager_options', $edit, t('Update'));
+ $this->drupalPost('admin/structure/views/nojs/display/test_store_pager_settings/default/pager_options', $edit, t('Update'));
$this->assertText('20 items');
// add new display and test the settings again, by override it.
@@ -70,19 +72,20 @@ class ViewsPagerTest extends DrupalWebTestCase {
'display' => 'page',
);
// Add a display and override the pager settings.
- $this->drupalPost('admin/build/views/edit/test_store_pager_settings', $edit, t('Add display'));
- $this->drupalPost('admin/build/views/nojs/display/test_store_pager_settings/page_1/pager', array(), t('Override'));
+ $this->drupalPost('admin/structure/views/edit/test_store_pager_settings', $edit, t('Add display'));
+ $this->drupalPost('admin/structure/views/nojs/display/test_store_pager_settings/page_1/pager', array(), t('Override'));
$edit = array(
'pager[type]' => 'mini',
);
- $this->drupalPost('admin/build/views/nojs/display/test_store_pager_settings/page_1/pager', array(), t('Update'));
+ $this->drupalPost('admin/structure/views/nojs/display/test_store_pager_settings/page_1/pager', $edit, t('Update'));
+ $this->drupalGet('admin/structure/views/edit/test_store_pager_settings');
$this->assertText('Mini pager', 'Changed pager plugin, should change some text');
$edit = array(
'pager_options[items_per_page]' => 10,
);
- $this->drupalPost('admin/build/views/nojs/display/test_store_pager_settings/default/pager_options', $edit, t('Update'));
+ $this->drupalPost('admin/structure/views/nojs/display/test_store_pager_settings/default/pager_options', $edit, t('Update'));
$this->assertText('20 items');
}
@@ -105,7 +108,192 @@ class ViewsPagerTest extends DrupalWebTestCase {
$handler->display->display_options['exposed_form']['type'] = 'basic';
$handler->display->display_options['pager']['type'] = 'none';
$handler->display->display_options['style_plugin'] = 'default';
- $handler->display->display_options['row_plugin'] = 'fields';
+ $handler->display->display_options['row_plugin'] = 'node';
return $view;
}
+
+ /**
+ * Test the none-pager-query.
+ */
+ public function testNoLimit() {
+ // Create 11 nodes and take sure that everyone is returned.
+ // We create 11 nodes, because the default pager plugin had 10 items per page.
+ for ($i = 0; $i < 11; $i++) {
+ $this->drupalCreateNode();
+ }
+ $view = $this->viewsPagerNoLimit();
+ $view->set_display('default');
+ $view->execute();
+ $this->assertEqual(count($view->result), 11, t('Take sure that every item is returned in the result'));
+
+ $view->destroy();
+
+ // Setup and test a offset.
+ $view = $this->viewsPagerNoLimit();
+ $view->set_display('default');
+
+ $pager = array(
+ 'type' => 'none',
+ 'options' => array(
+ 'offset' => 3,
+ ),
+ );
+ $view->display_handler->set_option('pager', $pager);
+ $view->execute();
+
+ $this->assertEqual(count($view->result), 8, t('Take sure that every item beside the first three is returned in the result'));
+
+ // Check some public functions.
+ $this->assertFalse($view->query->pager->use_pager());
+ $this->assertFalse($view->query->pager->use_count_query());
+ $this->assertEqual($view->query->pager->get_items_per_page(), 0);
+ }
+
+ public function viewsPagerNoLimit() {
+ $view = new view;
+ $view->name = 'test_pager_none';
+ $view->description = '';
+ $view->tag = '';
+ $view->view_php = '';
+ $view->base_table = 'node';
+ $view->is_cacheable = FALSE;
+ $view->api_version = 2;
+ $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
+
+ /* Display: Defaults */
+ $handler = $view->new_display('default', 'Defaults', 'default');
+ $handler->display->display_options['access']['type'] = 'none';
+ $handler->display->display_options['cache']['type'] = 'none';
+ $handler->display->display_options['exposed_form']['type'] = 'basic';
+ $handler->display->display_options['pager']['type'] = 'none';
+ $handler->display->display_options['style_plugin'] = 'default';
+ $handler->display->display_options['row_plugin'] = 'node';
+ return $view;
+ }
+
+ /**
+ * Test the some pager plugin.
+ */
+ public function testLimit() {
+ // Create 11 nodes and take sure that everyone is returned.
+ // We create 11 nodes, because the default pager plugin had 10 items per page.
+ for ($i = 0; $i < 11; $i++) {
+ $this->drupalCreateNode();
+ }
+ $view = $this->viewsPagerLimit();
+ $view->set_display('default');
+ $view->execute();
+ $this->assertEqual(count($view->result), 5, t('Take sure that only a certain count of items is returned'));
+ $view->destroy();
+
+ // Setup and test a offset.
+ $view = $this->viewsPagerLimit();
+ $view->set_display('default');
+
+ $pager = array(
+ 'type' => 'none',
+ 'options' => array(
+ 'offset' => 8,
+ 'items_per_page' => 5,
+ ),
+ );
+ $view->display_handler->set_option('pager', $pager);
+ $view->execute();
+ $this->assertEqual(count($view->result), 3, t('Take sure that only a certain count of items is returned'));
+
+ // Check some public functions.
+ $this->assertFalse($view->query->pager->use_pager());
+ $this->assertFalse($view->query->pager->use_count_query());
+ }
+
+ public function viewsPagerLimit() {
+ $view = new view;
+ $view->name = 'test_pager_some';
+ $view->description = '';
+ $view->tag = '';
+ $view->view_php = '';
+ $view->base_table = 'node';
+ $view->is_cacheable = FALSE;
+ $view->api_version = 2;
+ $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
+
+ /* Display: Defaults */
+ $handler = $view->new_display('default', 'Defaults', 'default');
+ $handler->display->display_options['access']['type'] = 'none';
+ $handler->display->display_options['cache']['type'] = 'none';
+ $handler->display->display_options['exposed_form']['type'] = 'basic';
+ $handler->display->display_options['pager']['type'] = 'some';
+ $handler->display->display_options['pager']['options']['offset'] = 0;
+ $handler->display->display_options['pager']['options']['items_per_page'] = 5;
+ $handler->display->display_options['style_plugin'] = 'default';
+ $handler->display->display_options['row_plugin'] = 'node';
+ return $view;
+ }
+
+ /**
+ * Test the normal pager.
+ */
+ public function testNormalPager() {
+ // Create 11 nodes and take sure that everyone is returned.
+ // We create 11 nodes, because the default pager plugin had 10 items per page.
+ for ($i = 0; $i < 11; $i++) {
+ $this->drupalCreateNode();
+ }
+ $view = $this->viewsPagerFull();
+ $view->set_display('default');
+ $view->execute();
+ $this->assertEqual(count($view->result), 5, t('Take sure that only a certain count of items is returned'));
+ $view->destroy();
+
+ // Setup and test a offset.
+ $view = $this->viewsPagerFull();
+ $view->set_display('default');
+
+ $pager = array(
+ 'type' => 'full',
+ 'options' => array(
+ 'offset' => 8,
+ 'items_per_page' => 5,
+ ),
+ );
+ $view->display_handler->set_option('pager', $pager);
+ $view->execute();
+ $this->assertEqual(count($view->result), 3, t('Take sure that only a certain count of items is returned'));
+
+ // TODO test number of pages.
+ }
+
+ function ViewsPagerFull() {
+ $view = new view;
+ $view->name = 'test_pager_full';
+ $view->description = '';
+ $view->tag = '';
+ $view->view_php = '';
+ $view->base_table = 'node';
+ $view->is_cacheable = FALSE;
+ $view->api_version = 2;
+ $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
+
+ /* Display: Defaults */
+ $handler = $view->new_display('default', 'Defaults', 'default');
+ $handler->display->display_options['access']['type'] = 'none';
+ $handler->display->display_options['cache']['type'] = 'none';
+ $handler->display->display_options['exposed_form']['type'] = 'basic';
+ $handler->display->display_options['pager']['type'] = 'full';
+ $handler->display->display_options['pager']['options']['items_per_page'] = '5';
+ $handler->display->display_options['pager']['options']['offset'] = '0';
+ $handler->display->display_options['pager']['options']['id'] = '0';
+ $handler->display->display_options['style_plugin'] = 'default';
+ $handler->display->display_options['row_plugin'] = 'node';
+
+ return $view;
+ }
+
+
+ /**
+ * Test the minipager.
+ */
+ public function testMiniPager() {
+ // the functionality is the same as the normal pager, so i don't know what to test here.
+ }
}
diff --git a/theme/theme.inc b/theme/theme.inc
index a8f7f9a..1a7fc97 100644
--- a/theme/theme.inc
+++ b/theme/theme.inc
@@ -72,24 +72,11 @@ function template_preprocess_views_view(&$vars) {
}
$vars['more'] = $view->display_handler->render_more_link();
$vars['feed_icon'] = !empty($view->feed_icon) ? $view->feed_icon : '';
+ $vars['pager'] = $view->query->render_pager();
$vars['attachment_before'] = !empty($view->attachment_before) ? $view->attachment_before : '';
$vars['attachment_after'] = !empty($view->attachment_after) ? $view->attachment_after : '';
- $vars['pager'] = '';
-
- $exposed_input = isset($view->exposed_data_raw) ? $view->exposed_data_raw : NULL;
- if ($view->display_handler->render_pager()) {
- $pager_type = ($view->pager['use_pager'] === 'mini' ? 'views_mini_pager' : 'pager');
- $pager_theme = views_theme_functions($pager_type, $view, $view->display_handler->display);
- $vars['pager'] = theme($pager_theme,
- array(
- 'tags' => $exposed_input,
- 'element' => $view->pager['element'],
- )
- );
- }
-
// if administrator, add some links. These used to be tabs, but this is better.
if (user_access('administer views') && module_exists('views_ui') && empty($view->hide_admin_links) && !variable_get('views_no_hover_links', FALSE)) {
$vars['admin_links_raw'] = array(
diff --git a/views.info b/views.info
index ffb4c4a..c783eb1 100644
--- a/views.info
+++ b/views.info
@@ -205,6 +205,11 @@ files[] = plugins/views_plugin_exposed_form_basic.inc
files[] = plugins/views_plugin_exposed_form.inc
files[] = plugins/views_plugin_exposed_form_input_required.inc
files[] = plugins/views_plugin_display_page.inc
+files[] = plugins/views_plugin_pager.inc
+files[] = plugins/views_plugin_pager_full.inc
+files[] = plugins/views_plugin_pager_mini.inc
+files[] = plugins/views_plugin_pager_none.inc
+files[] = plugins/views_plugin_pager_some.inc
files[] = plugins/views_plugin_query.inc
files[] = plugins/views_plugin_query_default.inc
files[] = plugins/views_plugin_row.inc