[ 'renderType' => 'localizationStateSelector', ], 'otherLanguageContent' => [ 'renderType' => 'otherLanguageContent', 'after' => [ 'localizationStateSelector', ], ], 'defaultLanguageDifferences' => [ 'renderType' => 'defaultLanguageDifferences', 'after' => [ 'otherLanguageContent', ], ], ]; public function __construct( private readonly IconFactory $iconFactory, ) {} /** * This will render a single-line datetime form field, possibly with various control/validation features * * @return array As defined in initializeResultArray() of AbstractNode */ public function render(): array { $table = $this->data['tableName']; $fieldName = $this->data['fieldName']; $parameterArray = $this->data['parameterArray']; $resultArray = $this->initializeResultArray(); $config = $parameterArray['fieldConf']['config']; $format = $config['format'] ?? 'datetime'; if (!in_array($format, ['datetime', 'date', 'time', 'timesec', 'datetimesec'], true)) { throw new \UnexpectedValueException( 'Format "' . $format . '" for field "' . $fieldName . '" in table "' . $table . '" is ' . 'not valid. Must be either empty or set to one of: "date", "datetime", "time", "timesec", "datetimesec".', 1647947686 ); } $datetime = $parameterArray['itemFormElValue']; if ($datetime !== null && !$datetime instanceof \DateTimeInterface) { throw new \UnexpectedValueException( 'The formEngine itemFormElValue parameter for field "' . $fieldName . '" in table "' . $table . '" is ' . 'not valid. It must be an instance of `\\DateTimeInterface` but is `' . gettype($datetime) . '`. ' . 'Make sure to have it processed by `FormDataProvider/DatabaseRowDateTimeFields`.', 1731132127 ); } $width = $this->formMaxWidth(MathUtility::forceIntegerInRange( $config['size'] ?? ($format === 'datetimesec' ? 14 : ($format === 'date' || $format === 'datetime' ? 13 : 10)), $this->minimumInputWidth, $this->maxInputWidth )); $fieldId = StringUtility::getUniqueId('formengine-input-'); $itemName = (string)$parameterArray['itemFormElName']; $renderedLabel = $this->renderLabel($fieldId); $fieldInformationResult = $this->renderFieldInformation(); $fieldInformationHtml = $fieldInformationResult['html']; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false); if ($config['readOnly'] ?? false) { if ($datetime === null) { $itemValue = ''; } elseif ($format === 'time') { $itemValue = (string)((int)$datetime->format('H') * 3600 + (int)$datetime->format('i') * 60); } elseif ($format === 'timesec') { $itemValue = (string)((int)$datetime->format('H') * 3600 + (int)$datetime->format('i') * 60 + (int)$datetime->format('s')); } else { $itemValue = (string)$datetime->getTimestamp(); } // Format the unix-timestamp to the defined format (date/year etc) $formattedDate = $this->formatValue($format, $itemValue); $html = []; $html[] = $renderedLabel; $html[] = '
'; $html[] = $fieldInformationHtml; $html[] = '
'; $html[] = '
'; $html[] = '
'; $html[] = ''; $html[] = '
'; $html[] = '
'; $html[] = '
'; $html[] = '
'; $resultArray['html'] = implode(LF, $html); return $resultArray; } $languageService = $this->getLanguageService(); // Always add the format to the eval list. $evalList = [$format]; $isNullable = $config['nullable'] ?? false; if ($isNullable) { $evalList[] = 'null'; } $attributes = [ 'value' => '', 'id' => $fieldId, 'class' => implode(' ', [ 'form-control', 'form-control-clearable', ]), 'data-input-type' => 'datetimepicker', 'data-date-type' => $format, 'data-formengine-validation-rules' => $this->getValidationDataAsJsonString($config), 'data-formengine-input-params' => (string)json_encode([ 'field' => $itemName, 'evalList' => implode(',', $evalList), ], JSON_THROW_ON_ERROR), 'data-formengine-input-name' => $itemName, ]; if (!empty($config['placeholder'])) { $attributes['placeholder'] = trim($config['placeholder']); } if ($format === 'datetime' || $format === 'date' || $format === 'datetimesec') { if (isset($config['range']['lower'])) { $lower = (int)$config['range']['lower']; $attributes['data-date-min-date'] = date(DateTimeFormat::ISO8601_LOCALTIME, $lower); } if (isset($config['range']['upper'])) { $upper = (int)$config['range']['upper']; $attributes['data-date-max-date'] = date(DateTimeFormat::ISO8601_LOCALTIME, $upper); } } $fieldWizardResult = $this->renderFieldWizard(); $fieldWizardHtml = $fieldWizardResult['html']; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false); $fieldControlResult = $this->renderFieldControl(); $fieldControlHtml = $fieldControlResult['html']; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldControlResult, false); $buttonAriaLabelEscaped = htmlspecialchars($languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.datepicker.label')); $dateISO8601 = $datetime?->format(DateTimeFormat::ISO8601_LOCALTIME) ?? ''; $expansionHtml = []; $expansionHtml[] = '
'; $expansionHtml[] = '
'; $expansionHtml[] = '
'; $expansionHtml[] = '
'; $expansionHtml[] = ''; $expansionHtml[] = ''; $expansionHtml[] = ''; $expansionHtml[] = '
'; $expansionHtml[] = '
'; if (!empty($fieldControlHtml)) { $expansionHtml[] = '
'; $expansionHtml[] = '
'; $expansionHtml[] = $fieldControlHtml; $expansionHtml[] = '
'; $expansionHtml[] = '
'; } if (!empty($fieldWizardHtml)) { $expansionHtml[] = '
'; $expansionHtml[] = $fieldWizardHtml; $expansionHtml[] = '
'; } $expansionHtml[] = '
'; $expansionHtml[] = '
'; $expansionHtml = implode(LF, $expansionHtml); $nullControlNameEscaped = htmlspecialchars('control[active][' . $table . '][' . $this->data['databaseRow']['uid'] . '][' . $fieldName . ']'); $fullElement = $expansionHtml; if ($this->hasNullCheckboxWithPlaceholder()) { $checked = $datetime !== null ? ' checked="checked"' : ''; $placeholder = $shortenedPlaceholder = (string)($config['placeholder'] ?? ''); if ($placeholder !== '') { $shortenedPlaceholder = GeneralUtility::fixed_lgd_cs($placeholder, 20); if ($placeholder !== $shortenedPlaceholder) { $overrideLabel = sprintf( $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.placeholder.override'), '' . htmlspecialchars($shortenedPlaceholder) . '' ); } else { $overrideLabel = sprintf( $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.placeholder.override'), htmlspecialchars($placeholder) ); } } else { $overrideLabel = $languageService->sL( 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.placeholder.override_not_available' ); } $fullElement = []; $fullElement[] = '
'; $fullElement[] = ''; $fullElement[] = ''; $fullElement[] = ''; $fullElement[] = '
'; $fullElement[] = '
'; $fullElement[] = '
'; $fullElement[] = ''; $fullElement[] = '
'; $fullElement[] = '
'; $fullElement[] = '
'; $fullElement[] = $expansionHtml; $fullElement[] = '
'; $fullElement = implode(LF, $fullElement); } $resultArray['html'] = $renderedLabel . ' ' . $fieldInformationHtml . ' ' . $fullElement . ' '; $resultArray['javaScriptModules'][] = JavaScriptModuleInstruction::create('@typo3/backend/form-engine/element/datetime-element.js'); return $resultArray; } }