Skip to content

Commit

Permalink
Merge pull request #2 from Prokyonn/enhancement/teaser-property-provider
Browse files Browse the repository at this point in the history
Add TeaserSelectionpropertyResolver
  • Loading branch information
Prokyonn authored Nov 12, 2024
2 parents db9b1a1 + 5bf0ca6 commit c1c6451
Show file tree
Hide file tree
Showing 15 changed files with 315 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace Sulu\Bundle\ContentBundle\Content\Application\PropertyResolver;

use Sulu\Bundle\ContentBundle\Content\Application\PropertyResolver\Resolver\PropertyResolverInterface;

class PropertyResolverProvider
{
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
use Sulu\Bundle\AdminBundle\Metadata\FormMetadata\FormMetadata;
use Sulu\Bundle\ContentBundle\Content\Application\ContentResolver\Value\ContentView;
use Sulu\Bundle\ContentBundle\Content\Application\MetadataResolver\MetadataResolver;
use Sulu\Bundle\ContentBundle\Content\Application\PropertyResolver\PropertyResolverInterface;

class BlockPropertyResolver implements PropertyResolverInterface
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
namespace Sulu\Bundle\ContentBundle\Content\Application\PropertyResolver\Resolver;

use Sulu\Bundle\ContentBundle\Content\Application\ContentResolver\Value\ContentView;
use Sulu\Bundle\ContentBundle\Content\Application\PropertyResolver\PropertyResolverInterface;

class DefaultPropertyResolver implements PropertyResolverInterface
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
namespace Sulu\Bundle\ContentBundle\Content\Application\PropertyResolver\Resolver;

use Sulu\Bundle\ContentBundle\Content\Application\ContentResolver\Value\ContentView;
use Sulu\Bundle\ContentBundle\Content\Application\PropertyResolver\PropertyResolverInterface;
use Sulu\Bundle\ContentBundle\Content\Application\ResourceLoader\LinkResourceLoader;
use Sulu\Bundle\ContentBundle\Content\Application\ResourceLoader\Loader\LinkResourceLoader;
use Sulu\Bundle\MarkupBundle\Markup\Link\LinkItem;

class LinkPropertyResolver implements PropertyResolverInterface
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* with this source code in the file LICENSE.
*/

namespace Sulu\Bundle\ContentBundle\Content\Application\PropertyResolver;
namespace Sulu\Bundle\ContentBundle\Content\Application\PropertyResolver\Resolver;

use Sulu\Bundle\ContentBundle\Content\Application\ContentResolver\Value\ContentView;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

/*
* This file is part of Sulu.
*
* (c) Sulu GmbH
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Sulu\Bundle\ContentBundle\Content\Application\PropertyResolver\Resolver;

use Sulu\Bundle\ContentBundle\Content\Application\ContentResolver\Value\ContentView;
use Sulu\Bundle\ContentBundle\Content\Application\ResourceLoader\Loader\TeaserResourceLoader;
use Sulu\Bundle\PageBundle\Teaser\Teaser;

class TeaserSelectionPropertyResolver implements PropertyResolverInterface
{
/**
* @param mixed[] $data
* @param mixed[] $params
*/
public function resolve(mixed $data, string $locale, array $params = []): ContentView
{
$returnedParams = ['presentsAs' => $data['presentsAs'] ?? null, ...$params];
unset($returnedParams['metadata']);

if (
!\is_array($data)
|| !\array_key_exists('items', $data)
|| !\is_array($data['items'])
) {
return ContentView::create($data, $returnedParams);
}

/** @var string $resourceLoaderKey */
$resourceLoaderKey = $params['resourceLoader'] ?? TeaserResourceLoader::getKey();

$contentViews = [];
foreach ($data['items'] as $item) {
if (!\is_array($item) || !\array_key_exists('id', $item) || !\array_key_exists('type', $item)) {
continue;
}
$type = $item['type'];
$id = $item['id'];

$contentViews[] = ContentView::createResolvable(
$type . '::' . $id,
$resourceLoaderKey,
[
'id' => $id,
'type' => $type,
],
static function(Teaser $resource) use ($item) {
return $resource->merge($item);
}
);
}

return ContentView::create($contentViews, $returnedParams);
}

public static function getType(): string
{
return 'teaser_selection';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* with this source code in the file LICENSE.
*/

namespace Sulu\Bundle\ContentBundle\Content\Application\ResourceLoader;
namespace Sulu\Bundle\ContentBundle\Content\Application\ResourceLoader\Loader;

use Sulu\Bundle\MarkupBundle\Markup\Link\LinkItem;
use Sulu\Bundle\MarkupBundle\Markup\Link\LinkProviderPoolInterface;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* with this source code in the file LICENSE.
*/

namespace Sulu\Bundle\ContentBundle\Content\Application\ResourceLoader;
namespace Sulu\Bundle\ContentBundle\Content\Application\ResourceLoader\Loader;

interface ResourceLoaderInterface
{
Expand Down
78 changes: 78 additions & 0 deletions Content/Application/ResourceLoader/Loader/TeaserResourceLoader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

declare(strict_types=1);

/*
* This file is part of Sulu.
*
* (c) Sulu GmbH
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Sulu\Bundle\ContentBundle\Content\Application\ResourceLoader\Loader;

use Sulu\Bundle\PageBundle\Teaser\TeaserManagerInterface;

class TeaserResourceLoader implements ResourceLoaderInterface
{
public const RESOURCE_LOADER_KEY = 'teaser';

public function __construct(
private TeaserManagerInterface $teaserManager
) {
}

/**
* @param string[] $ids
* @param mixed[] $params
*
* @return array<string, mixed>
*/
public function load(array $ids, ?string $locale, array $params = []): array
{
if ([] === $ids) {
return [];
}

if (null === $locale) {
throw new \RuntimeException('Locale is required to resolve Teasers');
}

$items = $this->getItemsByProvider($ids);
$teasers = [];
foreach ($items as $provider => $itemsPerProvider) {
$loadedTeasers = $this->teaserManager->find($itemsPerProvider, $locale);
foreach ($loadedTeasers as $teaser) {
$teasers[$provider . '::' . $teaser->getId()] = $teaser;
}
}

return $teasers;
}

/**
* @param string[] $ids
*
* @return array<string, non-empty-array<int, array{id: string, type: string}>>
*/
private function getItemsByProvider(array $ids): array
{
$idsByProvider = [];
foreach ($ids as $id) {
[$provider, $id] = \explode('::', $id, 2);
$idsByProvider[$provider][] = [
'id' => $id,
'type' => $provider,
];
}

return $idsByProvider;
}

public static function getKey(): string
{
return self::RESOURCE_LOADER_KEY;
}
}
2 changes: 2 additions & 0 deletions Content/Application/ResourceLoader/ResourceLoaderProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace Sulu\Bundle\ContentBundle\Content\Application\ResourceLoader;

use Sulu\Bundle\ContentBundle\Content\Application\ResourceLoader\Loader\ResourceLoaderInterface;

class ResourceLoaderProvider
{
/**
Expand Down
6 changes: 6 additions & 0 deletions Resources/config/resolvers.xml
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,11 @@

<tag name="sulu_content.property_resolver"/>
</service>

<service id="sulu_content.teaser_selection_property_resolver"
class="Sulu\Bundle\ContentBundle\Content\Application\PropertyResolver\Resolver\TeaserSelectionPropertyResolver">

<tag name="sulu_content.property_resolver"/>
</service>
</services>
</container>
9 changes: 8 additions & 1 deletion Resources/config/resource-loader.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,17 @@
</service>

<service id="sulu_content.link_resource_loader"
class="Sulu\Bundle\ContentBundle\Content\Application\ResourceLoader\LinkResourceLoader">
class="Sulu\Bundle\ContentBundle\Content\Application\ResourceLoader\Loader\LinkResourceLoader">
<argument type="service" id="sulu_markup.link_tag.provider_pool"/>

<tag name="sulu_content.resource_loader" type="link"/>
</service>

<service id="sulu_content.teaser_resource_loader"
class="Sulu\Bundle\ContentBundle\Content\Application\ResourceLoader\Loader\TeaserResourceLoader">
<argument type="service" id="sulu_page.teaser.manager"/>

<tag name="sulu_content.resource_loader" type="teaser"/>
</service>
</services>
</container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<?php

declare(strict_types=1);

/*
* This file is part of Sulu.
*
* (c) Sulu GmbH
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Sulu\Bundle\ContentBundle\Tests\Unit\Content\Application\PropertyResolver\Resolver;

use PHPUnit\Framework\TestCase;
use Sulu\Bundle\ContentBundle\Content\Application\ContentResolver\Value\ContentView;
use Sulu\Bundle\ContentBundle\Content\Application\ContentResolver\Value\ResolvableResource;
use Sulu\Bundle\ContentBundle\Content\Application\PropertyResolver\Resolver\TeaserSelectionPropertyResolver;
use Sulu\Bundle\PageBundle\Teaser\Teaser;

class TeaserSelectionPropertyResolverTest extends TestCase
{
private TeaserSelectionPropertyResolver $resolver;

protected function setUp(): void
{
$this->resolver = new TeaserSelectionPropertyResolver();
}

public function testResolveEmpty(): void
{
$contentView = $this->resolver->resolve([], 'en');

$this->assertSame([], $contentView->getContent());
$this->assertSame(['presentsAs' => null], $contentView->getView());
}

public function testResolveParams(): void
{
$contentView = $this->resolver->resolve([], 'en', ['custom' => 'params']);

$this->assertSame([], $contentView->getContent());
$this->assertSame(['presentsAs' => null, 'custom' => 'params'], $contentView->getView());
}

public function testResolveData(): void
{
$data = [
'presentsAs' => 'two-columns',
'items' => [
['id' => '123', 'type' => 'article'],
['id' => '456', 'type' => 'page'],
],
];

$contentView = $this->resolver->resolve($data, 'en');

$content = $contentView->getContent();
$this->assertIsArray($content);
$this->assertCount(2, $content);

$innerContentView1 = $content[0];
$this->assertInstanceOf(ContentView::class, $innerContentView1);
$resolvableResource = $innerContentView1->getContent();
$this->assertInstanceOf(ResolvableResource::class, $resolvableResource);
$this->assertSame('article::123', $resolvableResource->getId());
$this->assertSame('teaser', $resolvableResource->getResourceLoaderKey());
$this->assertSame(['id' => '123', 'type' => 'article'], $innerContentView1->getView());

$innerContentView2 = $content[1];
$this->assertInstanceOf(ContentView::class, $innerContentView2);
$resolvableResource = $innerContentView2->getContent();
$this->assertInstanceOf(ResolvableResource::class, $resolvableResource);
$this->assertSame('page::456', $resolvableResource->getId());
$this->assertSame('teaser', $resolvableResource->getResourceLoaderKey());
$this->assertSame(['id' => '456', 'type' => 'page'], $innerContentView2->getView());

$this->assertSame(['presentsAs' => 'two-columns'], $contentView->getView());
}

public function testResolveCustomResourceLoader(): void
{
$data = [
'items' => [
['id' => '123', 'type' => 'article'],
],
];

$contentView = $this->resolver->resolve($data, 'en', ['resourceLoader' => 'custom_teaser']);

$content = $contentView->getContent();
$this->assertIsArray($content);
$this->assertCount(1, $content);

$innerContent = $content[0];
$this->assertInstanceOf(ContentView::class, $innerContent);
$resolvable = $innerContent->getContent();
$this->assertInstanceOf(ResolvableResource::class, $resolvable);
$this->assertSame('article::123', $resolvable->getId());
$this->assertSame('custom_teaser', $resolvable->getResourceLoaderKey());
}

public function testResolveWithResourceCallback(): void
{
$data = [
'items' => [
[
'id' => '123',
'type' => 'article',
'title' => 'Article Title',
'description' => 'Article Description',
'mediaId' => 11,
],
],
];

$contentView = $this->resolver->resolve($data, 'en');

$content = $contentView->getContent();
$this->assertIsArray($content);
$this->assertCount(1, $content);

$innerContent = $content[0];
$this->assertInstanceOf(ContentView::class, $innerContent);
$resolvable = $innerContent->getContent();
$this->assertInstanceOf(ResolvableResource::class, $resolvable);
$this->assertSame('article::123', $resolvable->getId());
$this->assertSame('teaser', $resolvable->getResourceLoaderKey());

$teaser = new Teaser('123', 'article', 'en', '', '', '', 'http://example.com', 1);
$mergedTeaser = $resolvable->executeResourceCallback($teaser);
$this->assertInstanceOf(Teaser::class, $mergedTeaser);
$this->assertSame('Article Title', $mergedTeaser->getTitle());
$this->assertSame('Article Description', $mergedTeaser->getDescription());
$this->assertSame(11, $mergedTeaser->getMediaId());
}

public function testGetType(): void
{
$this->assertSame('teaser_selection', TeaserSelectionPropertyResolver::getType());
}
}
Loading

0 comments on commit c1c6451

Please sign in to comment.