From 154f2ef74fb602495ade79f7a7099f9c5fe21c13 Mon Sep 17 00:00:00 2001 From: Ryan Lee Date: Wed, 18 Jun 2025 10:00:49 +0100 Subject: [PATCH 1/5] IBX-10174 Add limit option to getSubtreeSize --- eZ/Publish/API/Repository/LocationService.php | 5 ++- .../Repository/Tests/LocationServiceTest.php | 37 +++++++++++++++++++ .../Persistence/Cache/LocationHandler.php | 4 +- .../Legacy/Content/Location/Gateway.php | 2 +- .../Location/Gateway/DoctrineDatabase.php | 21 +++++++++-- .../Location/Gateway/ExceptionConversion.php | 4 +- .../Legacy/Content/Location/Handler.php | 4 +- .../Core/Repository/LocationService.php | 5 ++- .../SiteAccessAware/LocationService.php | 4 +- .../Persistence/Content/Location/Handler.php | 2 +- .../Decorator/LocationServiceDecorator.php | 4 +- 11 files changed, 73 insertions(+), 19 deletions(-) diff --git a/eZ/Publish/API/Repository/LocationService.php b/eZ/Publish/API/Repository/LocationService.php index e8af6dbc4b..24295d9ea7 100644 --- a/eZ/Publish/API/Repository/LocationService.php +++ b/eZ/Publish/API/Repository/LocationService.php @@ -133,8 +133,11 @@ public function getLocationChildCount(Location $location): int; * Return the subtree size of a given location. * * Warning! This method is not permission aware by design. + * + * @param \eZ\Publish\API\Repository\Values\Content\Location $location + * @param int|null $limit Optional limit to the number of locations to count. (Can be used to limit the number of locations counted in large subtrees.) */ - public function getSubtreeSize(Location $location): int; + public function getSubtreeSize(Location $location, ?int $limit = null): int; /** * Creates the new $location in the content repository for the given content. diff --git a/eZ/Publish/API/Repository/Tests/LocationServiceTest.php b/eZ/Publish/API/Repository/Tests/LocationServiceTest.php index 153f768ba7..b996f0be9b 100644 --- a/eZ/Publish/API/Repository/Tests/LocationServiceTest.php +++ b/eZ/Publish/API/Repository/Tests/LocationServiceTest.php @@ -3552,6 +3552,43 @@ public function testGetSubtreeSize(): Location return $location; } + public function testGetSubtreeSizeWithLimit(): Location + { + $repository = $this->getRepository(); + $locationService = $repository->getLocationService(); + + $folder = $this->createFolder(['eng-GB' => 'Parent Folder'], 2); + $location = $folder->getVersionInfo()->getContentInfo()->getMainLocation(); + self::assertSame(1, $locationService->getSubtreeSize($location)); + + for ($i = 1; $i <= 10; $i++) { + $this->createFolder(['eng-GB' => 'Child ' . $i], $location->id); + } + + self::assertSame(3, $locationService->getSubtreeSize($location, 3)); + + return $location; + } + + public function testGetSubtreeSizeWithInvalidLimitHasNoEffect(): Location + { + $repository = $this->getRepository(); + $locationService = $repository->getLocationService(); + + $folder = $this->createFolder(['eng-GB' => 'Parent Folder'], 2); + $location = $folder->getVersionInfo()->getContentInfo()->getMainLocation(); + self::assertSame(1, $locationService->getSubtreeSize($location)); + + for ($i = 1; $i <= 10; $i++) { + $this->createFolder(['eng-GB' => 'Child ' . $i], $location->id); + } + + + self::assertSame(11, $locationService->getSubtreeSize($location, -2)); + + return $location; + } + /** * Loads properties from all locations in the $location's subtree. * diff --git a/eZ/Publish/Core/Persistence/Cache/LocationHandler.php b/eZ/Publish/Core/Persistence/Cache/LocationHandler.php index d34c03d3b0..d1f7686a4f 100644 --- a/eZ/Publish/Core/Persistence/Cache/LocationHandler.php +++ b/eZ/Publish/Core/Persistence/Cache/LocationHandler.php @@ -259,13 +259,13 @@ public function copySubtree($sourceId, $destinationParentId, $newOwnerId = null) return $this->persistenceHandler->locationHandler()->copySubtree($sourceId, $destinationParentId, $newOwnerId); } - public function getSubtreeSize(string $path): int + public function getSubtreeSize(string $path, ?int $limit = null): int { $this->logger->logCall(__METHOD__, [ 'path' => $path, ]); - return $this->persistenceHandler->locationHandler()->getSubtreeSize($path); + return $this->persistenceHandler->locationHandler()->getSubtreeSize($path, $limit); } /** diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway.php b/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway.php index d49a1f0286..a3a0e70e42 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway.php @@ -111,7 +111,7 @@ abstract public function loadParentLocationsDataForDraftContent(int $contentId): */ abstract public function getSubtreeContent(int $sourceId, bool $onlyIds = false): array; - abstract public function getSubtreeSize(string $path): int; + abstract public function getSubtreeSize(string $path, ?int $limit = null): int; /** * Returns data for the first level children of the location identified by given $locationId. diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway/DoctrineDatabase.php b/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway/DoctrineDatabase.php index 495947b5fa..6b33d3bab3 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway/DoctrineDatabase.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway/DoctrineDatabase.php @@ -237,18 +237,31 @@ public function getSubtreeContent(int $sourceId, bool $onlyIds = false): array : $results; } - public function getSubtreeSize(string $path): int + public function getSubtreeSize(string $path, ?int $limit = null): int { - $query = $this->createNodeQueryBuilder([$this->dbPlatform->getCountExpression('node_id')]); + $useLimit = $limit !== null && $limit > 0; + + $query = $this->createNodeQueryBuilder([$useLimit ? 'node_id': $this->dbPlatform->getCountExpression('node_id')]); $query->andWhere( - $query->expr()->like( + $query->expr()->like( 't.path_string', $query->createPositionalParameter( $path . '%', - ) + ), ) ); + if ($useLimit) { + $query->setMaxResults($limit); + $outerQuery = $this + ->connection + ->createQueryBuilder() + ->select($this->dbPlatform->getCountExpression( '*')) + ->from('(' . $query->getSQL() . ')', 't') + ->setParameters($query->getParameters()); + return (int) $outerQuery->execute()->fetchOne(); + } + return (int) $query->execute()->fetchOne(); } diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway/ExceptionConversion.php b/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway/ExceptionConversion.php index ed1acf56e2..57c90007c3 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway/ExceptionConversion.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway/ExceptionConversion.php @@ -106,10 +106,10 @@ public function getSubtreeContent(int $sourceId, bool $onlyIds = false): array } } - public function getSubtreeSize(string $path): int + public function getSubtreeSize(string $path, ?int $limit = null): int { try { - return $this->innerGateway->getSubtreeSize($path); + return $this->innerGateway->getSubtreeSize($path, $limit); } catch (DBALException | PDOException $e) { throw DatabaseException::wrap($e); } diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/Location/Handler.php b/eZ/Publish/Core/Persistence/Legacy/Content/Location/Handler.php index b125238675..93f51964a1 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/Location/Handler.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/Location/Handler.php @@ -346,9 +346,9 @@ public function copySubtree($sourceId, $destinationParentId, $newOwnerId = null) return $copiedSubtreeRootLocation; } - public function getSubtreeSize(string $path): int + public function getSubtreeSize(string $path, ?int $limit = null): int { - return $this->locationGateway->getSubtreeSize($path); + return $this->locationGateway->getSubtreeSize($path, $limit); } /** diff --git a/eZ/Publish/Core/Repository/LocationService.php b/eZ/Publish/Core/Repository/LocationService.php index 8fa272dd9c..9509400a70 100644 --- a/eZ/Publish/Core/Repository/LocationService.php +++ b/eZ/Publish/Core/Repository/LocationService.php @@ -379,10 +379,11 @@ public function getLocationChildCount(APILocation $location): int return $this->count($filter); } - public function getSubtreeSize(APILocation $location): int + public function getSubtreeSize(APILocation $location, ?int $limit = null): int { return $this->persistenceHandler->locationHandler()->getSubtreeSize( - $location->getPathString() + $location->getPathString(), + $limit ); } diff --git a/eZ/Publish/Core/Repository/SiteAccessAware/LocationService.php b/eZ/Publish/Core/Repository/SiteAccessAware/LocationService.php index 1a5700d2f1..132f9d2558 100644 --- a/eZ/Publish/Core/Repository/SiteAccessAware/LocationService.php +++ b/eZ/Publish/Core/Repository/SiteAccessAware/LocationService.php @@ -109,9 +109,9 @@ public function getLocationChildCount(Location $location): int return $this->service->getLocationChildCount($location); } - public function getSubtreeSize(Location $location): int + public function getSubtreeSize(Location $location, ?int $limit = null): int { - return $this->service->getSubtreeSize($location); + return $this->service->getSubtreeSize($location, $limit); } public function createLocation(ContentInfo $contentInfo, LocationCreateStruct $locationCreateStruct): Location diff --git a/eZ/Publish/SPI/Persistence/Content/Location/Handler.php b/eZ/Publish/SPI/Persistence/Content/Location/Handler.php index ff36c20df7..fc69b27adf 100644 --- a/eZ/Publish/SPI/Persistence/Content/Location/Handler.php +++ b/eZ/Publish/SPI/Persistence/Content/Location/Handler.php @@ -110,7 +110,7 @@ public function loadParentLocationsForDraftContent($contentId); */ public function copySubtree($sourceId, $destinationParentId); - public function getSubtreeSize(string $path): int; + public function getSubtreeSize(string $path, ?int $limit = null): int; /** * Moves location identified by $sourceId into new parent identified by $destinationParentId. diff --git a/eZ/Publish/SPI/Repository/Decorator/LocationServiceDecorator.php b/eZ/Publish/SPI/Repository/Decorator/LocationServiceDecorator.php index 31885e27b9..6debd1f067 100644 --- a/eZ/Publish/SPI/Repository/Decorator/LocationServiceDecorator.php +++ b/eZ/Publish/SPI/Repository/Decorator/LocationServiceDecorator.php @@ -87,9 +87,9 @@ public function getLocationChildCount(Location $location): int return $this->innerService->getLocationChildCount($location); } - public function getSubtreeSize(Location $location): int + public function getSubtreeSize(Location $location, ?int $limit = null): int { - return $this->innerService->getSubtreeSize($location); + return $this->innerService->getSubtreeSize($location, $limit); } public function createLocation( From 8eebd254582ec7c4f2167a15cba8436b2b77e4d4 Mon Sep 17 00:00:00 2001 From: Ryan Lee Date: Wed, 18 Jun 2025 10:05:16 +0100 Subject: [PATCH 2/5] IBX-10174 Run linter --- eZ/Publish/API/Repository/LocationService.php | 2 +- eZ/Publish/API/Repository/Tests/LocationServiceTest.php | 7 +++---- .../Legacy/Content/Location/Gateway/DoctrineDatabase.php | 9 +++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/eZ/Publish/API/Repository/LocationService.php b/eZ/Publish/API/Repository/LocationService.php index 24295d9ea7..cc1c858374 100644 --- a/eZ/Publish/API/Repository/LocationService.php +++ b/eZ/Publish/API/Repository/LocationService.php @@ -133,7 +133,7 @@ public function getLocationChildCount(Location $location): int; * Return the subtree size of a given location. * * Warning! This method is not permission aware by design. - * + * * @param \eZ\Publish\API\Repository\Values\Content\Location $location * @param int|null $limit Optional limit to the number of locations to count. (Can be used to limit the number of locations counted in large subtrees.) */ diff --git a/eZ/Publish/API/Repository/Tests/LocationServiceTest.php b/eZ/Publish/API/Repository/Tests/LocationServiceTest.php index b996f0be9b..a0d51747b3 100644 --- a/eZ/Publish/API/Repository/Tests/LocationServiceTest.php +++ b/eZ/Publish/API/Repository/Tests/LocationServiceTest.php @@ -3561,7 +3561,7 @@ public function testGetSubtreeSizeWithLimit(): Location $location = $folder->getVersionInfo()->getContentInfo()->getMainLocation(); self::assertSame(1, $locationService->getSubtreeSize($location)); - for ($i = 1; $i <= 10; $i++) { + for ($i = 1; $i <= 10; ++$i) { $this->createFolder(['eng-GB' => 'Child ' . $i], $location->id); } @@ -3570,7 +3570,7 @@ public function testGetSubtreeSizeWithLimit(): Location return $location; } - public function testGetSubtreeSizeWithInvalidLimitHasNoEffect(): Location + public function testGetSubtreeSizeWithInvalidLimitHasNoEffect(): Location { $repository = $this->getRepository(); $locationService = $repository->getLocationService(); @@ -3579,11 +3579,10 @@ public function testGetSubtreeSizeWithInvalidLimitHasNoEffect(): Location $location = $folder->getVersionInfo()->getContentInfo()->getMainLocation(); self::assertSame(1, $locationService->getSubtreeSize($location)); - for ($i = 1; $i <= 10; $i++) { + for ($i = 1; $i <= 10; ++$i) { $this->createFolder(['eng-GB' => 'Child ' . $i], $location->id); } - self::assertSame(11, $locationService->getSubtreeSize($location, -2)); return $location; diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway/DoctrineDatabase.php b/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway/DoctrineDatabase.php index 6b33d3bab3..179e4c71f7 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway/DoctrineDatabase.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway/DoctrineDatabase.php @@ -241,9 +241,9 @@ public function getSubtreeSize(string $path, ?int $limit = null): int { $useLimit = $limit !== null && $limit > 0; - $query = $this->createNodeQueryBuilder([$useLimit ? 'node_id': $this->dbPlatform->getCountExpression('node_id')]); + $query = $this->createNodeQueryBuilder([$useLimit ? 'node_id' : $this->dbPlatform->getCountExpression('node_id')]); $query->andWhere( - $query->expr()->like( + $query->expr()->like( 't.path_string', $query->createPositionalParameter( $path . '%', @@ -256,9 +256,10 @@ public function getSubtreeSize(string $path, ?int $limit = null): int $outerQuery = $this ->connection ->createQueryBuilder() - ->select($this->dbPlatform->getCountExpression( '*')) - ->from('(' . $query->getSQL() . ')', 't') + ->select($this->dbPlatform->getCountExpression('*')) + ->from('(' . $query->getSQL() . ')', 't') ->setParameters($query->getParameters()); + return (int) $outerQuery->execute()->fetchOne(); } From c52ca74e772ed03a1397415f87c0dbbcc24a8191 Mon Sep 17 00:00:00 2001 From: Ryan Lee Date: Thu, 19 Jun 2025 15:53:11 +0100 Subject: [PATCH 3/5] IBX-10186 Add limitation to ::count API's for performance reasons --- eZ/Publish/API/Repository/ContentService.php | 4 ++- eZ/Publish/API/Repository/LocationService.php | 6 +++-- .../Repository/Tests/LocationServiceTest.php | 20 ++++++++++++++ .../Content/Doctrine/DoctrineGateway.php | 26 ++++++++++++++++--- .../Legacy/Filter/Gateway/Gateway.php | 4 +-- .../Location/Doctrine/DoctrineGateway.php | 26 +++++++++++++++++-- .../Handler/ContentFilteringHandler.php | 4 +-- .../Handler/LocationFilteringHandler.php | 4 +-- eZ/Publish/Core/Repository/ContentService.php | 4 +-- .../Core/Repository/LocationService.php | 8 +++--- .../SiteAccessAware/ContentService.php | 5 ++-- .../SiteAccessAware/LocationService.php | 9 ++++--- .../Persistence/Filter/Content/Handler.php | 2 +- .../Persistence/Filter/Location/Handler.php | 2 +- .../Decorator/ContentServiceDecorator.php | 2 +- .../Decorator/LocationServiceDecorator.php | 8 +++--- .../LocationServiceDecoratorTest.php | 2 +- 17 files changed, 102 insertions(+), 34 deletions(-) diff --git a/eZ/Publish/API/Repository/ContentService.php b/eZ/Publish/API/Repository/ContentService.php index ead453871a..e13d4451ad 100644 --- a/eZ/Publish/API/Repository/ContentService.php +++ b/eZ/Publish/API/Repository/ContentService.php @@ -588,6 +588,8 @@ public function find(Filter $filter, ?array $languages = null): ContentList; * @param string[] $languages a list of language codes to be added as additional constraints. * If skipped, by default, unless SiteAccessAware layer has been disabled, languages set * for a SiteAccess in a current context will be used. + * @param int|null $limit If set, the count will be limited to first $limit items found. + * In some cases it can significantly speed up a count operation for more complex filters. */ - public function count(Filter $filter, ?array $languages = null): int; + public function count(Filter $filter, ?array $languages = null, ?int $limit = null): int; } diff --git a/eZ/Publish/API/Repository/LocationService.php b/eZ/Publish/API/Repository/LocationService.php index cc1c858374..750ce4838f 100644 --- a/eZ/Publish/API/Repository/LocationService.php +++ b/eZ/Publish/API/Repository/LocationService.php @@ -127,7 +127,7 @@ public function loadParentLocationsForDraftContent(VersionInfo $versionInfo, ?ar * * @return int */ - public function getLocationChildCount(Location $location): int; + public function getLocationChildCount(Location $location, ?int $limit = null): int; /** * Return the subtree size of a given location. @@ -278,6 +278,8 @@ public function find(Filter $filter, ?array $languages = null): LocationList; * @param string[] $languages a list of language codes to be added as additional constraints. * If skipped, by default, unless SiteAccessAware layer has been disabled, languages set * for a SiteAccess in a current context will be used. + * @param int|null $limit If set, the count will be limited to first $limit items found. + * In some cases it can significantly speed up a count operation for more complex filters. */ - public function count(Filter $filter, ?array $languages = null): int; + public function count(Filter $filter, ?array $languages = null, ?int $limit = null): int; } diff --git a/eZ/Publish/API/Repository/Tests/LocationServiceTest.php b/eZ/Publish/API/Repository/Tests/LocationServiceTest.php index a0d51747b3..0fd322cf63 100644 --- a/eZ/Publish/API/Repository/Tests/LocationServiceTest.php +++ b/eZ/Publish/API/Repository/Tests/LocationServiceTest.php @@ -1114,6 +1114,26 @@ public function testGetLocationChildCount() ); } + /** + * Test for the getLocationChildCount() method with a limitation on the number of children. + * + * @see \eZ\Publish\API\Repository\LocationService::getLocationChildCount() + * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation + */ + public function testGetLocationChildCountWithLimitation() + { + // $locationId is the ID of an existing location + $locationService = $this->getRepository()->getLocationService(); + + $this->assertSame( + 2, + $locationService->getLocationChildCount( + $locationService->loadLocation($this->generateId('location', 5)), + 2 + ) + ); + } + /** * Test for the loadLocationChildren() method. * diff --git a/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Content/Doctrine/DoctrineGateway.php b/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Content/Doctrine/DoctrineGateway.php index 0cef49854a..205f6e578b 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Content/Doctrine/DoctrineGateway.php +++ b/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Content/Doctrine/DoctrineGateway.php @@ -87,13 +87,33 @@ private function getDatabasePlatform(): AbstractPlatform } } - public function count(FilteringCriterion $criterion): int + public function count(FilteringCriterion $criterion, ?int $limit = null): int { + $useLimit = $limit !== null && $limit > 0; + $query = $this->buildQuery( - [$this->getDatabasePlatform()->getCountExpression('DISTINCT content.id')], - $criterion + [$useLimit ? + 'content.id' : + $this->getDatabasePlatform()->getCountExpression('DISTINCT content.id')], + $criterion ); + + if ($useLimit) { + $query->setMaxResults($limit); + $outerQuery = $this->connection->createQueryBuilder(); + $outerQuery + ->select( + $this->getDatabasePlatform()->getCountExpression('*') + ) + ->from('(' . $query->getSQL() . ')', 'subquery') + ->setParameters($query->getParameters(), $query->getParameterTypes()) + ; + + + return (int)$outerQuery->execute()->fetch(FetchMode::COLUMN); + } + return (int)$query->execute()->fetch(FetchMode::COLUMN); } diff --git a/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Gateway.php b/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Gateway.php index ec64507575..92368afabf 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Gateway.php +++ b/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Gateway.php @@ -18,9 +18,9 @@ interface Gateway { /** - * Return number of matched rows for the given Criteria (a total count w/o pagination constraints). + * Return number of matched rows for the given Criteria (a total count w/o pagination constraints unless an upper limit is applied). */ - public function count(FilteringCriterion $criterion): int; + public function count(FilteringCriterion $criterion, ?int $limit = null): int; /** * Return iterator for raw Repository data for the given Query result filtered by the given Criteria, diff --git a/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Location/Doctrine/DoctrineGateway.php b/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Location/Doctrine/DoctrineGateway.php index 3f545d58d2..bb567a5b56 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Location/Doctrine/DoctrineGateway.php +++ b/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Location/Doctrine/DoctrineGateway.php @@ -12,6 +12,7 @@ use Doctrine\DBAL\DBALException; use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\Platforms\AbstractPlatform; +use Exception; use eZ\Publish\Core\Base\Exceptions\DatabaseException; use eZ\Publish\Core\Persistence\Legacy\Content\Gateway as ContentGateway; use eZ\Publish\Core\Persistence\Legacy\Content\Location\Gateway as LocationGateway; @@ -54,11 +55,32 @@ private function getDatabasePlatform(): AbstractPlatform } } - public function count(FilteringCriterion $criterion): int + public function count(FilteringCriterion $criterion, ?int $limit = null): int { + $useLimit = $limit !== null && $limit > 0; $query = $this->buildQuery($criterion); - $query->select($this->getDatabasePlatform()->getCountExpression('DISTINCT location.node_id')); + $query->select( + $useLimit ? + 'location.node_id' : + $this->getDatabasePlatform()->getCountExpression('DISTINCT location.node_id') + ); + + + if ($useLimit) { + $query->setMaxResults($limit); + $outerQuery = $this->connection->createQueryBuilder(); + $outerQuery + ->select( + $this->getDatabasePlatform()->getCountExpression('*') + ) + ->from('(' . $query->getSQL() . ')', 'subquery') + ->setParameters($query->getParameters(), $query->getParameterTypes()) + ; + + + return (int)$outerQuery->execute()->fetch(FetchMode::COLUMN); + } return (int)$query->execute()->fetch(FetchMode::COLUMN); } diff --git a/eZ/Publish/Core/Persistence/Legacy/Filter/Handler/ContentFilteringHandler.php b/eZ/Publish/Core/Persistence/Legacy/Filter/Handler/ContentFilteringHandler.php index 488b7efdb9..eef6e88c50 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Filter/Handler/ContentFilteringHandler.php +++ b/eZ/Publish/Core/Persistence/Legacy/Filter/Handler/ContentFilteringHandler.php @@ -73,8 +73,8 @@ function (array $row): ContentItem { return $list; } - public function count(Filter $filter): int + public function count(Filter $filter, ?int $limit = null): int { - return $this->gateway->count($filter->getCriterion()); + return $this->gateway->count($filter->getCriterion(), $limit); } } diff --git a/eZ/Publish/Core/Persistence/Legacy/Filter/Handler/LocationFilteringHandler.php b/eZ/Publish/Core/Persistence/Legacy/Filter/Handler/LocationFilteringHandler.php index 7c27e62a16..ff422eeaac 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Filter/Handler/LocationFilteringHandler.php +++ b/eZ/Publish/Core/Persistence/Legacy/Filter/Handler/LocationFilteringHandler.php @@ -69,8 +69,8 @@ function (array $row): LocationWithContentInfo { return $list; } - public function count(Filter $filter): int + public function count(Filter $filter, ?int $limit = null): int { - return $this->gateway->count($filter->getCriterion()); + return $this->gateway->count($filter->getCriterion(), $limit); } } diff --git a/eZ/Publish/Core/Repository/ContentService.php b/eZ/Publish/Core/Repository/ContentService.php index 370bba6c90..d9f3edee9d 100644 --- a/eZ/Publish/Core/Repository/ContentService.php +++ b/eZ/Publish/Core/Repository/ContentService.php @@ -2626,7 +2626,7 @@ public function find(Filter $filter, ?array $languages = null): ContentList return new ContentList($contentItemsIterator->getTotalCount(), $contentItems); } - public function count(Filter $filter, ?array $languages = null): int + public function count(Filter $filter, ?array $languages = null, ?int $limit = null): int { $filter = clone $filter; if (!empty($languages)) { @@ -2646,6 +2646,6 @@ public function count(Filter $filter, ?array $languages = null): int $filter->andWithCriterion($permissionCriterion); } - return $this->contentFilteringHandler->count($filter); + return $this->contentFilteringHandler->count($filter, $limit); } } diff --git a/eZ/Publish/Core/Repository/LocationService.php b/eZ/Publish/Core/Repository/LocationService.php index 9509400a70..023fd8eb1b 100644 --- a/eZ/Publish/Core/Repository/LocationService.php +++ b/eZ/Publish/Core/Repository/LocationService.php @@ -372,11 +372,11 @@ public function loadParentLocationsForDraftContent(VersionInfo $versionInfo, ?ar /** * Returns the number of children which are readable by the current user of a Location object. */ - public function getLocationChildCount(APILocation $location): int + public function getLocationChildCount(APILocation $location, ?int $limit = null): int { $filter = $this->buildLocationChildrenFilter($location); - return $this->count($filter); + return $this->count($filter,null, $limit); } public function getSubtreeSize(APILocation $location, ?int $limit = null): int @@ -944,7 +944,7 @@ public function find(Filter $filter, ?array $languages = null): LocationList ); } - public function count(Filter $filter, ?array $languages = null): int + public function count(Filter $filter, ?array $languages = null, ?int $limit = null): int { $filter = clone $filter; if (!empty($languages)) { @@ -964,7 +964,7 @@ public function count(Filter $filter, ?array $languages = null): int $filter->andWithCriterion($permissionCriterion); } - return $this->locationFilteringHandler->count($filter); + return $this->locationFilteringHandler->count($filter, $limit); } /** diff --git a/eZ/Publish/Core/Repository/SiteAccessAware/ContentService.php b/eZ/Publish/Core/Repository/SiteAccessAware/ContentService.php index 3c76b09317..f8233bc303 100644 --- a/eZ/Publish/Core/Repository/SiteAccessAware/ContentService.php +++ b/eZ/Publish/Core/Repository/SiteAccessAware/ContentService.php @@ -284,11 +284,12 @@ public function find(Filter $filter, ?array $languages = null): ContentList ); } - public function count(Filter $filter, ?array $languages = null): int + public function count(Filter $filter, ?array $languages = null, ?int $limit = null): int { return $this->service->count( $filter, - $this->languageResolver->getPrioritizedLanguages($languages) + $this->languageResolver->getPrioritizedLanguages($languages), + $limit ); } } diff --git a/eZ/Publish/Core/Repository/SiteAccessAware/LocationService.php b/eZ/Publish/Core/Repository/SiteAccessAware/LocationService.php index 132f9d2558..86f4b83523 100644 --- a/eZ/Publish/Core/Repository/SiteAccessAware/LocationService.php +++ b/eZ/Publish/Core/Repository/SiteAccessAware/LocationService.php @@ -104,9 +104,9 @@ public function loadParentLocationsForDraftContent(VersionInfo $versionInfo, ?ar ); } - public function getLocationChildCount(Location $location): int + public function getLocationChildCount(Location $location, ?int $limit = null ): int { - return $this->service->getLocationChildCount($location); + return $this->service->getLocationChildCount($location, $limit); } public function getSubtreeSize(Location $location, ?int $limit = null): int @@ -192,11 +192,12 @@ public function find(Filter $filter, ?array $languages = null): LocationList ); } - public function count(Filter $filter, ?array $languages = null): int + public function count(Filter $filter, ?array $languages = null, ?int $limit = null): int { return $this->service->count( $filter, - $this->languageResolver->getPrioritizedLanguages($languages) + $this->languageResolver->getPrioritizedLanguages($languages), + $limit ); } } diff --git a/eZ/Publish/SPI/Persistence/Filter/Content/Handler.php b/eZ/Publish/SPI/Persistence/Filter/Content/Handler.php index 3acd26f354..d03db1cfe9 100644 --- a/eZ/Publish/SPI/Persistence/Filter/Content/Handler.php +++ b/eZ/Publish/SPI/Persistence/Filter/Content/Handler.php @@ -22,5 +22,5 @@ interface Handler */ public function find(Filter $filter): iterable; - public function count(Filter $filter): int; + public function count(Filter $filter, ?int $limit = null): int; } diff --git a/eZ/Publish/SPI/Persistence/Filter/Location/Handler.php b/eZ/Publish/SPI/Persistence/Filter/Location/Handler.php index 84ef9e397e..ae8110dede 100644 --- a/eZ/Publish/SPI/Persistence/Filter/Location/Handler.php +++ b/eZ/Publish/SPI/Persistence/Filter/Location/Handler.php @@ -22,5 +22,5 @@ interface Handler */ public function find(Filter $filter): iterable; - public function count(Filter $filter): int; + public function count(Filter $filter, ?int $limit = null): int; } diff --git a/eZ/Publish/SPI/Repository/Decorator/ContentServiceDecorator.php b/eZ/Publish/SPI/Repository/Decorator/ContentServiceDecorator.php index e45b5038be..755ffbe0a1 100644 --- a/eZ/Publish/SPI/Repository/Decorator/ContentServiceDecorator.php +++ b/eZ/Publish/SPI/Repository/Decorator/ContentServiceDecorator.php @@ -276,7 +276,7 @@ public function find(Filter $filter, ?array $languages = null): ContentList return $this->innerService->find($filter, $languages); } - public function count(Filter $filter, ?array $languages = null): int + public function count(Filter $filter, ?array $languages = null, ?int $limit = $limit): int { return $this->innerService->count($filter, $languages); } diff --git a/eZ/Publish/SPI/Repository/Decorator/LocationServiceDecorator.php b/eZ/Publish/SPI/Repository/Decorator/LocationServiceDecorator.php index 6debd1f067..276147a778 100644 --- a/eZ/Publish/SPI/Repository/Decorator/LocationServiceDecorator.php +++ b/eZ/Publish/SPI/Repository/Decorator/LocationServiceDecorator.php @@ -82,9 +82,9 @@ public function loadParentLocationsForDraftContent( return $this->innerService->loadParentLocationsForDraftContent($versionInfo, $prioritizedLanguages); } - public function getLocationChildCount(Location $location): int + public function getLocationChildCount(Location $location, ?int $limit = null): int { - return $this->innerService->getLocationChildCount($location); + return $this->innerService->getLocationChildCount($location, $limit); } public function getSubtreeSize(Location $location, ?int $limit = null): int @@ -160,8 +160,8 @@ public function find(Filter $filter, ?array $languages = null): LocationList return $this->innerService->find($filter, $languages); } - public function count(Filter $filter, ?array $languages = null): int + public function count(Filter $filter, ?array $languages = null, ?int $limit = null): int { - return $this->innerService->count($filter, $languages); + return $this->innerService->count($filter, $languages, $limit); } } diff --git a/eZ/Publish/SPI/Repository/Tests/Decorator/LocationServiceDecoratorTest.php b/eZ/Publish/SPI/Repository/Tests/Decorator/LocationServiceDecoratorTest.php index 128fc40758..0b9a3d5259 100644 --- a/eZ/Publish/SPI/Repository/Tests/Decorator/LocationServiceDecoratorTest.php +++ b/eZ/Publish/SPI/Repository/Tests/Decorator/LocationServiceDecoratorTest.php @@ -151,7 +151,7 @@ public function testGetLocationChildCountDecorator() $serviceMock = $this->createServiceMock(); $decoratedService = $this->createDecorator($serviceMock); - $parameters = [$this->createMock(Location::class)]; + $parameters = [$this->createMock(Location::class), 8]; $serviceMock->expects($this->once())->method('getLocationChildCount')->with(...$parameters); From 9b643def0c3369ea1f66b352afed81cab284da49 Mon Sep 17 00:00:00 2001 From: Ryan Lee Date: Thu, 19 Jun 2025 17:24:11 +0100 Subject: [PATCH 4/5] IBX-10186 Dedupe code to meet quality gate --- .../Location/Gateway/DoctrineDatabase.php | 23 ++++---- .../Content/Doctrine/DoctrineGateway.php | 29 ++++------ .../Location/Doctrine/DoctrineGateway.php | 30 ++++------- .../Doctrine/LimitedCountQueryTrait.php | 54 +++++++++++++++++++ .../Decorator/ContentServiceDecorator.php | 4 +- 5 files changed, 83 insertions(+), 57 deletions(-) create mode 100644 eZ/Publish/Core/Persistence/Legacy/Traits/Doctrine/LimitedCountQueryTrait.php diff --git a/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway/DoctrineDatabase.php b/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway/DoctrineDatabase.php index 179e4c71f7..b1617fe565 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway/DoctrineDatabase.php +++ b/eZ/Publish/Core/Persistence/Legacy/Content/Location/Gateway/DoctrineDatabase.php @@ -16,6 +16,7 @@ use eZ\Publish\Core\Persistence\Legacy\Content\Gateway as ContentGateway; use eZ\Publish\Core\Persistence\Legacy\Content\Language\MaskGenerator; use eZ\Publish\Core\Persistence\Legacy\Content\Location\Gateway; +use eZ\Publish\Core\Persistence\Legacy\Traits\Doctrine\LimitedCountQueryTrait; use eZ\Publish\Core\Search\Legacy\Content\Common\Gateway\CriteriaConverter; use eZ\Publish\Core\Search\Legacy\Content\Common\Gateway\SortClauseConverter; use eZ\Publish\SPI\Persistence\Content\ContentInfo; @@ -35,6 +36,8 @@ */ final class DoctrineDatabase extends Gateway { + use LimitedCountQueryTrait; + /** @var \Doctrine\DBAL\Connection */ private $connection; @@ -239,9 +242,7 @@ public function getSubtreeContent(int $sourceId, bool $onlyIds = false): array public function getSubtreeSize(string $path, ?int $limit = null): int { - $useLimit = $limit !== null && $limit > 0; - - $query = $this->createNodeQueryBuilder([$useLimit ? 'node_id' : $this->dbPlatform->getCountExpression('node_id')]); + $query = $this->createNodeQueryBuilder([$this->dbPlatform->getCountExpression('node_id')]); $query->andWhere( $query->expr()->like( 't.path_string', @@ -251,17 +252,11 @@ public function getSubtreeSize(string $path, ?int $limit = null): int ) ); - if ($useLimit) { - $query->setMaxResults($limit); - $outerQuery = $this - ->connection - ->createQueryBuilder() - ->select($this->dbPlatform->getCountExpression('*')) - ->from('(' . $query->getSQL() . ')', 't') - ->setParameters($query->getParameters()); - - return (int) $outerQuery->execute()->fetchOne(); - } + $query = $this->wrapCountQuery( + $query, + 't.node_id', + $limit + ); return (int) $query->execute()->fetchOne(); } diff --git a/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Content/Doctrine/DoctrineGateway.php b/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Content/Doctrine/DoctrineGateway.php index 205f6e578b..d7cec03fbd 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Content/Doctrine/DoctrineGateway.php +++ b/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Content/Doctrine/DoctrineGateway.php @@ -8,6 +8,7 @@ namespace eZ\Publish\Core\Persistence\Legacy\Filter\Gateway\Content\Doctrine; +use eZ\Publish\Core\Persistence\Legacy\Traits\Doctrine\LimitedCountQueryTrait; use function array_filter; use Doctrine\DBAL\Connection; use Doctrine\DBAL\DBALException; @@ -31,6 +32,8 @@ */ final class DoctrineGateway implements Gateway { + use LimitedCountQueryTrait; + public const COLUMN_MAP = [ // Content Info 'content_id' => 'content.id', @@ -89,30 +92,16 @@ private function getDatabasePlatform(): AbstractPlatform public function count(FilteringCriterion $criterion, ?int $limit = null): int { - $useLimit = $limit !== null && $limit > 0; - $query = $this->buildQuery( - [$useLimit ? - 'content.id' : - $this->getDatabasePlatform()->getCountExpression('DISTINCT content.id')], + [$this->getDatabasePlatform()->getCountExpression('DISTINCT content.id')], $criterion ); - - if ($useLimit) { - $query->setMaxResults($limit); - $outerQuery = $this->connection->createQueryBuilder(); - $outerQuery - ->select( - $this->getDatabasePlatform()->getCountExpression('*') - ) - ->from('(' . $query->getSQL() . ')', 'subquery') - ->setParameters($query->getParameters(), $query->getParameterTypes()) - ; - - - return (int)$outerQuery->execute()->fetch(FetchMode::COLUMN); - } + $query = $this->wrapCountQuery( + $query, + 'content.id', + $limit + ); return (int)$query->execute()->fetch(FetchMode::COLUMN); } diff --git a/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Location/Doctrine/DoctrineGateway.php b/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Location/Doctrine/DoctrineGateway.php index bb567a5b56..e08c15e827 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Location/Doctrine/DoctrineGateway.php +++ b/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Location/Doctrine/DoctrineGateway.php @@ -17,6 +17,7 @@ use eZ\Publish\Core\Persistence\Legacy\Content\Gateway as ContentGateway; use eZ\Publish\Core\Persistence\Legacy\Content\Location\Gateway as LocationGateway; use eZ\Publish\Core\Persistence\Legacy\Filter\Gateway\Gateway; +use eZ\Publish\Core\Persistence\Legacy\Traits\Doctrine\LimitedCountQueryTrait; use eZ\Publish\SPI\Persistence\Filter\CriterionVisitor; use eZ\Publish\SPI\Persistence\Filter\Doctrine\FilteringQueryBuilder; use eZ\Publish\SPI\Persistence\Filter\SortClauseVisitor; @@ -27,6 +28,8 @@ */ final class DoctrineGateway implements Gateway { + use LimitedCountQueryTrait; + /** @var \Doctrine\DBAL\Connection */ private $connection; @@ -57,30 +60,15 @@ private function getDatabasePlatform(): AbstractPlatform public function count(FilteringCriterion $criterion, ?int $limit = null): int { - $useLimit = $limit !== null && $limit > 0; $query = $this->buildQuery($criterion); - $query->select( - $useLimit ? - 'location.node_id' : - $this->getDatabasePlatform()->getCountExpression('DISTINCT location.node_id') - ); - + $query->select($this->getDatabasePlatform()->getCountExpression('DISTINCT location.node_id')); - if ($useLimit) { - $query->setMaxResults($limit); - $outerQuery = $this->connection->createQueryBuilder(); - $outerQuery - ->select( - $this->getDatabasePlatform()->getCountExpression('*') - ) - ->from('(' . $query->getSQL() . ')', 'subquery') - ->setParameters($query->getParameters(), $query->getParameterTypes()) - ; - - - return (int)$outerQuery->execute()->fetch(FetchMode::COLUMN); - } + $query = $this->wrapCountQuery( + $query, + 'location.node_id', + $limit + ); return (int)$query->execute()->fetch(FetchMode::COLUMN); } diff --git a/eZ/Publish/Core/Persistence/Legacy/Traits/Doctrine/LimitedCountQueryTrait.php b/eZ/Publish/Core/Persistence/Legacy/Traits/Doctrine/LimitedCountQueryTrait.php new file mode 100644 index 0000000000..1829fc071a --- /dev/null +++ b/eZ/Publish/Core/Persistence/Legacy/Traits/Doctrine/LimitedCountQueryTrait.php @@ -0,0 +1,54 @@ + 0; + + if(!$useLimit) { + return $queryBuilder; + } + + $querySql = $queryBuilder->select($countableField) + ->setMaxResults($limit) + ->getSQL(); + + $countQuery = $this->connection->createQueryBuilder(); + return $countQuery + ->select( + $queryBuilder->getConnection()->getDatabasePlatform()->getCountExpression('*') + ) + ->from('(' . $querySql . ')', 'csub') + ->setParameters($queryBuilder->getParameters(), $queryBuilder->getParameterTypes()); + } +} diff --git a/eZ/Publish/SPI/Repository/Decorator/ContentServiceDecorator.php b/eZ/Publish/SPI/Repository/Decorator/ContentServiceDecorator.php index 755ffbe0a1..27504fe6f6 100644 --- a/eZ/Publish/SPI/Repository/Decorator/ContentServiceDecorator.php +++ b/eZ/Publish/SPI/Repository/Decorator/ContentServiceDecorator.php @@ -276,8 +276,8 @@ public function find(Filter $filter, ?array $languages = null): ContentList return $this->innerService->find($filter, $languages); } - public function count(Filter $filter, ?array $languages = null, ?int $limit = $limit): int + public function count(Filter $filter, ?array $languages = null, ?int $limit = null): int { - return $this->innerService->count($filter, $languages); + return $this->innerService->count($filter, $languages, $limit); } } From a68fe6e6e8d4cc26a4c15ccac1df78e2e3925835 Mon Sep 17 00:00:00 2001 From: Ryan Lee Date: Thu, 19 Jun 2025 17:48:16 +0100 Subject: [PATCH 5/5] IBX-10186 Run CS --- .../API/Repository/Tests/LocationServiceTest.php | 2 +- .../Gateway/Content/Doctrine/DoctrineGateway.php | 4 ++-- .../Gateway/Location/Doctrine/DoctrineGateway.php | 1 - .../Legacy/Traits/Doctrine/LimitedCountQueryTrait.php | 10 ++++++---- eZ/Publish/Core/Repository/LocationService.php | 4 ++-- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/eZ/Publish/API/Repository/Tests/LocationServiceTest.php b/eZ/Publish/API/Repository/Tests/LocationServiceTest.php index 0fd322cf63..7979aa482b 100644 --- a/eZ/Publish/API/Repository/Tests/LocationServiceTest.php +++ b/eZ/Publish/API/Repository/Tests/LocationServiceTest.php @@ -1114,7 +1114,7 @@ public function testGetLocationChildCount() ); } - /** + /** * Test for the getLocationChildCount() method with a limitation on the number of children. * * @see \eZ\Publish\API\Repository\LocationService::getLocationChildCount() diff --git a/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Content/Doctrine/DoctrineGateway.php b/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Content/Doctrine/DoctrineGateway.php index d7cec03fbd..2855cf87df 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Content/Doctrine/DoctrineGateway.php +++ b/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Content/Doctrine/DoctrineGateway.php @@ -8,7 +8,6 @@ namespace eZ\Publish\Core\Persistence\Legacy\Filter\Gateway\Content\Doctrine; -use eZ\Publish\Core\Persistence\Legacy\Traits\Doctrine\LimitedCountQueryTrait; use function array_filter; use Doctrine\DBAL\Connection; use Doctrine\DBAL\DBALException; @@ -19,6 +18,7 @@ use eZ\Publish\Core\Persistence\Legacy\Content\Gateway as ContentGateway; use eZ\Publish\Core\Persistence\Legacy\Content\Location\Gateway as LocationGateway; use eZ\Publish\Core\Persistence\Legacy\Filter\Gateway\Gateway; +use eZ\Publish\Core\Persistence\Legacy\Traits\Doctrine\LimitedCountQueryTrait; use eZ\Publish\SPI\Persistence\Filter\CriterionVisitor; use eZ\Publish\SPI\Persistence\Filter\Doctrine\FilteringQueryBuilder; use eZ\Publish\SPI\Persistence\Filter\SortClauseVisitor; @@ -94,7 +94,7 @@ public function count(FilteringCriterion $criterion, ?int $limit = null): int { $query = $this->buildQuery( [$this->getDatabasePlatform()->getCountExpression('DISTINCT content.id')], - $criterion + $criterion ); $query = $this->wrapCountQuery( diff --git a/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Location/Doctrine/DoctrineGateway.php b/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Location/Doctrine/DoctrineGateway.php index e08c15e827..b7fe4e3b3c 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Location/Doctrine/DoctrineGateway.php +++ b/eZ/Publish/Core/Persistence/Legacy/Filter/Gateway/Location/Doctrine/DoctrineGateway.php @@ -12,7 +12,6 @@ use Doctrine\DBAL\DBALException; use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\Platforms\AbstractPlatform; -use Exception; use eZ\Publish\Core\Base\Exceptions\DatabaseException; use eZ\Publish\Core\Persistence\Legacy\Content\Gateway as ContentGateway; use eZ\Publish\Core\Persistence\Legacy\Content\Location\Gateway as LocationGateway; diff --git a/eZ/Publish/Core/Persistence/Legacy/Traits/Doctrine/LimitedCountQueryTrait.php b/eZ/Publish/Core/Persistence/Legacy/Traits/Doctrine/LimitedCountQueryTrait.php index 1829fc071a..8caa3a260c 100644 --- a/eZ/Publish/Core/Persistence/Legacy/Traits/Doctrine/LimitedCountQueryTrait.php +++ b/eZ/Publish/Core/Persistence/Legacy/Traits/Doctrine/LimitedCountQueryTrait.php @@ -17,15 +17,16 @@ trait LimitedCountQueryTrait { /** - * Takes a QueryBuilder and wraps it in a count query. + * Takes a QueryBuilder and wraps it in a count query. * This performs the following transformation to the passed query * SELECT DISTINCT COUNT(DISTINCT someField) FROM XXX WHERE YYY; * To - * SELECT COUNT(*) FROM (SELECT DISTINCT someField FROM XXX WHERE YYY LIMIT N) AS csub; - * + * SELECT COUNT(*) FROM (SELECT DISTINCT someField FROM XXX WHERE YYY LIMIT N) AS csub;. + * * @param \Doctrine\DBAL\Query\QueryBuilder $queryBuilder * @param string $countableField * @param mixed $limit + * * @return \Doctrine\DBAL\Query\QueryBuilder */ protected function wrapCountQuery( @@ -35,7 +36,7 @@ protected function wrapCountQuery( ): QueryBuilder { $useLimit = $limit !== null && $limit > 0; - if(!$useLimit) { + if (!$useLimit) { return $queryBuilder; } @@ -44,6 +45,7 @@ protected function wrapCountQuery( ->getSQL(); $countQuery = $this->connection->createQueryBuilder(); + return $countQuery ->select( $queryBuilder->getConnection()->getDatabasePlatform()->getCountExpression('*') diff --git a/eZ/Publish/Core/Repository/LocationService.php b/eZ/Publish/Core/Repository/LocationService.php index 023fd8eb1b..2b9d4d4af9 100644 --- a/eZ/Publish/Core/Repository/LocationService.php +++ b/eZ/Publish/Core/Repository/LocationService.php @@ -372,11 +372,11 @@ public function loadParentLocationsForDraftContent(VersionInfo $versionInfo, ?ar /** * Returns the number of children which are readable by the current user of a Location object. */ - public function getLocationChildCount(APILocation $location, ?int $limit = null): int + public function getLocationChildCount(APILocation $location, ?int $limit = null): int { $filter = $this->buildLocationChildrenFilter($location); - return $this->count($filter,null, $limit); + return $this->count($filter, null, $limit); } public function getSubtreeSize(APILocation $location, ?int $limit = null): int