2 namespace TYPO3\CMS\Install\Updates
;
4 /***************************************************************
7 * (c) 2011 Ingmar Schlecht <ingmar@typo3.org>
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.
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
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.
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
27 * Upgrade wizard which goes through all files referenced in the tt_content.image filed
28 * and creates sys_file records as well as sys_file_reference records for the individual usages.
30 * @author Ingmar Schlecht <ingmar@typo3.org>
31 * @license http://www.gnu.org/copyleft/gpl.html
33 use TYPO3\CMS\Core\Utility\GeneralUtility
;
36 * Updates TCEform references from direct file relations to FAL.
38 class TceformsUpdateWizard
extends \TYPO3\CMS\Install\Updates\AbstractUpdate
{
43 protected $title = 'Migrate all file relations from tt_content.image and pages.media';
46 * @var \TYPO3\CMS\Core\Resource\ResourceStorage
51 * @var \TYPO3\CMS\Core\Log\Logger
55 public function __construct() {
56 /** @var $logManager \TYPO3\CMS\Core\Log\LogManager */
57 $logManager = \TYPO3\CMS\Core\Utility\GeneralUtility
::makeInstance('TYPO3\\CMS\\Core\\Log\\LogManager');
58 $this->logger
= $logManager->getLogger(__CLASS__
);
62 * Initialize the storage repository.
64 public function init() {
65 /** @var $storageRepository \TYPO3\CMS\Core\Resource\StorageRepository */
66 $storageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility
::makeInstance('TYPO3\\CMS\\Core\\Resource\\StorageRepository');
67 $storages = $storageRepository->findAll();
68 $this->storage
= $storages[0];
72 * Checks if an update is needed
74 * @param string &$description: The description for the update
75 * @return boolean TRUE if an update is needed, FALSE otherwise
77 public function checkForUpdate(&$description) {
78 $description = 'This update wizard goes through all files that are referenced in the tt_content.image and pages.media / pages_language_overlay.media filed and adds the files to the new File Index.<br />It also moves the files from uploads/ to the fileadmin/_migrated/ path.<br /><br />This update wizard can be called multiple times in case it didn\'t finish after running once.';
79 // make this wizard always available
84 * Performs the database update.
86 * @param array &$dbQueries: queries done in this update
87 * @param mixed &$customMessages: custom messages
88 * @return boolean TRUE on success, FALSE on error
90 public function performUpdate(array &$dbQueries, &$customMessages) {
92 // Function below copied from sysext/install/updates/class.tx_coreupdates_imagelink.php
94 'tt_content' => array(
96 'sourcePath' => 'uploads/pics/',
97 // Relative to fileadmin
98 'targetPath' => '_migrated/pics/',
99 'titleTexts' => 'titleText',
100 'captions' => 'imagecaption',
101 'links' => 'image_link',
102 'alternativeTexts' => 'altText'
107 'sourcePath' => 'uploads/media/',
108 // Relative to fileadmin
109 'targetPath' => '_migrated/media/'
112 'pages_language_overlay' => array(
114 'sourcePath' => 'uploads/media/',
115 // Relative to fileadmin
116 'targetPath' => '_migrated/media/'
120 // We write down the fields that were migrated. Like this: tt_content:media
121 // so you can check whether a field was already migrated
122 if (isset($GLOBALS['TYPO3_CONF_VARS']['INSTALL']['wizardDone']['Tx_Install_Updates_File_TceformsUpdateWizard'])) {
123 $finishedFields = explode(',', $GLOBALS['TYPO3_CONF_VARS']['INSTALL']['wizardDone']['Tx_Install_Updates_File_TceformsUpdateWizard']);
125 $finishedFields = array();
128 if ($this->versionNumber
>= 6000000) {
131 // - get records from table
132 // - for each record:
135 foreach ($tables as $table => $tableConfiguration) {
136 $fieldsToMigrate = array_keys($tableConfiguration);
137 $fieldsToGet = array();
138 // find all additional fields we should get from the database
139 foreach ($tableConfiguration as $field => $fieldConfiguration) {
140 $fieldKey = $table . ':' . $field;
141 if (array_search($fieldKey, $finishedFields) !== FALSE
) {
142 // this field was already migrated
145 $finishedFields[] = $fieldKey;
147 $fieldsToGet[] = $field;
148 if (isset($fieldConfiguration['titleTexts'])) {
149 $fieldsToGet[] = $fieldConfiguration['titleTexts'];
151 if (isset($fieldConfiguration['alternativeTexts'])) {
152 $fieldsToGet[] = $fieldConfiguration['alternativeTexts'];
154 if (isset($fieldConfiguration['captions'])) {
155 $fieldsToGet[] = $fieldConfiguration['captions'];
157 if (isset($fieldConfiguration['links'])) {
158 $fieldsToGet[] = $fieldConfiguration['links'];
161 $records = $this->getRecordsFromTable($table, $fieldsToGet);
162 foreach ($records as $record) {
163 foreach ($fieldsToMigrate as $field) {
164 $dbQueries = array_merge($this->migrateField($table, $record, $field, $tableConfiguration[$field], $customMessages));
169 $finishedFields = implode(',', $finishedFields);
170 $this->markWizardAsDone($finishedFields);
174 protected function getRecordsFromTable($table, $relationFields) {
175 $fields = implode(',', array_merge($relationFields, array('uid', 'pid')));
176 $records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows($fields, $table, '');
181 * Migrates a single field.
183 * @param string $table
185 * @param string $fieldname
186 * @param array $fieldConfiguration
187 * @param string $customMessages
188 * @return array A list of performed database queries
191 protected function migrateField($table, $row, $fieldname, $fieldConfiguration, &$customMessages) {
192 $fieldItems = \TYPO3\CMS\Core\Utility\GeneralUtility
::trimExplode(',', $row[$fieldname], TRUE
);
193 if (empty($fieldItems) ||
is_numeric($row[$fieldname])) {
196 if (isset($fieldConfiguration['titleTexts'])) {
197 $titleTextField = $fieldConfiguration['titleTexts'];
198 $titleTextContents = explode(LF
, $row[$titleTextField]);
200 if (isset($fieldConfiguration['alternativeTexts'])) {
201 $alternativeTextField = $fieldConfiguration['alternativeTexts'];
202 $alternativeTextContents = explode(LF
, $row[$alternativeTextField]);
204 if (isset($fieldConfiguration['captions'])) {
205 $captionField = $fieldConfiguration['captions'];
206 $captionContents = explode(LF
, $row[$captionField]);
208 if (isset($fieldConfiguration['links'])) {
209 $linkField = $fieldConfiguration['links'];
210 $linkContents = explode(LF
, $row[$linkField]);
212 $fileadminDirectory = rtrim($GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'], '/') . '/';
215 foreach ($fieldItems as $item) {
217 throw new \
Exception('PATH_site was undefined.');
220 $sourcePath = PATH_site
. $fieldConfiguration['sourcePath'] . $item;
221 $targetPath = PATH_site
. $fileadminDirectory . $fieldConfiguration['targetPath'] . $item;
223 // if the source file does not exist, we should just continue, but leave a message in the docs;
224 // ideally, the user would be informed after the update as well.
225 if (!file_exists($sourcePath)) {
226 $this->logger
->notice('File ' . $fieldConfiguration['sourcePath'] . $item . ' does not exist. Reference was not migrated.', array('table' => $table, 'record' => $row, 'field' => $fieldname));
228 $format = 'File \'%s\' does not exist. Referencing field: %s.%d.%s. The reference was not migrated.';
229 $message = \TYPO3\CMS\Core\Utility\GeneralUtility
::makeInstance('\TYPO3\CMS\Core\Messaging\FlashMessage',
230 sprintf($format, $fieldConfiguration['sourcePath'] . $item, $table, $row['uid'], $fieldname),
231 '', \TYPO3\CMS\Core\Messaging\FlashMessage
::WARNING
233 /** @var \TYPO3\CMS\Core\Messaging\FlashMessage $message */
234 $customMessages .= '<br />' . $message->render();
239 if (!is_dir(dirname($targetPath))) {
240 \TYPO3\CMS\Core\Utility\GeneralUtility
::mkdir_deep(dirname($targetPath));
242 rename($sourcePath, $targetPath);
243 // get the File object
244 $file = $this->storage
->getFile($fieldConfiguration['targetPath'] . $item);
245 if ($file instanceof \TYPO3\CMS\Core\Resource\File
) {
247 // TODO add sorting/sorting_foreign
248 'fieldname' => $fieldname,
249 'table_local' => 'sys_file',
250 'uid_foreign' => $row['uid'],
251 'uid_local' => $file->getUid(),
252 'tablenames' => $table,
256 if (isset($titleTextField)) {
257 $fields['title'] = trim($titleTextContents[$i]);
259 if (isset($alternativeTextField)) {
260 $fields['alternative'] = trim($alternativeTextContents[$i]);
262 if (isset($captionField)) {
263 $fields['description'] = trim($captionContents[$i]);
265 if (isset($linkField)) {
266 $fields['link'] = trim($linkContents[$i]);
268 $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_file_reference', $fields);
269 $queries[] = str_replace(LF
, ' ', $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery
);
273 // Update referencing table's original field to now contain the count of references.
274 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid=' . $row['uid'], array($fieldname => $i));
275 $queries[] = str_replace(LF
, ' ', $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery
);