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