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 = 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;
}
}