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