diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ea2fe4d8..58d26836 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -66,3 +66,6 @@ jobs: - name: Run PHPUnit run: bin/phpunit + + - name: Run PHPUnit (Twig Hooks) + run: bin/phpunit -c src/TwigHooks/phpunit.xml.dist diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 50ce9883..cd9971c0 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -20,9 +20,16 @@ src/TwigHooks/tests + + + + kernel-required + + + diff --git a/src/TwigHooks/config/services.php b/src/TwigHooks/config/services.php index 8c2c24d0..7cfec9bd 100644 --- a/src/TwigHooks/config/services.php +++ b/src/TwigHooks/config/services.php @@ -36,10 +36,7 @@ $services->set(HooksRuntime::class) ->args([ - service('twig_hooks.registry.hookables'), - service('twig_hooks.renderer.hookable'), - service('twig_hooks.profiler.profile')->nullOnInvalid(), - param('kernel.debug'), + service('twig_hooks.renderer.hook'), ]) ->tag('twig.runtime') ; diff --git a/src/TwigHooks/config/services/debug.php b/src/TwigHooks/config/services/debug.php index 78a7d0bf..4a4bee73 100644 --- a/src/TwigHooks/config/services/debug.php +++ b/src/TwigHooks/config/services/debug.php @@ -4,7 +4,9 @@ use Sylius\TwigHooks\DependencyInjection\CompilerPass\UnregisterDebugServicesPass; use Sylius\TwigHooks\Hook\Renderer\Debug\HookDebugCommentRenderer; +use Sylius\TwigHooks\Hook\Renderer\Debug\HookProfilerRenderer; use Sylius\TwigHooks\Hookable\Renderer\Debug\HookableDebugCommentRenderer; +use Sylius\TwigHooks\Hookable\Renderer\Debug\HookableProfilerRenderer; use Sylius\TwigHooks\Profiler\HooksDataCollector; use Sylius\TwigHooks\Profiler\Profile; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -13,17 +15,35 @@ $services = $configurator->services(); $services->defaults()->tag(UnregisterDebugServicesPass::DEBUG_TAG); - $services->set('twig_hooks.renderer.hook.debug', HookDebugCommentRenderer::class) - ->decorate('twig_hooks.renderer.hook') + $services->set('twig_hooks.renderer.hook.debug_comment', HookDebugCommentRenderer::class) + ->decorate('twig_hooks.renderer.hook', priority: 256) ->args([ service('.inner'), ]) ; - $services->set('twig_hooks.renderer.hookable.debug', HookableDebugCommentRenderer::class) - ->decorate('twig_hooks.renderer.hookable') + $services->set('twig_hooks.renderer.hook.profiler', HookProfilerRenderer::class) + ->decorate('twig_hooks.renderer.hook', priority: 512) ->args([ service('.inner'), + service('twig_hooks.profiler.profile')->nullOnInvalid(), + service('debug.stopwatch')->nullOnInvalid(), + ]) + ; + + $services->set('twig_hooks.renderer.hookable.debug_comment', HookableDebugCommentRenderer::class) + ->decorate('twig_hooks.renderer.hookable', priority: 256) + ->args([ + service('.inner'), + ]) + ; + + $services->set('twig_hooks.renderer.hookable.profiler', HookableProfilerRenderer::class) + ->decorate('twig_hooks.renderer.hookable', priority: 512) + ->args([ + service('.inner'), + service('twig_hooks.profiler.profile')->nullOnInvalid(), + service('debug.stopwatch')->nullOnInvalid(), ]) ; diff --git a/src/TwigHooks/phpunit.xml b/src/TwigHooks/phpunit.xml.dist similarity index 100% rename from src/TwigHooks/phpunit.xml rename to src/TwigHooks/phpunit.xml.dist diff --git a/src/TwigHooks/src/DependencyInjection/CompilerPass/UnregisterDebugServicesPass.php b/src/TwigHooks/src/DependencyInjection/CompilerPass/UnregisterDebugServicesPass.php index 510684a6..652eea49 100644 --- a/src/TwigHooks/src/DependencyInjection/CompilerPass/UnregisterDebugServicesPass.php +++ b/src/TwigHooks/src/DependencyInjection/CompilerPass/UnregisterDebugServicesPass.php @@ -14,6 +14,7 @@ final class UnregisterDebugServicesPass implements CompilerPassInterface public function process(ContainerBuilder $container): void { $debug = !$container->hasParameter('kernel.debug') || $container->getParameter('kernel.debug'); + if (true === $debug) { return; } diff --git a/src/TwigHooks/src/Hook/Renderer/Debug/HookProfilerRenderer.php b/src/TwigHooks/src/Hook/Renderer/Debug/HookProfilerRenderer.php new file mode 100644 index 00000000..aad20e1e --- /dev/null +++ b/src/TwigHooks/src/Hook/Renderer/Debug/HookProfilerRenderer.php @@ -0,0 +1,33 @@ +profile?->registerHookStart($hooksNames); + $this->stopwatch?->start(md5(serialize($hooksNames))); + + $rendered = $this->innerRenderer->render($hooksNames, $data); + + $this->profile?->registerHookEnd( + $this->stopwatch?->stop(md5(serialize($hooksNames)))->getDuration(), + ); + + return $rendered; + } +} diff --git a/src/TwigHooks/src/Hookable/Renderer/Debug/HookableProfilerRenderer.php b/src/TwigHooks/src/Hookable/Renderer/Debug/HookableProfilerRenderer.php new file mode 100644 index 00000000..5817069a --- /dev/null +++ b/src/TwigHooks/src/Hookable/Renderer/Debug/HookableProfilerRenderer.php @@ -0,0 +1,34 @@ +profile?->registerHookableRenderStart($hookable); + $this->stopwatch?->start($hookable->getId()); + + $rendered = $this->innerRenderer->render($hookable, $hookData); + + $this->profile?->registerHookableRenderEnd( + $this->stopwatch?->stop($hookable->getId())->getDuration(), + ); + + return $rendered; + } +} diff --git a/src/TwigHooks/src/Twig/Runtime/HooksRuntime.php b/src/TwigHooks/src/Twig/Runtime/HooksRuntime.php index 32bad3f5..1caff002 100644 --- a/src/TwigHooks/src/Twig/Runtime/HooksRuntime.php +++ b/src/TwigHooks/src/Twig/Runtime/HooksRuntime.php @@ -4,11 +4,7 @@ namespace Sylius\TwigHooks\Twig\Runtime; -use Sylius\TwigHooks\Hookable\AbstractHookable; -use Sylius\TwigHooks\Hookable\Renderer\HookableRendererInterface; -use Sylius\TwigHooks\Profiler\Profile; -use Sylius\TwigHooks\Registry\HookablesRegistry; -use Symfony\Component\Stopwatch\Stopwatch; +use Sylius\TwigHooks\Hook\Renderer\HookRendererInterface; use Twig\Extension\RuntimeExtensionInterface; final class HooksRuntime implements RuntimeExtensionInterface @@ -17,17 +13,9 @@ final class HooksRuntime implements RuntimeExtensionInterface public const HOOKABLE_DATA_PARAMETER = 'hookable_data'; - private ?Stopwatch $stopwatch = null; - public function __construct ( - private HookablesRegistry $hookablesRegistry, - private HookableRendererInterface $compositeHookableRenderer, - private ?Profile $profile, - bool $debug, + private readonly HookRendererInterface $hookRenderer, ) { - if (class_exists(Stopwatch::class) && true === $debug) { - $this->stopwatch = new Stopwatch(); - } } public function createHookName(string $base, string ...$parts): string @@ -84,39 +72,12 @@ public function getHookableConfiguration(array $context): array * @param array $hooksNames * @param array $data */ - public function renderHook(array $hooksNames, array $data = []): string + public function renderHook(string|array $hooksNames, array $data = []): string { - $this->profile?->registerHookStart($hooksNames); - $this->stopwatch?->start(md5(serialize($hooksNames))); - - $result = []; - $enabledHookables = $this->hookablesRegistry->getEnabledFor($hooksNames); - - foreach ($enabledHookables as $hookable) { - $result[] = $this->renderHookable($hookable, $data); + if (is_string($hooksNames)) { + $hooksNames = [$hooksNames]; } - $this->profile?->registerHookEnd( - $this->stopwatch?->stop(md5(serialize($hooksNames)))->getDuration(), - ); - - return implode(PHP_EOL, $result); - } - - /** - * @param array $data - */ - public function renderHookable(AbstractHookable $hookable, array $data = []): string - { - $this->profile?->registerHookableRenderStart($hookable); - $this->stopwatch?->start($hookable->getId()); - - $result = $this->compositeHookableRenderer->render($hookable, $data); - - $this->profile?->registerHookableRenderEnd( - $this->stopwatch?->stop($hookable->getId())->getDuration(), - ); - - return $result; + return $this->hookRenderer->render($hooksNames, $data); } } diff --git a/src/TwigHooks/src/Twig/TokenParser/HookTokenParser.php b/src/TwigHooks/src/Twig/TokenParser/HookTokenParser.php index c9fb2858..194c7fcc 100644 --- a/src/TwigHooks/src/Twig/TokenParser/HookTokenParser.php +++ b/src/TwigHooks/src/Twig/TokenParser/HookTokenParser.php @@ -17,7 +17,7 @@ public function parse(Token $token): Node { $lineno = $token->getLine(); $stream = $this->parser->getStream(); - $hookNames = $this->parser->getExpressionParser()->parseMultitargetExpression(); + $hookNames = $this->parser->getExpressionParser()->parseExpression(); $variables = null; if ($stream->nextIf(Token::NAME_TYPE, 'with')) { diff --git a/src/TwigHooks/tests/Functional/.application/templates/parsing_hook_tag_test/multiple_hook_names.html.twig b/src/TwigHooks/tests/Functional/.application/templates/parsing_hook_tag_test/multiple_hook_names.html.twig new file mode 100644 index 00000000..1e594845 --- /dev/null +++ b/src/TwigHooks/tests/Functional/.application/templates/parsing_hook_tag_test/multiple_hook_names.html.twig @@ -0,0 +1 @@ +{% hook ['some_hook', 'another_hook'] %} diff --git a/src/TwigHooks/tests/Functional/.application/templates/parsing_hook_tag_test/single_hook_name.html.twig b/src/TwigHooks/tests/Functional/.application/templates/parsing_hook_tag_test/single_hook_name.html.twig new file mode 100644 index 00000000..e6aeb88d --- /dev/null +++ b/src/TwigHooks/tests/Functional/.application/templates/parsing_hook_tag_test/single_hook_name.html.twig @@ -0,0 +1 @@ +{% hook 'some_hook' %} diff --git a/src/TwigHooks/tests/Functional/Twig/ParsingHookTagTest.php b/src/TwigHooks/tests/Functional/Twig/ParsingHookTagTest.php new file mode 100644 index 00000000..73b20950 --- /dev/null +++ b/src/TwigHooks/tests/Functional/Twig/ParsingHookTagTest.php @@ -0,0 +1,46 @@ +assertSame( + << + + + EXPECTED, + $this->render('parsing_hook_tag_test/single_hook_name.html.twig'), + ); + } + + public function testItRendersMultipleHookNames(): void + { + $this->assertSame( + << + + + EXPECTED, + $this->render('parsing_hook_tag_test/multiple_hook_names.html.twig'), + ); + } + + private function render(string $path): string + { + /** @var Twig $twig */ + $twig = $this->getContainer()->get('twig'); + + return $twig->render($path); + } +} diff --git a/src/TwigHooks/tests/Integration/Twig/Runtime/HooksRuntimeTest.php b/src/TwigHooks/tests/Integration/Twig/Runtime/HooksRuntimeTest.php index cf0fd594..bb42e46c 100644 --- a/src/TwigHooks/tests/Integration/Twig/Runtime/HooksRuntimeTest.php +++ b/src/TwigHooks/tests/Integration/Twig/Runtime/HooksRuntimeTest.php @@ -7,6 +7,9 @@ use Sylius\TwigHooks\Twig\Runtime\HooksRuntime; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; +/** + * @group kernel-required + */ final class HooksRuntimeTest extends KernelTestCase { /**