[TASK] Merge submodule version into core
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Updates / TtContentUploadsUpdateWizard.php
1 <?php
2 namespace TYPO3\CMS\Install\Updates;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2011-2013 Steffen Ritter <steffen.ritter@typo3.org>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26 /**
27 * Upgrade wizard which goes through all files referenced in the tt_content.media filed
28 * and creates sys_file records as well as sys_file_reference records for the individual usages.
29 *
30 * @author Steffen Ritter <steffen.ritter@typo3.org>
31 * @license http://www.gnu.org/copyleft/gpl.html
32 */
33 class TtContentUploadsUpdateWizard extends \TYPO3\CMS\Install\Updates\AbstractUpdate {
34
35 const FOLDER_ContentUploads = '_migrated/content_uploads';
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 \TYPO3\CMS\Core\Resource\ResourceFactory
48 */
49 protected $fileFactory;
50
51 /**
52 * @var \TYPO3\CMS\Core\Resource\FileRepository
53 */
54 protected $fileRepository;
55
56 /**
57 * @var \TYPO3\CMS\Core\Resource\ResourceStorage
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 /** @var $storageRepository \TYPO3\CMS\Core\Resource\StorageRepository */
69 $storageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\StorageRepository');
70 $storages = $storageRepository->findAll();
71 foreach ($storages as $storage) {
72 $storageRecord = $storage->getStorageRecord();
73 $configuration = $storage->getConfiguration();
74 $isLocalDriver = $storageRecord['driver'] === 'Local';
75 $isOnFileadmin = !empty($configuration['basePath']) && \TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($configuration['basePath'], $fileadminDirectory);
76 if ($isLocalDriver && $isOnFileadmin) {
77 $this->storage = $storage;
78 break;
79 }
80 }
81 if (!isset($this->storage)) {
82 throw new \RuntimeException('Local default storage could not be initialized - might be due to missing sys_file* tables.');
83 }
84 $this->fileFactory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\ResourceFactory');
85 $this->fileRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\FileRepository');
86 $this->targetDirectory = PATH_site . $fileadminDirectory . self::FOLDER_ContentUploads . '/';
87 }
88
89 /**
90 * Checks if an update is needed
91 *
92 * @param string &$description: The description for the update
93 * @return boolean TRUE if an update is needed, FALSE otherwise
94 */
95 public function checkForUpdate(&$description) {
96 $updateNeeded = FALSE;
97 // Fetch records where the field media does not contain a plain integer value
98 // * check whether media field is not empty
99 // * then check whether media field does not contain a reference count (= not integer)
100 $notMigratedRowsCount = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('uid', 'tt_content', 'media <> \'\' AND CAST(CAST(media AS DECIMAL) AS CHAR) <> media OR (CType = \'uploads\' AND select_key != \'\')');
101 if ($notMigratedRowsCount > 0) {
102 $description = 'There are Content Elements of type "upload" which are referencing files that are not using ' . ' the File Abstraction Layer. This wizard will move the files to fileadmin/' . self::FOLDER_ContentUploads . ' and index them.';
103 $updateNeeded = TRUE;
104 }
105 return $updateNeeded;
106 }
107
108 /**
109 * Performs the database update.
110 *
111 * @param array &$dbQueries: queries done in this update
112 * @param mixed &$customMessages: custom messages
113 * @return boolean TRUE on success, FALSE on error
114 */
115 public function performUpdate(array &$dbQueries, &$customMessages) {
116 $this->init();
117 $records = $this->getRecordsFromTable('tt_content');
118 $this->checkPrerequisites();
119 foreach ($records as $singleRecord) {
120 $this->migrateRecord($singleRecord);
121 }
122 return TRUE;
123 }
124
125 /**
126 * Ensures a new folder "fileadmin/content_upload/" is available.
127 *
128 * @return void
129 */
130 protected function checkPrerequisites() {
131 if (!$this->storage->hasFolder(self::FOLDER_ContentUploads)) {
132 $this->storage->createFolder(self::FOLDER_ContentUploads, $this->storage->getRootLevelFolder());
133 }
134 }
135
136 /**
137 * Processes the actual transformation from CSV to sys_file_references
138 *
139 * @param array $record
140 * @return void
141 */
142 protected function migrateRecord(array $record) {
143 $collections = array();
144 if (trim($record['select_key'])) {
145 $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_file_collection', array(
146 'pid' => $record['pid'],
147 'title' => $record['select_key'],
148 'storage' => $this->storage->getUid(),
149 'folder' => ltrim('fileadmin/', $record['select_key'])
150 ));
151 $collections[] = $GLOBALS['TYPO3_DB']->sql_insert_id();
152 }
153 $files = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $record['media'], TRUE);
154 $descriptions = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode('
155 ', $record['imagecaption']);
156 $titleText = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode('
157 ', $record['titleText']);
158 $i = 0;
159 foreach ($files as $file) {
160 if (file_exists(PATH_site . 'uploads/media/' . $file)) {
161 \TYPO3\CMS\Core\Utility\GeneralUtility::upload_copy_move(PATH_site . 'uploads/media/' . $file, $this->targetDirectory . $file);
162 $fileObject = $this->storage->getFile(self::FOLDER_ContentUploads . '/' . $file);
163 $this->fileRepository->addToIndex($fileObject);
164 $dataArray = array(
165 'uid_local' => $fileObject->getUid(),
166 'tablenames' => 'tt_content',
167 'uid_foreign' => $record['uid'],
168 // the sys_file_reference record should always placed on the same page
169 // as the record to link to, see issue #46497
170 'pid' => $record['pid'],
171 'fieldname' => 'media',
172 'sorting_foreign' => $i
173 );
174 if (isset($descriptions[$i])) {
175 $dataArray['description'] = $descriptions[$i];
176 }
177 if (isset($titleText[$i])) {
178 $dataArray['alternative'] = $titleText[$i];
179 }
180 $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_file_reference', $dataArray);
181 unlink(PATH_site . 'uploads/media/' . $file);
182 }
183 $i++;
184 }
185 $this->cleanRecord($record, $i, $collections);
186 }
187
188 /**
189 * Removes the old fields from the database-record
190 *
191 * @param array $record
192 * @param integer $fileCount
193 * @param array $collectionUids
194 * @return void
195 */
196 protected function cleanRecord(array $record, $fileCount, array $collectionUids) {
197 $GLOBALS['TYPO3_DB']->exec_UPDATEquery('tt_content', 'uid = ' . $record['uid'], array(
198 'media' => $fileCount,
199 'imagecaption' => '',
200 'titleText' => '',
201 'altText' => '',
202 'select_key' => '',
203 'file_collections' => implode(',', $collectionUids)
204 ));
205 }
206
207 /**
208 * Retrieve every record which needs to be processed
209 *
210 * @return array
211 */
212 protected function getRecordsFromTable() {
213 $fields = implode(',', array('uid', 'pid', 'select_key', 'media', 'imagecaption', 'titleText'));
214 $records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows($fields, 'tt_content', 'media <> \'\' AND CAST(CAST(media AS DECIMAL) AS CHAR) <> media OR (CType = \'uploads\' AND select_key != \'\')');
215 return $records;
216 }
217
218 }
219
220
221 ?>