Skip to content

Commit 7ea0f30

Browse files
authored
Merge pull request #17 from DirectoryTree/remove-illuminate-support
Remove illuminate/support to be framework agnostic
2 parents 767d134 + 6b900fc commit 7ea0f30

File tree

8 files changed

+337
-19
lines changed

8 files changed

+337
-19
lines changed

composer.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
"php": "^8.1",
2121
"symfony/mime": ">=6.0",
2222
"nesbot/carbon": ">=2.0",
23-
"illuminate/pagination": ">=9.0",
2423
"illuminate/collections": ">=9.0",
2524
"zbateson/mail-mime-parser": "^3.0",
2625
"egulias/email-validator": "^4.0"

src/Collections/PaginatedCollection.php

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22

33
namespace DirectoryTree\ImapEngine\Collections;
44

5-
use Illuminate\Pagination\LengthAwarePaginator;
6-
use Illuminate\Pagination\Paginator;
5+
use DirectoryTree\ImapEngine\Pagination\LengthAwarePaginator;
76
use Illuminate\Support\Collection;
87

98
class PaginatedCollection extends Collection
109
{
1110
/**
12-
* Number of total entries.
11+
* The total number of items.
1312
*/
1413
protected int $total = 0;
1514

@@ -18,24 +17,19 @@ class PaginatedCollection extends Collection
1817
*/
1918
public function paginate(int $perPage = 15, ?int $page = null, string $pageName = 'page', bool $prepaginated = false): LengthAwarePaginator
2019
{
21-
$page = $page ?: Paginator::resolveCurrentPage($pageName);
22-
2320
$total = $this->total ?: $this->count();
2421

25-
$results = ! $prepaginated && $total ? $this->forPage($page, $perPage)->toArray() : $this->all();
22+
$results = ! $prepaginated && $total ? $this->forPage($page, $perPage) : $this;
2623

27-
return $this->paginator($results, $total, $perPage, $page, [
28-
'path' => Paginator::resolveCurrentPath(),
29-
'pageName' => $pageName,
30-
]);
24+
return $this->paginator($results, $total, $perPage, $page, $pageName);
3125
}
3226

3327
/**
3428
* Create a new length-aware paginator instance.
3529
*/
36-
protected function paginator(array $items, int $total, int $perPage, ?int $currentPage, array $options): LengthAwarePaginator
30+
protected function paginator(Collection $items, int $total, int $perPage, ?int $currentPage, string $pageName): LengthAwarePaginator
3731
{
38-
return new LengthAwarePaginator($items, $total, $perPage, $currentPage, $options);
32+
return new LengthAwarePaginator($items, $total, $perPage, $currentPage, $pageName);
3933
}
4034

4135
/**

src/Folder.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ public function is(Folder $folder): bool
8282
*/
8383
public function messages(): MessageQuery
8484
{
85-
return new MessageQuery(tap($this)->select(true), new ImapQueryBuilder);
85+
// Ensure the folder is selected.
86+
$this->select(true);
87+
88+
return new MessageQuery($this, new ImapQueryBuilder);
8689
}
8790

8891
/**

src/Mailbox.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,10 @@ public function inbox(): Folder
185185
*/
186186
public function folders(): FolderRepository
187187
{
188-
return new FolderRepository(
189-
tap($this)->connection()
190-
);
188+
// Ensure the connection is established.
189+
$this->connection();
190+
191+
return new FolderRepository($this);
191192
}
192193

193194
/**

src/MessageQuery.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
use DirectoryTree\ImapEngine\Connection\Responses\UntaggedResponse;
99
use DirectoryTree\ImapEngine\Connection\Tokens\Atom;
1010
use DirectoryTree\ImapEngine\Enums\ImapFetchIdentifier;
11+
use DirectoryTree\ImapEngine\Pagination\LengthAwarePaginator;
12+
use DirectoryTree\ImapEngine\Support\ForwardsCalls;
1113
use DirectoryTree\ImapEngine\Support\Str;
12-
use Illuminate\Pagination\LengthAwarePaginator;
1314
use Illuminate\Support\Collection;
1415
use Illuminate\Support\Traits\Conditionable;
15-
use Illuminate\Support\Traits\ForwardsCalls;
1616

1717
/**
1818
* @mixin \DirectoryTree\ImapEngine\Connection\ImapQueryBuilder
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
<?php
2+
3+
namespace DirectoryTree\ImapEngine\Pagination;
4+
5+
use DirectoryTree\ImapEngine\Support\ForwardsCalls;
6+
use Illuminate\Contracts\Support\Arrayable;
7+
use Illuminate\Support\Collection;
8+
use JsonSerializable;
9+
10+
class LengthAwarePaginator implements Arrayable, JsonSerializable
11+
{
12+
use ForwardsCalls;
13+
14+
/**
15+
* Constructor.
16+
*/
17+
public function __construct(
18+
protected Collection $items,
19+
protected int $total,
20+
protected int $perPage,
21+
protected int $currentPage = 1,
22+
protected string $path = '',
23+
protected array $query = [],
24+
protected string $pageName = 'page',
25+
) {
26+
$this->currentPage = max($currentPage, 1);
27+
28+
$this->path = rtrim($path, '/');
29+
}
30+
31+
/**
32+
* Handle dynamic method calls on the paginator.
33+
*/
34+
public function __call(string $method, array $parameters): mixed
35+
{
36+
return $this->forwardCallTo($this->items, $method, $parameters);
37+
}
38+
39+
/**
40+
* Get the items being paginated.
41+
*/
42+
public function items(): Collection
43+
{
44+
return $this->items;
45+
}
46+
47+
/**
48+
* Get the total number of items.
49+
*/
50+
public function total(): int
51+
{
52+
return $this->total;
53+
}
54+
55+
/**
56+
* Get the number of items per page.
57+
*/
58+
public function perPage(): int
59+
{
60+
return $this->perPage;
61+
}
62+
63+
/**
64+
* Get the current page number.
65+
*/
66+
public function currentPage(): int
67+
{
68+
return $this->currentPage;
69+
}
70+
71+
/**
72+
* Get the last page (total pages).
73+
*/
74+
public function lastPage(): int
75+
{
76+
return (int) ceil($this->total / $this->perPage);
77+
}
78+
79+
/**
80+
* Determine if there are enough items to split into multiple pages.
81+
*/
82+
public function hasPages(): bool
83+
{
84+
return $this->total() > $this->perPage();
85+
}
86+
87+
/**
88+
* Determine if there is a next page.
89+
*/
90+
public function hasMorePages(): bool
91+
{
92+
return $this->currentPage() < $this->lastPage();
93+
}
94+
95+
/**
96+
* Generate the URL for a given page.
97+
*/
98+
public function url(int $page): string
99+
{
100+
$params = array_merge($this->query, [$this->pageName => $page]);
101+
102+
$queryString = http_build_query($params);
103+
104+
return $this->path.($queryString ? '?'.$queryString : '');
105+
}
106+
107+
/**
108+
* Get the URL for the next page, or null if none.
109+
*/
110+
public function nextPageUrl(): ?string
111+
{
112+
if ($this->hasMorePages()) {
113+
return $this->url($this->currentPage() + 1);
114+
}
115+
116+
return null;
117+
}
118+
119+
/**
120+
* Get the URL for the previous page, or null if none.
121+
*/
122+
public function previousPageUrl(): ?string
123+
{
124+
if ($this->currentPage() > 1) {
125+
return $this->url($this->currentPage() - 1);
126+
}
127+
128+
return null;
129+
}
130+
131+
/**
132+
* Convert the pagination data to an array.
133+
*/
134+
public function toArray(): array
135+
{
136+
return [
137+
'path' => $this->path,
138+
'total' => $this->total(),
139+
'to' => $this->calculateTo(),
140+
'per_page' => $this->perPage(),
141+
'last_page' => $this->lastPage(),
142+
'first_page_url' => $this->url(1),
143+
'data' => $this->items()->toArray(),
144+
'current_page' => $this->currentPage(),
145+
'next_page_url' => $this->nextPageUrl(),
146+
'prev_page_url' => $this->previousPageUrl(),
147+
'last_page_url' => $this->url($this->lastPage()),
148+
'from' => $this->total() ? ($this->currentPage() - 1) * $this->perPage() + 1 : null,
149+
];
150+
}
151+
152+
/**
153+
* Calculate the "to" index for the current page.
154+
*/
155+
protected function calculateTo(): ?int
156+
{
157+
if (! $this->total()) {
158+
return null;
159+
}
160+
161+
$to = $this->currentPage() * $this->perPage();
162+
163+
return min($to, $this->total());
164+
}
165+
166+
/**
167+
* Convert the instance to JSON.
168+
*/
169+
public function jsonSerialize(): array
170+
{
171+
return $this->toArray();
172+
}
173+
}

