Feature: #107889 - Introduce TCA option "itemsProcessors" 

See forge#107889

Description 

As part of centralizing and improving the processing of items for select, check, and radio type fields, a new TCA option itemsProcessors has been introduced as a replacement for itemsProcFunc. This option is an array, allowing any number of processors to be called instead of just one. Processors are ordered by their array key (numerical) and executed in that order. Processors can receive arbitrary data through the $context->processorParameters property.

All processors must implement the ItemsProcessorInterface interface.

Processor methods receive two parameters: a SelectItemCollection instance containing the items, and an ItemsProcessorContext instance providing access to table, field, row data, and configuration. The processor must return a SelectItemCollection. This means that added items can no longer be untyped arrays, making the entire process cleaner and safer.

A new Page TSconfig option is also available, mirroring the existing one for itemsProcFunc. See the example below for syntax.

Example 

The TCA registration might look like this:

EXT:my_extension/Configuration/TCA/my_table.php
 use MyVendor\MyExtension\Processors\SpecialRelationsProcessor;

'relation' => [
    'label' => 'Relational field',
    'config' => [
        'type' => 'select',
        'renderType' => 'selectSingle',
        'items' => [
            [
                'value' => 0,
                'label' => '',
            ],
        ],
        'foreign_table' => 'some_foreign_table',
        'itemsProcessors' => [
            100 => [
                'class' => SpecialRelationsProcessor::class,
                'parameters' => [
                    'foo' => 'bar',
                ],
            ],
            50 => [
                'class' => SpecialRelationsProcessor2::class,
            ],
        ],
    ],
],
Copied!

In this example, SpecialRelationsProcessor2 will be called before SpecialRelationsProcessor.

Here is an example processor:

EXT:my_extension/Classes/Processors/SpecialRelationsProcessor.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Processors;

use TYPO3\CMS\Core\DataHandling\ItemsProcessorContext;
use TYPO3\CMS\Core\DataHandling\ItemsProcessorInterface;
use TYPO3\CMS\Core\Schema\Struct\SelectItem;
use TYPO3\CMS\Core\Schema\Struct\SelectItemCollection;

final class SpecialRelationsProcessor implements ItemsProcessorInterface
{
    public function processItems(
        SelectItemCollection $items,
        ItemsProcessorContext $context,
    ): SelectItemCollection {
        $items->add(
            new SelectItem(
                type: 'select',
                label: 'Extra item',
                value: 42,
            )
        );

        return $items;
    }
}
Copied!

The $context->processorParameters property contains any parameters defined in the TCA declaration.

Using Page TSconfig to pass custom parameters to the processor would look like this:

TCEFORM.example_table.content.itemsProcessors.100.foo = bar
Copied!

Note that the numerical key of the processor must be reused. With this setup, the class SpecialRelationsProcessor receives the PHP array ['foo' => 'bar'] in the $context->fieldTSconfig property. The class SpecialRelationsProcessor2 receives an empty array [] (since it is registered with the key 50).

Registration of processors is also possible within FlexForms:

EXT:my_package/Configuration/FlexForms/SomeForm.xml
<some_selector>
    <label>Choice</label>
    <config>
        <type>select</type>
        <renderType>selectSingle</renderType>
        <itemsProcessors>
            <numIndex index="100">
                <class>MyVendor\MyPackage\Processors\SpecialRelationsProcessor</class>
            </numIndex>
        </itemsProcessors>
    </config>
</some_selector>
Copied!

Impact 

It is still possible to use itemsProcFunc, but switching to itemsProcessors is recommended because it offers two main advantages:

  • Being an array, it allows extensions to add processors on top of existing ones and to define their execution order.
  • The processing chain is strictly typed, ensuring safer and more reliable code.

If both itemsProcFunc and itemsProcessors are defined, both are executed, with itemsProcFunc executed first.