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