Pagination::getCurrentPage()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
/**
4
 * Platine Pagination
5
 *
6
 * Platine Pagination is a lightweight PHP paginator, for generating pagination controls
7
 *
8
 * This content is released under the MIT License (MIT)
9
 *
10
 * Copyright (c) 2020 Platine Pagination
11
 * Copyright (c) 2014 Jason Grimes
12
 *
13
 * Permission is hereby granted, free of charge, to any person obtaining a copy
14
 * of this software and associated documentation files (the "Software"), to deal
15
 * in the Software without restriction, including without limitation the rights
16
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
 * copies of the Software, and to permit persons to whom the Software is
18
 * furnished to do so, subject to the following conditions:
19
 *
20
 * The above copyright notice and this permission notice shall be included in all
21
 * copies or substantial portions of the Software.
22
 *
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
 * SOFTWARE.
30
 */
31
32
/**
33
 *  @file Pagination.php
34
 *
35
 *  The pagination main class
36
 *
37
 *  @package    Platine\Pagination
38
 *  @author Platine Developers Team
39
 *  @copyright  Copyright (c) 2020
40
 *  @license    http://opensource.org/licenses/MIT  MIT License
41
 *  @link   https://www.platine-php.com
42
 *  @version 1.0.0
43
 *  @filesource
44
 */
45
46
declare(strict_types=1);
47
48
namespace Platine\Pagination;
49
50
use InvalidArgumentException;
51
use Platine\Pagination\Renderer\DefaultRenderer;
52
use Platine\Pagination\UrlGenerator\SimpleUrlGenerator;
53
use Stringable;
54
55
/**
56
 * @class Pagination
57
 * @package Platine\Pagination
58
 */
