Generell muss man verstehen, dass wir bei in2code TYPO3 immer nur mit funktionalen und benötigten Feldern an die Kunden ausliefern. Das bedeutet, dass Einstellungen, die keine Funktion beinhalten oder dass ungetestete und unbenötigte Einstellungen (TYPO3 und Extensions) von uns für alle Backend Benutzer (auch für Administratoren) ausgeblendet werden. Dies erhöht die Übersichtlichkeit und Usability des zu verwaltenden Content Management Systems.
1. Generelles zum Thema displayCond und FlexForm in TYPO3
Die Definition von FlexForm ist im Prinzip identisch mit der Definition von Feldern mittels TCA. Aber während es sich beim einen um eine PHP-Schreibweise handelt, handelt es sich beim anderen um eine XML-Schreibweise. Mit Hilfe der Eigenschaft displayCond kann man neben dem TCA also auch im FlexForm einfach auf Werte aus anderen Feldern zugreifen.
Hier wird das Feld field nur angezeigt, wenn sich im Feld field2 der Wert "1" befindet:
<settings.field>
<TCEforms>
<displayCond>FIELD:settings.field2:=:1</displayCond>
<label>My label</label>
<config>
<type>select</type>
<renderType>selectSingle</renderType>
<items type="array">
<numIndex index="0" type="array">
<numIndex index="0">please choose</numIndex>
<numIndex index="1"></numIndex>
</numIndex>
</items>
<foreign_table>fe_groups</foreign_table>
<foreign_table_where>AND fe_groups.deleted = 0</foreign_table_where>
</config>
</TCEforms>
</settings.field>
Man kann auch verschiedene Conditions mit AND oder mit OR miteinander verknüpften. Im nachfolgenden Beispiel wird auf einen Wert im Feld switchableControllerActions zurückgegriffen. Da dieser Wert spitze Klammern beinhaltet, wird hier auf eine Schreibweise mit CDATA zurückgegriffen:
<displayCond>
<OR>
<numIndex index="0"><![CDATA[FIELD:main.switchableControllerActions:=:New->new;]]></numIndex>
<numIndex index="1"><![CDATA[FIELD:main.switchableControllerActions:=:Invitation->new;]]></numIndex>
</OR>
</displayCond>
Tipp: Man kann auch ganze Tabs im FlexForm ausblenden, so wie es bei der Erweiterung femanger gemacht wird.
2. Ausblenden von Feldern in Drittextensions
Das Alles ist so weit vermutlich nichts neues für euch. Und TYPO3 macht es einem hier auch einfach, Extensions zu bauen, die genau so funktionieren sollen, wie wir uns das vorstellen. Schwerer wird das Ganze jedoch dann, wenn wir das FlexForm einer Drittextension manipulieren wollen. Gehen wir beispielsweise von der Extension news aus. Auch hier wollen wir unbenötigte Felder gar nicht erst im Plugin anzeigen.
Generell können wir die Felder im FlexForm ganz einfach per Page TSConfig ausblenden:
TCEFORM {
tt_content {
pi_flexform {
news_pi1 {
sDEF {
switchableControllerActions.removeItems := addToList(News->list,News->selectedList,News->dateMenu,News->searchForm,News->searchResult,Category->list,Tag->list)
settings\.categoryConjunction.disabled = 1
settings\.categories.disabled = 1
settings\.includeSubCategories.disabled = 1
settings\.recursive.disabled = 1
}
}
}
}
}
Tipp: Mit Hilfe von Conditions können wir auch auf eine Backend Benutzergruppe abfragen und einzelne Felder ausblenden.
Kommt es jedoch zur Anforderung, dass beispielsweise settings.backPid nur in der Listenansicht ausgeblendet werden soll, wird es schon kniffliger. Eigentlich müsste man jetzt das komplette FlexForm ersetzen. Aber da man hier Probleme mit künftigen Updates bekommen könnte, empfiehlt sich der Einsatz des FlexFormHooks.
Einbau in der ext_localconf.php eures Sitepackages:
/**
* Hook to remove flexform fields per condition
*/
$flexFormToolsName = \TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools::class;
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$flexFormToolsName]['flexParsing'][]
= \In2code\In2template\Hooks\FlexFormHook::class;
Neue Datei in Classes/Hooks/FlexFormHook.php innerhalb eures Sitepackages:
<?php
declare(strict_types=1);
namespace In2code\In2template\Hooks;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\ArrayUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* FlexFormHook
* to add display cond configuration by given page TS settings
*/
class FlexFormHook
{
const TABLE_NAME = 'tt_content';
/**
* Remove FlexForm fields depending to dataStructureKeys
* Example Page TSConfig:
* TCEFORM {
* tt_content {
* pi_flexform {
* _addDisplayCond {
* 1 {
* field = sheets/additional/ROOT/el/settings.backPid/TCEforms/displayCond
* value = FIELD:sDEF.switchableControllerActions:=:News->detail
* dataStructureKey = news_pi1,list
* }
* }
* }
* }
* }
* @param array $dataStructure
* @param array $identifier
* @return array
*/
public function parseDataStructureByIdentifierPostProcess(array $dataStructure, array $identifier): array
{
$pageTsConfig = BackendUtility::getPagesTSconfig($this->getCurrentPageIdentifier());
if ($this->isConditionEnabled($pageTsConfig, $identifier)) {
$configurationParts = $pageTsConfig['TCEFORM.'][$identifier['tableName'] . '.'][$identifier['fieldName'] . '.']['_addDisplayCond.'];
foreach ($configurationParts as $part) {
if ($part['dataStructureKey'] === $identifier['dataStructureKey']) {
$dataStructure = ArrayUtility::setValueByPath($dataStructure, $part['field'], $part['value']);
}
}
}
return $dataStructure;
}
/**
* @param array $pageTsConfig
* @param array $identifier
* @return bool
*/
protected function isConditionEnabled(array $pageTsConfig, array $identifier): bool
{
return isset($pageTsConfig['TCEFORM.'][$identifier['tableName'] . '.'][$identifier['fieldName'] . '.']['_addDisplayCond.']);
}
/**
* @return int
*/
protected function getCurrentPageIdentifier(): int
{
$contentIdentifier = $this->getCurrentContentIdentifier();
if ($contentIdentifier > 0) {
return $this->getPageIdentifierFromContentIdentifier($contentIdentifier);
}
return 0;
}
/**
* @return int
*/
protected function getCurrentContentIdentifier(): int
{
$edit = GeneralUtility::_GP('edit');
if (!empty($edit[self::TABLE_NAME])) {
return (int)key($edit[self::TABLE_NAME]);
}
return 0;
}
/**
* @param int $contentIdentifier
* @return int
*/
protected function getPageIdentifierFromContentIdentifier(int $contentIdentifier): int
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE_NAME);
$queryBuilder->getRestrictions()->removeAll();
return (int)$queryBuilder
->select('pid')
->from(self::TABLE_NAME)
->where('uid=' . (int)$contentIdentifier)
->execute()
->fetchColumn();
}
}
Danach könnte euer Page TSConfig so oder so ähnlich aussehen:
TCEFORM {
tt_content {
pi_flexform {
# Add display cond configuration to an existing FlexForm configuration (see FlexFormHook class)
_addDisplayCond {
1 {
# Hide settings.backPid in detail view
field = sheets/additional/ROOT/el/settings.backPid/TCEforms/displayCond
value = FIELD:sDEF.switchableControllerActions:=:News->detail
dataStructureKey = news_pi1,list
}
}
news_pi1 {
sDEF {
switchableControllerActions.removeItems := addToList(News->list,News->selectedList,News->dateMenu,News->searchForm,News->searchResult,Category->list,Tag->list)
settings\.categoryConjunction.disabled = 1
settings\.categories.disabled = 1
settings\.includeSubCategories.disabled = 1
settings\.recursive.disabled = 1
}
additional {
settings\.hidePagination.disabled = 1
settings\.limit.disabled = 1
settings\.listPid.disabled = 1
settings\.tags.disabled = 1
settings\.disableOverrideDemand.disabled = 1
settings\.list\.paginate\.itemsPerPage.disabled = 1
}
template {
settings\.templateLayout.disabled = 1
settings\.media\.maxWidth.disabled = 1
settings\.media\.maxHeight.disabled = 1
settings\.cropMaxCharacters.disabled = 1
}
}
}
}
tx_news_domain_model_news {
categories.disabled = 1
related.disabled = 1
related_from.disabled = 1
tags.disabled = 1
keywords.disabled = 1
description.disabled = 1
alternative_title.disabled = 1
editlock.disabled = 1
notes.disabled = 1
}
tx_news_domain_model_link {
description.disabled = 1
}
}