[TASK] Doctrine: Migrate RTE-related Upgrade Wizards
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / Classes / Hook / Install / RteAcronymButtonRenamedToAbbreviation.php
1 <?php
2 namespace TYPO3\CMS\Rtehtmlarea\Hook\Install;
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 Doctrine\DBAL\DBALException;
18 use TYPO3\CMS\Core\Database\ConnectionPool;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20 use TYPO3\CMS\Core\Utility\StringUtility;
21 use TYPO3\CMS\Install\Updates\AbstractUpdate;
22
23 /**
24 * Contains the update class for the replacement of deprecated acronym button by abbreviation button in Page TSconfig.
25 * Used by the upgrade wizard in the install tool.
26 */
27 class RteAcronymButtonRenamedToAbbreviation extends AbstractUpdate
28 {
29 /**
30 * @var string
31 */
32 protected $title = 'Rte "acronym" button renamed to "abbreviation"';
33
34 /**
35 * Function which checks if update is needed. Called in the beginning of an update process.
36 *
37 * @param string $description Pointer to description for the update
38 * @return bool TRUE if update is needs to be performed, FALSE otherwise.
39 */
40 public function checkForUpdate(&$description)
41 {
42 $result = false;
43
44 $pages = $this->getPagesWithDeprecatedRteProperties($customMessages);
45 $pagesCount = count($pages);
46 $description = '<p>The RTE "acronym" button is deprecated and replaced by the "abbreviation" button since TYPO3 CMS 7.0.</p>' . LF . '<p>Page TSconfig currently includes the string "acronym" on <strong>' . strval($pagesCount) . '&nbsp;pages</strong> (including deleted and hidden pages).</p>' . LF;
47 if ($pagesCount) {
48 $pagesUids = array();
49 foreach ($pages as $page) {
50 $pagesUids[] = $page['uid'];
51 }
52 $description .= '<p>Pages id\'s: ' . implode(', ', $pagesUids) . '</p>';
53 }
54 if ($pagesCount) {
55 $updateablePages = $this->findUpdateablePagesWithDeprecatedRteProperties($pages);
56 if (!empty($updateablePages)) {
57 $description .= '<p>This wizard will perform automatic replacement of the string "acronym" by the string "abbreviation" on the Page TSconfig of <strong>' . strval(count($updateablePages)) . '&nbsp;pages</strong> (including deleted and hidden):</p>' . LF;
58 }
59 $result = true;
60 } else {
61 // if we found no occurrence of deprecated settings and wizard was already executed, then
62 // we do not show up anymore
63 if ($this->isWizardDone()) {
64 $result = false;
65 }
66 }
67 $description .= '<p>Only page records are searched for the string "acronym". However, such string may also be used in BE group and BE user records. These are not searched nor updated by this wizard.</p>'
68 . LF . '<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>'
69 . LF . '<p>Note that this string replacement will apply to all contents of PageTSconfig.</p>'
70 . LF . '<p>Note that the configuration of RTE processing options (RTE.default.proc) may also include the string "acronym".</p>';
71
72 return $result;
73 }
74
75 /**
76 * Performs the update itself
77 *
78 * @param array $dbQueries Pointer where to insert all DB queries made, so they can be shown to the user if wanted
79 * @param string $customMessages Pointer to output custom messages
80 * @return bool TRUE if update succeeded, FALSE otherwise
81 */
82 public function performUpdate(array &$dbQueries, &$customMessages)
83 {
84 $customMessages = '';
85 $pages = $this->getPagesWithDeprecatedRteProperties($customMessages);
86 if (empty($customMessages)) {
87 $pagesCount = count($pages);
88 if ($pagesCount) {
89 $updateablePages = $this->findUpdateablePagesWithDeprecatedRteProperties($pages);
90 if (!empty($updateablePages)) {
91 $this->updatePages($updateablePages, $dbQueries, $customMessages);
92 // If the update was successful
93 if (empty($customMessages)) {
94 if (count($updateablePages) !== $pagesCount) {
95 $customMessages = 'Some deprecated Page TSconfig properties were found. However, the wizard was unable to automatically replace all the deprecated properties found. Some properties will have to be replaced manually.';
96 }
97 }
98 } else {
99 $customMessages = 'Some deprecated Page TSconfig properties were found. However, the wizard was unable to automatically replace any of the deprecated properties found. These properties will have to be replaced manually.';
100 }
101 }
102 }
103 $this->markWizardAsDone();
104 return empty($customMessages);
105 }
106
107 /**
108 * Gets the pages with deprecated RTE properties in TSconfig column
109 *
110 * @param string $customMessages Pointer to output custom messages
111 * @return array uid and inclusion string for the pages with deprecated RTE properties in TSconfig column
112 */
113 protected function getPagesWithDeprecatedRteProperties(&$customMessages)
114 {
115 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
116 $queryBuilder->getRestrictions()->removeAll();
117
118 $isMySQL = StringUtility::beginsWith($queryBuilder->getConnection()->getServerVersion(), 'MySQL');
119 if ($isMySQL) {
120 $whereClause = $queryBuilder->expr()->comparison(
121 $queryBuilder->quoteIdentifier('TSconfig'),
122 'LIKE BINARY',
123 $queryBuilder->createNamedParameter('%acronym%')
124 );
125 } else {
126 $whereClause = $queryBuilder->expr()->like('TSconfig', $queryBuilder->createNamedParameter('%acronym%'));
127 }
128
129 try {
130 return $queryBuilder
131 ->select('uid', 'TSconfig')
132 ->from('pages')
133 ->where($whereClause)
134 ->execute()
135 ->fetchAll();
136 } catch (DBALException $e) {
137 $customMessages = 'SQL-ERROR: ' . htmlspecialchars($e->getPrevious()->getMessage());
138 }
139
140 return [];
141 }
142
143 /**
144 * Gets the pages with updateable deprecated RTE properties in TSconfig column
145 *
146 * @param array $pages reference to pages with deprecated property
147 * @return array uid and inclusion string for the pages with deprecated RTE properties in TSconfig column
148 */
149 protected function findUpdateablePagesWithDeprecatedRteProperties(&$pages)
150 {
151 foreach ($pages as $index => $page) {
152 $updatedPageTSConfig = str_replace('acronym', 'abbreviation', $page['TSconfig']);
153 if ($updatedPageTSConfig === $page['TSconfig']) {
154 unset($pages[$index]);
155 } else {
156 $pages[$index]['TSconfig'] = $updatedPageTSConfig;
157 }
158 }
159 return $pages;
160 }
161
162 /**
163 * updates the pages records with updateable Page TSconfig properties
164 *
165 * @param array $pages Page records to update, fetched by getTemplates() and filtered by
166 * @param array $dbQueries Pointer where to insert all DB queries made, so they can be shown to the user if wanted
167 * @param string $customMessages Pointer to output custom messages
168 */
169 protected function updatePages($pages, &$dbQueries, &$customMessages)
170 {
171 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
172 foreach ($pages as $page) {
173 try {
174 $queryBuilder->update('pages')
175 ->where($queryBuilder->expr()->eq('uid', (int)$page['uid']))
176 ->set('TSconfig', $queryBuilder->quote($page['TSconfig']), false)
177 ->execute();
178 } catch (DBALException $e) {
179 $customMessages .= 'SQL-ERROR: ' . htmlspecialchars($e->getPrevious()->getMessage()) . LF . LF;
180 }
181 $dbQueries[] = str_replace(LF, ' ', $queryBuilder->getSQL());
182 }
183 }
184 }