[BUGFIX] Followup: Install Tool: Make upgrade wizards DBAL-compatible
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Updates / RteMagicImagesUpdateWizard.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 /**
18 * Upgrade wizard that moves all RTE magic images (usually in uploads/)
19 * that have the prefix RTEmagicC_* to the default storage (usually fileadmin/_migrated/RTE/)
20 * and also updates the according fields (e.g. tt_content:123:bodytext) with the new string, and updates
21 * the softreference index
22 *
23 * @author Benjamin Mack <benni@typo3.org>
24 */
25 class RteMagicImagesUpdateWizard extends AbstractUpdate {
26
27 /**
28 * Title of the update wizard
29 * @var string
30 */
31 protected $title = 'Migrate all RTE magic images from uploads/RTEmagicC_* to fileadmin/_migrated/RTE/';
32
33 /**
34 * @var \TYPO3\CMS\Core\Database\DatabaseConnection
35 */
36 protected $db;
37
38 /**
39 * The default storage
40 * @var \TYPO3\CMS\Core\Resource\ResourceStorage
41 */
42 protected $storage;
43
44 /**
45 * The old location of the file name, e.g. "uploads/RTEmagicC_"
46 * @var string
47 */
48 protected $oldPrefix = NULL;
49
50 /**
51 * @var \TYPO3\CMS\Core\Log\Logger
52 */
53 protected $logger;
54
55 /**
56 * Constructor
57 */
58 public function __construct() {
59 /** @var $logManager \TYPO3\CMS\Core\Log\LogManager */
60 $logManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Log\\LogManager');
61 $this->db = $GLOBALS['TYPO3_DB'];
62 $this->logger = $logManager->getLogger(__CLASS__);
63
64 // Set it to uploads/RTEmagicC_*
65 if (!empty($GLOBALS['TYPO3_CONF_VARS']['BE']['RTE_imageStorageDir'])) {
66 $this->oldPrefix = $GLOBALS['TYPO3_CONF_VARS']['BE']['RTE_imageStorageDir'] . 'RTEmagicC_';
67 }
68 }
69
70 /**
71 * Initialize the storage repository.
72 *
73 * @return void
74 */
75 public function init() {
76 /** @var $storageRepository \TYPO3\CMS\Core\Resource\StorageRepository */
77 $storageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\StorageRepository');
78 $storages = $storageRepository->findAll();
79 $this->storage = $storages[0];
80 }
81
82 /**
83 * Checks if an update is needed
84 *
85 * @param string $description The description for the update
86 * @return boolean TRUE if an update is needed, FALSE otherwise
87 */
88 public function checkForUpdate(&$description) {
89 $description = 'This update wizard goes through all magic images, located in "' . htmlspecialchars($this->oldPrefix) . '", and moves the files to fileadmin/_migrated/RTE/.';
90 $description .= '<br />It also moves the files from uploads/ to the fileadmin/_migrated/ path.';
91 // Issue warning about sys_refindex needing to be up to date
92 /** @var \TYPO3\CMS\Core\Messaging\FlashMessage $message */
93 $message = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
94 'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
95 'This script bases itself on the references contained in the general reference index (sys_refindex). It is strongly advised to update it before running this wizard.',
96 'Updating the reference index',
97 \TYPO3\CMS\Core\Messaging\FlashMessage::WARNING
98 );
99 $description .= $message->render();
100
101 // Wizard is only available if oldPrefix set
102 if ($this->oldPrefix) {
103 $oldRecords = $this->findMagicImagesInOldLocation();
104 if (count($oldRecords) > 0) {
105 $description .= '<br />There are currently <strong>' . count($oldRecords) . '</strong> magic images in the old directory.<br />';
106 return TRUE;
107 }
108 }
109
110 // Disable the update wizard if there are no old RTE magic images
111 return FALSE;
112 }
113
114 /**
115 * Performs the database update.
116 *
117 * @param array $dbQueries queries done in this update
118 * @param mixed $customMessages custom messages
119 * @return boolean TRUE on success, FALSE on error
120 */
121 public function performUpdate(array &$dbQueries, &$customMessages) {
122 $this->init();
123
124 if (!PATH_site) {
125 throw new \Exception('PATH_site was undefined.');
126 }
127
128 $fileadminDirectory = rtrim($GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'], '/');
129 $targetDirectory = '/_migrated/RTE/';
130 $fullTargetDirectory = PATH_site . $fileadminDirectory . $targetDirectory;
131
132 // Create the directory, if necessary
133 if (!is_dir($fullTargetDirectory)) {
134 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir_deep($fullTargetDirectory);
135 }
136
137
138 $oldRecords = $this->findMagicImagesInOldLocation();
139 foreach ($oldRecords as $refRecord) {
140
141 // Is usually uploads/RTE_magicC_123423324.png.png
142 $sourceFileName = $refRecord['ref_string'];
143 // Absolute path/filename
144 $fullSourceFileName = PATH_site . $refRecord['ref_string'];
145 $targetFileName = $targetDirectory . \TYPO3\CMS\Core\Utility\PathUtility::basename($refRecord['ref_string']);
146 // Full directory
147 $fullTargetFileName = $fullTargetDirectory . \TYPO3\CMS\Core\Utility\PathUtility::basename($refRecord['ref_string']);
148
149 // maybe the file has been moved previously
150 if (!file_exists($fullTargetFileName)) {
151 // If the source file does not exist, we should just continue, but leave a message in the docs;
152 // ideally, the user would be informed after the update as well.
153 if (!file_exists(PATH_site . $sourceFileName)) {
154 $this->logger->notice('File ' . $sourceFileName . ' does not exist. Reference was not migrated.', array());
155
156 $format = 'File \'%s\' does not exist. Referencing field: %s.%d.%s. The reference was not migrated.';
157 $message = sprintf($format, $sourceFileName, $refRecord['tablename'], $refRecord['recuid'], $refRecord['field']);
158 $customMessages .= PHP_EOL . $message;
159
160 continue;
161 }
162
163 rename($fullSourceFileName, $fullTargetFileName);
164 }
165
166 // Get the File object
167 $file = $this->storage->getFile($targetFileName);
168 if ($file instanceof \TYPO3\CMS\Core\Resource\File) {
169 // And now update the referencing field
170 $targetFieldName = $refRecord['field'];
171 $targetRecord = $this->db->exec_SELECTgetSingleRow(
172 'uid, ' . $targetFieldName,
173 $refRecord['tablename'],
174 'uid=' . (int)$refRecord['recuid']
175 );
176 if ($targetRecord) {
177 // Replace the old filename with the new one, and add data-* attributes used by the RTE
178 $searchString = 'src="' . $sourceFileName . '"';
179 $replacementString = 'src="' . $fileadminDirectory . $targetFileName . '"';
180 $replacementString .= ' data-htmlarea-file-uid="' . $file->getUid() . '"';
181 $replacementString .= ' data-htmlarea-file-table="sys_file"';
182 $targetRecord[$targetFieldName] = str_replace(
183 $searchString,
184 $replacementString,
185 $targetRecord[$targetFieldName]
186 );
187 // Update the record
188 $this->db->exec_UPDATEquery(
189 $refRecord['tablename'],
190 'uid=' . (int)$refRecord['recuid'],
191 array($targetFieldName => $targetRecord[$targetFieldName])
192 );
193 $queries[] = str_replace(LF, ' ', $this->db->debug_lastBuiltQuery);
194
195 // Finally, update the sys_refindex table as well
196 $this->db->exec_UPDATEquery(
197 'sys_refindex',
198 'hash=' . $this->db->fullQuoteStr($refRecord['hash'], 'sys_refindex'),
199 array(
200 'ref_table' => 'sys_file',
201 'softref_key' => 'rtehtmlarea_images',
202 'ref_uid' => $file->getUid(),
203 'ref_string' => $fileadminDirectory . $targetFileName
204 )
205 );
206 $queries[] = str_replace(LF, ' ', $this->db->debug_lastBuiltQuery);
207 }
208
209 }
210 }
211
212 return TRUE;
213 }
214
215 /**
216 * Go through the soft refindex and find all occurences where the old filename
217 * is still written in the ref_string
218 *
219 * @return array Entries from sys_refindex
220 */
221 protected function findMagicImagesInOldLocation() {
222 $records = $this->db->exec_SELECTgetRows(
223 'hash, tablename, recuid, field, ref_table, ref_uid, ref_string',
224 'sys_refindex',
225 'ref_string LIKE ' . $this->db->fullQuoteStr($this->db->escapeStrForLike($this->oldPrefix, 'sys_refindex') . '%', 'sys_refindex'),
226 '',
227 'ref_string ASC'
228 );
229 return $records;
230 }
231
232 }