Pull merge.
[yaffs-website] / web / core / lib / Drupal / Core / Database / Query / PagerSelectExtender.php
1 <?php
2
3 namespace Drupal\Core\Database\Query;
4
5 use Drupal\Core\Database\Connection;
6
7 /**
8  * Query extender for pager queries.
9  *
10  * This is the "default" pager mechanism.  It creates a paged query with a fixed
11  * number of entries per page.
12  *
13  * When adding this extender along with other extenders, be sure to add
14  * PagerSelectExtender last, so that its range and count are based on the full
15  * query.
16  */
17 class PagerSelectExtender extends SelectExtender {
18
19   /**
20    * The highest element we've autogenerated so far.
21    *
22    * @var int
23    */
24   public static $maxElement = 0;
25
26   /**
27    * The number of elements per page to allow.
28    *
29    * @var int
30    */
31   protected $limit = 10;
32
33   /**
34    * The unique ID of this pager on this page.
35    *
36    * @var int
37    */
38   protected $element = NULL;
39
40   /**
41    * The count query that will be used for this pager.
42    *
43    * @var \Drupal\Core\Database\Query\SelectInterface
44    */
45   protected $customCountQuery = FALSE;
46
47   public function __construct(SelectInterface $query, Connection $connection) {
48     parent::__construct($query, $connection);
49
50     // Add pager tag. Do this here to ensure that it is always added before
51     // preExecute() is called.
52     $this->addTag('pager');
53   }
54
55   /**
56    * Override the execute method.
57    *
58    * Before we run the query, we need to add pager-based range() instructions
59    * to it.
60    */
61   public function execute() {
62     // By calling preExecute() here, we force it to preprocess the extender
63     // object rather than just the base query object. That means
64     // hook_query_alter() gets access to the extended object.
65     if (!$this->preExecute($this)) {
66       return NULL;
67     }
68
69     // A NULL limit is the "kill switch" for pager queries.
70     if (empty($this->limit)) {
71       return;
72     }
73     $this->ensureElement();
74
75     $total_items = $this->getCountQuery()->execute()->fetchField();
76     $current_page = pager_default_initialize($total_items, $this->limit, $this->element);
77     $this->range($current_page * $this->limit, $this->limit);
78
79     // Now that we've added our pager-based range instructions, run the query normally.
80     return $this->query->execute();
81   }
82
83   /**
84    * Ensure that there is an element associated with this query.
85    * If an element was not specified previously, then the value of the
86    * $maxElement counter is taken, after which the counter is incremented.
87    *
88    * After running this method, access $this->element to get the element for this
89    * query.
90    */
91   protected function ensureElement() {
92     if (!isset($this->element)) {
93       $this->element = self::$maxElement++;
94     }
95   }
96
97   /**
98    * Specify the count query object to use for this pager.
99    *
100    * You will rarely need to specify a count query directly.  If not specified,
101    * one is generated off of the pager query itself.
102    *
103    * @param \Drupal\Core\Database\Query\SelectInterface $query
104    *   The count query object.  It must return a single row with a single column,
105    *   which is the total number of records.
106    */
107   public function setCountQuery(SelectInterface $query) {
108     $this->customCountQuery = $query;
109   }
110
111   /**
112    * Retrieve the count query for this pager.
113    *
114    * The count query may be specified manually or, by default, taken from the
115    * query we are extending.
116    *
117    * @return \Drupal\Core\Database\Query\SelectInterface
118    *   A count query object.
119    */
120   public function getCountQuery() {
121     if ($this->customCountQuery) {
122       return $this->customCountQuery;
123     }
124     else {
125       return $this->query->countQuery();
126     }
127   }
128
129   /**
130    * Specify the maximum number of elements per page for this query.
131    *
132    * The default if not specified is 10 items per page.
133    *
134    * @param int|false $limit
135    *   An integer specifying the number of elements per page. If passed a false
136    *   value (FALSE, 0, NULL), the pager is disabled.
137    */
138   public function limit($limit = 10) {
139     $this->limit = $limit;
140     return $this;
141   }
142
143   /**
144    * Specify the element ID for this pager query.
145    *
146    * The element is used to differentiate different pager queries on the same
147    * page so that they may be operated independently.  If you do not specify an
148    * element, every pager query on the page will get a unique element.  If for
149    * whatever reason you want to explicitly define an element for a given query,
150    * you may do so here.
151    *
152    * Setting the element here also increments the static $maxElement counter,
153    * which is used for determining the $element when there's none specified.
154    *
155    * Note that no collision detection is done when setting an element ID
156    * explicitly, so it is possible for two pagers to end up using the same ID
157    * if both are set explicitly.
158    *
159    * @param $element
160    *   Element ID that is used to differentiate different pager queries.
161    */
162   public function element($element) {
163     $this->element = $element;
164     if ($element >= self::$maxElement) {
165       self::$maxElement = $element + 1;
166     }
167     return $this;
168   }
169
170 }