Completed
Push — master ( 3dacb7...bbcbbc )
by Timo
05:19
created

Paginator::pageCount()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

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