For coders TYPO3 Tech Corner

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

Kennst du das: Immer nur schnell schnell?

Wie wäre es einmal mit Zeit und Respekt für Codequalität? Arbeiten im Team? Automatisierte Tests?

Komm zu uns

SQL: Zeige alle Tabellen absteigend nach Größe sortiert

Ich brauche in letzter Zeit häufiger den SQL-Befehl, um herauszufinden, welche Tabellen in der TYPO3-Datenbank am größten sind. Ich habe das Snippet einmal veröffentlicht.

Zum Beitrag

TYPO3 12 mit CKEditor 5: Stile als Einfachauswahl

Wenn man im RTE in TYPO3 einen Link setzt, kann es sein, dass man zwischen verschiedenen Link-Klassen auswählen muss, um beispielsweise Buttons im Frontend zu erzeugen. Neu ist in TYPO3 12 dass man...

Zum Beitrag

Null-Safe Operator im TYPO3-Bereich

Spätestens mit dem Einzug von PHP8 kann es an vielen Stellen zu Problemen mit undefinierten Arrays oder Variablen im Allgemeinen kommen. Hier ein paar Beispiele und einfache Lösung dafür.

Zum Beitrag

Die ersten/letzten Zeilen einer (SQL)-Datei löschen

Zu den nachfolgenden Befehlen gibt es eigentlich nicht viel zu sagen. Manchmal kann es nützlich sein, die ersten (bzw. letzten) X Zeilen aus einer Datei zu löschen. Und wenn die Datei zu groß zum...

Zum Beitrag

b13/container: Kindelemente in der Bearbeitungsansicht hinzufügen und ändern

Anders als in gridelements kann man in der Extension Container von B13 die Kindelemente nicht verwalten, wenn man den Container in der Bearbeitungsansicht öffnet. Wie man das schnell selber einbauen...

Zum Beitrag

Menü-Vergleich: Zahlen, Zahlen, Zahlen

Zum Beitrag