diff --git a/Content/ContentTypeResolver/LinkResolver.php b/Content/ContentTypeResolver/LinkResolver.php new file mode 100644 index 0000000..af3f005 --- /dev/null +++ b/Content/ContentTypeResolver/LinkResolver.php @@ -0,0 +1,106 @@ +linkProviderPool = $linkProviderPool; + } + + public function resolve($data, PropertyInterface $property, string $locale, array $attributes = []): ContentView + { + $content = $this->getContentData($property); + $view = $this->getViewData($property); + + return new ContentView($content, $view); + } + + /** + * @return array{ + * provider?: string, + * locale?: string, + * target?: string, + * title?: string + * } + */ + private function getViewData(PropertyInterface $property): array + { + $value = $property->getValue(); + + if (!$value) { + return []; + } + + $result = [ + 'provider' => $value['provider'], + 'locale' => $value['locale'], + ]; + + if (isset($value['target'])) { + $result['target'] = $value['target']; + } + + if (isset($value['title'])) { + $result['title'] = $value['title']; + } + + return $result; + } + + private function getContentData(PropertyInterface $property): ?string + { + $value = $property->getValue(); + + if (!$value || !isset($value['provider'])) { + return null; + } + + if (Link::LINK_TYPE_EXTERNAL === $value['provider']) { + return $value['href']; + } + + $provider = $this->linkProviderPool->getProvider($value['provider']); + + $linkItems = $provider->preload([$value['href']], $value['locale']); + + if (0 === \count($linkItems)) { + return null; + } + + $url = reset($linkItems)->getUrl(); + if (isset($value['anchor'])) { + $url = sprintf('%s#%s', $url, $value['anchor']); + } + + return $url; + } +} diff --git a/Resources/config/content-type-resolvers.xml b/Resources/config/content-type-resolvers.xml index 79dd76b..f321d03 100644 --- a/Resources/config/content-type-resolvers.xml +++ b/Resources/config/content-type-resolvers.xml @@ -180,6 +180,16 @@ + + + + + + */ - protected function getKernelParameters() + protected function getKernelParameters(): array { $parameters = parent::getKernelParameters(); diff --git a/Tests/Unit/Content/ContentTypeResolver/LinkResolverTest.php b/Tests/Unit/Content/ContentTypeResolver/LinkResolverTest.php new file mode 100644 index 0000000..c70ff13 --- /dev/null +++ b/Tests/Unit/Content/ContentTypeResolver/LinkResolverTest.php @@ -0,0 +1,116 @@ +prophesize(LinkProviderPoolInterface::class); + $linkResolver = new LinkResolver($linkProviderPool->reveal()); + + self::assertSame('link', $linkResolver::getContentType()); + } + + public function testResolve(): void + { + $providerPool = $this->prophesize(LinkProviderPoolInterface::class); + $provider = $this->prophesize(LinkProviderInterface::class); + $linkResolver = new LinkResolver($providerPool->reveal()); + + $property = $this->prophesize(PropertyInterface::class); + $property->getValue() + ->shouldBeCalled() + ->willReturn([ + 'provider' => 'page', + 'target' => '_self', + 'anchor' => 'link', + 'href' => '76fcf58e-0624-4cf0-85a5-170de9f14252', + 'title' => 'Internal Link', + 'locale' => 'en', + ]); + + $providerPool->getProvider(Argument::type('string')) + ->shouldBeCalled() + ->willReturn($provider->reveal()); + + $linkItem = new LinkItem( + '76fcf58e-0624-4cf0-85a5-170de9f14252', + 'Internal Link', + 'https://example.lo/link', + true + ); + + $provider->preload(['76fcf58e-0624-4cf0-85a5-170de9f14252'], 'en') + ->shouldBeCalled() + ->willReturn([$linkItem]); + + $result = $linkResolver->resolve([], $property->reveal(), 'en'); + + $this->assertSame('https://example.lo/link#link', $result->getContent()); + $this->assertSame([ + 'provider' => 'page', + 'locale' => 'en', + 'target' => '_self', + 'title' => 'Internal Link', + ], $result->getView()); + } + + public function testResolveMinimal(): void + { + $providerPool = $this->prophesize(LinkProviderPoolInterface::class); + $provider = $this->prophesize(LinkProviderInterface::class); + $linkResolver = new LinkResolver($providerPool->reveal()); + + $property = $this->prophesize(PropertyInterface::class); + $property->getValue() + ->shouldBeCalled() + ->willReturn([ + 'provider' => 'page', + 'href' => '76fcf58e-0624-4cf0-85a5-170de9f14252', + 'locale' => 'en', + ]); + + $providerPool->getProvider(Argument::type('string')) + ->shouldBeCalled() + ->willReturn($provider->reveal()); + + $linkItem = new LinkItem( + '76fcf58e-0624-4cf0-85a5-170de9f14252', + 'Internal Link', + 'https://example.lo/link', + true + ); + + $provider->preload(['76fcf58e-0624-4cf0-85a5-170de9f14252'], 'en') + ->shouldBeCalled() + ->willReturn([$linkItem]); + + $result = $linkResolver->resolve([], $property->reveal(), 'en'); + + $this->assertSame('https://example.lo/link', $result->getContent()); + $this->assertSame([ + 'provider' => 'page', + 'locale' => 'en', + ], $result->getView()); + } +} diff --git a/composer.json b/composer.json index 8d7b6e9..503cb7a 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "description": "Bundle that provides controllers and services for using Sulu as headless content management system", "require": { "php": "^7.3 || ^8.0", - "sulu/sulu": "^2.2 || ^2.3@dev", + "sulu/sulu": "^2.4", "symfony/config": "^4.4 || ^5.0", "symfony/dependency-injection": "^4.4 || ^5.0", "symfony/framework-bundle": "^4.4 || ^5.0",