From 0ab8b3ba8b9df43287137b11f2a8bf1dfdf60851 Mon Sep 17 00:00:00 2001 From: Jacob Tobiasz Date: Mon, 29 Apr 2024 13:44:19 +0200 Subject: [PATCH] [Twig Hooks] Introduce the ScalarDataBag object for the HookableMetadata configuration data --- src/TwigHooks/src/Bag/DataBag.php | 5 +++ src/TwigHooks/src/Bag/ScalarDataBag.php | 38 +++++++++++++++++++ .../src/Bag/ScalarDataBagInterface.php | 12 ++++++ .../src/Hook/Renderer/HookRenderer.php | 3 +- .../Hookable/Metadata/HookableMetadata.php | 3 +- .../HookableLiveComponentTrait.php | 4 +- .../DependencyInjection/ConfigurationTest.php | 2 +- .../Twig/Runtime/HooksRuntimeTest.php | 3 +- .../HookableComponentRendererTest.php | 3 +- .../HookableMetadataMotherObject.php | 14 ++++--- 10 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 src/TwigHooks/src/Bag/ScalarDataBag.php create mode 100644 src/TwigHooks/src/Bag/ScalarDataBagInterface.php diff --git a/src/TwigHooks/src/Bag/DataBag.php b/src/TwigHooks/src/Bag/DataBag.php index 55b810a6..68799edd 100644 --- a/src/TwigHooks/src/Bag/DataBag.php +++ b/src/TwigHooks/src/Bag/DataBag.php @@ -11,6 +11,11 @@ class DataBag implements DataBagInterface */ public function __construct(private array $container = []) { + foreach ($container as $key => $value) { + if (!is_string($key)) { + throw new \InvalidArgumentException('The key must be a string.'); + } + } } public function offsetExists(mixed $offset): bool diff --git a/src/TwigHooks/src/Bag/ScalarDataBag.php b/src/TwigHooks/src/Bag/ScalarDataBag.php new file mode 100644 index 00000000..282d4b69 --- /dev/null +++ b/src/TwigHooks/src/Bag/ScalarDataBag.php @@ -0,0 +1,38 @@ +validateValues($container); + + parent::__construct($container); + } + + public function offsetSet(mixed $offset, mixed $value): void + { + if (!is_scalar($value)) { + throw new \InvalidArgumentException('The value must be a scalar.'); + } + + parent::offsetSet($offset, $value); + } + + private function validateValues(array $values): void + { + foreach ($values as $value) { + if (is_array($value)) { + $this->validateValues($value); + continue; + } + + if (!is_scalar($value)) { + throw new \InvalidArgumentException('The value must be a scalar.'); + } + } + } +} diff --git a/src/TwigHooks/src/Bag/ScalarDataBagInterface.php b/src/TwigHooks/src/Bag/ScalarDataBagInterface.php new file mode 100644 index 00000000..18622371 --- /dev/null +++ b/src/TwigHooks/src/Bag/ScalarDataBagInterface.php @@ -0,0 +1,12 @@ + + */ +interface ScalarDataBagInterface extends \ArrayAccess +{ +} diff --git a/src/TwigHooks/src/Hook/Renderer/HookRenderer.php b/src/TwigHooks/src/Hook/Renderer/HookRenderer.php index 427bbd1c..2dadb54d 100644 --- a/src/TwigHooks/src/Hook/Renderer/HookRenderer.php +++ b/src/TwigHooks/src/Hook/Renderer/HookRenderer.php @@ -5,6 +5,7 @@ namespace Sylius\TwigHooks\Hook\Renderer; use Sylius\TwigHooks\Bag\DataBag; +use Sylius\TwigHooks\Bag\ScalarDataBag; use Sylius\TwigHooks\Hook\Metadata\HookMetadata; use Sylius\TwigHooks\Hookable\Metadata\HookableMetadata; use Sylius\TwigHooks\Hookable\Renderer\HookableRendererInterface; @@ -37,7 +38,7 @@ public function render(array $hookNames, array $hookContext = []): string $context = $this->contextProvider->provide($hookable, $hookContext); $configuration = $this->configurationProvider->provide($hookable); - $hookableMetadata = new HookableMetadata($hookMetadata, new DataBag($context), new DataBag($configuration), $hookNames); + $hookableMetadata = new HookableMetadata($hookMetadata, new DataBag($context), new ScalarDataBag($configuration), $hookNames); $renderedHookables[] = $this->compositeHookableRenderer->render($hookable, $hookableMetadata); } diff --git a/src/TwigHooks/src/Hookable/Metadata/HookableMetadata.php b/src/TwigHooks/src/Hookable/Metadata/HookableMetadata.php index f7dff0e5..94b0e918 100644 --- a/src/TwigHooks/src/Hookable/Metadata/HookableMetadata.php +++ b/src/TwigHooks/src/Hookable/Metadata/HookableMetadata.php @@ -5,6 +5,7 @@ namespace Sylius\TwigHooks\Hookable\Metadata; use Sylius\TwigHooks\Bag\DataBagInterface; +use Sylius\TwigHooks\Bag\ScalarDataBagInterface; use Sylius\TwigHooks\Hook\Metadata\HookMetadata; class HookableMetadata @@ -15,7 +16,7 @@ class HookableMetadata public function __construct( public readonly HookMetadata $renderedBy, public readonly DataBagInterface $context, - public readonly DataBagInterface $configuration, + public readonly ScalarDataBagInterface $configuration, public readonly array $prefixes = [], ) { foreach ($prefixes as $prefix) { diff --git a/src/TwigHooks/src/LiveComponent/HookableLiveComponentTrait.php b/src/TwigHooks/src/LiveComponent/HookableLiveComponentTrait.php index 4c0d0736..54df7423 100644 --- a/src/TwigHooks/src/LiveComponent/HookableLiveComponentTrait.php +++ b/src/TwigHooks/src/LiveComponent/HookableLiveComponentTrait.php @@ -5,6 +5,7 @@ namespace Sylius\TwigHooks\LiveComponent; use Sylius\TwigHooks\Bag\DataBag; +use Sylius\TwigHooks\Bag\ScalarDataBag; use Sylius\TwigHooks\Hook\Metadata\HookMetadata; use Sylius\TwigHooks\Hookable\Metadata\HookableMetadata; use Symfony\UX\LiveComponent\Attribute\LiveProp; @@ -21,7 +22,7 @@ public function hydrateHookableMetadata($data): HookableMetadata return new HookableMetadata( new HookMetadata($data['renderedBy'], new DataBag()), new DataBag(), - new DataBag(), + new ScalarDataBag(json_decode($data['configuration'], true)), $data['prefixes'] ?? [], ); } @@ -30,6 +31,7 @@ public function dehydrateHookableMetadata(HookableMetadata $metadata): array { return [ 'renderedBy' => $metadata->renderedBy->name, + 'configuration' => json_encode($metadata->configuration->all()), 'prefixes' => $metadata->prefixes, ]; } diff --git a/src/TwigHooks/tests/Integration/DependencyInjection/ConfigurationTest.php b/src/TwigHooks/tests/Integration/DependencyInjection/ConfigurationTest.php index 40377007..50ef7440 100644 --- a/src/TwigHooks/tests/Integration/DependencyInjection/ConfigurationTest.php +++ b/src/TwigHooks/tests/Integration/DependencyInjection/ConfigurationTest.php @@ -27,7 +27,7 @@ public function testItReturnsDefaultConfiguration(): void 'component' => HookableComponent::class, 'disabled' => DisabledHookable::class, ], - 'hook_name_section_separator' => '#', + 'hook_name_section_separator' => false, ], ); } diff --git a/src/TwigHooks/tests/Integration/Twig/Runtime/HooksRuntimeTest.php b/src/TwigHooks/tests/Integration/Twig/Runtime/HooksRuntimeTest.php index 3744c0f3..3c93debf 100644 --- a/src/TwigHooks/tests/Integration/Twig/Runtime/HooksRuntimeTest.php +++ b/src/TwigHooks/tests/Integration/Twig/Runtime/HooksRuntimeTest.php @@ -5,6 +5,7 @@ namespace Tests\Sylius\TwigHooks\Integration\Twig\Runtime; use Sylius\TwigHooks\Bag\DataBag; +use Sylius\TwigHooks\Bag\ScalarDataBag; use Sylius\TwigHooks\Twig\Runtime\HooksRuntime; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Tests\Sylius\TwigHooks\Utils\MotherObject\HookableMetadataMotherObject; @@ -47,7 +48,7 @@ public function testItReturnsHookableContext(): void public function testItReturnsHookableConfiguration(): void { $runtime = $this->getTestSubject(); - $configuration = new DataBag(); + $configuration = new ScalarDataBag(); $metadata = HookableMetadataMotherObject::withConfiguration($configuration); $this->assertSame($configuration, $runtime->getHookableConfiguration(['hookable_metadata' => $metadata])); diff --git a/src/TwigHooks/tests/Unit/Hookable/Renderer/HookableComponentRendererTest.php b/src/TwigHooks/tests/Unit/Hookable/Renderer/HookableComponentRendererTest.php index 57323ef0..4a0f20ce 100644 --- a/src/TwigHooks/tests/Unit/Hookable/Renderer/HookableComponentRendererTest.php +++ b/src/TwigHooks/tests/Unit/Hookable/Renderer/HookableComponentRendererTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Sylius\TwigHooks\Bag\DataBag; +use Sylius\TwigHooks\Bag\ScalarDataBag; use Sylius\TwigHooks\Hookable\Metadata\HookableMetadata; use Sylius\TwigHooks\Hookable\Renderer\HookableComponentRenderer; use Sylius\TwigHooks\Provider\PropsProviderInterface; @@ -54,7 +55,7 @@ public function testItRendersHookableComponent(): void $hookable = HookableComponentMotherObject::withTargetAndProps('some-component', ['some' => 'data']); $metadata = HookableMetadataMotherObject::withContextAndConfiguration( context: new DataBag(['some' => 'data']), - configuration: new DataBag(['some' => 'configuration']), + configuration: new ScalarDataBag(['some' => 'configuration']), ); $this->propsProvider->expects($this->once())->method('provide')->with($hookable, $metadata)->willReturn(['some' => 'props']); diff --git a/src/TwigHooks/tests/Utils/MotherObject/HookableMetadataMotherObject.php b/src/TwigHooks/tests/Utils/MotherObject/HookableMetadataMotherObject.php index e9e1a6b6..e6449d36 100644 --- a/src/TwigHooks/tests/Utils/MotherObject/HookableMetadataMotherObject.php +++ b/src/TwigHooks/tests/Utils/MotherObject/HookableMetadataMotherObject.php @@ -6,6 +6,8 @@ use Sylius\TwigHooks\Bag\DataBag; use Sylius\TwigHooks\Bag\DataBagInterface; +use Sylius\TwigHooks\Bag\ScalarDataBag; +use Sylius\TwigHooks\Bag\ScalarDataBagInterface; use Sylius\TwigHooks\Hookable\Metadata\HookableMetadata; final class HookableMetadataMotherObject @@ -15,7 +17,7 @@ public static function some(): HookableMetadata return new HookableMetadata( HookMetadataMotherObject::some(), new DataBag([]), - new DataBag([]), + new ScalarDataBag([]), [] ); } @@ -25,29 +27,29 @@ public static function withContext(DataBagInterface|array $context): HookableMet return new HookableMetadata( HookMetadataMotherObject::some(), is_array($context) ? new DataBag($context) : $context, - new DataBag([]), + new ScalarDataBag([]), [] ); } - public static function withConfiguration(DataBagInterface|array $configuration): HookableMetadata + public static function withConfiguration(ScalarDataBagInterface|array $configuration): HookableMetadata { return new HookableMetadata( HookMetadataMotherObject::some(), new DataBag([]), - is_array($configuration) ? new DataBag($configuration) : $configuration, + is_array($configuration) ? new ScalarDataBag($configuration) : $configuration, [] ); } public static function withContextAndConfiguration( DataBagInterface|array $context, - DataBagInterface|array $configuration, + ScalarDataBagInterface|array $configuration, ): HookableMetadata { return new HookableMetadata( HookMetadataMotherObject::some(), is_array($context) ? new DataBag($context) : $context, - is_array($configuration) ? new DataBag($configuration) : $configuration, + is_array($configuration) ? new ScalarDataBag($configuration) : $configuration, [] ); }