[BUGFIX] Improve performance of element rendering on flexforms
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Form / FormDataProvider / TcaFlexProcess.php
1 <?php
2 namespace TYPO3\CMS\Backend\Form\FormDataProvider;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Backend\Form\FormDataCompiler;
18 use TYPO3\CMS\Backend\Form\FormDataGroup\FlexFormSegment;
19 use TYPO3\CMS\Backend\Form\FormDataProviderInterface;
20 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22
23 /**
24 * Process data structures and data values, calculate defaults.
25 *
26 * This is typically the last provider, executed after TcaFlexPrepare
27 */
28 class TcaFlexProcess implements FormDataProviderInterface
29 {
30 /**
31 * Determine possible pageTsConfig overrides and apply them to ds.
32 * Determine available languages and sanitize dv for further processing. Then kick
33 * and validate further details like excluded fields. Finally for each possible
34 * value and ds call FormDataCompiler with set FlexFormSegment group to resolve
35 * single field stuff like item processor functions.
36 *
37 * @param array $result
38 * @return array
39 */
40 public function addData(array $result)
41 {
42 foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfig) {
43 if (empty($fieldConfig['config']['type']) || $fieldConfig['config']['type'] !== 'flex') {
44 continue;
45 }
46
47 $flexIdentifier = $this->getFlexIdentifier($result, $fieldName);
48 $pageTsConfigOfFlex = $this->getPageTsOfFlex($result, $fieldName, $flexIdentifier);
49 $result = $this->modifyOuterDataStructure($result, $fieldName, $pageTsConfigOfFlex);
50 $result = $this->removeExcludeFieldsFromDataStructure($result, $fieldName, $flexIdentifier);
51 $result = $this->removeDisabledFieldsFromDataStructure($result, $fieldName, $pageTsConfigOfFlex);
52 $result = $this->modifyDataStructureAndDataValuesByFlexFormSegmentGroup($result, $fieldName, $pageTsConfigOfFlex);
53 }
54
55 return $result;
56 }
57
58 /**
59 * Take care of ds_pointerField and friends to determine the correct sub array within
60 * TCA config ds.
61 *
62 * Gets extension identifier. Use second pointer field if it's value is not empty, "list" or "*",
63 * else it must be a plugin and first one will be used.
64 * This code basically determines the sub key of ds field:
65 * config = array(
66 * ds => array(
67 * 'aFlexConfig' => '<flexXml ...
68 * ^^^^^^^^^^^
69 * $flexformIdentifier contains "aFlexConfig" after this operation.
70 *
71 * @todo: This method is only implemented half. It basically should do all the
72 * @todo: pointer handling that is done within BackendUtility::getFlexFormDS() to $srcPointer.
73 *
74 * @param array $result Result array
75 * @param string $fieldName Current handle field name
76 * @return string Pointer
77 */
78 protected function getFlexIdentifier(array $result, $fieldName)
79 {
80 // @todo: Current implementation with the "list_type, CType" fallback is rather limited and customized for
81 // @todo: tt_content, also it forces a ds_pointerField to be defined and a casual "default" sub array does not work
82 $pointerFields = !empty($result['processedTca']['columns'][$fieldName]['config']['ds_pointerField'])
83 ? $result['processedTca']['columns'][$fieldName]['config']['ds_pointerField']
84 : 'list_type,CType';
85 $pointerFields = GeneralUtility::trimExplode(',', $pointerFields);
86 $flexformIdentifier = !empty($result['databaseRow'][$pointerFields[0]]) ? $result['databaseRow'][$pointerFields[0]] : '';
87 if (!empty($result['databaseRow'][$pointerFields[1]])
88 && $result['databaseRow'][$pointerFields[1]] !== 'list'
89 && $result['databaseRow'][$pointerFields[1]] !== '*'
90 ) {
91 $flexformIdentifier = $result['databaseRow'][$pointerFields[1]];
92 }
93 if (empty($flexformIdentifier)) {
94 $flexformIdentifier = 'default';
95 }
96
97 return $flexformIdentifier;
98 }
99
100 /**
101 * Determine TCEFORM.aTable.aField.matchingIdentifier
102 *
103 * @param array $result Result array
104 * @param string $fieldName Handled field name
105 * @param string $flexIdentifier Determined identifier
106 * @return array PageTsConfig for this flex
107 */
108 protected function getPageTsOfFlex(array $result, $fieldName, $flexIdentifier)
109 {
110 $table = $result['tableName'];
111 $pageTs = [];
112 if (!empty($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.'][$flexIdentifier . '.'])
113 && is_array($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.'][$flexIdentifier . '.'])) {
114 $pageTs = $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.'][$flexIdentifier . '.'];
115 }
116 return $pageTs;
117 }
118
119 /**
120 * Handle "outer" flex data structure changes like language and sheet
121 * description. Does not change "TCA" or values of single elements
122 *
123 * @param array $result Result array
124 * @param string $fieldName Current handle field name
125 * @param array $pageTsConfig Given pageTsConfig of this flex form
126 * @return array Modified item array
127 */
128 protected function modifyOuterDataStructure(array $result, $fieldName, $pageTsConfig)
129 {
130 $modifiedDataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
131
132 if (isset($modifiedDataStructure['sheets']) && is_array($modifiedDataStructure['sheets'])) {
133 // Handling multiple sheets
134 foreach ($modifiedDataStructure['sheets'] as $sheetName => $sheetStructure) {
135 if (isset($pageTsConfig[$sheetName . '.']) && is_array($pageTsConfig[$sheetName . '.'])) {
136 $pageTsOfSheet = $pageTsConfig[$sheetName . '.'];
137
138 // Remove whole sheet if disabled
139 if (!empty($pageTsOfSheet['disabled'])) {
140 unset($modifiedDataStructure['sheets'][$sheetName]);
141 continue;
142 }
143
144 // sheetTitle, sheetDescription, sheetShortDescr
145 $modifiedDataStructure['sheets'][$sheetName] = $this->modifySingleSheetInformation($sheetStructure, $pageTsOfSheet);
146 }
147 }
148 }
149
150 $result['processedTca']['columns'][$fieldName]['config']['ds'] = $modifiedDataStructure;
151
152 return $result;
153 }
154
155 /**
156 * Removes fields from data structure the user has no access to
157 *
158 * @param array $result Result array
159 * @param string $fieldName Current handle field name
160 * @param string $flexIdentifier Determined identifier
161 * @return array Modified result
162 */
163 protected function removeExcludeFieldsFromDataStructure(array $result, $fieldName, $flexIdentifier)
164 {
165 $dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
166 $backendUser = $this->getBackendUser();
167 if ($backendUser->isAdmin() || !isset($dataStructure['sheets']) || !is_array($dataStructure['sheets'])) {
168 return $result;
169 }
170
171 $userNonExcludeFields = GeneralUtility::trimExplode(',', $backendUser->groupData['non_exclude_fields']);
172 $excludeFieldsPrefix = $result['tableName'] . ':' . $fieldName . ';' . $flexIdentifier . ';';
173 $nonExcludeFields = [];
174 foreach ($userNonExcludeFields as $userNonExcludeField) {
175 if (strpos($userNonExcludeField, $excludeFieldsPrefix) !== false) {
176 $exploded = explode(';', $userNonExcludeField);
177 $sheetName = $exploded[2];
178 $fieldName = $exploded[3];
179 $nonExcludeFields[$sheetName] = $fieldName;
180 }
181 }
182
183 foreach ($dataStructure['sheets'] as $sheetName => $sheetDefinition) {
184 if (!isset($sheetDefinition['ROOT']['el']) || !is_array($sheetDefinition['ROOT']['el'])) {
185 continue;
186 }
187 foreach ($sheetDefinition['ROOT']['el'] as $flexFieldName => $fieldDefinition) {
188 if (!empty($fieldDefinition['exclude']) && empty($nonExcludeFields[$sheetName])) {
189 unset($result['processedTca']['columns'][$fieldName]['config']['ds']['sheets'][$sheetName]['ROOT']['el'][$flexFieldName]);
190 }
191 }
192 }
193
194 return $result;
195 }
196
197 /**
198 * Remove fields from data structure that are disabled in pageTsConfig.
199 *
200 * @param array $result Result array
201 * @param string $fieldName Current handle field name
202 * @param array $pageTsConfig Given pageTsConfig of this flex form
203 * @return array Modified item array
204 */
205 protected function removeDisabledFieldsFromDataStructure(array $result, $fieldName, $pageTsConfig)
206 {
207 $dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
208 if (!isset($dataStructure['sheets']) || !is_array($dataStructure['sheets'])) {
209 return $result;
210 }
211 foreach ($dataStructure['sheets'] as $sheetName => $sheetDefinition) {
212 if (!isset($sheetDefinition['ROOT']['el']) || !is_array($sheetDefinition['ROOT']['el'])
213 || !isset($pageTsConfig[$sheetName . '.'])) {
214 continue;
215 }
216 foreach ($sheetDefinition['ROOT']['el'] as $flexFieldName => $fieldDefinition) {
217 if (!empty($pageTsConfig[$sheetName . '.'][$flexFieldName . '.']['disabled'])) {
218 unset($result['processedTca']['columns'][$fieldName]['config']['ds']['sheets'][$sheetName]['ROOT']['el'][$flexFieldName]);
219 }
220 }
221 }
222 return $result;
223 }
224
225 /**
226 * Feed single flex field and data to FlexFormSegment FormData compiler and merge result.
227 * This one is nasty. Goal is to have processed TCA stuff in DS and also have validated / processed data values.
228 *
229 * Three main parts in this method:
230 * * Process values of existing section container for default values
231 * * Process values and TCA of possible section container and create a default value row for each
232 * * Process TCA of "normal" fields and have default values in data ['templateRows']['containerName'] parallel to section ['el']
233 *
234 * @param array $result Result array
235 * @param string $fieldName Current handle field name
236 * @param array $pageTsConfig Given pageTsConfig of this flex form
237 * @return array Modified item array
238 */
239 protected function modifyDataStructureAndDataValuesByFlexFormSegmentGroup(array $result, $fieldName, $pageTsConfig)
240 {
241 $dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
242 $dataValues = $result['databaseRow'][$fieldName];
243 $tableName = $result['tableName'];
244
245 if (!isset($dataStructure['sheets']) || !is_array($dataStructure['sheets'])) {
246 return $result;
247 }
248
249 /** @var FlexFormSegment $formDataGroup */
250 $formDataGroup = GeneralUtility::makeInstance(FlexFormSegment::class);
251 /** @var FormDataCompiler $formDataCompiler */
252 $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
253
254 foreach ($dataStructure['sheets'] as $dataStructureSheetName => $dataStructureSheetDefinition) {
255 if (!isset($dataStructureSheetDefinition['ROOT']['el']) || !is_array($dataStructureSheetDefinition['ROOT']['el'])) {
256 continue;
257 }
258 $dataStructureSheetElements = $dataStructureSheetDefinition['ROOT']['el'];
259
260 // Prepare pageTsConfig of this sheet
261 $pageTsConfig['TCEFORM.'][$tableName . '.'] = [];
262 if (isset($pageTsConfig[$dataStructureSheetName . '.']) && is_array($pageTsConfig[$dataStructureSheetName . '.'])) {
263 $pageTsConfig['TCEFORM.'][$tableName . '.'] = $pageTsConfig[$dataStructureSheetName . '.'];
264 }
265
266 $tcaNewColumns = [];
267 $tcaEditColumns = [];
268 $tcaValueArray = [
269 'uid' => $result['databaseRow']['uid'],
270 ];
271 foreach ($dataStructureSheetElements as $dataStructureSheetElementName => $dataStructureSheetElementDefinition) {
272 if (isset($dataStructureSheetElementDefinition['type']) && $dataStructureSheetElementDefinition['type'] === 'array'
273 && isset($dataStructureSheetElementDefinition['section']) && $dataStructureSheetElementDefinition['section'] === '1'
274 ) {
275 // A section
276
277 // Existing section container elements
278 if (isset($dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['el'])
279 && is_array($dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['el'])
280 ) {
281 $containerArray = $dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['el'];
282 foreach ($containerArray as $aContainerNumber => $aContainerArray) {
283 if (is_array($aContainerArray)) {
284 foreach ($aContainerArray as $aContainerName => $aContainerElementArray) {
285 if ($aContainerName === '_TOGGLE') {
286 // Don't handle internal toggle state field
287 continue;
288 }
289 if (!isset($dataStructureSheetElements[$dataStructureSheetElementName]['el'][$aContainerName])) {
290 // Container not defined in ds
291 continue;
292 }
293
294 $newColumns = [];
295 $editColumns = [];
296 $valueArray = [
297 'uid' => $result['databaseRow']['uid'],
298 ];
299 foreach ($dataStructureSheetElements[$dataStructureSheetElementName]['el'][$aContainerName]['el'] as $singleFieldName => $singleFieldConfiguration) {
300 // $singleFieldValueArray = ['data']['sSections']['lDEF']['section_1']['el']['1']['container_1']['el']['element_1']
301 $singleFieldValueArray = [];
302 if (isset($aContainerElementArray['el'][$singleFieldName])
303 && is_array($aContainerElementArray['el'][$singleFieldName])
304 ) {
305 $singleFieldValueArray = $aContainerElementArray['el'][$singleFieldName];
306 }
307
308 if (array_key_exists('vDEF', $singleFieldValueArray)) {
309 $editColumns[$singleFieldName] = $singleFieldConfiguration;
310 $valueArray[$singleFieldName] = $singleFieldValueArray['vDEF'];
311 } else {
312 $newColumns[$singleFieldName] = $singleFieldConfiguration;
313 }
314 }
315
316 $inputToFlexFormSegment = [
317 'tableName' => $result['tableName'],
318 'command' => '',
319 // It is currently not possible to have pageTsConfig for section container
320 'pageTsConfig' => [],
321 'databaseRow' => $valueArray,
322 'processedTca' => [
323 'ctrl' => [],
324 'columns' => [],
325 ],
326 ];
327
328 if (!empty($newColumns)) {
329 $inputToFlexFormSegment['command'] = 'new';
330 $inputToFlexFormSegment['processedTca']['columns'] = $newColumns;
331 $flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
332
333 foreach ($newColumns as $singleFieldName => $_) {
334 // Set data value result
335 if (array_key_exists($singleFieldName, $flexSegmentResult['databaseRow'])) {
336 $result['databaseRow'][$fieldName]
337 ['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]
338 ['el'][$aContainerNumber][$aContainerName]['el'][$singleFieldName]['vDEF'] =
339 $flexSegmentResult['databaseRow'][$singleFieldName];
340 }
341 // Set TCA structure result, actually, this call *might* be obsolete since the "dummy"
342 // handling below will set it again.
343 $result['processedTca']['columns'][$fieldName]['config']['ds']
344 ['sheets'][$dataStructureSheetName]['ROOT']['el']
345 [$dataStructureSheetElementName]['el'][$aContainerName]['el'][$singleFieldName] =
346 $flexSegmentResult['processedTca']['columns'][$singleFieldName];
347 }
348 }
349
350 if (!empty($editColumns)) {
351 $inputToFlexFormSegment['command'] = 'edit';
352 $inputToFlexFormSegment['processedTca']['columns'] = $editColumns;
353 $flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
354
355 foreach ($editColumns as $singleFieldName => $_) {
356 // Set data value result
357 if (array_key_exists($singleFieldName, $flexSegmentResult['databaseRow'])) {
358 $result['databaseRow'][$fieldName]
359 ['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]
360 ['el'][$aContainerNumber][$aContainerName]['el'][$singleFieldName]['vDEF'] =
361 $flexSegmentResult['databaseRow'][$singleFieldName];
362 }
363 // Set TCA structure result, actually, this call *might* be obsolete since the "dummy"
364 // handling below will set it again.
365 $result['processedTca']['columns'][$fieldName]['config']['ds']
366 ['sheets'][$dataStructureSheetName]['ROOT']['el']
367 [$dataStructureSheetElementName]['el'][$aContainerName]['el'][$singleFieldName] =
368 $flexSegmentResult['processedTca']['columns'][$singleFieldName];
369 }
370 }
371 }
372 }
373 }
374 // End of existing data value handling
375 } else {
376 // Force the section to be an empty array if there are no existing containers
377 $result['databaseRow'][$fieldName]
378 ['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['el'] = [];
379 }
380
381 // Prepare "fresh" row for every possible container
382 if (isset($dataStructureSheetElements[$dataStructureSheetElementName]['el']) && is_array($dataStructureSheetElements[$dataStructureSheetElementName]['el'])) {
383 foreach ($dataStructureSheetElements[$dataStructureSheetElementName]['el'] as $possibleContainerName => $possibleContainerConfiguration) {
384 if (isset($possibleContainerConfiguration['el']) && is_array($possibleContainerConfiguration['el'])) {
385 // Initialize result data array templateRows
386 $result['databaseRow'][$fieldName]
387 ['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['templateRows']
388 [$possibleContainerName]['el']
389 = [];
390 foreach ($possibleContainerConfiguration['el'] as $singleFieldName => $singleFieldConfiguration) {
391 $inputToFlexFormSegment = [
392 'tableName' => $result['tableName'],
393 'command' => 'new',
394 'pageTsConfig' => [],
395 'databaseRow' => [
396 'uid' => $result['databaseRow']['uid'],
397 ],
398 'processedTca' => [
399 'ctrl' => [],
400 'columns' => [
401 $singleFieldName => $singleFieldConfiguration,
402 ],
403 ],
404 ];
405 $flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
406 if (array_key_exists($singleFieldName, $flexSegmentResult['databaseRow'])) {
407 $result['databaseRow'][$fieldName]
408 ['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['templateRows']
409 [$possibleContainerName]['el'][$singleFieldName]['vDEF']
410 = $flexSegmentResult['databaseRow'][$singleFieldName];
411 }
412 $result['processedTca']['columns'][$fieldName]['config']['ds']
413 ['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]['el']
414 [$possibleContainerName]['el'][$singleFieldName]
415 = $flexSegmentResult['processedTca']['columns'][$singleFieldName];
416 }
417 }
418 }
419 } // End of preparation for each possible container
420
421 // type without section is not ok
422 } elseif (isset($dataStructureSheetElementDefinition['type']) || isset($dataStructureSheetElementDefinition['section'])) {
423 throw new \UnexpectedValueException(
424 'Broken data structure on field name ' . $fieldName . '. section without type or vice versa is not allowed',
425 1440685208
426 );
427
428 // A "normal" TCA element
429 } else {
430 if (isset($dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName])
431 && array_key_exists('vDEF', $dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName])
432 ) {
433 $tcaEditColumns[$dataStructureSheetElementName] = $dataStructureSheetElementDefinition;
434 $tcaValueArray[$dataStructureSheetElementName] = $dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['vDEF'];
435 } else {
436 $tcaNewColumns[$dataStructureSheetElementName] = $dataStructureSheetElementDefinition;
437 }
438
439 } // End of single element handling
440 }
441
442 // process the tca columns for the current sheet
443 $inputToFlexFormSegment = [
444 // tablename of "parent" is given down for inline elements to resolve correctly
445 'tableName' => $result['tableName'],
446 'command' => '',
447 'pageTsConfig' => $pageTsConfig,
448 'databaseRow' => $tcaValueArray,
449 'processedTca' => [
450 'ctrl' => [],
451 'columns' => [],
452 ],
453 ];
454
455 if (!empty($tcaNewColumns)) {
456 $inputToFlexFormSegment['command'] = 'new';
457 $inputToFlexFormSegment['processedTca']['columns'] = $tcaNewColumns;
458 $flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
459
460 foreach ($tcaNewColumns as $dataStructureSheetElementName => $_) {
461 // Set data value result
462 if (array_key_exists($dataStructureSheetElementName, $flexSegmentResult['databaseRow'])) {
463 $result['databaseRow'][$fieldName]
464 ['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['vDEF']
465 = $flexSegmentResult['databaseRow'][$dataStructureSheetElementName];
466 }
467 // Set TCA structure result
468 $result['processedTca']['columns'][$fieldName]['config']['ds']
469 ['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]
470 = $flexSegmentResult['processedTca']['columns'][$dataStructureSheetElementName];
471 }
472 }
473
474 if (!empty($tcaEditColumns)) {
475 $inputToFlexFormSegment['command'] = 'edit';
476 $inputToFlexFormSegment['processedTca']['columns'] = $tcaEditColumns;
477 $flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
478
479 foreach ($tcaEditColumns as $dataStructureSheetElementName => $_) {
480 // Set data value result
481 if (array_key_exists($dataStructureSheetElementName, $flexSegmentResult['databaseRow'])) {
482 $result['databaseRow'][$fieldName]
483 ['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['vDEF']
484 = $flexSegmentResult['databaseRow'][$dataStructureSheetElementName];
485 }
486 // Set TCA structure result
487 $result['processedTca']['columns'][$fieldName]['config']['ds']
488 ['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]
489 = $flexSegmentResult['processedTca']['columns'][$dataStructureSheetElementName];
490 }
491 }
492 }
493
494 return $result;
495 }
496
497 /**
498 * Modify data structure of a single "sheet"
499 * Sets "secondary" data like sheet names and so on, but does NOT modify single elements
500 *
501 * @param array $dataStructure Given data structure
502 * @param array $pageTsOfSheet Page Ts config of given field
503 * @return array Modified data structure
504 */
505 protected function modifySingleSheetInformation(array $dataStructure, array $pageTsOfSheet)
506 {
507 // Return if no elements defined
508 if (!isset($dataStructure['ROOT']['el']) || !is_array($dataStructure['ROOT']['el'])) {
509 return $dataStructure;
510 }
511
512 // Rename sheet (tab)
513 if (!empty($pageTsOfSheet['sheetTitle'])) {
514 $dataStructure['ROOT']['sheetTitle'] = $pageTsOfSheet['sheetTitle'];
515 }
516 // Set sheet description (tab)
517 if (!empty($pageTsOfSheet['sheetDescription'])) {
518 $dataStructure['ROOT']['sheetDescription'] = $pageTsOfSheet['sheetDescription'];
519 }
520 // Set sheet short description (tab)
521 if (!empty($pageTsOfSheet['sheetShortDescr'])) {
522 $dataStructure['ROOT']['sheetShortDescr'] = $pageTsOfSheet['sheetShortDescr'];
523 }
524
525 return $dataStructure;
526 }
527
528 /**
529 * @return BackendUserAuthentication
530 */
531 protected function getBackendUser()
532 {
533 return $GLOBALS['BE_USER'];
534 }
535 }