From 6a0a90bf5670959efa1105f52a42f9fdb1b47e72 Mon Sep 17 00:00:00 2001 From: Manuel Bertrams Date: Fri, 13 Sep 2024 01:02:14 +0200 Subject: [PATCH] DoctrineListRepresentationFactory with sorting of ids; hasNextPage with limit/pagination fix --- .../DoctrineListRepresentationFactory.php | 14 ++++ src/Content/EventDataProvider.php | 5 +- src/Repository/EventRepository.php | 84 +++++++------------ src/Resources/config/services.xml | 1 + src/Service/CountryCodeSelect.php | 4 +- 5 files changed, 49 insertions(+), 59 deletions(-) diff --git a/src/Common/DoctrineListRepresentationFactory.php b/src/Common/DoctrineListRepresentationFactory.php index e51145a..6be5a80 100644 --- a/src/Common/DoctrineListRepresentationFactory.php +++ b/src/Common/DoctrineListRepresentationFactory.php @@ -8,6 +8,7 @@ use Sulu\Bundle\MediaBundle\Media\Manager\MediaManagerInterface; use Sulu\Component\Rest\ListBuilder\Doctrine\DoctrineListBuilderFactory; use Sulu\Component\Rest\ListBuilder\Doctrine\FieldDescriptor\DoctrineFieldDescriptor; +use Sulu\Component\Rest\ListBuilder\ListRestHelperInterface; use Sulu\Component\Rest\ListBuilder\Metadata\FieldDescriptorFactoryInterface; use Sulu\Component\Rest\ListBuilder\PaginatedRepresentation; use Sulu\Component\Rest\RestHelperInterface; @@ -16,6 +17,7 @@ class DoctrineListRepresentationFactory { private RestHelperInterface $restHelper; + private ListRestHelperInterface $listRestHelper; private DoctrineListBuilderFactory $listBuilderFactory; private FieldDescriptorFactoryInterface $fieldDescriptorFactory; private WebspaceManagerInterface $webspaceManager; @@ -24,6 +26,7 @@ class DoctrineListRepresentationFactory public function __construct( RestHelperInterface $restHelper, + ListRestHelperInterface $listRestHelper, DoctrineListBuilderFactory $listBuilderFactory, FieldDescriptorFactoryInterface $fieldDescriptorFactory, WebspaceManagerInterface $webspaceManager, @@ -31,6 +34,7 @@ public function __construct( MediaManagerInterface $mediaManager ) { $this->restHelper = $restHelper; + $this->listRestHelper = $listRestHelper; $this->listBuilderFactory = $listBuilderFactory; $this->fieldDescriptorFactory = $fieldDescriptorFactory; $this->webspaceManager = $webspaceManager; @@ -66,6 +70,16 @@ public function createDoctrineListRepresentation( $list = $listBuilder->execute(); + // sort the items to reflect the order of the given ids if the list was requested to include specific ids + $requestedIds = $this->listRestHelper->getIds(); + if (null !== $requestedIds) { + $idPositions = array_flip($requestedIds); + + usort($list, function ($a, $b) use ($idPositions) { + return $idPositions[$a['id']] - $idPositions[$b['id']]; + }); + } + $list = $this->addGhostLocaleToListElements($list, $parameters['locale'] ?? null); $list = $this->addImagesToListElements($list, $parameters['locale'] ?? null); diff --git a/src/Content/EventDataProvider.php b/src/Content/EventDataProvider.php index 1721f6e..a878211 100644 --- a/src/Content/EventDataProvider.php +++ b/src/Content/EventDataProvider.php @@ -4,6 +4,7 @@ namespace Manuxi\SuluEventBundle\Content; +use Countable; use Manuxi\SuluEventBundle\Admin\EventAdmin; use Sulu\Component\Serializer\ArraySerializerInterface; use Sulu\Component\SmartContent\Configuration\ProviderConfigurationInterface; @@ -64,13 +65,13 @@ static function ($item) { * It combines the limit/query-count with the page and page-size. * * @noinspection PhpUnusedPrivateMethodInspection - * @param \Countable $queryResult + * @param Countable $queryResult * @param int|null $limit * @param int $page * @param int|null $pageSize * @return bool */ - private function hasNextPage(\Countable $queryResult, ?int $limit, int $page, ?int $pageSize): bool + private function hasNextPage(Countable $queryResult, ?int $limit, int $page, ?int $pageSize): bool { $count = $queryResult->count(); diff --git a/src/Repository/EventRepository.php b/src/Repository/EventRepository.php index 358e50f..6567dda 100644 --- a/src/Repository/EventRepository.php +++ b/src/Repository/EventRepository.php @@ -88,7 +88,9 @@ public function findAllForSitemap(int $page, int $limit): array public function countForSitemap() { $query = $this->createQueryBuilder('e') - ->select('count(e)'); + ->select('count(e)') + ->where('e.enabled = :enabled') + ->setParameter('enabled', 1); return $query->getQuery()->getSingleScalarResult(); } @@ -122,46 +124,6 @@ public function findAllScheduledEvents(int $limit) return $queryBuilder->getQuery()->getResult(); } - /** - * Returns filtered entities. - * When pagination is active the result count is pageSize + 1 to determine has next page. - * - * @param array $filters array of filters: tags, tagOperator - * @param int $page - * @param int $pageSize - * @param int $limit - * @param string $locale - * @param mixed[] $options - * @param UserInterface|null $user - * @param null $entityClass - * @param null $entityAlias - * @param null $permission - * @return object[] - * @noinspection PhpMissingReturnTypeInspection - * @noinspection PhpMissingParamTypeInspection - */ - /* public function findByFilters( - $filters, - $page, - $pageSize, - $limit, - $locale, - $options = [], - ?UserInterface $user = null, - $entityClass = null, - $entityAlias = null, - $permission = null - ) { - $entities = $this->parentFindByFilters($filters, $page, $pageSize, $limit, $locale, $options); - - return \array_map( - function (Event $entity) use ($locale) { - return $entity->setLocale($locale); - }, - $entities - ); - }*/ - protected function appendJoins(QueryBuilder $queryBuilder, $alias, $locale): void { @@ -212,9 +174,6 @@ function (Event $entity) use ($locale) { public function getActiveEvents(array $filters, string $locale, ?int $page, $pageSize, $limit = null, array $options): array { - // Determine the current page - $pageCurrent = array_key_exists('page', $options) ? (int) $options['page'] : 0; - // Initialize the query builder $queryBuilder = $this->createQueryBuilder('event') ->leftJoin('event.translations', 'translation') @@ -224,16 +183,13 @@ public function getActiveEvents(array $filters, string $locale, ?int $page, $pag ->setParameter('locale', $locale) ->orderBy('event.startDate', 'DESC'); - // Apply limit and pagination - if ($limit !== null) { - $queryBuilder->setMaxResults($limit); - } - if ($pageCurrent !== null && $limit !== null) { - $queryBuilder->setFirstResult($pageCurrent * $limit); - } - // Apply additional filters - $this->prepareFilter($queryBuilder, $filters); + $this->prepareFilters($queryBuilder, $filters); + + // Apply offset/max results + if (!$this->setOffsetResults($queryBuilder, $page, $pageSize, $limit)) { + return []; + } // Execute the query and return results $events = $queryBuilder->getQuery()->getResult(); @@ -241,7 +197,27 @@ public function getActiveEvents(array $filters, string $locale, ?int $page, $pag return $events ?: []; } - private function prepareFilter(QueryBuilder $queryBuilder, array $filters): void + private function setOffsetResults(QueryBuilder $queryBuilder, $page, $pageSize, $limit = null): bool { + if (null !== $page && $pageSize > 0) { + + $pageOffset = ($page - 1) * $pageSize; + $restLimit = $limit - $pageOffset; + + $maxResults = (null !== $limit && $pageSize > $restLimit ? $restLimit : $pageSize); + + if ($maxResults <= 0) { + return false; + } + + $queryBuilder->setMaxResults($maxResults); + $queryBuilder->setFirstResult($pageOffset); + } elseif (null !== $limit) { + $queryBuilder->setMaxResults($limit); + } + return true; + } + + private function prepareFilters(QueryBuilder $queryBuilder, array $filters): void { if (isset($filters['sortBy'])) { $queryBuilder->orderBy($filters['sortBy'], $filters['sortMethod']); diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml index 03ba31b..cc91b7b 100644 --- a/src/Resources/config/services.xml +++ b/src/Resources/config/services.xml @@ -32,6 +32,7 @@ + diff --git a/src/Service/CountryCodeSelect.php b/src/Service/CountryCodeSelect.php index ede42aa..7a74537 100644 --- a/src/Service/CountryCodeSelect.php +++ b/src/Service/CountryCodeSelect.php @@ -8,9 +8,7 @@ class CountryCodeSelect { - /** - * @return array[] - */ + public function getValues(): array { $values = [];