From b20c5546ae81a3f5104f527f5bf87005e3ba45b9 Mon Sep 17 00:00:00 2001 From: romainallanot Date: Fri, 20 Oct 2023 16:44:32 +0200 Subject: [PATCH] Eloquent pagination --- src/Laravel/ApiPlatformProvider.php | 42 ++++++++++++++++-- src/Laravel/Eloquent/Paginator.php | 44 +++++++++++++++++++ .../Eloquent/State/CollectionProvider.php | 19 +++++++- src/Laravel/config/api-platform.php | 16 +++++++ 4 files changed, 116 insertions(+), 5 deletions(-) create mode 100644 src/Laravel/Eloquent/Paginator.php diff --git a/src/Laravel/ApiPlatformProvider.php b/src/Laravel/ApiPlatformProvider.php index 0e178db00ba..5a8e8a74d50 100644 --- a/src/Laravel/ApiPlatformProvider.php +++ b/src/Laravel/ApiPlatformProvider.php @@ -86,6 +86,8 @@ use ApiPlatform\Serializer\SerializerContextBuilderInterface; use ApiPlatform\State\CallableProcessor; use ApiPlatform\State\CallableProvider; +use ApiPlatform\State\Pagination\Pagination; +use ApiPlatform\State\Pagination\PaginationOptions; use ApiPlatform\State\Processor\AddLinkHeaderProcessor; use ApiPlatform\State\Processor\RespondProcessor; use ApiPlatform\State\Processor\SerializeProcessor; @@ -149,6 +151,21 @@ public function register(): void 'jsonproblem' => ['application/problem+json'], ]; + $pagination = config('apĂ®-platform.collection.pagination') ?? [ + 'enabled' => true, + 'partial' => false, + 'client_enabled' => false, + 'client_items_per_page' => false, + 'client_partial' => false, + 'items_per_page' => 30, + 'maximum_items_per_page' => null, + 'page_parameter_name' => 'page', + 'enabled_parameter_name' => 'pagination', + 'items_per_page_parameter_name' => 'itemsPerPage', + 'partial_parameter_name' => 'partial', + ]; + $graphqlPagination = []; + // $configuration = [ // 'collection' => [ // 'pagination' => [ @@ -436,6 +453,26 @@ public function register(): void return new EntrypointAction($app->make(ResourceNameCollectionFactoryInterface::class), $app->make(ProviderInterface::class), $app->make(ProcessorInterface::class), ['jsonld' => ['application/ld+json']]); }); + $this->app->singleton(Pagination::class, function () use ($pagination, $graphqlPagination) { + return new Pagination($pagination, $graphqlPagination); + }); + + $this->app->singleton(PaginationOptions::class, function () use ($pagination) { + return new PaginationOptions( + $pagination['enabled'], + $pagination['page_parameter_name'], + $pagination['client_items_per_page'], + $pagination['items_per_page_parameter_name'], + $pagination['client_enabled'], + $pagination['enabled_parameter_name'], + $pagination['items_per_page'], + $pagination['maximum_items_per_page'], + $pagination['partial'], + $pagination['client_partial'], + $pagination['partial_parameter_name'], + ); + }); + $this->app->bind(OpenApiFactoryInterface::class, OpenApiFactory::class); $this->app->singleton(OpenApiFactory::class, function (Application $app) use ($formats) { return new OpenApiFactory( @@ -447,9 +484,8 @@ public function register(): void $app->make(TypeFactoryInterface::class), $app->make(FilterLocator::class), $formats, - // array $formats = [], - // ?Options $openApiOptions = null, - // ?PaginationOptions $paginationOptions = null, + null, // ?Options $openApiOptions = null, + $app->make(PaginationOptions::class), // ?PaginationOptions $paginationOptions = null, // ?RouterInterface $router = null ); }); diff --git a/src/Laravel/Eloquent/Paginator.php b/src/Laravel/Eloquent/Paginator.php new file mode 100644 index 00000000000..ace11760713 --- /dev/null +++ b/src/Laravel/Eloquent/Paginator.php @@ -0,0 +1,44 @@ +paginator->count(); + } + + public function getLastPage(): float + { + return $this->paginator->lastPage(); + } + + public function getTotalItems(): float + { + return $this->paginator->total(); + } + + public function getCurrentPage(): float + { + return $this->paginator->currentPage(); + } + + public function getItemsPerPage(): float + { + return $this->paginator->perPage(); + } + + public function getIterator(): \Traversable + { + return $this->paginator->getIterator(); + } +} diff --git a/src/Laravel/Eloquent/State/CollectionProvider.php b/src/Laravel/Eloquent/State/CollectionProvider.php index 26ee6e3ca2a..d5ea1d7e914 100644 --- a/src/Laravel/Eloquent/State/CollectionProvider.php +++ b/src/Laravel/Eloquent/State/CollectionProvider.php @@ -13,18 +13,33 @@ namespace ApiPlatform\Laravel\Eloquent\State; +use ApiPlatform\Laravel\Eloquent\Paginator; use ApiPlatform\Metadata\Operation; +use ApiPlatform\State\Pagination\Pagination; use ApiPlatform\State\ProviderInterface; +use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Application; class CollectionProvider implements ProviderInterface { - public function __construct(private readonly Application $application) + public function __construct(private readonly Application $application, private readonly Pagination $pagination) { } public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null { - return $this->application->make($operation->getClass())::all(); + /** @var Model $model */ + $model = $this->application->make($operation->getClass()); + + if (false === $this->pagination->isEnabled($operation, $context)) { + return $model::all(); + } + + return new Paginator($model::query() + ->paginate( + perPage: $this->pagination->getLimit($operation, $context), + page: $this->pagination->getPage($context), + ) + ); } } diff --git a/src/Laravel/config/api-platform.php b/src/Laravel/config/api-platform.php index ff483d94694..e50c7d6441b 100644 --- a/src/Laravel/config/api-platform.php +++ b/src/Laravel/config/api-platform.php @@ -48,4 +48,20 @@ 'error_formats' => [ 'jsonproblem' => ['application/problem+json'], ], + + 'collection' => [ + 'pagination' => [ + 'enabled' => true, + 'partial' => false, + 'client_enabled' => false, + 'client_items_per_page' => false, + 'client_partial' => false, + 'items_per_page' => 30, + 'maximum_items_per_page' => null, + 'page_parameter_name' => 'page', + 'enabled_parameter_name' => 'pagination', + 'items_per_page_parameter_name' => 'itemsPerPage', + 'partial_parameter_name' => 'partial', + ], + ], ];