GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Paginator::setOptions()   A
last analyzed

Complexity

Conditions 5
Paths 16

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 10
cts 10
cp 1
rs 9.3554
c 0
b 0
f 0
cc 5
nc 16
nop 1
crap 5
1
<?php declare(strict_types=1);
2
/**
3
 * Paginator.
4
 *
5
 * @copyright Copyright (c) 2016 Starweb AB
6
 * @license   BSD 3-Clause
7
 */
8
9
namespace Starlit\Paginator;
10
11
use Symfony\Component\HttpFoundation\Request;
12
13
/**
14
 * @author Andreas Nilsson <http://github.com/jandreasn>
15
 * @author David Ajnered <https://github.com/davidajnered>
16
 */
17
class Paginator
18
{
19
    /**
20
     * @var int
21
     */
22
    protected $currentPageNo;
23
24
    /**
25
     * @var int
26
     */
27
    protected $pages;
28
29
    /**
30
     * @var int
31
     */
32
    protected $maxPagesToShow = 9; // Use odd number so that one number can be in the middle
33
34
    /**
35
     * @var callable
36
     */
37
    protected $urlGenerator;
38
39
    /**
40
     * @var Request|null
41
     */
42
    protected $request;
43
44
    /**
45
     * @var string
46
     */
47
    protected $containerCssClass = 'pagination';
48
49
    /**
50
     * @var string
51
     */
52
    protected $description;
53
54
    /**
55
     * If description should be shown regardless of number of pages.
56
     *
57
     * @var bool
58
     */
59
    protected $alwaysShowDescription = false;
60
61
    /**
62
     * Constructor.
63
     *
64
     * @param int $currentPageNo
65
     * @param int $rowsPerPage
66
     * @param int $totalRowCount
67
     * @param callable|Request $urlGeneratorOrRequest
68
     * @param array $options
69
     */
70 10
    public function __construct(
71
        int $currentPageNo,
72
        int $rowsPerPage,
73
        int $totalRowCount,
74
        $urlGeneratorOrRequest,
75
        array $options = []
76
    ) {
77 10
        $this->currentPageNo = $currentPageNo;
78
79 10
        $this->pages = (int) ceil($totalRowCount / $rowsPerPage);
80 10
        $this->pages = ($this->pages < 1) ? 1 : $this->pages; // Pages should never be less than 1
81
82 10
        if (is_callable($urlGeneratorOrRequest)) {
83 1
            $this->urlGenerator = $urlGeneratorOrRequest;
84 9
        } elseif ($urlGeneratorOrRequest instanceof Request) {
85 8
            $this->request = $urlGeneratorOrRequest;
86
        } else {
87 1
            throw new \InvalidArgumentException(
88 1
                'Argument must be either a Request or a callable url generator'
89
            );
90
        }
91
92 9
        $this->setOptions($options);
93 9
    }
94
95
    /**
96
     * @param array $options
97
     */
98 9
    public function setOptions(array $options = []): void
99
    {
100 9
        if (isset($options['maxPagesToShow'])) {
101 1
            $this->maxPagesToShow = (int) $options['maxPagesToShow'];
102
        }
103
104 9
        if (isset($options['containerCssClass'])) {
105 1
            $this->containerCssClass = $options['containerCssClass'];
106
        }
107
108 9
        if (isset($options['description'])) {
109 1
            $this->description = $options['description'];
110
        }
111
112 9
        if (isset($options['alwaysShowDescription'])) {
113 1
            $this->alwaysShowDescription = (bool) $options['alwaysShowDescription'];
114
        }
115 9
    }
116
117
    /**
118
     * @return string
119
     */
120 9
    public function getHtml(): string
121
    {
122 9
        $leftRightSpan = (($this->maxPagesToShow - 1) / 2);
123 9
        $showAll = false;
124
125 9
        if ($this->pages > $this->maxPagesToShow) {
126
            // Default start and end values. This works as long the selected page is not to close to the edges
127 4
            $paginationStart = $this->currentPageNo - $leftRightSpan + 1;
128 4
            $paginationStart = ($paginationStart < 2) ? 2 : $paginationStart;
129
130 4
            $paginationEnd = $this->currentPageNo + $leftRightSpan - 1;
131 4
            $paginationEnd = ($paginationEnd > ($this->pages - 1)) ? $this->pages - 1 : $paginationEnd;
132
133
            // If we're closer to the left side
134 4
            if ($this->currentPageNo <= $leftRightSpan) {
135 2
                $paginationEnd += $leftRightSpan - $this->currentPageNo + 1;
136
            }
137
138
            // If we're closer to the right side
139 4
            if ($this->currentPageNo >= $this->pages - $leftRightSpan) {
140 1
                $paginationStart -= $leftRightSpan - ($this->pages - $this->currentPageNo);
141
            }
142
143
            // If dots will be shown to the left, show one less list item so that the total list
144
            // item count won't be more than max
145 4
            if (($this->currentPageNo - 1) > $leftRightSpan) {
146 2
                $paginationStart++;
147
            }
148
149
            // If dots will be shown to the right, show one less list item
150 4
            if ($this->currentPageNo < ($this->pages - $leftRightSpan)) {
151 4
                $paginationEnd--;
152
            }
153
        } else {
154 5
            $paginationStart = 2;
155 5
            $paginationEnd = $this->pages - 1;
156 5
            $showAll = true;
157
        }
158
159
160 9
        $html = '<div class="'. $this->containerCssClass . ' ' . ($this->hasMultiplePages()
161 8
            ? 'multiple-pages'
162 9
            : 'single-page') . '">';
163
164 9
        if ($this->description && ($this->alwaysShowDescription || $this->hasMultiplePages())) {
165 1
            $html .= '<p>' . $this->description . '</p>';
166
        }
167
168 9
        if ($this->hasMultiplePages()) {
169 8
            $html .= '<ul>';
170
171
            // Prev link
172 8
            $html .= $this->getListItemHtml('prev');
173
174
            // Permanent first link
175 8
            $html .= $this->getListItemHtml(1);
176
177
            // If there are more than 4 links to the left of active link, show dots
178 8
            if (!$showAll && ($this->currentPageNo - 1) > $leftRightSpan) {
179 2
                $html .= '<li class="disabled gap"><span>...</span></li>';
180
            }
181
182
            // Loop and build links
183 8
            for ($page = $paginationStart; $page <= $paginationEnd; $page++) {
184 5
                $html .= $this->getListItemHtml($page);
185
            }
186
187
            // If there are more than 4 links to the right of active link, show dots
188 8
            if (!$showAll && $this->currentPageNo < ($this->pages - $leftRightSpan)) {
189 3
                $html .= '<li class="disabled gap"><span>...</span></li>';
190
            }
191
192
            // Permanent last link
193 8
            if ($this->pages > 1) {
194 8
                $html .= $this->getListItemHtml($this->pages);
195
            }
196
197
            // Next link
198 8
            $html .= $this->getListItemHtml('next');
199
200 8
            $html .= '</ul>';
201
        }
202
203 9
        $html .= '</div>';
204
205 9
        return $html;
206
    }
207
208
    /**
209
     * @param mixed $listItem Either a page number, or the strings 'prev' or 'next'
210
     * @return string
211
     */
212 8
    protected function getListItemHtml($listItem): string
213
    {
214 8
        $cssClass = '';
215 8
        $disabled = false;
216
        switch ($listItem) {
217 8
            case 'prev':
218 8
                $linkText = '&laquo;';
219 8
                $page = $this->currentPageNo - 1;
220 8
                $cssClass = 'previous';
221
222 8
                if ($this->currentPageNo === 1) {
223 5
                    $disabled = true;
224
                }
225
226 8
                break;
227 8
            case 'next':
228 8
                $linkText = '&raquo;';
229 8
                $page = $this->currentPageNo + 1;
230 8
                $cssClass = 'next';
231
232 8
                if ($this->currentPageNo === $this->pages) {
233 1
                    $disabled = true;
234
                }
235
236 8
                break;
237
            default:
238 8
                $linkText = $listItem;
239 8
                $page = (int) $listItem;
240
241 8
                if ($page === $this->currentPageNo) {
242 8
                    $cssClass = 'active';
243
                }
244 8
                break;
245
        }
246
247 8
        if ($disabled) {
248 6
            $cssClass .= ' disabled';
249
        }
250
251 8
        $html = '<li' . ($cssClass ? ' class="' . $cssClass . '"' : '') . '>';
252
253 8
        if ($disabled) {
254 6
            $html .= '<span>' . $linkText . '</span>';
255
        } else {
256 8
            $html .= '<a href="' . $this->getUrl($page) . '">' . $linkText . '</a>';
257
        }
258
259 8
        $html .= '</li>';
260
261
262 8
        return $html;
263
    }
264
265
    /**
266
     * @param int $page
267
     * @return string
268
     */
269 8
    protected function getUrl(int $page): string
270
    {
271 8
        if ($this->urlGenerator) {
272 1
            return call_user_func($this->urlGenerator, $page);
273
        }
274
275 7
        return $this->getRequestUrlWithNewPage($page);
276
    }
277
278
    /**
279
     * @param int $page
280
     * @return string
281
     */
282 7
    protected function getRequestUrlWithNewPage(int $page): string
283
    {
284
        // Make up paginated url from current url
285 7
        $url = $this->request->getRequestUri();
286 7
        $urlWithoutQueryString = (($pos = strpos($url, '?')) !== false) ? substr($url, 0, $pos) : $url;
287 7
        $parameters = array_merge($this->request->query->all(), ['page' => $page]);
288 7
        $newQueryString = http_build_query($parameters, '', '&amp;');
289
290 7
        return $urlWithoutQueryString . '?' . $newQueryString;
291
    }
292
293
    /**
294
     * @return bool
295
     */
296 9
    public function hasMultiplePages(): bool
297
    {
298 9
        return ($this->pages > 1);
299
    }
300
301
    /**
302
     * @return string
303
     */
304 1
    public function __toString(): string
305
    {
306 1
        return $this->getHtml();
307
    }
308
}
309