Skip to content

Commit

Permalink
Add cursor pagination support to API resources (#37315)
Browse files Browse the repository at this point in the history
  • Loading branch information
paras-malhotra authored May 10, 2021
1 parent 68b1d3f commit 9110caa
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 2 deletions.
3 changes: 2 additions & 1 deletion src/Illuminate/Http/Resources/CollectsResources.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Illuminate\Http\Resources;

use Illuminate\Pagination\AbstractCursorPaginator;
use Illuminate\Pagination\AbstractPaginator;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
Expand Down Expand Up @@ -30,7 +31,7 @@ protected function collectResource($resource)
? $resource->mapInto($collects)
: $resource->toBase();

return $resource instanceof AbstractPaginator
return ($resource instanceof AbstractPaginator || $resource instanceof AbstractCursorPaginator)
? $resource->setCollection($this->collection)
: $this->collection;
}
Expand Down
3 changes: 2 additions & 1 deletion src/Illuminate/Http/Resources/Json/ResourceCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Countable;
use Illuminate\Http\Resources\CollectsResources;
use Illuminate\Pagination\AbstractCursorPaginator;
use Illuminate\Pagination\AbstractPaginator;
use IteratorAggregate;

Expand Down Expand Up @@ -108,7 +109,7 @@ public function toArray($request)
*/
public function toResponse($request)
{
if ($this->resource instanceof AbstractPaginator) {
if ($this->resource instanceof AbstractPaginator || $this->resource instanceof AbstractCursorPaginator) {
return $this->preparePaginatedResponse($request);
}

Expand Down
113 changes: 113 additions & 0 deletions tests/Integration/Http/ResourceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\MergeValue;
use Illuminate\Http\Resources\MissingValue;
use Illuminate\Pagination\Cursor;
use Illuminate\Pagination\CursorPaginator;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Route;
Expand Down Expand Up @@ -678,6 +680,117 @@ public function testPaginatorResourceCanReceiveQueryParameters()
]);
}

public function testCursorPaginatorReceiveLinks()
{
Route::get('/', function () {
$paginator = new CursorPaginator(
collect([new Post(['id' => 5, 'title' => 'Test Title']), new Post(['id' => 6, 'title' => 'Hello'])]),
1, null, ['parameters' => ['id']]
);

return new PostCollectionResource($paginator);
});

$response = $this->withoutExceptionHandling()->get(
'/', ['Accept' => 'application/json']
);

$response->assertStatus(200);

$response->assertJson([
'data' => [
[
'id' => 5,
'title' => 'Test Title',
],
],
'links' => [
'first' => null,
'last' => null,
'prev' => null,
'next' => '/?cursor='.(new Cursor(['id' => 5]))->encode(),
],
'meta' => [
'path' => '/',
'per_page' => 1,
],
]);
}

public function testCursorPaginatorResourceCanPreserveQueryParameters()
{
Route::get('/', function () {
$collection = collect([new Post(['id' => 5, 'title' => 'Test Title']), new Post(['id' => 6, 'title' => 'Hello'])]);
$paginator = new CursorPaginator(
$collection, 1, null, ['parameters' => ['id']]
);

return PostCollectionResource::make($paginator)->preserveQuery();
});

$response = $this->withoutExceptionHandling()->get(
'/?framework=laravel&author=Otwell', ['Accept' => 'application/json']
);

$response->assertStatus(200);

$response->assertJson([
'data' => [
[
'id' => 5,
'title' => 'Test Title',
],
],
'links' => [
'first' => null,
'last' => null,
'prev' => null,
'next' => '/?framework=laravel&author=Otwell&cursor='.(new Cursor(['id' => 5]))->encode(),
],
'meta' => [
'path' => '/',
'per_page' => 1,
],
]);
}

public function testCursorPaginatorResourceCanReceiveQueryParameters()
{
Route::get('/', function () {
$collection = collect([new Post(['id' => 5, 'title' => 'Test Title']), new Post(['id' => 6, 'title' => 'Hello'])]);
$paginator = new CursorPaginator(
$collection, 1, null, ['parameters' => ['id']]
);

return PostCollectionResource::make($paginator)->withQuery(['author' => 'Taylor']);
});

$response = $this->withoutExceptionHandling()->get(
'/?framework=laravel&author=Otwell', ['Accept' => 'application/json']
);

$response->assertStatus(200);

$response->assertJson([
'data' => [
[
'id' => 5,
'title' => 'Test Title',
],
],
'links' => [
'first' => null,
'last' => null,
'prev' => null,
'next' => '/?author=Taylor&cursor='.(new Cursor(['id' => 5]))->encode(),
],
'meta' => [
'path' => '/',
'per_page' => 1,
],
]);
}

public function testToJsonMayBeLeftOffOfCollection()
{
Route::get('/', function () {
Expand Down

0 comments on commit 9110caa

Please sign in to comment.