Completed
Push — master ( a7eca7...eff6ed )
by Timo
05:40
created

Paginator::_getNextPageUrl()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 4
cts 4
cp 1
rs 9.6666
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 0
crap 2
1
<?php
2
3
namespace hamburgscleanest\DataTables\Models\DataComponents;
4
5
use hamburgscleanest\DataTables\Facades\UrlHelper;
6
use hamburgscleanest\DataTables\Models\DataComponent;
7
use Illuminate\Database\Eloquent\Builder;
8
9
/**
10
 * Class Paginator
11
 * @package hamburgscleanest\DataTables\Models\DataComponents
12
 */
13
class Paginator extends DataComponent {
14
15
    /** @var int */
16
    private $_perPage;
17
18
    /** @var int */
19
    private $_currentPage;
20
21
    /** @var string */
22
    private $_firstPageSymbol = 'first';
23
24
    /** @var string */
25
    private $_previousPageSymbol = '←';
26
27
    /** @var string */
28
    private $_nextPageSymbol = '→';
29
30
    /** @var string */
31
    private $_lastPageSymbol = 'last';
32
33
    /** @var int */
34
    private $_surroundingPages = 2;
35
36
37
    /**
38
     * Paginator constructor.
39
     * @param int $perPage
40
     */
41 5
    public function __construct(int $perPage = 15)
42
    {
43 5
        $this->_perPage = $perPage;
44 5
    }
45
46
    /**
47
     * How many entries per page?
48
     *
49
     * @param int $perPage
50
     * @return Paginator
51
     */
52
    public function entriesPerPage($perPage = 15): Paginator
53
    {
54
        $this->_perPage = $perPage;
55
56
        return $this;
57
    }
58
59
    /**
60
     * How many surrounding pages should be shown?
61
     *
62
     * @param int $count
63
     * @return Paginator
64
     */
65
    public function surroundingPages($count = 2): Paginator
66
    {
67
        $this->_surroundingPages = $count;
68
69
        return $this;
70
    }
71
72
    /**
73
     * @return Builder
74
     */
75
    public function _shapeData(): Builder
76
    {
77
        if ($this->_perPage === 0)
78
        {
79
            return $this->_queryBuilder;
80
        }
81
82
        return $this->_queryBuilder->limit($this->_perPage)->offset(($this->_currentPage - 1) * $this->_perPage);
83
    }
84
85
    /**
86
     * Render the page links.
87
     *
88
     * @return string
89
     * @throws \RuntimeException
90
     */
91 4
    public function render(): string
92
    {
93 4
        if ($this->_perPage === 0)
94
        {
95 1
            return '<ul class="pagination"><li class="active">1</li></ul>';
96
        }
97
98
        return '<ul class="pagination">' .
99 3
               $this->_renderListItem($this->_currentPage - 1, $this->_getFirstPageUrl(), $this->_firstPageSymbol) .
100 3
               $this->_renderListItem($this->_currentPage - 1, $this->_getPreviousPageUrl(), $this->_previousPageSymbol) .
101 3
               $this->_renderPageList() .
102 3
               $this->_renderListItem($this->_currentPage + 1, $this->_getNextPageUrl(), $this->_nextPageSymbol) .
103 3
               $this->_renderListItem($this->_currentPage + 1, $this->_getLastPageUrl(), $this->_lastPageSymbol) .
104 3
               '</ul>';
105
    }
106
107
    /**
108
     * Renders a list item with a page link.
109
     *
110
     * @param int $pagenumber
111
     * @param string $url
112
     * @param string|null $symbol
113
     *
114
     * @return string
115
     */
116 3
    private function _renderListItem(int $pagenumber, ? string $url, ? string $symbol = null): string
117
    {
118 3
        if ($url === null)
119
        {
120 2
            return '';
121
        }
122
123 3
        return '<li' . ($pagenumber === $this->_currentPage ? ' class="active"' : '') . '><a href="' . $url . '">' . ($symbol ?? $pagenumber) . '</a></li>';
124
    }
125
126
    /**
127
     * @return null|string
128
     * @throws \RuntimeException
129
     */
130 3
    private function _getFirstPageUrl()
131
    {
132 3
        if ($this->_currentPage <= $this->_surroundingPages + 1)
133
        {
134 1
            return null;
135
        }
136
137 2
        return $this->_buildPageUrl(1);
138
    }
139
140
    /**
141
     * Generate URL to jump to {$pageNumber}.
142
     *
143
     * @param int $pageNumber
144
     * @return string
145
     *
146
     * @throws \RuntimeException
147
     */
148 3
    private function _buildPageUrl(int $pageNumber): string
149
    {
150 3
        $parameters = UrlHelper::parameterizeQuery($this->_request->getQueryString());
151 3
        $parameters['page'] = $pageNumber;
152
153 3
        return $this->_request->url() . '?' . \http_build_query($parameters);
154
    }
155
156
    /**
157
     * @return null|string
158
     * @throws \RuntimeException
159
     */
160 3
    private function _getPreviousPageUrl()
161
    {
162 3
        $previousPage = $this->_currentPage - 1;
163 3
        if ($previousPage < 1)
164
        {
165 1
            return null;
166
        }
167
168 2
        return $this->_buildPageUrl($previousPage);
169
    }
170
171
    /**
172
     * Renders a list of pages.
173
     *
174
     * @return string
175
     * @throws \RuntimeException
176
     */
177 3
    private function _renderPageList(): string
178
    {
179 3
        $end = $this->_getEndPage();
180
181 3
        $pageList = '';
182 3
        for ($i = $this->_getStartPage(); $i <= $end; $i ++)
183
        {
184 3
            $pageList .= $this->_renderListItem($i, $this->_buildPageUrl($i));
185
        }
186
187 3
        return $pageList;
188
    }
189
190
    /**
191
     * @return int
192
     */
193 3
    private function _getEndPage(): int
194
    {
195 3
        $end = $this->_currentPage + $this->_surroundingPages;
196 3
        $pageCount = $this->pageCount();
197
198 3
        return $end > $pageCount ? $pageCount : $end;
199
    }
200
201
    /**
202
     * @return int
203
     */
204 4
    public function pageCount(): int
205
    {
206 4
        if ($this->_perPage === 0)
207
        {
208 1
            return 1;
209
        }
210
211 3
        $queryCount = $this->getQueryCount();
212 3
        if ($queryCount < $this->_perPage)
213
        {
214
            return 1;
215
        }
216
217 3
        return (int) \ceil($queryCount / $this->_perPage);
218
    }
219
220
    /**
221
     * @return int
222
     */
223 3
    private function _getStartPage(): int
224
    {
225 3
        $start = $this->_currentPage - $this->_surroundingPages;
226
227 3
        return $start < 1 ? 1 : $start;
228
    }
229
230
    /**
231
     * @return null|string
232
     * @throws \RuntimeException
233
     */
234 3
    private function _getNextPageUrl()
235
    {
236 3
        if ($this->_currentPage >= $this->pageCount())
237
        {
238 1
            return null;
239
        }
240
241 2
        return $this->_buildPageUrl($this->_currentPage + 1);
242
    }
243
244
    /**
245
     * @return null|string
246
     * @throws \RuntimeException
247
     */
248 3
    private function _getLastPageUrl()
249
    {
250 3
        $lastPage = $this->pageCount();
251 3
        if ($this->_currentPage + $this->_surroundingPages >= $lastPage)
252
        {
253 1
            return null;
254
        }
255
256 2
        return $this->_buildPageUrl($lastPage);
257
    }
258
259 5
    protected function _afterInit()
260
    {
261 5
        $this->_currentPage = + $this->_request->get('page', 1);
262
    }
263
}