Skip to content

Commit

Permalink
IBX-4477: Added LocationService::getSubtreeSize method (#360)
Browse files Browse the repository at this point in the history
For more details see https://issues.ibexa.co/browse/IBX-4477 and ezsystems/ezplatform-kernel#360

* Added LocationService::getSubtreeSize API

* Added ContentType::isContainer getter method for magic $isContainer property

* Added Location::getPathString getter method for magic property

* [Tests] Added integration test coverage for getSubtreeSize

---------

Co-authored-by: Andrew Longosz <[email protected]>
  • Loading branch information
adamwojs and alongosz authored Feb 13, 2023
1 parent c2c83cb commit b787ccb
Show file tree
Hide file tree
Showing 14 changed files with 101 additions and 2 deletions.
7 changes: 7 additions & 0 deletions eZ/Publish/API/Repository/LocationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ public function loadParentLocationsForDraftContent(VersionInfo $versionInfo, ?ar
*/
public function getLocationChildCount(Location $location): int;

/**
* Return the subtree size of a given location.
*
* Warning! This method is not permission aware by design.
*/
public function getSubtreeSize(Location $location): int;

/**
* Creates the new $location in the content repository for the given content.
*
Expand Down
17 changes: 17 additions & 0 deletions eZ/Publish/API/Repository/Tests/LocationServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3471,6 +3471,23 @@ public function testMoveSubtreeKeepsContentHiddenOnChildren(): void
}
}

public function testGetSubtreeSize(): 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));

$this->createFolder(['eng-GB' => 'Child 1'], $location->id);
$this->createFolder(['eng-GB' => 'Child 2'], $location->id);

self::assertSame(3, $locationService->getSubtreeSize($location));

return $location;
}

/**
* Loads properties from all locations in the $location's subtree.
*
Expand Down
11 changes: 10 additions & 1 deletion eZ/Publish/API/Repository/Values/Content/Location.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* @property-read bool $explicitlyHidden Indicates that the Location entity has been explicitly marked as hidden.
* @property-read string $remoteId a global unique id of the content object
* @property-read int $parentLocationId the id of the parent location
* @property-read string $pathString the path to this location e.g. /1/2/4/23 where 23 is current id.
* @property-read string $pathString @deprecated use {@see Location::getPathString()} instead.
* @property-read array $path Same as $pathString but as array, e.g. [ 1, 2, 4, 23 ]
* @property-read int $depth Depth location has in the location tree
* @property-read int $sortField Specifies which property the child locations should be sorted on. Valid values are found at {@link Location::SORT_FIELD_*}
Expand Down Expand Up @@ -239,4 +239,13 @@ public function getSortClauses(): array

return [$sortClause];
}

/**
* The path to the Location represented by the current instance,
* e.g. /1/2/4/23 where 23 is current id.
*/
public function getPathString(): string
{
return $this->pathString;
}
}
7 changes: 6 additions & 1 deletion eZ/Publish/API/Repository/Values/ContentType/ContentType.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
* @property-read string $remoteId a global unique id of the content object
* @property-read string $urlAliasSchema URL alias schema. If nothing is provided, $nameSchema will be used instead.
* @property-read string $nameSchema The name schema.
* @property-read bool $isContainer This flag hints to UIs if type may have children or not.
* @property-read bool $isContainer @deprecated use strict getter {@see ContentType::isContainer} instead.
* @property-read string $mainLanguageCode the main language of the content type names and description used for fallback.
* @property-read bool $defaultAlwaysAvailable if an instance of a content type is created the always available flag is set by default this this value.
* @property-read string[] $languageCodes array of language codes used by content type translations.
Expand Down Expand Up @@ -228,4 +228,9 @@ public function getFirstFieldDefinitionOfType(string $fieldTypeIdentifier): ?Fie

return null;
}

