TemplateResolver 

Implement the \CPSIT\Typo3Handlebars\Renderer\Template\TemplateResolver interface to change how template and partial names are resolved to absolute file paths — for example to support a different directory layout, an additional file extension, or a database-driven path lookup.

The extension ships two implementations: \CPSIT\Typo3Handlebars\Renderer\Template\FlatTemplateResolver (the default) and \CPSIT\Typo3Handlebars\Renderer\Template\HandlebarsTemplateResolver .

\CPSIT\Typo3Handlebars\Renderer\Template\BaseTemplateResolver implements supports() and provides protected helpers for normalizing root paths and resolving filenames with EXT: syntax. Extending it keeps implementations concise.

interface TemplateResolver
Fully qualified name
\CPSIT\Typo3Handlebars\Renderer\Template\TemplateResolver
supports(string $fileExtension)

Return true if this resolver handles the given file extension.

param string $fileExtension

File extension without leading dot.

returntype

bool

resolveTemplatePath(string $templatePath, ?string $format = null)

Resolve a template name or relative path to its absolute file path.

param string $templatePath

Template name or relative path.

param string|null $format

Optional file extension override.

returntype

string

resolvePartialPath(string $partialPath, ?string $format = null)

Resolve a partial name or relative path to its absolute file path.

param string $partialPath

Partial name or relative path.

param string|null $format

Optional file extension override.

returntype

string

FlatTemplateResolver 

FlatTemplateResolver is the default implementation. It scans all configured root paths recursively and builds an in-memory map of every template file, keyed by its bare filename (without directory). A lookup therefore succeeds regardless of where in the directory tree the file lives.

Template and partial names must be prefixed with @ to trigger flat resolution, optionally with a --<variant> suffix that falls back to the base name (see Referencing templates and partials for usage). A name without the prefix is passed directly to HandlebarsTemplateResolver (see below).

When the same filename exists under multiple root paths, the higher-priority root path wins (see Template paths). Within a single root path, files are sorted by name and the first occurrence is used, matching Fractal's uniqueness guarantee.

HandlebarsTemplateResolver 

HandlebarsTemplateResolver resolves template and partial names as paths relative to the configured root paths. Given the name Blog/List, it searches each root path (highest priority first) for a matching file — for example Blog/List.hbs.

This resolver is used as the fallback inside FlatTemplateResolver for any name that does not start with @, so both resolution strategies are active at the same time.

Example implementation 

EXT:my_extension/Classes/Renderer/Template/MyTemplateResolver.php
namespace Vendor\Extension\Renderer\Template;

use CPSIT\Typo3Handlebars\Exception;
use CPSIT\Typo3Handlebars\Renderer\Template\BaseTemplateResolver;
use CPSIT\Typo3Handlebars\Renderer\Template\TemplatePaths;

final readonly class MyTemplateResolver extends BaseTemplateResolver
{
    public function __construct(
        private TemplatePaths $templatePaths,
    ) {}

    public function resolveTemplatePath(string $templatePath, ?string $format = null): string
    {
        [$templateRootPaths] = $this->resolveTemplatePaths($this->templatePaths);

        foreach (array_reverse($templateRootPaths) as $rootPath) {
            $filename = $this->resolveFilename($templatePath, $rootPath, $format ?? 'hbs');

            if (is_file($filename)) {
                return $filename;
            }
        }

        throw new Exception\TemplatePathIsNotResolvable($templatePath);
    }

    public function resolvePartialPath(string $partialPath, ?string $format = null): string
    {
        [, $partialRootPaths] = $this->resolveTemplatePaths($this->templatePaths);

        foreach (array_reverse($partialRootPaths) as $rootPath) {
            $filename = $this->resolveFilename($partialPath, $rootPath, $format ?? 'hbs');

            if (is_file($filename)) {
                return $filename;
            }
        }

        throw new Exception\PartialPathIsNotResolvable($partialPath);
    }
}
Copied!

Wiring the implementation 

Register the custom resolver as the implementation of the TemplateResolver interface in your extension's Services.yaml:

Configuration/Services.yaml
services:
  CPSIT\Typo3Handlebars\Renderer\Template\TemplateResolver:
    alias: Vendor\Extension\Renderer\Template\MyTemplateResolver
Copied!