‪TYPO3CMS  11.5
BackendLayoutWizardElement.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
22 
28 {
34  protected ‪$defaultFieldInformation = [
35  'tcaDescription' => [
36  'renderType' => 'tcaDescription',
37  ],
38  ];
39 
43  protected ‪$rows = [];
44 
48  protected ‪$colCount = 0;
49 
53  protected ‪$rowCount = 0;
54 
58  public function ‪render()
59  {
60  $lang = $this->‪getLanguageService();
61  $resultArray = $this->‪initializeResultArray();
62  $this->‪init();
63 
64  $row = $this->data['databaseRow'];
65  ‪$tca = $this->data['processedTca'];
66  $parameterArray = $this->data['parameterArray'];
67 
68  // readOnly is not supported as columns config but might be set by SingleFieldContainer in case
69  // "l10n_display" is set to "defaultAsReadonly". To prevent misbehaviour for fields, which falsely
70  // set this, we also check for "defaultAsReadonly" being set and whether the record is an overlay.
71  $readOnly = ($parameterArray['fieldConf']['config']['readOnly'] ?? false)
72  && (‪$tca['ctrl']['transOrigPointerField'] ?? false)
73  && ($row[‪$tca['ctrl']['transOrigPointerField']][0] ?? $row[‪$tca['ctrl']['transOrigPointerField']] ?? false)
74  && GeneralUtility::inList($parameterArray['fieldConf']['l10n_display'] ?? '', 'defaultAsReadonly');
75 
76  $fieldInformationResult = $this->‪renderFieldInformation();
77  $fieldInformationHtml = $fieldInformationResult['html'];
78  $resultArray = $this->‪mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
79 
80  $fieldWizardResult = $this->‪renderFieldWizard();
81  $fieldWizardHtml = $fieldWizardResult['html'];
82  $resultArray = $this->‪mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
83 
84  // Use CodeMirror if available
86  $codeMirrorConfig = [
87  'label' => $lang->getLL('buttons.pageTsConfig'),
88  'panel' => 'top',
89  'mode' => 'TYPO3/CMS/T3editor/Mode/typoscript/typoscript',
90  'nolazyload' => 'true',
91  'options' => GeneralUtility::jsonEncodeForHtmlAttribute([
92  'readOnly' => 'true',
93  ], false),
94  ];
95  $editor = '
96  <typo3-t3editor-codemirror class="t3js-grideditor-preview-config grideditor-preview" ' . GeneralUtility::implodeAttributes($codeMirrorConfig, true) . '>
97  <textarea class="t3js-tsconfig-preview-area"></textarea>
98  </typo3-t3editor-codemirror>';
99 
100  $resultArray['stylesheetFiles'][] = 'EXT:t3editor/Resources/Public/JavaScript/Contrib/codemirror/lib/codemirror.css';
101  $resultArray['stylesheetFiles'][] = 'EXT:t3editor/Resources/Public/Css/t3editor.css';
102  $resultArray['requireJsModules'][] = ‪JavaScriptModuleInstruction::forRequireJS('TYPO3/CMS/T3editor/Element/CodeMirrorElement');
103  } else {
104  $editor = '
105  <label>' . htmlspecialchars($lang->getLL('buttons.pageTsConfig')) . '</label>
106  <div class="t3js-grideditor-preview-config grideditor-preview">
107  <textarea class="t3js-tsconfig-preview-area form-control" rows="25" readonly></textarea>
108  </div>';
109  }
110 
111  $json = (string)json_encode($this->rows, JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS);
112  $html = [];
113  $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
114  $html[] = $fieldInformationHtml;
115  $html[] = '<div class="form-control-wrap">';
116  $html[] = '<div class="form-wizards-wrap">';
117  $html[] = '<div class="form-wizards-element">';
118  $html[] = '<input';
119  $html[] = ' type="hidden"';
120  $html[] = ' name="' . htmlspecialchars($this->data['parameterArray']['itemFormElName']) . '"';
121  $html[] = ' value="' . htmlspecialchars($this->data['parameterArray']['itemFormElValue']) . '"';
122  $html[] = '/>';
123  $html[] = '<table class="grideditor table table-bordered">';
124  if (!$readOnly) {
125  $html[] = '<tr>';
126  $html[] = '<td colspan="2" align="center">';
127  $html[] = '<div class="btn-group">';
128  $html[] = '<a class="btn btn-default btn-sm t3js-grideditor-removerow-top" href="#"';
129  $html[] = ' title="' . htmlspecialchars($lang->getLL('grid_removeRow')) . '">';
130  $html[] = '<i class="fa fa-fw fa-minus"></i>';
131  $html[] = '</a>';
132  $html[] = '<a class="btn btn-default btn-sm t3js-grideditor-addrow-top" href="#"';
133  $html[] = ' title="' . htmlspecialchars($lang->getLL('grid_addRow')) . '">';
134  $html[] = '<i class="fa fa-fw fa-plus"></i>';
135  $html[] = '</a>';
136  $html[] = '</div>';
137  $html[] = '</td>';
138  $html[] = '</tr>';
139  }
140  $html[] = '<tr>';
141  $html[] = '<td class="editor_cell">';
142  $html[] = '<div';
143  $html[] = ' id="editor"';
144  $html[] = ' class="t3js-grideditor"';
145  $html[] = ' data-data="' . htmlspecialchars($json) . '"';
146  $html[] = ' data-rowcount="' . (int)$this->rowCount . '"';
147  $html[] = ' data-colcount="' . (int)$this->colCount . '"';
148  $html[] = ' data-readonly="' . ($readOnly ? '1' : '0') . '"';
149  $html[] = ' data-field="' . htmlspecialchars($this->data['parameterArray']['itemFormElName']) . '"';
150  $html[] = '>';
151  $html[] = '</div>';
152  $html[] = '</td>';
153  if (!$readOnly) {
154  $html[] = '<td>';
155  $html[] = '<div class="btn-group-vertical">';
156  $html[] = '<a class="btn btn-default btn-sm t3js-grideditor-addcolumn" href="#"';
157  $html[] = ' title="' . htmlspecialchars($lang->getLL('grid_addColumn')) . '">';
158  $html[] = '<i class="fa fa-fw fa-plus"></i>';
159  $html[] = '</a>';
160  $html[] = '<a class="btn btn-default btn-sm t3js-grideditor-removecolumn" href="#"';
161  $html[] = ' title="' . htmlspecialchars($lang->getLL('grid_removeColumn')) . '">';
162  $html[] = '<i class="fa fa-fw fa-minus"></i>';
163  $html[] = '</a>';
164  $html[] = '</div>';
165  $html[] = '</td>';
166  $html[] = '</tr>';
167  $html[] = '<tr>';
168  $html[] = '<td colspan="2" align="center">';
169  $html[] = '<div class="btn-group">';
170  $html[] = '<a class="btn btn-default btn-sm t3js-grideditor-addrow-bottom" href="#"';
171  $html[] = ' title="' . htmlspecialchars($lang->getLL('grid_addRow')) . '">';
172  $html[] = '<i class="fa fa-fw fa-plus"></i>';
173  $html[] = '</a>';
174  $html[] = '<a class="btn btn-default btn-sm t3js-grideditor-removerow-bottom" href="#"';
175  $html[] = ' title="' . htmlspecialchars($lang->getLL('grid_removeRow')) . '">';
176  $html[] = '<i class="fa fa-fw fa-minus"></i>';
177  $html[] = '</a>';
178  $html[] = '</div>';
179  $html[] = '</td>';
180  }
181  $html[] = '</tr>';
182  $html[] = '<tr>';
183  $html[] = '<td colspan="2">';
184  $html[] = $editor;
185  $html[] = '</td>';
186  $html[] = '</tr>';
187  $html[] = '</table>';
188  $html[] = '</div>';
189  if (!$readOnly && !empty($fieldWizardHtml)) {
190  $html[] = '<div class="form-wizards-items-bottom">';
191  $html[] = $fieldWizardHtml;
192  $html[] = '</div>';
193  }
194  $html[] = '</div>';
195  $html[] = '</div>';
196  $html[] = '</div>';
197 
198  $html = implode(LF, $html);
199  $resultArray['html'] = $html;
200  $resultArray['requireJsModules'][] = ‪JavaScriptModuleInstruction::forRequireJS(
201  'TYPO3/CMS/Backend/GridEditor',
202  'GridEditor'
203  )->instance();
204  $resultArray['additionalInlineLanguageLabelFiles'][] = 'EXT:core/Resources/Private/Language/locallang_wizards.xlf';
205  $resultArray['additionalInlineLanguageLabelFiles'][] = 'EXT:backend/Resources/Private/Language/locallang.xlf';
206 
207  return $resultArray;
208  }
209 
213  protected function ‪init()
214  {
215  // Initialize default values
216  ‪$rows = [[['colspan' => 1, 'rowspan' => 1, 'spanned' => 0, 'name' => '0x0']]];
217  ‪$colCount = 1;
218  ‪$rowCount = 1;
219 
220  if (!empty($this->data['parameterArray']['itemFormElValue'])) {
221  // load TS parser in case we already have a config (e.g. database value or default from TCA)
222  ‪$parser = GeneralUtility::makeInstance(TypoScriptParser::class);
223  ‪$parser->parse($this->data['parameterArray']['itemFormElValue']);
224  if (is_array(‪$parser->setup['backend_layout.'] ?? false)) {
225  // Only evaluate, in case the "backend_layout." array exists on root level
226  ‪$data = ‪$parser->setup['backend_layout.'];
227  ‪$rows = [];
228  ‪$colCount = ‪$data['colCount'];
229  ‪$rowCount = ‪$data['rowCount'];
230  $dataRows = ‪$data['rows.'];
231  $spannedMatrix = [];
232  for ($i = 1; $i <= ‪$rowCount; $i++) {
233  $cells = [];
234  $row = array_shift($dataRows);
235  $columns = $row['columns.'];
236  for ($j = 1; $j <= ‪$colCount; $j++) {
237  $cellData = [];
238  if (!($spannedMatrix[$i][$j] ?? false)) {
239  if (is_array($columns) && !empty($columns)) {
240  $column = array_shift($columns);
241  if (isset($column['colspan'])) {
242  $cellData['colspan'] = (int)$column['colspan'];
243  $columnColSpan = (int)$column['colspan'];
244  if (isset($column['rowspan'])) {
245  $columnRowSpan = (int)$column['rowspan'];
246  for ($spanRow = 0; $spanRow < $columnRowSpan; $spanRow++) {
247  for ($spanColumn = 0; $spanColumn < $columnColSpan; $spanColumn++) {
248  $spannedMatrix[$i + $spanRow][$j + $spanColumn] = 1;
249  }
250  }
251  } else {
252  for ($spanColumn = 0; $spanColumn < $columnColSpan; $spanColumn++) {
253  $spannedMatrix[$i][$j + $spanColumn] = 1;
254  }
255  }
256  } else {
257  $cellData['colspan'] = 1;
258  if (isset($column['rowspan'])) {
259  $columnRowSpan = (int)$column['rowspan'];
260  for ($spanRow = 0; $spanRow < $columnRowSpan; $spanRow++) {
261  $spannedMatrix[$i + $spanRow][$j] = 1;
262  }
263  }
264  }
265  if (isset($column['rowspan'])) {
266  $cellData['rowspan'] = (int)$column['rowspan'];
267  } else {
268  $cellData['rowspan'] = 1;
269  }
270  if (isset($column['name'])) {
271  $cellData['name'] = $column['name'];
272  }
273  if (isset($column['colPos'])) {
274  $cellData['column'] = (int)$column['colPos'];
275  }
276  }
277  } else {
278  $cellData = ['colspan' => 1, 'rowspan' => 1, 'spanned' => 1];
279  }
280  $cells[] = $cellData;
281  }
282  ‪$rows[] = $cells;
283  if (!empty($spannedMatrix[$i]) && is_array($spannedMatrix[$i])) {
284  ksort($spannedMatrix[$i]);
285  }
286  }
287  }
288  }
289 
290  $this->rows = ‪$rows;
291  $this->colCount = (int)‪$colCount;
292  $this->rowCount = (int)‪$rowCount;
293  }
294 }
‪TYPO3\CMS\Backend\Form\Element\BackendLayoutWizardElement\render
‪array render()
Definition: BackendLayoutWizardElement.php:54
‪TYPO3\CMS\Backend\Form\Element\AbstractFormElement\renderFieldInformation
‪array renderFieldInformation()
Definition: AbstractFormElement.php:76
‪TYPO3\CMS\Backend\Form\Element\BackendLayoutWizardElement\$defaultFieldInformation
‪array $defaultFieldInformation
Definition: BackendLayoutWizardElement.php:33
‪TYPO3\CMS\Backend\Form\Element\BackendLayoutWizardElement
Definition: BackendLayoutWizardElement.php:28
‪TYPO3\CMS\Backend\Form\AbstractNode\mergeChildReturnIntoExistingResult
‪array mergeChildReturnIntoExistingResult(array $existing, array $childReturn, bool $mergeHtml=true)
Definition: AbstractNode.php:120
‪TYPO3\CMS\Backend\Form\AbstractNode\initializeResultArray
‪array initializeResultArray()
Definition: AbstractNode.php:91
‪TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser
Definition: TypoScriptParser.php:36
‪$parser
‪$parser
Definition: annotationChecker.php:110
‪TYPO3\CMS\Backend\Form\Element\AbstractFormElement
Definition: AbstractFormElement.php:35
‪TYPO3\CMS\Core\Page\JavaScriptModuleInstruction
Definition: JavaScriptModuleInstruction.php:23
‪TYPO3\CMS\Backend\Form\Element
Definition: AbstractFormElement.php:16
‪TYPO3\CMS\Core\Page\JavaScriptModuleInstruction\forRequireJS
‪static self forRequireJS(string $name, string $exportName=null)
Definition: JavaScriptModuleInstruction.php:49
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:43
‪TYPO3\CMS\Backend\Form\AbstractNode\$data
‪array $data
Definition: AbstractNode.php:43
‪TYPO3\CMS\Backend\Form\Element\BackendLayoutWizardElement\$rows
‪array $rows
Definition: BackendLayoutWizardElement.php:41
‪TYPO3\CMS\Backend\Form\Element\BackendLayoutWizardElement\$rowCount
‪int $rowCount
Definition: BackendLayoutWizardElement.php:49
‪$tca
‪$tca
Definition: sys_file_metadata.php:5
‪TYPO3\CMS\Backend\Form\Element\AbstractFormElement\getLanguageService
‪LanguageService getLanguageService()
Definition: AbstractFormElement.php:448
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50
‪TYPO3\CMS\Backend\Form\Element\BackendLayoutWizardElement\$colCount
‪int $colCount
Definition: BackendLayoutWizardElement.php:45
‪TYPO3\CMS\Backend\Form\Element\AbstractFormElement\renderFieldWizard
‪array renderFieldWizard()
Definition: AbstractFormElement.php:108
‪TYPO3\CMS\Backend\Form\Element\BackendLayoutWizardElement\init
‪init()
Definition: BackendLayoutWizardElement.php:209
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static bool isLoaded($key)
Definition: ExtensionManagementUtility.php:114