]> git.mxchange.org Git - friendica.git/blob - src/Content/Pager.php
fafb68084c6b1bfd2d3e2983334250660d1d5ed2
[friendica.git] / src / Content / Pager.php
1 <?php
2
3 namespace Friendica\Content;
4
5 use Friendica\Core\L10n;
6 use Friendica\Core\Renderer;
7 use Friendica\Util\Strings;
8
9 /**
10  * The Pager has two very different output, Minimal and Full, see renderMinimal() and renderFull() for more details.
11  *
12  * @author Hypolite Petovan <mrpetovan@gmail.com>
13  */
14 class Pager
15 {
16         /**
17          * @var integer
18          */
19         private $page = 1;
20         /**
21          * @var integer
22          */
23         private $itemsPerPage = 50;
24
25         /**
26          * @var string
27          */
28         private $baseQueryString = '';
29
30         /**
31          * Instantiates a new Pager with the base parameters.
32          *
33          * Guesses the page number from the GET parameter 'page'.
34          *
35          * @param string  $queryString  The query string of the current page
36          * @param integer $itemsPerPage An optional number of items per page to override the default value
37          */
38         public function __construct($queryString, $itemsPerPage = 50)
39         {
40                 $this->setQueryString($queryString);
41                 $this->setItemsPerPage($itemsPerPage);
42                 $this->setPage(defaults($_GET, 'page', 1));
43         }
44
45         /**
46          * Returns the start offset for a LIMIT clause. Starts at 0.
47          *
48          * @return integer
49          */
50         public function getStart()
51         {
52                 return max(0, ($this->page * $this->itemsPerPage) - $this->itemsPerPage);
53         }
54
55         /**
56          * Returns the number of items per page
57          *
58          * @return integer
59          */
60         public function getItemsPerPage()
61         {
62                 return $this->itemsPerPage;
63         }
64
65         /**
66          * Returns the current page number
67          *
68          * @return type
69          */
70         public function getPage()
71         {
72                 return $this->page;
73         }
74
75         /**
76          * Returns the base query string.
77          *
78          * Warning: this isn't the same value as passed to the constructor.
79          * See setQueryString() for the inventory of transformations
80          *
81          * @see setBaseQuery()
82          * @return string
83          */
84         public function getBaseQueryString()
85         {
86                 return $this->baseQueryString;
87         }
88
89         /**
90          * Sets the number of items per page, 1 minimum.
91          *
92          * @param integer $itemsPerPage
93          */
94         public function setItemsPerPage($itemsPerPage)
95         {
96                 $this->itemsPerPage = max(1, intval($itemsPerPage));
97         }
98
99         /**
100          * Sets the current page number. Starts at 1.
101          *
102          * @param integer $page
103          */
104         public function setPage($page)
105         {
106                 $this->page = max(1, intval($page));
107         }
108
109         /**
110          * Sets the base query string from a full query string.
111          *
112          * Strips the 'page' parameter, and remove the 'q=' string for some reason.
113          *
114          * @param string $queryString
115          */
116         public function setQueryString($queryString)
117         {
118                 $stripped = preg_replace('/([&?]page=[0-9]*)/', '', $queryString);
119
120                 $stripped = str_replace('q=', '', $stripped);
121                 $stripped = trim($stripped, '/');
122
123                 $this->baseQueryString = $stripped;
124         }
125
126         /**
127          * Ensures the provided URI has its query string punctuation in order.
128          *
129          * @param string $uri
130          * @return string
131          */
132         private function ensureQueryParameter($uri)
133         {
134                 if (strpos($uri, '?') === false && ($pos = strpos($uri, '&')) !== false) {
135                         $uri = substr($uri, 0, $pos) . '?' . substr($uri, $pos + 1);
136                 }
137
138                 return $uri;
139         }
140
141         /**
142          * @brief Minimal pager (newer/older)
143          *
144          * This mode is intended for reverse chronological pages and presents only two links, newer (previous) and older (next).
145          * The itemCount is the number of displayed items. If no items are displayed, the older button is disabled.
146          *
147          * Example usage:
148          *
149          * $pager = new Pager($a->query_string);
150          *
151          * $params = ['order' => ['sort_field' => true], 'limit' => [$pager->getStart(), $pager->getItemsPerPage()]];
152          * $items = DBA::toArray(DBA::select($table, $fields, $condition, $params));
153          *
154          * $html = $pager->renderMinimal(count($items));
155          *
156          * @param integer $itemCount The number of displayed items on the page
157          * @return string HTML string of the pager
158          */
159         public function renderMinimal($itemCount)
160         {
161                 $displayedItemCount = max(0, intval($itemCount));
162
163                 $data = [
164                         'class' => 'pager',
165                         'prev'  => [
166                                 'url'   => Strings::ensureQueryParameter($this->baseQueryString . '&page=' . ($this->getPage() - 1)),
167                                 'text'  => L10n::t('newer'),
168                                 'class' => 'previous' . ($this->getPage() == 1 ? ' disabled' : '')
169                         ],
170                         'next'  => [
171                                 'url'   => Strings::ensureQueryParameter($this->baseQueryString . '&page=' . ($this->getPage() + 1)),
172                                 'text'  => L10n::t('older'),
173                                 'class' =>  'next' . ($displayedItemCount < $this->getItemsPerPage() ? ' disabled' : '')
174                         ]
175                 ];
176
177                 $tpl = Renderer::getMarkupTemplate('paginate.tpl');
178                 return Renderer::replaceMacros($tpl, ['pager' => $data]);
179         }
180
181         /**
182          * @brief Full pager (first / prev / 1 / 2 / ... / 14 / 15 / next / last)
183          *
184          * This mode presents page numbers as well as first, previous, next and last links.
185          * The itemCount is the total number of items including those not displayed.
186          *
187          * Example usage:
188          *
189          * $total = DBA::count($table, $condition);
190          *
191          * $pager = new Pager($a->query_string, $total);
192          *
193          * $params = ['limit' => [$pager->getStart(), $pager->getItemsPerPage()]];
194          * $items = DBA::toArray(DBA::select($table, $fields, $condition, $params));
195          *
196          * $html = $pager->renderFull();
197          *
198          * @param integer $itemCount The total number of items including those note displayed on the page
199          * @return string HTML string of the pager
200          */
201         public function renderFull($itemCount)
202         {
203                 $totalItemCount = max(0, intval($itemCount));
204
205                 $data = [];
206
207                 $data['class'] = 'pagination';
208                 if ($totalItemCount > $this->getItemsPerPage()) {
209                         $data['first'] = [
210                                 'url'   => Strings::ensureQueryParameter($this->baseQueryString . '&page=1'),
211                                 'text'  => L10n::t('first'),
212                                 'class' => $this->getPage() == 1 ? 'disabled' : ''
213                         ];
214                         $data['prev'] = [
215                                 'url'   => Strings::ensureQueryParameter($this->baseQueryString . '&page=' . ($this->getPage() - 1)),
216                                 'text'  => L10n::t('prev'),
217                                 'class' => $this->getPage() == 1 ? 'disabled' : ''
218                         ];
219
220                         $numpages = $totalItemCount / $this->getItemsPerPage();
221
222                         $numstart = 1;
223                         $numstop = $numpages;
224
225                         // Limit the number of displayed page number buttons.
226                         if ($numpages > 8) {
227                                 $numstart = (($this->getPage() > 4) ? ($this->getPage() - 4) : 1);
228                                 $numstop = (($this->getPage() > ($numpages - 7)) ? $numpages : ($numstart + 8));
229                         }
230
231                         $pages = [];
232
233                         for ($i = $numstart; $i <= $numstop; $i++) {
234                                 if ($i == $this->getPage()) {
235                                         $pages[$i] = [
236                                                 'url'   => '#',
237                                                 'text'  => $i,
238                                                 'class' => 'current active'
239                                         ];
240                                 } else {
241                                         $pages[$i] = [
242                                                 'url'   => Strings::ensureQueryParameter($this->baseQueryString . '&page=' . $i),
243                                                 'text'  => $i,
244                                                 'class' => 'n'
245                                         ];
246                                 }
247                         }
248
249                         if (($totalItemCount % $this->getItemsPerPage()) != 0) {
250                                 if ($i == $this->getPage()) {
251                                         $pages[$i] = [
252                                                 'url'   => '#',
253                                                 'text'  => $i,
254                                                 'class' => 'current active'
255                                         ];
256                                 } else {
257                                         $pages[$i] = [
258                                                 'url'   => Strings::ensureQueryParameter($this->baseQueryString . '&page=' . $i),
259                                                 'text'  => $i,
260                                                 'class' => 'n'
261                                         ];
262                                 }
263                         }
264
265                         $data['pages'] = $pages;
266
267                         $lastpage = (($numpages > intval($numpages)) ? intval($numpages)+1 : $numpages);
268
269                         $data['next'] = [
270                                 'url'   => Strings::ensureQueryParameter($this->baseQueryString . '&page=' . ($this->getPage() + 1)),
271                                 'text'  => L10n::t('next'),
272                                 'class' => $this->getPage() == $lastpage ? 'disabled' : ''
273                         ];
274                         $data['last'] = [
275                                 'url'   => Strings::ensureQueryParameter($this->baseQueryString . '&page=' . $lastpage),
276                                 'text'  => L10n::t('last'),
277                                 'class' => $this->getPage() == $lastpage ? 'disabled' : ''
278                         ];
279                 }
280
281                 $tpl = Renderer::getMarkupTemplate('paginate.tpl');
282                 return Renderer::replaceMacros($tpl, ['pager' => $data]);
283         }
284 }