From 13bd157e4996552a607afd54ab6685bf13a4a602 Mon Sep 17 00:00:00 2001 From: Dawid Parafinski Date: Fri, 25 Oct 2024 12:01:12 +0200 Subject: [PATCH 1/5] IBX-8534: Added RelationListIteratorAdapter --- .../RelationListIteratorAdapter.php | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/contracts/Repository/Iterator/BatchIteratorAdapter/RelationListIteratorAdapter.php diff --git a/src/contracts/Repository/Iterator/BatchIteratorAdapter/RelationListIteratorAdapter.php b/src/contracts/Repository/Iterator/BatchIteratorAdapter/RelationListIteratorAdapter.php new file mode 100644 index 0000000000..38ee471fda --- /dev/null +++ b/src/contracts/Repository/Iterator/BatchIteratorAdapter/RelationListIteratorAdapter.php @@ -0,0 +1,42 @@ +contentService->loadRelationList( + $this->versionInfo, + $offset, + $limit, + $this->relationType + )->getIterator(); + + if ($iterator instanceof Iterator) { + return $iterator; + } + + return new IteratorIterator($iterator); + } +} From b9f0825dd8c7c1f21a9843fce6aa54ef4a719178 Mon Sep 17 00:00:00 2001 From: Dawid Parafinski Date: Fri, 25 Oct 2024 13:45:42 +0200 Subject: [PATCH 2/5] IBX-8534: Added relationList helper --- src/bundle/Core/Resources/config/helpers.yml | 4 ++ src/lib/Helper/RelationListHelper.php | 47 ++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/lib/Helper/RelationListHelper.php diff --git a/src/bundle/Core/Resources/config/helpers.yml b/src/bundle/Core/Resources/config/helpers.yml index 1ea501e559..9f7d8ce313 100644 --- a/src/bundle/Core/Resources/config/helpers.yml +++ b/src/bundle/Core/Resources/config/helpers.yml @@ -65,3 +65,7 @@ services: Ibexa\Bundle\Core\SiteAccess\Config\IOConfigResolver: arguments: $complexConfigProcessor: '@Ibexa\Bundle\Core\SiteAccess\Config\ComplexConfigProcessor' + + Ibexa\Core\Helper\RelationListHelper: + arguments: + $contentService: '@ibexa.api.service.content' diff --git a/src/lib/Helper/RelationListHelper.php b/src/lib/Helper/RelationListHelper.php new file mode 100644 index 0000000000..8bdb40045c --- /dev/null +++ b/src/lib/Helper/RelationListHelper.php @@ -0,0 +1,47 @@ +contentService, + $versionInfo + ) + ); + + $relations = []; + /** @var \Ibexa\Contracts\Core\Repository\Values\Content\RelationList\RelationListItemInterface $relationListItem */ + foreach ($relationListIterator as $relationListItem) { + if ($relationListItem->hasRelation()) { + /** @var \Ibexa\Core\Repository\Values\Content\Relation $relation */ + $relation = $relationListItem->getRelation(); + $relations[] = $relation; + } + } + + return $relations; + } +} From 634b9721095104e45006fafe37fafe0476c71408 Mon Sep 17 00:00:00 2001 From: Dawid Parafinski Date: Thu, 31 Oct 2024 12:18:32 +0100 Subject: [PATCH 3/5] Move from helper to Repository namespace + unit tests --- src/bundle/Core/Resources/config/helpers.yml | 4 - .../ContentService/RelationListFacade.php | 22 +++++ .../ContentService/RelationListFacade.php} | 16 ++- .../Resources/settings/repository/inner.yml | 6 ++ .../ContentService/RelationListFacadeTest.php | 98 +++++++++++++++++++ 5 files changed, 132 insertions(+), 14 deletions(-) create mode 100644 src/contracts/Repository/ContentService/RelationListFacade.php rename src/lib/{Helper/RelationListHelper.php => Repository/ContentService/RelationListFacade.php} (71%) create mode 100644 tests/lib/Repository/ContentService/RelationListFacadeTest.php diff --git a/src/bundle/Core/Resources/config/helpers.yml b/src/bundle/Core/Resources/config/helpers.yml index 9f7d8ce313..1ea501e559 100644 --- a/src/bundle/Core/Resources/config/helpers.yml +++ b/src/bundle/Core/Resources/config/helpers.yml @@ -65,7 +65,3 @@ services: Ibexa\Bundle\Core\SiteAccess\Config\IOConfigResolver: arguments: $complexConfigProcessor: '@Ibexa\Bundle\Core\SiteAccess\Config\ComplexConfigProcessor' - - Ibexa\Core\Helper\RelationListHelper: - arguments: - $contentService: '@ibexa.api.service.content' diff --git a/src/contracts/Repository/ContentService/RelationListFacade.php b/src/contracts/Repository/ContentService/RelationListFacade.php new file mode 100644 index 0000000000..16d8ebda16 --- /dev/null +++ b/src/contracts/Repository/ContentService/RelationListFacade.php @@ -0,0 +1,22 @@ +hasRelation()) { - /** @var \Ibexa\Core\Repository\Values\Content\Relation $relation */ - $relation = $relationListItem->getRelation(); - $relations[] = $relation; + /** @var \Ibexa\Contracts\Core\Repository\Values\Content\Relation $relation */ + yield $relationListItem->getRelation(); } } - - return $relations; } } diff --git a/src/lib/Resources/settings/repository/inner.yml b/src/lib/Resources/settings/repository/inner.yml index d5098b4811..7af5069fee 100644 --- a/src/lib/Resources/settings/repository/inner.yml +++ b/src/lib/Resources/settings/repository/inner.yml @@ -272,3 +272,9 @@ services: Ibexa\Core\Repository\Validator\TargetContentValidatorInterface: alias: Ibexa\Core\Repository\Validator\TargetContentValidator + + Ibexa\Contracts\Core\Repository\ContentService\RelationListFacade: '@Ibexa\Core\Repository\ContentService\RelationListFacade' + + Ibexa\Core\Repository\ContentService\RelationListFacade: + arguments: + $contentService: '@ibexa.api.service.content' diff --git a/tests/lib/Repository/ContentService/RelationListFacadeTest.php b/tests/lib/Repository/ContentService/RelationListFacadeTest.php new file mode 100644 index 0000000000..af8c7400e2 --- /dev/null +++ b/tests/lib/Repository/ContentService/RelationListFacadeTest.php @@ -0,0 +1,98 @@ +contentService = $this->createMock(ContentService::class); + $this->versionInfo = $this->createMock(VersionInfo::class); + $this->relationListFacade = new RelationListFacade($this->contentService); + } + + public function testGetRelationsReturnsEmptyIteratorWhenNoRelations(): void + { + $relationList = $this->createMock(RelationList::class); + $relationList->method('getIterator') + ->willReturn(new \ArrayIterator([])); + + $this->contentService->expects(self::once()) + ->method('loadRelationList') + ->with($this->versionInfo) + ->willReturn($relationList); + + $result = iterator_to_array($this->relationListFacade->getRelations($this->versionInfo)); + + self::assertEmpty($result); + } + + public function testGetRelationsIgnoresItemsWithoutRelations(): void + { + $relationListItem = $this->createMock(RelationListItemInterface::class); + $relationListItem + ->expects(self::any()) + ->method('hasRelation') + ->willReturn(false); + + $relationList = $this->createMock(RelationList::class); + $relationList->method('getIterator') + ->willReturn(new \ArrayIterator([$relationListItem])); + + $this->contentService->expects(self::once()) + ->method('loadRelationList') + ->with($this->versionInfo) + ->willReturn($relationList); + + $result = iterator_to_array($this->relationListFacade->getRelations($this->versionInfo)); + + self::assertEmpty($result); + } + + public function testGetRelationsYieldsRelationsWhenPresent(): void + { + $relation = $this->createMock(Relation::class); + + $relationListItem = $this->createMock(RelationListItemInterface::class); + $relationListItem->expects(self::any()) + ->method('hasRelation') + ->willReturn(true); + $relationListItem->expects(self::any()) + ->method('getRelation') + ->willReturn($relation); + + $relationList = $this->createMock(RelationList::class); + $relationList->method('getIterator') + ->willReturn(new \ArrayIterator([$relationListItem])); + + $this->contentService->expects(self::once()) + ->method('loadRelationList') + ->with($this->versionInfo) + ->willReturn($relationList); + + $result = iterator_to_array($this->relationListFacade->getRelations($this->versionInfo)); + + self::assertCount(1, $result); + self::assertSame($relation, $result[0]); + } +} From b16abf8d94c042f878fab8e42bfb85889ddf8bd9 Mon Sep 17 00:00:00 2001 From: Dawid Parafinski Date: Thu, 31 Oct 2024 12:42:17 +0100 Subject: [PATCH 4/5] Move from helper to Repository namespace + unit tests --- src/lib/Repository/ContentService/RelationListFacade.php | 3 ++- .../lib/Repository/ContentService/RelationListFacadeTest.php | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/lib/Repository/ContentService/RelationListFacade.php b/src/lib/Repository/ContentService/RelationListFacade.php index 61fead67be..445d3be824 100644 --- a/src/lib/Repository/ContentService/RelationListFacade.php +++ b/src/lib/Repository/ContentService/RelationListFacade.php @@ -36,7 +36,8 @@ public function getRelations(VersionInfo $versionInfo): iterable foreach ($relationListIterator as $relationListItem) { if ($relationListItem->hasRelation()) { /** @var \Ibexa\Contracts\Core\Repository\Values\Content\Relation $relation */ - yield $relationListItem->getRelation(); + $relation = $relationListItem->getRelation(); + yield $relation; } } } diff --git a/tests/lib/Repository/ContentService/RelationListFacadeTest.php b/tests/lib/Repository/ContentService/RelationListFacadeTest.php index af8c7400e2..edf8ddd5d5 100644 --- a/tests/lib/Repository/ContentService/RelationListFacadeTest.php +++ b/tests/lib/Repository/ContentService/RelationListFacadeTest.php @@ -14,15 +14,16 @@ use Ibexa\Contracts\Core\Repository\Values\Content\RelationList\RelationListItemInterface; use Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo; use Ibexa\Core\Repository\ContentService\RelationListFacade; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; final class RelationListFacadeTest extends TestCase { - private ContentService $contentService; + private ContentService&MockObject $contentService; private RelationListFacade $relationListFacade; - private VersionInfo $versionInfo; + private VersionInfo&MockObject $versionInfo; protected function setUp(): void { From 95a8a93c75db79b666f4bb1110f44d3149b6596c Mon Sep 17 00:00:00 2001 From: Dawid Parafinski Date: Mon, 4 Nov 2024 12:29:18 +0100 Subject: [PATCH 5/5] Included code review remakrs --- ...acade.php => RelationListFacadeInterface.php} | 4 ++-- .../RelationList/RelationListItemInterface.php | 2 +- .../ContentService/RelationListFacade.php | 9 ++------- src/lib/Resources/settings/repository/inner.yml | 2 +- .../ContentService/RelationListFacadeTest.php | 16 +++++++++------- 5 files changed, 15 insertions(+), 18 deletions(-) rename src/contracts/Repository/ContentService/{RelationListFacade.php => RelationListFacadeInterface.php} (78%) diff --git a/src/contracts/Repository/ContentService/RelationListFacade.php b/src/contracts/Repository/ContentService/RelationListFacadeInterface.php similarity index 78% rename from src/contracts/Repository/ContentService/RelationListFacade.php rename to src/contracts/Repository/ContentService/RelationListFacadeInterface.php index 16d8ebda16..dcd7e6ed7f 100644 --- a/src/contracts/Repository/ContentService/RelationListFacade.php +++ b/src/contracts/Repository/ContentService/RelationListFacadeInterface.php @@ -13,10 +13,10 @@ /** * @internal */ -interface RelationListFacade +interface RelationListFacadeInterface { /** - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Relation[] + * @return iterable<\Ibexa\Contracts\Core\Repository\Values\Content\Relation> */ public function getRelations(VersionInfo $versionInfo): iterable; } diff --git a/src/contracts/Repository/Values/Content/RelationList/RelationListItemInterface.php b/src/contracts/Repository/Values/Content/RelationList/RelationListItemInterface.php index 06499d694d..2900f1d2c6 100644 --- a/src/contracts/Repository/Values/Content/RelationList/RelationListItemInterface.php +++ b/src/contracts/Repository/Values/Content/RelationList/RelationListItemInterface.php @@ -18,7 +18,7 @@ interface RelationListItemInterface public function getRelation(): ?Relation; /** - * @return bool + * @phpstan-assert-if-true !null $this->getRelation() */ public function hasRelation(): bool; } diff --git a/src/lib/Repository/ContentService/RelationListFacade.php b/src/lib/Repository/ContentService/RelationListFacade.php index 445d3be824..c23a5241d0 100644 --- a/src/lib/Repository/ContentService/RelationListFacade.php +++ b/src/lib/Repository/ContentService/RelationListFacade.php @@ -13,16 +13,13 @@ use Ibexa\Contracts\Core\Repository\Iterator\BatchIteratorAdapter\RelationListIteratorAdapter; use Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo; -final class RelationListFacade implements ContentService\RelationListFacade +final class RelationListFacade implements ContentService\RelationListFacadeInterface { public function __construct( private readonly ContentService $contentService ) { } - /** - * @return \Ibexa\Contracts\Core\Repository\Values\Content\Relation[] - */ public function getRelations(VersionInfo $versionInfo): iterable { $relationListIterator = new BatchIterator( @@ -35,9 +32,7 @@ public function getRelations(VersionInfo $versionInfo): iterable /** @var \Ibexa\Contracts\Core\Repository\Values\Content\RelationList\RelationListItemInterface $relationListItem */ foreach ($relationListIterator as $relationListItem) { if ($relationListItem->hasRelation()) { - /** @var \Ibexa\Contracts\Core\Repository\Values\Content\Relation $relation */ - $relation = $relationListItem->getRelation(); - yield $relation; + yield $relationListItem->getRelation(); } } } diff --git a/src/lib/Resources/settings/repository/inner.yml b/src/lib/Resources/settings/repository/inner.yml index 7af5069fee..006910c116 100644 --- a/src/lib/Resources/settings/repository/inner.yml +++ b/src/lib/Resources/settings/repository/inner.yml @@ -273,7 +273,7 @@ services: Ibexa\Core\Repository\Validator\TargetContentValidatorInterface: alias: Ibexa\Core\Repository\Validator\TargetContentValidator - Ibexa\Contracts\Core\Repository\ContentService\RelationListFacade: '@Ibexa\Core\Repository\ContentService\RelationListFacade' + Ibexa\Contracts\Core\Repository\ContentService\RelationListFacadeInterface: '@Ibexa\Core\Repository\ContentService\RelationListFacade' Ibexa\Core\Repository\ContentService\RelationListFacade: arguments: diff --git a/tests/lib/Repository/ContentService/RelationListFacadeTest.php b/tests/lib/Repository/ContentService/RelationListFacadeTest.php index edf8ddd5d5..79a6477ee6 100644 --- a/tests/lib/Repository/ContentService/RelationListFacadeTest.php +++ b/tests/lib/Repository/ContentService/RelationListFacadeTest.php @@ -38,7 +38,8 @@ public function testGetRelationsReturnsEmptyIteratorWhenNoRelations(): void $relationList->method('getIterator') ->willReturn(new \ArrayIterator([])); - $this->contentService->expects(self::once()) + $this->contentService + ->expects(self::once()) ->method('loadRelationList') ->with($this->versionInfo) ->willReturn($relationList); @@ -52,7 +53,6 @@ public function testGetRelationsIgnoresItemsWithoutRelations(): void { $relationListItem = $this->createMock(RelationListItemInterface::class); $relationListItem - ->expects(self::any()) ->method('hasRelation') ->willReturn(false); @@ -60,9 +60,10 @@ public function testGetRelationsIgnoresItemsWithoutRelations(): void $relationList->method('getIterator') ->willReturn(new \ArrayIterator([$relationListItem])); - $this->contentService->expects(self::once()) + $this->contentService + ->expects(self::once()) ->method('loadRelationList') - ->with($this->versionInfo) + ->with(self::identicalTo($this->versionInfo)) ->willReturn($relationList); $result = iterator_to_array($this->relationListFacade->getRelations($this->versionInfo)); @@ -75,10 +76,10 @@ public function testGetRelationsYieldsRelationsWhenPresent(): void $relation = $this->createMock(Relation::class); $relationListItem = $this->createMock(RelationListItemInterface::class); - $relationListItem->expects(self::any()) + $relationListItem ->method('hasRelation') ->willReturn(true); - $relationListItem->expects(self::any()) + $relationListItem ->method('getRelation') ->willReturn($relation); @@ -86,7 +87,8 @@ public function testGetRelationsYieldsRelationsWhenPresent(): void $relationList->method('getIterator') ->willReturn(new \ArrayIterator([$relationListItem])); - $this->contentService->expects(self::once()) + $this->contentService + ->expects(self::once()) ->method('loadRelationList') ->with($this->versionInfo) ->willReturn($relationList);