0b9811959318bd3f746d2326ccf1dfb1d6613e0f
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Migrations / TcaMigration.php
1 <?php
2 declare(strict_types=1);
3 namespace TYPO3\CMS\Core\Migrations;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19
20 /**
21 * Migrate TCA from old to new syntax. Used in bootstrap and Flex Form Data Structures.
22 *
23 * @internal Class and API may change any time.
24 */
25 class TcaMigration
26 {
27 /**
28 * Accumulate migration messages
29 *
30 * @var array
31 */
32 protected $messages = [];
33
34 /**
35 * Run some general TCA validations, then migrate old TCA to new TCA.
36 *
37 * This class is typically called within bootstrap with empty caches after all TCA
38 * files from extensions have been loaded. The migration is then applied and
39 * the migrated result is cached.
40 * For flex form TCA, this class is called dynamically if opening a record in the backend.
41 *
42 * See unit tests for details.
43 *
44 * @param array $tca
45 * @return array
46 */
47 public function migrate(array $tca): array
48 {
49 $this->validateTcaType($tca);
50
51 $tca = $this->migrateT3editorWizardToRenderTypeT3editorIfNotEnabledByTypeConfig($tca);
52 $tca = $this->migrateSpecialConfigurationAndRemoveShowItemStylePointerConfig($tca);
53 $tca = $this->migrateT3editorWizardWithEnabledByTypeConfigToColumnsOverrides($tca);
54 $tca = $this->migrateShowItemAdditionalPaletteToOwnPalette($tca);
55 $tca = $this->migrateIconsForFormFieldWizardToNewLocation($tca);
56 $tca = $this->migrateExtAndSysextPathToEXTPath($tca);
57 $tca = $this->migrateIconsInOptionTags($tca);
58 $tca = $this->migrateIconfileRelativePathOrFilenameOnlyToExtReference($tca);
59 $tca = $this->migrateSelectFieldRenderType($tca);
60 $tca = $this->migrateSelectFieldIconTable($tca);
61 $tca = $this->migrateElementBrowserWizardToLinkHandler($tca);
62 $tca = $this->migrateDefaultExtrasRteTransFormOptions($tca);
63 $tca = $this->migrateSelectTreeOptions($tca);
64 $tca = $this->migrateTSconfigSoftReferences($tca);
65 $tca = $this->migrateShowIfRteOption($tca);
66 $tca = $this->migrateWorkspacesOptions($tca);
67 $tca = $this->migrateTranslationTable($tca);
68 $tca = $this->migrateL10nModeDefinitions($tca);
69 $tca = $this->migrateRequestUpdate($tca);
70 $tca = $this->migrateInputDateTimeToRenderType($tca);
71 $tca = $this->migrateWizardEnableByTypeConfigToColumnsOverrides($tca);
72 $tca = $this->migrateColorPickerWizardToRenderType($tca);
73 $tca = $this->migrateSelectWizardToValuePicker($tca);
74 $tca = $this->migrateSliderWizardToSliderConfiguration($tca);
75 $tca = $this->migrateLinkWizardToRenderTypeAndFieldControl($tca);
76 $tca = $this->migrateEditWizardToFieldControl($tca);
77 $tca = $this->migrateAddWizardToFieldControl($tca);
78 $tca = $this->migrateListWizardToFieldControl($tca);
79 $tca = $this->migrateLastPiecesOfDefaultExtras($tca);
80 $tca = $this->migrateTableWizardToRenderType($tca);
81 $tca = $this->migrateFullScreenRichtextToFieldControl($tca);
82 $tca = $this->migrateSuggestWizardTypeGroup($tca);
83 $tca = $this->migrateOptionsOfTypeGroup($tca);
84 $tca = $this->migrateSelectShowIconTable($tca);
85 $tca = $this->migrateImageManipulationConfig($tca);
86 return $tca;
87 }
88
89 /**
90 * Get messages of migrated fields. Can be used for deprecation messages after migrate() was called.
91 *
92 * @return array Migration messages
93 */
94 public function getMessages(): array
95 {
96 return $this->messages;
97 }
98
99 /**
100 * Check for required TCA configuration
101 *
102 * @param array $tca Incoming TCA
103 */
104 protected function validateTcaType(array $tca)
105 {
106 foreach ($tca as $table => $tableDefinition) {
107 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
108 continue;
109 }
110 foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
111 if (isset($fieldConfig['config']) && is_array($fieldConfig['config']) && empty($fieldConfig['config']['type'])) {
112 throw new \UnexpectedValueException(
113 'Missing "type" in TCA of field "[\'' . $table . '\'][\'' . $fieldName . '\'][\'config\']".',
114 1482394401
115 );
116 }
117 }
118 }
119 }
120
121 /**
122 * Migrate type=text field with t3editor wizard to renderType=t3editor without this wizard
123 *
124 * @param array $tca Incoming TCA
125 * @return array Migrated TCA
126 */
127 protected function migrateT3editorWizardToRenderTypeT3editorIfNotEnabledByTypeConfig(array $tca): array
128 {
129 $newTca = $tca;
130 foreach ($tca as $table => $tableDefinition) {
131 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
132 continue;
133 }
134 foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
135 if (
136 !empty($fieldConfig['config']['type']) // type is set
137 && trim($fieldConfig['config']['type']) === 'text' // to "text"
138 && isset($fieldConfig['config']['wizards'])
139 && is_array($fieldConfig['config']['wizards']) // and there are wizards
140 ) {
141 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
142 if (
143 !empty($wizardConfig['userFunc']) // a userFunc is defined
144 && trim($wizardConfig['userFunc']) === 'TYPO3\\CMS\\T3editor\\FormWizard->main' // and set to FormWizard
145 && (
146 !isset($wizardConfig['enableByTypeConfig']) // and enableByTypeConfig is not set
147 || (isset($wizardConfig['enableByTypeConfig']) && !$wizardConfig['enableByTypeConfig']) // or set, but not enabled
148 )
149 ) {
150 // Set renderType from text to t3editor
151 $newTca[$table]['columns'][$fieldName]['config']['renderType'] = 't3editor';
152 // Unset this wizard definition
153 unset($newTca[$table]['columns'][$fieldName]['config']['wizards'][$wizardName]);
154 // Move format parameter
155 if (!empty($wizardConfig['params']['format'])) {
156 $newTca[$table]['columns'][$fieldName]['config']['format'] = $wizardConfig['params']['format'];
157 }
158 $this->messages[] = 'The t3editor wizard using \'type\' = \'text\' has been migrated to a \'renderType\' = \'t3editor\' definition.'
159 . 'It has been migrated from TCA "' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'t3editor\']"'
160 . 'to "' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'renderType\'] = \'t3editor\'"';
161 }
162 }
163 // If no wizard is left after migration, unset the whole sub array
164 if (empty($newTca[$table]['columns'][$fieldName]['config']['wizards'])) {
165 unset($newTca[$table]['columns'][$fieldName]['config']['wizards']);
166 }
167 }
168 }
169 }
170 return $newTca;
171 }
172
173 /**
174 * Remove "style pointer", the 5th parameter from "types" "showitem" configuration.
175 * Move "specConf", 4th parameter from "types" "showitem" to "types" "columnsOverrides".
176 *
177 * @param array $tca Incoming TCA
178 * @return array Modified TCA
179 */
180 protected function migrateSpecialConfigurationAndRemoveShowItemStylePointerConfig(array $tca): array
181 {
182 $newTca = $tca;
183 foreach ($tca as $table => $tableDefinition) {
184 if (!isset($tableDefinition['types']) || !is_array($tableDefinition['types'])) {
185 continue;
186 }
187 foreach ($tableDefinition['types'] as $typeName => $typeArray) {
188 if (!isset($typeArray['showitem']) || !is_string($typeArray['showitem']) || strpos($typeArray['showitem'], ';') === false) {
189 // Continue directly if no semicolon is found
190 continue;
191 }
192 $itemList = GeneralUtility::trimExplode(',', $typeArray['showitem'], true);
193 $newFieldStrings = [];
194 foreach ($itemList as $fieldString) {
195 $fieldString = rtrim($fieldString, ';');
196 // Unpack the field definition, migrate and remove as much as possible
197 // Keep empty parameters in trimExplode here (third parameter FALSE), so position is not changed
198 $fieldArray = GeneralUtility::trimExplode(';', $fieldString);
199 $fieldArray = [
200 'fieldName' => isset($fieldArray[0]) ? $fieldArray[0] : '',
201 'fieldLabel' => isset($fieldArray[1]) ? $fieldArray[1] : null,
202 'paletteName' => isset($fieldArray[2]) ? $fieldArray[2] : null,
203 'fieldExtra' => isset($fieldArray[3]) ? $fieldArray[3] : null,
204 ];
205 $fieldName = $fieldArray['fieldName'];
206 if (!empty($fieldArray['fieldExtra'])) {
207 // Move fieldExtra "specConf" to columnsOverrides "defaultExtras"
208 if (!isset($newTca[$table]['types'][$typeName]['columnsOverrides'])) {
209 $newTca[$table]['types'][$typeName]['columnsOverrides'] = [];
210 }
211 if (!isset($newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldArray['fieldName']])) {
212 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldArray['fieldName']] = [];
213 }
214 // Merge with given defaultExtras from columns.
215 // They will be the first part of the string, so if "specConf" from types changes the same settings,
216 // those will override settings from defaultExtras of columns
217 $newDefaultExtras = [];
218 if (!empty($tca[$table]['columns'][$fieldArray['fieldName']]['defaultExtras'])) {
219 $newDefaultExtras[] = $tca[$table]['columns'][$fieldArray['fieldName']]['defaultExtras'];
220 }
221 $newDefaultExtras[] = $fieldArray['fieldExtra'];
222 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldArray['fieldName']]['defaultExtras'] = implode(':', $newDefaultExtras);
223 }
224 unset($fieldArray['fieldExtra']);
225 if (count($fieldArray) === 3 && empty($fieldArray['paletteName'])) {
226 unset($fieldArray['paletteName']);
227 }
228 if (count($fieldArray) === 2 && empty($fieldArray['fieldLabel'])) {
229 unset($fieldArray['fieldLabel']);
230 }
231 if (count($fieldArray) === 1 && empty($fieldArray['fieldName'])) {
232 // The field may vanish if nothing is left
233 unset($fieldArray['fieldName']);
234 }
235 $newFieldString = implode(';', $fieldArray);
236 if ($newFieldString !== $fieldString) {
237 $this->messages[] = 'The 4th parameter \'specConf\' of the field \'showitem\' with fieldName = \'' . $fieldArray['fieldName'] . '\' has been migrated, from TCA table "'
238 . $table . '[\'types\'][\'' . $typeName . '\'][\'showitem\']"' . 'to "'
239 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'' . $fieldArray['fieldName'] . '\'][\'defaultExtras\']".';
240 }
241 if (!empty($newFieldString)) {
242 $newFieldStrings[] = $newFieldString;
243 }
244 }
245 $newTca[$table]['types'][$typeName]['showitem'] = implode(',', $newFieldStrings);
246 }
247 }
248 return $newTca;
249 }
250
251 /**
252 * Migrate type=text field with t3editor wizard that is "enableByTypeConfig" to columnsOverrides
253 * with renderType=t3editor
254 *
255 * @param array $tca Incoming TCA
256 * @return array Migrated TCA
257 */
258 protected function migrateT3editorWizardWithEnabledByTypeConfigToColumnsOverrides(array $tca): array
259 {
260 $newTca = $tca;
261 foreach ($tca as $table => $tableDefinition) {
262 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
263 continue;
264 }
265 foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
266 if (
267 !empty($fieldConfig['config']['type']) // type is set
268 && trim($fieldConfig['config']['type']) === 'text' // to "text"
269 && isset($fieldConfig['config']['wizards'])
270 && is_array($fieldConfig['config']['wizards']) // and there are wizards
271 ) {
272 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
273 if (
274 !empty($wizardConfig['userFunc']) // a userFunc is defined
275 && trim($wizardConfig['userFunc']) === 'TYPO3\CMS\T3editor\FormWizard->main' // and set to FormWizard
276 && !empty($wizardConfig['enableByTypeConfig']) // and enableByTypeConfig is enabled
277 ) {
278 // Remove this wizard
279 unset($newTca[$table]['columns'][$fieldName]['config']['wizards'][$wizardName]);
280 // Find configured types that use this wizard
281 if (!isset($tableDefinition['types']) || !is_array($tableDefinition['types'])) {
282 // No type definition at all ... continue directly
283 continue;
284 }
285 foreach ($tableDefinition['types'] as $typeName => $typeArray) {
286 if (
287 empty($typeArray['columnsOverrides'][$fieldName]['defaultExtras'])
288 || strpos($typeArray['columnsOverrides'][$fieldName]['defaultExtras'], $wizardName) === false
289 ) {
290 // Continue directly if this wizard is not enabled for given type
291 continue;
292 }
293 $defaultExtras = $typeArray['columnsOverrides'][$fieldName]['defaultExtras'];
294 $defaultExtrasArray = GeneralUtility::trimExplode(':', $defaultExtras, true);
295 $newDefaultExtrasArray = [];
296 foreach ($defaultExtrasArray as $fieldExtraField) {
297 // There might be multiple enabled wizards separated by | ... split them
298 if (substr($fieldExtraField, 0, 8) === 'wizards[') {
299 $enabledWizards = substr($fieldExtraField, 8, strlen($fieldExtraField) - 8); // Cut off "wizards[
300 $enabledWizards = substr($enabledWizards, 0, strlen($enabledWizards) - 1);
301 $enabledWizardsArray = GeneralUtility::trimExplode('|', $enabledWizards, true);
302 $newEnabledWizardsArray = [];
303 foreach ($enabledWizardsArray as $enabledWizardName) {
304 if ($enabledWizardName === $wizardName) {
305 // Found a columnsOverrides configuration that has this wizard enabled
306 // Force renderType = t3editor
307 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldName]['config']['renderType'] = 't3editor';
308 // Transfer format option if given
309 if (!empty($wizardConfig['params']['format'])) {
310 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldName]['config']['format'] = $wizardConfig['params']['format'];
311 }
312 $this->messages[] = 'The t3editor wizard using \'type\' = \'text\', with the "enableByTypeConfig" wizard set to 1,'
313 . 'has been migrated to the \'renderType\' = \'t3editor\' definition.'
314 . 'It has been migrated from TCA "' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'t3editor\']"'
315 . 'to "' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'renderType\'] = \'t3editor\'"';
316 } else {
317 // Some other enabled wizard
318 $newEnabledWizardsArray[] = $enabledWizardName;
319 }
320 }
321 if (!empty($newEnabledWizardsArray)) {
322 $newDefaultExtrasArray[] = 'wizards[' . implode('|', $newEnabledWizardsArray) . ']';
323 }
324 } else {
325 $newDefaultExtrasArray[] = $fieldExtraField;
326 }
327 }
328 if (!empty($newDefaultExtrasArray)) {
329 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldName]['defaultExtras'] = implode(':', $newDefaultExtrasArray);
330 } else {
331 unset($newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldName]['defaultExtras']);
332 }
333 }
334 }
335 }
336 // If no wizard is left after migration, unset the whole sub array
337 if (empty($newTca[$table]['columns'][$fieldName]['config']['wizards'])) {
338 unset($newTca[$table]['columns'][$fieldName]['config']['wizards']);
339 }
340 }
341 }
342 }
343 return $newTca;
344 }
345
346 /**
347 * Migrate types showitem 'aField;aLabel;aPalette' to 'afield;aLabel, --palette--;;aPalette'
348 *
349 * Old showitem can have a syntax like:
350 * fieldName;aLabel;aPalette
351 * This way, the palette with name "aPalette" is rendered after fieldName.
352 * The migration parses this to a syntax like:
353 * fieldName;aLabel, --palette--;;paletteName
354 *
355 * @param array $tca Incoming TCA
356 * @return array Migrated TCA
357 */
358 protected function migrateShowItemAdditionalPaletteToOwnPalette(array $tca): array
359 {
360 $newTca = $tca;
361 foreach ($tca as $table => $tableDefinition) {
362 if (!isset($tableDefinition['types']) || !is_array($tableDefinition['types'])) {
363 continue;
364 }
365 foreach ($tableDefinition['types'] as $typeName => $typeArray) {
366 if (
367 !isset($typeArray['showitem'])
368 || !is_string($typeArray['showitem'])
369 || strpos($typeArray['showitem'], ';') === false // no field parameters
370 ) {
371 continue;
372 }
373 $itemList = GeneralUtility::trimExplode(',', $typeArray['showitem'], true);
374 $newFieldStrings = [];
375 foreach ($itemList as $fieldString) {
376 $fieldArray = GeneralUtility::trimExplode(';', $fieldString);
377 $fieldArray = [
378 'fieldName' => isset($fieldArray[0]) ? $fieldArray[0] : '',
379 'fieldLabel' => isset($fieldArray[1]) ? $fieldArray[1] : null,
380 'paletteName' => isset($fieldArray[2]) ? $fieldArray[2] : null,
381 ];
382 if ($fieldArray['fieldName'] !== '--palette--' && $fieldArray['paletteName'] !== null) {
383 if ($fieldArray['fieldLabel']) {
384 $fieldString = $fieldArray['fieldName'] . ';' . $fieldArray['fieldLabel'];
385 } else {
386 $fieldString = $fieldArray['fieldName'];
387 }
388 $paletteString = '--palette--;;' . $fieldArray['paletteName'];
389 $this->messages[] = 'Migrated \'showitem\' field from TCA table '
390 . $table . '[\'types\'][\'' . $typeName . '\']" : Moved additional palette'
391 . ' with name "' . $table . '[\'types\'][\'' . $typeName . '\'][\'' . $fieldArray['paletteName'] . '\']" as 3rd argument of field "'
392 . $table . '[\'types\'][\'' . $typeName . '\'][\'' . $fieldArray['fieldName'] . '\']"'
393 . 'to an own palette. The result of this part is: "' . $fieldString . ', ' . $paletteString . '"';
394 $newFieldStrings[] = $fieldString;
395 $newFieldStrings[] = $paletteString;
396 } else {
397 $newFieldStrings[] = $fieldString;
398 }
399 }
400 $newTca[$table]['types'][$typeName]['showitem'] = implode(',', $newFieldStrings);
401 }
402 }
403 return $newTca;
404 }
405
406 /**
407 * Migrate core icons for form field wizard to new location
408 *
409 * @param array $tca Incoming TCA
410 * @return array Migrated TCA
411 */
412 protected function migrateIconsForFormFieldWizardToNewLocation(array $tca): array
413 {
414 $newTca = $tca;
415
416 $newFileLocations = [
417 'add.gif' => 'actions-add',
418 'link_popup.gif' => 'actions-wizard-link',
419 'wizard_rte2.gif' => 'actions-wizard-rte',
420 'wizard_table.gif' => 'content-table',
421 'edit2.gif' => 'actions-open',
422 'list.gif' => 'actions-system-list-open',
423 'wizard_forms.gif' => 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_forms.gif',
424 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_add.gif' => 'actions-add',
425 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_table.gif' => 'content-table',
426 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_edit.gif' => 'actions-open',
427 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_list.gif' => 'actions-system-list-open',
428 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_link.gif' => 'actions-wizard-link',
429 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_rte.gif' => 'actions-wizard-rte'
430 ];
431 $oldFileNames = array_keys($newFileLocations);
432
433 foreach ($tca as $table => $tableDefinition) {
434 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
435 continue;
436 }
437 foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
438 if (
439 isset($fieldConfig['config']['wizards'])
440 && is_array($fieldConfig['config']['wizards']) // and there are wizards
441 ) {
442 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
443 if (!is_array($wizardConfig)) {
444 continue;
445 }
446
447 foreach ($wizardConfig as $option => $value) {
448 if ($option === 'icon' && in_array($value, $oldFileNames, true)) {
449 $newTca[$table]['columns'][$fieldName]['config']['wizards'][$wizardName]['icon'] = $newFileLocations[$value];
450 $this->messages[] = 'The icon path of wizard "' . $wizardName
451 . '" from TCA table "'
452 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'' . $wizardName . '\'][\'icon\']"'
453 . 'has been migrated to '
454 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'' . $wizardName . '\'][\'icon\']" = \'' . $newFileLocations[$value] . '\'.';
455 }
456 }
457 }
458 }
459 }
460 }
461
462 return $newTca;
463 }
464
465 /**
466 * Migrate file reference which starts with ext/ or sysext/ to EXT:
467 *
468 * @param array $tca Incoming TCA
469 * @return array Migrated TCA
470 */
471 protected function migrateExtAndSysextPathToEXTPath(array $tca): array
472 {
473 foreach ($tca as $table => &$tableDefinition) {
474 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
475 continue;
476 }
477 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
478 if (
479 !empty($fieldConfig['config']['type']) // type is set
480 && trim($fieldConfig['config']['type']) === 'select' // to "select"
481 && isset($fieldConfig['config']['items'])
482 && is_array($fieldConfig['config']['items']) // and there are items
483 ) {
484 foreach ($fieldConfig['config']['items'] as &$itemConfig) {
485 // more then two values? then the third entry is the image path
486 if (!empty($itemConfig[2])) {
487 $tcaPath = implode('.', [$table, 'columns', $fieldName, 'config', 'items']);
488 $pathParts = GeneralUtility::trimExplode('/', $itemConfig[2]);
489 // remove first element (ext or sysext)
490 array_shift($pathParts);
491 $path = implode('/', $pathParts);
492 // If the path starts with ext/ or sysext/ migrate it
493 if (
494 strpos($itemConfig[2], 'ext/') === 0
495 || strpos($itemConfig[2], 'sysext/') === 0
496 ) {
497 $this->messages[] = '[' . $tcaPath . '] ext/ or sysext/ within the path (' . $path . ') in items array is deprecated, use EXT: reference';
498 $itemConfig[2] = 'EXT:' . $path;
499 } elseif (strpos($itemConfig[2], 'i/') === 0) {
500 $this->messages[] = '[' . $tcaPath . '] i/ within the path (' . $path . ') in items array is deprecated, use EXT: reference';
501 $itemConfig[2] = 'EXT:backend/Resources/Public/Images/' . substr($itemConfig[2], 2);
502 }
503 }
504 }
505 }
506 }
507 }
508 return $tca;
509 }
510
511 /**
512 * Migrate "iconsInOptionTags" for "select" TCA fields
513 *
514 * @param array $tca Incoming TCA
515 * @return array Migrated TCA
516 */
517 protected function migrateIconsInOptionTags(array $tca): array
518 {
519 $newTca = $tca;
520
521 foreach ($newTca as $table => &$tableDefinition) {
522 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
523 continue;
524 }
525 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
526 if (isset($fieldConfig['config']['iconsInOptionTags'])) {
527 unset($fieldConfig['config']['iconsInOptionTags']);
528 $this->messages[] = 'Configuration option \'iconsInOptionTags\' was removed from field "' . $fieldName . '" in TCA table "' . $table . '[\'config\']"';
529 }
530 }
531 }
532
533 return $newTca;
534 }
535
536 /**
537 * Migrate "iconfile" references which starts with ../ to EXT: and consisting of filename only to absolute paths in EXT:t3skin
538 *
539 * @param array $tca Incoming TCA
540 * @return array Migrated TCA
541 */
542 protected function migrateIconfileRelativePathOrFilenameOnlyToExtReference(array $tca): array
543 {
544 foreach ($tca as $table => &$tableDefinition) {
545 if (!isset($tableDefinition['ctrl']) || !is_array($tableDefinition['ctrl'])) {
546 continue;
547 }
548 if (!isset($tableDefinition['ctrl']['iconfile'])) {
549 continue;
550 }
551 if (strpos($tableDefinition['ctrl']['iconfile'], '../typo3conf/ext/') === 0) {
552 $tableDefinition['ctrl']['iconfile'] = str_replace('../typo3conf/ext/', 'EXT:', $tableDefinition['ctrl']['iconfile']);
553 $tcaPath = implode('.', [$table, 'ctrl', 'iconfile']);
554 $this->messages[] = '[' . $tcaPath . '] relative path to ../typo3conf/ext/ is deprecated, use EXT: instead';
555 } elseif (strpos($tableDefinition['ctrl']['iconfile'], '/') === false) {
556 $tableDefinition['ctrl']['iconfile'] = 'EXT:backend/Resources/Public/Images/' . $tableDefinition['ctrl']['iconfile'];
557 $tcaPath = implode('.', [$table, 'ctrl', 'iconfile']);
558 $this->messages[] = '[' . $tcaPath . '] filename only is deprecated, use EXT: or absolute reference instead';
559 }
560 }
561 return $tca;
562 }
563
564 /**
565 * Migrate "type=select" with "renderMode=[tree|singlebox|checkbox]" to "renderType=[selectTree|selectSingleBox|selectCheckBox]".
566 * This migration also take care of "maxitems" settings and set "renderType=[selectSingle|selectMultipleSideBySide]" if no other
567 * renderType is already set.
568 *
569 * @param array $tca
570 * @return array
571 */
572 public function migrateSelectFieldRenderType(array $tca): array
573 {
574 $newTca = $tca;
575
576 foreach ($newTca as $table => &$tableDefinition) {
577 if (empty($tableDefinition['columns'])) {
578 continue;
579 }
580
581 foreach ($tableDefinition['columns'] as $columnName => &$columnDefinition) {
582 // Only handle select fields.
583 if (empty($columnDefinition['config']['type']) || $columnDefinition['config']['type'] !== 'select') {
584 continue;
585 }
586 // Do not handle field where the render type is set.
587 if (!empty($columnDefinition['config']['renderType'])) {
588 continue;
589 }
590
591 $tableColumnInfo = 'table "' . $table . '[\'columns\'][\'' . $columnName . '\']"';
592 $this->messages[] = 'Using the \'type\' = \'select\' field in "' . $table . '[\'columns\'][\'' . $columnName . '\'][\'config\'][\'type\'] = \'select\'" without the "renderType" setting in "'
593 . $table . '[\'columns\'][\'' . $columnName . '\'][\'config\'][\'renderType\']" is deprecated.';
594
595 $columnConfig = &$columnDefinition['config'];
596 if (!empty($columnConfig['renderMode'])) {
597 $this->messages[] = 'The "renderMode" setting for select fields is deprecated. Please use "renderType" instead in ' . $tableColumnInfo;
598 switch ($columnConfig['renderMode']) {
599 case 'tree':
600 $columnConfig['renderType'] = 'selectTree';
601 break;
602 case 'singlebox':
603 $columnConfig['renderType'] = 'selectSingleBox';
604 break;
605 case 'checkbox':
606 $columnConfig['renderType'] = 'selectCheckBox';
607 break;
608 default:
609 $this->messages[] = 'The render mode ' . $columnConfig['renderMode'] . ' is invalid for the select field in ' . $tableColumnInfo;
610 }
611 continue;
612 }
613
614 $maxItems = !empty($columnConfig['maxitems']) ? (int)$columnConfig['maxitems'] : 1;
615 if ($maxItems <= 1) {
616 $columnConfig['renderType'] = 'selectSingle';
617 } else {
618 $columnConfig['renderType'] = 'selectMultipleSideBySide';
619 }
620 }
621 }
622
623 return $newTca;
624 }
625
626 /**
627 * Migrate the visibility of the icon table for fields with "renderType=selectSingle"
628 *
629 * @param array $tca
630 * @return array Migrated TCA
631 */
632 public function migrateSelectFieldIconTable(array $tca): array
633 {
634 foreach ($tca as $table => &$tableDefinition) {
635 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
636 continue;
637 }
638 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
639 if (empty($fieldConfig['config']['renderType']) || $fieldConfig['config']['renderType'] !== 'selectSingle') {
640 continue;
641 }
642 if (array_key_exists('noIconsBelowSelect', $fieldConfig['config'])) {
643 $this->messages[] = 'The "noIconsBelowSelect" setting for select fields in table "'
644 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']" was removed. Please define the setting "showIconTable" in table "'
645 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'showIconTable\']"';
646 if (!$fieldConfig['config']['noIconsBelowSelect']) {
647 // If old setting was explicitly false, enable icon table if not defined yet
648 if (!array_key_exists('showIconTable', $fieldConfig['config'])) {
649 $fieldConfig['config']['showIconTable'] = true;
650 }
651 }
652 unset($fieldConfig['config']['noIconsBelowSelect']);
653 }
654 if (array_key_exists('suppress_icons', $fieldConfig['config'])) {
655 $this->messages[] = 'The "suppress_icons" setting for select fields in table "'
656 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']" was removed. Please define the setting "showIconTable" for table "'
657 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'showIconTable\']"';
658 unset($fieldConfig['config']['suppress_icons']);
659 }
660 if (array_key_exists('foreign_table_loadIcons', $fieldConfig['config'])) {
661 $this->messages[] = 'The "foreign_table_loadIcons" setting for select fields in table "'
662 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']" was removed. Please define the setting "showIconTable" for table "'
663 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'showIconTable\']"';
664 unset($fieldConfig['config']['foreign_table_loadIcons']);
665 }
666 }
667 }
668 return $tca;
669 }
670
671 /**
672 * Migrate wizard "wizard_element_browser" used in mode "wizard" to use the "wizard_link" instead
673 *
674 * @param array $tca
675 * @return array Migrated TCA
676 */
677 protected function migrateElementBrowserWizardToLinkHandler(array $tca): array
678 {
679 foreach ($tca as $table => &$tableDefinition) {
680 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
681 continue;
682 }
683 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
684 if (
685 isset($fieldConfig['config']['wizards']['link']['module']['name']) && $fieldConfig['config']['wizards']['link']['module']['name'] === 'wizard_element_browser'
686 && isset($fieldConfig['config']['wizards']['link']['module']['urlParameters']['mode']) && $fieldConfig['config']['wizards']['link']['module']['urlParameters']['mode'] === 'wizard'
687 ) {
688 $fieldConfig['config']['wizards']['link']['module']['name'] = 'wizard_link';
689 unset($fieldConfig['config']['wizards']['link']['module']['urlParameters']['mode']);
690 if (empty($fieldConfig['config']['wizards']['link']['module']['urlParameters'])) {
691 unset($fieldConfig['config']['wizards']['link']['module']['urlParameters']);
692 }
693 $this->messages[] = 'Reference to "wizard_element_browser" was migrated from"'
694 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'link\'][\'module\'][\'name\'] === \'wizard_element_browser\'"'
695 . 'to new "wizard_link", "'
696 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'link\'][\'module\'][\'name\'] = \'wizard_link\' "';
697 }
698 }
699 }
700 return $tca;
701 }
702
703 /**
704 * Migrate defaultExtras "richtext:rte_transform[mode=ts_css]" and similar stuff like
705 * "richtext:rte_transform[mode=ts_css]" to "richtext:rte_transform"
706 *
707 * @param array $tca
708 * @return array Migrated TCA
709 */
710 protected function migrateDefaultExtrasRteTransFormOptions(array $tca): array
711 {
712 foreach ($tca as $table => &$tableDefinition) {
713 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
714 continue;
715 }
716 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
717 if (isset($fieldConfig['defaultExtras'])) {
718 $originalValue = $fieldConfig['defaultExtras'];
719 $defaultExtrasArray = GeneralUtility::trimExplode(':', $originalValue, true);
720 $isRichtextField = false;
721 foreach ($defaultExtrasArray as $defaultExtrasField) {
722 if (substr($defaultExtrasField, 0, 8) === 'richtext') {
723 $isRichtextField = true;
724 $fieldConfig['config']['enableRichtext'] = true;
725 $fieldConfig['config']['richtextConfiguration'] = 'default';
726 }
727 }
728 if ($isRichtextField) {
729 unset($fieldConfig['defaultExtras']);
730 $this->messages[] = 'RTE configuration via \'defaultExtras\' options are deprecated. String "' . $originalValue . '" in TCA'
731 . ' ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'defaultExtras\'] was changed to'
732 . ' options in ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']';
733 }
734 }
735 }
736 }
737
738 foreach ($tca as $table => &$tableDefinition) {
739 if (!isset($tableDefinition['types']) || !is_array($tableDefinition['types'])) {
740 continue;
741 }
742 foreach ($tableDefinition['types'] as $typeName => &$typeArray) {
743 if (!isset($typeArray['columnsOverrides']) || !is_array($typeArray['columnsOverrides'])) {
744 continue;
745 }
746 foreach ($typeArray['columnsOverrides'] as $fieldName => &$fieldConfig) {
747 if (isset($fieldConfig['defaultExtras'])) {
748 $originalValue = $fieldConfig['defaultExtras'];
749 $defaultExtrasArray = GeneralUtility::trimExplode(':', $originalValue, true);
750 $isRichtextField = false;
751 foreach ($defaultExtrasArray as $defaultExtrasField) {
752 if (substr($defaultExtrasField, 0, 8) === 'richtext') {
753 $isRichtextField = true;
754 $fieldConfig['config']['enableRichtext'] = true;
755 $fieldConfig['config']['richtextConfiguration'] = 'default';
756 }
757 }
758 if ($isRichtextField) {
759 unset($fieldConfig['defaultExtras']);
760 $this->messages[] = 'RTE configuration via \'defaultExtras\' options are deprecated. String "' . $originalValue . '" in TCA'
761 . ' ' . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'' . $fieldName . '\'][\'defaultExtras\']' .
762 ' was changed to options in ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']';
763 }
764 }
765 }
766 }
767 }
768
769 return $tca;
770 }
771
772 /**
773 * Migrates selectTree fields deprecated options
774 *
775 * @param array $tca Incoming TCA
776 * @return array Migrated TCA
777 */
778 protected function migrateSelectTreeOptions(array $tca): array
779 {
780 foreach ($tca as $table => &$tableDefinition) {
781 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
782 continue;
783 }
784 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
785 if (isset($fieldConfig['config']['renderType']) && $fieldConfig['config']['renderType'] === 'selectTree') {
786 if (isset($fieldConfig['config']['treeConfig']['appearance']['width'])) {
787 $this->messages[] = 'The selectTree field [\'treeConfig\'][\'appearance\'][\'width\'] setting is deprecated'
788 . ' and was removed in TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']'
789 . '[\'treeConfig\'][\'appearance\'][\'width\'] ';
790 unset($fieldConfig['config']['treeConfig']['appearance']['width']);
791 }
792
793 if (isset($fieldConfig['config']['treeConfig']['appearance']['allowRecursiveMode'])) {
794 $this->messages[] = 'The selectTree field [\'treeConfig\'][\'appearance\'][\'allowRecursiveMode\'] setting is deprecated'
795 . ' and was removed in TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']'
796 . '[\'treeConfig\'][\'appearance\'][\'allowRecursiveMode\'] ';
797 unset($fieldConfig['config']['treeConfig']['appearance']['allowRecursiveMode']);
798 }
799
800 if (isset($fieldConfig['config']['autoSizeMax'])) {
801 $this->messages[] = 'The selectTree field [\'autoSizeMax\'] setting is deprecated'
802 . ' and was removed in TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'autoSizeMax\'].'
803 . ' The \'size\' value was adapted to the previous autoSizeMax value';
804 $fieldConfig['config']['size'] = $fieldConfig['config']['autoSizeMax'];
805 unset($fieldConfig['config']['autoSizeMax']);
806 }
807 }
808 }
809 }
810 return $tca;
811 }
812
813 /**
814 * Migrates selectTree fields deprecated options
815 *
816 * @param array $tca Incoming TCA
817 * @return array Migrated TCA
818 */
819 protected function migrateTSconfigSoftReferences(array $tca): array
820 {
821 foreach ($tca as $table => &$tableDefinition) {
822 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
823 continue;
824 }
825 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
826 if (isset($fieldConfig['config'])) {
827 if (isset($fieldConfig['config']['softref'])) {
828 $softReferences = array_flip(GeneralUtility::trimExplode(',', $fieldConfig['config']['softref']));
829 $changed = false;
830 if (isset($softReferences['TSconfig'])) {
831 $changed = true;
832 unset($softReferences['TSconfig']);
833 }
834 if (isset($softReferences['TStemplate'])) {
835 $changed = true;
836 unset($softReferences['TStemplate']);
837 }
838 if ($changed) {
839 if (!empty($softReferences)) {
840 $softReferences = array_flip($softReferences);
841 $fieldConfig['config']['softref'] = implode(',', $softReferences);
842 } else {
843 unset($fieldConfig['config']['softref']);
844 }
845 $this->messages[] = 'The soft reference setting using \'TSconfig\' and '
846 . '\'TStemplate\' was removed in TCA ' . $table . '[\'columns\']'
847 . '[\'' . $fieldName . '\'][\'config\'][\'softref\']';
848 }
849 }
850 }
851 }
852 }
853 return $tca;
854 }
855
856 /**
857 * Removes the option "showIfRTE" for TCA type "check"
858 *
859 * @param array $tca Incoming TCA
860 * @return array Migrated TCA
861 */
862 protected function migrateShowIfRteOption(array $tca): array
863 {
864 foreach ($tca as $table => &$tableDefinition) {
865 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
866 continue;
867 }
868 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
869 if (isset($fieldConfig['config']) && $fieldConfig['config']['type'] === 'check') {
870 if (isset($fieldConfig['config']['showIfRTE'])) {
871 unset($fieldConfig['config']['showIfRTE']);
872 $this->messages[] = 'The TCA setting \'showIfRTE\' was removed '
873 . 'in TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']';
874 }
875 }
876 }
877 }
878 return $tca;
879 }
880
881 /**
882 * Casts "versioningWS" to bool, and removes "versioning_followPages"
883 *
884 * @param array $tca Incoming TCA
885 * @return array Migrated TCA
886 */
887 protected function migrateWorkspacesOptions(array $tca): array
888 {
889 foreach ($tca as $table => &$tableDefinition) {
890 if (isset($tableDefinition['ctrl']['versioningWS']) && !is_bool($tableDefinition['ctrl']['versioningWS'])) {
891 $tableDefinition['ctrl']['versioningWS'] = (bool)$tableDefinition['ctrl']['versioningWS'];
892 $this->messages[] = 'The TCA setting \'versioningWS\' was set to a boolean value '
893 . 'in TCA ' . $table . '[\'ctrl\'][\'versioningWS\']';
894 }
895 if (isset($tableDefinition['ctrl']['versioning_followPages']) && !empty($tableDefinition['ctrl']['versioning_followPages'])) {
896 unset($tableDefinition['ctrl']['versioning_followPages']);
897 $this->messages[] = 'The TCA setting \'versioning_followPages\' was removed as it is unused '
898 . 'in TCA ' . $table . '[\'ctrl\'][\'versioning_followPages\']';
899 }
900 }
901 return $tca;
902 }
903
904 /**
905 * Removes "transForeignTable" and "transOrigPointerTable" which has been
906 * used for tables "pages" and "pages_languages_overlay" in the core only.
907 *
908 * @param array $tca Incoming TCA
909 * @return array Migrated TCA
910 */
911 protected function migrateTranslationTable(array $tca): array
912 {
913 foreach ($tca as $table => &$tableDefinition) {
914 if (!empty($tableDefinition['ctrl']['transForeignTable'])) {
915 unset($tableDefinition['ctrl']['transForeignTable']);
916 $this->messages[] = 'The TCA setting \'transForeignTable\' was removed '
917 . 'in TCA ' . $table . '[\'ctrl\'][\'transForeignTable\']';
918 }
919 if (!empty($tableDefinition['ctrl']['transOrigPointerTable'])) {
920 unset($tableDefinition['ctrl']['transOrigPointerTable']);
921 $this->messages[] = 'The TCA setting \'transOrigPointerTable\' was removed '
922 . 'in TCA ' . $table . '[\'ctrl\'][\'transOrigPointerTable\']';
923 }
924 }
925 return $tca;
926 }
927
928 /**
929 * Removes "noCopy" from possible settings for "l10n_mode" for each column.
930 *
931 * @param array $tca
932 * @return array Migrated TCA
933 */
934 protected function migrateL10nModeDefinitions(array $tca)
935 {
936 foreach ($tca as $table => &$tableDefinition) {
937 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
938 continue;
939 }
940 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
941 if (empty($fieldConfig['l10n_mode'])) {
942 continue;
943 }
944 if ($fieldConfig['l10n_mode'] === 'noCopy') {
945 unset($fieldConfig['l10n_mode']);
946 $this->messages[] = 'The TCA setting \'noCopy\' was removed '
947 . 'in TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'l10n_mode\']';
948 }
949 if ($fieldConfig['l10n_mode'] === 'mergeIfNotBlank') {
950 unset($fieldConfig['l10n_mode']);
951 if (empty($fieldConfig['config']['behaviour']['allowLanguageSynchronization'])) {
952 $fieldConfig['config']['behaviour']['allowLanguageSynchronization'] = true;
953 }
954 $this->messages[] = 'The TCA setting \'mergeIfNotBlank\' was removed '
955 . 'in TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'l10n_mode\']'
956 . ' and changed to ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'behaviour\']'
957 . '[\'allowLanguageSynchronization\'] = true';
958 }
959 }
960 }
961 return $tca;
962 }
963
964 /**
965 * Move ['ctrl']['requestUpdate'] to 'onChange => "reload"' of single fields
966 *
967 * @param array $tca Incoming TCA
968 * @return array Migrated TCA
969 */
970 protected function migrateRequestUpdate(array $tca): array
971 {
972 foreach ($tca as $table => &$tableDefinition) {
973 if (!empty($tableDefinition['ctrl']['requestUpdate'])) {
974 $fields = GeneralUtility::trimExplode(',', $tableDefinition['ctrl']['requestUpdate']);
975 foreach ($fields as $field) {
976 if (isset($tableDefinition['columns'][$field])) {
977 $tableDefinition['columns'][$field]['onChange'] = 'reload';
978 }
979 }
980 $this->messages[] = 'The TCA setting [\'ctrl\'][\'requestUpdate\'] was removed from '
981 . ' table ' . $table . '. The column field(s) "' . implode('" and "', $fields) . '" were updated'
982 . ' and contain option "\'onChange\' => \'reload\'" parallel to \'config\' and \'label\' section.';
983 unset($tableDefinition['ctrl']['requestUpdate']);
984 }
985 }
986 return $tca;
987 }
988
989 /**
990 * Move all type=input with eval=date/time configuration to an own renderType
991 *
992 * @param array $tca
993 * @return array Migrated TCA
994 */
995 protected function migrateInputDateTimeToRenderType(array $tca): array
996 {
997 foreach ($tca as $table => &$tableDefinition) {
998 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
999 continue;
1000 }
1001 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
1002 if ($fieldConfig['config']['type'] !== 'input') {
1003 continue;
1004 }
1005 $eval = $fieldConfig['config']['eval'] ?? '';
1006 $eval = GeneralUtility::trimExplode(',', $eval, true);
1007 if (in_array('date', $eval, true)
1008 || in_array('datetime', $eval, true)
1009 || in_array('time', $eval, true)
1010 || in_array('timesec', $eval, true)
1011 ) {
1012 if (!isset($fieldConfig['config']['renderType'])) {
1013 $fieldConfig['config']['renderType'] = 'inputDateTime';
1014 $this->messages[] = 'The TCA setting \'renderType\' => \'inputDateTime\' was added '
1015 . 'in TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']';
1016 }
1017 }
1018 }
1019 }
1020 return $tca;
1021 }
1022
1023 /**
1024 * Wizards configuration may hold "enableByTypeConfig" and are then enabled
1025 * for certain types via "defaultExtras".
1026 * Find wizards configured like that and migrate them to "columnsOverrides"
1027 *
1028 * @param array $tca Incoming TCA
1029 * @return array Migrated TCA
1030 */
1031 public function migrateWizardEnableByTypeConfigToColumnsOverrides(array $tca): array
1032 {
1033 $newTca = $tca;
1034 foreach ($tca as $table => $tableDefinition) {
1035 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
1036 continue;
1037 }
1038 foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
1039 if (
1040 !empty($fieldConfig['config']['type']) // type is set
1041 && isset($fieldConfig['config']['wizards'])
1042 && is_array($fieldConfig['config']['wizards']) // and there are wizards
1043 ) {
1044 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
1045 if (isset($wizardConfig['enableByTypeConfig']) // and enableByTypeConfig is given
1046 && $wizardConfig['enableByTypeConfig'] // and enabled
1047 ) { // and enableByTypeConfig is enabled
1048 // Remove this "enableByTypeConfig" wizard from columns
1049 unset($newTca[$table]['columns'][$fieldName]['config']['wizards'][$wizardName]);
1050 if (!isset($tableDefinition['types']) || !is_array($tableDefinition['types'])) {
1051 // No type definition at all ... continue directly
1052 continue;
1053 }
1054 foreach ($tableDefinition['types'] as $typeName => $typeArray) {
1055 if (empty($typeArray['columnsOverrides'][$fieldName]['defaultExtras'])
1056 || strpos($typeArray['columnsOverrides'][$fieldName]['defaultExtras'], $wizardName) === false
1057 ) {
1058 // Continue directly if this wizard is not enabled for given type
1059 continue;
1060 }
1061 $defaultExtras = $typeArray['columnsOverrides'][$fieldName]['defaultExtras'];
1062 $defaultExtrasArray = GeneralUtility::trimExplode(':', $defaultExtras, true);
1063 $newDefaultExtrasArray = [];
1064 foreach ($defaultExtrasArray as $fieldExtraField) {
1065 if (substr($fieldExtraField, 0, 8) === 'wizards[') {
1066 $enabledWizards = substr($fieldExtraField, 8, strlen($fieldExtraField) - 8); // Cut off "wizards[
1067 $enabledWizards = substr($enabledWizards, 0, strlen($enabledWizards) - 1);
1068 $enabledWizardsArray = GeneralUtility::trimExplode('|', $enabledWizards, true);
1069 foreach ($enabledWizardsArray as $enabledWizardName) {
1070 if ($enabledWizardName === $wizardName) {
1071 // Fill new array
1072 unset($newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldName]['defaultExtras']);
1073 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldName]['config']['wizards'][$enabledWizardName] = $wizardConfig;
1074 unset($newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldName]['config']['wizards'][$enabledWizardName]['enableByTypeConfig']);
1075 $this->messages[] = 'The wizard with "enableByTypeConfig" set to 1 has been migrated to \'columnsOverrides\'.'
1076 . ' It has been migrated from "'
1077 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'' . $wizardName . '\']" to '
1078 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'' . $wizardName . '\'].';
1079 }
1080 }
1081 } else {
1082 $newDefaultExtrasArray[] = $fieldExtraField;
1083 }
1084 }
1085 if ($defaultExtrasArray !== $newDefaultExtrasArray
1086 && !empty($newDefaultExtrasArray)
1087 ) {
1088 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldName]['defaultExtras'] = implode(':', $newDefaultExtrasArray);
1089 }
1090 }
1091 } elseif (isset($wizardConfig['enableByTypeConfig'])) {
1092 // enableByTypeConfig is set, but not true or 1 or '1', just delete it.
1093 unset($newTca[$table]['columns'][$fieldName]['config']['wizards'][$wizardName]['enableByTypeConfig']);
1094 }
1095 }
1096 }
1097 }
1098 }
1099 return $newTca;
1100 }
1101
1102 /**
1103 * Migrates fields having a colorpicker wizard to a color field
1104 *
1105 * @param array $tca Incoming TCA
1106 * @return array Migrated TCA
1107 */
1108 protected function migrateColorPickerWizardToRenderType(array $tca): array
1109 {
1110 foreach ($tca as $table => &$tableDefinition) {
1111 if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
1112 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
1113 if (isset($fieldConfig['config'])) {
1114 // Do not handle field where the render type is set.
1115 if (!empty($fieldConfig['config']['renderType'])) {
1116 continue;
1117 }
1118 if ($fieldConfig['config']['type'] === 'input') {
1119 if (isset($fieldConfig['config']['wizards']) && is_array($fieldConfig['config']['wizards'])) {
1120 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizard) {
1121 if (isset($wizard['type']) && ($wizard['type'] === 'colorbox')) {
1122 unset($fieldConfig['config']['wizards'][$wizardName]);
1123 if (empty($fieldConfig['config']['wizards'])) {
1124 unset($fieldConfig['config']['wizards']);
1125 }
1126 $fieldConfig['config']['renderType'] = 'colorpicker';
1127 $this->messages[] = 'The color-picker wizard using \'colorbox\' is deprecated'
1128 . ' in TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']'
1129 . '[\'wizards\'][\'' . $wizardName . '\'] and was changed to ' . $table
1130 . '[\'columns\'][\'' . $fieldName . '\'][\'config\'] = \'colorpicker\'';
1131 }
1132 }
1133 }
1134 if (empty($fieldConfig['config']['wizards'])) {
1135 unset($fieldConfig['config']['wizards']);
1136 }
1137 if (isset($tableDefinition['types']) && is_array($tableDefinition['types'])) {
1138 foreach ($tableDefinition['types'] as $typeName => &$typeArray) {
1139 if (isset($typeArray['columnsOverrides']) && is_array($typeArray['columnsOverrides'])) {
1140 if (isset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1141 && is_array($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1142 ) {
1143 foreach ($typeArray['columnsOverrides'][$fieldName]['config']['wizards'] as $wizardName => $wizard) {
1144 if (isset($wizard['type']) && ($wizard['type'] === 'colorbox')) {
1145 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'][$wizardName]);
1146 $typeArray['columnsOverrides'][$fieldName]['config']['type'] = 'input';
1147 $typeArray['columnsOverrides'][$fieldName]['config']['renderType'] = 'colorpicker';
1148 $this->messages[] = 'The color-picker wizard in columnsOverrides using \'colorbox\' has been migrated to a \'rendertype\' = \'colorpicker\'.'
1149 . ' It has been migrated from TCA "' . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\']'
1150 . '[\'wizards\'][\'' . $wizardName . '\'][\'type\'] = \'colorbox\'"" to "' . $table
1151 . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\'][\'renderType\'] = \'colorpicker\'"';
1152 }
1153 }
1154 if (empty($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])) {
1155 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards']);
1156 }
1157 }
1158 }
1159 }
1160 }
1161 }
1162 }
1163 }
1164 }
1165 }
1166
1167 return $tca;
1168 }
1169
1170 /**
1171 * Move type=input with select wizard to config['valuePicker']
1172 *
1173 * @param array $tca
1174 * @return array Migrated TCA
1175 */
1176 protected function migrateSelectWizardToValuePicker(array $tca): array
1177 {
1178 foreach ($tca as $table => &$tableDefinition) {
1179 if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
1180 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
1181 if ($fieldConfig['config']['type'] === 'input' || $fieldConfig['config']['type'] === 'text') {
1182 if (isset($fieldConfig['config']['wizards']) && is_array($fieldConfig['config']['wizards'])) {
1183 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
1184 if (isset($wizardConfig['type'])
1185 && $wizardConfig['type'] === 'select'
1186 && isset($wizardConfig['items'])
1187 && is_array($wizardConfig['items'])
1188 ) {
1189 $fieldConfig['config']['valuePicker']['items'] = $wizardConfig['items'];
1190 if (isset($wizardConfig['mode'])
1191 && is_string($wizardConfig['mode'])
1192 && in_array($wizardConfig['mode'], ['append', 'prepend', ''])
1193 ) {
1194 $fieldConfig['config']['valuePicker']['mode'] = $wizardConfig['mode'];
1195 }
1196 unset($fieldConfig['config']['wizards'][$wizardName]);
1197 $this->messages[] = 'The select wizard in TCA '
1198 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'' . $wizardName . '\']'
1199 . ' has been migrated to '
1200 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'valuePicker\'].';
1201 }
1202 }
1203 }
1204 if (empty($fieldConfig['config']['wizards'])) {
1205 unset($fieldConfig['config']['wizards']);
1206 }
1207 if (isset($tableDefinition['types']) && is_array($tableDefinition['types'])) {
1208 foreach ($tableDefinition['types'] as $typeName => &$typeArray) {
1209 if (isset($typeArray['columnsOverrides']) && is_array($typeArray['columnsOverrides'])) {
1210 if (isset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1211 && is_array($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1212 ) {
1213 foreach ($typeArray['columnsOverrides'][$fieldName]['config']['wizards'] as $wizardName => $wizard) {
1214 if (isset($wizard['type'])
1215 && ($wizard['type'] === 'select')
1216 && isset($wizard['items'])
1217 && is_array($wizard['items'])
1218 ) {
1219 $typeArray['columnsOverrides'][$fieldName]['config']['valuePicker'] = $wizard;
1220 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'][$wizardName]);
1221 unset($typeArray['columnsOverrides'][$fieldName]['config']['valuePicker']['type']);
1222 $this->messages[] = 'The select wizard in columnsOverrides using \'type\' = \'select\' has been migrated'
1223 . ' from TCA ' . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\']'
1224 . '[\'wizards\'][\'' . $wizardName . '\'] to ' . $table
1225 . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\'][\'valuePicker\']';
1226 }
1227 }
1228 if (empty($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])) {
1229 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards']);
1230 }
1231 }
1232 }
1233 }
1234 }
1235 }
1236 }
1237 }
1238 }
1239 return $tca;
1240 }
1241
1242 /**
1243 * Move type=input with select wizard to config['valuePicker']
1244 *
1245 * @param array $tca
1246 * @return array Migrated TCA
1247 */
1248 protected function migrateSliderWizardToSliderConfiguration(array $tca): array
1249 {
1250 foreach ($tca as $table => &$tableDefinition) {
1251 if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
1252 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
1253 if ($fieldConfig['config']['type'] === 'input') {
1254 if (isset($fieldConfig['config']['wizards'])
1255 && is_array($fieldConfig['config']['wizards'])) {
1256 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
1257 if (isset($wizardConfig['type']) && $wizardConfig['type'] === 'slider') {
1258 $fieldConfig['config']['slider'] = [];
1259 if (isset($wizardConfig['width'])) {
1260 $fieldConfig['config']['slider']['width'] = $wizardConfig['width'];
1261 }
1262 if (isset($wizardConfig['step'])) {
1263 $fieldConfig['config']['slider']['step'] = $wizardConfig['step'];
1264 }
1265 unset($fieldConfig['config']['wizards'][$wizardName]);
1266 $this->messages[] = 'The slider wizard in TCA '
1267 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'' . $wizardName . '\']'
1268 . ' has been migrated to '
1269 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'slider\'].';
1270 }
1271 }
1272 }
1273 if (empty($fieldConfig['config']['wizards'])) {
1274 unset($fieldConfig['config']['wizards']);
1275 }
1276 if (isset($tableDefinition['types']) && is_array($tableDefinition['types'])) {
1277 foreach ($tableDefinition['types'] as $typeName => &$typeArray) {
1278 if (isset($typeArray['columnsOverrides']) && is_array($typeArray['columnsOverrides'])) {
1279 if (isset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1280 && is_array($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1281 ) {
1282 foreach ($typeArray['columnsOverrides'][$fieldName]['config']['wizards'] as $wizardName => $wizard) {
1283 if (isset($wizard['type']) && ($wizard['type'] === 'slider')) {
1284 $typeArray['columnsOverrides'][$fieldName]['config']['slider'] = $wizard;
1285 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'][$wizardName]);
1286 unset($typeArray['columnsOverrides'][$fieldName]['config']['slider']['type']);
1287 $this->messages[] = 'The slider wizard in columnsOverrides using \'type\' = \'slider\' has been migrated'
1288 . ' from TCA ' . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\']'
1289 . '[\'wizards\'][\'' . $wizardName . '\'] to ' . $table
1290 . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\'][\'slider\']';
1291 }
1292 }
1293 if (empty($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])) {
1294 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards']);
1295 }
1296 }
1297 }
1298 }
1299 }
1300 }
1301 }
1302 }
1303 }
1304 return $tca;
1305 }
1306
1307 /**
1308 * Move type=input fields that have a "link" wizard to an own renderType with fieldControl
1309 *
1310 * @param array $tca
1311 * @return array Modified TCA
1312 */
1313 protected function migrateLinkWizardToRenderTypeAndFieldControl(array $tca): array
1314 {
1315 foreach ($tca as $table => &$tableDefinition) {
1316 if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
1317 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
1318 if ($fieldConfig['config']['type'] === 'input'
1319 && !isset($fieldConfig['config']['renderType'])
1320 ) {
1321 if (isset($fieldConfig['config']['wizards'])
1322 && is_array($fieldConfig['config']['wizards'])) {
1323 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
1324 if (isset($wizardConfig['type'])
1325 && $wizardConfig['type'] === 'popup'
1326 && isset($wizardConfig['module']['name'])
1327 && $wizardConfig['module']['name'] === 'wizard_link'
1328 ) {
1329 $fieldConfig['config']['renderType'] = 'inputLink';
1330 if (isset($wizardConfig['title'])) {
1331 $fieldConfig['config']['fieldControl']['linkPopup']['options']['title'] = $wizardConfig['title'];
1332 }
1333 if (isset($wizardConfig['JSopenParams'])) {
1334 $fieldConfig['config']['fieldControl']['linkPopup']['options']['windowOpenParameters']
1335 = $wizardConfig['JSopenParams'];
1336 }
1337 if (isset($wizardConfig['params']['blindLinkOptions'])) {
1338 $fieldConfig['config']['fieldControl']['linkPopup']['options']['blindLinkOptions']
1339 = $wizardConfig['params']['blindLinkOptions'];
1340 }
1341 if (isset($wizardConfig['params']['blindLinkFields'])) {
1342 $fieldConfig['config']['fieldControl']['linkPopup']['options']['blindLinkFields']
1343 = $wizardConfig['params']['blindLinkFields'];
1344 }
1345 if (isset($wizardConfig['params']['allowedExtensions'])) {
1346 $fieldConfig['config']['fieldControl']['linkPopup']['options']['allowedExtensions']
1347 = $wizardConfig['params']['allowedExtensions'];
1348 }
1349 unset($fieldConfig['config']['wizards'][$wizardName]);
1350 $this->messages[] = 'The link wizard has been migrated to a \'renderType\' => \'inputLink \'. '
1351 . 'It has been migrated from TCA table "'
1352 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'' . $wizardName . '\']" to "'
1353 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'] = \'inputLink\'".';
1354 }
1355 }
1356 }
1357 if (empty($fieldConfig['config']['wizards'])) {
1358 unset($fieldConfig['config']['wizards']);
1359 }
1360 if (isset($tableDefinition['types']) && is_array($tableDefinition['types'])) {
1361 foreach ($tableDefinition['types'] as $typeName => &$typeArray) {
1362 if (isset($typeArray['columnsOverrides']) && is_array($typeArray['columnsOverrides'])) {
1363 if (isset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1364 && is_array($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1365 ) {
1366 foreach ($typeArray['columnsOverrides'][$fieldName]['config']['wizards'] as $wizardName => $wizard) {
1367 if (isset($wizard['type'])
1368 && $wizard['type'] === 'popup'
1369 && isset($wizard['module']['name'])
1370 && $wizard['module']['name'] === 'wizard_link'
1371 ) {
1372 $typeArray['columnsOverrides'][$fieldName]['config']['renderType'] = 'inputLink';
1373 if (isset($wizard['title'])) {
1374 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['linkPopup']['options']['title'] = $wizard['title'];
1375 }
1376 if (isset($wizard['JSopenParams'])) {
1377 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['linkPopup']['options']['windowOpenParameters']
1378 = $wizard['JSopenParams'];
1379 }
1380 if (isset($wizard['params']['blindLinkOptions'])) {
1381 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['linkPopup']['options']['blindLinkOptions']
1382 = $wizard['params']['blindLinkOptions'];
1383 }
1384 if (isset($wizard['params']['blindLinkFields'])) {
1385 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['linkPopup']['options']['blindLinkFields']
1386 = $wizard['params']['blindLinkFields'];
1387 }
1388 if (isset($wizard['params']['allowedExtensions'])) {
1389 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['linkPopup']['options']['allowedExtensions']
1390 = $wizard['params']['allowedExtensions'];
1391 }
1392 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'][$wizardName]);
1393 $this->messages[] = 'The link wizard in columnsOverrides using \'type\' = \'popup\' has been migrated to a \'renderType\' = \'inputLink\'.'
1394 . ' It has been migrated from TCA "' . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\']'
1395 . '[\'wizards\'][\'' . $wizardName . '\']" to "' . $table
1396 . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\'][\'renderType\'] = \'inputLink\'"';
1397 }
1398 }
1399 if (empty($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])) {
1400 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards']);
1401 }
1402 }
1403 }
1404 }
1405 }
1406 }
1407 }
1408 }
1409 }
1410
1411 return $tca;
1412 }
1413
1414 /**
1415 * Find select and group fields with enabled edit wizard and migrate to "fieldControl"
1416 *
1417 * @param array $tca
1418 * @return array
1419 */
1420 protected function migrateEditWizardToFieldControl(array $tca): array
1421 {
1422 foreach ($tca as $table => &$tableDefinition) {
1423 if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
1424 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
1425 if ($fieldConfig['config']['type'] === 'group'
1426 || $fieldConfig['config']['type'] === 'select'
1427 ) {
1428 if (isset($fieldConfig['config']['wizards'])
1429 && is_array($fieldConfig['config']['wizards'])
1430 ) {
1431 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
1432 if (isset($wizardConfig['type'])
1433 && $wizardConfig['type'] === 'popup'
1434 && isset($wizardConfig['module']['name'])
1435 && $wizardConfig['module']['name'] === 'wizard_edit'
1436 && !isset($fieldConfig['config']['fieldControl']['editPopup'])
1437 ) {
1438 $fieldConfig['config']['fieldControl']['editPopup']['disabled'] = false;
1439 if (isset($wizardConfig['title'])) {
1440 $fieldConfig['config']['fieldControl']['editPopup']['options']['title'] = $wizardConfig['title'];
1441 }
1442 if (isset($wizardConfig['JSopenParams'])) {
1443 $fieldConfig['config']['fieldControl']['editPopup']['options']['windowOpenParameters']
1444 = $wizardConfig['JSopenParams'];
1445 }
1446 unset($fieldConfig['config']['wizards'][$wizardName]);
1447 $this->messages[] = 'The edit wizard in TCA has been migrated to a \'fieldControl\' = \'editPopup\' element.'
1448 . ' It has been migrated from TCA "'
1449 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'' . $wizardName . '\']" to "'
1450 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'fieldControl\']=\'editPopup\'".';
1451 }
1452 }
1453 }
1454 if (empty($fieldConfig['config']['wizards'])) {
1455 unset($fieldConfig['config']['wizards']);
1456 }
1457 if (isset($tableDefinition['types']) && is_array($tableDefinition['types'])) {
1458 foreach ($tableDefinition['types'] as $typeName => &$typeArray) {
1459 if (isset($typeArray['columnsOverrides']) && is_array($typeArray['columnsOverrides'])) {
1460 if (isset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1461 && is_array($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1462 ) {
1463 foreach ($typeArray['columnsOverrides'][$fieldName]['config']['wizards'] as $wizardName => $wizard) {
1464 if (isset($wizard['type'])
1465 && $wizard['type'] === 'popup'
1466 && isset($wizard['module']['name'])
1467 && $wizard['module']['name'] === 'wizard_edit'
1468 ) {
1469 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['editPopup']['disabled'] = false;
1470 if (isset($wizard['title'])) {
1471 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['editPopup']['options']['title']
1472 = $wizard['title'];
1473 }
1474 if (isset($wizard['JSopenParams'])) {
1475 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['editPopup']['options']['windowOpenParameters']
1476 = $wizard['JSopenParams'];
1477 }
1478 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'][$wizardName]);
1479 $this->messages[] = 'The edit wizard in columnsOverrides using \'type\' = \'popup\' has been migrated to a \'fieldControl\' = \'editPopup\' element.'
1480 . ' It has been migrated from TCA "'
1481 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\']'
1482 . '[\'wizards\'][\'' . $wizardName . '\']" , to "'
1483 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\'][\'fieldControl\']=\'editPopup\'".';
1484 }
1485 }
1486 if (empty($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])) {
1487 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards']);
1488 }
1489 }
1490 }
1491 }
1492 }
1493 }
1494 }
1495 }
1496 }
1497
1498 return $tca;
1499 }
1500
1501 /**
1502 * Find select and group fields with enabled add wizard and migrate to "fieldControl"
1503 *
1504 * @param array $tca
1505 * @return array
1506 */
1507 protected function migrateAddWizardToFieldControl(array $tca): array
1508 {
1509 foreach ($tca as $table => &$tableDefinition) {
1510 if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
1511 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
1512 if ($fieldConfig['config']['type'] === 'group'
1513 || $fieldConfig['config']['type'] === 'select'
1514 ) {
1515 if (isset($fieldConfig['config']['wizards'])
1516 && is_array($fieldConfig['config']['wizards'])
1517 ) {
1518 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
1519 if (isset($wizardConfig['type'])
1520 && $wizardConfig['type'] === 'script'
1521 && isset($wizardConfig['module']['name'])
1522 && $wizardConfig['module']['name'] === 'wizard_add'
1523 && !isset($fieldConfig['config']['fieldControl']['addRecord'])
1524 ) {
1525 $fieldConfig['config']['fieldControl']['addRecord']['disabled'] = false;
1526 if (isset($wizardConfig['title'])) {
1527 $fieldConfig['config']['fieldControl']['addRecord']['options']['title'] = $wizardConfig['title'];
1528 }
1529 if (isset($wizardConfig['params']['table'])) {
1530 $fieldConfig['config']['fieldControl']['addRecord']['options']['table']
1531 = $wizardConfig['params']['table'];
1532 }
1533 if (isset($wizardConfig['params']['pid'])) {
1534 $fieldConfig['config']['fieldControl']['addRecord']['options']['pid']
1535 = $wizardConfig['params']['pid'];
1536 }
1537 if (isset($wizardConfig['params']['setValue'])) {
1538 $fieldConfig['config']['fieldControl']['addRecord']['options']['setValue']
1539 = $wizardConfig['params']['setValue'];
1540 }
1541 unset($fieldConfig['config']['wizards'][$wizardName]);
1542 $this->messages[] = 'The add wizard in TCA has been migrated to a \'fieldControl\' = \'addRecord\' element.'
1543 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'' . $wizardName . '\']'
1544 . ' It has been migrated from TCA "'
1545 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'fieldControl\']=\'addRecord\'.';
1546 }
1547 }
1548 }
1549 if (empty($fieldConfig['config']['wizards'])) {
1550 unset($fieldConfig['config']['wizards']);
1551 }
1552 if (isset($tableDefinition['types']) && is_array($tableDefinition['types'])) {
1553 foreach ($tableDefinition['types'] as $typeName => &$typeArray) {
1554 if (isset($typeArray['columnsOverrides']) && is_array($typeArray['columnsOverrides'])) {
1555 if (isset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1556 && is_array($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1557 ) {
1558 foreach ($typeArray['columnsOverrides'][$fieldName]['config']['wizards'] as $wizardName => $wizard) {
1559 if (isset($wizard['type'])
1560 && $wizard['type'] === 'script'
1561 && isset($wizard['module']['name'])
1562 && $wizard['module']['name'] === 'wizard_add'
1563 ) {
1564 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['addRecord']['disabled'] = false;
1565 if (isset($wizard['title'])) {
1566 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['addRecord']['options']['title']
1567 = $wizard['title'];
1568 }
1569 if (isset($wizard['params']['table'])) {
1570 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['addRecord']['options']['table']
1571 = $wizard['params']['table'];
1572 }
1573 if (isset($wizard['params']['pid'])) {
1574 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['addRecord']['options']['pid']
1575 = $wizard['params']['pid'];
1576 }
1577 if (isset($wizard['params']['setValue'])) {
1578 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['addRecord']['options']['setValue']
1579 = $wizard['params']['setValue'];
1580 }
1581 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'][$wizardName]);
1582 $this->messages[] = 'The add wizard in columnsOverrides using \'type\' = \'script\' has been migrated to a \'fieldControl\' = \'addRecord\' element.'
1583 . ' It has been migrated from TCA "'
1584 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\']'
1585 . '[\'wizards\'][\'' . $wizardName . '\']" to "'
1586 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\'][\'fieldControl\'=\'addRecord\'".';
1587 }
1588 }
1589 if (empty($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])) {
1590 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards']);
1591 }
1592 }
1593 }
1594 }
1595 }
1596 }
1597 }
1598 }
1599 }
1600
1601 return $tca;
1602 }
1603
1604 /**
1605 * Find select and group fields with enabled list wizard and migrate to "fieldControl"
1606 *
1607 * @param array $tca
1608 * @return array
1609 */
1610 protected function migrateListWizardToFieldControl(array $tca): array
1611 {
1612 foreach ($tca as $table => &$tableDefinition) {
1613 if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
1614 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
1615 if ($fieldConfig['config']['type'] === 'group'
1616 || $fieldConfig['config']['type'] === 'select'
1617 ) {
1618 if (isset($fieldConfig['config']['wizards'])
1619 && is_array($fieldConfig['config']['wizards'])
1620 ) {
1621 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
1622 if (isset($wizardConfig['type'])
1623 && $wizardConfig['type'] === 'script'
1624 && isset($wizardConfig['module']['name'])
1625 && $wizardConfig['module']['name'] === 'wizard_list'
1626 && !isset($fieldConfig['config']['fieldControl']['listModule'])
1627 ) {
1628 $fieldConfig['config']['fieldControl']['listModule']['disabled'] = false;
1629 if (isset($wizardConfig['title'])) {
1630 $fieldConfig['config']['fieldControl']['listModule']['options']['title'] = $wizardConfig['title'];
1631 }
1632 if (isset($wizardConfig['params']['table'])) {
1633 $fieldConfig['config']['fieldControl']['listModule']['options']['table']
1634 = $wizardConfig['params']['table'];
1635 }
1636 if (isset($wizardConfig['params']['pid'])) {
1637 $fieldConfig['config']['fieldControl']['listModule']['options']['pid']
1638 = $wizardConfig['params']['pid'];
1639 }
1640 unset($fieldConfig['config']['wizards'][$wizardName]);
1641 $this->messages[] = 'The list wizard in TCA has been migrated to a \'fieldControl\' = \'listModule\' element.'
1642 . ' It has been migrated from TCA "'
1643 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'' . $wizardName . '\']'
1644 . '" to "'
1645 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'fieldControl\'=\'listModule\'".';
1646 }
1647 }
1648 }
1649 if (empty($fieldConfig['config']['wizards'])) {
1650 unset($fieldConfig['config']['wizards']);
1651 }
1652 if (isset($tableDefinition['types']) && is_array($tableDefinition['types'])) {
1653 foreach ($tableDefinition['types'] as $typeName => &$typeArray) {
1654 if (isset($typeArray['columnsOverrides']) && is_array($typeArray['columnsOverrides'])) {
1655 if (isset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1656 && is_array($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1657 ) {
1658 foreach ($typeArray['columnsOverrides'][$fieldName]['config']['wizards'] as $wizardName => $wizard) {
1659 if (isset($wizard['type'])
1660 && $wizard['type'] === 'script'
1661 && isset($wizard['module']['name'])
1662 && $wizard['module']['name'] === 'wizard_list'
1663 ) {
1664 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['listModule']['disabled'] = false;
1665 if (isset($wizard['title'])) {
1666 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['listModule']['options']['title']
1667 = $wizard['title'];
1668 }
1669 if (isset($wizard['params']['table'])) {
1670 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['listModule']['options']['table']
1671 = $wizard['params']['table'];
1672 }
1673 if (isset($wizard['params']['pid'])) {
1674 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['listModule']['options']['pid']
1675 = $wizard['params']['pid'];
1676 }
1677 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'][$wizardName]);
1678 $this->messages[] = 'The list wizard in columnsOverrides using \'type\' = \'script\' has been migrated to a \'fieldControl\' = \'listModule\' element.'
1679 . ' It has been migrated from TCA "'
1680 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\']'
1681 . '[\'wizards\'][\'' . $wizardName . '\']" to "'
1682 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\'][\'fieldControl\'=\'listModule\'".';
1683 }
1684 }
1685 if (empty($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])) {
1686 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards']);
1687 }
1688 }
1689 }
1690 }
1691 }
1692 }
1693 }
1694 }
1695 }
1696
1697 return $tca;
1698 }
1699
1700 /**
1701 * Migrate defaultExtras "nowrap", "enable-tab", "fixed-font". Then drop all
1702 * remaining "defaultExtras", there shouldn't exist anymore.
1703 *
1704 * @param array $tca
1705 * @return array
1706 */
1707 protected function migrateLastPiecesOfDefaultExtras(array $tca): array
1708 {
1709 foreach ($tca as $table => &$tableDefinition) {
1710 if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
1711 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
1712 if (isset($fieldConfig['defaultExtras'])) {
1713 $defaultExtrasArray = GeneralUtility::trimExplode(':', $fieldConfig['defaultExtras'], true);
1714 foreach ($defaultExtrasArray as $defaultExtrasSetting) {
1715 if ($defaultExtrasSetting === 'rte_only') {
1716 $this->messages[] = 'The defaultExtras setting \'rte_only\' in TCA table '
1717 . $table . '[\'columns\'][\'' . $fieldName . '\'] has been dropped, the setting'
1718 . ' is no longer supported';
1719 continue;
1720 } elseif ($defaultExtrasSetting === 'nowrap') {
1721 $fieldConfig['config']['wrap'] = 'off';
1722 $this->messages[] = 'The defaultExtras setting \'nowrap\' in TCA table '
1723 . $table . '[\'columns\'][\'' . $fieldName . '\'] has been migrated to TCA table '
1724 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wrap\'] = \'off\'';
1725 } elseif ($defaultExtrasSetting === 'enable-tab') {
1726 $fieldConfig['config']['enableTabulator'] = true;
1727 $this->messages[] = 'The defaultExtras setting \'enable-tab\' in TCA table '
1728 . $table . '[\'columns\'][\'' . $fieldName . '\'] has been migrated to TCA table '
1729 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'enableTabulator\'] = true';
1730 } elseif ($defaultExtrasSetting === 'fixed-font') {
1731 $fieldConfig['config']['fixedFont'] = true;
1732 $this->messages[] = 'The defaultExtras setting \'fixed-font\' in TCA table '
1733 . $table . '[\'columns\'][\'' . $fieldName . '\'] has been migrated to TCA table '
1734 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'fixedFont\'] = true';
1735 } else {
1736 $this->messages[] = 'The defaultExtras setting \'' . $defaultExtrasSetting . '\' in TCA table '
1737 . $table . '[\'columns\'][\'' . $fieldName . '\'] is unknown and has been dropped.';
1738 }
1739 }
1740 unset($fieldConfig['defaultExtras']);
1741 }
1742 }
1743 }
1744 if (isset($tableDefinition['types']) && is_array($tableDefinition['types'])) {
1745 foreach ($tableDefinition['types'] as $typeName => &$typeArray) {
1746 if (isset($typeArray['columnsOverrides']) && is_array($typeArray['columnsOverrides'])) {
1747 foreach ($typeArray['columnsOverrides'] as $fieldName => &$overrideConfig) {
1748 $defaultExtrasArray = GeneralUtility::trimExplode(':', $overrideConfig['defaultExtras'], true);
1749 foreach ($defaultExtrasArray as $defaultExtrasSetting) {
1750 if ($defaultExtrasSetting === 'rte_only') {
1751 $this->messages[] = 'The defaultExtras setting \'rte_only\' in TCA table '
1752 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'' . $fieldName . '\']'
1753 . ' has been dropped, the setting is no longer supported';
1754 continue;
1755 } elseif ($defaultExtrasSetting === 'nowrap') {
1756 $overrideConfig['config']['wrap'] = 'off';
1757 $this->messages[] = 'The defaultExtras setting \'nowrap\' in TCA table '
1758 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'' . $fieldName . '\']'
1759 . ' has been migrated to TCA table '
1760 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'' . $fieldName . '\'][\'config\'][\'wrap\'] = \'off\'';
1761 } elseif ($defaultExtrasSetting === 'enable-tab') {
1762 $overrideConfig['config']['enableTabulator'] = true;
1763 $this->messages[] = 'The defaultExtras setting \'enable-tab\' in TCA table '
1764 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'' . $fieldName . '\']'
1765 . ' has been migrated to TCA table '
1766 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'' . $fieldName . '\'][\'config\'][\'enableTabulator\'] = true';
1767 } elseif ($defaultExtrasSetting === 'fixed-font') {
1768 $overrideConfig['config']['fixedFont'] = true;
1769 $this->messages[] = 'The defaultExtras setting \'fixed-font\' in TCA table '
1770 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'' . $fieldName . '\']'
1771 . ' has been migrated to TCA table '
1772 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'' . $fieldName . '\'][\'config\'][\'fixedFont\'] = true';
1773 } else {
1774 $this->messages[] = 'The defaultExtras setting \'' . $defaultExtrasSetting . '\' in TCA table '
1775 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'' . $fieldName . '\']'
1776 . ' is unknown and has been dropped.';
1777 }
1778 }
1779 unset($overrideConfig['defaultExtras']);
1780 }
1781 }
1782 }
1783 }
1784 }
1785
1786 return $tca;
1787 }
1788
1789 /**
1790 * Migrate wizard_table script to renderType="textTable" with options in fieldControl
1791 *
1792 * @param array $tca
1793 * @return array
1794 */
1795 protected function migrateTableWizardToRenderType(array $tca): array
1796 {
1797 foreach ($tca as $table => &$tableDefinition) {
1798 if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
1799 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
1800 if ($fieldConfig['config']['type'] === 'text') {
1801 if (isset($fieldConfig['config']['wizards'])
1802 && is_array($fieldConfig['config']['wizards'])
1803 ) {
1804 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
1805 if (isset($wizardConfig['type'])
1806 && $wizardConfig['type'] === 'script'
1807 && isset($wizardConfig['module']['name'])
1808 && $wizardConfig['module']['name'] === 'wizard_table'
1809 && !isset($fieldConfig['config']['fieldControl']['tableWizard'])
1810 && !isset($fieldConfig['config']['renderType'])
1811 ) {
1812 $fieldConfig['config']['renderType'] = 'textTable';
1813 if (isset($wizardConfig['title'])) {
1814 $fieldConfig['config']['fieldControl']['tableWizard']['options']['title'] = $wizardConfig['title'];
1815 }
1816 if (isset($wizardConfig['params']['xmlOutput']) && (int)$wizardConfig['params']['xmlOutput'] !== 0) {
1817 $fieldConfig['config']['fieldControl']['tableWizard']['options']['xmlOutput']
1818 = (int)$wizardConfig['params']['xmlOutput'];
1819 }
1820 if (isset($wizardConfig['params']['numNewRows'])) {
1821 $fieldConfig['config']['fieldControl']['tableWizard']['options']['numNewRows']
1822 = $wizardConfig['params']['numNewRows'];
1823 }
1824 unset($fieldConfig['config']['wizards'][$wizardName]);
1825 $this->messages[] = 'The table wizard in TCA has been migrated to a \'renderType\' = \'textTable\'.'
1826 . ' It has been migrated from TCA "'
1827 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'' . $wizardName . '\']'
1828 . '" to "'
1829 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'renderType\'] = \'textTable\'".';
1830 }
1831 }
1832 }
1833 if (empty($fieldConfig['config']['wizards'])) {
1834 unset($fieldConfig['config']['wizards']);
1835 }
1836 if (isset($tableDefinition['types']) && is_array($tableDefinition['types'])) {
1837 foreach ($tableDefinition['types'] as $typeName => &$typeArray) {
1838 if (isset($typeArray['columnsOverrides']) && is_array($typeArray['columnsOverrides'])) {
1839 if (isset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1840 && is_array($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1841 ) {
1842 foreach ($typeArray['columnsOverrides'][$fieldName]['config']['wizards'] as $wizardName => $wizard) {
1843 if (isset($wizard['type'])
1844 && $wizard['type'] === 'script'
1845 && isset($wizard['module']['name'])
1846 && $wizard['module']['name'] === 'wizard_table'
1847 && !isset($typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['tableWizard'])
1848 && !isset($typeArray['columnsOverrides'][$fieldName]['config']['renderType'])
1849 ) {
1850 $typeArray['columnsOverrides'][$fieldName]['config']['renderType'] = 'textTable';
1851 if (isset($wizard['title'])) {
1852 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['tableWizard']['options']['title']
1853 = $wizard['title'];
1854 }
1855 if (isset($wizard['params']['xmlOutput']) && (int)$wizard['params']['xmlOutput'] !== 0) {
1856 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['tableWizard']['options']['xmlOutput']
1857 = (int)$wizard['params']['xmlOutput'];
1858 }
1859 if (isset($wizard['params']['numNewRows'])) {
1860 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['tableWizard']['options']['numNewRows']
1861 = $wizard['params']['numNewRows'];
1862 }
1863 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'][$wizardName]);
1864 $this->messages[] = 'The table wizard in columnsOverrides using \'type\' = \'script\' has been migrated to a \'renderType\' = \'textTable\'.'
1865 . ' It has been migrated from TCA "'
1866 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\']'
1867 . '[\'wizards\'][\'' . $wizardName . '\']" to "'
1868 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\'][\'renderType\'] = \'textTable\'".';
1869 }
1870 }
1871 if (empty($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])) {
1872 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards']);
1873 }
1874 }
1875 }
1876 }
1877 }
1878 }
1879 }
1880 }
1881 }
1882
1883 return $tca;
1884 }
1885
1886 /**
1887 * Migrate "wizard_rte" wizards to rtehtmlarea fieldControl
1888 *
1889 * @param array $tca
1890 * @return array
1891 */
1892 protected function migrateFullScreenRichtextToFieldControl(array $tca): array
1893 {
1894 foreach ($tca as $table => &$tableDefinition) {
1895 if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
1896 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
1897 if ($fieldConfig['config']['type'] === 'text') {
1898 if (isset($fieldConfig['config']['wizards'])
1899 && is_array($fieldConfig['config']['wizards'])
1900 ) {
1901 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
1902 if (isset($wizardConfig['type'])
1903 && $wizardConfig['type'] === 'script'
1904 && isset($wizardConfig['module']['name'])
1905 && $wizardConfig['module']['name'] === 'wizard_rte'
1906 && !isset($fieldConfig['config']['fieldControl']['fullScreenRichtext'])
1907 && isset($fieldConfig['config']['enableRichtext'])
1908 && (bool)$fieldConfig['config']['enableRichtext'] === true
1909 ) {
1910 // Field is configured for richtext, so enable the full screen wizard
1911 $fieldConfig['config']['fieldControl']['fullScreenRichtext']['disabled'] = false;
1912 if (isset($wizardConfig['title'])) {
1913 $fieldConfig['config']['fieldControl']['fullScreenRichtext']['options']['title'] = $wizardConfig['title'];
1914 }
1915 unset($fieldConfig['config']['wizards'][$wizardName]);
1916 $this->messages[] = 'The RTE fullscreen wizard in TCA has been migrated to a \'fieldControl\' = \'fullScreenRichtext\'.'
1917 . ' It has been migrated from TCA "'
1918 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'' . $wizardName . '\']'
1919 . '" to "'
1920 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'fieldControl\']=\'fullScreenRichtext\'".';
1921 } elseif (isset($wizardConfig['type'])
1922 && $wizardConfig['type'] === 'script'
1923 && isset($wizardConfig['module']['name'])
1924 && $wizardConfig['module']['name'] === 'wizard_rte'
1925 && !isset($fieldConfig['config']['fieldControl']['fullScreenRichtext'])
1926 && (!isset($fieldConfig['config']['enableRichtext'])
1927 || isset($fieldConfig['config']['enableRichtext']) && (bool)$fieldConfig['config']['enableRichtext'] === false
1928 )
1929 ) {
1930 // Wizard is given, but field is not configured for richtext
1931 // Find types that enableRichtext and enable full screen for those types
1932 if (isset($tableDefinition['types']) && is_array($tableDefinition['types'])) {
1933 foreach ($tableDefinition['types'] as $typeName => &$typeArray) {
1934 if (isset($typeArray['columnsOverrides']) && is_array($typeArray['columnsOverrides'])) {
1935 if (isset($typeArray['columnsOverrides'][$fieldName]['config']['enableRichtext'])
1936 && (bool)$typeArray['columnsOverrides'][$fieldName]['config']['enableRichtext'] === true
1937 ) {
1938 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['fullScreenRichtext']['disabled'] = false;
1939 if (isset($wizardConfig['title'])) {
1940 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['fullScreenRichtext']['options']['title']
1941 = $wizardConfig['title'];
1942 }
1943 $this->messages[] = 'The RTE fullscreen wizard in TCA has been migrated to a \'fieldControl\' = \'fullScreenRichtext\'.'
1944 . ' It has been migrated from TCA "'
1945 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'' . $wizardName . '\']'
1946 . '" to "'
1947 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\'][\'fieldControl\']=\'fullScreenRichtext\'';
1948 }
1949 }
1950 }
1951 }
1952 unset($fieldConfig['config']['wizards'][$wizardName]);
1953 }
1954 }
1955 }
1956 if (empty($fieldConfig['config']['wizards'])) {
1957 unset($fieldConfig['config']['wizards']);
1958 }
1959 if (isset($tableDefinition['types']) && is_array($tableDefinition['types'])) {
1960 foreach ($tableDefinition['types'] as $typeName => &$typeArray) {
1961 if (isset($typeArray['columnsOverrides']) && is_array($typeArray['columnsOverrides'])) {
1962 if (isset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1963 && is_array($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
1964 ) {
1965 foreach ($typeArray['columnsOverrides'][$fieldName]['config']['wizards'] as $wizardName => $wizard) {
1966 if (isset($wizard['type'])
1967 && $wizard['type'] === 'script'
1968 && isset($wizard['module']['name'])
1969 && $wizard['module']['name'] === 'wizard_rte'
1970 && !isset($typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['fullScreenRichtext'])
1971 ) {
1972 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['fullScreenRichtext']['disabled'] = false;
1973 if (isset($wizard['title'])) {
1974 $typeArray['columnsOverrides'][$fieldName]['config']['fieldControl']['fullScreenRichtext']['options']['title']
1975 = $wizard['title'];
1976 }
1977 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'][$wizardName]);
1978 $this->messages[] = 'The RTE fullscreen wizard in columnsOverrides using \'type\' = \'script\' has been migrated to a \'fieldControl\' = \'fullScreenRichtext\'.'
1979 . ' It has been migrated from TCA "'
1980 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\']'
1981 . '[\'wizards\'][\'' . $wizardName . '\']" to "'
1982 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\'][\'fieldControl\']=\'fullScreenRichtext\'".';
1983 }
1984 }
1985 if (empty($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])) {
1986 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards']);
1987 }
1988 }
1989 }
1990 }
1991 }
1992 }
1993 }
1994 }
1995 }
1996
1997 return $tca;
1998 }
1999
2000 /**
2001 * Migrate the "suggest" wizard in type=group to "hideSuggest" and "suggestOptions"
2002 *
2003 * @param array $tca Given TCA
2004 * @return array Modified TCA
2005 */
2006 protected function migrateSuggestWizardTypeGroup(array $tca): array
2007 {
2008 foreach ($tca as $table => &$tableDefinition) {
2009 if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
2010 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
2011 if ($fieldConfig['config']['type'] === 'group'
2012 && isset($fieldConfig['config']['internal_type'])
2013 && $fieldConfig['config']['internal_type'] === 'db'
2014 ) {
2015 if (isset($fieldConfig['config']['hideSuggest'])) {
2016 continue;
2017 }
2018 if (isset($fieldConfig['config']['wizards']) && is_array($fieldConfig['config']['wizards'])) {
2019 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
2020 if (isset($wizardConfig['type']) && $wizardConfig['type'] === 'suggest') {
2021 unset($wizardConfig['type']);
2022 if (!empty($wizardConfig)) {
2023 $fieldConfig['config']['suggestOptions'] = $wizardConfig;
2024 $this->messages[] = 'The suggest wizard options in TCA '
2025 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'' . $wizardName . '\']'
2026 . ' have been migrated to '
2027 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'suggestOptions\'].';
2028 } else {
2029 $this->messages[] = 'The suggest wizard in TCA '
2030 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'wizards\'][\'' . $wizardName . '\']'
2031 . ' is enabled by default and has been removed.';
2032 }
2033 unset($fieldConfig['config']['wizards'][$wizardName]);
2034 }
2035 }
2036 }
2037 if (empty($fieldConfig['config']['wizards'])) {
2038 unset($fieldConfig['config']['wizards']);
2039 }
2040 if (isset($tableDefinition['types']) && is_array($tableDefinition['types'])) {
2041 foreach ($tableDefinition['types'] as $typeName => &$typeArray) {
2042 if (isset($typeArray['columnsOverrides']) && is_array($typeArray['columnsOverrides'])) {
2043 if (isset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
2044 && is_array($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])
2045 ) {
2046 foreach ($typeArray['columnsOverrides'][$fieldName]['config']['wizards'] as $wizardName => $wizard) {
2047 if (isset($wizard['type']) && $wizard['type'] === 'suggest'
2048 ) {
2049 unset($wizard['type']);
2050 $fieldConfig['config']['hideSuggest'] = true;
2051 $typeArray['columnsOverrides'][$fieldName]['config']['hideSuggest'] = false;
2052 if (!empty($wizard)) {
2053 $typeArray['columnsOverrides'][$fieldName]['config']['suggestOptions'] = $wizard;
2054 $this->messages[] = 'The suggest wizard options in columnsOverrides have been migrated'
2055 . ' from TCA ' . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\']'
2056 . '[\'wizards\'][\'' . $wizardName . '\'] to \'suggestOptions\' in '
2057 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\']';
2058 } else {
2059 $this->messages[] = 'The suggest wizard in columnsOverrides has been migrated'
2060 . ' from TCA ' . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\']'
2061 . '[\'wizards\'][\'' . $wizardName . '\'] to \'hideSuggest\' => false in '
2062 . $table . '[\'types\'][\'' . $typeName . '\'][\'columnsOverrides\'][\'config\'][\'hideSuggest\']';
2063 }
2064 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards'][$wizardName]);
2065 }
2066 }
2067 if (empty($typeArray['columnsOverrides'][$fieldName]['config']['wizards'])) {
2068 unset($typeArray['columnsOverrides'][$fieldName]['config']['wizards']);
2069 }
2070 }
2071 }
2072 }
2073 }
2074 }
2075 }
2076 }
2077 }
2078
2079 return $tca;
2080 }
2081
2082 /**
2083 * Migrate some detail options of type=group config
2084 *
2085 * @param array $tca Given TCA
2086 * @return array Modified TCA
2087 */
2088 protected function migrateOptionsOfTypeGroup(array $tca): array
2089 {
2090 foreach ($tca as $table => &$tableDefinition) {
2091 if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
2092 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
2093 if ($fieldConfig['config']['type'] === 'group') {
2094 if (isset($fieldConfig['config']['selectedListStyle'])) {
2095 unset($fieldConfig['config']['selectedListStyle']);
2096 $this->messages[] = 'The \'type\' = \'group\' option \'selectedListStyle\' is obsolete and has been dropped'
2097 . ' from TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']';
2098 }
2099 if (isset($fieldConfig['config']['show_thumbs'])) {
2100 if ((bool)$fieldConfig['config']['show_thumbs'] === false && $fieldConfig['config']['internal_type'] === 'db') {
2101 $fieldConfig['config']['fieldWizard']['recordsOverview']['disabled'] = true;
2102 $this->messages[] = 'The \'type\' = \'group\' option \'show_thumbs\' = false is obsolete'
2103 . ' from TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']'
2104 . ' and has been migrated to'
2105 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'fieldWizard\'][\'recordsOverview\'][\'disabled\'] = true';
2106 } elseif ((bool)$fieldConfig['config']['show_thumbs'] === false && $fieldConfig['config']['internal_type'] === 'file') {
2107 $fieldConfig['config']['fieldWizard']['fileThumbnails']['disabled'] = true;
2108 $this->messages[] = 'The \'type\' = \'group\' option \'show_thumbs\' = false is obsolete'
2109 . ' from TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']'
2110 . ' and has been migrated to'
2111 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'fieldWizard\'][\'fileThumbnails\'][\'disabled\'] = true';
2112 } else {
2113 $this->messages[] = 'The \'type\' = \'group\' option \'show_thumbs\' is obsolete and has been dropped'
2114 . ' from TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']';
2115 }
2116 unset($fieldConfig['config']['show_thumbs']);
2117 }
2118 if (isset($fieldConfig['config']['disable_controls']) && is_string($fieldConfig['config']['disable_controls'])) {
2119 $controls = GeneralUtility::trimExplode(',', $fieldConfig['config']['disable_controls'], true);
2120 foreach ($controls as $control) {
2121 if ($control === 'browser') {
2122 $fieldConfig['config']['fieldControl']['elementBrowser']['disabled'] = true;
2123 $this->messages[] = 'The \'type\' = \'group\' option \'disable_controls\' = \'browser\''
2124 . ' from TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']'
2125 . ' and has been migrated to'
2126 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'fieldControl\'][\'elementBrowser\'][\'disabled\'] = true';
2127 } elseif ($control === 'delete') {
2128 $this->messages[] = 'The \'type\' = \'group\' option \'disable_controls\' = \'delete\''
2129 . ' from TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']'
2130 . ' and has been migrated to'
2131 . $table . '[\'columns\'][\' . $fieldName . \'][\'config\'][\'hideDeleteIcon\'] = true';
2132 $fieldConfig['config']['hideDeleteIcon'] = true;
2133 } elseif ($control === 'allowedTables') {
2134 $fieldConfig['config']['fieldWizard']['tableList']['disabled'] = true;
2135 $this->messages[] = 'The \'type\' = \'group\' option \'disable_controls\' = \'allowedTables\''
2136 . ' from TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']'
2137 . ' and has been migrated to'
2138 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'fieldWizard\'][\'tableList\'][\'disabled\'] = true';
2139 } elseif ($control === 'upload') {
2140 $fieldConfig['config']['fieldWizard']['fileUpload']['disabled'] = true;
2141 $this->messages[] = 'The \'type\' = \'group\' option \'disable_controls\' = \'upload\''
2142 . ' from TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']'
2143 . ' and has been migrated to'
2144 . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'fieldWizard\'][\'fileUpload\'][\'disabled\'] = true';
2145 }
2146 }
2147 unset($fieldConfig['config']['disable_controls']);
2148 }
2149 }
2150 }
2151 }
2152 }
2153
2154 return $tca;
2155 }
2156
2157 /**
2158 * Migrate "showIconTable" to a field wizard, drop selicon_cols
2159 *
2160 * @param array $tca Given TCA
2161 * @return array Modified TCA
2162 */
2163 protected function migrateSelectShowIconTable(array $tca): array
2164 {
2165 foreach ($tca as $table => &$tableDefinition) {
2166 if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
2167 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
2168 if ($fieldConfig['config']['type'] === 'select'
2169 && isset($fieldConfig['config']['renderType'])
2170 && $fieldConfig['config']['renderType'] === 'selectSingle'
2171 ) {
2172 if (isset($fieldConfig['config']['showIconTable'])) {
2173 if ((bool)$fieldConfig['config']['showIconTable'] === true) {
2174 $fieldConfig['config']['fieldWizard']['selectIcons']['disabled'] = false;
2175 $this->messages[] = 'The \'type\' = \'select\' option \'showIconTable\' = true is obsolete'
2176 . ' from TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']'
2177 . ' and has been migrated to'
2178 . ' [\'config\'][\'fieldWizard\'][\'selectIcons\'][\'disabled\'] = false';
2179 } else {
2180 $this->messages[] = 'The \'type\' = \'group\' option \'showIconTable\' = false is obsolete'
2181 . ' from TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']'
2182 . ' and has been removed.';
2183 }
2184 unset($fieldConfig['config']['showIconTable']);
2185 }
2186 if (isset($fieldConfig['config']['selicon_cols'])) {
2187 unset($fieldConfig['config']['selicon_cols']);
2188 $this->messages[] = 'The \'type\' = \'group\' option \'selicon_cols\' = false is obsolete'
2189 . ' from TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']'
2190 . ' and has been removed.';
2191 }
2192 }
2193 }
2194 }
2195 }
2196
2197 return $tca;
2198 }
2199
2200 /**
2201 * Migrate imageManipulation "ratio" config to new "cropVariant" config
2202 *
2203 * @param array $tca
2204 * @return array
2205 */
2206 protected function migrateImageManipulationConfig(array $tca): array
2207 {
2208 foreach ($tca as $table => &$tableDefinition) {
2209 if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
2210 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
2211 if ($fieldConfig['config']['type'] === 'imageManipulation') {
2212 if (isset($fieldConfig['config']['enableZoom'])) {
2213 unset($fieldConfig['config']['enableZoom']);
2214 $this->messages[] = sprintf(
2215 'The config option "enableZoom" has been removed from TCA type "imageManipulation" in table "%s" and field "%s"',
2216 $table,
2217 $fieldName
2218 );
2219 }
2220 if (isset($fieldConfig['config']['ratios'])) {
2221 $legacyRatios = $fieldConfig['config']['ratios'];
2222 unset($fieldConfig['config']['ratios']);
2223 if (isset($fieldConfig['config']['cropVariants'])) {</