[BUGFIX] FormEngine: Exception on inline/section in flex container
[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 $result = $this->addDataStructurePointersToMetaData($result, $fieldName);
54 }
55
56 return $result;
57 }
58
59 /**
60 * Take care of ds_pointerField and friends to determine the correct sub array within
61 * TCA config ds.
62 *
63 * Gets extension identifier. Use second pointer field if it's value is not empty, "list" or "*",
64 * else it must be a plugin and first one will be used.
65 * This code basically determines the sub key of ds field:
66 * config = array(
67 * ds => array(
68 * 'aFlexConfig' => '<flexXml ...
69 * ^^^^^^^^^^^
70 * $flexformIdentifier contains "aFlexConfig" after this operation.
71 *
72 * @todo: This method is only implemented half. It basically should do all the
73 * @todo: pointer handling that is done within BackendUtility::getFlexFormDS() to $srcPointer.
74 *
75 * @param array $result Result array
76 * @param string $fieldName Current handle field name
77 * @return string Pointer
78 */
79 protected function getFlexIdentifier(array $result, $fieldName)
80 {
81 // @todo: Current implementation with the "list_type, CType" fallback is rather limited and customized for
82 // @todo: tt_content, also it forces a ds_pointerField to be defined and a casual "default" sub array does not work
83 $pointerFields = !empty($result['processedTca']['columns'][$fieldName]['config']['ds_pointerField'])
84 ? $result['processedTca']['columns'][$fieldName]['config']['ds_pointerField']
85 : 'list_type,CType';
86 $pointerFields = GeneralUtility::trimExplode(',', $pointerFields);
87 $flexformIdentifier = !empty($result['databaseRow'][$pointerFields[0]]) ? $result['databaseRow'][$pointerFields[0]] : '';
88 if (!empty($result['databaseRow'][$pointerFields[1]])
89 && $result['databaseRow'][$pointerFields[1]] !== 'list'
90 && $result['databaseRow'][$pointerFields[1]] !== '*'
91 ) {
92 $flexformIdentifier = $result['databaseRow'][$pointerFields[1]];
93 }
94 if (empty($flexformIdentifier)) {
95 $flexformIdentifier = 'default';
96 }
97
98 return $flexformIdentifier;
99 }
100
101 /**
102 * Determine TCEFORM.aTable.aField.matchingIdentifier
103 *
104 * @param array $result Result array
105 * @param string $fieldName Handled field name
106 * @param string $flexIdentifier Determined identifier
107 * @return array PageTsConfig for this flex
108 */
109 protected function getPageTsOfFlex(array $result, $fieldName, $flexIdentifier)
110 {
111 $table = $result['tableName'];
112 $pageTs = [];
113 if (!empty($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.'][$flexIdentifier . '.'])
114 && is_array($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.'][$flexIdentifier . '.'])) {
115 $pageTs = $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.'][$flexIdentifier . '.'];
116 }
117 return $pageTs;
118 }
119
120 /**
121 * Handle "outer" flex data structure changes like language and sheet
122 * description. Does not change "TCA" or values of single elements
123 *
124 * @param array $result Result array
125 * @param string $fieldName Current handle field name
126 * @param array $pageTsConfig Given pageTsConfig of this flex form
127 * @return array Modified item array
128 */
129 protected function modifyOuterDataStructure(array $result, $fieldName, $pageTsConfig)
130 {
131 $modifiedDataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
132
133 if (isset($modifiedDataStructure['sheets']) && is_array($modifiedDataStructure['sheets'])) {
134 // Handling multiple sheets
135 foreach ($modifiedDataStructure['sheets'] as $sheetName => $sheetStructure) {
136 if (isset($pageTsConfig[$sheetName . '.']) && is_array($pageTsConfig[$sheetName . '.'])) {
137 $pageTsOfSheet = $pageTsConfig[$sheetName . '.'];
138
139 // Remove whole sheet if disabled
140 if (!empty($pageTsOfSheet['disabled'])) {
141 unset($modifiedDataStructure['sheets'][$sheetName]);
142 continue;
143 }
144
145 // sheetTitle, sheetDescription, sheetShortDescr
146 $modifiedDataStructure['sheets'][$sheetName] = $this->modifySingleSheetInformation($sheetStructure, $pageTsOfSheet);
147 }
148 }
149 }
150
151 $result['processedTca']['columns'][$fieldName]['config']['ds'] = $modifiedDataStructure;
152
153 return $result;
154 }
155
156 /**
157 * Removes fields from data structure the user has no access to
158 *
159 * @param array $result Result array
160 * @param string $fieldName Current handle field name
161 * @param string $flexIdentifier Determined identifier
162 * @return array Modified result
163 */
164 protected function removeExcludeFieldsFromDataStructure(array $result, $fieldName, $flexIdentifier)
165 {
166 $dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
167 $backendUser = $this->getBackendUser();
168 if ($backendUser->isAdmin() || !isset($dataStructure['sheets']) || !is_array($dataStructure['sheets'])) {
169 return $result;
170 }
171
172 $userNonExcludeFields = GeneralUtility::trimExplode(',', $backendUser->groupData['non_exclude_fields']);
173 $excludeFieldsPrefix = $result['tableName'] . ':' . $fieldName . ';' . $flexIdentifier . ';';
174 $nonExcludeFields = [];
175 foreach ($userNonExcludeFields as $userNonExcludeField) {
176 if (strpos($userNonExcludeField, $excludeFieldsPrefix) !== false) {
177 $exploded = explode(';', $userNonExcludeField);
178 $sheetName = $exploded[2];
179 $allowedFlexFieldName = $exploded[3];
180 $nonExcludeFields[$sheetName][$allowedFlexFieldName] = true;
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']) && !isset($nonExcludeFields[$sheetName][$flexFieldName])) {
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 * @throws \UnexpectedValueException
239 */
240 protected function modifyDataStructureAndDataValuesByFlexFormSegmentGroup(array $result, $fieldName, $pageTsConfig)
241 {
242 $dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
243 $dataValues = $result['databaseRow'][$fieldName];
244 $tableName = $result['tableName'];
245
246 if (!isset($dataStructure['sheets']) || !is_array($dataStructure['sheets'])) {
247 return $result;
248 }
249
250 /** @var FlexFormSegment $formDataGroup */
251 $formDataGroup = GeneralUtility::makeInstance(FlexFormSegment::class);
252 /** @var FormDataCompiler $formDataCompiler */
253 $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
254
255 foreach ($dataStructure['sheets'] as $dataStructureSheetName => $dataStructureSheetDefinition) {
256 if (!isset($dataStructureSheetDefinition['ROOT']['el']) || !is_array($dataStructureSheetDefinition['ROOT']['el'])) {
257 continue;
258 }
259 $dataStructureSheetElements = $dataStructureSheetDefinition['ROOT']['el'];
260
261 // Prepare pageTsConfig of this sheet
262 $pageTsConfig['TCEFORM.'][$tableName . '.'] = [];
263 if (isset($pageTsConfig[$dataStructureSheetName . '.']) && is_array($pageTsConfig[$dataStructureSheetName . '.'])) {
264 $pageTsConfig['TCEFORM.'][$tableName . '.'] = $pageTsConfig[$dataStructureSheetName . '.'];
265 }
266
267 // List of "new" tca fields that have no value within the flexform, yet. Those will be compiled in one go later.
268 $tcaNewColumns = [];
269 // List of "edit" tca fields that have a value in flexform, already. Those will be compiled in one go later.
270 $tcaEditColumns = [];
271 // Contains the data values for the "edit" tca fields.
272 $tcaValueArray = [
273 'uid' => $result['databaseRow']['uid'],
274 ];
275 foreach ($dataStructureSheetElements as $dataStructureSheetElementName => $dataStructureSheetElementDefinition) {
276 if (isset($dataStructureSheetElementDefinition['type']) && $dataStructureSheetElementDefinition['type'] === 'array'
277 && isset($dataStructureSheetElementDefinition['section']) && (string)$dataStructureSheetElementDefinition['section'] === '1'
278 ) {
279 // A section
280
281 // Existing section container elements
282 if (isset($dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['el'])
283 && is_array($dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['el'])
284 ) {
285 $containerArray = $dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['el'];
286 foreach ($containerArray as $aContainerNumber => $aContainerArray) {
287 if (is_array($aContainerArray)) {
288 foreach ($aContainerArray as $aContainerName => $aContainerElementArray) {
289 if ($aContainerName === '_TOGGLE') {
290 // Don't handle internal toggle state field
291 continue;
292 }
293 if (!isset($dataStructureSheetElements[$dataStructureSheetElementName]['el'][$aContainerName])) {
294 // Container not defined in ds
295 continue;
296 }
297
298 $newColumns = [];
299 $editColumns = [];
300 $valueArray = [
301 'uid' => $result['databaseRow']['uid'],
302 ];
303 foreach ($dataStructureSheetElements[$dataStructureSheetElementName]['el'][$aContainerName]['el'] as $singleFieldName => $singleFieldConfiguration) {
304 // $singleFieldValueArray = ['data']['sSections']['lDEF']['section_1']['el']['1']['container_1']['el']['element_1']
305 $singleFieldValueArray = [];
306 if (isset($aContainerElementArray['el'][$singleFieldName])
307 && is_array($aContainerElementArray['el'][$singleFieldName])
308 ) {
309 $singleFieldValueArray = $aContainerElementArray['el'][$singleFieldName];
310 }
311
312 if (array_key_exists('vDEF', $singleFieldValueArray)) {
313 $editColumns[$singleFieldName] = $singleFieldConfiguration;
314 $valueArray[$singleFieldName] = $singleFieldValueArray['vDEF'];
315 } else {
316 $newColumns[$singleFieldName] = $singleFieldConfiguration;
317 }
318 }
319
320 $inputToFlexFormSegment = [
321 'tableName' => $result['tableName'],
322 'command' => '',
323 // It is currently not possible to have pageTsConfig for section container
324 'pageTsConfig' => [],
325 'databaseRow' => $valueArray,
326 'processedTca' => [
327 'ctrl' => [],
328 'columns' => [],
329 ],
330 'flexParentDatabaseRow' => $result['databaseRow'],
331 ];
332
333 if (!empty($newColumns)) {
334 $inputToFlexFormSegment['command'] = 'new';
335 $inputToFlexFormSegment['processedTca']['columns'] = $newColumns;
336 $flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
337
338 foreach ($newColumns as $singleFieldName => $_) {
339 // Set data value result
340 if (array_key_exists($singleFieldName, $flexSegmentResult['databaseRow'])) {
341 $result['databaseRow'][$fieldName]
342 ['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]
343 ['el'][$aContainerNumber][$aContainerName]['el'][$singleFieldName]['vDEF'] =
344 $flexSegmentResult['databaseRow'][$singleFieldName];
345 }
346 // Set TCA structure result, actually, this call *might* be obsolete since the "dummy"
347 // handling below will set it again.
348 $result['processedTca']['columns'][$fieldName]['config']['ds']
349 ['sheets'][$dataStructureSheetName]['ROOT']['el']
350 [$dataStructureSheetElementName]['el'][$aContainerName]['el'][$singleFieldName] =
351 $flexSegmentResult['processedTca']['columns'][$singleFieldName];
352 }
353 }
354
355 if (!empty($editColumns)) {
356 $inputToFlexFormSegment['command'] = 'edit';
357 $inputToFlexFormSegment['processedTca']['columns'] = $editColumns;
358 $flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
359
360 foreach ($editColumns as $singleFieldName => $_) {
361 // Set data value result
362 if (array_key_exists($singleFieldName, $flexSegmentResult['databaseRow'])) {
363 $result['databaseRow'][$fieldName]
364 ['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]
365 ['el'][$aContainerNumber][$aContainerName]['el'][$singleFieldName]['vDEF'] =
366 $flexSegmentResult['databaseRow'][$singleFieldName];
367 }
368 // Set TCA structure result, actually, this call *might* be obsolete since the "dummy"
369 // handling below will set it again.
370 $result['processedTca']['columns'][$fieldName]['config']['ds']
371 ['sheets'][$dataStructureSheetName]['ROOT']['el']
372 [$dataStructureSheetElementName]['el'][$aContainerName]['el'][$singleFieldName] =
373 $flexSegmentResult['processedTca']['columns'][$singleFieldName];
374 }
375 }
376 }
377 }
378 }
379 // End of existing data value handling
380 } else {
381 // Force the section to be an empty array if there are no existing containers
382 $result['databaseRow'][$fieldName]
383 ['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['el'] = [];
384 }
385
386 // Prepare "fresh" row for every possible container
387 if (isset($dataStructureSheetElements[$dataStructureSheetElementName]['el']) && is_array($dataStructureSheetElements[$dataStructureSheetElementName]['el'])) {
388 foreach ($dataStructureSheetElements[$dataStructureSheetElementName]['el'] as $possibleContainerName => $possibleContainerConfiguration) {
389 if (isset($possibleContainerConfiguration['el']) && is_array($possibleContainerConfiguration['el'])) {
390 // Initialize result data array templateRows
391 $result['databaseRow'][$fieldName]
392 ['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['templateRows']
393 [$possibleContainerName]['el']
394 = [];
395 foreach ($possibleContainerConfiguration['el'] as $singleFieldName => $singleFieldConfiguration) {
396
397 // Nesting type=inline in container sections is not supported. Throw an exception if configured.
398 if (isset($singleFieldConfiguration['config']['type']) && $singleFieldConfiguration['config']['type'] === 'inline') {
399 throw new \UnexpectedValueException(
400 'Invalid flex form data structure on field name "' . $fieldName . '" with element "' . $singleFieldName . '"'
401 . ' in section container "' . $possibleContainerName . '": Nesting inline elements in flex form'
402 . ' sections is not allowed.',
403 1458745468
404 );
405 }
406
407 // Nesting sections is not supported. Throw an exception if configured.
408 if (is_array($singleFieldConfiguration)
409 && isset($singleFieldConfiguration['type']) && $singleFieldConfiguration['type'] === 'array'
410 && isset($singleFieldConfiguration['section']) && (string)$singleFieldConfiguration['section'] === '1'
411 ) {
412 throw new \UnexpectedValueException(
413 'Invalid flex form data structure on field name "' . $fieldName . '" with element "' . $singleFieldName . '"'
414 . ' in section container "' . $possibleContainerName . '": Nesting sections in container elements'
415 . ' sections is not allowed.',
416 1458745712
417 );
418 }
419
420 $inputToFlexFormSegment = [
421 'tableName' => $result['tableName'],
422 'command' => 'new',
423 'pageTsConfig' => [],
424 'databaseRow' => [
425 'uid' => $result['databaseRow']['uid'],
426 ],
427 'processedTca' => [
428 'ctrl' => [],
429 'columns' => [
430 $singleFieldName => $singleFieldConfiguration,
431 ],
432 ],
433 'flexParentDatabaseRow' => $result['databaseRow'],
434 ];
435 $flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
436 if (array_key_exists($singleFieldName, $flexSegmentResult['databaseRow'])) {
437 $result['databaseRow'][$fieldName]
438 ['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['templateRows']
439 [$possibleContainerName]['el'][$singleFieldName]['vDEF']
440 = $flexSegmentResult['databaseRow'][$singleFieldName];
441 }
442 $result['processedTca']['columns'][$fieldName]['config']['ds']
443 ['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]['el']
444 [$possibleContainerName]['el'][$singleFieldName]
445 = $flexSegmentResult['processedTca']['columns'][$singleFieldName];
446 }
447 }
448 }
449 } // End of preparation for each possible container
450
451 // type without section is not ok
452 } elseif (isset($dataStructureSheetElementDefinition['type']) || isset($dataStructureSheetElementDefinition['section'])) {
453 throw new \UnexpectedValueException(
454 'Broken data structure on field name ' . $fieldName . '. section without type or vice versa is not allowed',
455 1440685208
456 );
457
458 // A "normal" TCA element
459 } else {
460 if (isset($dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName])
461 && array_key_exists('vDEF', $dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName])
462 ) {
463 $tcaEditColumns[$dataStructureSheetElementName] = $dataStructureSheetElementDefinition;
464 $tcaValueArray[$dataStructureSheetElementName] = $dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['vDEF'];
465 } else {
466 $tcaNewColumns[$dataStructureSheetElementName] = $dataStructureSheetElementDefinition;
467 }
468 } // End of single element handling
469 }
470
471 // process the tca columns for the current sheet
472 $inputToFlexFormSegment = [
473 // tablename of "parent" is given down for inline elements to resolve correctly
474 'tableName' => $result['tableName'],
475 'command' => '',
476 'pageTsConfig' => $pageTsConfig,
477 'databaseRow' => $tcaValueArray,
478 'processedTca' => [
479 'ctrl' => [],
480 'columns' => [],
481 ],
482 'flexParentDatabaseRow' => $result['databaseRow'],
483 ];
484
485 if (!empty($tcaNewColumns)) {
486 $inputToFlexFormSegment['command'] = 'new';
487 $inputToFlexFormSegment['processedTca']['columns'] = $tcaNewColumns;
488 $flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
489
490 foreach ($tcaNewColumns as $dataStructureSheetElementName => $_) {
491 // Set data value result
492 if (array_key_exists($dataStructureSheetElementName, $flexSegmentResult['databaseRow'])) {
493 $result['databaseRow'][$fieldName]
494 ['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['vDEF']
495 = $flexSegmentResult['databaseRow'][$dataStructureSheetElementName];
496 }
497 // Set TCA structure result
498 $result['processedTca']['columns'][$fieldName]['config']['ds']
499 ['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]
500 = $flexSegmentResult['processedTca']['columns'][$dataStructureSheetElementName];
501 }
502 }
503
504 if (!empty($tcaEditColumns)) {
505 $inputToFlexFormSegment['command'] = 'edit';
506 $inputToFlexFormSegment['processedTca']['columns'] = $tcaEditColumns;
507 $flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
508
509 foreach ($tcaEditColumns as $dataStructureSheetElementName => $_) {
510 // Set data value result
511 if (array_key_exists($dataStructureSheetElementName, $flexSegmentResult['databaseRow'])) {
512 $result['databaseRow'][$fieldName]
513 ['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['vDEF']
514 = $flexSegmentResult['databaseRow'][$dataStructureSheetElementName];
515 }
516 // Set TCA structure result
517 $result['processedTca']['columns'][$fieldName]['config']['ds']
518 ['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]
519 = $flexSegmentResult['processedTca']['columns'][$dataStructureSheetElementName];
520 }
521 }
522 }
523
524 return $result;
525 }
526
527 /**
528 * Modify data structure of a single "sheet"
529 * Sets "secondary" data like sheet names and so on, but does NOT modify single elements
530 *
531 * @param array $dataStructure Given data structure
532 * @param array $pageTsOfSheet Page Ts config of given field
533 * @return array Modified data structure
534 */
535 protected function modifySingleSheetInformation(array $dataStructure, array $pageTsOfSheet)
536 {
537 // Return if no elements defined
538 if (!isset($dataStructure['ROOT']['el']) || !is_array($dataStructure['ROOT']['el'])) {
539 return $dataStructure;
540 }
541
542 // Rename sheet (tab)
543 if (!empty($pageTsOfSheet['sheetTitle'])) {
544 $dataStructure['ROOT']['sheetTitle'] = $pageTsOfSheet['sheetTitle'];
545 }
546 // Set sheet description (tab)
547 if (!empty($pageTsOfSheet['sheetDescription'])) {
548 $dataStructure['ROOT']['sheetDescription'] = $pageTsOfSheet['sheetDescription'];
549 }
550 // Set sheet short description (tab)
551 if (!empty($pageTsOfSheet['sheetShortDescr'])) {
552 $dataStructure['ROOT']['sheetShortDescr'] = $pageTsOfSheet['sheetShortDescr'];
553 }
554
555 return $dataStructure;
556 }
557
558 /**
559 * Add fields and values used by ds_pointerField to the meta data array so they can be used in AJAX context during rendering.
560 *
561 * @todo: This method is a stopgap measure to get required information into the AJAX controller
562 *
563 * @param array $result Result array
564 * @param string $fieldName Current handle field name
565 * @return array
566 * @internal
567 */
568 protected function addDataStructurePointersToMetaData(array $result, $fieldName)
569 {
570 if (empty($result['processedTca']['columns'][$fieldName]['config']['ds_pointerField'])) {
571 return $result;
572 }
573
574 $pointerFields = GeneralUtility::trimExplode(
575 ',',
576 $result['processedTca']['columns'][$fieldName]['config']['ds_pointerField']
577 );
578 $dsPointers = [
579 $pointerFields[0] => !empty($result['databaseRow'][$pointerFields[0]]) ? $result['databaseRow'][$pointerFields[0]] : ''
580 ];
581
582 if (!empty($pointerFields[1])) {
583 $dsPointers[$pointerFields[1]] =
584 !empty($result['databaseRow'][$pointerFields[1]]) ? $result['databaseRow'][$pointerFields[1]] : '';
585 }
586 $result['processedTca']['columns'][$fieldName]['config']['ds']['meta']['dataStructurePointers'] = $dsPointers;
587 return $result;
588 }
589
590 /**
591 * @return BackendUserAuthentication
592 */
593 protected function getBackendUser()
594 {
595 return $GLOBALS['BE_USER'];
596 }
597
598 }