DataSourceAwareProcessor 

Implement the \CPSIT\Typo3Handlebars\DataProcessing\DataSource\DataSourceAwareProcessor interface to run custom PHP logic during the preProcessing or postProcessing stages of a process-variables processor (or of HANDLEBARSTEMPLATE directly). Unlike standard TYPO3 data processors, implementations receive a DataSourceCollection that gives structured access to all four data sources available at that point in the pipeline.

interface DataSourceAwareProcessor
Fully qualified name
\CPSIT\Typo3Handlebars\DataProcessing\DataSource\DataSourceAwareProcessor
process ( array $variables, DataSourceCollection $collection, ContentObjectRenderer $contentObjectRenderer)

Process the current variable set and return the (modified) array.

param array $variables

Current template variable set.

param DataSourceCollection $collection

All four data sources for the current rendering.

param ContentObjectRenderer $contentObjectRenderer

Current content element renderer.

returntype

array

Reading from DataSourceCollection 

DataSourceCollection::resolve() searches the data sources in priority order and returns the first match. Pass a specific DataSource case to restrict the lookup:

use CPSIT\Typo3Handlebars\DataProcessing\DataSource\DataSource;

// Search all sources (highest priority first)
$table = $collection->resolve('table');

// Search only the processor configuration
$table = $collection->resolve('table', DataSource::ProcessorConfiguration);

// Search two specific sources, in the given order
$table = $collection->resolve('table', [
    DataSource::ProcessorConfiguration,
    DataSource::ContentObjectConfiguration,
]);
Copied!

The four DataSource cases mirror the processorConfiguration , processedData , contentObjectRenderer and contentObjectConfiguration identifiers described in Data sources.

The $key argument may use / to reach into a nested array within the searched source(s), e.g. $collection->resolve('some/nested/key') — see Reaching into nested keys.

By default, a key (or path segment) that cannot be found in any searched source simply yields the given $default value ( null if none is given). Pass optional: false to make resolve() throw \Exception\PathIsMissingInDataSource instead, once none of the searched sources match and no default is configured:

use CPSIT\Typo3Handlebars\Exception;

try {
    $value = $collection->resolve('some/nested/key', optional: false);
} catch (Exception\PathIsMissingInDataSource $exception) {
    // None of the searched sources had "some/nested/key"
}
Copied!

Resolving a data payload via a configurable keyword 

Processors often accept a configuration option that itself points at the payload to work with — for example, an iterable option naming the data source to iterate over (see Resolving a data payload (dataSource / data) for the full resolution rules). DataSourceProvider::provide() covers this pattern in one call: it reads the option named by its $keyword argument (default dataSource ) from DataSource::ProcessorConfiguration and resolves it. Since DataSourceAwareProcessor implementations are instantiated via GeneralUtility::makeInstance() , DataSourceProvider can be injected through the constructor like any other service:

use CPSIT\Typo3Handlebars\DataProcessing\DataSource\DataSourceProvider;
use CPSIT\Typo3Handlebars\Exception;

final readonly class MyPreProcessor implements DataSourceAwareProcessor
{
    public function __construct(
        private DataSourceProvider $dataSourceProvider,
    ) {}

    public function process(
        array $variables,
        DataSourceCollection $collection,
        ContentObjectRenderer $contentObjectRenderer,
    ): array {
        try {
            // Resolves the "iterable" processor option, e.g. "processedData:news"
            $variables['items'] = $this->dataSourceProvider->provide($collection, 'iterable');
        } catch (
            Exception\DataSourceIsNotSupported
            | Exception\DataSourceIsMissingInCollection
            | Exception\PathIsMissingInDataSource
        ) {
            // The "iterable" option is not configured, or invalid
        }

        return $variables;
    }
}
Copied!

Example implementation 

EXT:my_extension/Classes/DataProcessing/MyPreProcessor.php
namespace Vendor\Extension\DataProcessing;

use CPSIT\Typo3Handlebars\DataProcessing\DataSource\DataSource;
use CPSIT\Typo3Handlebars\DataProcessing\DataSource\DataSourceAwareProcessor;
use CPSIT\Typo3Handlebars\DataProcessing\DataSource\DataSourceCollection;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;

final readonly class MyPreProcessor implements DataSourceAwareProcessor
{
    public function process(
        array $variables,
        DataSourceCollection $collection,
        ContentObjectRenderer $contentObjectRenderer,
    ): array {
        $table = $collection->resolve('table', DataSource::ProcessorConfiguration, 'tt_content');
        $variables['tableName'] = $table;

        return $variables;
    }
}
Copied!

Registering the processor 

Reference the processor class by its fully qualified class name in preProcessing or postProcessing :

10 = process-variables
10 {
    variables {
        header = TEXT
        header.field = header
    }

    preProcessing {
        10 = Vendor\Extension\DataProcessing\MyPreProcessor
    }
}
Copied!

The numeric keys control execution order when multiple processors are registered. The class is instantiated via GeneralUtility::makeInstance() , so constructor injection works as normal.