Skip to content

Commit

Permalink
Merge pull request #380 from CPS-IT/feature/1.x/handlebars-layout-name
Browse files Browse the repository at this point in the history
[!!!][FEATURE] Migrate handlebars layout action mode to enum
  • Loading branch information
eliashaeussler authored Jan 7, 2025
2 parents cdbb2ff + 2a5e0b6 commit 930c27c
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 84 deletions.
8 changes: 4 additions & 4 deletions Classes/Renderer/Component/Layout/HandlebarsLayout.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
55 changes: 10 additions & 45 deletions Classes/Renderer/Component/Layout/HandlebarsLayoutAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

namespace Fr\Typo3Handlebars\Renderer\Component\Layout;

use Fr\Typo3Handlebars\Exception;
use Fr\Typo3Handlebars\Renderer;

/**
Expand All @@ -32,61 +31,27 @@
* @author Elias Häußler <e.haeussler@familie-redlich.de>
* @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;
}
}
42 changes: 42 additions & 0 deletions Classes/Renderer/Component/Layout/HandlebarsLayoutActionMode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

/*
* This file is part of the TYPO3 CMS extension "handlebars".
*
* Copyright (C) 2025 Elias Häußler <e.haeussler@familie-redlich.de>
*
* 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 <https://www.gnu.org/licenses/>.
*/

namespace Fr\Typo3Handlebars\Renderer\Component\Layout;

/**
* HandlebarsLayoutActionMode
*
* @author Elias Häußler <e.haeussler@familie-redlich.de>
* @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));
}
}
13 changes: 10 additions & 3 deletions Classes/Renderer/Helper/ContentHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);

Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, array{Src\Renderer\Component\Layout\HandlebarsLayoutAction::*, string}>
* @return \Generator<string, array{Src\Renderer\Component\Layout\HandlebarsLayoutActionMode, string}>
*/
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'];
}
}
53 changes: 31 additions & 22 deletions Tests/Unit/Renderer/Component/Layout/HandlebarsLayoutTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,30 +37,16 @@
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;

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]
Expand All @@ -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(),
Expand All @@ -95,19 +83,22 @@ 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()));
}

#[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'));
}

Expand All @@ -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,
),
);
}
}

0 comments on commit 930c27c

Please sign in to comment.