Skip to content

Commit

Permalink
Fix pagination include/exclude problems and add a better solution for…
Browse files Browse the repository at this point in the history
… building paginators
  • Loading branch information
rubenvanassche committed May 3, 2024
1 parent 6075b43 commit 0ecd1b7
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 2 deletions.
59 changes: 57 additions & 2 deletions src/Resolvers/TransformedDataCollectableResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Exception;
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Pagination\CursorPaginator;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Arr;
use Illuminate\Support\Enumerable;
use Spatie\LaravelData\Contracts\BaseData;
Expand Down Expand Up @@ -93,12 +94,66 @@ protected function transformPaginator(
return $paginator->map(fn (BaseData $data) => $this->transformationClosure($nestedContext)($data))->all();
}

$paginated = $paginator->toArray();
$items = array_map(fn (BaseData $data) => $this->transformationClosure($nestedContext)($data), $paginator->items());

['links' => $links, 'meta' => $meta] = match ($paginator::class) {
LengthAwarePaginator::class => $this->resolveLengthAwarePaginatorLinksAndMeta($paginator),
CursorPaginator::class => $this->resolveCursorPaginatorLinksAndMeta($paginator),
default => $this->resolveUnknownPaginatorLinksAndMeta($paginator),
};

$wrapKey = $wrap->getKey() ?? 'data';

return [
$wrapKey => array_map(fn (BaseData $data) => $this->transformationClosure($nestedContext)($data), $paginator->items()),
$wrapKey => $items,
'links' => $links,
'meta' => $meta,
];
}

protected function resolveLengthAwarePaginatorLinksAndMeta(
LengthAwarePaginator $paginator
): array {
return [
'links' => $paginator->linkCollection()->toArray(),
'meta' => [
'current_page' => $paginator->currentPage(),
'first_page_url' => $paginator->url(1),
'from' => $paginator->firstItem(),
'last_page' => $paginator->lastPage(),
'last_page_url' => $paginator->url($paginator->lastPage()),
'next_page_url' => $paginator->nextPageUrl(),
'path' => $paginator->path(),
'per_page' => $paginator->perPage(),
'prev_page_url' => $paginator->previousPageUrl(),
'to' => $paginator->lastItem(),
'total' => $paginator->total(),
],
];
}

protected function resolveCursorPaginatorLinksAndMeta(
CursorPaginator $paginator
): array {
return [
'links' => [],
'meta' => [
'path' => $paginator->path(),
'per_page' => $paginator->perPage(),
'next_cursor' => $paginator->nextCursor()?->encode(),
'next_page_url' => $paginator->nextPageUrl(),
'prev_cursor' => $paginator->previousCursor()?->encode(),
'prev_page_url' => $paginator->previousPageUrl(),
],
];
}

protected function resolveUnknownPaginatorLinksAndMeta(
Paginator|CursorPaginator $paginator,
): array {
$paginated = $paginator->toArray();

return [
'links' => $paginated['links'] ?? [],
'meta' => Arr::except($paginated, [
'data',
Expand Down
21 changes: 21 additions & 0 deletions tests/DataCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
use Spatie\LaravelData\DataCollection;
use Spatie\LaravelData\PaginatedDataCollection;
use Spatie\LaravelData\Tests\Fakes\Collections\CustomCollection;
use Spatie\LaravelData\Tests\Fakes\DummyDto;
use Spatie\LaravelData\Tests\Fakes\LazyData;
use Spatie\LaravelData\Tests\Fakes\MultiLazyData;
use Spatie\LaravelData\Tests\Fakes\SimpleData;

it('can filter a collection', function () {
Expand Down Expand Up @@ -276,3 +278,22 @@
expect($collection->toArray())->toBe($expect);
expect($collection->toArray())->toBe($expect);
});

it('it can include lazy items through a paginated data collection', function () {
// https://github.com/spatie/laravel-data/issues/746

$collection = new PaginatedDataCollection(
MultiLazyData::class,
new LengthAwarePaginator([
DummyDto::rick(),
DummyDto::bon(),
], 2, 15),
);

$filtered = $collection->through(fn (MultiLazyData $data) => $data->include('artist'))->toArray();

expect($filtered['data'])->toMatchArray([
['artist' => 'Rick Astley'],
['artist' => 'Bon Jovi'],
]);
});

0 comments on commit 0ecd1b7

Please sign in to comment.