[BUGFIX] Upgrade Wizards appear over and over again
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / hooks / install / class.tx_rtehtmlarea_deprecatedrteproperties.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2011 Stanislas Rolland <typo3@sjbr.ca>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27
28 /**
29 * Contains the update class for the replacement of deprecated RTE properties in Page TSconfig. Used by the update wizard in the install tool.
30 *
31 * @author Stanislas Rolland <typo3@sjbr.ca>
32 */
33 class tx_rtehtmlarea_deprecatedRteProperties extends Tx_Install_Updates_Base {
34 protected $title = 'Deprecated RTE properties in Page TSconfig';
35 // Properties that may be replaced automatically in Page TSconfig (except inludes from external files)
36 protected $replacementRteProperties = array(
37 'disableRightClick' => 'contextMenu.disable',
38 'disableContextMenu' => 'contextMenu.disable',
39 'hidePStyleItems' => 'buttons.formatblock.removeItems',
40 'hideFontFaces' => 'buttons.fontstyle.removeItems',
41 'fontFace' => 'buttons.fontstyle.addItems',
42 'hideFontSizes' => 'buttons.fontsize.removeItems',
43 'classesCharacter' => 'buttons.textstyle.tags.span.allowedClasses',
44 'classesParagraph' => 'buttons.blockstyle.tags.div.allowedClasses',
45 'classesTable' => 'buttons.blockstyle.tags.table.allowedClasses',
46 'classesTD' => 'buttons.blockstyle.tags.td.allowedClasses',
47 'classesImage' => 'buttons.image.properties.class.allowedClasses',
48 'classesLinks' => 'buttons.link.properties.class.allowedClasses',
49 'blindImageOptions' => 'buttons.image.options.removeItems',
50 'blindLinkOptions' => 'buttons.link.options.removeItems',
51 'defaultLinkTarget' => 'buttons.link.properties.target.default',
52 );
53 protected $doubleReplacementRteProperties = array(
54 'disableTYPO3Browsers' => array(
55 'buttons.image.TYPO3Browser.disabled',
56 'buttons.link.TYPO3Browser.disabled',
57 ),
58 'showTagFreeClasses' => array(
59 'buttons.blockstyle.showTagFreeClasses',
60 'buttons.textstyle.showTagFreeClasses',
61 ),
62 'disablePCexamples' => array(
63 'buttons.blockstyle.disableStyleOnOptionLabel',
64 'buttons.textstyle.disableStyleOnOptionLabel',
65 ),
66 );
67 // Properties that may not be replaced automatically in Page TSconfig
68 protected $useInsteadRteProperties = array(
69 'fontSize' => 'buttons.fontsize.addItems',
70 'RTE.default.classesAnchor' => 'RTE.default.buttons.link.properties.class.allowedClasses',
71 'RTE.default.classesAnchor.default.[link-type]' => 'RTE.default.buttons.link.[link-type].properties.class.default',
72 'mainStyleOverride' => 'contentCSS',
73 'mainStyleOverride_add.[key]' => 'contentCSS',
74 'mainStyle_font' => 'contentCSS',
75 'mainStyle_size' => 'contentCSS',
76 'mainStyle_color' => 'contentCSS',
77 'mainStyle_bgcolor' => 'contentCSS',
78 'inlineStyle.[any-keystring]' => 'contentCSS',
79 'ignoreMainStyleOverride' => 'n.a.',
80 );
81
82 /**
83 * Function which checks if update is needed. Called in the beginning of an update process.
84 *
85 * @param string pointer to description for the update
86 * @return boolean TRUE if update is needs to be performed, FALSE otherwise.
87 */
88 public function checkForUpdate(&$description) {
89 $result = FALSE;
90 // TYPO3 version 4.6 and above
91 if ($this->versionNumber >= 4006000) {
92 $pages = $this->getPagesWithDeprecatedRteProperties($dbQueries, $customMessages);
93 $pagesCount = count($pages);
94 $deprecatedProperties = '';
95 $deprecatedRteProperties = array_merge($this->replacementRteProperties, $this->useInsteadRteProperties);
96 foreach ($deprecatedRteProperties as $deprecatedProperty => $replacementProperty) {
97 $deprecatedProperties .= '<tr><td>' . $deprecatedProperty . '</td><td>' . $replacementProperty . '</td></tr>' . LF;
98 }
99 foreach ($this->doubleReplacementRteProperties as $deprecatedProperty => $replacementProperties) {
100 $deprecatedProperties .= '<tr><td>' . $deprecatedProperty . '</td><td>' . implode(' and ', $replacementProperties) . '</td></tr>' . LF;
101 }
102 $description = '<p>The following Page TSconfig RTE properties are deprecated since TYPO3 4.6 and will be removed in TYPO3 4.8.</p>' . LF .
103 '<table><thead><tr><th>Deprecated property</th><th>Use instead</th></tr></thead>' . LF . '<tbody>' . $deprecatedProperties . '</tboby></table>' . LF .
104 '<p>You are currently using some of these properties on <strong>' . strval($pagesCount) . '&nbsp;pages</strong> (including deleted and hidden pages).</p>' . LF;
105 if ($pagesCount) {
106 $pagesUids = array();
107 foreach ($pages as $page) {
108 $pagesUids[] = $page['uid'];
109 }
110 $description .= '<p>Pages id\'s: ' . implode(', ', $pagesUids) . '</p>';
111 }
112 $replacementProperties = '';
113 foreach ($this->useInsteadRteProperties as $deprecatedProperty => $replacementProperty) {
114 $replacementProperties .= '<tr><td>' . $deprecatedProperty . '</td><td>' . $replacementProperty . '</td></tr>' . LF;
115 }
116 if ($pagesCount) {
117 $updateablePages = $this->findUpdateablePagesWithDeprecatedRteProperties($pages);
118 if (count($updateablePages)) {
119 $replacementProperties = '';
120 foreach ($this->replacementRteProperties as $deprecatedProperty => $replacementProperty) {
121 $replacementProperties .= '<tr><td>' . $deprecatedProperty . '</td><td>' . $replacementProperty . '</td></tr>' . LF;
122 }
123 $description .= '<p>This wizard will perform automatic replacement of the following properties on <strong>' . strval(count($updateablePages)) . '&nbsp;pages</strong> (including deleted and hidden):</p>' . LF .
124 '<table><thead><tr><th>Deprecated property</th><th>Will be replaced by</th></tr></thead><tbody>' . $replacementProperties . '</tboby></table>' . LF .
125 '<p>The Page TSconfig column of the remaining pages will need to be updated manually.</p>' . LF;
126 } else {
127 $replacementProperties = '';
128 foreach (array_keys(array_merge($this->useInsteadRteProperties, $this->doubleReplacementRteProperties)) as $deprecatedProperty) {
129 $replacementProperties .= '<tr><td>' . $deprecatedProperty . '</td></tr>' . LF;
130 }
131 $description .= '<p>This wizard cannot update the following properties, some of which are present on those pages:</p>' . LF .
132 '<table><thead><tr><th>Deprecated property</th></tr></thead><tbody>' . $replacementProperties . '</tboby></table>' . LF .
133 '<p>Therefore, the Page TSconfig column of those pages will need to be updated manually.</p>' . LF;
134 }
135 $result = TRUE;
136 } else {
137 // if we found no occurence of deprecated settings and wizard was already executed, then
138 // we do not show up anymore
139 if ($this->isWizardDone()) {
140 $result = FALSE;
141 }
142 }
143 $description .= '<p>Only page records were searched for deprecated properties. However, such properties can also be used in BE group and BE user records (prepended with page.). These are not searched nor updated by this wizard.</p>' . LF .
144 '<p>Page TSconfig may also be included from external files. These are not updated by this wizard. If required, the update will need to be done manually.</p>' . LF .
145 '<p>Note also that deprecated properties have been replaced in default configurations provided by htmlArea RTE';
146
147 }
148 return $result;
149 }
150
151 /**
152 * Performs the update itself
153 *
154 * @param array pointer where to insert all DB queries made, so they can be shown to the user if wanted
155 * @param string pointer to output custom messages
156 * @return boolean TRUE if update succeeded, FALSE otherwise
157 */
158 public function performUpdate(&$dbQueries, &$customMessages) {
159 $success = FALSE;
160 $pages = $this->getPagesWithDeprecatedRteProperties($dbQueries, $customMessages);
161 if (empty($customMessages)) {
162 if (count($pages)) {
163 $updateablePages = $this->findUpdateablePagesWithDeprecatedRteProperties($pages);
164 if (count($updateablePages)) {
165 $this->updatePages($updateablePages, $dbQueries, $customMessages);
166 } else {
167 $customMessages = '<p>Some deprecated Page TSconfig properties were found. However, the wizard was unable to automatically replace any of the deprecated properties found. They will have to be replaced manually.</p>' . LF;
168 $success = TRUE;
169 }
170 } else {
171 $customMessages = '<p>No deprecated Page TSconfig properties were found on page records.</p>' . LF ;
172 $success = TRUE;
173 }
174 $customMessages .= '<p>Only page records were searched for deprecated properties. However, such properties can also be used in BE group and BE user records (prepended with page.). These are not searched nor updated by this wizard.</p>' . LF .
175 '<p>Page TSconfig may also be included from external files. These were not updated by this wizard. If required, the update will need to be done manually.</p>';
176 }
177 $this->markWizardAsDone();
178 return empty($customMessages) || $success;
179 }
180
181 /**
182 * Gets the pages with deprecated RTE properties in TSConfig column
183 *
184 * @param array pointer where to insert all DB queries made, so they can be shown to the user if wanted
185 * @param string pointer to output custom messages
186 * @return array uid and inclusion string for the pages with deprecated RTE properties in TSConfig column
187 */
188 protected function getPagesWithDeprecatedRteProperties(&$dbQueries, &$customMessages) {
189 $fields = 'uid, TSconfig';
190 $table = 'pages';
191 $deprecatedRteProperties = array_keys(array_merge($this->replacementRteProperties, $this->useInsteadRteProperties, $this->doubleReplacementRteProperties));
192 $where = '';
193 foreach ($deprecatedRteProperties as $deprecatedRteProperty) {
194 $where .= ($where ? ' OR ' : '') . '(TSConfig LIKE BINARY "%RTE.%' . $deprecatedRteProperty . '%" AND TSConfig NOT LIKE BINARY "%RTE.%' . $deprecatedRteProperty . 's%") ';
195 }
196 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fields, $table, $where);
197
198 $dbQueries[] = str_replace(chr(10), ' ', $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery);
199
200 if ($GLOBALS['TYPO3_DB']->sql_error()) {
201 $customMessages = 'SQL-ERROR: ' . htmlspecialchars($GLOBALS['TYPO3_DB']->sql_error());
202 }
203
204 $pages = array();
205 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
206 $pages[] = $row;
207 }
208 return $pages;
209 }
210
211 /**
212 * Gets the pages with updated deprecated RTE properties in TSConfig column
213 *
214 * @param array $pages: reference to pages with deprecated property
215 * @return array uid and inclusion string for the pages with deprecated RTE properties in TSConfig column
216 */
217 protected function findUpdateablePagesWithDeprecatedRteProperties(&$pages) {
218 foreach ($pages as $index => $page) {
219 $deprecatedProperties = explode(',', '/' . implode('/,/((RTE\.(default\.|config\.[a-zA-Z0-9_\-]*\.[a-zA-Z0-9_\-]*\.))|\s)', array_keys($this->replacementRteProperties)) . '/');
220 $replacementProperties = explode(',', '$1' . implode(',$1', array_values($this->replacementRteProperties)));
221 $updatedPageTSConfig = preg_replace($deprecatedProperties, $replacementProperties, $page['TSconfig']);
222 if ($updatedPageTSConfig == $page['TSconfig']) {
223 unset($pages[$index]);
224 } else {
225 $pages[$index]['TSconfig'] = $updatedPageTSConfig;
226 }
227 }
228 return $pages;
229 }
230
231 /**
232 * updates the pages records with updateable Page TSconfig properties
233 *
234 * @param array pages records to update, fetched by getTemplates() and filtered by
235 * @param array pointer where to insert all DB queries made, so they can be shown to the user if wanted
236 * @param string pointer to output custom messages
237 */
238 protected function updatePages($pages, &$dbQueries, &$customMessages) {
239 foreach ($pages as $page) {
240 $table = 'pages';
241 $where = 'uid =' . $page['uid'];
242 $field_values = array(
243 'TSconfig' => $page['TSconfig']
244 );
245 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, $where, $field_values);
246 $dbQueries[] = str_replace(chr(10), ' ', $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery);
247 if ($GLOBALS['TYPO3_DB']->sql_error()) {
248 $customMessages = 'SQL-ERROR: ' . htmlspecialchars($GLOBALS['TYPO3_DB']->sql_error());
249 }
250 }
251 }
252 }
253 ?>