$fieldConfig) { if (empty($fieldConfig['config']['type']) || $fieldConfig['config']['type'] !== 'inline') { continue; } // Throw if an inline field without foreign_table is set if (!isset($fieldConfig['config']['foreign_table'])) { throw new \UnexpectedValueException( 'Inline field ' . $fieldName . ' of table ' . $result['tableName'] . ' must have a foreign_table config', 1443793404 ); } $result = $this->initializeMinMaxItems($result, $fieldName); $result = $this->initializeChildrenLanguage($result, $fieldName); $result = $this->initializeAppearance($result, $fieldName); $result = $this->addInlineSelectorAndUniqueConfiguration($result, $fieldName); } // If field is set to readOnly, set all fields of the relation to readOnly as well if (isset($result['inlineParentConfig']) && isset($result['inlineParentConfig']['readOnly']) && $result['inlineParentConfig']['readOnly']) { foreach ($result['processedTca']['columns'] as $columnName => $columnConfiguration) { $result['processedTca']['columns'][$columnName]['config']['readOnly'] = true; } } return $result; } /** * Set and validate minitems and maxitems in config * * @param array $result Result array * @param string $fieldName Current handle field name * @return array Modified item array * @return array */ protected function initializeMinMaxItems(array $result, $fieldName) { $config = $result['processedTca']['columns'][$fieldName]['config']; $minItems = 0; if (isset($config['minitems'])) { $minItems = MathUtility::forceIntegerInRange($config['minitems'], 0); } $result['processedTca']['columns'][$fieldName]['config']['minitems'] = $minItems; $maxItems = 99999; if (isset($config['maxitems'])) { $maxItems = MathUtility::forceIntegerInRange($config['maxitems'], 1); } $result['processedTca']['columns'][$fieldName]['config']['maxitems'] = $maxItems; return $result; } /** * Set appearance configuration * * @param array $result Result array * @param string $fieldName Current handle field name * @return array Modified item array * @return array */ protected function initializeAppearance(array $result, $fieldName) { $config = $result['processedTca']['columns'][$fieldName]['config']; if (!isset($config['appearance']) || !is_array($config['appearance'])) { // Init appearance if not set $config['appearance'] = []; } // Initialize position of the level links if (!isset($config['appearance']['levelLinksPosition']) || !in_array($config['appearance']['levelLinksPosition'], ['top', 'bottom', 'both'], true) ) { $config['appearance']['levelLinksPosition'] = 'top'; } // Hide level links (no matter the defined position) for "use combination" if (isset($config['foreign_selector']) && $config['foreign_selector'] && (!isset($config['appearance']['useCombination']) || !$config['appearance']['useCombination']) ) { $config['appearance']['showAllLocalizationLink'] = false; $config['appearance']['showSynchronizationLink'] = false; $config['appearance']['showNewRecordLink'] = false; } $config['appearance']['showPossibleLocalizationRecords'] = isset($config['appearance']['showPossibleLocalizationRecords']) && $config['appearance']['showPossibleLocalizationRecords']; // Defines which controls should be shown in header of each record $enabledControls = [ 'info' => true, 'new' => true, 'dragdrop' => true, 'sort' => true, 'hide' => true, 'delete' => true, 'localize' => true, ]; if (isset($config['appearance']['enabledControls']) && is_array($config['appearance']['enabledControls'])) { $config['appearance']['enabledControls'] = array_merge($enabledControls, $config['appearance']['enabledControls']); } else { $config['appearance']['enabledControls'] = $enabledControls; } $result['processedTca']['columns'][$fieldName]['config'] = $config; return $result; } /** * Set default value for child records 'sys_language_uid' field. This is relevant if a localized * parent is edited and a child is added via the ajax call. The child should then have the same * sys_language_uid as the parent. * The method verifies if the parent is a localized parent, and writes the current languageField * value into TCA ['config']['inline']['parentSysLanguageUid'] of the parent inline TCA field. The whole * ['config'] section is transferred to the 'create new child' ajax controller, the value is then used within * 'DatabaseRowInitializeNew' data provider to initialize the child languageField value with that value. * * @param array $result Result array * @param string $fieldName Current handle field name * @return array Modified item array */ protected function initializeChildrenLanguage(array $result, $fieldName) { $childTableName = $result['processedTca']['columns'][$fieldName]['config']['foreign_table']; if (empty($result['processedTca']['ctrl']['languageField']) || !$result['tcaSchemata']->get($childTableName)->isLanguageAware() ) { return $result; } $parentConfig = $result['processedTca']['columns'][$fieldName]['config']; $parentLanguageField = $result['processedTca']['ctrl']['languageField']; if (!isset($parentConfig['inline']['parentSysLanguageUid']) && isset($result['databaseRow'][$parentLanguageField]) ) { if (is_array($result['databaseRow'][$parentLanguageField])) { $result['processedTca']['columns'][$fieldName]['config']['inline']['parentSysLanguageUid'] = (int)($result['databaseRow'][$parentLanguageField][0] ?? 0); } else { $result['processedTca']['columns'][$fieldName]['config']['inline']['parentSysLanguageUid'] = (int)($result['databaseRow'][$parentLanguageField] ?? 0); } } return $result; } /** * If foreign_selector or foreign_unique is set, this points to a field configuration of the child * table. The InlineControlContainer may render a drop down field or an element browser later from this. * * Fetch configuration from child table configuration, sanitize and merge with * overrideChildTca of foreign_selector if given that allows overriding this field definition again. * * Final configuration is written to selectorOrUniqueConfiguration of inline config section. * * @param array $result Result array * @param string $fieldName Current handle field name * @return array Modified item array * @throws \UnexpectedValueException If configuration is broken */ protected function addInlineSelectorAndUniqueConfiguration(array $result, $fieldName) { $config = $result['processedTca']['columns'][$fieldName]['config']; // Early return if neither foreign_unique nor foreign_selector are set if (!isset($config['foreign_unique']) && !isset($config['foreign_selector'])) { return $result; } // If both are set, they must point to the same field if (isset($config['foreign_unique']) && isset($config['foreign_selector']) && $config['foreign_unique'] !== $config['foreign_selector'] ) { throw new \UnexpectedValueException( 'Table ' . $result['tableName'] . ' field ' . $fieldName . ': If both foreign_unique and' . ' foreign_selector are set, they must point to the same field', 1444995464 ); } if (isset($config['foreign_unique'])) { $fieldNameInChildConfiguration = $config['foreign_unique']; } else { $fieldNameInChildConfiguration = $config['foreign_selector']; } // Throw if field name in globals does not exist or is not of type select or group $foreignTableSchema = $result['tcaSchemata']->has($config['foreign_table']) ? $result['tcaSchemata']->get($config['foreign_table']) : null; if ($foreignTableSchema === null || !$foreignTableSchema->hasField($fieldNameInChildConfiguration) || ($foreignTableSchema->getField($fieldNameInChildConfiguration)->getType() !== 'select' && $foreignTableSchema->getField($fieldNameInChildConfiguration)->getType() !== 'group') ) { throw new \UnexpectedValueException( 'Table ' . $result['tableName'] . ' field ' . $fieldName . ' points in foreign_selector or foreign_unique' . ' to field ' . $fieldNameInChildConfiguration . ' of table ' . $config['foreign_table'] . ', but this field' . ' is either not defined or is not of type select or group', 1444996537 ); } $selectorOrUniqueConfiguration = [ 'config' => $foreignTableSchema->getField($fieldNameInChildConfiguration)->getConfiguration(), ]; // Merge overrideChildTca of foreign_selector if given if (isset($config['foreign_selector'], $config['overrideChildTca']['columns'][$config['foreign_selector']]['config']) && is_array($config['overrideChildTca']['columns'][$config['foreign_selector']]['config']) ) { $selectorOrUniqueConfiguration['config'] = array_replace_recursive($selectorOrUniqueConfiguration['config'], $config['overrideChildTca']['columns'][$config['foreign_selector']]['config']); } // Add field name to config for easy access later $selectorOrUniqueConfiguration['fieldName'] = $fieldNameInChildConfiguration; // Add remote table name for easy access later if ($selectorOrUniqueConfiguration['config']['type'] === 'select') { if (!isset($selectorOrUniqueConfiguration['config']['foreign_table'])) { throw new \UnexpectedValueException( 'Table ' . $result['tableName'] . ' field ' . $fieldName . ' points in foreign_selector or foreign_unique' . ' to field ' . $fieldNameInChildConfiguration . ' of table ' . $config['foreign_table'] . '. This field' . ' is of type select and must define foreign_table', 1445078627 ); } $foreignTable = $selectorOrUniqueConfiguration['config']['foreign_table']; } else { if (!isset($selectorOrUniqueConfiguration['config']['allowed'])) { throw new \UnexpectedValueException( 'Table ' . $result['tableName'] . ' field ' . $fieldName . ' points in foreign_selector or foreign_unique' . ' to field ' . $fieldNameInChildConfiguration . ' of table ' . $config['foreign_table'] . '. This field' . ' is of type select and must define allowed', 1445078628 ); } $foreignTable = $selectorOrUniqueConfiguration['config']['allowed']; } $selectorOrUniqueConfiguration['foreignTable'] = $foreignTable; // If this is a foreign_selector field, mark it as such for data fetching later $selectorOrUniqueConfiguration['isSelector'] = false; if (isset($config['foreign_selector'])) { $selectorOrUniqueConfiguration['isSelector'] = true; } // If this is a foreign_unique field, mark it a such for unique data fetching later $selectorOrUniqueConfiguration['isUnique'] = false; if (isset($config['foreign_unique'])) { $selectorOrUniqueConfiguration['isUnique'] = true; } // Add field configuration to inline configuration $result['processedTca']['columns'][$fieldName]['config']['selectorOrUniqueConfiguration'] = $selectorOrUniqueConfiguration; return $result; } }