TYPO3  7.6
FileIndexRepository.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Core\Resource\Index;
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 
21 
31 {
35  protected $table = 'sys_file';
36 
42  protected $fields = array(
43  'uid', 'pid', 'missing', 'type', 'storage', 'identifier', 'identifier_hash', 'extension',
44  'mime_type', 'name', 'sha1', 'size', 'creation_date', 'modification_date', 'folder_hash'
45  );
46 
52  protected function getDatabaseConnection()
53  {
54  return $GLOBALS['TYPO3_DB'];
55  }
56 
62  protected function getResourceFactory()
63  {
64  return \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance();
65  }
66 
67 
73  public static function getInstance()
74  {
75  return GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\Index\FileIndexRepository::class);
76  }
77 
84  public function findOneByCombinedIdentifier($combinedIdentifier)
85  {
86  list($storageUid, $identifier) = GeneralUtility::trimExplode(':', $combinedIdentifier, false, 2);
87  return $this->findOneByStorageUidAndIdentifier($storageUid, $identifier);
88  }
89 
96  public function findOneByUid($fileUid)
97  {
98  $row = $this->getDatabaseConnection()->exec_SELECTgetSingleRow(
99  implode(',', $this->fields),
100  $this->table,
101  'uid=' . (int)$fileUid
102  );
103  return is_array($row) ? $row : false;
104  }
105 
115  public function findOneByStorageUidAndIdentifier($storageUid, $identifier)
116  {
117  $identifierHash = $this->getResourceFactory()->getStorageObject($storageUid)->hashFileIdentifier($identifier);
118  return $this->findOneByStorageUidAndIdentifierHash($storageUid, $identifierHash);
119  }
120 
130  public function findOneByStorageUidAndIdentifierHash($storageUid, $identifierHash)
131  {
132  $row = $this->getDatabaseConnection()->exec_SELECTgetSingleRow(
133  implode(',', $this->fields),
134  $this->table,
135  sprintf('storage=%u AND identifier_hash=%s', (int)$storageUid, $this->getDatabaseConnection()->fullQuoteStr($identifierHash, $this->table))
136  );
137  return is_array($row) ? $row : false;
138  }
139 
148  public function findOneByFileObject(\TYPO3\CMS\Core\Resource\FileInterface $fileObject)
149  {
150  $storageUid = $fileObject->getStorage()->getUid();
151  $identifierHash = $fileObject->getHashedIdentifier();
152  return $this->findOneByStorageUidAndIdentifierHash($storageUid, $identifierHash);
153  }
154 
162  public function findByContentHash($hash)
163  {
164  if (!preg_match('/^[0-9a-f]{40}$/i', $hash)) {
165  return array();
166  }
167  $resultRows = $this->getDatabaseConnection()->exec_SELECTgetRows(
168  implode(',', $this->fields),
169  $this->table,
170  'sha1=' . $this->getDatabaseConnection()->fullQuoteStr($hash, $this->table)
171  );
172  return $resultRows;
173  }
174 
181  public function findByFolder(\TYPO3\CMS\Core\Resource\Folder $folder)
182  {
183  $resultRows = $this->getDatabaseConnection()->exec_SELECTgetRows(
184  implode(',', $this->fields),
185  $this->table,
186  'folder_hash = ' . $this->getDatabaseConnection()->fullQuoteStr($folder->getHashedIdentifier(), $this->table) .
187  ' AND storage = ' . (int)$folder->getStorage()->getUid(),
188  '',
189  '',
190  '',
191  'identifier'
192  );
193  return $resultRows;
194  }
195 
203  public function findByFolders(array $folders, $includeMissing = true)
204  {
205  $storageUids = [];
206  $folderIdentifiers = [];
207 
208  foreach ($folders as $folder) {
209  if (!$folder instanceof \TYPO3\CMS\Core\Resource\Folder) {
210  continue;
211  }
212 
213  $storageUids[] = (int)$folder->getStorage()->getUid();
214  $folderIdentifiers[] = $folder->getHashedIdentifier();
215  }
216  $storageUids = array_unique($storageUids);
217  $folderIdentifiers = array_unique($folderIdentifiers);
218 
219  $fileRecords = $this->getDatabaseConnection()->exec_SELECTgetRows(
220  implode(',', $this->fields),
221  $this->table,
222  'folder_hash IN ( ' . implode(',', $this->getDatabaseConnection()->fullQuoteArray($folderIdentifiers, $this->table)) . ')' .
223  ' AND storage IN (' . implode(',', $storageUids) . ')' .
224  ($includeMissing ? '' : ' AND missing = 0'),
225  '',
226  '',
227  '',
228  'identifier'
229  );
230 
231  return $fileRecords;
232  }
233 
240  public function add(File $file)
241  {
242  if ($this->hasIndexRecord($file)) {
243  $this->update($file);
244  if ($file->_getPropertyRaw('uid') === null) {
245  $file->updateProperties($this->findOneByFileObject($file));
246  }
247  } else {
248  $file->updateProperties(array('uid' => $this->insertRecord($file->getProperties())));
249  }
250  }
251 
258  public function addRaw(array $data)
259  {
260  $data['uid'] = $this->insertRecord($data);
261  return $data;
262  }
263 
271  protected function insertRecord(array $data)
272  {
273  $data = array_intersect_key($data, array_flip($this->fields));
274  $data['tstamp'] = time();
275  $this->getDatabaseConnection()->exec_INSERTquery($this->table, $data);
276  $data['uid'] = $this->getDatabaseConnection()->sql_insert_id();
277  $this->updateRefIndex($data['uid']);
278  $this->emitRecordCreatedSignal($data);
279  return $data['uid'];
280  }
287  public function hasIndexRecord(File $file)
288  {
289  return $this->getDatabaseConnection()->exec_SELECTcountRows('uid', $this->table, $this->getWhereClauseForFile($file)) >= 1;
290  }
291 
298  public function update(File $file)
299  {
300  $updatedProperties = array_intersect($this->fields, $file->getUpdatedProperties());
301  $updateRow = array();
302  foreach ($updatedProperties as $key) {
303  $updateRow[$key] = $file->getProperty($key);
304  }
305  if (!empty($updateRow)) {
306  $updateRow['tstamp'] = time();
307  $this->getDatabaseConnection()->exec_UPDATEquery($this->table, $this->getWhereClauseForFile($file), $updateRow);
308  $this->updateRefIndex($file->getUid());
309  $this->emitRecordUpdatedSignal(array_intersect_key($file->getProperties(), array_flip($this->fields)));
310  }
311  }
312 
320  public function findInStorageWithIndexOutstanding(\TYPO3\CMS\Core\Resource\ResourceStorage $storage, $limit = -1)
321  {
322  return $this->getDatabaseConnection()->exec_SELECTgetRows(
323  implode(',', $this->fields),
324  $this->table,
325  'tstamp > last_indexed AND storage = ' . (int)$storage->getUid(),
326  '',
327  'tstamp ASC',
328  (int)$limit > 0 ? (int)$limit : ''
329  );
330  }
331 
332 
340  public function findInStorageAndNotInUidList(\TYPO3\CMS\Core\Resource\ResourceStorage $storage, array $uidList)
341  {
342  $where = 'storage = ' . (int)$storage->getUid();
343  if (!empty($uidList)) {
344  $where .= ' AND uid NOT IN (' . implode(',', $this->getDatabaseConnection()->cleanIntArray($uidList)) . ')';
345  }
346  return $this->getDatabaseConnection()->exec_SELECTgetRows(implode(',', $this->fields), $this->table, $where);
347  }
348 
355  public function updateIndexingTime($fileUid)
356  {
357  $this->getDatabaseConnection()->exec_UPDATEquery($this->table, 'uid = ' . (int)$fileUid, array('last_indexed' => time()));
358  }
359 
366  public function markFileAsMissing($fileUid)
367  {
368  $this->getDatabaseConnection()->exec_UPDATEquery($this->table, 'uid = ' . (int)$fileUid, array('missing' => 1));
369  $this->emitRecordMarkedAsMissingSignal($fileUid);
370  }
371 
379  protected function getWhereClauseForFile(File $file)
380  {
381  if ((int)$file->_getPropertyRaw('uid') > 0) {
382  $where = 'uid=' . (int)$file->getUid();
383  } else {
384  $where = sprintf(
385  'storage=%u AND identifier LIKE %s',
386  (int)$file->getStorage()->getUid(),
387  $this->getDatabaseConnection()->fullQuoteStr($file->_getPropertyRaw('identifier'), $this->table)
388  );
389  }
390  return $where;
391  }
392 
399  public function remove($fileUid)
400  {
401  $this->getDatabaseConnection()->exec_DELETEquery($this->table, 'uid=' . (int)$fileUid);
402  $this->updateRefIndex($fileUid);
403  $this->emitRecordDeletedSignal($fileUid);
404  }
405 
406 
413  public function updateRefIndex($id)
414  {
416  $refIndexObj = GeneralUtility::makeInstance(ReferenceIndex::class);
417  $refIndexObj->updateRefIndexTable($this->table, $id);
418  }
419 
420 
421  /*
422  * Get the SignalSlot dispatcher
423  *
424  * @return \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
425  */
426  protected function getSignalSlotDispatcher()
427  {
428  return $this->getObjectManager()->get(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class);
429  }
430 
436  protected function getObjectManager()
437  {
438  return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
439  }
440 
441 
442 
449  protected function emitRecordUpdatedSignal(array $data)
450  {
451  $this->getSignalSlotDispatcher()->dispatch(\TYPO3\CMS\Core\Resource\Index\FileIndexRepository::class, 'recordUpdated', array($data));
452  }
453 
460  protected function emitRecordCreatedSignal(array $data)
461  {
462  $this->getSignalSlotDispatcher()->dispatch(\TYPO3\CMS\Core\Resource\Index\FileIndexRepository::class, 'recordCreated', array($data));
463  }
464 
471  protected function emitRecordDeletedSignal($fileUid)
472  {
473  $this->getSignalSlotDispatcher()->dispatch(\TYPO3\CMS\Core\Resource\Index\FileIndexRepository::class, 'recordDeleted', array($fileUid));
474  }
475 
482  protected function emitRecordMarkedAsMissingSignal($fileUid)
483  {
484  $this->getSignalSlotDispatcher()->dispatch(\TYPO3\CMS\Core\Resource\Index\FileIndexRepository::class, 'recordMarkedAsMissing', array($fileUid));
485  }
486 }