From 2a5e0b6d417593a368730587532409a55236dc33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20H=C3=A4u=C3=9Fler?= Date: Tue, 7 Jan 2025 09:19:04 +0100 Subject: [PATCH] [!!!][FEATURE] Migrate handlebars layout action mode to enum --- .../Component/Layout/HandlebarsLayout.php | 8 +-- .../Layout/HandlebarsLayoutAction.php | 55 ++++--------------- .../Layout/HandlebarsLayoutActionMode.php | 42 ++++++++++++++ Classes/Renderer/Helper/ContentHelper.php | 13 ++++- .../Layout/HandlebarsLayoutActionTest.php | 19 +++---- .../Component/Layout/HandlebarsLayoutTest.php | 53 ++++++++++-------- 6 files changed, 106 insertions(+), 84 deletions(-) create mode 100644 Classes/Renderer/Component/Layout/HandlebarsLayoutActionMode.php diff --git a/Classes/Renderer/Component/Layout/HandlebarsLayout.php b/Classes/Renderer/Component/Layout/HandlebarsLayout.php index eb1fc205..8cc07422 100644 --- a/Classes/Renderer/Component/Layout/HandlebarsLayout.php +++ b/Classes/Renderer/Component/Layout/HandlebarsLayout.php @@ -51,11 +51,11 @@ public function parse(): void ($this->parseFunction)(); } - public function addAction(string $name, HandlebarsLayoutAction $action): void + public function addAction(HandlebarsLayoutAction $action): void { - if (!isset($this->actions[$name])) { - $this->actions[$name] = []; - } + $name = $action->getName(); + + $this->actions[$name] ??= []; $this->actions[$name][] = $action; } diff --git a/Classes/Renderer/Component/Layout/HandlebarsLayoutAction.php b/Classes/Renderer/Component/Layout/HandlebarsLayoutAction.php index 4ddba0bc..ceb95824 100644 --- a/Classes/Renderer/Component/Layout/HandlebarsLayoutAction.php +++ b/Classes/Renderer/Component/Layout/HandlebarsLayoutAction.php @@ -23,7 +23,6 @@ namespace Fr\Typo3Handlebars\Renderer\Component\Layout; -use Fr\Typo3Handlebars\Exception; use Fr\Typo3Handlebars\Renderer; /** @@ -32,61 +31,27 @@ * @author Elias Häußler * @license GPL-2.0-or-later */ -class HandlebarsLayoutAction +final readonly class HandlebarsLayoutAction { - public const REPLACE = 'replace'; - public const APPEND = 'append'; - public const PREPEND = 'prepend'; - - protected readonly string $mode; - - /** - * @throws Exception\UnsupportedTypeException - */ public function __construct( - protected readonly Renderer\Helper\Context\HelperContext $context, - string $mode = self::REPLACE, - ) { - $this->mode = strtolower($mode); - $this->validate(); - } + private string $name, + private Renderer\Helper\Context\HelperContext $context, + private HandlebarsLayoutActionMode $mode = HandlebarsLayoutActionMode::Replace, + ) {} - /** - * @param string $value - * @return string - * @throws Exception\UnsupportedTypeException - */ public function render(string $value): string { $renderResult = $this->context->renderChildren($this->context->renderingContext); return match ($this->mode) { - self::APPEND => $value . $renderResult, - self::PREPEND => $renderResult . $value, - self::REPLACE => $renderResult, - default => throw Exception\UnsupportedTypeException::create($this->mode), + HandlebarsLayoutActionMode::Append => $value . $renderResult, + HandlebarsLayoutActionMode::Prepend => $renderResult . $value, + HandlebarsLayoutActionMode::Replace => $renderResult, }; } - /** - * @return string[] - */ - protected function getSupportedModes(): array - { - return [ - self::REPLACE, - self::APPEND, - self::PREPEND, - ]; - } - - /** - * @throws Exception\UnsupportedTypeException - */ - protected function validate(): void + public function getName(): string { - if (!\in_array($this->mode, $this->getSupportedModes(), true)) { - throw Exception\UnsupportedTypeException::create($this->mode); - } + return $this->name; } } diff --git a/Classes/Renderer/Component/Layout/HandlebarsLayoutActionMode.php b/Classes/Renderer/Component/Layout/HandlebarsLayoutActionMode.php new file mode 100644 index 00000000..abf94a07 --- /dev/null +++ b/Classes/Renderer/Component/Layout/HandlebarsLayoutActionMode.php @@ -0,0 +1,42 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +namespace Fr\Typo3Handlebars\Renderer\Component\Layout; + +/** + * HandlebarsLayoutActionMode + * + * @author Elias Häußler + * @license GPL-2.0-or-later + */ +enum HandlebarsLayoutActionMode: string +{ + case Append = 'append'; + case Replace = 'replace'; + case Prepend = 'prepend'; + + public static function tryFromCaseInsensitive(string $mode): ?self + { + return self::tryFrom(\strtolower($mode)); + } +} diff --git a/Classes/Renderer/Helper/ContentHelper.php b/Classes/Renderer/Helper/ContentHelper.php index 210503fa..4252c964 100644 --- a/Classes/Renderer/Helper/ContentHelper.php +++ b/Classes/Renderer/Helper/ContentHelper.php @@ -44,7 +44,6 @@ public function __construct( public function render(Context\HelperContext $context): ?bool { $name = $context[0]; - $mode = $context['mode'] ?? Renderer\Component\Layout\HandlebarsLayoutAction::REPLACE; $layoutStack = $this->getLayoutStack($context); // Early return if "content" helper is requested outside of an "extend" helper block @@ -57,6 +56,14 @@ public function render(Context\HelperContext $context): ?bool return $context->isBlockHelper() ? null : false; } + // Get layout action mode + if (isset($context['mode'])) { + $mode = Renderer\Component\Layout\HandlebarsLayoutActionMode::tryFromCaseInsensitive($context['mode']) + ?? Renderer\Component\Layout\HandlebarsLayoutActionMode::Replace; + } else { + $mode = Renderer\Component\Layout\HandlebarsLayoutActionMode::Replace; + } + // Get upper layout from stack $layout = end($layoutStack); @@ -70,8 +77,8 @@ public function render(Context\HelperContext $context): ?bool } // Add concrete action for the requested block - $action = new Renderer\Component\Layout\HandlebarsLayoutAction($context, $mode); - $layout->addAction($name, $action); + $action = new Renderer\Component\Layout\HandlebarsLayoutAction($name, $context, $mode); + $layout->addAction($action); // This helper does not return any content, it's just here to register layout actions return null; diff --git a/Tests/Unit/Renderer/Component/Layout/HandlebarsLayoutActionTest.php b/Tests/Unit/Renderer/Component/Layout/HandlebarsLayoutActionTest.php index 49c6c705..4d4bf81e 100644 --- a/Tests/Unit/Renderer/Component/Layout/HandlebarsLayoutActionTest.php +++ b/Tests/Unit/Renderer/Component/Layout/HandlebarsLayoutActionTest.php @@ -56,25 +56,24 @@ public function setUp(): void ); } - /** - * @param Src\Renderer\Component\Layout\HandlebarsLayoutAction::* $mode - */ #[Framework\Attributes\Test] #[Framework\Attributes\DataProvider('renderReturnsProcessedValueDataProvider')] - public function renderReturnsProcessedValue(string $mode, string $expected): void - { - $subject = new Src\Renderer\Component\Layout\HandlebarsLayoutAction($this->context, $mode); + public function renderReturnsProcessedValue( + Src\Renderer\Component\Layout\HandlebarsLayoutActionMode $mode, + string $expected, + ): void { + $subject = new Src\Renderer\Component\Layout\HandlebarsLayoutAction('foo', $this->context, $mode); self::assertSame($expected, $subject->render('foo')); } /** - * @return \Generator + * @return \Generator */ public static function renderReturnsProcessedValueDataProvider(): \Generator { - yield 'replace' => [Src\Renderer\Component\Layout\HandlebarsLayoutAction::REPLACE, 'baz']; - yield 'append' => [Src\Renderer\Component\Layout\HandlebarsLayoutAction::APPEND, 'foobaz']; - yield 'prepend' => [Src\Renderer\Component\Layout\HandlebarsLayoutAction::PREPEND, 'bazfoo']; + yield 'append' => [Src\Renderer\Component\Layout\HandlebarsLayoutActionMode::Append, 'foobaz']; + yield 'prepend' => [Src\Renderer\Component\Layout\HandlebarsLayoutActionMode::Prepend, 'bazfoo']; + yield 'replace' => [Src\Renderer\Component\Layout\HandlebarsLayoutActionMode::Replace, 'baz']; } } diff --git a/Tests/Unit/Renderer/Component/Layout/HandlebarsLayoutTest.php b/Tests/Unit/Renderer/Component/Layout/HandlebarsLayoutTest.php index bd807756..e811cd66 100644 --- a/Tests/Unit/Renderer/Component/Layout/HandlebarsLayoutTest.php +++ b/Tests/Unit/Renderer/Component/Layout/HandlebarsLayoutTest.php @@ -37,7 +37,6 @@ final class HandlebarsLayoutTest extends TestingFramework\Core\Unit\UnitTestCase { private Src\Renderer\Component\Layout\HandlebarsLayout $subject; - private Src\Renderer\Component\Layout\HandlebarsLayoutAction $action; private bool $parseFunctionInvoked = false; @@ -45,22 +44,9 @@ public function setUp(): void { parent::setUp(); - $stack = []; - $renderingContext = []; - $data = []; - $this->subject = new Src\Renderer\Component\Layout\HandlebarsLayout( fn() => $this->parseFunctionInvoked = true, ); - $this->action = new Src\Renderer\Component\Layout\HandlebarsLayoutAction( - new Src\Renderer\Helper\Context\HelperContext( - [], - [], - new Src\Renderer\Helper\Context\RenderingContextStack($stack), - $renderingContext, - $data, - ), - ); } #[Framework\Attributes\Test] @@ -80,12 +66,14 @@ public function addActionRegistersGivenAction(): void { self::assertSame([], $this->subject->getActions()); - $this->subject->addAction('foo', $this->action); + $action = $this->createAction('foo'); + + $this->subject->addAction($action); self::assertSame( [ 'foo' => [ - $this->action, + $action, ], ], $this->subject->getActions(), @@ -95,8 +83,8 @@ public function addActionRegistersGivenAction(): void #[Framework\Attributes\Test] public function getActionsReturnsAllRegisteredActions(): void { - $this->subject->addAction('foo', $this->action); - $this->subject->addAction('baz', $this->action); + $this->subject->addAction($this->createAction('foo')); + $this->subject->addAction($this->createAction('baz')); self::assertSame(['foo', 'baz'], \array_keys($this->subject->getActions())); } @@ -104,10 +92,13 @@ public function getActionsReturnsAllRegisteredActions(): void #[Framework\Attributes\Test] public function getActionsReturnsRegisteredActionsByGivenName(): void { - $this->subject->addAction('foo', $this->action); - $this->subject->addAction('baz', $this->action); + $fooAction = $this->createAction('foo'); + $bazAction = $this->createAction('baz'); + + $this->subject->addAction($fooAction); + $this->subject->addAction($bazAction); - self::assertSame([$this->action], $this->subject->getActions('foo')); + self::assertSame([$fooAction], $this->subject->getActions('foo')); self::assertSame([], $this->subject->getActions('missing')); } @@ -116,8 +107,26 @@ public function hasActionReturnsTrueIfActionOfGivenNameWasRegistered(): void { self::assertFalse($this->subject->hasAction('foo')); - $this->subject->addAction('foo', $this->action); + $this->subject->addAction($this->createAction('foo')); self::assertTrue($this->subject->hasAction('foo')); } + + private function createAction(string $name): Src\Renderer\Component\Layout\HandlebarsLayoutAction + { + $stack = []; + $renderingContext = []; + $data = []; + + return new Src\Renderer\Component\Layout\HandlebarsLayoutAction( + $name, + new Src\Renderer\Helper\Context\HelperContext( + [], + [], + new Src\Renderer\Helper\Context\RenderingContextStack($stack), + $renderingContext, + $data, + ), + ); + } }