[!!!][FEATURE] Streamline Fluid Styled Content and CSS Styled Content
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Updates / TableFlexFormToTtContentFieldsUpdate.php
1 <?php
2 namespace TYPO3\CMS\Install\Updates;
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\Database\ConnectionPool;
18 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
19 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21
22 /**
23 * Migrate the Flexform for CType 'table' to regular fields in tt_content
24 */
25 class TableFlexFormToTtContentFieldsUpdate extends AbstractUpdate
26 {
27 /**
28 * @var string
29 */
30 protected $title = 'Migrate the Flexform for CType "table" to regular fields in tt_content';
31
32 /**
33 * Checks if an update is needed
34 *
35 * @param string &$description The description for the update
36 * @return bool Whether an update is needed (TRUE) or not (FALSE)
37 */
38 public function checkForUpdate(&$description)
39 {
40 if ($this->isWizardDone()) {
41 return false;
42 }
43
44 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content');
45 $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
46 $flexFormCount = $queryBuilder->count('uid')
47 ->from('tt_content')
48 ->where(
49 $queryBuilder->expr()->eq('CType', $queryBuilder->createNamedParameter('table', \PDO::PARAM_STR)),
50 $queryBuilder->expr()->isNotNull('pi_flexform')
51 )
52 ->execute()->fetchColumn(0);
53
54 if ($flexFormCount) {
55 $description = 'The extension "frontend" uses regular database fields in the tt_content table '
56 . 'for the CType "table". Before this was a FlexForm.<br /><br />'
57 . 'This update wizard migrates these FlexForms to regular database fields.';
58 }
59
60 return (bool)$flexFormCount;
61 }
62
63 /**
64 * Performs the database update if CType 'table' still has content in pi_flexform
65 *
66 * @param array &$databaseQueries Queries done in this update
67 * @param mixed &$customMessages Custom messages
68 * @return bool
69 */
70 public function performUpdate(array &$databaseQueries, &$customMessages)
71 {
72 $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('tt_content');
73 $queryBuilder = $connection->createQueryBuilder();
74 $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
75 $statement = $queryBuilder->select('uid', 'pi_flexform')
76 ->from('tt_content')
77 ->where(
78 $queryBuilder->expr()->eq('Ctype', $queryBuilder->createNamedParameter('table', \PDO::PARAM_STR)),
79 $queryBuilder->expr()->isNotNull('pi_flexform')
80 )
81 ->execute();
82 while ($tableRecord = $statement->fetch()) {
83 $flexForm = $this->initializeFlexForm($tableRecord['pi_flexform']);
84 if (is_array($flexForm)) {
85 $fields = $this->mapFieldsFromFlexForm($flexForm);
86 $queryBuilder = $connection->createQueryBuilder();
87 $queryBuilder->update('tt_content')
88 ->where(
89 $queryBuilder->expr()->eq(
90 'uid',
91 $queryBuilder->createNamedParameter($tableRecord['uid'], \PDO::PARAM_INT)
92 )
93 )
94 ->set('pi_flexform', 'null', false);
95 foreach ($fields as $identifier => $value) {
96 $queryBuilder->set($identifier, $value);
97 }
98 $databaseQueries[] = $queryBuilder->getSQL();
99 $queryBuilder->execute();
100 }
101 }
102
103 $this->markWizardAsDone();
104 return true;
105 }
106
107 /**
108 * Map the old FlexForm values to the new database fields
109 * and fill them with the proper data
110 *
111 * @param array $flexForm The content of the FlexForm
112 * @return array The fields which need to be updated in the tt_content table
113 */
114 protected function mapFieldsFromFlexForm($flexForm)
115 {
116 $fields = [];
117
118 $mapping = [
119 'table_caption' => [
120 'sheet' => 'sDEF',
121 'fieldName' => 'acctables_caption',
122 'default' => '',
123 'values' => 'passthrough'
124 ],
125 'table_delimiter' => [
126 'sheet' => 's_parsing',
127 'fieldName' => 'tableparsing_delimiter',
128 'default' => 124,
129 'values' => 'passthrough'
130 ],
131 'table_enclosure' => [
132 'sheet' => 's_parsing',
133 'fieldName' => 'tableparsing_quote',
134 'default' => 0,
135 'values' => 'passthrough'
136 ],
137 'table_header_position' => [
138 'sheet' => 'sDEF',
139 'fieldName' => 'acctables_headerpos',
140 'default' => 0,
141 'values' => [
142 'top' => 1,
143 'left' => 2
144 ]
145 ],
146 'table_tfoot' => [
147 'sheet' => 'sDEF',
148 'fieldName' => 'acctables_tfoot',
149 'default' => 0,
150 'values' => 'passthrough'
151 ],
152 'table_class' => [
153 'sheet' => 'sDEF',
154 'fieldName' => 'acctables_tableclass',
155 'default' => 0,
156 'values' => 'passthrough'
157 ]
158 ];
159
160 foreach ($mapping as $fieldName => $configuration) {
161 $flexFormValue = $this->getFlexFormValue($flexForm, $configuration['fieldName'], $configuration['sheet']);
162
163 if ((string)$flexFormValue !== '') {
164 if ($configuration['values'] === 'passthrough') {
165 $fields[$fieldName] = $flexFormValue;
166 } elseif (is_array($configuration['values'])) {
167 $fields[$fieldName] = $configuration['values'][$flexFormValue];
168 }
169 } else {
170 $fields[$fieldName] = $configuration['default'];
171 }
172 }
173
174 return $fields;
175 }
176
177 /**
178 * Convert the XML of the FlexForm to an array
179 *
180 * @param string|NULL $flexFormXml The XML of the FlexForm
181 * @return array|NULL Converted XML to array
182 */
183 protected function initializeFlexForm($flexFormXml)
184 {
185 $flexForm = null;
186
187 if ($flexFormXml) {
188 $flexForm = GeneralUtility::xml2array($flexFormXml);
189 if (!is_array($flexForm)) {
190 $flexForm = null;
191 }
192 }
193
194 return $flexForm;
195 }
196
197 /**
198 * @param array $flexForm The content of the FlexForm
199 * @param string $fieldName The field name to get the value for
200 * @param string $sheet The sheet on which this value is located
201 * @return string The value
202 */
203 protected function getFlexFormValue(array $flexForm, $fieldName, $sheet = 'sDEF')
204 {
205 return $flexForm['data'][$sheet]['lDEF'][$fieldName]['vDEF'];
206 }
207 }