[TASK] Move form field wizard icons
[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
19 /**
20 * Migrate TCA from old to new syntax. Used in bootstrap and Flex Form Data Structures.
21 *
22 * @internal Class and API may change any time.
23 */
24 class TcaMigration {
25
26 /**
27 * Accumulate migration messages
28 *
29 * @var array
30 */
31 protected $messages = array();
32
33 /**
34 * Migrate old TCA to new TCA.
35 *
36 * See unit tests for details.
37 *
38 * @param array $tca
39 * @return array
40 */
41 public function migrate(array $tca) {
42 $tca = $this->migrateT3editorWizardToRenderTypeT3editorIfNotEnabledByTypeConfig($tca);
43 $tca = $this->migrateSpecialConfigurationAndRemoveShowItemStylePointerConfig($tca);
44 $tca = $this->migrateT3editorWizardWithEnabledByTypeConfigToColumnsOverrides($tca);
45 $tca = $this->migrateShowItemAdditionalPaletteToOwnPalette($tca);
46 $tca = $this->migrateIconsForFormFieldWizardsToNewLocation($tca);
47 // @todo: if showitem/defaultExtras wizards[xy] is migrated to columnsOverrides here, enableByTypeConfig could be dropped
48 return $tca;
49 }
50
51 /**
52 * Get messages of migrated fields. Can be used for deprecation messages after migrate() was called.
53 *
54 * @return array Migration messages
55 */
56 public function getMessages() {
57 return $this->messages;
58 }
59
60 /**
61 * Migrate type=text field with t3editor wizard to renderType=t3editor without this wizard
62 *
63 * @param array $tca Incoming TCA
64 * @return array Migrated TCA
65 */
66 protected function migrateT3editorWizardToRenderTypeT3editorIfNotEnabledByTypeConfig(array $tca) {
67 $newTca = $tca;
68 foreach ($tca as $table => $tableDefinition) {
69 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
70 continue;
71 }
72 foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
73 if (
74 !empty($fieldConfig['config']['type']) // type is set
75 && trim($fieldConfig['config']['type']) === 'text' // to "text"
76 && isset($fieldConfig['config']['wizards'])
77 && is_array($fieldConfig['config']['wizards']) // and there are wizards
78 ) {
79 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
80 if (
81 !empty($wizardConfig['userFunc']) // a userFunc is defined
82 && trim($wizardConfig['userFunc']) === 'TYPO3\\CMS\\T3editor\\FormWizard->main' // and set to FormWizard
83 && (
84 !isset($wizardConfig['enableByTypeConfig']) // and enableByTypeConfig is not set
85 || (isset($wizardConfig['enableByTypeConfig']) && !$wizardConfig['enableByTypeConfig']) // or set, but not enabled
86 )
87 ) {
88 // Set renderType from text to t3editor
89 $newTca[$table]['columns'][$fieldName]['config']['renderType'] = 't3editor';
90 // Unset this wizard definition
91 unset($newTca[$table]['columns'][$fieldName]['config']['wizards'][$wizardName]);
92 // Move format parameter
93 if (!empty($wizardConfig['params']['format'])) {
94 $newTca[$table]['columns'][$fieldName]['config']['format'] = $wizardConfig['params']['format'];
95 }
96 $this->messages[] = 'Migrated t3editor wizard in TCA of table "' . $table . '" field "' . $fieldName . '" to a renderType definition.';
97 }
98 }
99 // If no wizard is left after migration, unset the whole sub array
100 if (empty($newTca[$table]['columns'][$fieldName]['config']['wizards'])) {
101 unset($newTca[$table]['columns'][$fieldName]['config']['wizards']);
102 }
103 }
104 }
105 }
106 return $newTca;
107 }
108
109 /**
110 * Remove "style pointer", the 5th parameter from "types" "showitem" configuration.
111 * Move "specConf", 4th parameter from "tyes" "showitem" to "types" "columnsOverrides.
112 *
113 * @param array $tca Incoming TCA
114 * @return array Modified TCA
115 */
116 protected function migrateSpecialConfigurationAndRemoveShowItemStylePointerConfig(array $tca) {
117 $newTca = $tca;
118 foreach ($tca as $table => $tableDefinition) {
119 if (!isset($tableDefinition['types']) || !is_array($tableDefinition['types'])) {
120 continue;
121 }
122 foreach ($tableDefinition['types'] as $typeName => $typeArray) {
123 if (!is_string($typeArray['showitem']) || strpos($typeArray['showitem'], ';') === FALSE) {
124 // Continue directly if no semicolon is found
125 continue;
126 }
127 $itemList = GeneralUtility::trimExplode(',', $typeArray['showitem'], TRUE);
128 $newFieldStrings = array();
129 foreach ($itemList as $fieldString) {
130 $fieldString = rtrim($fieldString, ';');
131 // Unpack the field definition, migrate and remove as much as possible
132 // Keep empty parameters in trimExplode here (third parameter FALSE), so position is not changed
133 $fieldArray = GeneralUtility::trimExplode(';', $fieldString);
134 $fieldArray = array(
135 'fieldName' => isset($fieldArray[0]) ? $fieldArray[0] : '',
136 'fieldLabel' => isset($fieldArray[1]) ? $fieldArray[1] : NULL,
137 'paletteName' => isset($fieldArray[2]) ? $fieldArray[2] : NULL,
138 'fieldExtra' => isset($fieldArray[3]) ? $fieldArray[3] : NULL,
139 );
140 $fieldName = $fieldArray['fieldName'];
141 if (!empty($fieldArray['fieldExtra'])) {
142 // Move fieldExtra "specConf" to columnsOverrides "defaultExtras"
143 if (!isset($newTca[$table]['types'][$typeName]['columnsOverrides'])) {
144 $newTca[$table]['types'][$typeName]['columnsOverrides'] = array();
145 }
146 if (!isset($newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldArray['fieldName']])) {
147 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldArray['fieldName']] = array();
148 }
149 // Merge with given defaultExtras from columns.
150 // They will be the first part of the string, so if "specConf" from types changes the same settings,
151 // those will override settings from defaultExtras of columns
152 $newDefaultExtras = array();
153 if (!empty($tca[$table]['columns'][$fieldArray['fieldName']]['defaultExtras'])) {
154 $newDefaultExtras[] = $tca[$table]['columns'][$fieldArray['fieldName']]['defaultExtras'];
155 }
156 $newDefaultExtras[] = $fieldArray['fieldExtra'];
157 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldArray['fieldName']]['defaultExtras'] = implode(':', $newDefaultExtras);
158 }
159 unset($fieldArray['fieldExtra']);
160 if (count($fieldArray) === 3 && empty($fieldArray['paletteName'])) {
161 unset($fieldArray['paletteName']);
162 }
163 if (count($fieldArray) === 2 && empty($fieldArray['fieldLabel'])) {
164 unset($fieldArray['fieldLabel']);
165 }
166 if (count($fieldArray) === 1 && empty($fieldArray['fieldName'])) {
167 // The field may vanish if nothing is left
168 unset($fieldArray['fieldName']);
169 }
170 $newFieldString = implode(';', $fieldArray);
171 if ($newFieldString !== $fieldString) {
172 $this->messages[] = 'Changed showitem string of TCA table "' . $table . '" type "' . $typeName . '" due to changed field "' . $fieldName . '".';
173 }
174 if (!empty($newFieldString)) {
175 $newFieldStrings[] = $newFieldString;
176 }
177 }
178 $newTca[$table]['types'][$typeName]['showitem'] = implode(',', $newFieldStrings);
179 }
180 }
181 return $newTca;
182 }
183
184 /**
185 * Migrate type=text field with t3editor wizard that is "enableByTypeConfig" to columnsOverrides
186 * with renderType=t3editor
187 *
188 * @param array $tca Incoming TCA
189 * @return array Migrated TCA
190 */
191 protected function migrateT3editorWizardWithEnabledByTypeConfigToColumnsOverrides(array $tca) {
192 $newTca = $tca;
193 foreach ($tca as $table => $tableDefinition) {
194 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
195 continue;
196 }
197 foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
198 if (
199 !empty($fieldConfig['config']['type']) // type is set
200 && trim($fieldConfig['config']['type']) === 'text' // to "text"
201 && isset($fieldConfig['config']['wizards'])
202 && is_array($fieldConfig['config']['wizards']) // and there are wizards
203 ) {
204 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
205 if (
206 !empty($wizardConfig['userFunc']) // a userFunc is defined
207 && trim($wizardConfig['userFunc']) === 'TYPO3\CMS\T3editor\FormWizard->main' // and set to FormWizard
208 && !empty($wizardConfig['enableByTypeConfig']) // and enableByTypeConfig is enabled
209 ) {
210 // Remove this wizard
211 unset($newTca[$table]['columns'][$fieldName]['config']['wizards'][$wizardName]);
212 // Find configured types that use this wizard
213 if (!isset($tableDefinition['types']) || !is_array($tableDefinition['types'])) {
214 // No type definition at all ... continue directly
215 continue;
216 }
217 foreach ($tableDefinition['types'] as $typeName => $typeArray) {
218 if (
219 empty($typeArray['columnsOverrides'][$fieldName]['defaultExtras'])
220 || strpos($typeArray['columnsOverrides'][$fieldName]['defaultExtras'], $wizardName) === FALSE
221 ) {
222 // Continue directly if this wizard is not enabled for given type
223 continue;
224 }
225 $defaultExtras = $typeArray['columnsOverrides'][$fieldName]['defaultExtras'];
226 $defaultExtrasArray = GeneralUtility::trimExplode(':', $defaultExtras, TRUE);
227 $newDefaultExtrasArray = array();
228 foreach ($defaultExtrasArray as $fieldExtraField) {
229 // There might be multiple enabled wizards separated by | ... split them
230 if (substr($fieldExtraField, 0, 8) === 'wizards[') {
231 $enabledWizards = substr($fieldExtraField, 8, strlen($fieldExtraField) - 8); // Cut off "wizards[
232 $enabledWizards = substr($enabledWizards, 0, strlen($enabledWizards) - 1);
233 $enabledWizardsArray = GeneralUtility::trimExplode('|', $enabledWizards, TRUE);
234 $newEnabledWizardsArray = array();
235 foreach ($enabledWizardsArray as $enabledWizardName) {
236 if ($enabledWizardName === $wizardName) {
237 // Found a columnsOverrides configuration that has this wizard enabled
238 // Force renderType = t3editor
239 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldName]['config']['renderType'] = 't3editor';
240 // Transfer format option if given
241 if (!empty($wizardConfig['params']['format'])) {
242 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldName]['config']['format'] = $wizardConfig['params']['format'];
243 }
244 $this->messages[] = 'Migrated t3editor wizard in TCA of table "' . $table . '" field "' . $fieldName
245 . '" to a renderType definition with columnsOverrides in type "' . $typeName . '".';
246 } else {
247 // Some other enabled wizard
248 $newEnabledWizardsArray[] = $enabledWizardName;
249 }
250 }
251 if (!empty($newEnabledWizardsArray)) {
252 $newDefaultExtrasArray[] = 'wizards[' . implode('|', $newEnabledWizardsArray) . ']';
253 }
254 } else {
255 $newDefaultExtrasArray[] = $fieldExtraField;
256 }
257 }
258 if (!empty($newDefaultExtrasArray)) {
259 $newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldName]['defaultExtras'] = implode(':', $newDefaultExtrasArray);
260 } else {
261 unset($newTca[$table]['types'][$typeName]['columnsOverrides'][$fieldName]['defaultExtras']);
262 }
263 }
264 }
265 }
266 // If no wizard is left after migration, unset the whole sub array
267 if (empty($newTca[$table]['columns'][$fieldName]['config']['wizards'])) {
268 unset($newTca[$table]['columns'][$fieldName]['config']['wizards']);
269 }
270 }
271 }
272 }
273 return $newTca;
274 }
275
276 /**
277 * Migrate types showitem 'aField;aLabel;aPalette' to 'afield;aLabel, --palette--;;aPalette'
278 *
279 * Old showitem can have a syntax like:
280 * fieldName;aLabel;aPalette
281 * This way, the palette with name "aPalette" is rendered after fieldName.
282 * The migration parses this to a syntax like:
283 * fieldName;aLabel, --palette--;;paletteName
284 *
285 * @param array $tca Incoming TCA
286 * @return array Migrated TCA
287 */
288 protected function migrateShowItemAdditionalPaletteToOwnPalette(array $tca) {
289 $newTca = $tca;
290 foreach ($tca as $table => $tableDefinition) {
291 if (!isset($tableDefinition['types']) || !is_array($tableDefinition['types'])) {
292 continue;
293 }
294 foreach ($tableDefinition['types'] as $typeName => $typeArray) {
295 if (
296 !isset($typeArray['showitem'])
297 || !is_string($typeArray['showitem'])
298 || strpos($typeArray['showitem'], ';') === FALSE // no field parameters
299 ) {
300 continue;
301 }
302 $itemList = GeneralUtility::trimExplode(',', $typeArray['showitem'], TRUE);
303 $newFieldStrings = array();
304 foreach ($itemList as $fieldString) {
305 $fieldArray = GeneralUtility::trimExplode(';', $fieldString);
306 $fieldArray = array(
307 'fieldName' => isset($fieldArray[0]) ? $fieldArray[0] : '',
308 'fieldLabel' => isset($fieldArray[1]) ? $fieldArray[1] : NULL,
309 'paletteName' => isset($fieldArray[2]) ? $fieldArray[2] : NULL,
310 );
311 if ($fieldArray['fieldName'] !== '--palette--' && $fieldArray['paletteName'] !== NULL) {
312 if ($fieldArray['fieldLabel']) {
313 $fieldString = $fieldArray['fieldName'] . ';' . $fieldArray['fieldLabel'];
314 } else {
315 $fieldString = $fieldArray['fieldName'];
316 }
317 $paletteString = '--palette--;;' . $fieldArray['paletteName'];
318 $this->messages[] = 'Migrated TCA table "' . $table . '" showitem field of type "' . $typeName . '": Moved additional palette'
319 . ' with name "' . $fieldArray['paletteName'] . '" as 3rd argument of field "' . $fieldArray['fieldName']
320 . '" to an own palette. The result of this part is: "' . $fieldString . ', ' . $paletteString . '"';
321 $newFieldStrings[] = $fieldString;
322 $newFieldStrings[] = $paletteString;
323 } else {
324 $newFieldStrings[] = $fieldString;
325 }
326 }
327 $newTca[$table]['types'][$typeName]['showitem'] = implode(',', $newFieldStrings);
328 }
329 }
330 return $newTca;
331 }
332
333 /**
334 * Migrate core icons for form field wizard to new location
335 *
336 * add.gif => EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_add.gif
337 * link_popup.gif => EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_link.gif
338 * wizard_rte2.gif => EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_rte.gif
339 * wizard_table.gif => EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_table.gif
340 * edit2.gif => EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_edit.gif
341 * list.gif => EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_list.gif
342 * wizard_forms.gif => EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_forms.gif
343 *
344 * @param array $tca Incoming TCA
345 * @return array Migrated TCA
346 */
347 protected function migrateIconsForFormFieldWizardsToNewLocation($tca) {
348 $newTca = $tca;
349
350 $oldFileNames = array(
351 'add.gif',
352 'link_popup.gif',
353 'wizard_rte2.gif',
354 'wizard_table.gif',
355 'edit2.gif',
356 'list.gif',
357 'wizard_forms.gif',
358 );
359
360 $newFileLocations = array(
361 'add.gif' => 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_add.gif',
362 'link_popup.gif' => 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_link.gif',
363 'wizard_rte2.gif' => 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_rte.gif',
364 'wizard_table.gif' => 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_table.gif',
365 'edit2.gif' => 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_edit.gif',
366 'list.gif' => 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_list.gif',
367 'wizard_forms.gif' => 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_forms.gif',
368 );
369
370 foreach ($tca as $table => $tableDefinition) {
371 if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
372 continue;
373 }
374 foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
375 if (
376 isset($fieldConfig['config']['wizards'])
377 && is_array($fieldConfig['config']['wizards']) // and there are wizards
378 ) {
379 foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizardConfig) {
380 if (!is_array($wizardConfig)) {
381 continue;
382 }
383
384 foreach ($wizardConfig as $option => $value) {
385 if ($option === 'icon' && in_array($value, $oldFileNames, TRUE)) {
386 $newTca[$table]['columns'][$fieldName]['config']['wizards'][$wizardName]['icon'] = $newFileLocations[$value];
387 $this->messages[] = 'Migrated icon path of wizard "' . $wizardName . '" in field "' . $fieldName . '" from TCA table "' . $table . '". New path is: ' . $newFileLocations[$value];
388 }
389 }
390 }
391 }
392 }
393 }
394
395 return $newTca;
396 }
397 }