Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
83.08% covered (success)
83.08%
54 / 65
80.00% covered (success)
80.00%
8 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
Range
83.08% covered (success)
83.08%
54 / 65
80.00% covered (success)
80.00%
8 / 10
40.94
0.00% covered (danger)
0.00%
0 / 1
 setSeparator
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setClassOn
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setClassOff
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getSeparator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLinkRange
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 getClassOn
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getClassOff
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createRange
75.61% covered (success)
75.61%
31 / 41
0.00% covered (danger)
0.00%
0 / 1
21.19
 wrapLinks
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
6
 __toString
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
2.15
1<?php
2/**
3 * Pop PHP Framework (http://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@nolainteractive.com>
7 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
8 * @license    http://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Paginator;
15
16/**
17 * Paginator range of links class
18 *
19 * @category   Pop
20 * @package    Pop\Paginator
21 * @author     Nick Sagona, III <dev@nolainteractive.com>
22 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
23 * @license    http://www.popphp.org/license     New BSD License
24 * @version    4.0.0
25 */
26class Range extends AbstractPaginator
27{
28
29    /**
30     * Link separator
31     * @var ?string
32     */
33    protected ?string $separator = null;
34
35    /**
36     * Page links property
37     * @var array
38     */
39    protected array $links = [];
40
41    /**
42     * Class 'on' name for page link tags
43     * @var ?string
44     */
45    protected ?string $classOn = null;
46
47    /**
48     * Class 'off' name for page link tags
49     * @var ?string
50     */
51    protected ?string $classOff = null;
52
53    /**
54     * Set the bookend separator
55     *
56     * @param  string $sep
57     * @return Range
58     */
59    public function setSeparator(string $sep): Range
60    {
61        $this->separator = $sep;
62        return $this;
63    }
64
65    /**
66     * Set the class 'on' name
67     *
68     * @param  string $class
69     * @return Range
70     */
71    public function setClassOn(string $class): Range
72    {
73        $this->classOn = $class;
74        return $this;
75    }
76
77    /**
78     * Set the class 'off' name.
79     *
80     * @param  string $class
81     * @return Range
82     */
83    public function setClassOff(string $class): Range
84    {
85        $this->classOff = $class;
86        return $this;
87    }
88
89    /**
90     * Get the bookend separator
91     *
92     * @return string
93     */
94    public function getSeparator(): string
95    {
96        return $this->separator;
97    }
98
99    /**
100     * Get the page links
101     *
102     * @param  ?int $page
103     * @return array
104     */
105    public function getLinkRange(?int $page = null): array
106    {
107        if ($page === null) {
108            $page = (isset($_GET[$this->queryKey]) && ((int)$_GET[$this->queryKey] > 0)) ? (int)$_GET[$this->queryKey] : 1;
109        }
110        $this->calculateRange($page);
111        $this->createRange($page);
112
113        return $this->links;
114    }
115
116    /**
117     * Get the class 'on' name
118     *
119     * @return string
120     */
121    public function getClassOn(): string
122    {
123        return $this->classOn;
124    }
125
126    /**
127     * Get the class 'off' name.
128     *
129     * @return string
130     */
131    public function getClassOff(): string
132    {
133        return $this->classOff;
134    }
135
136    /**
137     * Create links
138     *
139     * @param  int  $page
140     * @return void
141     */
142    public function createRange(int $page = 1): void
143    {
144        $this->currentPage = $page;
145
146        // Generate the page links.
147        $this->links = [];
148
149        // Preserve any passed GET parameters.
150        $query = null;
151        $uri   = null;
152
153        if (isset($_SERVER['REQUEST_URI'])) {
154            $uri = (!empty($_SERVER['QUERY_STRING'])) ?
155                str_replace('?' . $_SERVER['QUERY_STRING'], '', $_SERVER['REQUEST_URI']) :
156                $_SERVER['REQUEST_URI'];
157
158            if (count($_GET) > 0) {
159                $get = $_GET;
160                if (isset($get[$this->queryKey])) {
161                    unset($get[$this->queryKey]);
162                }
163                $query = '&' . http_build_query($get);
164            }
165        }
166
167        // Calculate page range
168        $pageRange = $this->calculateRange($page);
169
170        for ($i = $pageRange['start']; $i <= $pageRange['end']; $i++) {
171            $newLink  = null;
172            $prevLink = null;
173            $nextLink = null;
174            $classOff = ($this->classOff !== null) ? " class=\"{$this->classOff}\"" : null;
175            $classOn  = ($this->classOn !== null) ? " class=\"{$this->classOn}\"" : null;
176
177            $newLink = ($i == $page) ? "<span{$classOff}>{$i}</span>" : "<a{$classOn} href=\"" . $uri . "?" .
178                $this->queryKey . "={$i}{$query}\">{$i}</a>";
179
180            if (($i == $pageRange['start']) && ($pageRange['prev'])) {
181                if ($this->bookends['start'] !== null) {
182                    $startLink = "<a{$classOn} href=\"" . $uri . "?" . $this->queryKey . "=1" . "{$query}\">" .
183                        $this->bookends['start'] . "</a>";
184                    $this->links[] = $startLink;
185                }
186                if ($this->bookends['previous'] !== null) {
187                    $prevLink  = "<a{$classOn} href=\"" . $uri . "?" . $this->queryKey . "=" . ($i - 1) . "{$query}\">" .
188                        $this->bookends['previous'] . "</a>";
189                    $this->links[] = $prevLink;
190                }
191            }
192
193            $this->links[] = $newLink;
194
195            if (($i == $pageRange['end']) && ($pageRange['next'])) {
196                if ($this->bookends['next'] !== null) {
197                    $nextLink = "<a{$classOn} href=\"" . $uri . "?" . $this->queryKey . "=" . ($i + 1) . "{$query}\">" .
198                        $this->bookends['next'] . "</a>";
199                    $this->links[] = $nextLink;
200                }
201                if ($this->bookends['end'] !== null) {
202                    $endLink  = "<a{$classOn} href=\"" . $uri . "?" . $this->queryKey . "=" . $this->numberOfPages .
203                        "{$query}\">" . $this->bookends['end'] . "</a>";
204                    $this->links[] = $endLink;
205                }
206            }
207        }
208    }
209
210    /**
211     * Wrap page links in an HTML node
212     *
213     * @param  string  $node
214     * @param  ?string $classOn
215     * @param  ?string $classOff
216     * @return array
217     */
218    public function wrapLinks(string $node, ?string $classOn = null, ?string $classOff = null): array
219    {
220        if (empty($this->links)) {
221            $this->getLinkRange();
222        }
223        $classOff = ($classOff !== null) ? " class=\"{$classOff}\"" : null;
224        $classOn  = ($classOn !== null) ? " class=\"{$classOn}\"" : null;
225
226        foreach ($this->links as $i => $link) {
227            $this->links[$i] = '<' . $node . ((str_contains($link, 'span')) ? $classOff : $classOn) . '>' . $link . '</' . $node . '>';
228        }
229
230        return $this->links;
231    }
232
233    /**
234     * Output the rendered page links
235     *
236     * @return string
237     */
238    public function __toString(): string
239    {
240        if (empty($this->links)) {
241            $this->getLinkRange();
242        }
243        return implode((string)$this->separator, $this->links) . PHP_EOL;
244    }
245
246}