Passed
Pull Request — master (#154)
by
unknown
03:55
created

Paginator::currentPageLink()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 7
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace Quantum\Libraries\Database\Idiorm;
4
5
use Quantum\Libraries\Database\PaginatorInterface;
6
use Quantum\Exceptions\DatabaseException;
7
use IdiormResultSet;
8
9
class Paginator implements PaginatorInterface
10
{
11
	/**
12
	 * @var int
13
	 */
14
	private $total;
15
16
	/**
17
	 * @var IdiormDbal
18
	 */
19
	private $dbal;
20
21
	/**
22
	 * @var int
23
	 */
24
	protected $per_page;
25
26
	/**
27
	 * @var int
28
	 */
29
	protected $page;
30
31
	/**
32
	 * @var array|IdiormResultSet
33
	 */
34
	public $data;
35
36
	/**
37
	 * @param $idiormDbal
38
	 * @param int $per_page
39
	 * @param int $page
40
	 * @throws DatabaseException
41
	 */
42
	public function __construct($idiormDbal, int $per_page, int $page = 1)
43
	{
44
		/** @var IdiormDbal $idiormDbal */
45
		$this->setTotal($idiormDbal);
46
		$this->dbal = $idiormDbal;
47
		$this->dbal->limit($per_page)->offset($per_page * ($page - 1));
48
		$this->data = $this->dbal->getOrmModel()->find_many();
49
		$this->per_page = $per_page;
50
		$this->page = $page;
51
	}
52
53
	/**
54
	 * @return int
55
	 */
56
	public function currentPageNumber(): int
57
	{
58
		return $this->page;
59
	}
60
61
	/**
62
	 * @param bool $withBaseUrl
63
	 * @return string|null
64
	 */
65
	public function currentPageLink(bool $withBaseUrl = false): ?string
66
	{
67
		$current = null;
68
		if (!empty($this->page)) {
69
			$current = $this->getUri($withBaseUrl) . 'per_page=' . $this->per_page . '&page=' . $this->page;
70
		}
71
		return $current;
72
	}
73
74
	/**
75
	 * @return int|null
76
	 */
77
	public function previousPageNumber(): ?int
78
	{
79
		$previous = null;
80
		if ($this->page > 1) {
81
			$previous = $this->page - 1;
82
		} elseif ($this->page == 1) {
83
			$previous = $this->page;
84
		}
85
86
		return $previous;
87
	}
88
89
	/**
90
	 * @param bool $withBaseUrl
91
	 * @return string|null
92
	 */
93
	public function previousPageLink(bool $withBaseUrl = false): ?string
94
	{
95
		$previous = null;
96
		if (!empty($this->previousPageNumber())) {
97
			$previous = $this->getUri($withBaseUrl) . 'per_page=' . $this->per_page . '&page=' . $this->previousPageNumber();
98
		}
99
		return $previous;
100
	}
101
102
	/**
103
	 * @return int|null
104
	 */
105
	public function nextPageNumber(): ?int
106
	{
107
		$next = null;
108
		if ($this->page < $this->lastPageNumber()) {
109
			$next = $this->page + 1;
110
		} elseif ($this->page == $this->lastPageNumber()) {
111
			$next = $this->page;
112
		}
113
		return $next;
114
	}
115
116
	/**
117
	 * @param bool $withBaseUrl
118
	 * @return string|null
119
	 */
120
	public function nextPageLink(bool $withBaseUrl = false): ?string
121
	{
122
		$next = null;
123
		if (!empty($this->nextPageNumber())) {
124
			$next = $this->getUri($withBaseUrl) . 'per_page=' . $this->per_page . '&page=' . $this->nextPageNumber();
125
		}
126
		return $next;
127
	}
128
129
	/**
130
	 * @param bool $withBaseUrl
131
	 * @return string|null
132
	 */
133
	public function firstPageLink(bool $withBaseUrl = false): ?string
134
	{
135
		return $this->getUri($withBaseUrl) . 'per_page=' . $this->per_page . '&page=1';
136
	}
137
138
	/**
139
	 * @return int
140
	 */
141
	public function lastPageNumber(): int
142
	{
143
		return (int)ceil($this->total() / $this->per_page);
144
	}
145
146
	/**
147
	 * @param bool $withBaseUrl
148
	 * @return string|null
149
	 */
150
	public function lastPageLink(bool $withBaseUrl = false): ?string
151
	{
152
		$last = null;
153
		if (!empty($this->lastPageNumber())) {
154
			$last = $this->getUri($withBaseUrl) . 'per_page=' . $this->per_page . '&page=' . $this->lastPageNumber();
155
		}
156
		return $last;
157
	}
158
159
	/**
160
	 * @return mixed
161
	 */
162
	public function firstItem()
163
	{
164
		return $this->data[array_key_first($this->data)];
0 ignored issues
show
Bug introduced by
It seems like $this->data can also be of type IdiormResultSet; however, parameter $array of array_key_first() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

164
		return $this->data[array_key_first(/** @scrutinizer ignore-type */ $this->data)];
Loading history...
165
	}
166
167
	/**
168
	 * @return mixed
169
	 */
170
	public function lastItem()
171
	{
172
		return $this->data[array_key_last($this->data)];
0 ignored issues
show
Bug introduced by
It seems like $this->data can also be of type IdiormResultSet; however, parameter $array of array_key_last() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

172
		return $this->data[array_key_last(/** @scrutinizer ignore-type */ $this->data)];
Loading history...
173
	}
174
175
	/**
176
	 * @return int
177
	 */
178
	public function perPage()
179
	{
180
		return $this->per_page;
181
	}
182
183
	/**
184
	 * @return int
185
	 */
186
	public function total()
187
	{
188
		return $this->total;
189
	}
190
191
	/**
192
	 * @param bool $withBaseUrl
193
	 * @return array
194
	 */
195
	public function links(bool $withBaseUrl = false): array
196
	{
197
		$links = [];
198
		for ($i = 1; $i <= $this->lastPageNumber(); $i++) {
199
			$links[] = $this->getUri($withBaseUrl) . 'per_page=' . $this->per_page . '&page=' . $i;
200
		}
201
202
		return $links;
203
	}
204
205
	/**
206
	 * @param bool $withBaseUrl
207
	 * @param $pageItemsCount
208
	 * @return string|null
209
	 */
210
	public function getPagination(bool $withBaseUrl = false, $pageItemsCount = null): ?string
211
	{
212
		if (!is_null($pageItemsCount) && $pageItemsCount < 3) {
213
			$pageItemsCount = 3;
214
		}
215
216
		$currentPage = $this->currentPageNumber();
217
		$totalPages = $this->lastPageNumber();
218
219
		if ($totalPages <= 1) {
220
			return null;
221
		}
222
223
		$pagination = '<ul class="pagination">';
224
225
		if ($currentPage > 1) {
226
			$pagination .= '<li><a href="' . $this->previousPageLink() . '">&laquo; Previous</a></li>';
227
		}
228
229
		if ($pageItemsCount) {
230
			$startPage = max(1, $currentPage - ceil(($pageItemsCount - 3) / 2));
231
			$endPage = min($totalPages, $startPage + $pageItemsCount - 3);
232
			$startPage = max(1, $endPage - $pageItemsCount + 3);
233
234
			if ($startPage > 1) {
235
				$pagination .= '<li><a href="' . $this->firstPageLink() . '">1</a></li>';
236
				if ($startPage > 2) {
237
					$pagination .= '<li><span>...</span></li>';
238
				}
239
			}
240
241
			$links = $this->links($withBaseUrl);
242
			for ($i = $startPage; $i <= $endPage; $i++) {
243
				$active = $i == $currentPage ? 'class="active"' : '';
244
				$pagination .= '<li ' . $active . '><a href="' . $links[$i - 1] . '">' . $i . '</a></li>';
245
			}
246
247
			if ($endPage < $totalPages) {
248
				if ($endPage < $totalPages - 1) {
249
					$pagination .= '<li><span>...</span></li>';
250
				}
251
252
				$pagination .= '<li><a href="' . $links[$totalPages - 1] . '">' . $totalPages . '</a></li>';
253
			}
254
		}
255
256
		if ($currentPage < $totalPages) {
257
			$pagination .= '<li><a href="' . $this->nextPageLink() . '">Next &raquo;</a></li>';
258
		}
259
260
		$pagination .= '</ul>';
261
262
		return $pagination;
263
	}
264
265
	/**
266
	 * @return array|IdiormResultSet
267
	 */
268
	public function data()
269
	{
270
		return $this->data ?? [];
271
	}
272
273
	/**
274
	 * @param IdiormDbal $idiormDbal
275
	 * @return void
276
	 * @throws DatabaseException
277
	 */
278
	private function setTotal(IdiormDbal $idiormDbal)
279
	{
280
		$this->total = $idiormDbal->getOrmModel()->count();
281
	}
282
283
	/**
284
	 * @param bool $withBaseUrl
285
	 * @return string
286
	 */
287
	private function getUri(bool $withBaseUrl = false)
288
	{
289
		$base_url = base_url();
290
		$routeUrl = preg_replace('/([?&](page|per_page)=\d+)/', '', route_uri());
291
		$routeUrl = preg_replace('/&/', '?', $routeUrl, 1);
292
		$url = $routeUrl;
293
		if ($withBaseUrl) {
294
			$url = $base_url . $routeUrl;
295
		}
296
297
		$delimiter = str_contains($url, '?') ? '&' : '?';
298
299
		return $url . $delimiter;
300
	}
301
}