• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

codeigniter4 / CodeIgniter4 / 12673986434

08 Jan 2025 03:42PM UTC coverage: 84.455% (+0.001%) from 84.454%
12673986434

Pull #9385

github

web-flow
Merge 06e47f0ee into e475fd8fa
Pull Request #9385: refactor: Fix phpstan expr.resultUnused

20699 of 24509 relevant lines covered (84.45%)

190.57 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.56
/system/Pager/PagerRenderer.php
1
<?php
2

3
declare(strict_types=1);
4

5
/**
6
 * This file is part of CodeIgniter 4 framework.
7
 *
8
 * (c) CodeIgniter Foundation <admin@codeigniter.com>
9
 *
10
 * For the full copyright and license information, please view
11
 * the LICENSE file that was distributed with this source code.
12
 */
13

14
namespace CodeIgniter\Pager;
15

16
use CodeIgniter\HTTP\URI;
17

18
/**
19
 * Class PagerRenderer
20
 *
21
 * This class is passed to the view that describes the pagination,
22
 * and is used to get the link information and provide utility
23
 * methods needed to work with pagination.
24
 *
25
 * @see \CodeIgniter\Pager\PagerRendererTest
26
 */
27
class PagerRenderer
28
{
29
    /**
30
     * First page number in the set of links to be displayed.
31
     *
32
     * @var int
33
     */
34
    protected $first;
35

36
    /**
37
     * Last page number in the set of links to be displayed.
38
     *
39
     * @var int
40
     */
41
    protected $last;
42

43
    /**
44
     * Current page number.
45
     *
46
     * @var int
47
     */
48
    protected $current;
49

50
    /**
51
     * Total number of items.
52
     *
53
     * @var int
54
     */
55
    protected $total;
56

57
    /**
58
     * Total number of pages.
59
     *
60
     * @var int
61
     */
62
    protected $pageCount;
63

64
    /**
65
     * URI base for pagination links
66
     *
67
     * @var URI
68
     */
69
    protected $uri;
70

71
    /**
72
     * Segment number used for pagination.
73
     *
74
     * @var int
75
     */
76
    protected $segment;
77

78
    /**
79
     * Name of $_GET parameter
80
     *
81
     * @var string
82
     */
83
    protected $pageSelector;
84

85
    /**
86
     * Returns the number of results per page that should be shown.
87
     */
88
    protected ?int $perPage;
89

90
    /**
91
     * The number of items the page starts with.
92
     */
93
    protected ?int $perPageStart = null;
94

95
    /**
96
     * The number of items the page ends with.
97
     */
98
    protected ?int $perPageEnd = null;
99

100
    /**
101
     * Constructor.
102
     */
103
    public function __construct(array $details)
104
    {
105
        // `first` and `last` will be updated by `setSurroundCount()`.
106
        // You must call `setSurroundCount()` after instantiation.
107
        $this->first = 1;
41✔
108
        $this->last  = $details['pageCount'];
41✔
109

110
        $this->current      = $details['currentPage'];
41✔
111
        $this->total        = $details['total'];
41✔
112
        $this->uri          = $details['uri'];
41✔
113
        $this->pageCount    = $details['pageCount'];
41✔
114
        $this->segment      = $details['segment'] ?? 0;
41✔
115
        $this->pageSelector = $details['pageSelector'] ?? 'page';
41✔
116
        $this->perPage      = $details['perPage'] ?? null;
41✔
117
        $this->updatePerPages();
41✔
118
    }
119

120
    /**
121
     * Sets the total number of links that should appear on either
122
     * side of the current page. Adjusts the first and last counts
123
     * to reflect it.
124
     *
125
     * @return PagerRenderer
126
     */
127
    public function setSurroundCount(?int $count = null)
128
    {
129
        $this->updatePages($count);
28✔
130

131
        return $this;
28✔
132
    }
133

134
    /**
135
     * Checks to see if there is a "previous" page before our "first" page.
136
     */
137
    public function hasPrevious(): bool
138
    {
139
        return $this->first > 1;
12✔
140
    }
141

142
    /**
143
     * Returns a URL to the "previous" page. The previous page is NOT the
144
     * page before the current page, but is the page just before the
145
     * "first" page.
146
     *
147
     * @return string|null
148
     */
149
    public function getPrevious()
150
    {
151
        if (! $this->hasPrevious()) {
8✔
152
            return null;
2✔
153
        }
154

155
        $uri = clone $this->uri;
7✔
156

157
        if ($this->segment === 0) {
7✔
158
            $uri->addQuery($this->pageSelector, $this->first - 1);
5✔
159
        } else {
160
            $uri->setSegment($this->segment, $this->first - 1);
2✔
161
        }
162

163
        return URI::createURIString(
7✔
164
            $uri->getScheme(),
7✔
165
            $uri->getAuthority(),
7✔
166
            $uri->getPath(),
7✔
167
            $uri->getQuery(),
7✔
168
            $uri->getFragment()
7✔
169
        );
7✔
170
    }
171

172
    /**
173
     * Checks to see if there is a "next" page after our "last" page.
174
     */
175
    public function hasNext(): bool
176
    {
177
        return $this->pageCount > $this->last;
12✔
178
    }
179

180
    /**
181
     * Returns a URL to the "next" page. The next page is NOT, the
182
     * page after the current page, but is the page that follows the
183
     * "last" page.
184
     *
185
     * @return string|null
186
     */
187
    public function getNext()
188
    {
189
        if (! $this->hasNext()) {
9✔
190
            return null;
2✔
191
        }
192

193
        $uri = clone $this->uri;
8✔
194

195
        if ($this->segment === 0) {
8✔
196
            $uri->addQuery($this->pageSelector, $this->last + 1);
6✔
197
        } else {
198
            $uri->setSegment($this->segment, $this->last + 1);
2✔
199
        }
200

201
        return URI::createURIString(
8✔
202
            $uri->getScheme(),
8✔
203
            $uri->getAuthority(),
8✔
204
            $uri->getPath(),
8✔
205
            $uri->getQuery(),
8✔
206
            $uri->getFragment()
8✔
207
        );
8✔
208
    }
209

210
    /**
211
     * Returns the URI of the first page.
212
     */
213
    public function getFirst(): string
214
    {
215
        $uri = clone $this->uri;
3✔
216

217
        if ($this->segment === 0) {
3✔
218
            $uri->addQuery($this->pageSelector, 1);
2✔
219
        } else {
220
            $uri->setSegment($this->segment, 1);
1✔
221
        }
222

223
        return URI::createURIString(
3✔
224
            $uri->getScheme(),
3✔
225
            $uri->getAuthority(),
3✔
226
            $uri->getPath(),
3✔
227
            $uri->getQuery(),
3✔
228
            $uri->getFragment()
3✔
229
        );
3✔
230
    }
231

232
    /**
233
     * Returns the URI of the last page.
234
     */
235
    public function getLast(): string
236
    {
237
        $uri = clone $this->uri;
3✔
238

239
        if ($this->segment === 0) {
3✔
240
            $uri->addQuery($this->pageSelector, $this->pageCount);
2✔
241
        } else {
242
            $uri->setSegment($this->segment, $this->pageCount);
1✔
243
        }
244

245
        return URI::createURIString(
3✔
246
            $uri->getScheme(),
3✔
247
            $uri->getAuthority(),
3✔
248
            $uri->getPath(),
3✔
249
            $uri->getQuery(),
3✔
250
            $uri->getFragment()
3✔
251
        );
3✔
252
    }
253

254
    /**
255
     * Returns the URI of the current page.
256
     */
257
    public function getCurrent(): string
258
    {
259
        $uri = clone $this->uri;
4✔
260

261
        if ($this->segment === 0) {
4✔
262
            $uri->addQuery($this->pageSelector, $this->current);
3✔
263
        } else {
264
            $uri->setSegment($this->segment, $this->current);
1✔
265
        }
266

267
        return URI::createURIString(
4✔
268
            $uri->getScheme(),
4✔
269
            $uri->getAuthority(),
4✔
270
            $uri->getPath(),
4✔
271
            $uri->getQuery(),
4✔
272
            $uri->getFragment()
4✔
273
        );
4✔
274
    }
275

276
    /**
277
     * Returns an array of links that should be displayed. Each link
278
     * is represented by another array containing of the URI the link
279
     * should go to, the title (number) of the link, and a boolean
280
     * value representing whether this link is active or not.
281
     *
282
     * @return list<array{uri:string, title:int, active:bool}>
283
     */
284
    public function links(): array
285
    {
286
        $links = [];
5✔
287

288
        $uri = clone $this->uri;
5✔
289

290
        for ($i = $this->first; $i <= $this->last; $i++) {
5✔
291
            $uri     = $this->segment === 0 ? $uri->addQuery($this->pageSelector, $i) : $uri->setSegment($this->segment, $i);
5✔
292
            $links[] = [
5✔
293
                'uri' => URI::createURIString(
5✔
294
                    $uri->getScheme(),
5✔
295
                    $uri->getAuthority(),
5✔
296
                    $uri->getPath(),
5✔
297
                    $uri->getQuery(),
5✔
298
                    $uri->getFragment()
5✔
299
                ),
5✔
300
                'title'  => $i,
5✔
301
                'active' => ($i === $this->current),
5✔
302
            ];
5✔
303
        }
304

305
        return $links;
5✔
306
    }
307

308
    /**
309
     * Updates the first and last pages based on $surroundCount,
310
     * which is the number of links surrounding the active page
311
     * to show.
312
     *
313
     * @param int|null $count The new "surroundCount"
314
     *
315
     * @return void
316
     */
317
    protected function updatePages(?int $count = null)
318
    {
319
        if ($count === null) {
28✔
320
            return;
1✔
321
        }
322

323
        $this->first = $this->current - $count > 0 ? $this->current - $count : 1;
28✔
324
        $this->last  = $this->current + $count <= $this->pageCount ? $this->current + $count : (int) $this->pageCount;
28✔
325
    }
326

327
    /**
328
     * Updates the start and end items per pages, which is
329
     * the number of items displayed on the active page.
330
     */
331
    protected function updatePerPages(): void
332
    {
333
        if ($this->total === null || $this->perPage === null) {
41✔
334
            return;
33✔
335
        }
336

337
        // When the page is the last, perform a different calculation.
338
        if ($this->last === $this->current) {
8✔
339
            $this->perPageStart = $this->perPage * ($this->current - 1) + 1;
4✔
340
            $this->perPageEnd   = $this->total;
4✔
341

342
            return;
4✔
343
        }
344

345
        $this->perPageStart = $this->current === 1 ? 1 : ($this->perPage * $this->current) - $this->perPage + 1;
6✔
346
        $this->perPageEnd   = $this->perPage * $this->current;
6✔
347
    }
348

349
    /**
350
     * Checks to see if there is a "previous" page before our "first" page.
351
     */
352
    public function hasPreviousPage(): bool
353
    {
354
        return $this->current > 1;
3✔
355
    }
356

357
    /**
358
     * Returns a URL to the "previous" page.
359
     *
360
     * You MUST call hasPreviousPage() first, or this value may be invalid.
361
     *
362
     * @return string|null
363
     */
364
    public function getPreviousPage()
365
    {
366
        if (! $this->hasPreviousPage()) {
3✔
367
            return null;
1✔
368
        }
369

370
        $uri = clone $this->uri;
2✔
371

372
        if ($this->segment === 0) {
2✔
373
            $uri->addQuery($this->pageSelector, $this->current - 1);
1✔
374
        } else {
375
            $uri->setSegment($this->segment, $this->current - 1);
1✔
376
        }
377

378
        return URI::createURIString(
2✔
379
            $uri->getScheme(),
2✔
380
            $uri->getAuthority(),
2✔
381
            $uri->getPath(),
2✔
382
            $uri->getQuery(),
2✔
383
            $uri->getFragment()
2✔
384
        );
2✔
385
    }
386

387
    /**
388
     * Checks to see if there is a "next" page after our "last" page.
389
     */
390
    public function hasNextPage(): bool
391
    {
392
        return $this->current < $this->last;
3✔
393
    }
394

395
    /**
396
     * Returns a URL to the "next" page.
397
     *
398
     * You MUST call hasNextPage() first, or this value may be invalid.
399
     *
400
     * @return string|null
401
     */
402
    public function getNextPage()
403
    {
404
        if (! $this->hasNextPage()) {
3✔
405
            return null;
1✔
406
        }
407

408
        $uri = clone $this->uri;
2✔
409

410
        if ($this->segment === 0) {
2✔
411
            $uri->addQuery($this->pageSelector, $this->current + 1);
1✔
412
        } else {
413
            $uri->setSegment($this->segment, $this->current + 1);
1✔
414
        }
415

416
        return URI::createURIString(
2✔
417
            $uri->getScheme(),
2✔
418
            $uri->getAuthority(),
2✔
419
            $uri->getPath(),
2✔
420
            $uri->getQuery(),
2✔
421
            $uri->getFragment()
2✔
422
        );
2✔
423
    }
424

425
    /**
426
     * Returns the page number of the first page in the set of links to be displayed.
427
     */
428
    public function getFirstPageNumber(): int
429
    {
430
        return $this->first;
2✔
431
    }
432

433
    /**
434
     * Returns the page number of the current page.
435
     */
436
    public function getCurrentPageNumber(): int
437
    {
438
        return $this->current;
2✔
439
    }
440

441
    /**
442
     * Returns the page number of the last page in the set of links to be displayed.
443
     */
444
    public function getLastPageNumber(): int
445
    {
446
        return $this->last;
2✔
447
    }
448

449
    /**
450
     * Returns total number of pages.
451
     */
452
    public function getPageCount(): int
453
    {
454
        return $this->pageCount;
1✔
455
    }
456

457
    /**
458
     * Returns the previous page number.
459
     */
460
    public function getPreviousPageNumber(): ?int
461
    {
462
        return ($this->current === 1) ? null : $this->current - 1;
2✔
463
    }
464

465
    /**
466
     * Returns the next page number.
467
     */
468
    public function getNextPageNumber(): ?int
469
    {
470
        return ($this->current === $this->pageCount) ? null : $this->current + 1;
2✔
471
    }
472

473
    /**
474
     * Returns the total items of the page.
475
     */
476
    public function getTotal(): ?int
477
    {
478
        return $this->total;
×
479
    }
480

481
    /**
482
     * Returns the number of items to be displayed on the page.
483
     */
484
    public function getPerPage(): ?int
485
    {
486
        return $this->perPage;
×
487
    }
488

489
    /**
490
     * Returns the number of items the page starts with.
491
     */
492
    public function getPerPageStart(): ?int
493
    {
494
        return $this->perPageStart;
5✔
495
    }
496

497
    /**
498
     * Returns the number of items the page ends with.
499
     */
500
    public function getPerPageEnd(): ?int
501
    {
502
        return $this->perPageEnd;
5✔
503
    }
504
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc