For coders TYPO3 Tech Corner

[TYPO3] Set tt_content.layout and .frame_class options dynamically

[TYPO3] Set tt_content.layout and .frame_class options dynamically

With the help of the fields tt_content.layout and tt_content.frame_class you can influence the appearance of content elements and plugins in the frontend. But maybe the list of options in the TYPO3 backend should adapt to the settings made previously? After all, we don't want to burden the editors with non-working options. If you are looking for something like this, we may have just the thing for you.

How you can easily change the options via Page TSconfig - also depending on the CType, is well described in the TYPO3 documentation - e.g .:

TCEFORM { tt_content { layout { removeItems = 0,1,2,3 types { # Change labels for CType textpic textpic { addItems { 10 = Red 20 = Blue } } # Change labels for CType textmedia textmedia { removeItems = 1,2 altLabels { 0 = Standard 1 = Pink } } } } } }

Tip: Instead of entering the labels hardcoded, you can also use the LLL syntax in TYPO3 to offer your editors localized options.

ItemsProcFunc

If this is no longer sufficient (with or without conditions) and you want to influence which options are displayed depending on several factors, you can get itemsProcFunc for help. To do this, you have to call up one or more itemsProcFunc in the file Configuration/TCA/Overrides/tt_content.php in your site package in order to limit the selection list as you wish. In this example for the fields layout and frame_class:

$GLOBALS['TCA']['tt_content']['columns']['layout']['config']['itemsProcFunc'] = \Vendor\Sitepackage\Tca\TtContentLayoutOptions::class . '->addOptions'; $GLOBALS['TCA']['tt_content']['columns']['frame_class']['config']['itemsProcFunc'] = \Vendor\Sitepackage\Tca\TtContentLayoutOptions::class . '->addOptions';

The UserFunc for this can then look like this, for example:

<?php declare(strict_types=1); namespace Vendor\Sitepackage\Tca; use Vendor\Sitepackage\Utility\BackendUtility; /** * Class TtContentLayoutOptions * to show field options of tt_content.layout and .frame_class when some conditions are fitting */ class TtContentLayoutOptions { /** * @var array */ protected $mapping = [ 'layout' => [ [ 'conditions' => [ 'fields' => [ 'CType' => [ 'textpic' ] ] ], 'options' => [ [ 'weiß', '0' ], [ 'Box mit Bild', 'box-picture', ], ], ], [ 'conditions' => [ 'fields' => [ 'CType' => [ 'gridelements_pi1' ], 'tx_gridelements_backend_layout' => [ 'one-column' ] ] ], 'options' => [ [ 'Weiß', '10' ], [ 'Grau', '20', ], ], ], [ 'conditions' => [ 'fields' => [ 'CType' => [ 'list' ], 'list_type' => [ 'news_pi1' ] ] ], 'options' => [ [ 'Einzelansicht', '1000' ], [ 'Liste - 100%', '100', ], ], ] ], 'frame_class' => [ [ 'conditions' => [ 'fields' => [ 'CType' => [ 'div' ] ] ], 'options' => [ [ 'Standard', '0' ], [ 'Trenner Grau', 'divider-grey', ], ], ], [ 'conditions' => [ 'fields' => [ 'CType' => [ 'textpic' ], 'layout' => [ 'box-picture' ] ] ], 'options' => [ [ 'Graue Box mit Bild oben', 'grey-box-imagetop', ], [ 'Graue Box mit Bild unten', 'grey-box-imagebottom', ], ], ], [ 'conditions' => [ 'fields' => [ 'CType' => [ 'textpic' ], 'layout' => [ 'colorvariants' ] ] ], 'options' => [ [ 'Grauer Hintergrund', 'components', ], [ 'Roter Hintergrund', 'primary-1', ], ], ], [ 'conditions' => [ 'fields' => [ 'CType' => [ 'textpic' ], 'layout' => [ 'colorvariants' ] ], 'functions' => [ 'isSuperEditorOrAdminCondition' ] ], 'options' => [ [ 'Hellblauer Hintergrund', 'info' ], [ 'Hellblauer Rahmen', 'outline-info' ] ] ], [ 'conditions' => [ 'fields' => [ 'CType' => [ 'textpic' ], 'layout' => [ 'box-overlay' ] ], ], 'options' => [ [ 'LLL:EXT:sitepackage/Resources/Private/Language/Backend/locallang.xlf:' . 'tt_content.frame_class.box-overlay-bright', 'box-overlay-bright' ], [ 'LLL:EXT:sitepackage/Resources/Private/Language/Backend/locallang.xlf:' . 'tt_content.frame_class.box-overlay-dark', 'box-overlay-dark' ], ] ], [ 'conditions' => [ 'fields' => [ 'CType' => [ 'list' ], 'list_type' => [ 'news_pi1' ], 'layout' => [ '66', '444', '100' ] ], ], 'options' => [ [ 'Standard', '1' ], [ 'Standard mit Bild', '14' ], ] ], ] ]; /** * Values of tt_content.* * * @var array */ protected $properties = []; /** * Options like * [ * [ * 'label 1', * 'value 1' * ], * [ * 'label 2', * 'value 2' * ] * ] * * @var array */ protected $items = []; /** * Current field where userFunc was added (e.g. "layout" or "frame_class") * * @var string */ protected $field = ''; /** * @param array $params * @return void */ protected function initialize(array &$params): void { $this->properties = $params['row']; if (is_array($this->properties['CType'])) { $this->properties['CType'] = $this->properties['CType'][0]; } if (is_array($this->properties['layout'])) { $this->properties['layout'] = $this->properties['layout'][0]; } if (is_array($this->properties['frame_class'])) { $this->properties['frame_class'] = $this->properties['frame_class'][0]; } $this->items = &$params['items']; $this->items = []; $this->field = $params['field']; } /** * @param array $params * @return void */ public function addOptions(array &$params): void { $this->initialize($params); $this->setOptions(); } /** * @return void */ protected function setOptions(): void { foreach ($this->mapping[$this->field] as $configuration) { if ($this->isConditionMatching($configuration['conditions'])) { $this->items = array_merge($this->items, $configuration['options']); } } } /** * @param array $conditions * @return bool */ protected function isConditionMatching(array $conditions): bool { if (isset($conditions['fields'])) { foreach ($conditions['fields'] as $startField => $compareFields) { if (in_array($this->properties[$startField], $compareFields) === false) { return false; } } } if (isset($conditions['functions'])) { foreach ($conditions['functions'] as $function) { if ($this->{$function}() === false) { return false; } } } return true; } /** * @return bool * @noinspection PhpUnused */ protected function isSuperEditorOrAdminCondition(): bool { return BackendUtility::isAdministrator() || BackendUtility::isSuperEditor(); } }

The mapping property defines which options are to be output per field. With the help of the key conditions you can define when these options should be displayed.

Note: We have no longer added the isAdministrator() and isSuperEditor() functions here. You can do this yourself very quickly by accessing $GLOBALS['BE_USER'].

"Code faster, look at the time" - does this sound familiar to you?

How about time and respect for code quality? Working in a team? Automated tests?

Join us

SQL: Show all tables sorted by size in descending order

Lately I've been using the SQL command more often to find out which tables in the TYPO3 database are the largest. I've published the snippet once.

Go to news

TYPO3 12 with CKEditor 5: Styles in a single selection

If you set a link in the RTE in TYPO3, you may have to choose between different link classes, for example to create buttons in the frontend. What's new in TYPO3 12 is that you can select not just one...

Go to news

Null-Safe Operator in the TYPO3 area

With the introduction of PHP8, problems with undefined arrays or variables in general can arise in many places. Here are a few examples and simple solutions.

Go to news

Delete the first/last lines of a (SQL) file

There isn't much to say about the following commands. Sometimes it can be useful to delete the first (or last) X lines from a file. And if the file is too large to open with a conventional program, a...

Go to news

b13/container: Add and modify child elements in edit view

Unlike gridelements, you cannot manage the child elements in the B13 Container extension when you open the container in the editing view. I would be happy to show you how you can quickly install this...

Go to news

Menu comparison: Numbers, numbers, numbers

Go to news