Skip to content

Commit

Permalink
Merge pull request #17 from DirectoryTree/remove-illuminate-support
Browse files Browse the repository at this point in the history
Remove illuminate/support to be framework agnostic
  • Loading branch information
stevebauman authored Feb 14, 2025
2 parents 767d134 + 6b900fc commit 7ea0f30
Show file tree
Hide file tree
Showing 8 changed files with 337 additions and 19 deletions.
1 change: 0 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
"php": "^8.1",
"symfony/mime": ">=6.0",
"nesbot/carbon": ">=2.0",
"illuminate/pagination": ">=9.0",
"illuminate/collections": ">=9.0",
"zbateson/mail-mime-parser": "^3.0",
"egulias/email-validator": "^4.0"
Expand Down
18 changes: 6 additions & 12 deletions src/Collections/PaginatedCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

namespace DirectoryTree\ImapEngine\Collections;

use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;
use DirectoryTree\ImapEngine\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;

class PaginatedCollection extends Collection
{
/**
* Number of total entries.
* The total number of items.
*/
protected int $total = 0;

Expand All @@ -18,24 +17,19 @@ class PaginatedCollection extends Collection
*/
public function paginate(int $perPage = 15, ?int $page = null, string $pageName = 'page', bool $prepaginated = false): LengthAwarePaginator
{
$page = $page ?: Paginator::resolveCurrentPage($pageName);

$total = $this->total ?: $this->count();

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

return $this->paginator($results, $total, $perPage, $page, [
'path' => Paginator::resolveCurrentPath(),
'pageName' => $pageName,
]);
return $this->paginator($results, $total, $perPage, $page, $pageName);
}

/**
* Create a new length-aware paginator instance.
*/
protected function paginator(array $items, int $total, int $perPage, ?int $currentPage, array $options): LengthAwarePaginator
protected function paginator(Collection $items, int $total, int $perPage, ?int $currentPage, string $pageName): LengthAwarePaginator
{
return new LengthAwarePaginator($items, $total, $perPage, $currentPage, $options);
return new LengthAwarePaginator($items, $total, $perPage, $currentPage, $pageName);
}

/**
Expand Down
5 changes: 4 additions & 1 deletion src/Folder.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ public function is(Folder $folder): bool
*/
public function messages(): MessageQuery
{
return new MessageQuery(tap($this)->select(true), new ImapQueryBuilder);
// Ensure the folder is selected.
$this->select(true);

return new MessageQuery($this, new ImapQueryBuilder);
}

/**
Expand Down
7 changes: 4 additions & 3 deletions src/Mailbox.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,10 @@ public function inbox(): Folder
*/
public function folders(): FolderRepository
{
return new FolderRepository(
tap($this)->connection()
);
// Ensure the connection is established.
$this->connection();

return new FolderRepository($this);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/MessageQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
use DirectoryTree\ImapEngine\Connection\Responses\UntaggedResponse;
use DirectoryTree\ImapEngine\Connection\Tokens\Atom;
use DirectoryTree\ImapEngine\Enums\ImapFetchIdentifier;
use DirectoryTree\ImapEngine\Pagination\LengthAwarePaginator;
use DirectoryTree\ImapEngine\Support\ForwardsCalls;
use DirectoryTree\ImapEngine\Support\Str;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Illuminate\Support\Traits\Conditionable;
use Illuminate\Support\Traits\ForwardsCalls;

/**
* @mixin \DirectoryTree\ImapEngine\Connection\ImapQueryBuilder
Expand Down
173 changes: 173 additions & 0 deletions src/Pagination/LengthAwarePaginator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
<?php

namespace DirectoryTree\ImapEngine\Pagination;

use DirectoryTree\ImapEngine\Support\ForwardsCalls;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Collection;
use JsonSerializable;

class LengthAwarePaginator implements Arrayable, JsonSerializable
{
use ForwardsCalls;

/**
* Constructor.
*/
public function __construct(
protected Collection $items,
protected int $total,
protected int $perPage,
protected int $currentPage = 1,
protected string $path = '',
protected array $query = [],
protected string $pageName = 'page',
) {
$this->currentPage = max($currentPage, 1);

$this->path = rtrim($path, '/');
}

/**
* Handle dynamic method calls on the paginator.
*/
public function __call(string $method, array $parameters): mixed
{
return $this->forwardCallTo($this->items, $method, $parameters);
}

/**
* Get the items being paginated.
*/
public function items(): Collection
{
return $this->items;
}

/**
* Get the total number of items.
*/
public function total(): int
{
return $this->total;
}

/**
* Get the number of items per page.
*/
public function perPage(): int
{
return $this->perPage;
}

/**
* Get the current page number.
*/
public function currentPage(): int
{
return $this->currentPage;
}

/**
* Get the last page (total pages).
*/
public function lastPage(): int
{
return (int) ceil($this->total / $this->perPage);
}

/**
* Determine if there are enough items to split into multiple pages.
*/
public function hasPages(): bool
{
return $this->total() > $this->perPage();
}

/**
* Determine if there is a next page.
*/
public function hasMorePages(): bool
{
return $this->currentPage() < $this->lastPage();
}

/**
* Generate the URL for a given page.
*/
public function url(int $page): string
{
$params = array_merge($this->query, [$this->pageName => $page]);

$queryString = http_build_query($params);

return $this->path.($queryString ? '?'.$queryString : '');
}

/**
* Get the URL for the next page, or null if none.
*/
public function nextPageUrl(): ?string
{
if ($this->hasMorePages()) {
return $this->url($this->currentPage() + 1);
}

return null;
}

/**
* Get the URL for the previous page, or null if none.
*/
public function previousPageUrl(): ?string
{
if ($this->currentPage() > 1) {
return $this->url($this->currentPage() - 1);
}

return null;
}

/**
* Convert the pagination data to an array.
*/
public function toArray(): array
{
return [
'path' => $this->path,
'total' => $this->total(),
'to' => $this->calculateTo(),
'per_page' => $this->perPage(),
'last_page' => $this->lastPage(),
'first_page_url' => $this->url(1),
'data' => $this->items()->toArray(),
'current_page' => $this->currentPage(),
'next_page_url' => $this->nextPageUrl(),
'prev_page_url' => $this->previousPageUrl(),
'last_page_url' => $this->url($this->lastPage()),
'from' => $this->total() ? ($this->currentPage() - 1) * $this->perPage() + 1 : null,
];
}

/**
* Calculate the "to" index for the current page.
*/
protected function calculateTo(): ?int
{
if (! $this->total()) {
return null;
}

$to = $this->currentPage() * $this->perPage();

return min($to, $this->total());
}

/**
* Convert the instance to JSON.
*/
public function jsonSerialize(): array
{
return $this->toArray();
}
}
42 changes: 42 additions & 0 deletions src/Support/ForwardsCalls.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace DirectoryTree\ImapEngine\Support;

use BadMethodCallException;
use Error;

trait ForwardsCalls
{
/**
* Forward a method call to the given object.
*/
protected function forwardCallTo(object $object, string $method, array $parameters): mixed
{
try {
return $object->{$method}(...$parameters);
} catch (Error|BadMethodCallException $e) {
$pattern = '~^Call to undefined method (?P<class>[^:]+)::(?P<method>[^\(]+)\(\)$~';

if (! preg_match($pattern, $e->getMessage(), $matches)) {
throw $e;
}

if ($matches['class'] != get_class($object) ||
$matches['method'] != $method) {
throw $e;
}

static::throwBadMethodCallException($method);
}
}

/**
* Throw a bad method call exception for the given method.
*/
protected static function throwBadMethodCallException(string $method)
{
throw new BadMethodCallException(sprintf(
'Call to undefined method %s::%s()', static::class, $method
));
}
}
Loading

0 comments on commit 7ea0f30

Please sign in to comment.