From daf1d3dfa69891a07895c2416d75c62edc4aa98b Mon Sep 17 00:00:00 2001 From: Tobias Gross-Vogt <tgros@tugraz.at> Date: Tue, 20 Sep 2022 09:22:42 +0200 Subject: [PATCH] do pagination in backend --- composer.lock | 16 ++-------- src/API/PersonProviderInterface.php | 5 ++-- .../PersonCollectionDataProvider.php | 30 +++++++------------ src/Entity/Person.php | 1 + src/Service/DummyPersonProvider.php | 14 +++++---- src/TestUtils/DummyPersonProvider.php | 9 ++++-- 6 files changed, 32 insertions(+), 43 deletions(-) diff --git a/composer.lock b/composer.lock index 9cfe8ec..3e4f55a 100644 --- a/composer.lock +++ b/composer.lock @@ -179,15 +179,9 @@ "version": "v0.1.42", "source": { "type": "git", - "url": "https://gitlab.tugraz.at/dbp/relay/dbp-relay-core-bundle.git", + "url": "git@gitlab.tugraz.at:dbp/relay/dbp-relay-core-bundle.git", "reference": "6ae27634574cff5f08ef2ff6cbb3cf72c155cf20" }, - "dist": { - "type": "zip", - "url": "https://gitlab.tugraz.at/api/v4/projects/dbp%2Frelay%2Fdbp-relay-core-bundle/repository/archive.zip?sha=6ae27634574cff5f08ef2ff6cbb3cf72c155cf20", - "reference": "6ae27634574cff5f08ef2ff6cbb3cf72c155cf20", - "shasum": "" - }, "require": { "api-platform/core": "^2.6.6", "doctrine/annotations": "^1.0", @@ -284,11 +278,7 @@ "AGPL-3.0-or-later" ], "description": "The core bundle of the Relay API gateway", - "support": { - "source": "https://gitlab.tugraz.at/dbp/relay/dbp-relay-core-bundle/-/tree/v0.1.42", - "issues": "https://gitlab.tugraz.at/dbp/relay/dbp-relay-core-bundle/-/issues" - }, - "time": "2022-09-14T12:25:56+02:00" + "time": "2022-09-14T10:25:56+00:00" }, { "name": "doctrine/annotations", @@ -10255,5 +10245,5 @@ "platform-overrides": { "php": "7.3" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } diff --git a/src/API/PersonProviderInterface.php b/src/API/PersonProviderInterface.php index a7462c4..a992a1c 100644 --- a/src/API/PersonProviderInterface.php +++ b/src/API/PersonProviderInterface.php @@ -6,6 +6,7 @@ namespace Dbp\Relay\BasePersonBundle\API; use Dbp\Relay\BasePersonBundle\Entity\Person; use Dbp\Relay\CoreBundle\Exception\ApiError; +use Dbp\Relay\CoreBundle\Pagination\Paginator; interface PersonProviderInterface { @@ -16,10 +17,8 @@ interface PersonProviderInterface * * LocalData::QUERY_PARAMETER_NAME * * @throws ApiError - * - * @return Person[] */ - public function getPersons(array $options): array; + public function getPersons(array $options): Paginator; /** * Throws an HTTP_NOT_FOUND exception if no person with the given ID can be found. diff --git a/src/DataProvider/PersonCollectionDataProvider.php b/src/DataProvider/PersonCollectionDataProvider.php index 6a07118..e128a98 100644 --- a/src/DataProvider/PersonCollectionDataProvider.php +++ b/src/DataProvider/PersonCollectionDataProvider.php @@ -8,19 +8,21 @@ use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; use Dbp\Relay\BasePersonBundle\API\PersonProviderInterface; use Dbp\Relay\BasePersonBundle\Entity\Person; -use Dbp\Relay\CoreBundle\Helpers\ArrayFullPaginator; use Dbp\Relay\CoreBundle\LocalData\LocalData; +use Dbp\Relay\CoreBundle\Pagination\Pagination; +use Dbp\Relay\CoreBundle\Pagination\Paginator; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; final class PersonCollectionDataProvider extends AbstractController implements CollectionDataProviderInterface, RestrictedDataProviderInterface { - public const ITEMS_PER_PAGE = 250; + public const MAX_NUM_ITEMS_PER_PAGE_DEFAULT = 50; - private $api; + /** @var PersonProviderInterface */ + private $personProvider; - public function __construct(PersonProviderInterface $api) + public function __construct(PersonProviderInterface $personProvider) { - $this->api = $api; + $this->personProvider = $personProvider; } public function supports(string $resourceClass, string $operationName = null, array $context = []): bool @@ -28,12 +30,10 @@ final class PersonCollectionDataProvider extends AbstractController implements C return Person::class === $resourceClass; } - public function getCollection(string $resourceClass, string $operationName = null, array $context = []): ArrayFullPaginator + public function getCollection(string $resourceClass, string $operationName = null, array $context = []): Paginator { $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY'); - $perPage = self::ITEMS_PER_PAGE; - $page = 1; $filters = $context['filters'] ?? []; $options = []; @@ -42,18 +42,8 @@ final class PersonCollectionDataProvider extends AbstractController implements C } LocalData::addOptions($options, $filters); + Pagination::addOptions($options, $filters, self::MAX_NUM_ITEMS_PER_PAGE_DEFAULT); - $persons = $this->api->getPersons($options); - - if (isset($filters['page'])) { - $page = (int) $filters['page']; - } - - if (isset($filters['perPage'])) { - $perPage = (int) $filters['perPage']; - } - - // TODO: do pagination via API - return new ArrayFullPaginator($persons, $page, $perPage); + return $this->personProvider->getPersons($options); } } diff --git a/src/Entity/Person.php b/src/Entity/Person.php index 35cef0b..c7b1b89 100644 --- a/src/Entity/Person.php +++ b/src/Entity/Person.php @@ -19,6 +19,7 @@ use Dbp\Relay\CoreBundle\LocalData\LocalDataAwareTrait; * "parameters" = { * {"name" = "includeLocal", "in" = "query", "description" = "Local data attributes to include", "type" = "string"}, * {"name" = "queryLocal", "in" = "query", "description" = "Local query parameters to apply", "type" = "string"}, + * {"name" = "partialPagination", "in" = "query", "description" = "Partial pagination", "type" = "bool", "example" = "false"} * } * } * }, diff --git a/src/Service/DummyPersonProvider.php b/src/Service/DummyPersonProvider.php index 792018a..0760ccf 100644 --- a/src/Service/DummyPersonProvider.php +++ b/src/Service/DummyPersonProvider.php @@ -6,6 +6,9 @@ namespace Dbp\Relay\BasePersonBundle\Service; use Dbp\Relay\BasePersonBundle\API\PersonProviderInterface; use Dbp\Relay\BasePersonBundle\Entity\Person; +use Dbp\Relay\CoreBundle\Pagination\FullPaginator; +use Dbp\Relay\CoreBundle\Pagination\Pagination; +use Dbp\Relay\CoreBundle\Pagination\Paginator; class DummyPersonProvider implements PersonProviderInterface { @@ -19,14 +22,15 @@ class DummyPersonProvider implements PersonProviderInterface $this->currentIdentifier = null; } - public function getPersons(array $options): array + public function getPersons(array $options): Paginator { - $person = $this->getCurrentPerson(); - if ($person !== null) { - return [$person]; + $persons = []; + $currentPerson = $this->getCurrentPerson(); + if ($currentPerson !== null) { + $persons[] = $currentPerson; } - return []; + return new FullPaginator($persons, 1, Pagination::MAX_NUM_ITEMS_PER_PAGE_DEFAULT, count($persons)); } public function getPerson(string $id, array $options = []): Person diff --git a/src/TestUtils/DummyPersonProvider.php b/src/TestUtils/DummyPersonProvider.php index f10bb38..861746c 100644 --- a/src/TestUtils/DummyPersonProvider.php +++ b/src/TestUtils/DummyPersonProvider.php @@ -6,6 +6,9 @@ namespace Dbp\Relay\BasePersonBundle\TestUtils; use Dbp\Relay\BasePersonBundle\API\PersonProviderInterface; use Dbp\Relay\BasePersonBundle\Entity\Person; +use Dbp\Relay\CoreBundle\Pagination\FullPaginator; +use Dbp\Relay\CoreBundle\Pagination\Pagination; +use Dbp\Relay\CoreBundle\Pagination\Paginator; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; class DummyPersonProvider implements PersonProviderInterface @@ -18,9 +21,11 @@ class DummyPersonProvider implements PersonProviderInterface $this->person = $person; } - public function getPersons(array $options): array + public function getPersons(array $options): Paginator { - return [$this->person]; + $persons = [$this->person]; + + return new FullPaginator($persons, 1, Pagination::MAX_NUM_ITEMS_PER_PAGE_DEFAULT, count($persons)); } public function getPerson(string $id, array $options = []): Person -- GitLab