Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 20
CRAP
0.00% covered (danger)
0.00%
0 / 1
Pager
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 20
552
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
2
 getId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isFirstDisabled
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
 isPrevDisabled
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isNextDisabled
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
 isLastDisabled
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
 getCurrentOffset
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFirstOffset
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPrevOffset
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getNextOffset
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLastOffset
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getStartOrdinal
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getEndOrdinal
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTotalPages
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTotalResults
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLimit
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPosition
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPaginationSizeOptions
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPaginationSizeDefault
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getHtml
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Pager.php
4 *
5 * This file is part of the Codex design system, the official design system for Wikimedia projects.
6 * It contains the definition and implementation of the `Pager` class, responsible for managing
7 * the behavior and properties of the corresponding component.
8 *
9 * @category Component
10 * @package  Codex\Component
11 * @since    0.1.0
12 * @author   Doğu Abaris <abaris@null.net>
13 * @license  https://www.gnu.org/copyleft/gpl.html GPL-2.0-or-later
14 * @link     https://doc.wikimedia.org/codex/main/ Codex Documentation
15 */
16
17namespace Wikimedia\Codex\Component;
18
19use Wikimedia\Codex\Renderer\PagerRenderer;
20
21/**
22 * Pager
23 *
24 * This class is part of the Codex PHP library and is responsible for
25 * representing an immutable object. It is primarily intended for use
26 * with a builder class to construct its instances.
27 *
28 * @category Component
29 * @package  Codex\Component
30 * @since    0.1.0
31 * @author   Doğu Abaris <abaris@null.net>
32 * @license  https://www.gnu.org/copyleft/gpl.html GPL-2.0-or-later
33 * @link     https://doc.wikimedia.org/codex/main/ Codex Documentation
34 */
35class Pager {
36
37    /**
38     * The ID for the pager.
39     */
40    protected string $id;
41
42    /**
43     * Available options for the number of results displayed per page.
44     */
45    protected array $paginationSizeOptions;
46
47    /**
48     * Default pagination size.
49     */
50    protected int $paginationSizeDefault;
51
52    /**
53     * Total number of pages in the dataset.
54     */
55    protected int $totalPages;
56
57    /**
58     * Total number of results in the dataset.
59     */
60    protected int $totalResults;
61
62    /**
63     * Position of the pagination controls ('top', 'bottom', or 'both').
64     */
65    protected string $position;
66
67    /**
68     * Array of additional attributes for the pager.
69     */
70    protected array $attributes;
71
72    /**
73     * Number of results to display per page.
74     */
75    protected int $limit;
76
77    /**
78     * Offset of the current page.
79     */
80    protected ?int $currentOffset;
81
82    /**
83     * Offset for the next page.
84     */
85    protected ?int $nextOffset;
86
87    /**
88     * Offset for the previous page.
89     */
90    protected ?int $prevOffset;
91
92    /**
93     * Offset for the first page.
94     */
95    protected ?int $firstOffset;
96
97    /**
98     * Offset for the last page.
99     */
100    protected ?int $lastOffset;
101
102    /**
103     * Start ordinal for the current page.
104     */
105    protected int $startOrdinal;
106
107    /**
108     * End ordinal for the current page.
109     */
110    protected int $endOrdinal;
111
112    /**
113     * The renderer instance used to render the pager.
114     */
115    protected PagerRenderer $renderer;
116
117    /**
118     * Constructor for the Pager class.
119     *
120     * Initializes the Pager with the necessary properties.
121     *
122     * @param string $id The ID for the pager.
123     * @param array $paginationSizeOptions Available pagination size options.
124     * @param int $paginationSizeDefault Default pagination size.
125     * @param int $totalPages Total number of pages in the dataset.
126     * @param int $totalResults Total number of results in the dataset.
127     * @param string $position Position of the pagination controls.
128     * @param array $attributes Additional HTML attributes for the pager.
129     * @param int $limit Number of results per page.
130     * @param int|null $currentOffset Offset of the current page.
131     * @param int|null $nextOffset Offset for the next page.
132     * @param int|null $prevOffset Offset for the previous page.
133     * @param int|null $firstOffset Offset for the first page.
134     * @param int|null $lastOffset Offset for the last page.
135     * @param int $startOrdinal Start ordinal for the current page.
136     * @param int $endOrdinal End ordinal for the current page.
137     * @param PagerRenderer $renderer Instance of the renderer for rendering the pager.
138     */
139    public function __construct(
140        string $id,
141        array $paginationSizeOptions,
142        int $paginationSizeDefault,
143        int $totalPages,
144        int $totalResults,
145        string $position,
146        array $attributes,
147        int $limit,
148        ?int $currentOffset,
149        ?int $nextOffset,
150        ?int $prevOffset,
151        ?int $firstOffset,
152        ?int $lastOffset,
153        int $startOrdinal,
154        int $endOrdinal,
155        PagerRenderer $renderer
156    ) {
157        $this->id = $id;
158        $this->paginationSizeOptions = $paginationSizeOptions;
159        $this->paginationSizeDefault = $paginationSizeDefault;
160        $this->totalPages = $totalPages;
161        $this->totalResults = $totalResults;
162        $this->position = $position;
163        $this->attributes = $attributes;
164        $this->limit = $limit;
165        $this->currentOffset = $currentOffset;
166        $this->nextOffset = $nextOffset;
167        $this->prevOffset = $prevOffset;
168        $this->firstOffset = $firstOffset;
169        $this->lastOffset = $lastOffset;
170        $this->startOrdinal = $startOrdinal;
171        $this->endOrdinal = $endOrdinal;
172        $this->renderer = $renderer;
173    }
174
175    /**
176     * Get the Pager's HTML ID attribute.
177     *
178     * This method returns the ID assigned to the pager element, which is used
179     * for identifying the pager in the HTML document.
180     *
181     * @since 0.1.0
182     * @return string The ID of the Pager.
183     */
184    public function getId(): string {
185        return $this->id;
186    }
187
188    /**
189     * Determine if the first button should be disabled.
190     *
191     * This method checks whether the first button should be disabled based on the current page.
192     *
193     * @since 0.1.0
194     * @return bool Returns true if the first button should be disabled, false otherwise.
195     */
196    public function isFirstDisabled(): bool {
197        return $this->firstOffset == null && $this->prevOffset == null;
198    }
199
200    /**
201     * Determine if the previous button should be disabled.
202     *
203     * This method checks whether the previous button should be disabled based on the current page.
204     *
205     * @since 0.1.0
206     * @return bool Returns true if the previous button should be disabled, false otherwise.
207     */
208    public function isPrevDisabled(): bool {
209        return $this->prevOffset == null;
210    }
211
212    /**
213     * Determine if the next button should be disabled.
214     *
215     * This method checks whether the next button should be disabled based on the total results and the current page.
216     *
217     * @since 0.1.0
218     * @return bool Returns true if the next button should be disabled, false otherwise.
219     */
220    public function isNextDisabled(): bool {
221        return $this->nextOffset == null || $this->currentOffset == $this->lastOffset;
222    }
223
224    /**
225     * Determine if the last button should be disabled.
226     *
227     * This method checks whether the last button should be disabled based on the indeterminate state.
228     *
229     * @since 0.1.0
230     * @return bool Returns true if the last button should be disabled, false otherwise.
231     */
232    public function isLastDisabled(): bool {
233        return $this->nextOffset == null || $this->currentOffset == $this->lastOffset;
234    }
235
236    /**
237     * Get the current offset for the pager.
238     *
239     * This method returns the current offset value, which determines the
240     * starting point for the data on the current page. In cursor-based
241     * pagination, this offset is usually a timestamp or unique identifier.
242     *
243     * @since 0.1.0
244     * @return ?int The offset value for the current page.
245     */
246    public function getCurrentOffset(): ?int {
247        return $this->currentOffset;
248    }
249
250    /**
251     * Get the offset for the first page.
252     *
253     * This method returns the offset for the first page in cursor-based
254     * pagination. The first page offset usually represents the earliest
255     * timestamp or unique identifier in the dataset.
256     *
257     * @since 0.1.0
258     * @return ?int The offset value for the first page, or null if not set.
259     */
260    public function getFirstOffset(): ?int {
261        return $this->firstOffset;
262    }
263
264    /**
265     * Get the offset for the previous page.
266     *
267     * This method returns the offset for the previous page in cursor-based
268     * pagination. The previous page offset is typically the timestamp or
269     * unique identifier of the first item in the current page.
270     *
271     * @since 0.1.0
272     * @return ?int The offset value for the previous page, or null if not set.
273     */
274    public function getPrevOffset(): ?int {
275        return $this->prevOffset;
276    }
277
278    /**
279     * Get the offset for the next page.
280     *
281     * This method returns the offset for the next page in cursor-based
282     * pagination. The next page offset is typically the timestamp or
283     * unique identifier of the last item on the current page.
284     *
285     * @since 0.1.0
286     * @return ?int The offset value for the next page, or null if not set.
287     */
288    public function getNextOffset(): ?int {
289        return $this->nextOffset;
290    }
291
292    /**
293     * Get the offset for the last page.
294     *
295     * This method returns the offset for the last page in cursor-based
296     * pagination. The last page offset typically represents the timestamp
297     * or unique identifier of the last item in the dataset.
298     *
299     * @since 0.1.0
300     * @return ?int The offset value for the last page, or null if not set.
301     */
302    public function getLastOffset(): ?int {
303        return $this->lastOffset;
304    }
305
306    /**
307     * Get the start ordinal for the current page.
308     *
309     * @since 0.1.0
310     * @return int The start ordinal.
311     */
312    public function getStartOrdinal(): int {
313        return $this->startOrdinal;
314    }
315
316    /**
317     * Get the end ordinal for the current page.
318     *
319     * @since 0.1.0
320     * @return int The end ordinal.
321     */
322    public function getEndOrdinal(): int {
323        return $this->endOrdinal;
324    }
325
326    /**
327     * Get the total number of pages.
328     *
329     * This method returns the total number of pages available based on the dataset.
330     *
331     * @since 0.1.0
332     * @return int The total number of pages.
333     */
334    public function getTotalPages(): int {
335        return $this->totalPages;
336    }
337
338    /**
339     * Get the total number of results.
340     *
341     * This method returns the total number of results in the dataset.
342     *
343     * @since 0.1.0
344     * @return int The total number of results.
345     */
346    public function getTotalResults(): int {
347        return $this->totalResults;
348    }
349
350    /**
351     * Get the limit for the pager.
352     *
353     * This method returns the number of results to be displayed per page.
354     *
355     * @since 0.1.0
356     * @return int The number of results per page.
357     */
358    public function getLimit(): int {
359        return $this->limit;
360    }
361
362    /**
363     * Get the position of the pagination controls.
364     *
365     * This method returns the position where the pagination controls are displayed. Valid positions
366     * are 'top', 'bottom', or 'both'.
367     *
368     * @since 0.1.0
369     * @return string The position of the pagination controls.
370     */
371    public function getPosition(): string {
372        return $this->position;
373    }
374
375    /**
376     * Get the pagination size options.
377     *
378     * This method returns the available options for the number of results displayed per page.
379     * Users can select from these options in a dropdown.
380     *
381     * @since 0.1.0
382     * @return array The array of pagination size options.
383     */
384    public function getPaginationSizeOptions(): array {
385        return $this->paginationSizeOptions;
386    }
387
388    /**
389     * Get the default pagination size.
390     *
391     * This method returns the default number of rows displayed per page.
392     *
393     * @since 0.1.0
394     * @return int The default pagination size.
395     */
396    public function getPaginationSizeDefault(): int {
397        return $this->paginationSizeDefault;
398    }
399
400    /**
401     * Get the component's HTML representation.
402     *
403     * This method generates the HTML markup for the component, incorporating relevant properties
404     * and any additional attributes. The component is structured using appropriate HTML elements
405     * as defined by the implementation.
406     *
407     * @since 0.1.0
408     * @return string The generated HTML string for the component.
409     */
410    public function getHtml(): string {
411        return $this->renderer->render( $this );
412    }
413}