TYPO3 CMS  TYPO3_8-7
FileIndexRepository.php
Go to the documentation of this file.
1 <?php
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 
29 
39 {
43  protected $table = 'sys_file';
44 
50  protected $fields = [
51  'uid', 'pid', 'missing', 'type', 'storage', 'identifier', 'identifier_hash', 'extension',
52  'mime_type', 'name', 'sha1', 'size', 'creation_date', 'modification_date', 'folder_hash'
53  ];
54 
60  protected function getResourceFactory()
61  {
63  }
64 
70  public static function getInstance()
71  {
72  return GeneralUtility::makeInstance(self::class);
73  }
74 
81  public function findOneByCombinedIdentifier($combinedIdentifier)
82  {
83  list($storageUid, $identifier) = GeneralUtility::trimExplode(':', $combinedIdentifier, false, 2);
84  return $this->findOneByStorageUidAndIdentifier($storageUid, $identifier);
85  }
86 
93  public function findOneByUid($fileUid)
94  {
95  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
96  ->getQueryBuilderForTable($this->table);
97 
98  $row = $queryBuilder
99  ->select(...$this->fields)
100  ->from($this->table)
101  ->where(
102  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($fileUid, \PDO::PARAM_INT))
103  )
104  ->execute()
105  ->fetch();
106 
107  return is_array($row) ? $row : false;
108  }
109 
119  public function findOneByStorageUidAndIdentifier($storageUid, $identifier)
120  {
121  $identifierHash = $this->getResourceFactory()->getStorageObject($storageUid)->hashFileIdentifier($identifier);
122  return $this->findOneByStorageUidAndIdentifierHash($storageUid, $identifierHash);
123  }
124 
134  public function findOneByStorageUidAndIdentifierHash($storageUid, $identifierHash)
135  {
136  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
137  ->getQueryBuilderForTable($this->table);
138 
139  $row = $queryBuilder
140  ->select(...$this->fields)
141  ->from($this->table)
142  ->where(
143  $queryBuilder->expr()->eq('storage', $queryBuilder->createNamedParameter($storageUid, \PDO::PARAM_INT)),
144  $queryBuilder->expr()->eq('identifier_hash', $queryBuilder->createNamedParameter($identifierHash))
145  )
146  ->execute()
147  ->fetch();
148 
149  return is_array($row) ? $row : false;
150  }
151 
160  public function findOneByFileObject(FileInterface $fileObject)
161  {
162  $storageUid = $fileObject->getStorage()->getUid();
163  $identifierHash = $fileObject->getHashedIdentifier();
164  return $this->findOneByStorageUidAndIdentifierHash($storageUid, $identifierHash);
165  }
166 
174  public function findByContentHash($hash)
175  {
176  if (!preg_match('/^[0-9a-f]{40}$/i', $hash)) {
177  return [];
178  }
179 
180  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
181  ->getQueryBuilderForTable($this->table);
182 
183  $resultRows = $queryBuilder
184  ->select(...$this->fields)
185  ->from($this->table)
186  ->where(
187  $queryBuilder->expr()->eq('sha1', $queryBuilder->createNamedParameter($hash, \PDO::PARAM_STR))
188  )
189  ->execute()
190  ->fetchAll();
191 
192  return $resultRows;
193  }
194 
201  public function findByFolder(Folder $folder)
202  {
203  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
204  ->getQueryBuilderForTable($this->table);
205 
206  $result = $queryBuilder
207  ->select(...$this->fields)
208  ->from($this->table)
209  ->where(
210  $queryBuilder->expr()->eq(
211  'folder_hash',
212  $queryBuilder->createNamedParameter($folder->getHashedIdentifier(), \PDO::PARAM_STR)
213  ),
214  $queryBuilder->expr()->eq(
215  'storage',
216  $queryBuilder->createNamedParameter($folder->getStorage()->getUid(), \PDO::PARAM_INT)
217  )
218  )
219  ->execute();
220 
221  $resultRows = [];
222  while ($row = $result->fetch()) {
223  $resultRows[$row['identifier']] = $row;
224  }
225 
226  return $resultRows;
227  }
228 
237  public function findByFolders(array $folders, $includeMissing = true, $fileName = null)
238  {
239  $storageUids = [];
240  $folderIdentifiers = [];
241 
242  foreach ($folders as $folder) {
243  if (!$folder instanceof Folder) {
244  continue;
245  }
246 
247  $storageUids[] = (int)$folder->getStorage()->getUid();
248  $folderIdentifiers[] = $folder->getHashedIdentifier();
249  }
250 
251  $storageUids = array_unique($storageUids);
252  $folderIdentifiers = array_unique($folderIdentifiers);
253 
254  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
255 
256  $queryBuilder
257  ->select(...$this->fields)
258  ->from($this->table)
259  ->where(
260  $queryBuilder->expr()->in(
261  'folder_hash',
262  $queryBuilder->createNamedParameter($folderIdentifiers, Connection::PARAM_STR_ARRAY)
263  ),
264  $queryBuilder->expr()->in(
265  'storage',
266  $queryBuilder->createNamedParameter($storageUids, Connection::PARAM_INT_ARRAY)
267  )
268  );
269 
270  if (isset($fileName)) {
271  $nameParts = str_getcsv($fileName, ' ');
272  foreach ($nameParts as $part) {
273  $part = trim($part);
274  if ($part !== '') {
275  $queryBuilder->andWhere(
276  $queryBuilder->expr()->like(
277  'name',
278  $queryBuilder->createNamedParameter(
279  '%' . $queryBuilder->escapeLikeWildcards($part) . '%',
280  \PDO::PARAM_STR
281  )
282  )
283  );
284  }
285  }
286  }
287 
288  if (!$includeMissing) {
289  $queryBuilder->andWhere($queryBuilder->expr()->eq('missing', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)));
290  }
291 
292  $result = $queryBuilder->execute();
293 
294  $fileRecords = [];
295  while ($fileRecord = $result->fetch()) {
296  $fileRecords[$fileRecord['identifier']] = $fileRecord;
297  }
298 
299  return $fileRecords;
300  }
301 
307  public function add(File $file)
308  {
309  if ($this->hasIndexRecord($file)) {
310  $this->update($file);
311  if ($file->_getPropertyRaw('uid') === null) {
312  $file->updateProperties($this->findOneByFileObject($file));
313  }
314  } else {
315  $file->updateProperties(['uid' => $this->insertRecord($file->getProperties())]);
316  }
317  }
318 
325  public function addRaw(array $data)
326  {
327  $data['uid'] = $this->insertRecord($data);
328  return $data;
329  }
330 
338  protected function insertRecord(array $data)
339  {
340  $data = array_intersect_key($data, array_flip($this->fields));
341  $data['tstamp'] = time();
342  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->table);
343  $connection->insert(
344  $this->table,
345  $data
346  );
347  $data['uid'] = $connection->lastInsertId($this->table);
348  $this->updateRefIndex($data['uid']);
349  $this->emitRecordCreatedSignal($data);
350  return $data['uid'];
351  }
352 
359  public function hasIndexRecord(File $file)
360  {
361  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
362 
363  if ((int)$file->_getPropertyRaw('uid') > 0) {
364  $constraints = [
365  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($file->getUid(), \PDO::PARAM_INT))
366  ];
367  } else {
368  $constraints = [
369  $queryBuilder->expr()->eq(
370  'storage',
371  $queryBuilder->createNamedParameter($file->getStorage()->getUid(), \PDO::PARAM_INT)
372  ),
373  $queryBuilder->expr()->eq(
374  'identifier',
375  $queryBuilder->createNamedParameter($file->_getPropertyRaw('identifier'), \PDO::PARAM_STR)
376  )
377  ];
378  }
379 
380  $count = $queryBuilder
381  ->count('uid')
382  ->from($this->table)
383  ->where(...$constraints)
384  ->execute()
385  ->fetchColumn(0);
386 
387  return (bool)$count;
388  }
389 
395  public function update(File $file)
396  {
397  $updatedProperties = array_intersect($this->fields, $file->getUpdatedProperties());
398  $updateRow = [];
399  foreach ($updatedProperties as $key) {
400  $updateRow[$key] = $file->getProperty($key);
401  }
402  if (!empty($updateRow)) {
403  if ((int)$file->_getPropertyRaw('uid') > 0) {
404  $constraints = ['uid' => (int)$file->getUid()];
405  } else {
406  $constraints = [
407  'storage' => (int)$file->getStorage()->getUid(),
408  'identifier' => $file->_getPropertyRaw('identifier')
409  ];
410  }
411 
412  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->table);
413  $updateRow['tstamp'] = time();
414 
415  $connection->update(
416  $this->table,
417  $updateRow,
418  $constraints
419  );
420 
421  $this->updateRefIndex($file->getUid());
422  $this->emitRecordUpdatedSignal(array_intersect_key($file->getProperties(), array_flip($this->fields)));
423  }
424  }
425 
433  public function findInStorageWithIndexOutstanding(ResourceStorage $storage, $limit = -1)
434  {
435  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
436 
437  if ((int)$limit > 0) {
438  $queryBuilder->setMaxResults((int)$limit);
439  }
440 
441  $rows = $queryBuilder
442  ->select(...$this->fields)
443  ->from($this->table)
444  ->where(
445  $queryBuilder->expr()->gt('tstamp', $queryBuilder->quoteIdentifier('last_indexed')),
446  $queryBuilder->expr()->eq('storage', $queryBuilder->createNamedParameter($storage->getUid(), \PDO::PARAM_INT))
447  )
448  ->orderBy('tstamp', 'ASC')
449  ->execute()
450  ->fetchAll();
451 
452  return $rows;
453  }
454 
462  public function findInStorageAndNotInUidList(ResourceStorage $storage, array $uidList)
463  {
464  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
465 
466  $queryBuilder
467  ->select(...$this->fields)
468  ->from($this->table)
469  ->where(
470  $queryBuilder->expr()->eq(
471  'storage',
472  $queryBuilder->createNamedParameter($storage->getUid(), \PDO::PARAM_INT)
473  )
474  );
475 
476  if (!empty($uidList)) {
477  $queryBuilder->andWhere(
478  $queryBuilder->expr()->notIn(
479  'uid',
480  array_map('intval', $uidList)
481  )
482  );
483  }
484 
485  $rows = $queryBuilder->execute()->fetchAll();
486 
487  return $rows;
488  }
489 
495  public function updateIndexingTime($fileUid)
496  {
497  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->table);
498  $connection->update(
499  $this->table,
500  [
501  'last_indexed' => time()
502  ],
503  [
504  'uid' => (int)$fileUid
505  ]
506  );
507  }
508 
514  public function markFileAsMissing($fileUid)
515  {
516  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->table);
517  $connection->update(
518  $this->table,
519  [
520  'missing' => 1
521  ],
522  [
523  'uid' => (int)$fileUid
524  ]
525  );
526  $this->emitRecordMarkedAsMissingSignal($fileUid);
527  }
528 
534  public function remove($fileUid)
535  {
536  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->table);
537  $connection->delete(
538  $this->table,
539  [
540  'uid' => (int)$fileUid
541  ]
542  );
543  $this->updateRefIndex($fileUid);
544  $this->emitRecordDeletedSignal($fileUid);
545  }
546 
552  public function updateRefIndex($id)
553  {
555  $refIndexObj = GeneralUtility::makeInstance(ReferenceIndex::class);
556  $refIndexObj->updateRefIndexTable($this->table, $id);
557  }
558 
559  /*
560  * Get the SignalSlot dispatcher
561  *
562  * @return Dispatcher
563  */
564  protected function getSignalSlotDispatcher()
565  {
566  return $this->getObjectManager()->get(Dispatcher::class);
567  }
568 
574  protected function getObjectManager()
575  {
576  return GeneralUtility::makeInstance(ObjectManager::class);
577  }
578 
585  protected function emitRecordUpdatedSignal(array $data)
586  {
587  $this->getSignalSlotDispatcher()->dispatch(self::class, 'recordUpdated', [$data]);
588  }
589 
596  protected function emitRecordCreatedSignal(array $data)
597  {
598  $this->getSignalSlotDispatcher()->dispatch(self::class, 'recordCreated', [$data]);
599  }
600 
607  protected function emitRecordDeletedSignal($fileUid)
608  {
609  $this->getSignalSlotDispatcher()->dispatch(self::class, 'recordDeleted', [$fileUid]);
610  }
611 
618  protected function emitRecordMarkedAsMissingSignal($fileUid)
619  {
620  $this->getSignalSlotDispatcher()->dispatch(self::class, 'recordMarkedAsMissing', [$fileUid]);
621  }
622 }
findInStorageWithIndexOutstanding(ResourceStorage $storage, $limit=-1)
findByFolders(array $folders, $includeMissing=true, $fileName=null)
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
updateProperties(array $properties)
Definition: File.php:201
static makeInstance($className,... $constructorArguments)
findInStorageAndNotInUidList(ResourceStorage $storage, array $uidList)
findOneByStorageUidAndIdentifierHash($storageUid, $identifierHash)