Skip to content

Commit

Permalink
Merge pull request #382 from CPS-IT/feature/1.x/helper-registry
Browse files Browse the repository at this point in the history
[!!!][FEATURE] Introduce HelperRegistry as successor for helper trait
  • Loading branch information
eliashaeussler authored Jan 7, 2025
2 parents 312c734 + 2709935 commit 83f34e8
Show file tree
Hide file tree
Showing 18 changed files with 296 additions and 189 deletions.
61 changes: 15 additions & 46 deletions Classes/DependencyInjection/HandlebarsHelperPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,8 @@

namespace Fr\Typo3Handlebars\DependencyInjection;

use Fr\Typo3Handlebars\Renderer\HelperAwareInterface;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Fr\Typo3Handlebars\Renderer;
use Symfony\Component\DependencyInjection;

/**
* HandlebarsHelperPass
Expand All @@ -37,56 +34,28 @@
* @internal
* @codeCoverageIgnore
*/
final class HandlebarsHelperPass implements CompilerPassInterface
final readonly class HandlebarsHelperPass implements DependencyInjection\Compiler\CompilerPassInterface
{
/**
* @var Definition[]
*/
private array $rendererDefinitions = [];

public function __construct(
private readonly string $helperTagName,
private readonly string $rendererTagName,
private string $helperTagName,
) {}

public function process(ContainerBuilder $container): void
public function process(DependencyInjection\ContainerBuilder $container): void
{
$this->fetchRendererDefinitions($container);
$registryDefinition = $container->getDefinition(Renderer\Helper\HelperRegistry::class);

// Register tagged Handlebars helper at all Helper-aware renderers
foreach ($container->findTaggedServiceIds($this->helperTagName) as $serviceId => $tags) {
$container->findDefinition($serviceId)->setPublic(true);

foreach (array_filter($tags) as $attributes) {
$this->validateTag($serviceId, $attributes);
$this->registerHelper(
$attributes['identifier'],
[new Reference($serviceId), $attributes['method']]
);
}
}
}

/**
* @param array{0: string|Reference, 1: string} $callable
*/
private function registerHelper(string $name, array $callable): void
{
foreach ($this->rendererDefinitions as $rendererDefinition) {
$rendererDefinition->addMethodCall('registerHelper', [$name, $callable]);
}
}

protected function fetchRendererDefinitions(ContainerBuilder $container): void
{
$this->rendererDefinitions = [];

foreach (array_keys($container->findTaggedServiceIds($this->rendererTagName)) as $serviceId) {
$rendererDefinition = $container->findDefinition($serviceId);
$rendererClass = $rendererDefinition->getClass();

if ($rendererClass !== null && \in_array(HelperAwareInterface::class, class_implements($rendererClass) ?: [])) {
$this->rendererDefinitions[] = $rendererDefinition;
$registryDefinition->addMethodCall(
'add',
[
$attributes['identifier'],
[new DependencyInjection\Reference($serviceId), $attributes['method']],
],
);
}
}
}
Expand All @@ -99,13 +68,13 @@ private function validateTag(string $serviceId, array $tagAttributes): void
if (!\array_key_exists('identifier', $tagAttributes) || (string)$tagAttributes['identifier'] === '') {
throw new \InvalidArgumentException(
\sprintf('Service tag "%s" requires an identifier attribute to be defined, missing in: %s', $this->helperTagName, $serviceId),
1606236820
1606236820,
);
}
if (!\array_key_exists('method', $tagAttributes) || (string)$tagAttributes['method'] === '') {
throw new \InvalidArgumentException(
\sprintf('Service tag "%s" requires an method attribute to be defined, missing in: %s', $this->helperTagName, $serviceId),
1606245140
1606245140,
);
}
}
Expand Down
32 changes: 32 additions & 0 deletions Classes/Exception/Exception.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?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\Exception;

/**
* Exception
*
* @author Elias Häußler <e.haeussler@familie-redlich.de>
* @license GPL-2.0-or-later
*/
abstract class Exception extends \Exception {}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/*
* This file is part of the TYPO3 CMS extension "handlebars".
*
* Copyright (C) 2021 Elias Häußler <e.haeussler@familie-redlich.de>
* 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
Expand All @@ -21,25 +21,21 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

namespace Fr\Typo3Handlebars\Renderer;
namespace Fr\Typo3Handlebars\Exception;

/**
* HelperAwareInterface
* HelperIsNotRegistered
*
* @author Elias Häußler <e.haeussler@familie-redlich.de>
* @license GPL-2.0-or-later
*/
interface HelperAwareInterface
final class HelperIsNotRegistered extends Exception
{
/**
* Get all registered Handlebars helpers.
*
* @return array<string, callable>
*/
public function getHelpers(): array;

/**
* Register new Handlebars helper with given function.
*/
public function registerHelper(string $name, mixed $function): void;
public function __construct(string $name)
{
parent::__construct(
\sprintf('Handlebars helper "%s" is not registered.', $name),
1736242470,
);
}
}
11 changes: 5 additions & 6 deletions Classes/Renderer/HandlebarsRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
use Fr\Typo3Handlebars\Exception\InvalidTemplateFileException;
use Fr\Typo3Handlebars\Exception\TemplateCompilationException;
use Fr\Typo3Handlebars\Exception\TemplateNotFoundException;
use Fr\Typo3Handlebars\Renderer\Helper\HelperRegistry;
use Fr\Typo3Handlebars\Renderer\Template\TemplateResolverInterface;
use Fr\Typo3Handlebars\Traits\HandlebarsHelperTrait;
use LightnCandy\Context;
use LightnCandy\LightnCandy;
use LightnCandy\Partial;
Expand All @@ -52,10 +52,8 @@
*/
#[AsAlias('handlebars.renderer')]
#[Autoconfigure(tags: ['handlebars.renderer'])]
class HandlebarsRenderer implements RendererInterface, HelperAwareInterface
class HandlebarsRenderer implements RendererInterface
{
use HandlebarsHelperTrait;

protected readonly bool $debugMode;

/**
Expand All @@ -65,6 +63,7 @@ public function __construct(
#[Autowire('@handlebars.cache')]
protected readonly CacheInterface $cache,
protected readonly EventDispatcherInterface $eventDispatcher,
protected readonly HelperRegistry $helperRegistry,
protected readonly LoggerInterface $logger,
#[Autowire('@handlebars.template_resolver')]
protected readonly TemplateResolverInterface $templateResolver,
Expand Down Expand Up @@ -122,7 +121,7 @@ protected function processRendering(string $templatePath, array $data): string
// Render content
$content = $renderer($beforeRenderingEvent->getData(), [
'debug' => Runtime::DEBUG_TAGS_HTML,
'helpers' => $this->helpers,
'helpers' => $this->helperRegistry->getAll(),
]);

// Dispatch after rendering event
Expand Down Expand Up @@ -235,7 +234,7 @@ protected function prepareCompileResult(string $compileResult): callable
*/
protected function getHelperStubs(): array
{
return array_fill_keys(array_keys($this->helpers), true);
return array_fill_keys(array_keys($this->helperRegistry->getAll()), true);
}

/**
Expand Down
Loading

0 comments on commit 83f34e8

Please sign in to comment.