getLanguageService(); $resultArray = $this->initializeResultArray(); $this->initializeWizard(); $row = $this->data['databaseRow']; $tca = $this->data['processedTca']; $parameterArray = $this->data['parameterArray']; // 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. $readOnly = ($parameterArray['fieldConf']['config']['readOnly'] ?? false) && ($tca['ctrl']['transOrigPointerField'] ?? false) && ($row[$tca['ctrl']['transOrigPointerField']][0] ?? $row[$tca['ctrl']['transOrigPointerField']] ?? false) && GeneralUtility::inList($parameterArray['fieldConf']['l10n_display'] ?? '', 'defaultAsReadonly'); $fieldInformationResult = $this->renderFieldInformation(); $fieldInformationHtml = $fieldInformationResult['html']; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false); $fieldWizardResult = $this->renderFieldWizard(); $fieldWizardHtml = $fieldWizardResult['html']; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false); // Use CodeMirror if available $codeMirrorConfig = [ 'label' => $lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf:buttons.pageTsConfig'), 'panel' => 'top', 'mode' => GeneralUtility::jsonEncodeForHtmlAttribute(JavaScriptModuleInstruction::create('@typo3/backend/code-editor/language/typoscript.js', 'typoscript')->invoke(), false), 'nolazyload' => 'true', 'readonly' => 'true', ]; $resultArray['javaScriptModules'][] = JavaScriptModuleInstruction::create('@typo3/backend/code-editor/element/code-mirror-element.js'); $json = (string)json_encode($this->rows, JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS); $codeMirrorConfig = (string)json_encode($codeMirrorConfig, JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS); $html = []; $html[] = '
'; $html[] = $fieldInformationHtml; $html[] = '
'; $html[] = '
'; $html[] = '
'; $html[] = 'data['parameterArray']['itemFormElName']) . '"'; $html[] = ' value="' . htmlspecialchars($this->data['parameterArray']['itemFormElValue']) . '"'; $html[] = '/>'; $html[] = 'rowCount . '"'; $html[] = ' colCount="' . (int)$this->colCount . '"'; $html[] = ($readOnly ? 'readonly="true"' : ''); $html[] = ' fieldName="' . htmlspecialchars($this->data['parameterArray']['itemFormElName']) . '"'; $html[] = ' codeMirrorConfig="' . htmlspecialchars($codeMirrorConfig) . '"'; $html[] = '>'; if (!$readOnly && !empty($fieldWizardHtml)) { $html[] = '
' . $fieldWizardHtml . '
'; } $html[] = '
'; $html[] = '
'; $html[] = '
'; $html[] = '
'; $html = implode(LF, $html); $resultArray['html'] = $this->wrapWithFieldsetAndLegend($html); $resultArray['javaScriptModules'][] = JavaScriptModuleInstruction::create( '@typo3/backend/grid-editor.js', 'GridEditor' )->instance(); $resultArray['additionalInlineLanguageLabelFiles'][] = 'EXT:core/Resources/Private/Language/locallang_wizards.xlf'; $resultArray['additionalInlineLanguageLabelFiles'][] = 'EXT:backend/Resources/Private/Language/locallang.xlf'; $resultArray['additionalInlineLanguageLabelFiles'][] = 'EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf'; return $resultArray; } protected function initializeWizard(): void { // Initialize default values $rows = [[['colspan' => 1, 'rowspan' => 1, 'spanned' => 0, 'name' => '0x0']]]; $colCount = 1; $rowCount = 1; if (!empty($this->data['parameterArray']['itemFormElValue'])) { // Parse the TypoScript a-like syntax in case we already have a config (e.g. database value or default from TCA) $typoScriptTree = $this->typoScriptStringFactory->parseFromString($this->data['parameterArray']['itemFormElValue'], new AstBuilder(new NoopEventDispatcher())); $typoScriptArray = $typoScriptTree->toArray(); if (is_array($typoScriptArray['backend_layout.'] ?? false)) { // Only evaluate, in case the "backend_layout." array exists on root level $data = $typoScriptArray['backend_layout.']; $rows = []; $colCount = $data['colCount']; $rowCount = $data['rowCount']; $dataRows = $data['rows.']; $spannedMatrix = []; for ($i = 1; $i <= $rowCount; $i++) { $cells = []; $row = array_shift($dataRows); $columns = $row['columns.'] ?? []; for ($j = 1; $j <= $colCount; $j++) { $cellData = []; if (!($spannedMatrix[$i][$j] ?? false)) { if (is_array($columns) && !empty($columns)) { $column = array_shift($columns); if (isset($column['colspan'])) { $cellData['colspan'] = (int)$column['colspan']; $columnColSpan = (int)$column['colspan']; if (isset($column['rowspan'])) { $columnRowSpan = (int)$column['rowspan']; for ($spanRow = 0; $spanRow < $columnRowSpan; $spanRow++) { for ($spanColumn = 0; $spanColumn < $columnColSpan; $spanColumn++) { $spannedMatrix[$i + $spanRow][$j + $spanColumn] = 1; } } } else { for ($spanColumn = 0; $spanColumn < $columnColSpan; $spanColumn++) { $spannedMatrix[$i][$j + $spanColumn] = 1; } } } else { $cellData['colspan'] = 1; if (isset($column['rowspan'])) { $columnRowSpan = (int)$column['rowspan']; for ($spanRow = 0; $spanRow < $columnRowSpan; $spanRow++) { $spannedMatrix[$i + $spanRow][$j] = 1; } } } if (isset($column['rowspan'])) { $cellData['rowspan'] = (int)$column['rowspan']; } else { $cellData['rowspan'] = 1; } if (isset($column['name'])) { $cellData['name'] = $column['name']; } if (isset($column['colPos'])) { $cellData['column'] = (int)$column['colPos']; } if (isset($column['identifier'])) { $cellData['identifier'] = $column['identifier']; } if (isset($column['slideMode'])) { $cellData['slideMode'] = $column['slideMode']; } } } else { $cellData = ['colspan' => 1, 'rowspan' => 1, 'spanned' => 1]; } $cells[] = $cellData; } $rows[] = $cells; if (is_array($spannedMatrix[$i] ?? false) && $spannedMatrix[$i] !== []) { ksort($spannedMatrix[$i]); } } } } $this->rows = $rows; $this->colCount = (int)$colCount; $this->rowCount = (int)$rowCount; } }