59
class Pagination implements Stringable
60
{
61
    /**
62
     * The URL generator instance
63
     * @var UrlGeneratorInterface
64
     */
65
    protected UrlGeneratorInterface $urlGenerator;
66
67
    /**
68
     * The pagination renderer
69
     * @var RendererInterface
70
     */
71
    protected RendererInterface $renderer;
72
73
    /**
74
     * The pagination total items
75
     * @var int
76
     */
77
    protected int $totalItems = 0;
78
79
    /**
80
     * The pagination number of items per page
81
     * @var int
82
     */
83
    protected int $itemsPerPage = 10;
84
85
    /**
86
     * The pagination current page number
87
     * @var int
88
     */
89
    protected int $currentPage = 1;
90
91
    /**
92
     * The pagination total page after calculation
93
     * @var int
94
     */
95
    protected int $totalPages = 0;
96
97
    /**
98
     * The pagination max page to show
99
     * @var int
100
     */
101
    protected int $maxPages = 10;
102
103
    /**
104
     * The pagination previous text
105
     * @var string
106
     */
107
    protected string $previousText = 'Previous';
108
109
    /**
110
     * The pagination next text
111
     * @var string
112
     */
113
    protected string $nextText = 'Next';
114
115
    /**
116
     * Create new instance
117
     * @param UrlGeneratorInterface|null $urlGenerator
118
     * @param RendererInterface|null $renderer
119
     */
120
    public function __construct(
121
        ?UrlGeneratorInterface $urlGenerator = null,
122
        ?RendererInterface $renderer = null
123
    ) {
124
        $this->urlGenerator = $urlGenerator ?? new SimpleUrlGenerator();
125
        $this->renderer = $renderer ?? new DefaultRenderer();
126
127
        $this->updateTotalPages();
128
    }
129
130
    /**
131
     * Whether the pagination has next page
132
     * @return bool
133
     */
134
    public function hasNextPage(): bool
135
    {
136
        return $this->currentPage < $this->totalPages;
137
    }
138
139
    /**
140
     * Return the next page number
141
     * @return int|null
142
     */
143
    public function getNextPage(): ?int
144
    {
145
        if ($this->hasNextPage()) {
146
            return $this->currentPage + 1;
147
        }
148
149
        return null;
150
    }
151
152
    /**
153
     * Return the next page URL
154
     * @return string|null
155
     */
156
    public function getNextUrl(): ?string
157
    {
158
        if ($this->hasNextPage()) {
159
            return $this->getPageUrl((int) $this->getNextPage());
160
        }
161
162
        return null;
163
    }
164
165
    /**
166
     * Whether the pagination has previous page
167
     * @return bool
168
     */
169
    public function hasPreviousPage(): bool
170
    {
171
        return $this->currentPage > 1;
172
    }
173
174
    /**
175
     * Return the previous page number
176
     * @return int|null
177
     */
178
    public function getPreviousPage(): ?int
179
    {
180
        if ($this->hasPreviousPage()) {
181
            return $this->currentPage - 1;
182
        }
183
184
        return null;
185
    }
186
187
    /**
188
     * Return the previous page URL
189
     * @return string|null
190
     */
191
    public function getPreviousUrl(): ?string
192
    {
193
        if ($this->hasPreviousPage()) {
194
            return $this->getPageUrl((int) $this->getPreviousPage());
195
        }
196
197
        return null;
198
    }
199
200
    /**
201
     * Return the offset so that it can be used
202
     * in other contexts, for example in SQL query
203
     * @return int
204
     */
205
    public function getOffset(): int
206
    {
207
        return ($this->currentPage - 1) * $this->itemsPerPage;
208
    }
209
210
    /**
211
     * Return the page URL for the given number
212
     * @param int $page
213
     * @return string
214
     */
215
    public function getPageUrl(int $page): string
216
    {
217
        return $this->urlGenerator->generatePageUrl($page);
218
    }
219
220
    /**
221
     * Set the URL generator to use
222
     * @param UrlGeneratorInterface $urlGenerator
223
     * @return $this
224
     */
225
    public function setUrlGenerator(UrlGeneratorInterface $urlGenerator): self
226
    {
227
        $this->urlGenerator = $urlGenerator;
228
229
        return $this;
230
    }
231
232
    /**
233
     * Set the renderer to use
234
     * @param RendererInterface $renderer
235
     * @return $this
236
     */
237
    public function setRenderer(RendererInterface $renderer): self
238
    {
239
        $this->renderer = $renderer;
240
241
        return $this;
242
    }
243
244
    /**
245
     * Set total items
246
     * @param int $totalItems
247
     * @return $this
248
     */
249
    public function setTotalItems(int $totalItems): self
250
    {
251
        $this->totalItems = $totalItems;
252
253
        $this->updateTotalPages();
254
255
        return $this;
256
    }
257
258
    /**
259
     * Set number of items to show per page
260
     * @param int $itemsPerPage
261
     * @return $this
262
     */
263
    public function setItemsPerPage(int $itemsPerPage): self
264
    {
265
        $this->itemsPerPage = $itemsPerPage;
266
267
        $this->updateTotalPages();
268
269
        return $this;
270
    }
271
272
    /**
273
     * Set current page number
274
     * @param int $currentPage
275
     * @return $this
276
     */
277
    public function setCurrentPage(int $currentPage): self
278
    {
279
        $this->currentPage = $currentPage;
280
281
        return $this;
282
    }
283
284
    /**
285
     * Set max pages to show int the links
286
     * @param int $maxPages
287
     * @return $this
288
     */
289
    public function setMaxPages(int $maxPages): self
290
    {
291
        if ($maxPages < 3) {
292
            throw new InvalidArgumentException(sprintf(
293
                'Max page to show can not be less than 3, %d given',
294
                $maxPages
295
            ));
296
        }
297
298
        $this->maxPages = $maxPages;
299
300
        return $this;
301
    }
302
303
    /**
304
     * Set previous text
305
     * @param string $previousText
306
     * @return $this
307
     */
308
    public function setPreviousText(string $previousText): self
309
    {
310
        $this->previousText = $previousText;
311
312
        return $this;
313
    }
314
315
    /**
316
     * Set next text
317
     * @param string $nextText
318
     * @return $this
319
     */
320
    public function setNextText(string $nextText): self
321
    {
322
        $this->nextText = $nextText;
323
324
        return $this;
325
    }
326
327
    /**
328
     * Return the URL generator instance
329
     * @return UrlGeneratorInterface
330
     */
331
    public function getUrlGenerator(): UrlGeneratorInterface
332
    {
333
        return $this->urlGenerator;
334
    }
335
336
    /**
337
     * Return the renderer instance
338
     * @return RendererInterface
339
     */
340
    public function getRenderer(): RendererInterface
341
    {
342
        return $this->renderer;
343
    }
344
345
    /**
346
     * Return the previous text
347
     * @return string
348
     */
349
    public function getPreviousText(): string
350
    {
351
        return $this->previousText;
352
    }
353
354
    /**
355
     * Return the next text
356
     * @return string
357
     */
358
    public function getNextText(): string
359
    {
360
        return $this->nextText;
361
    }
362
363
    /**
364
     * Return the total items
365
     * @return int
366
     */
367
    public function getTotalItems(): int
368
    {
369
        return $this->totalItems;
370
    }
371
372
    /**
373
     * Return the number of items per page
374
     * @return int
375
     */
376
    public function getItemsPerPage(): int
377
    {
378
        return $this->itemsPerPage;
379
    }
380
381
    /**
382
     * Return the current page number
383
     * @return int
384
     */
385
    public function getCurrentPage(): int
386
    {
387
        return $this->currentPage;
388
    }
389
390
    /**
391
     * Return the total number of pages
392
     * @return int
393
     */
394
    public function getTotalPages(): int
395
    {
396
        return $this->totalPages;
397
    }
398
399
    /**
400
     * Return the max pages to show
401
     * @return int
402
     */
403
    public function getMaxPages(): int
404
    {
405
        return $this->maxPages;
406
    }
407
408
    /**
409
     * Return the pages links data
410
     *
411
     * @return Page[]
412
     */
413
    public function getPages(): array
414
    {
415
        if ($this->totalPages <= 1) {
416
            return [];
417
        }
418
419
        $pages = [];
420
421
        if ($this->totalPages <= $this->maxPages) {
422
            for ($i = 1; $i <= $this->totalPages; $i++) {
423
                $pages[] = $this->createPage($i, $i === $this->currentPage);
424
            }
425
        } else {
426
            // Determine the sliding range, centered around the current page.
427
            $numAdjacents = (int) floor(($this->maxPages - 3) / 2);
428
            $slidingStart = -1;
429
430
            if ($this->currentPage + $numAdjacents > $this->totalPages) {
431
                $slidingStart = $this->totalPages - $this->maxPages + 2;
432
            } else {
433
                $slidingStart = $this->currentPage - $numAdjacents;
434
            }
435
436
            if ($slidingStart < 2) {
437
                $slidingStart = 2;
438
            }
439
440
            $slidingEnd = $slidingStart + $this->maxPages - 3;
441
442
            if ($slidingEnd >= $this->totalPages) {
443
                $slidingEnd = $this->totalPages - 1;
444
            }
445
446
            // Build the list of pages.
447
            $pages[] = $this->createPage(1, 1 === $this->currentPage);
448
449
            if ($slidingStart > 2) {
450
                $pages[] = $this->createPageEllipsis();
451
            }
452
453
            for ($i = $slidingStart; $i <= $slidingEnd; $i++) {
454
                $pages[] = $this->createPage($i, $i === $this->currentPage);
455
            }
456
457
            if ($slidingEnd < $this->totalPages - 1) {
458
                $pages[] = $this->createPageEllipsis();
459
            }
460
461
            $pages[] = $this->createPage(
462
                $this->totalPages,
463
                $this->totalPages === $this->currentPage
464
            );
465
        }
466
467
        return $pages;
468
    }
469
470
    /**
471
     * Render the pagination links
472
     * @return string
473
     */
474
    public function render(): string
475
    {
476
        return $this->renderer->render($this);
477
    }
478
479
    /**
480
     * Return the pagination details
481
     * @return array<string, mixed>
482
     */
483
    public function getInfo(): array
484
    {
485
        $pages = [];
486
        foreach ($this->getPages() as $page) {
487
            $pages[] = $page->getNumber();
488
        }
489
490
        return [
491
            'offset' => $this->getOffset(),
492
            'limit' => $this->getItemsPerPage(),
493
            'total_items' => $this->getTotalItems(),
494
            'total_page' => $this->getTotalPages(),
495
            'page' => $this->getCurrentPage(),
496
            'pages' => $pages,
497
            'next' => $this->getNextPage(),
498
            'previous' => $this->getPreviousPage(),
499
            'url' => $this->getUrlGenerator()->getUrlPattern(),
500
        ];
501
    }
502
503
    /**
504
     * The string representation of pagination
505
     * @return string
506
     */
507
    public function __toString(): string
508
    {
509
        return $this->render();
510
    }
511
512
    /**
513
     * Create page data
514
     * @param int $page
515
     * @param bool $isCurrent
516
     * @return Page
517
     */
518
    protected function createPage(int $page, bool $isCurrent = false): Page
519
    {
520
        return new Page(
521
            $page,
522
            $this->getPageUrl($page),
523
            $isCurrent,
524
        );
525
    }
526
527
    /**
528
     * Create page ellipsis data
529
     * @return Page
530
     */
531
    protected function createPageEllipsis(): Page
532
    {
533
        return new Page(
534
            '...',
535
            null,
536
            false,
537
        );
538
    }
539
540
    /**
541
     * Update the total pages information's
542
     * @return void
543
     */
544
    protected function updateTotalPages(): void
545
    {
546
        $this->totalPages = ($this->itemsPerPage <= 0)
547
                            ? 0
548
                            : (int) ceil($this->totalItems / $this->itemsPerPage);
549
    }
550
}
551