public function isContainer(): bool
{
return $this->isContainer;
}
}
9 changes: 9 additions & 0 deletions eZ/Publish/Core/Persistence/Cache/LocationHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,15 @@ public function copySubtree($sourceId, $destinationParentId, $newOwnerId = null)
return $this->persistenceHandler->locationHandler()->copySubtree($sourceId, $destinationParentId, $newOwnerId);
}

public function getSubtreeSize(string $path): int
{
$this->logger->logCall(__METHOD__, [
'path' => $path,
]);

return $this->persistenceHandler->locationHandler()->getSubtreeSize($path);
}

/**
* {@inheritdoc}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ abstract public function loadParentLocationsDataForDraftContent(int $contentId):
*/
abstract public function getSubtreeContent(int $sourceId, bool $onlyIds = false): array;

abstract public function getSubtreeSize(string $path): int;

/**
* Returns data for the first level children of the location identified by given $locationId.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,21 @@ public function getSubtreeContent(int $sourceId, bool $onlyIds = false): array
: $results;
}

public function getSubtreeSize(string $path): int
{
$query = $this->createNodeQueryBuilder([$this->dbPlatform->getCountExpression('node_id')]);
$query->andWhere(
$query->expr()->like(
't.path_string',
$query->createPositionalParameter(
$path . '%',
)
)
);

return (int) $query->execute()->fetchOne();
}

/**
* Return constraint which limits the given $query to the subtree starting at $rootLocationId.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,15 @@ public function getSubtreeContent(int $sourceId, bool $onlyIds = false): array
}
}

public function getSubtreeSize(string $path): int
{
try {
return $this->innerGateway->getSubtreeSize($path);
} catch (DBALException | PDOException $e) {
throw DatabaseException::wrap($e);
}
}

public function getChildren(int $locationId): array
{
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,11 @@ public function copySubtree($sourceId, $destinationParentId, $newOwnerId = null)
return $copiedSubtreeRootLocation;
}

public function getSubtreeSize(string $path): int
{
return $this->locationGateway->getSubtreeSize($path);
}

/**
* Retrieves section ID of the location's content.
*
Expand Down
7 changes: 7 additions & 0 deletions eZ/Publish/Core/Repository/LocationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,13 @@ public function getLocationChildCount(APILocation $location): int
return $this->count($filter);
}

public function getSubtreeSize(APILocation $location): int
{
return $this->persistenceHandler->locationHandler()->getSubtreeSize(
$location->getPathString()
);
}

protected function buildLocationChildrenFilter(APILocation $location): Filter
{
$filter = new Filter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ public function getLocationChildCount(Location $location): int
return $this->service->getLocationChildCount($location);
}

public function getSubtreeSize(Location $location): int
{
return $this->service->getSubtreeSize($location);
}

public function createLocation(ContentInfo $contentInfo, LocationCreateStruct $locationCreateStruct): Location
{
return $this->service->createLocation($contentInfo, $locationCreateStruct);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public function providerForPassTroughMethods(): array

['getLocationChildCount', [$location], 100],

['getSubtreeSize', [$location], 100],

['createLocation', [$contentInfo, $locationCreateStruct], $location],

['updateLocation', [$location, $locationUpdateStruct], $location],
Expand Down
2 changes: 2 additions & 0 deletions eZ/Publish/SPI/Persistence/Content/Location/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ public function loadParentLocationsForDraftContent($contentId);
*/
public function copySubtree($sourceId, $destinationParentId);

public function getSubtreeSize(string $path): int;

/**
* Moves location identified by $sourceId into new parent identified by $destinationParentId.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ public function getLocationChildCount(Location $location): int
return $this->innerService->getLocationChildCount($location);
}

public function getSubtreeSize(Location $location): int
{
return $this->innerService->getSubtreeSize($location);
}

public function createLocation(
ContentInfo $contentInfo,
LocationCreateStruct $locationCreateStruct
Expand Down

0 comments on commit b787ccb

Please sign in to comment.