Completed
Push — master ( 46970d...7de56e )
by Timo
06:29
created

Paginator   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 252
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 30
lcom 1
cbo 2
dl 0
loc 252
ccs 74
cts 74
cp 1
rs 10
c 0
b 0
f 0

17 Methods

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