[ 'renderType' => 'elementBrowser', ], 'insertClipboard' => [ 'renderType' => 'insertClipboard', 'after' => [ 'elementBrowser' ], ], 'editPopup' => [ 'renderType' => 'editPopup', 'disabled' => true, 'after' => [ 'insertClipboard' ], ], 'addRecord' => [ 'renderType' => 'addRecord', 'disabled' => true, 'after' => [ 'editPopup' ], ], 'listModule' => [ 'renderType' => 'listModule', 'disabled' => true, 'after' => [ 'addRecord' ], ], ]; /** * Default field wizards for this element * * @var array */ protected $defaultFieldWizard = [ 'tableList' => [ 'renderType' => 'tableList', ], 'recordsOverview' => [ 'renderType' => 'recordsOverview', 'after' => [ 'tableList' ], ], 'localizationStateSelector' => [ 'renderType' => 'localizationStateSelector', 'after' => [ 'recordsOverview' ], ], 'otherLanguageContent' => [ 'renderType' => 'otherLanguageContent', 'after' => [ 'localizationStateSelector' ], ], 'defaultLanguageDifferences' => [ 'renderType' => 'defaultLanguageDifferences', 'after' => [ 'otherLanguageContent' ], ], 'shortcutValidation' => [ 'renderType' => 'shortcutValidation', 'after' => [ 'defaultLanguageDifferences' ], ], ]; public function __construct( private readonly IconFactory $iconFactory, ) {} /** * This will render a selector box into which elements from the database * can be inserted. Relations. * * @return array As defined in initializeResultArray() of AbstractNode * @throws \RuntimeException */ public function render(): array { $languageService = $this->getLanguageService(); $backendUser = $this->getBackendUserAuthentication(); $resultArray = $this->initializeResultArray(); $table = $this->data['tableName']; $fieldName = $this->data['fieldName']; $row = $this->data['databaseRow']; $parameterArray = $this->data['parameterArray']; $config = $parameterArray['fieldConf']['config']; $elementName = $parameterArray['itemFormElName']; $recordTypeValue = $this->data['recordTypeValue'] ?? null; $selectedItems = $parameterArray['itemFormElValue']; $maxItems = $config['maxitems']; $size = (int)($config['size'] ?? 5); $autoSizeMax = (int)($config['autoSizeMax'] ?? 0); if ($autoSizeMax > 0) { $size = MathUtility::forceIntegerInRange($size, 1); $size = MathUtility::forceIntegerInRange(count($selectedItems) + 1, $size, $autoSizeMax); } $fieldId = StringUtility::getUniqueId('tceforms-multiselect-'); $listOfSelectedValues = []; $selectorOptionsHtml = []; foreach ($selectedItems as $selectedItem) { $tableWithUid = $selectedItem['table'] . '_' . $selectedItem['uid']; $listOfSelectedValues[] = $tableWithUid; $title = $selectedItem['title']; if (empty($title)) { $title = '[' . $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.no_title') . ']'; } $shortenedTitle = BackendUtility::cropToTitleLength($title); $selectorOptionsHtml[] = ''; } $fieldInformationResult = $this->renderFieldInformation(); $fieldInformationHtml = $fieldInformationResult['html']; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false); if (isset($config['readOnly']) && $config['readOnly']) { // Return early if element is read only $html = []; $html[] = $this->renderLabel($fieldId); $html[] = '
'; $html[] = $fieldInformationHtml; $html[] = '
'; $html[] = '
'; $html[] = 'data['processedTca']['columns'][$fieldName]['config']['type'] === 'flex') { $flexFormConfig = $this->data['processedTca']['columns'][$fieldName]; $dataStructureIdentifier = $flexFormConfig['config']['dataStructureIdentifier']; if (!isset($flexFormConfig['config']['dataStructureIdentifier'])) { throw new \RuntimeException( 'A data structure identifier must be set in [\'config\'] part of a flex form.' . ' This is usually added by TcaFlexPrepare data processor', 1485206970 ); } if (isset($this->data['flexFormSheetName'])) { $flexFormSheetName = $this->data['flexFormSheetName']; } if (isset($this->data['flexFormFieldName'])) { $flexFormFieldName = $this->data['flexFormFieldName']; } if (isset($this->data['flexFormContainerName'])) { $flexFormContainerName = $this->data['flexFormContainerName']; } if (isset($this->data['flexFormContainerFieldName'])) { $flexFormContainerFieldName = $this->data['flexFormContainerFieldName']; } } // Get minimum characters for suggest from TCA and override by TsConfig $suggestMinimumCharacters = 0; if (isset($config['suggestOptions']['default']['minimumCharacters'])) { $suggestMinimumCharacters = (int)$config['suggestOptions']['default']['minimumCharacters']; } if (isset($parameterArray['fieldTSConfig']['suggest.']['default.']['minimumCharacters'])) { $suggestMinimumCharacters = (int)$parameterArray['fieldTSConfig']['suggest.']['default.']['minimumCharacters']; } $suggestMinimumCharacters = $suggestMinimumCharacters > 0 ? $suggestMinimumCharacters : 2; $itemCanBeSelectedMoreThanOnce = !empty($config['multiple']); $showMoveIcons = true; if (isset($config['hideMoveIcons']) && $config['hideMoveIcons']) { $showMoveIcons = false; } $showDeleteControl = true; if (isset($config['hideDeleteIcon']) && $config['hideDeleteIcon']) { $showDeleteControl = false; } $selectorAttributes = [ 'id' => $fieldId, 'data-formengine-input-name' => htmlspecialchars($elementName), 'data-maxitems' => (string)$maxItems, 'size' => (string)$size, ]; $selectorAttributes['class'] = 'form-select'; if ($maxItems !== 1 && $size !== 1) { $selectorAttributes['multiple'] = 'multiple'; } $fieldControlResult = $this->renderFieldControl(); $fieldControlHtml = $fieldControlResult['html']; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldControlResult, false); $fieldWizardResult = $this->renderFieldWizard(); $fieldWizardHtml = $fieldWizardResult['html']; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false); $html = []; $html[] = $this->renderLabel($fieldId); $html[] = '
'; $html[] = $fieldInformationHtml; $html[] = '
'; if (!isset($config['hideSuggest']) || (bool)$config['hideSuggest'] !== true) { $html[] = '
'; $html[] = '
'; $html[] = 'sL('LLL:EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf:search.find_record') . '"'; $html[] = ' data-fieldname="' . htmlspecialchars($fieldName) . '"'; $html[] = ' data-tablename="' . htmlspecialchars($table) . '"'; $html[] = ' data-field="' . htmlspecialchars($elementName) . '"'; $html[] = ' data-uid="' . htmlspecialchars($this->data['databaseRow']['uid']) . '"'; $html[] = ' data-pid="' . htmlspecialchars($this->data['parentPageRow']['uid'] ?? 0) . '"'; $html[] = ' data-fieldtype="' . htmlspecialchars($config['type']) . '"'; $html[] = ' data-minchars="' . htmlspecialchars((string)$suggestMinimumCharacters) . '"'; $html[] = ' data-datastructureidentifier="' . htmlspecialchars($dataStructureIdentifier) . '"'; $html[] = ' data-flexformsheetname="' . htmlspecialchars($flexFormSheetName) . '"'; $html[] = ' data-flexformfieldname="' . htmlspecialchars($flexFormFieldName) . '"'; $html[] = ' data-flexformcontainername="' . htmlspecialchars($flexFormContainerName) . '"'; $html[] = ' data-flexformcontainerfieldname="' . htmlspecialchars($flexFormContainerFieldName) . '"'; if ($recordTypeValue !== null && $recordTypeValue !== '') { $html[] = ' data-recordtypevalue="' . htmlspecialchars($recordTypeValue) . '"'; } $html[] = '/>'; $html[] = '
'; $html[] = '
'; } $html[] = '
'; $html[] = ''; $html[] = ''; $html[] = '
'; if (($maxItems > 1 && $size > 1 && $showMoveIcons) || $showDeleteControl) { $html[] = '
'; $html[] = '
'; if ($maxItems > 1 && $size >= 2 && $showMoveIcons) { $html[] = ''; } if ($maxItems > 1 && $size > 1 && $showMoveIcons) { $html[] = ''; $html[] = ''; } if ($maxItems > 1 && $size >= 2 && $showMoveIcons) { $html[] = ''; } if ($showDeleteControl) { $html[] = ''; } $html[] = '
'; $html[] = '
'; } if ($fieldControlHtml !== '') { $html[] = '
'; $html[] = '
'; $html[] = $fieldControlHtml; $html[] = '
'; $html[] = '
'; } if (!empty($fieldWizardHtml)) { $html[] = '
'; $html[] = $fieldWizardHtml; $html[] = '
'; } $html[] = '
'; $hiddenElementAttrs = array_merge( [ 'type' => 'hidden', 'name' => $elementName, 'data-formengine-validation-rules' => $this->getValidationDataAsJsonString($config), 'value' => implode(',', $listOfSelectedValues), ], $this->getOnFieldChangeAttrs('change', $parameterArray['fieldChangeFunc'] ?? []) ); $html[] = ''; $html[] = '
'; $resultArray['javaScriptModules'][] = JavaScriptModuleInstruction::create( '@typo3/backend/form-engine/element/group-element.js' )->instance($fieldId); $resultArray['html'] = implode(LF, $html); return $resultArray; } protected function getBackendUserAuthentication(): BackendUserAuthentication { return $GLOBALS['BE_USER']; } }