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