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