TYPO3 CMS  TYPO3_8-7
TcaFlexProcess.php
Go to the documentation of this file.
1 <?php
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 
22 
29 {
41  public function addData(array $result)
42  {
43  foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfig) {
44  if (empty($fieldConfig['config']['type']) || $fieldConfig['config']['type'] !== 'flex') {
45  continue;
46  }
47  if (!isset($result['processedTca']['columns'][$fieldName]['config']['dataStructureIdentifier'])) {
48  throw new \RuntimeException(
49  'Data structure identifier must be set, typically by executing TcaFlexPrepare data provider before',
50  1480765571
51  );
52  }
53  $this->scanForInvalidSectionContainerTca($result, $fieldName);
54  $dataStructureIdentifier = $result['processedTca']['columns'][$fieldName]['config']['dataStructureIdentifier'];
55  $simpleDataStructureIdentifier = $this->getSimplifiedDataStructureIdentifier($dataStructureIdentifier);
56  $pageTsConfigOfFlex = $this->getPageTsOfFlex($result, $fieldName, $simpleDataStructureIdentifier);
57  $result = $this->modifyOuterDataStructure($result, $fieldName, $pageTsConfigOfFlex);
58  $result = $this->removeExcludeFieldsFromDataStructure($result, $fieldName, $simpleDataStructureIdentifier);
59  $result = $this->removeDisabledFieldsFromDataStructure($result, $fieldName, $pageTsConfigOfFlex);
60  // A "normal" call opening a record: Process data structure and field values
61  // This is called for "new" container ajax request too, since display conditions from section container
62  // elements can access record values of other flex form sheets and we need their values then.
63  $result = $this->modifyDataStructureAndDataValuesByFlexFormSegmentGroup($result, $fieldName, $pageTsConfigOfFlex);
64  if (!empty($result['flexSectionContainerPreparation'])) {
65  // Create data and default values for a new section container, set by FormFlexAjaxController
66  $result = $this->prepareNewSectionContainer($result, $fieldName);
67  }
68  }
69 
70  return $result;
71  }
72 
81  protected function scanForInvalidSectionContainerTca(array $result, string $fieldName)
82  {
83  $dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
84  if (!isset($dataStructure['sheets']) || !is_array($dataStructure['sheets'])) {
85  return;
86  }
87  foreach ($dataStructure['sheets'] as $dataStructureSheetName => $dataStructureSheetDefinition) {
88  if (!isset($dataStructureSheetDefinition['ROOT']['el']) || !is_array($dataStructureSheetDefinition['ROOT']['el'])) {
89  continue;
90  }
91  $dataStructureFields = $dataStructureSheetDefinition['ROOT']['el'];
92  foreach ($dataStructureFields as $dataStructureFieldName => $dataStructureFieldDefinition) {
93  if (isset($dataStructureFieldDefinition['type']) && $dataStructureFieldDefinition['type'] === 'array'
94  && isset($dataStructureFieldDefinition['section']) && (string)$dataStructureFieldDefinition['section'] === '1'
95  ) {
96  if (isset($dataStructureFieldDefinition['el']) && is_array($dataStructureFieldDefinition['el'])) {
97  foreach ($dataStructureFieldDefinition['el'] as $containerName => $containerConfiguration) {
98  if (isset($containerConfiguration['el']) && is_array($containerConfiguration['el'])) {
99  foreach ($containerConfiguration['el'] as $singleFieldName => $singleFieldConfiguration) {
100  // Nesting type=inline in container sections is not supported. Throw an exception if configured.
101  if (isset($singleFieldConfiguration['config']['type']) && $singleFieldConfiguration['config']['type'] === 'inline') {
102  throw new \UnexpectedValueException(
103  'Invalid flex form data structure on field name "' . $fieldName . '" with element "' . $singleFieldName . '"'
104  . ' in section container "' . $containerName . '": Nesting inline elements in flex form'
105  . ' sections is not allowed.',
106  1458745468
107  );
108  }
109 
110  // Nesting sections is not supported. Throw an exception if configured.
111  if (is_array($singleFieldConfiguration)
112  && isset($singleFieldConfiguration['type']) && $singleFieldConfiguration['type'] === 'array'
113  && isset($singleFieldConfiguration['section']) && (string)$singleFieldConfiguration['section'] === '1'
114  ) {
115  throw new \UnexpectedValueException(
116  'Invalid flex form data structure on field name "' . $fieldName . '" with element "' . $singleFieldName . '"'
117  . ' in section container "' . $containerName . '": Nesting sections in container elements'
118  . ' sections is not allowed.',
119  1458745712
120  );
121  }
122 
123  // Nesting type="select" and type="group" within section containers is not supported,
124  // the data storage can not deal with that and in general it is not supported to add a
125  // named reference to the anonymous section container structure.
126  if (is_array($singleFieldConfiguration)
127  && isset($singleFieldConfiguration['config']['type'])
128  && ($singleFieldConfiguration['config']['type'] === 'group' || $singleFieldConfiguration['config']['type'] === 'select')
129  && array_key_exists('MM', $singleFieldConfiguration['config'])
130  ) {
131  throw new \UnexpectedValueException(
132  'Invalid flex form data structure on field name "' . $fieldName . '" with element "' . $singleFieldName . '"'
133  . ' in section container "' . $containerName . '": Nesting select and group elements in flex form'
134  . ' sections is not allowed with MM relations.',
135  1481647089
136  );
137  }
138  }
139  }
140  }
141  }
142  } elseif (isset($dataStructureFieldDefinition['type']) || isset($dataStructureFieldDefinition['section'])) {
143  // type without section is not ok
144  throw new \UnexpectedValueException(
145  'Broken data structure on field name ' . $fieldName . '. section without type or vice versa is not allowed',
146  1440685208
147  );
148  }
149  }
150  }
151  }
152 
188  protected function getSimplifiedDataStructureIdentifier(string $dataStructureIdentifier): string
189  {
190  $identifierArray = json_decode($dataStructureIdentifier, true);
191  $simpleDataStructureIdentifier = 'default';
192  if (isset($identifierArray['type']) && $identifierArray['type'] === 'tca' && isset($identifierArray['dataStructureKey'])) {
193  $explodedKey = explode(',', $identifierArray['dataStructureKey']);
194  if (!empty($explodedKey[1]) && $explodedKey[1] !== 'list' && $explodedKey[1] !== '*') {
195  $simpleDataStructureIdentifier = $explodedKey[1];
196  } elseif (!empty($explodedKey[0]) && $explodedKey[0] !== 'list' && $explodedKey[0] !== '*') {
197  $simpleDataStructureIdentifier = $explodedKey[0];
198  }
199  }
200  return $simpleDataStructureIdentifier;
201  }
202 
211  protected function getPageTsOfFlex(array $result, $fieldName, $flexIdentifier)
212  {
213  $table = $result['tableName'];
214  $pageTs = [];
215  if (!empty($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.'][$flexIdentifier . '.'])
216  && is_array($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.'][$flexIdentifier . '.'])) {
217  $pageTs = $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.'][$flexIdentifier . '.'];
218  }
219  return $pageTs;
220  }
221 
231  protected function modifyOuterDataStructure(array $result, $fieldName, $pageTsConfig)
232  {
233  $modifiedDataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
234 
235  if (isset($modifiedDataStructure['sheets']) && is_array($modifiedDataStructure['sheets'])) {
236  // Handling multiple sheets
237  foreach ($modifiedDataStructure['sheets'] as $sheetName => $sheetStructure) {
238  if (isset($pageTsConfig[$sheetName . '.']) && is_array($pageTsConfig[$sheetName . '.'])) {
239  $pageTsOfSheet = $pageTsConfig[$sheetName . '.'];
240 
241  // Remove whole sheet if disabled
242  if (!empty($pageTsOfSheet['disabled'])) {
243  unset($modifiedDataStructure['sheets'][$sheetName]);
244  continue;
245  }
246 
247  // sheetTitle, sheetDescription, sheetShortDescr
248  $modifiedDataStructure['sheets'][$sheetName] = $this->modifySingleSheetInformation($sheetStructure, $pageTsOfSheet);
249  }
250  }
251  }
252 
253  $result['processedTca']['columns'][$fieldName]['config']['ds'] = $modifiedDataStructure;
254 
255  return $result;
256  }
257 
266  protected function removeExcludeFieldsFromDataStructure(array $result, $fieldName, $flexIdentifier)
267  {
268  $dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
269  $backendUser = $this->getBackendUser();
270  if ($backendUser->isAdmin() || !isset($dataStructure['sheets']) || !is_array($dataStructure['sheets'])) {
271  return $result;
272  }
273 
274  $userNonExcludeFields = GeneralUtility::trimExplode(',', $backendUser->groupData['non_exclude_fields']);
275  $excludeFieldsPrefix = $result['tableName'] . ':' . $fieldName . ';' . $flexIdentifier . ';';
276  $nonExcludeFields = [];
277  foreach ($userNonExcludeFields as $userNonExcludeField) {
278  if (strpos($userNonExcludeField, $excludeFieldsPrefix) !== false) {
279  $exploded = explode(';', $userNonExcludeField);
280  $sheetName = $exploded[2];
281  $allowedFlexFieldName = $exploded[3];
282  $nonExcludeFields[$sheetName][$allowedFlexFieldName] = true;
283  }
284  }
285  foreach ($dataStructure['sheets'] as $sheetName => $sheetDefinition) {
286  if (!isset($sheetDefinition['ROOT']['el']) || !is_array($sheetDefinition['ROOT']['el'])) {
287  continue;
288  }
289  foreach ($sheetDefinition['ROOT']['el'] as $flexFieldName => $fieldDefinition) {
290  if (!empty($fieldDefinition['exclude']) && !isset($nonExcludeFields[$sheetName][$flexFieldName])) {
291  unset($result['processedTca']['columns'][$fieldName]['config']['ds']['sheets'][$sheetName]['ROOT']['el'][$flexFieldName]);
292  }
293  }
294  }
295 
296  return $result;
297  }
298 
307  protected function removeDisabledFieldsFromDataStructure(array $result, $fieldName, $pageTsConfig)
308  {
309  $dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
310  if (!isset($dataStructure['sheets']) || !is_array($dataStructure['sheets'])) {
311  return $result;
312  }
313  foreach ($dataStructure['sheets'] as $sheetName => $sheetDefinition) {
314  if (!isset($sheetDefinition['ROOT']['el']) || !is_array($sheetDefinition['ROOT']['el'])
315  || !isset($pageTsConfig[$sheetName . '.'])) {
316  continue;
317  }
318  foreach ($sheetDefinition['ROOT']['el'] as $flexFieldName => $fieldDefinition) {
319  if (!empty($pageTsConfig[$sheetName . '.'][$flexFieldName . '.']['disabled'])) {
320  unset($result['processedTca']['columns'][$fieldName]['config']['ds']['sheets'][$sheetName]['ROOT']['el'][$flexFieldName]);
321  }
322  }
323  }
324  return $result;
325  }
326 
341  protected function modifyDataStructureAndDataValuesByFlexFormSegmentGroup(array $result, $fieldName, $pageTsConfig)
342  {
343  $dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
344  $dataValues = $result['databaseRow'][$fieldName];
345  $tableName = $result['tableName'];
346 
347  if (!isset($dataStructure['sheets']) || !is_array($dataStructure['sheets'])) {
348  return $result;
349  }
350 
351  $formDataGroup = GeneralUtility::makeInstance(FlexFormSegment::class);
352  $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
353 
354  foreach ($dataStructure['sheets'] as $dataStructureSheetName => $dataStructureSheetDefinition) {
355  if (!isset($dataStructureSheetDefinition['ROOT']['el']) || !is_array($dataStructureSheetDefinition['ROOT']['el'])) {
356  continue;
357  }
358  $dataStructureFields = $dataStructureSheetDefinition['ROOT']['el'];
359 
360  // Prepare pageTsConfig of this sheet
361  $pageTsConfig['TCEFORM.'][$tableName . '.'] = [];
362  if (isset($pageTsConfig[$dataStructureSheetName . '.']) && is_array($pageTsConfig[$dataStructureSheetName . '.'])) {
363  $pageTsConfig['TCEFORM.'][$tableName . '.'] = $pageTsConfig[$dataStructureSheetName . '.'];
364  }
365 
366  // It is possible to have a flex field field with of foreign_table (eg. type=select) that has markers in
367  // a foreign_table_where like ###PAGE_TSCONFIG_ID###. It was possible to set this in page TSConfig for flex fields like this:
368  // TCEFORM.theTable.theFlexfield.PAGE_TSCONFIG_ID = 42
369  // This hands over this PAGE_TSCONFIG_ID to all flex fields that have this foreign_table_where marker.
370  // This is a contradiction to the "usual" page TSConfig flex configuration that should be done for single flex fields:
371  // TCEFORM.theTable.theFlexfield.theDataStructure.theSheet.theField.PAGE_TSCONFIG_ID = 42
372  // The below code is a hack to still simulate the old behavior that is now deprecated.
373  // @deprecated since TYPO3 v8, will be removed in TYPO3 v9
374  // When deleting this code and comment block, the according code within AbstractItemProvider can be removed, too.
375  if (isset($result['pageTsConfig']['TCEFORM.'][$tableName . '.'][$fieldName . '.']['PAGE_TSCONFIG_ID'])) {
377  'The page TSConfig setting TCEFORM.' . $tableName . '.' . $fieldName . '.PAGE_TSCONFIG_ID for flex forms'
378  . ' is deprecated. Use this setting for single flex fields instead, example: TCEFORM.' . $tableName . '.'
379  . $fieldName . '.theDataStructureName.theSheet.theFieldName.PAGE_TSCONFIG_ID. Be aware these settings are'
380  . ' no longer allowed for fields within flex form section container elements.'
381  );
382  $pageTsConfig['flexHack.']['PAGE_TSCONFIG_ID'] = $result['pageTsConfig']['TCEFORM.'][$tableName . '.'][$fieldName . '.']['PAGE_TSCONFIG_ID'];
383  }
384  if (isset($result['pageTsConfig']['TCEFORM.'][$tableName . '.'][$fieldName . '.']['PAGE_TSCONFIG_IDLIST'])) {
386  'The page TSConfig setting TCEFORM.' . $tableName . '.' . $fieldName . '.PAGE_TSCONFIG_IDLIST for flex forms'
387  . ' is deprecated. Use this setting for single flex fields instead, example: TCEFORM.' . $tableName . '.'
388  . $fieldName . '.theDataStructureName.theSheet.theFieldName.PAGE_TSCONFIG_IDLIST. Be aware these settings are'
389  . ' no longer allowed for fields within flex form section container elements.'
390  );
391  $pageTsConfig['flexHack.']['PAGE_TSCONFIG_IDLIST'] = $result['pageTsConfig']['TCEFORM.'][$tableName . '.'][$fieldName . '.']['PAGE_TSCONFIG_IDLIST'];
392  }
393  if (isset($result['pageTsConfig']['TCEFORM.'][$tableName . '.'][$fieldName . '.']['PAGE_TSCONFIG_STR'])) {
395  'The page TSConfig setting TCEFORM.' . $tableName . '.' . $fieldName . '.PAGE_TSCONFIG_STR for flex forms'
396  . ' is deprecated. Use this setting for single flex fields instead, example: TCEFORM.' . $tableName . '.'
397  . $fieldName . '.theDataStructureName.theSheet.theFieldName.PAGE_TSCONFIG_STR. Be aware these settings are'
398  . ' no longer allowed for fields within flex form section container elements.'
399  );
400  $pageTsConfig['flexHack.']['PAGE_TSCONFIG_STR'] = $result['pageTsConfig']['TCEFORM.'][$tableName . '.'][$fieldName . '.']['PAGE_TSCONFIG_STR'];
401  }
402 
403  // List of "new" tca fields that have no value within the flexform, yet. Those will be compiled in one go later.
404  $tcaNewColumns = [];
405  // List of "edit" tca fields that have a value in flexform, already. Those will be compiled in one go later.
406  $tcaEditColumns = [];
407  // Contains the data values for the "edit" tca fields.
408  $tcaValueArray = [
409  'uid' => $result['databaseRow']['uid'],
410  ];
411  foreach ($dataStructureFields as $dataStructureFieldName => $dataStructureFieldDefinition) {
412  if (isset($dataStructureFieldDefinition['type']) && $dataStructureFieldDefinition['type'] === 'array'
413  && isset($dataStructureFieldDefinition['section']) && (string)$dataStructureFieldDefinition['section'] === '1'
414  ) {
415  // Existing section containers. Prepare data values and create a unique data structure per container.
416  // This is important for instance for display conditions later enabling them to change ds per container instance.
417  // In the end, the data values in
418  // ['databaseRow']['aFieldName']['data']['aSheet']['lDEF']['aSectionField']['el']['aContainer']
419  // are prepared, and additionally, the processedTca data structure is changed and has a specific container
420  // name per container instance in
421  // ['processedTca']['columns']['aFieldName']['config']['ds']['sheets']['aSheet']['ROOT']['el']['aSectionField']['children']['aContainer']
422  if (isset($dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureFieldName]['el'])
423  && is_array($dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureFieldName]['el'])
424  ) {
425  $containerValueArray = $dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureFieldName]['el'];
426  $containerDataStructuresPerContainer = [];
427  foreach ($containerValueArray as $aContainerIdentifier => $aContainerArray) {
428  if (is_array($aContainerArray)) {
429  foreach ($aContainerArray as $aContainerName => $aContainerElementArray) {
430  if ($aContainerName === '_TOGGLE') {
431  // Don't handle internal toggle state field
432  continue;
433  }
434  if (!isset($dataStructureFields[$dataStructureFieldName]['el'][$aContainerName])) {
435  // Container not defined in ds
436  continue;
437  }
438  $vanillaContainerDataStructure = $dataStructureFields[$dataStructureFieldName]['el'][$aContainerName];
439 
440  $newColumns = [];
441  $editColumns = [];
442  $valueArray = [
443  'uid' => $result['databaseRow']['uid'],
444  ];
445  foreach ($vanillaContainerDataStructure['el'] as $singleFieldName => $singleFieldConfiguration) {
446  // $singleFieldValueArray = ['data']['sSections']['lDEF']['section_1']['el']['1']['container_1']['el']['element_1']
447  $singleFieldValueArray = [];
448  if (isset($aContainerElementArray['el'][$singleFieldName])
449  && is_array($aContainerElementArray['el'][$singleFieldName])
450  ) {
451  $singleFieldValueArray = $aContainerElementArray['el'][$singleFieldName];
452  }
453 
454  if (array_key_exists('vDEF', $singleFieldValueArray)) {
455  $valueArray[$singleFieldName] = $singleFieldValueArray['vDEF'];
456  } else {
457  $newColumns[$singleFieldName] = $singleFieldConfiguration;
458  }
459  $editColumns[$singleFieldName] = $singleFieldConfiguration;
460  }
461 
462  $inputToFlexFormSegment = [
463  'tableName' => $result['tableName'],
464  'command' => '',
465  // It is currently not possible to have pageTsConfig for section container
466  'pageTsConfig' => [],
467  'databaseRow' => $valueArray,
468  'processedTca' => [
469  'ctrl' => [],
470  'columns' => [],
471  ],
472  'selectTreeCompileItems' => $result['selectTreeCompileItems'],
473  'flexParentDatabaseRow' => $result['databaseRow'],
474  'effectivePid' => $result['effectivePid'],
475  ];
476 
477  if (!empty($newColumns)) {
478  // This is scenario "field has been added to data structure, but field value does not exist in value array yet"
479  // We want that stuff like TCA "default" values are then applied to those fields. What we do here is
480  // calling the data compiler with those "new" fields to fetch their values and set them in value array.
481  // Those fields are then compiled a second time in the "edit" phase to prepare their final TCA.
482  // This two-phase compiling is needed to ensure that for instance display conditions work with
483  // fields that may just have been added to the data structure but are not yet initialized as data value.
484  $inputToFlexFormSegment['command'] = 'new';
485  $inputToFlexFormSegment['processedTca']['columns'] = $newColumns;
486  $flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
487  foreach ($newColumns as $singleFieldName => $_) {
488  // Set data value result to feed it to "edit" next
489  $valueArray[$singleFieldName] = $flexSegmentResult['databaseRow'][$singleFieldName];
490  }
491  }
492 
493  if (!empty($editColumns)) {
494  $inputToFlexFormSegment['command'] = 'edit';
495  $inputToFlexFormSegment['processedTca']['columns'] = $editColumns;
496  $flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
497  foreach ($editColumns as $singleFieldName => $_) {
498  $result['databaseRow'][$fieldName]
499  ['data'][$dataStructureSheetName]['lDEF'][$dataStructureFieldName]
500  ['el'][$aContainerIdentifier][$aContainerName]['el'][$singleFieldName]['vDEF']
501  = $flexSegmentResult['databaseRow'][$singleFieldName];
502  $containerDataStructuresPerContainer[$aContainerIdentifier] = $vanillaContainerDataStructure;
503  $containerDataStructuresPerContainer[$aContainerIdentifier]['el'] = $flexSegmentResult['processedTca']['columns'];
504  }
505  }
506  }
507  }
508  } // End of existing data value handling
509  // Set 'data structures per container' next to 'el' that contains vanilla data structures
510  $result['processedTca']['columns'][$fieldName]['config']['ds']
511  ['sheets'][$dataStructureSheetName]['ROOT']['el']
512  [$dataStructureFieldName]['children'] = $containerDataStructuresPerContainer;
513  } else {
514  // Force the section data array to be an empty array if there are no existing containers
515  $result['databaseRow'][$fieldName]
516  ['data'][$dataStructureSheetName]['lDEF'][$dataStructureFieldName]['el'] = [];
517  // Force data structure array to be empty if there are no existing containers
518  $result['processedTca']['columns'][$fieldName]['config']['ds']
519  ['sheets'][$dataStructureSheetName]['ROOT']['el']
520  [$dataStructureFieldName]['children'] = [];
521  }
522  } else {
523  // A "normal" TCA flex form element, no section
524  if (isset($dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureFieldName])
525  && array_key_exists('vDEF', $dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureFieldName])
526  ) {
527  $tcaEditColumns[$dataStructureFieldName] = $dataStructureFieldDefinition;
528  $tcaValueArray[$dataStructureFieldName] = $dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureFieldName]['vDEF'];
529  } else {
530  $tcaNewColumns[$dataStructureFieldName] = $dataStructureFieldDefinition;
531  }
532  } // End of single element handling
533  }
534 
535  // process the tca columns for the current sheet
536  $inputToFlexFormSegment = [
537  'tableName' => $result['tableName'],
538  'command' => '',
539  'pageTsConfig' => $pageTsConfig,
540  'databaseRow' => $tcaValueArray,
541  'processedTca' => [
542  'ctrl' => [],
543  'columns' => [],
544  ],
545  'flexParentDatabaseRow' => $result['databaseRow'],
546  // Whether to compile TCA tree items - inherit from parent
547  'selectTreeCompileItems' => $result['selectTreeCompileItems'],
548  'effectivePid' => $result['effectivePid'],
549  ];
550 
551  if (!empty($tcaNewColumns)) {
552  // @todo: this has the same problem in scenario "a field was added later" as flex section container
553  $inputToFlexFormSegment['command'] = 'new';
554  $inputToFlexFormSegment['processedTca']['columns'] = $tcaNewColumns;
555  $flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
556 
557  foreach ($tcaNewColumns as $dataStructureFieldName => $_) {
558  // Set data value result
559  if (array_key_exists($dataStructureFieldName, $flexSegmentResult['databaseRow'])) {
560  $result['databaseRow'][$fieldName]
561  ['data'][$dataStructureSheetName]['lDEF'][$dataStructureFieldName]['vDEF']
562  = $flexSegmentResult['databaseRow'][$dataStructureFieldName];
563  }
564  // Set TCA structure result
565  $result['processedTca']['columns'][$fieldName]['config']['ds']
566  ['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureFieldName]
567  = $flexSegmentResult['processedTca']['columns'][$dataStructureFieldName];
568  }
569  }
570 
571  if (!empty($tcaEditColumns)) {
572  $inputToFlexFormSegment['command'] = 'edit';
573  $inputToFlexFormSegment['processedTca']['columns'] = $tcaEditColumns;
574  $flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
575 
576  foreach ($tcaEditColumns as $dataStructureFieldName => $_) {
577  // Set data value result
578  if (array_key_exists($dataStructureFieldName, $flexSegmentResult['databaseRow'])) {
579  $result['databaseRow'][$fieldName]
580  ['data'][$dataStructureSheetName]['lDEF'][$dataStructureFieldName]['vDEF']
581  = $flexSegmentResult['databaseRow'][$dataStructureFieldName];
582  }
583  // Set TCA structure result
584  $result['processedTca']['columns'][$fieldName]['config']['ds']
585  ['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureFieldName]
586  = $flexSegmentResult['processedTca']['columns'][$dataStructureFieldName];
587  }
588  }
589  }
590 
591  return $result;
592  }
593 
601  protected function prepareNewSectionContainer(array $result, string $fieldName): array
602  {
603  $flexSectionContainerPreparation = $result['flexSectionContainerPreparation'];
604  $flexFormSheetName = $flexSectionContainerPreparation['flexFormSheetName'];
605  $flexFormFieldName = $flexSectionContainerPreparation['flexFormFieldName'];
606  $flexFormContainerName = $flexSectionContainerPreparation['flexFormContainerName'];
607  $flexFormContainerIdentifier = $flexSectionContainerPreparation['flexFormContainerIdentifier'];
608 
609  $containerConfiguration = $result['processedTca']['columns'][$fieldName]['config']['ds']
610  ['sheets'][$flexFormSheetName]['ROOT']['el'][$flexFormFieldName]['el'][$flexFormContainerName];
611 
612  if (isset($containerConfiguration['el']) && is_array($containerConfiguration['el'])) {
613  $formDataGroup = GeneralUtility::makeInstance(FlexFormSegment::class);
614  $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
615  $inputToFlexFormSegment = [
616  'tableName' => $result['tableName'],
617  'command' => 'new',
618  // It is currently not possible to have pageTsConfig for section container
619  'pageTsConfig' => [],
620  'databaseRow' => [
621  'uid' => $result['databaseRow']['uid'],
622  ],
623  'processedTca' => [
624  'ctrl' => [],
625  'columns' => $containerConfiguration['el'],
626  ],
627  'selectTreeCompileItems' => $result['selectTreeCompileItems'],
628  'flexParentDatabaseRow' => $result['databaseRow'],
629  'effectivePid' => $result['effectivePid'],
630  ];
631  $flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
632 
633  foreach ($containerConfiguration['el'] as $singleFieldName => $singleFieldConfiguration) {
634  // Set 'data structures for this new container' to 'children'
635  $result['processedTca']['columns'][$fieldName]['config']['ds']
636  ['sheets'][$flexFormSheetName]['ROOT']['el']
637  [$flexFormFieldName]['children'][$flexFormContainerIdentifier]
638  = $containerConfiguration;
639  $result['processedTca']['columns'][$fieldName]['config']['ds']
640  ['sheets'][$flexFormSheetName]['ROOT']['el']
641  [$flexFormFieldName]['children'][$flexFormContainerIdentifier]['el']
642  = $flexSegmentResult['processedTca']['columns'];
643  // Set calculated value - this especially contains "default values from TCA"
644  $result['databaseRow'][$fieldName]['data'][$flexFormSheetName]['lDEF']
645  [$flexFormFieldName]['el']
646  [$flexFormContainerIdentifier][$flexFormContainerName]['el'][$singleFieldName]['vDEF']
647  = $flexSegmentResult['databaseRow'][$singleFieldName];
648  }
649  }
650 
651  return $result;
652  }
653 
662  protected function modifySingleSheetInformation(array $dataStructure, array $pageTsOfSheet)
663  {
664  // Return if no elements defined
665  if (!isset($dataStructure['ROOT']['el']) || !is_array($dataStructure['ROOT']['el'])) {
666  return $dataStructure;
667  }
668  // Rename sheet (tab)
669  if (!empty($pageTsOfSheet['sheetTitle'])) {
670  $dataStructure['ROOT']['sheetTitle'] = $pageTsOfSheet['sheetTitle'];
671  }
672  // Set sheet description (tab)
673  if (!empty($pageTsOfSheet['sheetDescription'])) {
674  $dataStructure['ROOT']['sheetDescription'] = $pageTsOfSheet['sheetDescription'];
675  }
676  // Set sheet short description (tab)
677  if (!empty($pageTsOfSheet['sheetShortDescr'])) {
678  $dataStructure['ROOT']['sheetShortDescr'] = $pageTsOfSheet['sheetShortDescr'];
679  }
680 
681  return $dataStructure;
682  }
683 
687  protected function getBackendUser()
688  {
689  return $GLOBALS['BE_USER'];
690  }
691 }
removeExcludeFieldsFromDataStructure(array $result, $fieldName, $flexIdentifier)
getSimplifiedDataStructureIdentifier(string $dataStructureIdentifier)
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
modifySingleSheetInformation(array $dataStructure, array $pageTsOfSheet)
static makeInstance($className,... $constructorArguments)
modifyDataStructureAndDataValuesByFlexFormSegmentGroup(array $result, $fieldName, $pageTsConfig)
removeDisabledFieldsFromDataStructure(array $result, $fieldName, $pageTsConfig)
prepareNewSectionContainer(array $result, string $fieldName)
modifyOuterDataStructure(array $result, $fieldName, $pageTsConfig)
scanForInvalidSectionContainerTca(array $result, string $fieldName)
getPageTsOfFlex(array $result, $fieldName, $flexIdentifier)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']