From e9f05f1e992908b1850da9c158461966262fe771 Mon Sep 17 00:00:00 2001 From: Chuoke Date: Tue, 23 Nov 2021 03:12:43 +0800 Subject: [PATCH] [8.x] Add custom pagination information in resource (#39600) * add custom pagination information in resource * Update PaginatedResourceResponse.php Co-authored-by: Taylor Otwell --- .../Json/PaginatedResourceResponse.php | 8 ++- ...rceCollectionWithPaginationInformation.php | 20 ++++++ ...ctionResourceWithPaginationInformation.php | 27 ++++++++ ...rceCollectionWithPaginationInformation.php | 28 ++++++++ tests/Integration/Http/ResourceTest.php | 64 +++++++++++++++++++ 5 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 tests/Integration/Http/Fixtures/AnonymousResourceCollectionWithPaginationInformation.php create mode 100644 tests/Integration/Http/Fixtures/PostCollectionResourceWithPaginationInformation.php create mode 100644 tests/Integration/Http/Fixtures/PostResourceWithAnonymousResourceCollectionWithPaginationInformation.php diff --git a/src/Illuminate/Http/Resources/Json/PaginatedResourceResponse.php b/src/Illuminate/Http/Resources/Json/PaginatedResourceResponse.php index 5fb35ea071c9..c5e8fbcb164c 100644 --- a/src/Illuminate/Http/Resources/Json/PaginatedResourceResponse.php +++ b/src/Illuminate/Http/Resources/Json/PaginatedResourceResponse.php @@ -43,10 +43,16 @@ protected function paginationInformation($request) { $paginated = $this->resource->resource->toArray(); - return [ + $default = [ 'links' => $this->paginationLinks($paginated), 'meta' => $this->meta($paginated), ]; + + if (method_exists($this->resource, 'paginationInformation')) { + return $this->resource->paginationInformation($request, $paginated, $default); + } + + return $default; } /** diff --git a/tests/Integration/Http/Fixtures/AnonymousResourceCollectionWithPaginationInformation.php b/tests/Integration/Http/Fixtures/AnonymousResourceCollectionWithPaginationInformation.php new file mode 100644 index 000000000000..10d77fde3d0f --- /dev/null +++ b/tests/Integration/Http/Fixtures/AnonymousResourceCollectionWithPaginationInformation.php @@ -0,0 +1,20 @@ +resource->toArray(); + + return [ + 'current_page' => $paginated['current_page'], + 'per_page' => $paginated['per_page'], + 'total' => $paginated['total'], + 'total_page' => $paginated['last_page'], + ]; + } +} diff --git a/tests/Integration/Http/Fixtures/PostCollectionResourceWithPaginationInformation.php b/tests/Integration/Http/Fixtures/PostCollectionResourceWithPaginationInformation.php new file mode 100644 index 000000000000..020be9d36062 --- /dev/null +++ b/tests/Integration/Http/Fixtures/PostCollectionResourceWithPaginationInformation.php @@ -0,0 +1,27 @@ + $this->collection]; + } + + public function paginationInformation($request) + { + $paginated = $this->resource->toArray(); + + return [ + 'current_page' => $paginated['current_page'], + 'per_page' => $paginated['per_page'], + 'total' => $paginated['total'], + 'total_page' => $paginated['last_page'], + ]; + } +} diff --git a/tests/Integration/Http/Fixtures/PostResourceWithAnonymousResourceCollectionWithPaginationInformation.php b/tests/Integration/Http/Fixtures/PostResourceWithAnonymousResourceCollectionWithPaginationInformation.php new file mode 100644 index 000000000000..8a8d0a2dab08 --- /dev/null +++ b/tests/Integration/Http/Fixtures/PostResourceWithAnonymousResourceCollectionWithPaginationInformation.php @@ -0,0 +1,28 @@ + $this->id, 'title' => $this->title, 'custom' => true]; + } + + /** + * Create a new anonymous resource collection. + * + * @param mixed $resource + * @return AnonymousResourceCollectionWithPaginationInformation + */ + public static function collection($resource) + { + return tap(new AnonymousResourceCollectionWithPaginationInformation($resource, static::class), function ($collection) { + if (property_exists(static::class, 'preserveKeys')) { + $collection->preserveKeys = (new static([]))->preserveKeys === true; + } + }); + } +} diff --git a/tests/Integration/Http/ResourceTest.php b/tests/Integration/Http/ResourceTest.php index 87a08f9acb8f..98dfc6e16541 100644 --- a/tests/Integration/Http/ResourceTest.php +++ b/tests/Integration/Http/ResourceTest.php @@ -20,7 +20,9 @@ use Illuminate\Tests\Integration\Http\Fixtures\ObjectResource; use Illuminate\Tests\Integration\Http\Fixtures\Post; use Illuminate\Tests\Integration\Http\Fixtures\PostCollectionResource; +use Illuminate\Tests\Integration\Http\Fixtures\PostCollectionResourceWithPaginationInformation; use Illuminate\Tests\Integration\Http\Fixtures\PostResource; +use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithAnonymousResourceCollectionWithPaginationInformation; use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithExtraData; use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalAppendedAttributes; use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalData; @@ -885,6 +887,68 @@ public function testOriginalOnResponseIsCollectionOfModelWhenCollectionResource( }); } + public function testCollectionResourceWithPaginationInfomation() + { + $posts = collect([ + new Post(['id' => 5, 'title' => 'Test Title']), + ]); + + Route::get('/', function () use ($posts) { + return new PostCollectionResourceWithPaginationInformation(new LengthAwarePaginator($posts, 10, 1, 1)); + }); + + $response = $this->withoutExceptionHandling()->get( + '/', + ['Accept' => 'application/json'] + ); + + $response->assertStatus(200); + + $response->assertJson([ + 'data' => [ + [ + 'id' => 5, + 'title' => 'Test Title', + ], + ], + 'current_page' => 1, + 'per_page' => 1, + 'total_page' => 10, + 'total' => 10, + ]); + } + + public function testResourceWithPaginationInfomation() + { + $posts = collect([ + new Post(['id' => 5, 'title' => 'Test Title']), + ]); + + Route::get('/', function () use ($posts) { + return PostResourceWithAnonymousResourceCollectionWithPaginationInformation::collection(new LengthAwarePaginator($posts, 10, 1, 1)); + }); + + $response = $this->withoutExceptionHandling()->get( + '/', + ['Accept' => 'application/json'] + ); + + $response->assertStatus(200); + + $response->assertJson([ + 'data' => [ + [ + 'id' => 5, + 'title' => 'Test Title', + ], + ], + 'current_page' => 1, + 'per_page' => 1, + 'total_page' => 10, + 'total' => 10, + ]); + } + public function testCollectionResourcesAreCountable() { $posts = collect([