From 333ff172d53ffc3591ca85e149c07d765c852648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edi=20Modri=C4=87?= Date: Thu, 12 Dec 2024 13:32:56 +0100 Subject: [PATCH] Add methods to access reverse relations on content --- lib/API/RelationService.php | 28 ++++++++ lib/API/Values/Content.php | 88 ++++++++++++++++++++++++ lib/Core/Site/RelationService.php | 58 ++++++++++++++++ lib/Core/Site/Values/Content.php | 108 ++++++++++++++++++++++++++++++ 4 files changed, 282 insertions(+) diff --git a/lib/API/RelationService.php b/lib/API/RelationService.php index 3a369511..166310cd 100644 --- a/lib/API/RelationService.php +++ b/lib/API/RelationService.php @@ -61,4 +61,32 @@ public function loadFieldRelationLocations( array $contentTypeIdentifiers = [], ?int $limit = null, ): array; + + /** + * Load all reverse related Content from $fieldDefinitionIdentifier field to the given + * $content, optionally limited by a list of $contentTypeIdentifiers and $limit. + * + * @return \Netgen\IbexaSiteApi\API\Values\Content[] + */ + public function loadReverseRelations( + Content $content, + string $fieldDefinitionIdentifier, + array $contentTypeIdentifiers = [], + ?int $limit = null, + ): array; + + /** + * Load all reverse related Locations from $fieldDefinitionIdentifier field to the given + * $content, optionally limited by a list of $contentTypeIdentifiers and $limit. + * + * Note: only visible main Locations of the reverse related Content will be used. + * + * @return \Netgen\IbexaSiteApi\API\Values\Location[] + */ + public function loadReverseRelationLocations( + Content $content, + string $fieldDefinitionIdentifier, + array $contentTypeIdentifiers = [], + ?int $limit = null, + ): array; } diff --git a/lib/API/Values/Content.php b/lib/API/Values/Content.php index 193d8f52..b588887c 100644 --- a/lib/API/Values/Content.php +++ b/lib/API/Values/Content.php @@ -196,6 +196,94 @@ abstract public function filterSudoFieldRelationLocations( int $currentPage = 1, ): Pagerfanta; + /** + * Return all reverse related Content from $fieldDefinitionIdentifier. + * + * @return \Netgen\IbexaSiteApi\API\Values\Content[] + */ + abstract public function getReverseRelations(string $fieldDefinitionIdentifier, int $limit = 25): array; + + /** + * Return all reverse related Content from $fieldDefinitionIdentifier using repository sudo. + * + * @return \Netgen\IbexaSiteApi\API\Values\Content[] + */ + abstract public function getSudoReverseRelations(string $fieldDefinitionIdentifier, int $limit = 25): array; + + /** + * Return reverse related Content from $fieldDefinitionIdentifier field, + * optionally limited by a list of $contentTypeIdentifiers. + * + * @param string[] $contentTypeIdentifiers + * + * @return \Pagerfanta\Pagerfanta Pagerfanta instance iterating over Site API Content items + */ + abstract public function filterReverseRelations( + string $fieldDefinitionIdentifier, + array $contentTypeIdentifiers = [], + int $maxPerPage = 25, + int $currentPage = 1, + ): Pagerfanta; + + /** + * Return reverse related Content from $fieldDefinitionIdentifier field using repository sudo, + * optionally limited by a list of $contentTypeIdentifiers. + * + * @param string[] $contentTypeIdentifiers + * + * @return \Pagerfanta\Pagerfanta Pagerfanta instance iterating over Site API Content items + */ + abstract public function filterSudoReverseRelations( + string $fieldDefinitionIdentifier, + array $contentTypeIdentifiers = [], + int $maxPerPage = 25, + int $currentPage = 1, + ): Pagerfanta; + + /** + * Return all reverse related Locations from $fieldDefinitionIdentifier. + * + * @return \Netgen\IbexaSiteApi\API\Values\Location[] + */ + abstract public function getReverseRelationLocations(string $fieldDefinitionIdentifier, int $limit = 25): array; + + /** + * Return all reverse related Locations from $fieldDefinitionIdentifier using repository sudo. + * + * @return \Netgen\IbexaSiteApi\API\Values\Location[] + */ + abstract public function getSudoReverseRelationLocations(string $fieldDefinitionIdentifier, int $limit = 25): array; + + /** + * Return reverse related Locations from $fieldDefinitionIdentifier field, + * optionally limited by a list of $contentTypeIdentifiers. + * + * @param string[] $contentTypeIdentifiers + * + * @return \Pagerfanta\Pagerfanta Pagerfanta instance iterating over Site API Locations + */ + abstract public function filterReverseRelationLocations( + string $fieldDefinitionIdentifier, + array $contentTypeIdentifiers = [], + int $maxPerPage = 25, + int $currentPage = 1, + ): Pagerfanta; + + /** + * Return reverse related Locations from $fieldDefinitionIdentifier field using repository sudo, + * optionally limited by a list of $contentTypeIdentifiers. + * + * @param string[] $contentTypeIdentifiers + * + * @return \Pagerfanta\Pagerfanta Pagerfanta instance iterating over Site API Locations + */ + abstract public function filterSudoReverseRelationLocations( + string $fieldDefinitionIdentifier, + array $contentTypeIdentifiers = [], + int $maxPerPage = 25, + int $currentPage = 1, + ): Pagerfanta; + /** * Return absolute path for the Content. * diff --git a/lib/Core/Site/RelationService.php b/lib/Core/Site/RelationService.php index 006fed5d..cdab0a7a 100644 --- a/lib/Core/Site/RelationService.php +++ b/lib/Core/Site/RelationService.php @@ -5,6 +5,9 @@ namespace Netgen\IbexaSiteApi\Core\Site; use Exception; +use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; +use Ibexa\Contracts\Core\Repository\Values\Content\Query; +use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; use Netgen\IbexaSiteApi\API\RelationService as RelationServiceInterface; use Netgen\IbexaSiteApi\API\Site as SiteInterface; use Netgen\IbexaSiteApi\API\Values\Content; @@ -139,6 +142,61 @@ public function loadFieldRelationLocations( return $locations; } + public function loadReverseRelations( + Content $content, + string $fieldDefinitionIdentifier, + array $contentTypeIdentifiers = [], + ?int $limit = null, + ): array { + $query = new Query(); + + $criteria = [ + new Criterion\FieldRelation($fieldDefinitionIdentifier, Criterion\Operator::CONTAINS, [$content->id]) + ]; + + if (count($contentTypeIdentifiers) > 0) { + $criteria[] = new Criterion\ContentTypeIdentifier($contentTypeIdentifiers); + } + + $query->filter = new Criterion\LogicalAnd($criteria); + + if ($limit !== null && $limit > 0) { + $query->limit = $limit; + } + + $result = $this->site->getFindService()->findContent($query); + + return $this->extractContentItems($result); + } + + public function loadReverseRelationLocations( + Content $content, + string $fieldDefinitionIdentifier, + array $contentTypeIdentifiers = [], + ?int $limit = null, + ): array { + $query = new LocationQuery(); + + $criteria = [ + new Criterion\FieldRelation($fieldDefinitionIdentifier, Criterion\Operator::CONTAINS, [$content->id]), + new Criterion\Location\IsMainLocation(Criterion\Location\IsMainLocation::MAIN), + ]; + + if (count($contentTypeIdentifiers) > 0) { + $criteria[] = new Criterion\ContentTypeIdentifier($contentTypeIdentifiers); + } + + $query->filter = new Criterion\LogicalAnd($criteria); + + if ($limit !== null && $limit > 0) { + $query->limit = $limit; + } + + $result = $this->site->getFindService()->findLocations($query); + + return $this->extractLocations($result); + } + /** * Return an array of related Content items. * diff --git a/lib/Core/Site/Values/Content.php b/lib/Core/Site/Values/Content.php index 1fd3ba85..ab39085c 100644 --- a/lib/Core/Site/Values/Content.php +++ b/lib/Core/Site/Values/Content.php @@ -351,6 +351,114 @@ public function filterSudoFieldRelationLocations( ); } + public function getReverseRelations(string $fieldDefinitionIdentifier, int $limit = 25): array + { + return $this->site->getRelationService()->loadReverseRelations( + $this, + $fieldDefinitionIdentifier, + [], + $limit, + ); + } + + public function getSudoReverseRelations(string $fieldDefinitionIdentifier, int $limit = 25): array + { + return $this->repository->sudo( + fn () => $this->getReverseRelations($fieldDefinitionIdentifier, $limit), + ); + } + + public function filterReverseRelations( + string $fieldDefinitionIdentifier, + array $contentTypeIdentifiers = [], + int $maxPerPage = 25, + int $currentPage = 1, + ): Pagerfanta { + $relations = $this->site->getRelationService()->loadReverseRelations( + $this, + $fieldDefinitionIdentifier, + $contentTypeIdentifiers, + ); + + $pager = new Pagerfanta(new ArrayAdapter($relations)); + + $pager->setNormalizeOutOfRangePages(true); + $pager->setMaxPerPage($maxPerPage); + $pager->setCurrentPage($currentPage); + + return $pager; + } + + public function filterSudoReverseRelations( + string $fieldDefinitionIdentifier, + array $contentTypeIdentifiers = [], + int $maxPerPage = 25, + int $currentPage = 1, + ): Pagerfanta { + return $this->repository->sudo( + fn () => $this->filterReverseRelations( + $fieldDefinitionIdentifier, + $contentTypeIdentifiers, + $maxPerPage, + $currentPage + ), + ); + } + + public function getReverseRelationLocations(string $fieldDefinitionIdentifier, int $limit = 25): array + { + return $this->site->getRelationService()->loadReverseRelationLocations( + $this, + $fieldDefinitionIdentifier, + [], + $limit, + ); + } + + public function getSudoReverseRelationLocations(string $fieldDefinitionIdentifier, int $limit = 25): array + { + return $this->repository->sudo( + fn () => $this->getReverseRelationLocations($fieldDefinitionIdentifier, $limit), + ); + } + + public function filterReverseRelationLocations( + string $fieldDefinitionIdentifier, + array $contentTypeIdentifiers = [], + int $maxPerPage = 25, + int $currentPage = 1, + ): Pagerfanta { + $relations = $this->site->getRelationService()->loadReverseRelationLocations( + $this, + $fieldDefinitionIdentifier, + $contentTypeIdentifiers, + ); + + $pager = new Pagerfanta(new ArrayAdapter($relations)); + + $pager->setNormalizeOutOfRangePages(true); + $pager->setMaxPerPage($maxPerPage); + $pager->setCurrentPage($currentPage); + + return $pager; + } + + public function filterSudoReverseRelationLocations( + string $fieldDefinitionIdentifier, + array $contentTypeIdentifiers = [], + int $maxPerPage = 25, + int $currentPage = 1, + ): Pagerfanta { + return $this->repository->sudo( + fn () => $this->filterReverseRelationLocations( + $fieldDefinitionIdentifier, + $contentTypeIdentifiers, + $maxPerPage, + $currentPage + ), + ); + } + public function getPath(array $parameters = []): string { return $this->internalGetPath()->getAbsolute($parameters);