src/Support/ForwardsCalls.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace DirectoryTree\ImapEngine\Support;
4+
5+
use BadMethodCallException;
6+
use Error;
7+
8+
trait ForwardsCalls
9+
{
10+
/**
11+
* Forward a method call to the given object.
12+
*/
13+
protected function forwardCallTo(object $object, string $method, array $parameters): mixed
14+
{
15+
try {
16+
return $object->{$method}(...$parameters);
17+
} catch (Error|BadMethodCallException $e) {
18+
$pattern = '~^Call to undefined method (?P<class>[^:]+)::(?P<method>[^\(]+)\(\)$~';
19+
20+
if (! preg_match($pattern, $e->getMessage(), $matches)) {
21+
throw $e;
22+
}
23+
24+
if ($matches['class'] != get_class($object) ||
25+
$matches['method'] != $method) {
26+
throw $e;
27+
}
28+
29+
static::throwBadMethodCallException($method);
30+
}
31+
}
32+
33+
/**
34+
* Throw a bad method call exception for the given method.
35+
*/
36+
protected static function throwBadMethodCallException(string $method)
37+
{
38+
throw new BadMethodCallException(sprintf(
39+
'Call to undefined method %s::%s()', static::class, $method
40+
));
41+
}
42+
}

0 commit comments

Comments
 (0)