diff --git a/Content/ContentTypeResolver/TeaserSelectionResolver.php b/Content/ContentTypeResolver/TeaserSelectionResolver.php
new file mode 100644
index 0000000..6c57d73
--- /dev/null
+++ b/Content/ContentTypeResolver/TeaserSelectionResolver.php
@@ -0,0 +1,70 @@
+teaserManager = $teaserManager;
+ $this->teaserSerializer = $teaserSerializer;
+ }
+
+ public function resolve($data, PropertyInterface $property, string $locale, array $attributes = []): ContentView
+ {
+ $value = array_merge(
+ [
+ 'presentAs' => null,
+ 'items' => [],
+ ],
+ \is_array($data) ? $data : []
+ );
+ $items = $value['items'] ?? [];
+
+ if (!\is_array($items) || 0 === \count($items)) {
+ return new ContentView([], $value);
+ }
+
+ $teasers = $this->teaserManager->find($items, $locale);
+ $teasers = array_map(
+ function (Teaser $teaser) use ($locale) {
+ return $this->teaserSerializer->serialize($teaser, $locale);
+ },
+ $teasers
+ );
+
+ return new ContentView($teasers, $value);
+ }
+}
diff --git a/Content/Serializer/TeaserSerializer.php b/Content/Serializer/TeaserSerializer.php
new file mode 100644
index 0000000..c518a70
--- /dev/null
+++ b/Content/Serializer/TeaserSerializer.php
@@ -0,0 +1,103 @@
+arraySerializer = $arraySerializer;
+ $this->mediaSerializer = $mediaSerializer;
+ $this->mediaManager = $mediaManager;
+ $this->referenceStorePool = $referenceStorePool;
+ }
+
+ /**
+ * @return mixed[]
+ */
+ public function serialize(Teaser $teaser, string $locale, ?SerializationContext $context = null): array
+ {
+ $teaserData = $this->arraySerializer->serialize($teaser, $context);
+ unset($teaserData['mediaId']);
+
+ $mediaId = $teaser->getMediaId();
+ $mediaData = null;
+ if ($mediaId) {
+ $media = $this->mediaManager->getEntityById($mediaId);
+ $mediaData = $this->mediaSerializer->serialize($media, $locale);
+ }
+
+ $teaserData['media'] = $mediaData;
+
+ $this->addToReferenceStore($teaser->getId(), $teaser->getType());
+
+ return $teaserData;
+ }
+
+ /**
+ * @param int|string $id
+ */
+ private function addToReferenceStore($id, string $alias): void
+ {
+ if ('pages' === $alias) {
+ // unfortunately the reference store for pages was not adjusted and still uses content as alias
+ $alias = 'content';
+ }
+
+ if ('articles' === $alias) {
+ $alias = 'article';
+ }
+
+ try {
+ $referenceStore = $this->referenceStorePool->getStore($alias);
+ } catch (ReferenceStoreNotExistsException $e) {
+ // @ignoreException do nothing when reference store was not found
+
+ return;
+ }
+
+ $referenceStore->add($id);
+ }
+}
diff --git a/Content/Serializer/TeaserSerializerInterface.php b/Content/Serializer/TeaserSerializerInterface.php
new file mode 100644
index 0000000..a382a70
--- /dev/null
+++ b/Content/Serializer/TeaserSerializerInterface.php
@@ -0,0 +1,25 @@
+
+
hello world.
', + 'moreText' => 'foo', + 'url' => '/my-page', + 'attributes' => [ + 'structureType' => 'default', + 'webspaceKey' => 'example', + ], + 'media' => [ + 'id' => 1, + 'formatUri' => '/media/1/{format}/media-1.jpg?=v1-0', + ], + ]); + + $this->teaserSerializer->serialize($articleTeaser->reveal(), $locale)->willReturn([ + 'id' => '5524447a-1afd-4d08-bb25-d34f46e3621c', + 'type' => 'articles', + 'locale' => 'en', + 'title' => 'My article', + 'description' => 'hello world.
', + 'moreText' => 'foo', + 'url' => '/my-article', + 'attributes' => [ + 'structureType' => 'default', + 'webspaceKey' => 'example', + ], + 'media' => null, + ]); + + $this->teaserSerializer->serialize($otherTeaser->reveal(), $locale)->willReturn([ + 'id' => 'bb03b2f1-135f-4fcf-b27a-b2cf5f36be66', + 'type' => 'other', + 'locale' => 'en', + 'title' => 'My thing', + 'description' => 'hello world.
', + 'moreText' => 'foo', + 'url' => '/my-thing', + 'media' => null, + ]); + + $result = $this->teaserSelectionResolver->resolve($value, $property->reveal(), $locale); + + self::assertSame([ + [ + 'id' => '74a36ca1-4805-48a0-b37d-3ffb3a6be9b1', + 'type' => 'pages', + 'locale' => 'en', + 'title' => 'My page', + 'description' => 'hello world.
', + 'moreText' => 'foo', + 'url' => '/my-page', + 'attributes' => [ + 'structureType' => 'default', + 'webspaceKey' => 'example', + ], + 'media' => [ + 'id' => 1, + 'formatUri' => '/media/1/{format}/media-1.jpg?=v1-0', + ], + ], + [ + 'id' => '5524447a-1afd-4d08-bb25-d34f46e3621c', + 'type' => 'articles', + 'locale' => 'en', + 'title' => 'My article', + 'description' => 'hello world.
', + 'moreText' => 'foo', + 'url' => '/my-article', + 'attributes' => [ + 'structureType' => 'default', + 'webspaceKey' => 'example', + ], + 'media' => null, + ], + [ + 'id' => 'bb03b2f1-135f-4fcf-b27a-b2cf5f36be66', + 'type' => 'other', + 'locale' => 'en', + 'title' => 'My thing', + 'description' => 'hello world.
', + 'moreText' => 'foo', + 'url' => '/my-thing', + 'media' => null, + ], + ], $result->getContent()); + self::assertSame($value, $result->getView()); + } + + public function testResolveNullValue(): void + { + $locale = 'en'; + $value = null; + + /** @var PropertyInterface|ObjectProphecy $property */ + $property = $this->prophesize(PropertyInterface::class); + + $this->teaserManager->find(Argument::any())->shouldNotBeCalled(); + $this->teaserSerializer->serialize(Argument::any())->shouldNotBeCalled(); + + $result = $this->teaserSelectionResolver->resolve($value, $property->reveal(), $locale); + + self::assertSame([], $result->getContent()); + self::assertSame([ + 'presentAs' => null, + 'items' => [], + ], $result->getView()); + } +} diff --git a/Tests/Unit/Content/Serializer/TeaserSerializerTest.php b/Tests/Unit/Content/Serializer/TeaserSerializerTest.php new file mode 100644 index 0000000..7e33208 --- /dev/null +++ b/Tests/Unit/Content/Serializer/TeaserSerializerTest.php @@ -0,0 +1,216 @@ +arraySerializer = $this->prophesize(ArraySerializerInterface::class); + $this->mediaSerializer = $this->prophesize(MediaSerializerInterface::class); + $this->mediaManager = $this->prophesize(MediaManagerInterface::class); + $this->referenceStorePool = $this->prophesize(ReferenceStorePoolInterface::class); + + $this->teaserSerializer = new TeaserSerializer( + $this->arraySerializer->reveal(), + $this->mediaSerializer->reveal(), + $this->mediaManager->reveal(), + $this->referenceStorePool->reveal() + ); + } + + public function testSerialize(): void + { + $locale = 'en'; + + $teaser = $this->prophesize(Teaser::class); + $teaser->getId()->willReturn('74a36ca1-4805-48a0-b37d-3ffb3a6be9b1'); + $teaser->getType()->willReturn('pages'); + $teaser->getMediaId()->willReturn(1); + + $media = $this->prophesize(MediaInterface::class); + $this->mediaManager->getEntityById(1)->willReturn($media->reveal()); + + $this->arraySerializer->serialize($teaser, null)->willReturn([ + 'id' => '74a36ca1-4805-48a0-b37d-3ffb3a6be9b1', + 'type' => 'pages', + 'locale' => 'en', + 'title' => 'My page', + 'description' => 'hello world.
', + 'moreText' => 'foo', + 'mediaId' => 1, + 'url' => '/my-page', + 'attributes' => [ + 'structureType' => 'default', + 'webspaceKey' => 'example', + ], + ]); + + $this->mediaSerializer->serialize($media, $locale)->willReturn([ + 'id' => 1, + 'formatUri' => '/media/1/{format}/media-1.jpg?=v1-0', + ]); + + $referenceStore = $this->prophesize(ReferenceStoreInterface::class); + $this->referenceStorePool->getStore('content')->willReturn($referenceStore->reveal()); + $referenceStore->add('74a36ca1-4805-48a0-b37d-3ffb3a6be9b1')->shouldBeCalled(); + + $result = $this->teaserSerializer->serialize($teaser->reveal(), $locale); + + $this->assertSame([ + 'id' => '74a36ca1-4805-48a0-b37d-3ffb3a6be9b1', + 'type' => 'pages', + 'locale' => 'en', + 'title' => 'My page', + 'description' => 'hello world.
', + 'moreText' => 'foo', + 'url' => '/my-page', + 'attributes' => [ + 'structureType' => 'default', + 'webspaceKey' => 'example', + ], + 'media' => [ + 'id' => 1, + 'formatUri' => '/media/1/{format}/media-1.jpg?=v1-0', + ], + ], $result); + } + + public function testSerializeArticleTeaserWithoutMedia(): void + { + $locale = 'en'; + + $teaser = $this->prophesize(Teaser::class); + $teaser->getId()->willReturn('5524447a-1afd-4d08-bb25-d34f46e3621c'); + $teaser->getType()->willReturn('articles'); + $teaser->getMediaId()->willReturn(null); + + $this->mediaManager->getEntityById(Argument::any())->shouldNotBeCalled(); + + $this->arraySerializer->serialize($teaser, null)->willReturn([ + 'id' => '5524447a-1afd-4d08-bb25-d34f46e3621c', + 'type' => 'articles', + 'locale' => 'en', + 'title' => 'My article', + 'description' => 'hello world.
', + 'moreText' => 'foo', + 'mediaId' => null, + 'url' => '/my-article', + 'attributes' => [ + 'structureType' => 'default', + 'webspaceKey' => 'example', + ], + ]); + + $this->mediaSerializer->serialize(Argument::any())->shouldNotBeCalled(); + + $referenceStore = $this->prophesize(ReferenceStoreInterface::class); + $this->referenceStorePool->getStore('article')->willReturn($referenceStore->reveal()); + $referenceStore->add('5524447a-1afd-4d08-bb25-d34f46e3621c')->shouldBeCalled(); + + $result = $this->teaserSerializer->serialize($teaser->reveal(), $locale); + + $this->assertSame([ + 'id' => '5524447a-1afd-4d08-bb25-d34f46e3621c', + 'type' => 'articles', + 'locale' => 'en', + 'title' => 'My article', + 'description' => 'hello world.
', + 'moreText' => 'foo', + 'url' => '/my-article', + 'attributes' => [ + 'structureType' => 'default', + 'webspaceKey' => 'example', + ], + 'media' => null, + ], $result); + } + + public function testSerializeOtherTeaserWithContext(): void + { + $locale = 'en'; + $context = $this->prophesize(SerializationContext::class); + + $teaser = $this->prophesize(Teaser::class); + $teaser->getId()->willReturn('bb03b2f1-135f-4fcf-b27a-b2cf5f36be66'); + $teaser->getType()->willReturn('other'); + $teaser->getMediaId()->willReturn(null); + + $this->arraySerializer->serialize($teaser, $context)->willReturn([ + 'id' => 'bb03b2f1-135f-4fcf-b27a-b2cf5f36be66', + 'type' => 'other', + 'locale' => 'en', + 'title' => 'My thing', + 'description' => 'hello world.
', + 'moreText' => 'foo', + 'mediaId' => null, + 'url' => '/my-thing', + ]); + + $this->referenceStorePool->getStore('other')->willThrow(ReferenceStoreNotExistsException::class); + + $result = $this->teaserSerializer->serialize($teaser->reveal(), $locale, $context->reveal()); + + $this->assertSame([ + 'id' => 'bb03b2f1-135f-4fcf-b27a-b2cf5f36be66', + 'type' => 'other', + 'locale' => 'en', + 'title' => 'My thing', + 'description' => 'hello world.
', + 'moreText' => 'foo', + 'url' => '/my-thing', + 'media' => null, + ], $result); + } +}