Completed
Push — master ( a35e5d...c48d7b )
by Timo
03:03
created

Paginator   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 251
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 91.8%

Importance

Changes 0
Metric Value
wmc 29
lcom 1
cbo 2
dl 0
loc 251
ccs 56
cts 61
cp 0.918
rs 10
c 0
b 0
f 0

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A entriesPerPage() 0 6 1
A surroundingPages() 0 6 1
A _shapeData() 0 9 2
A render() 0 15 2
A _renderListItem() 0 9 3
A _getFirstPageUrl() 0 9 2
A _buildPageUrl() 0 7 1
A _getPreviousPageUrl() 0 10 2
A _renderPageList() 0 12 2
A _getEndPage() 0 7 2
A pageCount() 0 15 3
A _getStartPage() 0 6 2
A _getNextPageUrl() 0 9 2
A _getLastPageUrl() 0 10 2
A _afterInit() 0 4 1
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 3
    public function __construct(int $perPage = 15)
42
    {
43 3
        $this->_perPage = $perPage;
44 3
    }
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 2
    public function render(): string
92
    {
93 2
        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 1
               $this->_renderListItem($this->_currentPage - 1, $this->_getFirstPageUrl(), $this->_firstPageSymbol) .
100 1
               $this->_renderListItem($this->_currentPage - 1, $this->_getPreviousPageUrl(), $this->_previousPageSymbol) .
101 1
               $this->_renderPageList() .
102 1
               $this->_renderListItem($this->_currentPage + 1, $this->_getNextPageUrl(), $this->_nextPageSymbol) .
103 1
               $this->_renderListItem($this->_currentPage + 1, $this->_getLastPageUrl(), $this->_lastPageSymbol) .
104 1
               '</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 1
    private function _renderListItem(int $pagenumber, ? string $url, ? string $symbol = null): string
117
    {
118 1
        if ($url === null)
119
        {
120 1
            return '';
121
        }
122
123 1
        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 1
    private function _getFirstPageUrl()
131
    {
132 1
        if ($this->_currentPage <= $this->_surroundingPages + 1)
133
        {
134 1
            return null;
135
        }
136
137
        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 1
    private function _buildPageUrl(int $pageNumber): string
149
    {
150 1
        $parameters = UrlHelper::parameterizeQuery($this->_request->getQueryString());
151 1
        $parameters['page'] = $pageNumber;
152
153 1
        return $this->_request->url() . '?' . \http_build_query($parameters);
154
    }
155
156
    /**
157
     * @return null|string
158
     * @throws \RuntimeException
159
     */
160 1
    private function _getPreviousPageUrl()
161
    {
162 1
        $previousPage = $this->_currentPage - 1;
163 1
        if ($previousPage < 1)
164
        {
165 1
            return null;
166
        }
167
168
        return $this->_buildPageUrl($previousPage);
169
    }
170
171
    /**
172
     * Renders a list of pages.
173
     *
174
     * @return string
175
     * @throws \RuntimeException
176
     */
177 1
    private function _renderPageList(): string
178
    {
179 1
        $end = $this->_getEndPage();
180
181 1
        $pageList = '';
182 1
        for ($i = $this->_getStartPage(); $i <= $end; $i ++)
183
        {
184 1
            $pageList .= $this->_renderListItem($i, $this->_buildPageUrl($i));
185
        }
186
187 1
        return $pageList;
188
    }
189
190
    /**
191
     * @return int
192
     */
193 1
    private function _getEndPage(): int
194
    {
195 1
        $end = $this->_currentPage + $this->_surroundingPages;
196 1
        $pageCount = $this->pageCount();
197
198 1
        return $end > $pageCount ? $pageCount : $end;
199
    }
200
201
    /**
202
     * @return int
203
     */
204 2
    public function pageCount(): int
205
    {
206 2
        if ($this->_perPage === 0)
207
        {
208 1
            return 1;
209
        }
210
211 1
        $queryCount = $this->getQueryCount();
212 1
        if ($queryCount < $this->_perPage)
213
        {
214
            return 1;
215
        }
216
217 1
        return (int) \floor($queryCount / $this->_perPage);
218
    }
219
220
    /**
221
     * @return int
222
     */
223 1
    private function _getStartPage(): int
224
    {
225 1
        $start = $this->_currentPage - $this->_surroundingPages;
226
227 1
        return $start < 1 ? 1 : $start;
228
    }
229
230
    /**
231
     * @return null|string
232
     * @throws \RuntimeException
233
     */
234 1
    private function _getNextPageUrl()
235
    {
236 1
        if ($this->_currentPage >= $this->pageCount())
237
        {
238
            return null;
239
        }
240
241 1
        return $this->_buildPageUrl($this->_currentPage + 1);
242
    }
243
244
    /**
245
     * @return null|string
246
     * @throws \RuntimeException
247
     */
248 1
    private function _getLastPageUrl()
249
    {
250 1
        $lastPage = $this->pageCount();
251 1
        if ($this->_currentPage + $this->_surroundingPages >= $lastPage)
252
        {
253
            return null;
254
        }
255
256 1
        return $this->_buildPageUrl($lastPage);
257
    }
258
259 3
    protected function _afterInit()
260
    {
261 3
        $this->_currentPage = + $this->_request->get('page', 1);
262
    }
263
}