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