[ 'renderType' => 'localizationStateSelector', ], 'otherLanguageContent' => [ 'renderType' => 'otherLanguageContent', 'after' => [ 'localizationStateSelector', ], ], 'defaultLanguageDifferences' => [ 'renderType' => 'defaultLanguageDifferences', 'after' => [ 'otherLanguageContent', ], ], ]; public function __construct( private readonly IconFactory $iconFactory, private readonly HashService $hashService, ) {} /** * This will render a single-line input form field, possibly with various control/validation features * * @return array As defined in initializeResultArray() of AbstractNode */ public function render(): array { $table = $this->data['tableName']; $row = $this->data['databaseRow']; $parameterArray = $this->data['parameterArray']; $resultArray = $this->initializeResultArray(); $languageId = 0; if ($this->data['tcaSchemata']->has($table) && $this->data['tcaSchemata']->get($table)->hasCapability(TcaSchemaCapability::Language)) { $languageField = $this->data['tcaSchemata']->get($table)->getCapability(TcaSchemaCapability::Language)->getLanguageField()->getName(); $languageId = (int)((is_array($row[$languageField] ?? null) ? ($row[$languageField][0] ?? 0) : $row[$languageField]) ?? 0); } $itemValue = $parameterArray['itemFormElValue']; $config = $parameterArray['fieldConf']['config']; $evalList = GeneralUtility::trimExplode(',', $config['eval'] ?? '', true); $size = MathUtility::forceIntegerInRange($config['size'] ?? $this->defaultInputWidth, $this->minimumInputWidth, $this->maxInputWidth); $width = $this->formMaxWidth($size); $baseUrl = $this->data['customData'][$this->data['fieldName']]['slugPrefix'] ?? ''; $fieldId = StringUtility::getUniqueId('formengine-input-'); $renderedLabel = $this->renderLabel($fieldId); // Convert UTF-8 characters back (that is important, see Slug class when sanitizing) $itemValue = rawurldecode($itemValue); $fieldInformationResult = $this->renderFieldInformation(); $fieldInformationHtml = $fieldInformationResult['html']; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false); // readOnly is not supported as columns config but might be set by SingleFieldContainer in case // "l10n_display" is set to "defaultAsReadonly". To prevent misbehaviour for fields, which falsely // set this, we also check for "defaultAsReadonly" being set and whether the record is an overlay. if (($config['readOnly'] ?? false) && ($this->data['processedTca']['ctrl']['transOrigPointerField'] ?? false) && ($row[$this->data['processedTca']['ctrl']['transOrigPointerField']][0] ?? $row[$this->data['processedTca']['ctrl']['transOrigPointerField']] ?? false) && GeneralUtility::inList($parameterArray['fieldConf']['l10n_display'] ?? '', 'defaultAsReadonly') ) { $disabledFieldAttributes = [ 'class' => 'form-control', 'data-formengine-input-name' => $parameterArray['itemFormElName'], 'type' => 'text', 'value' => $itemValue, 'title' => $itemValue, 'id' => $fieldId, ]; $html = []; $html[] = $renderedLabel; $html[] = '
'; $html[] = $fieldInformationHtml; $html[] = '
'; $html[] = '
'; $html[] = '
'; $html[] = '
'; $html[] = ($baseUrl ? '' . htmlspecialchars($baseUrl) . '' : ''); $html[] = ''; $html[] = '
'; $html[] = '
'; $html[] = '
'; $html[] = '
'; $html[] = '
'; $resultArray['html'] = implode(LF, $html); return $resultArray; } $fieldControlResult = $this->renderFieldControl(); $fieldControlHtml = $fieldControlResult['html']; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldControlResult, false); $fieldWizardResult = $this->renderFieldWizard(); $fieldWizardHtml = $fieldWizardResult['html']; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false); $toggleButtonTitle = $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:buttons.toggleSlugExplanation'); $recreateButtonTitle = $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:buttons.recreateSlugExplanation'); $successMessage = $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:slugCreation.success.' . ($table === 'pages' ? 'page' : 'record')); $errorMessage = $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:slugCreation.error'); $thisSlugId = 't3js-form-field-slug-id' . StringUtility::getUniqueId(); $mainFieldHtml = []; $mainFieldHtml[] = $renderedLabel; $mainFieldHtml[] = '
'; $mainFieldHtml[] = $fieldInformationHtml; $mainFieldHtml[] = '
'; $mainFieldHtml[] = '
'; $mainFieldHtml[] = '
'; $mainFieldHtml[] = '
'; $mainFieldHtml[] = ($baseUrl ? '' . htmlspecialchars($baseUrl) . '' : ''); // We deal with 3 fields here: a readonly field for current / default values, an input // field to manipulate the value, and the final hidden field used to send the value $mainFieldHtml[] = 'getValidationDataAsJsonString($config)) . '"'; $mainFieldHtml[] = ' data-formengine-input-params="' . htmlspecialchars((string)json_encode(['field' => $parameterArray['itemFormElName'], 'evalList' => implode(',', $evalList)])) . '"'; $mainFieldHtml[] = ' data-formengine-input-name="' . htmlspecialchars($parameterArray['itemFormElName']) . '"'; $mainFieldHtml[] = ' />'; $mainFieldHtml[] = ''; $mainFieldHtml[] = $this->iconFactory->getIcon('actions-version-workspaces-preview-link', IconSize::SMALL)->render(); $mainFieldHtml[] = ''; $mainFieldHtml[] = ''; $mainFieldHtml[] = '
'; $mainFieldHtml[] = '
'; if (!empty($fieldControlHtml)) { $mainFieldHtml[] = '
'; $mainFieldHtml[] = '
'; $mainFieldHtml[] = $fieldControlHtml; $mainFieldHtml[] = '
'; $mainFieldHtml[] = '
'; } $mainFieldHtml[] = '
'; $mainFieldHtml[] = ''; $mainFieldHtml[] = ''; $mainFieldHtml[] = $fieldWizardHtml; $mainFieldHtml[] = '
'; $mainFieldHtml[] = '
'; $mainFieldHtml[] = '
'; $mainFieldHtml[] = '
'; $resultArray['html'] = implode(LF, $mainFieldHtml); [$commonElementPrefix] = GeneralUtility::revExplode('[', $parameterArray['itemFormElName'], 2); $validInputNamesToListenTo = []; $includeUidInValues = false; foreach ($config['generatorOptions']['fields'] ?? [] as $fieldNameParts) { if (is_string($fieldNameParts)) { $fieldNameParts = GeneralUtility::trimExplode(',', $fieldNameParts); } foreach ($fieldNameParts as $listenerFieldName) { if ($listenerFieldName === 'uid') { $includeUidInValues = true; continue; } $validInputNamesToListenTo[$listenerFieldName] = $commonElementPrefix . '[' . htmlspecialchars($listenerFieldName) . ']'; } } $parentPageId = $this->data['parentPageRow']['uid'] ?? 0; $signature = $this->hashService->hmac( implode( '', [ $table, $this->data['effectivePid'], $row['uid'], $languageId, $this->data['fieldName'], $this->data['command'], $parentPageId, ] ), FormSlugAjaxController::class ); $optionsForModule = [ 'pageId' => $this->data['effectivePid'], 'recordId' => $row['uid'], 'tableName' => $table, 'fieldName' => $this->data['fieldName'], 'config' => $config, 'listenerFieldNames' => $validInputNamesToListenTo, 'language' => $languageId, 'originalValue' => $itemValue, 'signature' => $signature, 'command' => $this->data['command'], 'parentPageId' => $parentPageId, 'includeUidInValues' => $includeUidInValues, ]; $resultArray['javaScriptModules'][] = JavaScriptModuleInstruction::create( '@typo3/backend/form-engine/element/slug-element.js' )->instance('#' . $thisSlugId, $optionsForModule); return $resultArray; } }