TYPO3 CMS  TYPO3_8-7
TcaFlexPrepare.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 
27 
34 {
44  public function addData(array $result)
45  {
46  foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfig) {
47  if (empty($fieldConfig['config']['type']) || $fieldConfig['config']['type'] !== 'flex') {
48  continue;
49  }
50  $result = $this->initializeDataStructure($result, $fieldName);
51  $result = $this->initializeDataValues($result, $fieldName);
52  $result = $this->removeTceFormsArrayKeyFromDataStructureElements($result, $fieldName);
53  $result = $this->migrateFlexformTcaDataStructureElements($result, $fieldName);
54  }
55 
56  return $result;
57  }
58 
70  protected function initializeDataStructure(array $result, $fieldName)
71  {
72  if (!isset($result['processedTca']['columns'][$fieldName]['config']['dataStructureIdentifier'])) {
73  $flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
74 
75  $dataStructureIdentifier = '';
76  $dataStructureArray = [ 'sheets' => [ 'sDEF' => [] ] ];
77 
78  try {
79  $dataStructureIdentifier = $flexFormTools->getDataStructureIdentifier(
80  $result['processedTca']['columns'][$fieldName],
81  $result['tableName'],
82  $fieldName,
83  $result['databaseRow']
84  );
85  $dataStructureArray = $flexFormTools->parseDataStructureByIdentifier($dataStructureIdentifier);
86  } catch (InvalidParentRowException $e) {
87  } catch (InvalidParentRowLoopException $e) {
88  } catch (InvalidParentRowRootException $e) {
90  } catch (InvalidIdentifierException $e) {
91  } finally {
92  // Add the identifier to TCA to use it later during rendering
93  $result['processedTca']['columns'][$fieldName]['config']['dataStructureIdentifier'] = $dataStructureIdentifier;
94  }
95  } else {
96  // Assume the data structure has been given from outside if the data structure identifier is already set.
97  $dataStructureArray = $result['processedTca']['columns'][$fieldName]['config']['ds'];
98  }
99  if (!isset($dataStructureArray['meta']) || !is_array($dataStructureArray['meta'])) {
100  $dataStructureArray['meta'] = [];
101  }
102  // This kicks one array depth: config['ds']['listOfDataStructures'] becomes config['ds']
103  // This also ensures the final ds can be found in 'ds', even if the DS was fetch from
104  // a record, see FlexFormTools->getDataStructureIdentifier() for details.
105  $result['processedTca']['columns'][$fieldName]['config']['ds'] = $dataStructureArray;
106  return $result;
107  }
108 
116  protected function initializeDataValues(array $result, $fieldName)
117  {
118  if (!array_key_exists($fieldName, $result['databaseRow'])) {
119  $result['databaseRow'][$fieldName] = '';
120  }
121  $valueArray = [];
122  if (isset($result['databaseRow'][$fieldName])) {
123  $valueArray = $result['databaseRow'][$fieldName];
124  }
125  if (!is_array($result['databaseRow'][$fieldName])) {
126  $valueArray = GeneralUtility::xml2array($result['databaseRow'][$fieldName]);
127  }
128  if (!is_array($valueArray)) {
129  $valueArray = [];
130  }
131  if (!isset($valueArray['data'])) {
132  $valueArray['data'] = [];
133  }
134  if (!isset($valueArray['meta'])) {
135  $valueArray['meta'] = [];
136  }
137  $result['databaseRow'][$fieldName] = $valueArray;
138  return $result;
139  }
140 
152  protected function removeTceFormsArrayKeyFromDataStructureElements(array $result, $fieldName)
153  {
154  $modifiedDataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
155  $modifiedDataStructure = $this->removeElementTceFormsRecursive($modifiedDataStructure);
156  $result['processedTca']['columns'][$fieldName]['config']['ds'] = $modifiedDataStructure;
157  return $result;
158  }
159 
166  protected function removeElementTceFormsRecursive(array $structure)
167  {
168  $newStructure = [];
169  foreach ($structure as $key => $value) {
170  if ($key === 'ROOT' && is_array($value) && isset($value['TCEforms'])) {
171  $value = array_merge($value, $value['TCEforms']);
172  unset($value['TCEforms']);
173  }
174  if ($key === 'el' && is_array($value)) {
175  $newSubStructure = [];
176  foreach ($value as $subKey => $subValue) {
177  if (is_array($subValue) && count($subValue) === 1 && isset($subValue['TCEforms'])) {
178  $newSubStructure[$subKey] = $subValue['TCEforms'];
179  } else {
180  $newSubStructure[$subKey] = $subValue;
181  }
182  }
183  $value = $newSubStructure;
184  }
185  if (is_array($value)) {
186  $value = $this->removeElementTceFormsRecursive($value);
187  }
188  $newStructure[$key] = $value;
189  }
190  return $newStructure;
191  }
192 
200  protected function migrateFlexformTcaDataStructureElements(array $result, $fieldName)
201  {
202  $modifiedDataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
203  $modifiedDataStructure = $this->migrateFlexformTcaRecursive($modifiedDataStructure, $result['tableName'], $fieldName);
204  $result['processedTca']['columns'][$fieldName]['config']['ds'] = $modifiedDataStructure;
205  return $result;
206  }
207 
216  protected function migrateFlexformTcaRecursive($structure, $table, $fieldName)
217  {
218  $newStructure = [];
219  foreach ($structure as $key => $value) {
220  if ($key === 'el' && is_array($value)) {
221  $newSubStructure = [];
222  $tcaMigration = GeneralUtility::makeInstance(TcaMigration::class);
223  $tcaPreparation = GeneralUtility::makeInstance(TcaPreparation::class);
224  foreach ($value as $subKey => $subValue) {
225  // On-the-fly migration for flex form "TCA"
226  // @deprecated since TYPO3 CMS 7. Not removed in TYPO3 CMS 8 though. This call will stay for now to allow further TCA migrations in 8.
227  $dummyTca = [
228  'dummyTable' => [
229  'columns' => [
230  'dummyField' => $subValue,
231  ],
232  ],
233  ];
234  $migratedTca = $tcaMigration->migrate($dummyTca);
235  $messages = $tcaMigration->getMessages();
236  if (!empty($messages)) {
237  $context = 'FormEngine did an on-the-fly migration of a flex form data structure. This is deprecated and will be removed.'
238  . ' Merge the following changes into the flex form definition of table "' . $table . '"" in field "' . $fieldName . '"":';
239  array_unshift($messages, $context);
240  GeneralUtility::deprecationLog(implode(LF, $messages));
241  }
242  $preparedTca = $tcaPreparation->prepare($migratedTca);
243  $newSubStructure[$subKey] = $preparedTca['dummyTable']['columns']['dummyField'];
244  }
245  $value = $newSubStructure;
246  }
247  if (is_array($value)) {
248  $value = $this->migrateFlexformTcaRecursive($value, $table, $fieldName);
249  }
250  $newStructure[$key] = $value;
251  }
252  return $newStructure;
253  }
254 }
removeTceFormsArrayKeyFromDataStructureElements(array $result, $fieldName)
static makeInstance($className,... $constructorArguments)
migrateFlexformTcaRecursive($structure, $table, $fieldName)
migrateFlexformTcaDataStructureElements(array $result, $fieldName)
static xml2array($string, $NSprefix='', $reportDocTag=false)