Skip to content

Commit

Permalink
Add Single Media Property Resolver and displayOption handling (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-schranz authored Oct 17, 2024
1 parent cc00588 commit 69c006e
Show file tree
Hide file tree
Showing 6 changed files with 408 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Sulu\Bundle\ContentBundle\Content\Application\ContentResolver\Value\ResolvableResource;
use Sulu\Bundle\CategoryBundle\Infrastructure\Sulu\Content\PropertyResolver\CategorySelectionPropertyResolver;
use Sulu\Bundle\ContentBundle\Content\Application\ContentResolver\Value\ResolvableResource;

#[CoversClass(CategorySelectionPropertyResolver::class)]
class CategorySelectionPropertyResolverTest extends TestCase
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\MediaBundle\Infrastructure\Sulu\Content\PropertyResolver\Resolver;
namespace Sulu\Bundle\MediaBundle\Infrastructure\Sulu\Content\PropertyResolver;

use Sulu\Bundle\ContentBundle\Content\Application\ContentResolver\Value\ContentView;
use Sulu\Bundle\ContentBundle\Content\Application\PropertyResolver\PropertyResolverInterface;
Expand All @@ -26,8 +26,15 @@ class MediaSelectionPropertyResolver implements PropertyResolverInterface
{
public function resolve(mixed $data, string $locale, array $params = []): ContentView
{
if (empty($data) || !\is_array($data) || !isset($data['ids'])) {
return ContentView::create([], ['ids' => []]);
$displayOption = (\is_array($data) && isset($data['displayOption']) && \is_string($data['displayOption']))
? $data['displayOption']
: null;

if (!\is_array($data)
|| !isset($data['ids'])
|| !\array_is_list($data['ids'])
) {
return ContentView::create([], ['ids' => [], 'displayOption' => $displayOption, ...$params]);
}

/** @var string $resourceLoaderKey */
Expand All @@ -36,7 +43,11 @@ public function resolve(mixed $data, string $locale, array $params = []): Conten
return ContentView::createResolvables(
$data['ids'],
$resourceLoaderKey,
['ids' => $data['ids']],
[
'ids' => $data['ids'],
'displayOption' => $displayOption,
...$params,
],
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?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\MediaBundle\Infrastructure\Sulu\Content\PropertyResolver;

use Sulu\Bundle\ContentBundle\Content\Application\ContentResolver\Value\ContentView;
use Sulu\Bundle\ContentBundle\Content\Application\PropertyResolver\PropertyResolverInterface;
use Sulu\Bundle\MediaBundle\Infrastructure\Sulu\Content\ResourceLoader\MediaResourceLoader;

/**
* @internal if you need to override this service, create a new service with based on ResourceLoaderInterface instead of extending this class
*
* @final
*/
class SingleMediaSelectionPropertyResolver implements PropertyResolverInterface
{
public function resolve(mixed $data, string $locale, array $params = []): ContentView
{
$displayOption = (\is_array($data) && isset($data['displayOption']) && \is_string($data['displayOption']))
? $data['displayOption']
: null;

if (!\is_array($data)
|| !isset($data['id'])
|| !\is_numeric($data['id'])
) {
return ContentView::create(null, ['id' => null, 'displayOption' => $displayOption, ...$params]);
}

/** @var string $resourceLoaderKey */
$resourceLoaderKey = $params['resourceLoader'] ?? MediaResourceLoader::getKey();
$id = (int) $data['id'];

return ContentView::createResolvable(
$id,
$resourceLoaderKey,
[
'id' => $id,
'displayOption' => $displayOption,
...$params,
],
);
}

public static function getType(): string
{
return 'single_media_selection';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?php

/*
* 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\MediaBundle\Tests\Unit\Infrastructure\Sulu\Content\PropertyResolver;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Sulu\Bundle\ContentBundle\Content\Application\ContentResolver\Value\ResolvableResource;
use Sulu\Bundle\MediaBundle\Infrastructure\Sulu\Content\PropertyResolver\MediaSelectionPropertyResolver;

#[CoversClass(MediaSelectionPropertyResolver::class)]
class MediaSelectionPropertyResolverTest extends TestCase
{
private MediaSelectionPropertyResolver $resolver;

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

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

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

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

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

#[DataProvider('provideUnresolvableData')]
public function testResolveUnresolvableData(mixed $data, ?string $expectedDisplayOption = null): void
{
$contentView = $this->resolver->resolve($data, 'en');

$this->assertSame([], $contentView->getContent());
$this->assertSame(['ids' => [], 'displayOption' => $expectedDisplayOption], $contentView->getView());
}

/**
* @return iterable<array{
* 0: mixed,
* }>
*/
public static function provideUnresolvableData(): iterable
{
yield 'null' => [null];
yield 'smart_content' => [['source' => '123']];
yield 'single_value' => [1];
yield 'object' => [(object) [1, 2]];
yield 'int_list_not_in_ids' => [[1, 2]];
yield 'ids_null' => [['ids' => null]];
yield 'display_option_only' => [['displayOption' => 'left'], 'left'];
}

/**
* @param array{
* ids?: array<string|int>,
* displayOption?: string|null,
* } $data
*/
#[DataProvider('provideResolvableData')]
public function testResolveResolvableData(array $data, ?string $expectedDisplayOption = null): void
{
$contentView = $this->resolver->resolve($data, 'en');

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

foreach (($data['ids'] ?? []) as $key => $value) {
$resolvable = $content[$key] ?? null;
$this->assertInstanceOf(ResolvableResource::class, $resolvable);
$this->assertSame($value, $resolvable->getId());
$this->assertSame('media', $resolvable->getResourceLoaderKey());
}

$this->assertSame([
'ids' => ($data['ids'] ?? []),
'displayOption' => $expectedDisplayOption,
], $contentView->getView());
}

/**
* @return iterable<array{
* 0: array{
* ids: array<string|int>,
* displayOption?: string|null,
* },
* }>
*/
public static function provideResolvableData(): iterable
{
yield 'empty' => [[]];
yield 'int_list' => [['ids' => [1, 2]]];
yield 'int_list_with_display_option' => [['ids' => [1, 2], 'displayOption' => 'left'], 'left'];
yield 'string_list' => [['ids' => ['1', '2']]];
yield 'string_list_with_display_option' => [['ids' => ['1', '2'], 'displayOption' => 'left'], 'left'];
}

public function testCustomResourceLoader(): void
{
$contentView = $this->resolver->resolve(['ids' => [1]], 'en', ['resourceLoader' => 'custom_media']);

$content = $contentView->getContent();
$this->assertIsArray($content);
$resolvable = $content[0] ?? null;
$this->assertInstanceOf(ResolvableResource::class, $resolvable);
$this->assertSame(1, $resolvable->getId());
$this->assertSame('custom_media', $resolvable->getResourceLoaderKey());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?php

/*
* 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\MediaBundle\Tests\Unit\Infrastructure\Sulu\Content\PropertyResolver;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Sulu\Bundle\ContentBundle\Content\Application\ContentResolver\Value\ResolvableResource;
use Sulu\Bundle\MediaBundle\Infrastructure\Sulu\Content\PropertyResolver\SingleMediaSelectionPropertyResolver;

#[CoversClass(SingleMediaSelectionPropertyResolver::class)]
class SingleMediaSelectionPropertyResolverTest extends TestCase
{
private SingleMediaSelectionPropertyResolver $resolver;

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

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

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

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

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

#[DataProvider('provideUnresolvableData')]
public function testResolveUnresolvableData(mixed $data, ?string $expectedDisplayOption = null): void
{
$contentView = $this->resolver->resolve($data, 'en');

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

/**
* @return iterable<array{
* 0: mixed,
* }>
*/
public static function provideUnresolvableData(): iterable
{
yield 'null' => [null];
yield 'smart_content' => [['source' => '123']];
yield 'single_value' => [1];
yield 'object' => [(object) [1, 2]];
yield 'int_list_not_in_ids' => [[1, 2]];
yield 'ids_null' => [['ids' => null]];
yield 'ids_list' => [['ids' => [1, 2]]];
yield 'id_list' => [['id' => [1, 2]]];
yield 'display_option_only' => [['displayOption' => 'left'], 'left'];
}

/**
* @param array{
* id?: string|int,
* displayOption?: string|null,
* } $data
*/
#[DataProvider('provideResolvableData')]
public function testResolveResolvableData(array $data, ?string $expectedDisplayOption = null): void
{
$contentView = $this->resolver->resolve($data, 'en');

$content = $contentView->getContent();
$id = $data['id'] ?? null;
if (null !== $id) {
$id = (int) $id;
$this->assertInstanceOf(ResolvableResource::class, $content);
$this->assertSame($id, $content->getId());
$this->assertSame('media', $content->getResourceLoaderKey());
}

$this->assertSame([
'id' => $id,
'displayOption' => $expectedDisplayOption,
], $contentView->getView());
}

/**
* @return iterable<array{
* 0: array{
* id: string|int,
* displayOption?: string|null,
* },
* }>
*/
public static function provideResolvableData(): iterable
{
yield 'empty' => [[]];
yield 'int_id' => [['id' => 1]];
yield 'int_id_with_display_option' => [['id' => 1, 'displayOption' => 'left'], 'left'];
yield 'string_id' => [['id' => '1']];
yield 'string_id_with_display_option' => [['id' => '1', 'displayOption' => 'left'], 'left'];
}

public function testCustomResourceLoader(): void
{
$contentView = $this->resolver->resolve(['ids' => [1]], 'en', ['resourceLoader' => 'custom_media']);

$content = $contentView->getContent();
$this->assertIsArray($content);
$resolvable = $content[0] ?? null;
$this->assertInstanceOf(ResolvableResource::class, $resolvable);
$this->assertSame(1, $resolvable->getId());
$this->assertSame('custom_media', $resolvable->getResourceLoaderKey());
}
}
Loading

0 comments on commit 69c006e

Please sign in to comment.