Custom data processors
When there is no suitable data processor that
prepares the variables needed for your content element or template, you can
define a custom data processor by implementing
\TYPO3\
.
You can find the example below in the TYPO3 Documentation Team extension EXT:examples.
Using a custom data processor in TypoScript
The data processor can be configured through a TypoScript setup configuration. A custom data processor can be used in the definition of a "new custom content element" as follows:
tt_content {
examples_dataproccustom =< lib.contentElement
examples_dataproccustom {
templateName = DataProcCustom
# Before TYPO3 v12.1 you have to give the fully-qualified class name of the processor
# dataProcessing.10 = T3docs\Examples\DataProcessing\CustomCategoryProcessor
# Since TYPO3 v12.1 one can also use a (in Services.yaml) configured alias
dataProcessing.10 = custom-category
dataProcessing.10 {
as = categories
categoryList.field = categories
}
}
}
In the extension examples you can find the code in
EXT:
.
In the field categories
the comma-separated categories are stored.
Note
The custom data processor described here should serve as a simple example.
It can therefore only work with comma-separated values, not with an m:n
relationship as used in the field categories
of tables like
tt_
. For that, further logic would need to be implemented.
Register an alias for the data processor (optional)
New in version 12.1
Instead of using the fully-qualified class name as data processor identifier
(in the example above \T3docs\
)
you can also define a short alias in Configuration/
:
T3docs\Examples\DataProcessing\CustomCategoryProcessor:
tags:
- name: 'data.processor'
identifier: 'custom-category'
The alias custom-
can now be used as data processor identifier
like in the TypoScript example above.
Note
When registering a data processor alias please be sure you don't override an existing alias (from TYPO3 Core or a third-party extension) as this may cause errors.
Tip
It is recommended to tag custom data processors as this will
automatically add them to the internal Data
,
enabling dependency injection by default.
Otherwise, the service would need to be set public.
Note
If your data processor should not be shared then
you need to set the shared: false
tag attribute for the service.
Implementing the custom data processor
The custom data processor must implement \TYPO3\
.
The main method process
gets called with the following parameters:
Content
Object Renderer $c Obj - Receives the data of the current TypoScript context, in this case the data of the calling content element.
array $content
Object Configuration - Contains the configuration of the calling content element. In this example it is
the configuration
tt_
content. examples_ dataproccustom array $processor
Configuration - Contains the configuration of the currently called data processor. In this
example it is the value of
as
and thestd
configuration of theWrap category
List array $processed
Data - On calling, contains the processed data of all previously called data processors on this same content element. Your custom data processor also stores the variables to be sent to the Fluid template here.
This is an example implementation of a custom data processor:
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project. [...]
*/
namespace T3docs\Examples\DataProcessing;
use T3docs\Examples\Domain\Repository\CategoryRepository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface;
/**
* Class for data processing comma separated categories
*/
class CustomCategoryProcessor implements DataProcessorInterface
{
/**
* Process data for the content element "My new content element"
*
* @param ContentObjectRenderer $cObj The data of the content element or page
* @param array $contentObjectConfiguration The configuration of Content Object
* @param array $processorConfiguration The configuration of this processor
* @param array $processedData Key/value store of processed data (e.g. to be passed to a Fluid View)
* @return array the processed data as key/value store
*/
public function process(
ContentObjectRenderer $cObj,
array $contentObjectConfiguration,
array $processorConfiguration,
array $processedData
) {
if (isset($processorConfiguration['if.']) && !$cObj->checkIf($processorConfiguration['if.'])) {
return $processedData;
}
// categories by comma separated list
$categoryIdList = $cObj->stdWrapValue('categoryList', $processorConfiguration ?? []);
$categories = [];
if ($categoryIdList) {
$categoryIdList = GeneralUtility::intExplode(',', (string)$categoryIdList, true);
/** @var CategoryRepository $categoryRepository */
$categoryRepository = GeneralUtility::makeInstance(CategoryRepository::class);
foreach ($categoryIdList as $categoryId) {
$categories[] = $categoryRepository->findByUid($categoryId);
}
// set the categories into a variable, default "categories"
$targetVariableName = $cObj->stdWrapValue('as', $processorConfiguration, 'categories');
$processedData[$targetVariableName] = $categories;
}
return $processedData;
}
}
In the extension examples you can find the code in
EXT:/
.
On being called, the Custom
runs std
on the calling ContentObjectRenderer, which has the data of the table
tt_
in the calling content element.
The field category
gets configured in TypoScript as follows:
categoryList.field = categories
stdWrap fetches the value of category
from
tt_
of the currently calling content
element.
Now the custom data processor processes the comma-separated values into an array
of integers that represent uids of the table sys_
. It then
fetches the category data from the Category
by calling
find
.
The data of the category records then get stored in the desired key in the
$processed
array.
To make the data processor more configurable, we test for a TypoScript
if condition at the beginning, and name the key
we use to store the data configurable by the configuration as
.