[TASK] Remove leftover page/branch versioning code
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Migrations / TcaMigration.php
1 <?php
2 namespace TYPO3\CMS\Core\Migrations;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Utility\GeneralUtility;
18 use TYPO3\CMS\Core\Utility\StringUtility;
19
20 /**
21 * Migrate TCA from old to new syntax. Used in bootstrap and Flex Form Data Structures.
22 *
23 * @internal Class and API may change any time.
24 */
25 class TcaMigration
26 {
27 /**
28 * Accumulate migration messages
29 *
30 * @var array
31 */
32 protected $messages = [];
33
34 /**
35 * Migrate old TCA to new TCA.
36 *
37 * See unit tests for details.
38 *
39 * @param array $tca
40 * @return array
41 */
42 public function migrate(array $tca)
43 {
44 $tca = $this->migrateT3editorWizardToRenderTypeT3editorIfNotEnabledByTypeConfig($tca);
45 $tca = $this->migrateSpecialConfigurationAndRemoveShowItemStylePointerConfig($tca);
46 $tca = $this->migrateT3editorWizardWithEnabledByTypeConfigToColumnsOverrides($tca);
47 $tca = $this->migrateShowItemAdditionalPaletteToOwnPalette($tca);
48 $tca = $this->migrateIconsForFormFieldWizardsToNewLocation($tca);
49 $tca = $this->migrateExtAndSysextPathToEXTPath($tca);
50 $tca = $this->migrateIconsInOptionTags($tca);
51 $tca = $this->migrateIconfileRelativePathOrFilenameOnlyToExtReference($tca);
52 $tca = $this->migrateSelectFieldRenderType($tca);
53 $tca = $this->migrateSelectFieldIconTable($tca);
54 $tca = $this->migrateElementBrowserWizardToLinkHandler($tca);
55 $tca = $this->migrateDefaultExtrasRteTransFormOptions($tca);
56 $tca = $this->migrateColorPickerWizardToRenderType($tca);
57 $tca = $this->migrateSelectTreeOptions($tca);
58 $tca = $this->migrateTSconfigSoftReferences($tca);
59 $tca = $this->migrateShowIfRteOption($tca);
60 $tca = $this->migrateWorkspacesOptions($tca);
61 // @todo: if showitem/defaultExtras wizards[xy] is migrated to columnsOverrides here, enableByTypeConfig could be dropped
62 return $tca;
63 }
64
65 /**
66 * Get messages of migrated fields. Can be used for deprecation messages after migrate() was called.
67 *
68 * @return array Migration messages
69 */
70 public function getMessages()
71 {
72 return $this->messages;
73 }
74
75 /**
76 * Migrate type=text field with t3editor wizard to renderType=t3editor without this wizard
77 *
78 * @param array $tca Incoming TCA
79 * @return array Migrated TCA
80 */
81 protected function migrateT3editorWizardToRenderTypeT3editorIfNotEnabledByTypeConfig(array $tca)
82 {
83 $newTca = $tca;
84 foreach ($tca as $table => $tableDefinition) {
85 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
86 continue;
87 }
88 foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
89 if (
90 !empty($fieldConfig['config']['type']) // type is set
91 && trim($fieldConfig['config']['type']) === 'text' // to "text"
92 && isset($fieldConfig['config']['wizards'])
93 && is_array($fieldConfig['config']['wizards']) // and there are wizards
94 ) {
95 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
96 if (
97 !empty($wizardConfig['userFunc']) // a userFunc is defined
98 && trim($wizardConfig['userFunc']) === 'TYPO3\\CMS\\T3editor\\FormWizard->main' // and set to FormWizard
99 && (
100 !isset($wizardConfig['enableByTypeConfig']) // and enableByTypeConfig is not set
101 || (isset($wizardConfig['enableByTypeConfig']) && !$wizardConfig['enableByTypeConfig']) // or set, but not enabled
102 )
103 ) {
104 // Set renderType from text to t3editor
105 $newTca[$table]['columns'][$fieldName]['config']['renderType'] = 't3editor';
106 // Unset this wizard definition
107 unset($newTca[$table]['columns'][$fieldName]['config']['wizards'][$wizardName]);
108 // Move format parameter
109 if (!empty($wizardConfig['params']['format'])) {
110 $newTca[$table]['columns'][$fieldName]['config']['format'] = $wizardConfig['params']['format'];
111 }
112 $this->messages[] = 'Migrated t3editor wizard in TCA of table "' . $table . '" field "' . $fieldName . '" to a renderType definition.';
113 }
114 }
115 // If no wizard is left after migration, unset the whole sub array
116 if (empty($newTca[$table]['columns'][$fieldName]['config']['wizards'])) {
117 unset($newTca[$table]['columns'][$fieldName]['config']['wizards']);
118 }
119 }
120 }
121 }
122 return $newTca;
123 }
124
125 /**
126 * Remove "style pointer", the 5th parameter from "types" "showitem" configuration.
127 * Move "specConf", 4th parameter from "tyes" "showitem" to "types" "columnsOverrides.
128 *
129 * @param array $tca Incoming TCA
130 * @return array Modified TCA
131 */
132 protected function migrateSpecialConfigurationAndRemoveShowItemStylePointerConfig(array $tca)
133 {
134 $newTca = $tca;
135 foreach ($tca as $table => $tableDefinition) {
136 if (!isset($tableDefinition['types']) || !is_array($tableDefinition['types'])) {
137 continue;
138 }
139 foreach ($tableDefinition['types'] as $typeName => $typeArray) {
140 if (!isset($typeArray['showitem']) || !is_string($typeArray['showitem']) || strpos($typeArray['showitem'], ';') === false) {
141 // Continue directly if no semicolon is found
142 continue;
143 }
144 $itemList = GeneralUtility::trimExplode(',', $typeArray['showitem'], true);
145 $newFieldStrings = [];
146 foreach ($itemList as $fieldString) {
147 $fieldString = rtrim($fieldString, ';');
148 // Unpack the field definition, migrate and remove as much as possible
149 // Keep empty parameters in trimExplode here (third parameter FALSE), so position is not changed
150 $fieldArray = GeneralUtility::trimExplode(';', $fieldString);
151 $fieldArray = [
152 'fieldName' => isset($fieldArray[0]) ? $fieldArray[0] : '',
153 'fieldLabel' => isset($fieldArray[1]) ? $fieldArray[1] : null,
154 'paletteName' => isset($fieldArray[2]) ? $fieldArray[2] : null,
155 'fieldExtra' => isset($fieldArray[3]) ? $fieldArray[3] : null,
156 ];
157 $fieldName = $fieldArray['fieldName'];
158 if (!empty($fieldArray['fieldExtra'])) {
159 // Move fieldExtra "specConf" to columnsOverrides "defaultExtras"
160 if (!isset($newTca[$table]['types'][$typeName]['columnsOverrides'])) {
161 $newTca[$table]['types'][$typeName]['columnsOverrides'] = [];
162 }
163 if (!isset($newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldArray['fieldName']])) {
164 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldArray['fieldName']] = [];
165 }
166 // Merge with given defaultExtras from columns.
167 // They will be the first part of the string, so if "specConf" from types changes the same settings,
168 // those will override settings from defaultExtras of columns
169 $newDefaultExtras = [];
170 if (!empty($tca[$table]['columns'][$fieldArray['fieldName']]['defaultExtras'])) {
171 $newDefaultExtras[] = $tca[$table]['columns'][$fieldArray['fieldName']]['defaultExtras'];
172 }
173 $newDefaultExtras[] = $fieldArray['fieldExtra'];
174 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldArray['fieldName']]['defaultExtras'] = implode(':', $newDefaultExtras);
175 }
176 unset($fieldArray['fieldExtra']);
177 if (count($fieldArray) === 3 && empty($fieldArray['paletteName'])) {
178 unset($fieldArray['paletteName']);
179 }
180 if (count($fieldArray) === 2 && empty($fieldArray['fieldLabel'])) {
181 unset($fieldArray['fieldLabel']);
182 }
183 if (count($fieldArray) === 1 && empty($fieldArray['fieldName'])) {
184 // The field may vanish if nothing is left
185 unset($fieldArray['fieldName']);
186 }
187 $newFieldString = implode(';', $fieldArray);
188 if ($newFieldString !== $fieldString) {
189 $this->messages[] = 'Changed showitem string of TCA table "' . $table . '" type "' . $typeName . '" due to changed field "' . $fieldName . '".';
190 }
191 if (!empty($newFieldString)) {
192 $newFieldStrings[] = $newFieldString;
193 }
194 }
195 $newTca[$table]['types'][$typeName]['showitem'] = implode(',', $newFieldStrings);
196 }
197 }
198 return $newTca;
199 }
200
201 /**
202 * Migrate type=text field with t3editor wizard that is "enableByTypeConfig" to columnsOverrides
203 * with renderType=t3editor
204 *
205 * @param array $tca Incoming TCA
206 * @return array Migrated TCA
207 */
208 protected function migrateT3editorWizardWithEnabledByTypeConfigToColumnsOverrides(array $tca)
209 {
210 $newTca = $tca;
211 foreach ($tca as $table => $tableDefinition) {
212 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
213 continue;
214 }
215 foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
216 if (
217 !empty($fieldConfig['config']['type']) // type is set
218 && trim($fieldConfig['config']['type']) === 'text' // to "text"
219 && isset($fieldConfig['config']['wizards'])
220 && is_array($fieldConfig['config']['wizards']) // and there are wizards
221 ) {
222 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
223 if (
224 !empty($wizardConfig['userFunc']) // a userFunc is defined
225 && trim($wizardConfig['userFunc']) === 'TYPO3\CMS\T3editor\FormWizard->main' // and set to FormWizard
226 && !empty($wizardConfig['enableByTypeConfig']) // and enableByTypeConfig is enabled
227 ) {
228 // Remove this wizard
229 unset($newTca[$table]['columns'][$fieldName]['config']['wizards'][$wizardName]);
230 // Find configured types that use this wizard
231 if (!isset($tableDefinition['types']) || !is_array($tableDefinition['types'])) {
232 // No type definition at all ... continue directly
233 continue;
234 }
235 foreach ($tableDefinition['types'] as $typeName => $typeArray) {
236 if (
237 empty($typeArray['columnsOverrides'][$fieldName]['defaultExtras'])
238 || strpos($typeArray['columnsOverrides'][$fieldName]['defaultExtras'], $wizardName) === false
239 ) {
240 // Continue directly if this wizard is not enabled for given type
241 continue;
242 }
243 $defaultExtras = $typeArray['columnsOverrides'][$fieldName]['defaultExtras'];
244 $defaultExtrasArray = GeneralUtility::trimExplode(':', $defaultExtras, true);
245 $newDefaultExtrasArray = [];
246 foreach ($defaultExtrasArray as $fieldExtraField) {
247 // There might be multiple enabled wizards separated by | ... split them
248 if (substr($fieldExtraField, 0, 8) === 'wizards[') {
249 $enabledWizards = substr($fieldExtraField, 8, strlen($fieldExtraField) - 8); // Cut off "wizards[
250 $enabledWizards = substr($enabledWizards, 0, strlen($enabledWizards) - 1);
251 $enabledWizardsArray = GeneralUtility::trimExplode('|', $enabledWizards, true);
252 $newEnabledWizardsArray = [];
253 foreach ($enabledWizardsArray as $enabledWizardName) {
254 if ($enabledWizardName === $wizardName) {
255 // Found a columnsOverrides configuration that has this wizard enabled
256 // Force renderType = t3editor
257 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldName]['config']['renderType'] = 't3editor';
258 // Transfer format option if given
259 if (!empty($wizardConfig['params']['format'])) {
260 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldName]['config']['format'] = $wizardConfig['params']['format'];
261 }
262 $this->messages[] = 'Migrated t3editor wizard in TCA of table "' . $table . '" field "' . $fieldName
263 . '" to a renderType definition with columnsOverrides in type "' . $typeName . '".';
264 } else {
265 // Some other enabled wizard
266 $newEnabledWizardsArray[] = $enabledWizardName;
267 }
268 }
269 if (!empty($newEnabledWizardsArray)) {
270 $newDefaultExtrasArray[] = 'wizards[' . implode('|', $newEnabledWizardsArray) . ']';
271 }
272 } else {
273 $newDefaultExtrasArray[] = $fieldExtraField;
274 }
275 }
276 if (!empty($newDefaultExtrasArray)) {
277 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldName]['defaultExtras'] = implode(':', $newDefaultExtrasArray);
278 } else {
279 unset($newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldName]['defaultExtras']);
280 }
281 }
282 }
283 }
284 // If no wizard is left after migration, unset the whole sub array
285 if (empty($newTca[$table]['columns'][$fieldName]['config']['wizards'])) {
286 unset($newTca[$table]['columns'][$fieldName]['config']['wizards']);
287 }
288 }
289 }
290 }
291 return $newTca;
292 }
293
294 /**
295 * Migrate types showitem 'aField;aLabel;aPalette' to 'afield;aLabel, --palette--;;aPalette'
296 *
297 * Old showitem can have a syntax like:
298 * fieldName;aLabel;aPalette
299 * This way, the palette with name "aPalette" is rendered after fieldName.
300 * The migration parses this to a syntax like:
301 * fieldName;aLabel, --palette--;;paletteName
302 *
303 * @param array $tca Incoming TCA
304 * @return array Migrated TCA
305 */
306 protected function migrateShowItemAdditionalPaletteToOwnPalette(array $tca)
307 {
308 $newTca = $tca;
309 foreach ($tca as $table => $tableDefinition) {
310 if (!isset($tableDefinition['types']) || !is_array($tableDefinition['types'])) {
311 continue;
312 }
313 foreach ($tableDefinition['types'] as $typeName => $typeArray) {
314 if (
315 !isset($typeArray['showitem'])
316 || !is_string($typeArray['showitem'])
317 || strpos($typeArray['showitem'], ';') === false // no field parameters
318 ) {
319 continue;
320 }
321 $itemList = GeneralUtility::trimExplode(',', $typeArray['showitem'], true);
322 $newFieldStrings = [];
323 foreach ($itemList as $fieldString) {
324 $fieldArray = GeneralUtility::trimExplode(';', $fieldString);
325 $fieldArray = [
326 'fieldName' => isset($fieldArray[0]) ? $fieldArray[0] : '',
327 'fieldLabel' => isset($fieldArray[1]) ? $fieldArray[1] : null,
328 'paletteName' => isset($fieldArray[2]) ? $fieldArray[2] : null,
329 ];
330 if ($fieldArray['fieldName'] !== '--palette--' && $fieldArray['paletteName'] !== null) {
331 if ($fieldArray['fieldLabel']) {
332 $fieldString = $fieldArray['fieldName'] . ';' . $fieldArray['fieldLabel'];
333 } else {
334 $fieldString = $fieldArray['fieldName'];
335 }
336 $paletteString = '--palette--;;' . $fieldArray['paletteName'];
337 $this->messages[] = 'Migrated TCA table "' . $table . '" showitem field of type "' . $typeName . '": Moved additional palette'
338 . ' with name "' . $fieldArray['paletteName'] . '" as 3rd argument of field "' . $fieldArray['fieldName']
339 . '" to an own palette. The result of this part is: "' . $fieldString . ', ' . $paletteString . '"';
340 $newFieldStrings[] = $fieldString;
341 $newFieldStrings[] = $paletteString;
342 } else {
343 $newFieldStrings[] = $fieldString;
344 }
345 }
346 $newTca[$table]['types'][$typeName]['showitem'] = implode(',', $newFieldStrings);
347 }
348 }
349 return $newTca;
350 }
351
352 /**
353 * Migrate core icons for form field wizard to new location
354 *
355 * @param array $tca Incoming TCA
356 * @return array Migrated TCA
357 */
358 protected function migrateIconsForFormFieldWizardsToNewLocation(array $tca)
359 {
360 $newTca = $tca;
361
362 $newFileLocations = [
363 'add.gif' => 'actions-add',
364 'link_popup.gif' => 'actions-wizard-link',
365 'wizard_rte2.gif' => 'actions-wizard-rte',
366 'wizard_table.gif' => 'content-table',
367 'edit2.gif' => 'actions-open',
368 'list.gif' => 'actions-system-list-open',
369 'wizard_forms.gif' => 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_forms.gif',
370 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_add.gif' => 'actions-add',
371 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_table.gif' => 'content-table',
372 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_edit.gif' => 'actions-open',
373 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_list.gif' => 'actions-system-list-open',
374 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_link.gif' => 'actions-wizard-link',
375 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_rte.gif' => 'actions-wizard-rte'
376 ];
377 $oldFileNames = array_keys($newFileLocations);
378
379 foreach ($tca as $table => $tableDefinition) {
380 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
381 continue;
382 }
383 foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
384 if (
385 isset($fieldConfig['config']['wizards'])
386 && is_array($fieldConfig['config']['wizards']) // and there are wizards
387 ) {
388 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
389 if (!is_array($wizardConfig)) {
390 continue;
391 }
392
393 foreach ($wizardConfig as $option => $value) {
394 if ($option === 'icon' && in_array($value, $oldFileNames, true)) {
395 $newTca[$table]['columns'][$fieldName]['config']['wizards'][$wizardName]['icon'] = $newFileLocations[$value];
396 $this->messages[] = 'Migrated icon path of wizard "' . $wizardName . '" in field "' . $fieldName . '" from TCA table "' . $table . '". New path is: ' . $newFileLocations[$value];
397 }
398 }
399 }
400 }
401 }
402 }
403
404 return $newTca;
405 }
406
407 /**
408 * Migrate file reference which starts with ext/ or sysext/ to EXT:
409 *
410 * @param array $tca Incoming TCA
411 * @return array Migrated TCA
412 */
413 protected function migrateExtAndSysextPathToEXTPath(array $tca)
414 {
415 foreach ($tca as $table => &$tableDefinition) {
416 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
417 continue;
418 }
419 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
420 if (
421 !empty($fieldConfig['config']['type']) // type is set
422 && trim($fieldConfig['config']['type']) === 'select' // to "select"
423 && isset($fieldConfig['config']['items'])
424 && is_array($fieldConfig['config']['items']) // and there are items
425 ) {
426 foreach ($fieldConfig['config']['items'] as &$itemConfig) {
427 // more then two values? then the third entry is the image path
428 if (!empty($itemConfig[2])) {
429 $tcaPath = implode('.', [$table, 'columns', $fieldName, 'config', 'items']);
430 $pathParts = GeneralUtility::trimExplode('/', $itemConfig[2]);
431 // remove first element (ext or sysext)
432 array_shift($pathParts);
433 $path = implode('/', $pathParts);
434 // If the path starts with ext/ or sysext/ migrate it
435 if (
436 StringUtility::beginsWith($itemConfig[2], 'ext/')
437 || StringUtility::beginsWith($itemConfig[2], 'sysext/')
438 ) {
439 $this->messages[] = '[' . $tcaPath . '] ext/ or sysext/ within the path (' . $path . ') in items array is deprecated, use EXT: reference';
440 $itemConfig[2] = 'EXT:' . $path;
441 } elseif (StringUtility::beginsWith($itemConfig[2], 'i/')) {
442 $this->messages[] = '[' . $tcaPath . '] i/ within the path (' . $path . ') in items array is deprecated, use EXT: reference';
443 $itemConfig[2] = 'EXT:t3skin/icons/gfx/' . $itemConfig[2];
444 }
445 }
446 }
447 }
448 }
449 }
450 return $tca;
451 }
452
453 /**
454 * Migrate "iconsInOptionTags" for "select" TCA fields
455 *
456 * @param array $tca Incoming TCA
457 * @return array Migrated TCA
458 */
459 protected function migrateIconsInOptionTags(array $tca)
460 {
461 $newTca = $tca;
462
463 foreach ($newTca as $table => &$tableDefinition) {
464 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
465 continue;
466 }
467 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
468 if (isset($fieldConfig['config']['iconsInOptionTags'])) {
469 unset($fieldConfig['config']['iconsInOptionTags']);
470 $this->messages[] = 'Configuration option "iconsInOptionTags" was removed from field "' . $fieldName . '" in TCA table "' . $table . '"';
471 }
472 }
473 }
474
475 return $newTca;
476 }
477
478 /**
479 * Migrate "iconfile" references which starts with ../ to EXT: and consisting of filename only to absolute paths in EXT:t3skin
480 *
481 * @param array $tca Incoming TCA
482 * @return array Migrated TCA
483 */
484 protected function migrateIconfileRelativePathOrFilenameOnlyToExtReference(array $tca)
485 {
486 foreach ($tca as $table => &$tableDefinition) {
487 if (!isset($tableDefinition['ctrl']) || !is_array($tableDefinition['ctrl'])) {
488 continue;
489 }
490 if (!isset($tableDefinition['ctrl']['iconfile'])) {
491 continue;
492 }
493 if (StringUtility::beginsWith($tableDefinition['ctrl']['iconfile'], '../typo3conf/ext/')) {
494 $tableDefinition['ctrl']['iconfile'] = str_replace('../typo3conf/ext/', 'EXT:', $tableDefinition['ctrl']['iconfile']);
495 $tcaPath = implode('.', [$table, 'ctrl', 'iconfile']);
496 $this->messages[] = '[' . $tcaPath . '] relative path to ../typo3conf/ext/ is deprecated, use EXT: instead';
497 } elseif (strpos($tableDefinition['ctrl']['iconfile'], '/') === false) {
498 $tableDefinition['ctrl']['iconfile'] = 'EXT:t3skin/icons/gfx/i/' . $tableDefinition['ctrl']['iconfile'];
499 $tcaPath = implode('.', [$table, 'ctrl', 'iconfile']);
500 $this->messages[] = '[' . $tcaPath . '] filename only is deprecated, use EXT: or absolute reference instead';
501 }
502 }
503 return $tca;
504 }
505
506 /**
507 * Migrate "type=select" with "renderMode=[tree|singlebox|checkbox]" to "renderType=[selectTree|selectSingleBox|selectCheckBox]".
508 * This migration also take care of "maxitems" settings and set "renderType=[selectSingle|selectMultipleSideBySide]" if no other
509 * renderType is already set.
510 *
511 * @param array $tca
512 * @return array
513 */
514 public function migrateSelectFieldRenderType(array $tca)
515 {
516 $newTca = $tca;
517
518 foreach ($newTca as $table => &$tableDefinition) {
519 if (empty($tableDefinition['columns'])) {
520 continue;
521 }
522
523 foreach ($tableDefinition['columns'] as $columnName => &$columnDefinition) {
524 // Only handle select fields.
525 if (empty($columnDefinition['config']['type']) || $columnDefinition['config']['type'] !== 'select') {
526 continue;
527 }
528 // Do not handle field where the render type is set.
529 if (!empty($columnDefinition['config']['renderType'])) {
530 continue;
531 }
532
533 $tableColumnInfo = 'table "' . $table . '" and column "' . $columnName . '"';
534 $this->messages[] = 'Using select fields without the "renderType" setting is deprecated in ' . $tableColumnInfo;
535
536 $columnConfig = &$columnDefinition['config'];
537 if (!empty($columnConfig['renderMode'])) {
538 $this->messages[] = 'The "renderMode" setting for select fields is deprecated. Please use "renderType" instead in ' . $tableColumnInfo;
539 switch ($columnConfig['renderMode']) {
540 case 'tree':
541 $columnConfig['renderType'] = 'selectTree';
542 break;
543 case 'singlebox':
544 $columnConfig['renderType'] = 'selectSingleBox';
545 break;
546 case 'checkbox':
547 $columnConfig['renderType'] = 'selectCheckBox';
548 break;
549 default:
550 $this->messages[] = 'The render mode ' . $columnConfig['renderMode'] . ' is invalid for the select field in ' . $tableColumnInfo;
551 }
552 continue;
553 }
554
555 $maxItems = !empty($columnConfig['maxitems']) ? (int)$columnConfig['maxitems'] : 1;
556 if ($maxItems <= 1) {
557 $columnConfig['renderType'] = 'selectSingle';
558 } else {
559 $columnConfig['renderType'] = 'selectMultipleSideBySide';
560 }
561 }
562 }
563
564 return $newTca;
565 }
566
567 /**
568 * Migrate the visibility of the icon table for fields with "renderType=selectSingle"
569 *
570 * @param array $tca
571 * @return array Migrated TCA
572 */
573 public function migrateSelectFieldIconTable(array $tca)
574 {
575 foreach ($tca as $table => &$tableDefinition) {
576 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
577 continue;
578 }
579 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
580 if (empty($fieldConfig['config']['renderType']) || $fieldConfig['config']['renderType'] !== 'selectSingle') {
581 continue;
582 }
583 if (!empty($fieldConfig['config']['selicon_cols'])) {
584 // selicon_cols without showIconTable true does not make sense, so set it to true here if not already defined
585 if (!array_key_exists('showIconTable', $fieldConfig['config'])) {
586 $this->messages[] = 'The "showIconTable" setting is missing for table "' . $table . '" and field "' . $fieldName . '"';
587 $fieldConfig['config']['showIconTable'] = true;
588 }
589 }
590 if (array_key_exists('noIconsBelowSelect', $fieldConfig['config'])) {
591 $this->messages[] = 'The "noIconsBelowSelect" setting for select fields was removed. Please define the setting "showIconTable" for table "' . $table . '" and field "' . $fieldName . '"';
592 if (!$fieldConfig['config']['noIconsBelowSelect']) {
593 // If old setting was explicitly false, enable icon table if not defined yet
594 if (!array_key_exists('showIconTable', $fieldConfig['config'])) {
595 $fieldConfig['config']['showIconTable'] = true;
596 }
597 }
598 unset($fieldConfig['config']['noIconsBelowSelect']);
599 }
600 if (array_key_exists('suppress_icons', $fieldConfig['config'])) {
601 $this->messages[] = 'The "suppress_icons" setting for select fields was removed. Please define the setting "showIconTable" for table "' . $table . '" and field "' . $fieldName . '"';
602 unset($fieldConfig['config']['suppress_icons']);
603 }
604 if (array_key_exists('foreign_table_loadIcons', $fieldConfig['config'])) {
605 $this->messages[] = 'The "foreign_table_loadIcons" setting for select fields was removed. Please define the setting "showIconTable" for table "' . $table . '" and field "' . $fieldName . '"';
606 unset($fieldConfig['config']['foreign_table_loadIcons']);
607 }
608 }
609 }
610 return $tca;
611 }
612
613 /**
614 * Migrate wizard "wizard_element_browser" used in mode "wizard" to use the "wizard_link" instead
615 *
616 * @param array $tca
617 * @return array Migrated TCA
618 */
619 protected function migrateElementBrowserWizardToLinkHandler(array $tca)
620 {
621 foreach ($tca as $table => &$tableDefinition) {
622 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
623 continue;
624 }
625 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
626 if (
627 isset($fieldConfig['config']['wizards']['link']['module']['name']) && $fieldConfig['config']['wizards']['link']['module']['name'] === 'wizard_element_browser'
628 && isset($fieldConfig['config']['wizards']['link']['module']['urlParameters']['mode']) && $fieldConfig['config']['wizards']['link']['module']['urlParameters']['mode'] === 'wizard'
629 ) {
630 $fieldConfig['config']['wizards']['link']['module']['name'] = 'wizard_link';
631 unset($fieldConfig['config']['wizards']['link']['module']['urlParameters']['mode']);
632 if (empty($fieldConfig['config']['wizards']['link']['module']['urlParameters'])) {
633 unset($fieldConfig['config']['wizards']['link']['module']['urlParameters']);
634 }
635 $this->messages[] = 'Reference to "wizard_element_browser" was migrated to new "wizard_link" for field "' . $fieldName . '" in TCA table "' . $table . '"';
636 }
637 }
638 }
639 return $tca;
640 }
641
642 /**
643 * Migrate defaultExtras "richtext:rte_transform[mode=ts_css]" and similar stuff like
644 * "richtext:rte_transform[mode=ts_css]" to "richtext:rte_transform"
645 *
646 * @param array $tca
647 * @return array Migrated TCA
648 */
649 protected function migrateDefaultExtrasRteTransFormOptions(array $tca)
650 {
651 foreach ($tca as $table => &$tableDefinition) {
652 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
653 continue;
654 }
655 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
656 if (isset($fieldConfig['defaultExtras'])) {
657 $oldValue = $fieldConfig['defaultExtras'];
658 $fieldConfig['defaultExtras'] = preg_replace(
659 '/richtext(\[([^\]]*)\])*:rte_transform(\[([^\]]*)\])/',
660 'richtext${1}:rte_transform',
661 $fieldConfig['defaultExtras'],
662 -1,
663 $replacementCount
664 );
665 if ($replacementCount) {
666 $this->messages[] = 'rte_transform options are deprecated. String "' . $oldValue . '" in TCA'
667 . ' ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'defaultExtras\'] was changed to "'
668 . $fieldConfig['defaultExtras'] . '"';
669 }
670 }
671 }
672 }
673
674 foreach ($tca as $table => &$tableDefinition) {
675 if (!isset($tableDefinition['types']) || !is_array($tableDefinition['types'])) {
676 continue;
677 }
678 foreach ($tableDefinition['types'] as $typeName => &$typeArray) {
679 if (!isset($typeArray['columnsOverrides']) || !is_array($typeArray['columnsOverrides'])) {
680 continue;
681 }
682 foreach ($typeArray['columnsOverrides'] as $fieldName => &$fieldConfig) {
683 if (isset($fieldConfig['defaultExtras'])) {
684 $oldValue = $fieldConfig['defaultExtras'];
685 $fieldConfig['defaultExtras'] = preg_replace(
686 '/richtext(\[([^\]]*)\])*:rte_transform(\[([^\]]*)\])/',
687 'richtext${1}:rte_transform',
688 $fieldConfig['defaultExtras'],
689 -1,
690 $replacementCount
691 );
692 if ($replacementCount) {
693 $this->messages[] = 'rte_transform options are deprecated. String "'
694 . $oldValue . '" in TCA'
695 . ' ' . $table . '[\'types\'][\'' . $typeName
696 . '\'][\'columnsOverrides\'][\'' . $fieldName
697 . '\'][\'defaultExtras\']' .
698 ' was changed to "' . $fieldConfig['defaultExtras'] . '"';
699 }
700 }
701 }
702 }
703 }
704
705 return $tca;
706 }
707
708 /**
709 * Migrates fields having a colorpicker wizard to a color field
710 *
711 * @param array $tca Incoming TCA
712 * @return array Migrated TCA
713 */
714 protected function migrateColorPickerWizardToRenderType(array $tca)
715 {
716 foreach ($tca as $table => &$tableDefinition) {
717 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
718 continue;
719 }
720 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
721 if (isset($fieldConfig['config'])) {
722 if (isset($fieldConfig['config']['wizards'])) {
723 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizard) {
724 if (isset($wizard['type']) && ($wizard['type'] === 'colorbox')) {
725 unset($fieldConfig['config']['wizards'][$wizardName]);
726 if (empty($fieldConfig['config']['wizards'])) {
727 unset($fieldConfig['config']['wizards']);
728 }
729 $fieldConfig['config']['renderType'] = 'colorpicker';
730
731 $this->messages[] = 'The color-picker wizard using \'colorbox\' is deprecated'
732 . ' in TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']'
733 . '[\'wizards\'][\'' . $wizardName . '\'] and is changed to ' . $table
734 . '[\'columns\'][\'' . $fieldName . '\'][\'config\'] = \'colorpicker\'';
735 }
736 }
737 }
738 }
739 }
740 }
741
742 return $tca;
743 }
744
745 /**
746 * Migrates selectTree fields deprecated options
747 *
748 * @param array $tca Incoming TCA
749 * @return array Migrated TCA
750 */
751 protected function migrateSelectTreeOptions(array $tca)
752 {
753 foreach ($tca as $table => &$tableDefinition) {
754 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
755 continue;
756 }
757 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
758 if (isset($fieldConfig['config']['renderType']) && $fieldConfig['config']['renderType'] === 'selectTree') {
759 if (isset($fieldConfig['config']['treeConfig']['appearance']['width'])) {
760 $this->messages[] = 'The selectTree field [\'treeConfig\'][\'appearance\'][\'width\'] setting is deprecated'
761 . ' and was removed in TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']'
762 . '[\'treeConfig\'][\'appearance\'][\'width\'] ';
763 unset($fieldConfig['config']['treeConfig']['appearance']['width']);
764 }
765
766 if (isset($fieldConfig['config']['treeConfig']['appearance']['allowRecursiveMode'])) {
767 $this->messages[] = 'The selectTree field [\'treeConfig\'][\'appearance\'][\'allowRecursiveMode\'] setting is deprecated'
768 . ' and was removed in TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']'
769 . '[\'treeConfig\'][\'appearance\'][\'allowRecursiveMode\'] ';
770 unset($fieldConfig['config']['treeConfig']['appearance']['allowRecursiveMode']);
771 }
772
773 if (isset($fieldConfig['config']['autoSizeMax'])) {
774 $this->messages[] = 'The selectTree field [\'autoSizeMax\'] setting is deprecated'
775 . ' and was removed in TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\'][\'autoSizeMax\'].'
776 . ' The \'size\' value was adapted to the previous autoSizeMax value';
777 $fieldConfig['config']['size'] = $fieldConfig['config']['autoSizeMax'];
778 unset($fieldConfig['config']['autoSizeMax']);
779 }
780 }
781 }
782 }
783 return $tca;
784 }
785
786 /**
787 * Migrates selectTree fields deprecated options
788 *
789 * @param array $tca Incoming TCA
790 * @return array Migrated TCA
791 */
792 protected function migrateTSconfigSoftReferences(array $tca)
793 {
794 foreach ($tca as $table => &$tableDefinition) {
795 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
796 continue;
797 }
798 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
799 if (isset($fieldConfig['config'])) {
800 if (isset($fieldConfig['config']['softref'])) {
801 $softReferences = array_flip(GeneralUtility::trimExplode(',', $fieldConfig['config']['softref']));
802 $changed = false;
803 if (isset($softReferences['TSconfig'])) {
804 $changed = true;
805 unset($softReferences['TSconfig']);
806 }
807 if (isset($softReferences['TStemplate'])) {
808 $changed = true;
809 unset($softReferences['TStemplate']);
810 }
811 if ($changed) {
812 if (!empty($softReferences)) {
813 $softReferences = array_flip($softReferences);
814 $fieldConfig['config']['softref'] = implode(',', $softReferences);
815 } else {
816 unset($fieldConfig['config']['softref']);
817 }
818 $this->messages[] = 'The soft reference setting using \'TSconfig\' and '
819 . '\'TStemplate\' was removed in TCA ' . $table . '[\'columns\']'
820 . '[\'' . $fieldName . '\'][\'config\'][\'softref\']';
821 }
822 }
823 }
824 }
825 }
826 return $tca;
827 }
828
829 /**
830 * Removes the option "showIfRTE" for TCA type "check"
831 *
832 * @param array $tca Incoming TCA
833 * @return array Migrated TCA
834 */
835 protected function migrateShowIfRteOption(array $tca)
836 {
837 foreach ($tca as $table => &$tableDefinition) {
838 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
839 continue;
840 }
841 foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
842 if (isset($fieldConfig['config']) && $fieldConfig['config']['type'] === 'check') {
843 if (isset($fieldConfig['config']['showIfRTE'])) {
844 unset($fieldConfig['config']['showIfRTE']);
845 $this->messages[] = 'The TCA setting \'showIfRTE\' was removed '
846 . 'in TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']';
847 }
848 }
849 }
850 }
851 return $tca;
852 }
853
854 /**
855 * Casts "versioningWS" to bool, and removes "versioning_followPages"
856 *
857 * @param array $tca Incoming TCA
858 * @return array Migrated TCA
859 */
860 protected function migrateWorkspacesOptions(array $tca)
861 {
862 foreach ($tca as $table => &$tableDefinition) {
863 if (isset($tableDefinition['ctrl']['versioningWS']) && !is_bool($tableDefinition['ctrl']['versioningWS'])) {
864 $tableDefinition['ctrl']['versioningWS'] = (bool)$tableDefinition['ctrl']['versioningWS'];
865 $this->messages[] = 'The TCA setting \'versioningWS\' was set to a boolean value '
866 . 'in TCA ' . $table . '[\'ctrl\'][\'versioningWS\']';
867 }
868 if (isset($tableDefinition['ctrl']['versioning_followPages']) && !empty($tableDefinition['ctrl']['versioning_followPages'])) {
869 unset($tableDefinition['ctrl']['versioning_followPages']);
870 $this->messages[] = 'The TCA setting \'versioning_followPages\' was removed as it is unused '
871 . 'in TCA ' . $table . '[\'ctrl\'][\'versioning_followPages\']';
872 }
873 }
874 return $tca;
875 }
876 }