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