[TASK] Reduce CGL violations DoubleQuoteUsageNotRequired in install/
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Updates / File / TtContentUploadsUpdateWizard.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2011 Steffen Ritter <steffen.ritter@typo3.org>
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 3 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 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24
25 /**
26 * Upgrade wizard which goes through all files referenced in the tt_content.media filed
27 * and creates sys_file records as well as sys_file_reference records for the individual usages.
28 *
29 * @package TYPO3
30 * @author Steffen Ritter <steffen.ritter@typo3.org>
31 * @license http://www.gnu.org/copyleft/gpl.html
32 */
33 class Tx_Install_Updates_File_TtContentUploadsUpdateWizard extends Tx_Install_Updates_Base {
34 const FOLDER_ContentUploads = 'content_uploads';
35
36 /**
37 * @var string
38 */
39 protected $title = 'Migrate file relations of tt_content "uploads"';
40
41 /**
42 * @var string
43 */
44 protected $targetDirectory;
45
46 /**
47 * @var t3lib_file_Factory
48 */
49 protected $fileFactory;
50
51 /**
52 * @var t3lib_file_Repository_FileRepository
53 */
54 protected $fileRepository;
55
56 /**
57 * @var t3lib_file_Storage
58 */
59 protected $storage;
60
61 /**
62 * Initialize all required repository and factory objects.
63 *
64 * @throws RuntimeException
65 */
66 protected function init() {
67 $fileadminDirectory = rtrim($GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'], '/') . '/';
68
69 /** @var $storageRepository t3lib_file_Repository_StorageRepository */
70 $storageRepository = t3lib_div::makeInstance('t3lib_file_Repository_StorageRepository');
71 $storages = $storageRepository->findAll();
72
73 foreach ($storages as $storage) {
74 $storageRecord = $storage->getStorageRecord();
75 $configuration = $storage->getConfiguration();
76
77 $isLocalDriver = $storageRecord['driver'] === 'Local';
78 $isOnFileadmin = (!empty($configuration['basePath']) && t3lib_div::isFirstPartOfStr($configuration['basePath'], $fileadminDirectory));
79
80 if ($isLocalDriver && $isOnFileadmin) {
81 $this->storage = $storage;
82 break;
83 }
84 }
85
86 if (!isset($this->storage)) {
87 throw new RuntimeException('Local default storage could not be initialized - migth be due to missing sys_file* tables.');
88 }
89
90 $this->fileFactory = t3lib_div::makeInstance('t3lib_file_Factory');
91 $this->fileRepository= t3lib_div::makeInstance('t3lib_file_Repository_FileRepository');
92 $this->targetDirectory = PATH_site . $fileadminDirectory . self::FOLDER_ContentUploads . '/';
93 }
94
95 /**
96 * Checks if an update is needed
97 *
98 * @param string &$description: The description for the update
99 * @return boolean TRUE if an update is needed, FALSE otherwise
100 */
101 public function checkForUpdate(&$description) {
102 $updateNeeded = FALSE;
103
104 // Fetch records where the field media does not contain a plain integer value
105 // * check whether media field is not empty
106 // * then check whether media field does not contain a reference count (= not integer)
107 $notMigratedRowsCount = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
108 'uid',
109 'tt_content',
110 "media <> '' AND CAST(CAST(media AS DECIMAL) AS CHAR) <> media OR (CType = 'uploads' AND select_key != '')" // include also deleted, as they might be undeleted
111 );
112 if ($notMigratedRowsCount > 0) {
113 $description = 'There are Content Elements of type "upload" which are referencing files,' .
114 ' not using FAL. The Wizard will move the files to fileadmin/content_uploads/ and index them.';
115 $updateNeeded = TRUE;
116 }
117
118 return $updateNeeded;
119 }
120
121 /**
122 * Performs the database update.
123 *
124 * @param array &$dbQueries: queries done in this update
125 * @param mixed &$customMessages: custom messages
126 * @return boolean TRUE on success, FALSE on error
127 */
128 public function performUpdate(&$dbQueries, &$customMessages) {
129 $this->init();
130 $records = $this->getRecordsFromTable('tt_content');
131 $this->checkPrerequisites();
132
133 foreach ($records as $singleRecord) {
134 $this->migrateRecord($singleRecord);
135 }
136
137 return TRUE;
138 }
139
140 /**
141 * Ensures a new folder "fileadmin/content_upload/" is available.
142 *
143 * @return void
144 */
145 protected function checkPrerequisites() {
146 if (!$this->storage->hasFolder(self::FOLDER_ContentUploads)) {
147 $this->storage->createFolder(
148 self::FOLDER_ContentUploads,
149 $this->storage->getRootLevelFolder()
150 );
151 }
152 }
153
154 /**
155 * Processes the actual transformation from CSV to sys_file_references
156 *
157 * @param array $record
158 * @return void
159 */
160 protected function migrateRecord(array $record) {
161 $collections = array();
162 if (trim($record['select_key'])) {
163 $GLOBALS['TYPO3_DB']->exec_INSERTquery(
164 'sys_file_collection',
165 array(
166 'pid' => $record['pid'],
167 'title' => $record['select_key'],
168 'storage' => $this->storage->getUid(),
169 'folder' => ltrim('fileadmin/', $record['select_key'])
170 )
171 );
172 $collections[] = $GLOBALS['TYPO3_DB']->sql_insert_id();
173 }
174
175 $files = t3lib_div::trimExplode(',', $record['media'], TRUE);
176 $descriptions = t3lib_div::trimExplode("\n", $record['imagecaption']);
177 $titleText = t3lib_div::trimExplode("\n", $record['titleText']);
178
179 $i = 0;
180 foreach ($files as $file) {
181 if (file_exists(PATH_site . 'uploads/media/' . $file)) {
182 t3lib_div::upload_copy_move(
183 PATH_site . 'uploads/media/' . $file,
184 $this->targetDirectory . $file
185 );
186
187 $fileObject = $this->storage->getFile('content_uploads/' . $file);
188 $this->fileRepository->addToIndex($fileObject);
189
190 $dataArray = array(
191 'uid_local' => $fileObject->getUid(),
192 'tablenames' => 'tt_content',
193 'uid_foreign' => $record['uid'],
194 'fieldname' => 'media',
195 'sorting_foreign' => $i
196 );
197
198 if (isset($descriptions[$i])) {
199 $dataArray['description'] = $descriptions[$i];
200 }
201
202 if (isset($titleText[$i])) {
203 $dataArray['alternative'] = $titleText[$i];
204 }
205
206 $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_file_reference', $dataArray);
207 unlink(PATH_site . 'uploads/media/' . $file);
208 }
209
210 $i++;
211 }
212
213 $this->cleanRecord($record, $i, $collections);
214 }
215
216 /**
217 * Removes the old fields from the database-record
218 *
219 * @param array $record
220 * @param integer $fileCount
221 * @param array $collectionUids
222 * @return void
223 */
224 protected function cleanRecord(array $record, $fileCount, array $collectionUids) {
225 $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
226 'tt_content',
227 'uid = ' . $record['uid'],
228 array(
229 'media' => $fileCount,
230 'imagecaption' => '',
231 'titleText' => '',
232 'altText' => '',
233 'select_key' => '',
234 'file_collections' => implode(',', $collectionUids)
235 )
236 );
237 }
238
239 /**
240 * Retrieve every record which needs to be processed
241 *
242 * @return array
243 */
244 protected function getRecordsFromTable() {
245 $fields = implode(',', array('uid', 'pid', 'select_key', 'media', 'imagecaption', 'titleText'));
246
247 $records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
248 $fields,
249 'tt_content',
250 "media <> '' AND CAST(CAST(media AS DECIMAL) AS CHAR) <> media OR (CType = 'uploads' AND select_key != '')"
251 );
252
253 return $records;
254 }
255 }
256
257 ?>