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

Paginator::lastItem()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace Quantum\Libraries\Database\Sleekdb;
4
5
use SleekDB\Exceptions\InvalidConfigurationException;
6
use Quantum\Libraries\Database\PaginatorInterface;
7
use SleekDB\Exceptions\InvalidArgumentException;
8
use Quantum\Exceptions\DatabaseException;
9
use Quantum\Exceptions\ModelException;
10
use SleekDB\Exceptions\IOException;
11
12
class Paginator implements PaginatorInterface
13
{
14
	/**
15
	 * @var int
16
	 */
17
	private $total;
18
19
	/**
20
	 * @var SleekDbal
21
	 */
22
	private $dbal;
23
24
	/**
25
	 * @var int
26
	 */
27
	protected $per_page;
28
29
	/**
30
	 * @var int
31
	 */
32
	protected $page;
33
34
	/**
35
	 * @var array
36
	 */
37
	public $data;
38
39
	/**
40
	 * @param $sleekDbal
41
	 * @param int $per_page
42
	 * @param int $page
43
	 * @throws DatabaseException
44
	 * @throws ModelException
45
	 * @throws IOException
46
	 * @throws InvalidArgumentException
47
	 * @throws InvalidConfigurationException
48
	 */
49
	public function __construct($sleekDbal, int $per_page, int $page = 1)
50
	{
51
		/** @var SleekDbal $sleekDbal */
52
		$this->setTotal($sleekDbal);
53
		$this->dbal = $sleekDbal;
54
		$this->dbal->limit($per_page)->offset($per_page * ($page - 1));
55
		$this->data = $this->dbal->getBuilder()->getQuery()->fetch();
56
		$this->per_page = $per_page;
57
		$this->page = $page;
58
	}
59
60
	/**
61
	 * @return int
62
	 */
63
	public function currentPageNumber(): int
64
	{
65
		return $this->page;
66
	}
67
68
	/**
69
	 * @param bool $withBaseUrl
70
	 * @return string|null
71
	 */
72
	public function currentPageLink(bool $withBaseUrl = false): ?string
73
	{
74
		$current = null;
75
		if (!empty($this->page)) {
76
			$current = $this->getUri($withBaseUrl) . 'per_page=' . $this->per_page . '&page=' . $this->page;
77
		}
78
		return $current;
79
	}
80
81
	/**
82
	 * @return int|null
83
	 */
84
	public function previousPageNumber(): ?int
85
	{
86
		$previous = null;
87
		if ($this->page > 1) {
88
			$previous = $this->page - 1;
89
		} elseif ($this->page == 1) {
90
			$previous = $this->page;
91
		}
92
93
		return $previous;
94
	}
95
96
	/**
97
	 * @param bool $withBaseUrl
98
	 * @return string|null
99
	 */
100
	public function previousPageLink(bool $withBaseUrl = false): ?string
101
	{
102
		$previous = null;
103
		if (!empty($this->previousPageNumber())) {
104
			$previous = $this->getUri($withBaseUrl) . 'per_page=' . $this->per_page . '&page=' . $this->previousPageNumber();
105
		}
106
		return $previous;
107
	}
108
109
	/**
110
	 * @return int|null
111
	 */
112
	public function nextPageNumber(): ?int
113
	{
114
		$next = null;
115
		if ($this->page < $this->lastPageNumber()) {
116
			$next = $this->page + 1;
117
		} elseif ($this->page == $this->lastPageNumber()) {
118
			$next = $this->page;
119
		}
120
		return $next;
121
	}
122
123
	/**
124
	 * @param bool $withBaseUrl
125
	 * @return string|null
126
	 */
127
	public function nextPageLink(bool $withBaseUrl = false): ?string
128
	{
129
		$next = null;
130
		if (!empty($this->nextPageNumber())) {
131
			$next = $this->getUri($withBaseUrl) . 'per_page=' . $this->per_page . '&page=' . $this->nextPageNumber();
132
		}
133
		return $next;
134
	}
135
136
	/**
137
	 * @param bool $withBaseUrl
138
	 * @return string|null
139
	 */
140
	public function firstPageLink(bool $withBaseUrl = false): ?string
141
	{
142
		return $this->getUri($withBaseUrl) . 'per_page=' . $this->per_page . '&page=1';
143
	}
144
145
	/**
146
	 * @return int
147
	 */
148
	public function lastPageNumber(): int
149
	{
150
		return (int)ceil($this->total() / $this->per_page);
151
	}
152
153
	/**
154
	 * @param bool $withBaseUrl
155
	 * @return string|null
156
	 */
157
	public function lastPageLink(bool $withBaseUrl = false): ?string
158
	{
159
		$last = null;
160
		if (!empty($this->lastPageNumber())) {
161
			$last = $this->getUri($withBaseUrl) . 'per_page=' . $this->per_page . '&page=' . $this->lastPageNumber();
162
		}
163
		return $last;
164
	}
165
166
	/**
167
	 * @return mixed
168
	 */
169
	public function firstItem()
170
	{
171
		return $this->data[array_key_first($this->data)];
172
	}
173
174
	/**
175
	 * @return mixed
176
	 */
177
	public function lastItem()
178
	{
179
		return $this->data[array_key_last($this->data)];
180
	}
181
182
	/**
183
	 * @return int
184
	 */
185
	public function perPage(): int
186
	{
187
		return $this->per_page;
188
	}
189
190
	/**
191
	 * @return int
192
	 */
193
	public function total(): int
194
	{
195
		return $this->total;
196
	}
197
198
	/**
199
	 * @param bool $withBaseUrl
200
	 * @return array
201
	 */
202
	public function links(bool $withBaseUrl = false): array
203
	{
204
		$links = [];
205
		for ($i = 1; $i <= $this->lastPageNumber(); $i++) {
206
			$links[] = $this->getUri($withBaseUrl) . 'per_page=' . $this->per_page . '&page=' . $i;
207
		}
208
209
		return $links;
210
	}
211
212
	/**
213
	 * @param bool $withBaseUrl
214
	 * @param $pageItemsCount
215
	 * @return string|null
216
	 */
217
	public function getPagination(bool $withBaseUrl = false, $pageItemsCount = null): ?string
218
	{
219
		if (!is_null($pageItemsCount) && $pageItemsCount < 3) {
220
			$pageItemsCount = 3;
221
		}
222
223
		$currentPage = $this->currentPageNumber();
224
		$totalPages = $this->lastPageNumber();
225
226
		if ($totalPages <= 1) {
227
			return null;
228
		}
229
230
		$pagination = '<ul class="pagination">';
231
232
		if ($currentPage > 1) {
233
			$pagination .= '<li><a href="' . $this->previousPageLink() . '">&laquo; Previous</a></li>';
234
		}
235
236
		if ($pageItemsCount) {
237
			$startPage = max(1, $currentPage - ceil(($pageItemsCount - 3) / 2));
238
			$endPage = min($totalPages, $startPage + $pageItemsCount - 3);
239
			$startPage = max(1, $endPage - $pageItemsCount + 3);
240
241
			if ($startPage > 1) {
242
				$pagination .= '<li><a href="' . $this->firstPageLink() . '">1</a></li>';
243
				if ($startPage > 2) {
244
					$pagination .= '<li><span>...</span></li>';
245
				}
246
			}
247
248
			$links = $this->links($withBaseUrl);
249
			for ($i = $startPage; $i <= $endPage; $i++) {
250
				$active = $i == $currentPage ? 'class="active"' : '';
251
				$pagination .= '<li ' . $active . '><a href="' . $links[$i - 1] . '">' . $i . '</a></li>';
252
			}
253
254
			if ($endPage < $totalPages) {
255
				if ($endPage < $totalPages - 1) {
256
					$pagination .= '<li><span>...</span></li>';
257
				}
258
259
				$pagination .= '<li><a href="' . $links[$totalPages - 1] . '">' . $totalPages . '</a></li>';
260
			}
261
		}
262
263
		if ($currentPage < $totalPages) {
264
			$pagination .= '<li><a href="' . $this->nextPageLink() . '">Next &raquo;</a></li>';
265
		}
266
267
		$pagination .= '</ul>';
268
269
		return $pagination;
270
	}
271
272
	/**
273
	 * @return array|SleekDbal[]
274
	 */
275
	public function data(): array
276
	{
277
		$result = array_map(function ($element) {
278
			$item = clone $this->dbal;
279
			$item->setData($element);
280
			$item->setModifiedFields($element);
281
			$item->setIsNew(false);
282
			return $item;
283
		}, $this->data);
284
285
		return $result ?? [];
286
	}
287
288
	/**
289
	 * @param SleekDbal $sleekDbal
290
	 * @return void
291
	 * @throws DatabaseException
292
	 * @throws ModelException
293
	 * @throws IOException
294
	 * @throws InvalidArgumentException
295
	 * @throws InvalidConfigurationException
296
	 */
297
	private function setTotal(SleekDbal $sleekDbal)
298
	{
299
		$this->total = count($sleekDbal->getBuilder()->getQuery()->fetch());
300
	}
301
302
	/**
303
	 * @param bool $withBaseUrl
304
	 * @return string
305
	 */
306
	private function getUri(bool $withBaseUrl = false): string
307
	{
308
		$base_url = base_url();
309
		$routeUrl = preg_replace('/([?&](page|per_page)=\d+)/', '', route_uri());
310
		$routeUrl = preg_replace('/&/', '?', $routeUrl, 1);
311
		$url = $routeUrl;
312
		if ($withBaseUrl) {
313
			$url = $base_url . $routeUrl;
314
		}
315
316
		$delimiter = str_contains($url, '?') ? '&' : '?';
317
318
		return $url . $delimiter;
319
	}
320
}