[TYPO3] tt_content.layout und .frame_class Optionen dynamisch setzen

[TYPO3] tt_content.layout und .frame_class Optionen dynamisch setzen

Mit Hilfe der Felder tt_content.layout und tt_content.frame_class kann man das Aussehen von Inhaltselementen und Plugins im Frontend beeinflussen. Aber vielleicht soll sich die Liste der Optionen im Backend von TYPO3 an zuvor gemachte Einstellungen anpassen? Schließlich wollen wir die Redakteure nicht auch noch mit nicht-funktionierenden Optionen belasten. Falls ihr so etwas sucht, haben wir vielleicht genau das Richtige für euch.

Wie ihr die Optionen einfach per Page TSconfig verändern könnt - auch je nach CType, ist gut in der TYPO3 Dokumentation beschrieben - z.B.:
 

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 } } } } } }

Tipp: Statt die Labels hardcoded einzutragen, könnt ihr auch die LLL-Syntax in TYPO3 nutzen, um euren Redakteuren lokalisierte Optionen anzubieten.

ItemsProcFunc

Wenn dies (mit oder ohne Conditions) aber einmal nicht mehr ausreicht, und ihr wollt abhängig von mehreren Faktoren beeinflussen, welche Optionen angezeigt werden, könnt ihr itemsProcFunc zur Hilfe holen. Dazu müsst ihr in eurem Sitepackage in der Datei Configuration/TCA/Overrides/tt_content.php eine oder mehrere itemsProcFunc aufrufen, um die Auswahlliste beliebig einzuschränken. In diesem Beispiel eben für die Felder layout und 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';

Die UserFunc hierzu kann dann beispielsweise so aussehen:

<?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(); } }

Über die Eigenschaft mapping wird definiert welche Optionen pro Feld ausgegeben werden sollen. Mit Hilfe des Keys conditions kann man definieren, wann diese Optionen ausgespielt werden sollen.

Hinweis: Die Funktionen isAdministrator() und isSuperEditor() haben wir hier nicht mehr beigefügt. Dies lässt sich aber mit dem Zugriff auf $GLOBALS['BE_USER'] ganz schnell selber umsetzen.

TYPO3: Finding pages in mixed mode

In TYPO3, Mixed Mode refers to translated pages that contain content only partially related to the corresponding content in the main language. This is indicated in the backend by an error message. But...

Zum Beitrag

Extbase Extensions: Think extensibility with data, site and language

Today, I have a small request for the TYPO3 extension authors out there: Make sure your extensions are extensible. This will also promote the distribution of the corresponding plugins.

Zum Beitrag

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.

Zum Beitrag

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...

Zum Beitrag

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.

Zum Beitrag

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...

Zum Beitrag