Skip to content

Commit

Permalink
Change how data is passed to the component hookables
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubtobiasz committed Feb 7, 2024
1 parent f2dd5d5 commit 2d1c684
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 3 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"php": "^8.1",
"symfony/config": "^5.4 || ^6.0",
"symfony/dependency-injection": "^5.4 || ^6.0",
"symfony/expression-language": "^5.4 || ^6.0",
"symfony/http-kernel": "^5.4 || ^6.0",
"symfony/stopwatch": "^5.4 || ^6.0",
"symfony/ux-twig-component": "^2.12",
Expand Down
8 changes: 8 additions & 0 deletions src/TwigHooks/config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use Sylius\TwigHooks\Hook\NameGenerator\TemplateNameGenerator;
use Sylius\TwigHooks\Provider\ComponentDataProvider;
use Sylius\TwigHooks\Provider\DefaultConfigurationProvider;
use Sylius\TwigHooks\Provider\DefaultDataProvider;
use Sylius\TwigHooks\Registry\HookablesRegistry;
use Sylius\TwigHooks\Twig\HooksExtension;
use Sylius\TwigHooks\Twig\Runtime\HooksRuntime;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;

return static function (ContainerConfigurator $configurator): void {
$configurator->import(__DIR__ . '/services/*.php');
Expand All @@ -16,6 +18,12 @@

$services->set('twig_hooks.provider.default_data', DefaultDataProvider::class);

$services->set('twig_hooks.provider.component_data', ComponentDataProvider::class)
->args([
inline_service(ExpressionLanguage::class),
])
;

$services->set('twig_hooks.provider.default_configuration', DefaultConfigurationProvider::class);

$services->set('twig_hooks.registry.hookables', HookablesRegistry::class)
Expand Down
2 changes: 1 addition & 1 deletion src/TwigHooks/config/services/hookable_renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
$services->set('twig_hooks.renderer.hookable.component', HookableComponentRenderer::class)
->args([
service('ux.twig_component.component_renderer'),
service('twig_hooks.provider.default_data'),
service('twig_hooks.provider.component_data'),
service('twig_hooks.provider.default_configuration'),
])
->tag('twig_hooks.hookable_renderer')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ public function render(AbstractHookable $hookable, array $hookData = []): string
$configuration = $this->configurationProvider->provide($hookable);

return $this->componentRenderer->createAndRender($hookable->getTarget(), [
self::HOOKABLE_DATA_PARAMETER => $data,
self::HOOKABLE_CONFIGURATION_PARAMETER => $configuration,
...$data,
]);
}

Expand Down
43 changes: 43 additions & 0 deletions src/TwigHooks/src/Provider/ComponentDataProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace Sylius\TwigHooks\Provider;

use Sylius\TwigHooks\Hookable\AbstractHookable;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;

final class ComponentDataProvider implements DataProviderInterface
{
public function __construct (
private ExpressionLanguage $expressionLanguage,
) {
}

public function provide(AbstractHookable $hookable, array $hookData): array
{
return $this->mapArrayRecursively(function (mixed $value) use ($hookData): mixed {
if (is_string($value) && str_starts_with($value, '@=')) {
return $this->expressionLanguage->evaluate(substr($value, 2), ['data' => $hookData]);
}

return $value;
}, $hookable->getData());
}

/**
* @param array<array-key, mixed> $array
* @return array<array-key, mixed>
*/
private function mapArrayRecursively(callable $callback, array $array): array
{
$result = [];
foreach ($array as $key => $value) {
$result[$key] = is_array($value)
? $this->mapArrayRecursively($callback, $value)
: $callback($value);
}

return $result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ public function testItRendersHookableComponent(): void
$this->componentRenderer->expects($this->once())->method('createAndRender')->with(
'some-component',
[
HookableComponentRenderer::HOOKABLE_DATA_PARAMETER => ['some' => 'data'],
HookableComponentRenderer::HOOKABLE_CONFIGURATION_PARAMETER => ['some' => 'configuration'],
'some' => 'data',
]
)->willReturn('some-rendered-component');

Expand Down
50 changes: 50 additions & 0 deletions src/TwigHooks/tests/Unit/Provider/ComponentDataProviderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace Tests\Sylius\TwigHooks\Unit\Provider;

use PHPUnit\Framework\TestCase;
use Sylius\TwigHooks\Provider\ComponentDataProvider;
use Sylius\TwigHooks\Provider\DataProviderInterface;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Tests\Sylius\TwigHooks\Utils\MotherObject\BaseHookableMotherObject;

final class ComponentDataProviderTest extends TestCase
{
public function testItReturnsEmptyArrayWhenNoDataIsProvidedOnHookable(): void
{
$hookable = BaseHookableMotherObject::some();

$dataProvider = $this->createTestSubject();

$this->assertSame([], $dataProvider->provide($hookable, []));
$this->assertSame([], $dataProvider->provide($hookable, ['some' => 'data']));
}

public function testItReturnsDataFromHookable(): void
{
$hookable = BaseHookableMotherObject::withData(['some' => 'data']);

$dataProvider = $this->createTestSubject();

$this->assertSame(['some' => 'data'], $dataProvider->provide($hookable, []));
$this->assertSame(['some' => 'data'], $dataProvider->provide($hookable, ['more' => 'data']));
}

public function testItPassesTemplateLevelDataToExpressionLanguage(): void
{
$hookable = BaseHookableMotherObject::withData(['some_key' => '@=data["some"]']);

$dataProvider = $this->createTestSubject();

$this->assertSame(['some_key' => 'data'], $dataProvider->provide($hookable, ['some' => 'data']));
}

private function createTestSubject(): DataProviderInterface
{
return new ComponentDataProvider(
new ExpressionLanguage(),
);
}
}

0 comments on commit 2d1c684

Please sign in to comment.