[BUGFIX] Upgrade wizard fails if no deprecated properties are found
[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 TS Config. 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 TS Config';
35 // Properties that may be replaced automatically in Page TS Config (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 'fontSize' => 'buttons.fontsize.addItems',
44 'classesCharacter' => 'buttons.textstyle.tags.span.allowedClasses',
45 'classesParagraph' => 'buttons.blockstyle.tags.div.allowedClasses',
46 'classesTable' => 'buttons.blockstyle.tags.table.allowedClasses',
47 'classesTD' => 'buttons.blockstyle.tags.td.allowedClasses',
48 'classesImage' => 'buttons.image.properties.class.allowedClasses',
49 'classesLinks' => 'buttons.link.properties.class.allowedClasses',
50 'blindImageOptions' => 'buttons.image.options.removeItems',
51 'blindLinkOptions' => 'buttons.link.options.removeItems',
52 'defaultLinkTarget' => 'buttons.link.properties.target.default',
53 );
54 protected $doubleReplacementRteProperties = array(
55 'disableTYPO3Browsers' => array(
56 'buttons.image.TYPO3Browser.disabled',
57 'buttons.link.TYPO3Browser.disabled',
58 ),
59 'showTagFreeClasses' => array(
60 'buttons.blockstyle.showTagFreeClasses',
61 'buttons.textstyle.showTagFreeClasses',
62 ),
63 'disablePCexamples' => array(
64 'buttons.blockstyle.disableStyleOnOptionLabel',
65 'buttons.textstyle.disableStyleOnOptionLabel',
66 ),
67 );
68 // Properties that may not be replaced automatically in Page TS Config
69 protected $useInsteadRteProperties = array(
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 TS Config 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 TS Config 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 TS Config column of those pages will need to be updated manually.</p>' . LF;
134 }
135 }
136 $description .= '<p>Note that Page TS Config may be included from external files. These will not be updated by this wizard. If required, the update will need to be done manually.</p>' . LF .
137 '<p>Note also that deprecated properties have been replaced in default configurations provided by htmlArea RTE';
138 $result = TRUE;
139 }
140 return $result;
141 }
142
143 /**
144 * Performs the update itself
145 *
146 * @param array pointer where to insert all DB queries made, so they can be shown to the user if wanted
147 * @param string pointer to output custom messages
148 * @return boolean TRUE if update succeeded, FALSE otherwise
149 */
150 public function performUpdate(&$dbQueries, &$customMessages) {
151 $success = FALSE;
152 $pages = $this->getPagesWithDeprecatedRteProperties($dbQueries, $customMessages);
153 if (empty($customMessages)) {
154 if (count($pages)) {
155 $updateablePages = $this->findUpdateablePagesWithDeprecatedRteProperties($pages);
156 if (count($updateablePages)) {
157 $this->updatePages($updateablePages, $dbQueries, $customMessages);
158 } else {
159 $customMessages = '<p>Some deprecated Page TS Config 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>';
160 $success = TRUE;
161 }
162 } else {
163 $customMessages = '<p>No deprecated Page TS Config properties were found on page records.</p>' . LF .
164 '<p>Note that Page TS Config may be included from external files. These were not updated by this wizard. If required, the update will need to be done manually.</p>';
165 $success = TRUE;
166 }
167 }
168 return empty($customMessages) || $success;
169 }
170
171 /**
172 * Gets the pages with deprecated RTE properties in TSConfig column
173 *
174 * @param array pointer where to insert all DB queries made, so they can be shown to the user if wanted
175 * @param string pointer to output custom messages
176 * @return array uid and inclusion string for the pages with deprecated RTE properties in TSConfig column
177 */
178 protected function getPagesWithDeprecatedRteProperties(&$dbQueries, &$customMessages) {
179 $fields = 'uid, TSconfig';
180 $table = 'pages';
181 $deprecatedRteProperties = array_keys(array_merge($this->replacementRteProperties, $this->useInsteadRteProperties, $this->doubleReplacementRteProperties));
182 $where = '';
183 foreach ($deprecatedRteProperties as $deprecatedRteProperty) {
184 $where .= ($where ? ' OR ' : '') . 'TSConfig LIKE "%RTE.%' . $deprecatedRteProperty . '%"';
185 }
186 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fields, $table, $where);
187
188 $dbQueries[] = str_replace(chr(10), ' ', $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery);
189
190 if ($GLOBALS['TYPO3_DB']->sql_error()) {
191 $customMessages = 'SQL-ERROR: ' . htmlspecialchars($GLOBALS['TYPO3_DB']->sql_error());
192 }
193
194 $pages = array();
195 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
196 $pages[] = $row;
197 }
198 return $pages;
199 }
200
201 /**
202 * Gets the pages with updated deprecated RTE properties in TSConfig column
203 *
204 * @param array $pages: reference to pages with deprecated property
205 * @return array uid and inclusion string for the pages with deprecated RTE properties in TSConfig column
206 */
207 protected function findUpdateablePagesWithDeprecatedRteProperties(&$pages) {
208 foreach ($pages as $index => $page) {
209 $deprecatedProperties = explode(',', '/' . implode('/,/((RTE\.(default\.|config\.[a-zA-Z0-9_\-]*\.[a-zA-Z0-9_\-]*\.))|\s)', array_keys($this->replacementRteProperties)) . '/');
210 $replacementProperties = explode(',', '$1' . implode(',$1', array_values($this->replacementRteProperties)));
211 $updatedPageTSConfig = preg_replace($deprecatedProperties, $replacementProperties, $page['TSconfig']);
212 if ($updatedPageTSConfig == $page['TSconfig']) {
213 unset($pages[$index]);
214 } else {
215 $pages[$index]['TSconfig'] = $updatedPageTSConfig;
216 }
217 }
218 return $pages;
219 }
220
221 /**
222 * updates the pages records with updateable Page TS Config properties
223 *
224 * @param array pages records to update, fetched by getTemplates() and filtered by
225 * @param array pointer where to insert all DB queries made, so they can be shown to the user if wanted
226 * @param string pointer to output custom messages
227 */
228 protected function updatePages($pages, &$dbQueries, &$customMessages) {
229 foreach ($pages as $page) {
230 $table = 'pages';
231 $where = 'uid =' . $page['uid'];
232 $field_values = array(
233 'TSconfig' => $page['TSconfig']
234 );
235 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, $where, $field_values);
236 $dbQueries[] = str_replace(chr(10), ' ', $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery);
237 if ($GLOBALS['TYPO3_DB']->sql_error()) {
238 $customMessages = 'SQL-ERROR: ' . htmlspecialchars($GLOBALS['TYPO3_DB']->sql_error());
239 }
240 }
241 }
242 }
243 ?>