TYPO3 CMS  TYPO3_6-2
TtContentUploadsUpdateWizard.php
Go to the documentation of this file.
1 <?php
3 
24 
25  const FOLDER_ContentUploads = '_migrated/content_uploads';
26 
30  protected $title = 'Migrate file relations of tt_content "uploads"';
31 
35  protected $targetDirectory;
36 
40  protected $fileFactory;
41 
46 
50  protected $storage;
51 
57  protected function init() {
58  $fileadminDirectory = rtrim($GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'], '/') . '/';
60  $storageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\StorageRepository');
61  $storages = $storageRepository->findAll();
62  foreach ($storages as $storage) {
63  $storageRecord = $storage->getStorageRecord();
64  $configuration = $storage->getConfiguration();
65  $isLocalDriver = $storageRecord['driver'] === 'Local';
66  $isOnFileadmin = !empty($configuration['basePath']) && \TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($configuration['basePath'], $fileadminDirectory);
67  if ($isLocalDriver && $isOnFileadmin) {
68  $this->storage = $storage;
69  break;
70  }
71  }
72  if (!isset($this->storage)) {
73  throw new \RuntimeException('Local default storage could not be initialized - might be due to missing sys_file* tables.');
74  }
75  $this->fileFactory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\ResourceFactory');
76  $this->fileIndexRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\Index\\FileIndexRepository');
77  $this->targetDirectory = PATH_site . $fileadminDirectory . self::FOLDER_ContentUploads . '/';
78  }
79 
86  public function checkForUpdate(&$description) {
87  $updateNeeded = FALSE;
88  // Fetch records where the field media does not contain a plain integer value
89  // * check whether media field is not empty
90  // * then check whether media field does not contain a reference count (= not integer)
91  $mapping = $this->getTableColumnMapping();
92  $sql = $GLOBALS['TYPO3_DB']->SELECTquery(
93  'COUNT(' . $mapping['mapFieldNames']['uid'] . ')',
94  $mapping['mapTableName'],
95  '1=1'
96  );
97  $whereClause = $this->getDbalCompliantUpdateWhereClause();
98  $sql = str_replace('WHERE 1=1', $whereClause, $sql);
99  $resultSet = $GLOBALS['TYPO3_DB']->sql_query($sql);
100  $notMigratedRowsCount = 0;
101  if ($resultSet !== FALSE) {
102  list($notMigratedRowsCount) = $GLOBALS['TYPO3_DB']->sql_fetch_row($resultSet);
103  $notMigratedRowsCount = (int)$notMigratedRowsCount;
104  $GLOBALS['TYPO3_DB']->sql_free_result($resultSet);
105  }
106  if ($notMigratedRowsCount > 0) {
107  $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.';
108  $updateNeeded = TRUE;
109  }
110  return $updateNeeded;
111  }
112 
120  public function performUpdate(array &$dbQueries, &$customMessages) {
121  $this->init();
122  $records = $this->getRecordsFromTable('tt_content');
123  $this->checkPrerequisites();
124  foreach ($records as $singleRecord) {
125  $this->migrateRecord($singleRecord);
126  }
127  return TRUE;
128  }
129 
135  protected function checkPrerequisites() {
136  if (!$this->storage->hasFolder(self::FOLDER_ContentUploads)) {
137  $this->storage->createFolder(self::FOLDER_ContentUploads, $this->storage->getRootLevelFolder());
138  }
139  }
140 
147  protected function migrateRecord(array $record) {
148  $collections = array();
149  if (trim($record['select_key'])) {
150  $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_file_collection', array(
151  'pid' => $record['pid'],
152  'title' => $record['select_key'],
153  'storage' => $this->storage->getUid(),
154  'folder' => ltrim('fileadmin/', $record['select_key'])
155  ));
156  $collections[] = $GLOBALS['TYPO3_DB']->sql_insert_id();
157  }
158  $files = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $record['media'], TRUE);
160 ', $record['imagecaption']);
162 ', $record['titleText']);
163  $i = 0;
164  foreach ($files as $file) {
165  if (file_exists(PATH_site . 'uploads/media/' . $file)) {
166  \TYPO3\CMS\Core\Utility\GeneralUtility::upload_copy_move(PATH_site . 'uploads/media/' . $file, $this->targetDirectory . $file);
167  $fileObject = $this->storage->getFile(self::FOLDER_ContentUploads . '/' . $file);
168  $this->fileIndexRepository->add($fileObject);
169  $dataArray = array(
170  'uid_local' => $fileObject->getUid(),
171  'tablenames' => 'tt_content',
172  'uid_foreign' => $record['uid'],
173  // the sys_file_reference record should always placed on the same page
174  // as the record to link to, see issue #46497
175  'pid' => $record['pid'],
176  'fieldname' => 'media',
177  'sorting_foreign' => $i
178  );
179  if (isset($descriptions[$i])) {
180  $dataArray['description'] = $descriptions[$i];
181  }
182  if (isset($titleText[$i])) {
183  $dataArray['alternative'] = $titleText[$i];
184  }
185  $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_file_reference', $dataArray);
186  unlink(PATH_site . 'uploads/media/' . $file);
187  }
188  $i++;
189  }
190  $this->cleanRecord($record, $i, $collections);
191  }
192 
201  protected function cleanRecord(array $record, $fileCount, array $collectionUids) {
202  $GLOBALS['TYPO3_DB']->exec_UPDATEquery('tt_content', 'uid = ' . $record['uid'], array(
203  'media' => $fileCount,
204  'imagecaption' => '',
205  'titleText' => '',
206  'altText' => '',
207  'select_key' => '',
208  'file_collections' => implode(',', $collectionUids)
209  ));
210  }
211 
217  protected function getRecordsFromTable() {
218  $mapping = $this->getTableColumnMapping();
219  $reverseFieldMapping = array_flip($mapping['mapFieldNames']);
220 
221  $fields = array();
222  foreach (array('uid', 'pid', 'select_key', 'media', 'imagecaption', 'titleText') as $columnName) {
223  $fields[] = $mapping['mapFieldNames'][$columnName];
224  }
225  $fields = implode(',', $fields);
226 
227  $sql = $GLOBALS['TYPO3_DB']->SELECTquery(
228  $fields,
229  $mapping['mapTableName'],
230  '1=1'
231  );
232  $whereClause = $this->getDbalCompliantUpdateWhereClause();
233  $sql = str_replace('WHERE 1=1', $whereClause, $sql);
234  $resultSet = $GLOBALS['TYPO3_DB']->sql_query($sql);
235  $records = array();
236  if (!$GLOBALS['TYPO3_DB']->sql_error()) {
237  while (($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($resultSet)) !== FALSE) {
238  // Mapping back column names to native TYPO3 names
239  $record = array();
240  foreach ($reverseFieldMapping as $columnName => $finalColumnName) {
241  $record[$finalColumnName] = $row[$columnName];
242  }
243  $records[] = $record;
244  }
245  $GLOBALS['TYPO3_DB']->sql_free_result($resultSet);
246  }
247  return $records;
248  }
249 
258  protected function getDbalCompliantUpdateWhereClause() {
259  $mapping = $this->getTableColumnMapping();
260  $this->quoteIdentifiers($mapping);
261 
262  $where = sprintf(
263  'WHERE %s <> \'\' AND CAST(CAST(%s AS DECIMAL) AS CHAR) <> CAST(%s AS CHAR) OR (%s = \'uploads\' AND %s != \'\')',
264  $mapping['mapFieldNames']['media'],
265  $mapping['mapFieldNames']['media'],
266  $mapping['mapFieldNames']['media'],
267  $mapping['mapFieldNames']['CType'],
268  $mapping['mapFieldNames']['select_key']
269  );
270 
271  return $where;
272  }
273 
279  protected function getTableColumnMapping() {
280  $mapping = array(
281  'mapTableName' => 'tt_content',
282  'mapFieldNames' => array(
283  'uid' => 'uid',
284  'pid' => 'pid',
285  'media' => 'media',
286  'imagecaption' => 'imagecaption',
287  'titleText' => 'titleText',
288  'CType' => 'CType',
289  'select_key' => 'select_key',
290  )
291  );
292 
293  if ($GLOBALS['TYPO3_DB'] instanceof \TYPO3\CMS\Dbal\Database\DatabaseConnection) {
294  if (!empty($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['dbal']['mapping']['tt_content'])) {
295  $mapping = array_merge_recursive($mapping, $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['dbal']['mapping']['tt_content']);
296  }
297  }
298 
299  return $mapping;
300  }
301 
308  protected function quoteIdentifiers(array &$mapping) {
309  if ($GLOBALS['TYPO3_DB'] instanceof \TYPO3\CMS\Dbal\Database\DatabaseConnection) {
310  if (!$GLOBALS['TYPO3_DB']->runningNative() && !$GLOBALS['TYPO3_DB']->runningADOdbDriver('mysql')) {
311  $mapping['mapTableName'] = '"' . $mapping['mapTableName'] . '"';
312  foreach ($mapping['mapFieldNames'] as $key => &$value) {
313  $value = '"' . $value . '"';
314  }
315  }
316  }
317  }
318 
319 }
$sql
Definition: server.php:82
static isFirstPartOfStr($str, $partStr)
static trimExplode($delim, $string, $removeEmptyValues=FALSE, $limit=0)
cleanRecord(array $record, $fileCount, array $collectionUids)
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
static upload_copy_move($source, $destination)