‪TYPO3CMS  ‪main
FileIndexRepository.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\EventDispatcher\EventDispatcherInterface;
34 
44 {
48  protected ‪$table = 'sys_file';
49 
53  protected ‪$eventDispatcher;
54 
60  protected ‪$fields = [
61  'uid', 'pid', 'missing', 'type', 'storage', 'identifier', 'identifier_hash', 'extension',
62  'mime_type', 'name', 'sha1', 'size', 'creation_date', 'modification_date', 'folder_hash',
63  ];
64 
65  public function ‪__construct(EventDispatcherInterface ‪$eventDispatcher)
66  {
67  $this->eventDispatcher = ‪$eventDispatcher;
68  }
69 
76  public function ‪findOneByUid($fileUid)
77  {
78  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
79  ->getQueryBuilderForTable($this->table);
80 
81  $row = $queryBuilder
82  ->select(...$this->fields)
83  ->from($this->table)
84  ->where(
85  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($fileUid, ‪Connection::PARAM_INT))
86  )
87  ->executeQuery()
88  ->fetchAssociative();
89 
90  return is_array($row) ? $row : false;
91  }
92 
102  public function ‪findOneByStorageUidAndIdentifierHash($storageUid, $identifierHash)
103  {
104  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
105  ->getQueryBuilderForTable($this->table);
106 
107  $row = $queryBuilder
108  ->select(...$this->fields)
109  ->from($this->table)
110  ->where(
111  $queryBuilder->expr()->eq('storage', $queryBuilder->createNamedParameter($storageUid, ‪Connection::PARAM_INT)),
112  $queryBuilder->expr()->eq('identifier_hash', $queryBuilder->createNamedParameter($identifierHash))
113  )
114  ->executeQuery()
115  ->fetchAssociative();
116 
117  return is_array($row) ? $row : false;
118  }
119 
127  public function ‪findOneByStorageAndIdentifier(ResourceStorage $storage, ‪$identifier)
128  {
129  $identifierHash = $storage->hashFileIdentifier(‪$identifier);
130  return $this->‪findOneByStorageUidAndIdentifierHash($storage->getUid(), $identifierHash);
131  }
132 
139  public function ‪findOneByFileObject(FileInterface $fileObject)
140  {
141  return $this->‪findOneByStorageAndIdentifier($fileObject->getStorage(), $fileObject->getIdentifier());
142  }
143 
151  public function ‪findByContentHash($hash)
152  {
153  if (!preg_match('/^[0-9a-f]{40}$/i', $hash)) {
154  return [];
155  }
156 
157  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
158  ->getQueryBuilderForTable($this->table);
159 
160  $resultRows = $queryBuilder
161  ->select(...$this->fields)
162  ->from($this->table)
163  ->where(
164  $queryBuilder->expr()->eq('sha1', $queryBuilder->createNamedParameter($hash))
165  )
166  ->executeQuery()
167  ->fetchAllAssociative();
168 
169  return $resultRows;
170  }
171 
177  public function ‪findByFolder(Folder $folder)
178  {
179  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
180  ->getQueryBuilderForTable($this->table);
181 
182  $result = $queryBuilder
183  ->select(...$this->fields)
184  ->from($this->table)
185  ->where(
186  $queryBuilder->expr()->eq(
187  'folder_hash',
188  $queryBuilder->createNamedParameter($folder->getHashedIdentifier())
189  ),
190  $queryBuilder->expr()->eq(
191  'storage',
192  $queryBuilder->createNamedParameter($folder->getStorage()->getUid(), ‪Connection::PARAM_INT)
193  )
194  )
195  ->executeQuery();
196 
197  $resultRows = [];
198  while ($row = $result->fetchAssociative()) {
199  $resultRows[$row['identifier']] = $row;
200  }
201 
202  return $resultRows;
203  }
204 
213  public function ‪findByFolders(array $folders, $includeMissing = true, $fileName = null)
214  {
215  $storageUids = [];
216  $folderIdentifiers = [];
217 
218  foreach ($folders as $folder) {
219  if (!$folder instanceof Folder) {
220  continue;
221  }
222 
223  $storageUids[] = (int)$folder->getStorage()->getUid();
224  $folderIdentifiers[] = $folder->getHashedIdentifier();
225  }
226 
227  $storageUids = array_unique($storageUids);
228  $folderIdentifiers = array_unique($folderIdentifiers);
229 
230  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
231 
232  $queryBuilder
233  ->select(...$this->fields)
234  ->from($this->table)
235  ->where(
236  $queryBuilder->expr()->in(
237  'folder_hash',
238  $queryBuilder->createNamedParameter($folderIdentifiers, ‪Connection::PARAM_STR_ARRAY)
239  ),
240  $queryBuilder->expr()->in(
241  'storage',
242  $queryBuilder->createNamedParameter($storageUids, ‪Connection::PARAM_INT_ARRAY)
243  )
244  );
245 
246  if (isset($fileName)) {
247  $nameParts = str_getcsv($fileName, ' ');
248  foreach ($nameParts as $part) {
249  $part = trim($part);
250  if ($part !== '') {
251  $queryBuilder->andWhere(
252  $queryBuilder->expr()->like(
253  'name',
254  $queryBuilder->createNamedParameter(
255  '%' . $queryBuilder->escapeLikeWildcards($part) . '%'
256  )
257  )
258  );
259  }
260  }
261  }
262 
263  if (!$includeMissing) {
264  $queryBuilder->andWhere($queryBuilder->expr()->eq('missing', $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)));
265  }
266 
267  $result = $queryBuilder->executeQuery();
268 
269  $fileRecords = [];
270  while ($fileRecord = $result->fetchAssociative()) {
271  $fileRecords[$fileRecord['identifier']] = $fileRecord;
272  }
273 
274  return $fileRecords;
275  }
276 
280  public function ‪add(File $file)
281  {
282  if ($this->‪hasIndexRecord($file)) {
283  $this->‪update($file);
284  if ($file->_getPropertyRaw('uid') === null) {
285  $file->updateProperties($this->‪findOneByFileObject($file));
286  }
287  } else {
288  $file->updateProperties(['uid' => $this->‪insertRecord($file->getProperties())]);
289  }
290  }
291 
297  public function ‪addRaw(array $data)
298  {
299  $data['uid'] = $this->‪insertRecord($data);
300  return $data;
301  }
302 
306  protected function ‪insertRecord(array $data): int
307  {
308  $data = array_intersect_key($data, array_flip($this->fields));
309  $data['tstamp'] = time();
310  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->table);
311  $connection->insert(
312  $this->table,
313  $data
314  );
315  $data['uid'] = (int)$connection->lastInsertId();
316  $this->‪updateRefIndex($data['uid']);
317  $this->eventDispatcher->dispatch(new AfterFileAddedToIndexEvent($data['uid'], $data));
318  return $data['uid'];
319  }
320 
326  public function ‪hasIndexRecord(File $file)
327  {
328  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
329 
330  if ((int)$file->_getPropertyRaw('uid') > 0) {
331  $constraints = [
332  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($file->getUid(), ‪Connection::PARAM_INT)),
333  ];
334  } else {
335  $constraints = [
336  $queryBuilder->expr()->eq(
337  'storage',
338  $queryBuilder->createNamedParameter($file->getStorage()->getUid(), ‪Connection::PARAM_INT)
339  ),
340  $queryBuilder->expr()->eq(
341  'identifier',
342  $queryBuilder->createNamedParameter($file->_getPropertyRaw('identifier'))
343  ),
344  ];
345  }
346 
347  $count = $queryBuilder
348  ->count('uid')
349  ->from($this->table)
350  ->where(...$constraints)
351  ->executeQuery()
352  ->fetchOne();
353 
354  return (bool)$count;
355  }
356 
360  public function ‪update(File $file)
361  {
362  $updatedProperties = array_intersect($this->fields, $file->getUpdatedProperties());
363  $updateRow = [];
364  foreach ($updatedProperties as $key) {
365  $updateRow[$key] = $file->getProperty($key);
366  }
367  if (!empty($updateRow)) {
368  if ((int)$file->_getPropertyRaw('uid') > 0) {
369  $constraints = ['uid' => (int)$file->getUid()];
370  } else {
371  $constraints = [
372  'storage' => (int)$file->getStorage()->getUid(),
373  'identifier' => $file->_getPropertyRaw('identifier'),
374  ];
375  }
376 
377  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->table);
378  $updateRow['tstamp'] = time();
379 
380  $connection->update(
381  $this->table,
382  $updateRow,
383  $constraints
384  );
385 
386  $this->‪updateRefIndex($file->getUid());
387  $this->eventDispatcher->dispatch(new AfterFileUpdatedInIndexEvent($file, array_intersect_key($file->getProperties(), array_flip($this->fields)), $updateRow));
388  }
389  }
390 
397  public function ‪findInStorageWithIndexOutstanding(ResourceStorage $storage, $limit = -1)
398  {
399  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
400 
401  if ((int)$limit > 0) {
402  $queryBuilder->setMaxResults((int)$limit);
403  }
404 
405  $rows = $queryBuilder
406  ->select(...$this->fields)
407  ->from($this->table)
408  ->where(
409  $queryBuilder->expr()->gt('tstamp', $queryBuilder->quoteIdentifier('last_indexed')),
410  $queryBuilder->expr()->eq('storage', $queryBuilder->createNamedParameter($storage->getUid(), ‪Connection::PARAM_INT))
411  )
412  ->orderBy('tstamp', 'ASC')
413  ->executeQuery()
414  ->fetchAllAssociative();
415 
416  return $rows;
417  }
418 
425  public function ‪findInStorageAndNotInUidList(ResourceStorage $storage, array $uidList)
426  {
427  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
428 
429  $queryBuilder
430  ->select(...$this->fields)
431  ->from($this->table)
432  ->where(
433  $queryBuilder->expr()->eq(
434  'storage',
435  $queryBuilder->createNamedParameter($storage->getUid(), ‪Connection::PARAM_INT)
436  )
437  );
438 
439  if (!empty($uidList)) {
440  $queryBuilder->andWhere(
441  $queryBuilder->expr()->notIn(
442  'uid',
443  array_map(intval(...), $uidList)
444  )
445  );
446  }
447 
448  $rows = $queryBuilder->executeQuery()->fetchAllAssociative();
449 
450  return $rows;
451  }
452 
458  public function ‪updateIndexingTime($fileUid)
459  {
460  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->table);
461  $connection->update(
462  $this->table,
463  [
464  'last_indexed' => time(),
465  ],
466  [
467  'uid' => (int)$fileUid,
468  ]
469  );
470  }
471 
477  public function ‪markFileAsMissing($fileUid)
478  {
479  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->table);
480  $connection->update(
481  $this->table,
482  [
483  'missing' => 1,
484  ],
485  [
486  'uid' => (int)$fileUid,
487  ]
488  );
489  $this->eventDispatcher->dispatch(new AfterFileMarkedAsMissingEvent((int)$fileUid));
490  }
491 
497  public function remove($fileUid)
498  {
499  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->table);
500  $connection->delete(
501  $this->table,
502  [
503  'uid' => (int)$fileUid,
504  ]
505  );
506  $this->‪updateRefIndex((int)$fileUid);
507  $this->eventDispatcher->dispatch(new AfterFileRemovedFromIndexEvent((int)$fileUid));
508  }
509 
513  public function ‪updateRefIndex(int $id): void
514  {
515  $refIndexObj = GeneralUtility::makeInstance(ReferenceIndex::class);
516  $refIndexObj->updateRefIndexTable($this->table, $id);
517  }
518 }
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\findInStorageAndNotInUidList
‪array findInStorageAndNotInUidList(ResourceStorage $storage, array $uidList)
Definition: FileIndexRepository.php:422
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\findOneByFileObject
‪array bool findOneByFileObject(FileInterface $fileObject)
Definition: FileIndexRepository.php:136
‪TYPO3\CMS\Core\Resource\ResourceInterface\getIdentifier
‪getIdentifier()
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository
Definition: FileIndexRepository.php:44
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\updateRefIndex
‪updateRefIndex(int $id)
Definition: FileIndexRepository.php:510
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:52
‪TYPO3\CMS\Core\Resource\ResourceStorage\getUid
‪int getUid()
Definition: ResourceStorage.php:338
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\addRaw
‪array addRaw(array $data)
Definition: FileIndexRepository.php:294
‪TYPO3\CMS\Core\Resource\FileInterface
Definition: FileInterface.php:26
‪TYPO3\CMS\Core\Resource\Event\AfterFileUpdatedInIndexEvent
Definition: AfterFileUpdatedInIndexEvent.php:27
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\findByFolders
‪array null findByFolders(array $folders, $includeMissing=true, $fileName=null)
Definition: FileIndexRepository.php:210
‪TYPO3\CMS\Core\Database\ReferenceIndex
Definition: ReferenceIndex.php:40
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\hasIndexRecord
‪bool hasIndexRecord(File $file)
Definition: FileIndexRepository.php:323
‪TYPO3\CMS\Core\Resource\ResourceInterface\getStorage
‪getStorage()
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\findByFolder
‪array null findByFolder(Folder $folder)
Definition: FileIndexRepository.php:174
‪TYPO3\CMS\Core\Resource\Event\AfterFileAddedToIndexEvent
Definition: AfterFileAddedToIndexEvent.php:26
‪TYPO3\CMS\Core\Resource\File\getUpdatedProperties
‪array getUpdatedProperties()
Definition: File.php:194
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\update
‪update(File $file)
Definition: FileIndexRepository.php:357
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\add
‪add(File $file)
Definition: FileIndexRepository.php:277
‪TYPO3\CMS\Core\Resource\File\getProperty
‪getProperty(string $key)
Definition: File.php:62
‪TYPO3\CMS\Core\Resource\Folder\getHashedIdentifier
‪getHashedIdentifier()
Definition: Folder.php:155
‪TYPO3\CMS\Core\Resource\ResourceStorage\hashFileIdentifier
‪string hashFileIdentifier($file)
Definition: ResourceStorage.php:1348
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\updateIndexingTime
‪updateIndexingTime($fileUid)
Definition: FileIndexRepository.php:455
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\findByContentHash
‪mixed findByContentHash($hash)
Definition: FileIndexRepository.php:148
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\findInStorageWithIndexOutstanding
‪array findInStorageWithIndexOutstanding(ResourceStorage $storage, $limit=-1)
Definition: FileIndexRepository.php:394
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\$eventDispatcher
‪EventDispatcherInterface $eventDispatcher
Definition: FileIndexRepository.php:51
‪TYPO3\CMS\Core\Resource\AbstractFile\getStorage
‪int< 0, getSize():int { if( $this->deleted) { throw new \RuntimeException( 'File has been deleted.', 1329821480);} if(empty( $this->properties[ 'size'])) { $fileInfo=$this-> getStorage() -> getFileInfoByIdentifier($this->getIdentifier(), ['size'])
‪TYPO3\CMS\Core\Database\Connection\PARAM_STR_ARRAY
‪const PARAM_STR_ARRAY
Definition: Connection.php:77
‪TYPO3\CMS\Core\Resource\Folder
Definition: Folder.php:38
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:26
‪TYPO3\CMS\Core\Resource\Folder\getStorage
‪getStorage()
Definition: Folder.php:139
‪TYPO3\CMS\Core\Resource\Event\AfterFileRemovedFromIndexEvent
Definition: AfterFileRemovedFromIndexEvent.php:26
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\__construct
‪__construct(EventDispatcherInterface $eventDispatcher)
Definition: FileIndexRepository.php:62
‪TYPO3\CMS\Core\Resource\File\getProperties
‪getProperties()
Definition: File.php:87
‪TYPO3\CMS\Core\Resource\Index
Definition: ExtractorInterface.php:16
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\$fields
‪array $fields
Definition: FileIndexRepository.php:57
‪TYPO3\CMS\Core\Resource\AbstractFile\getUid
‪return MathUtility::canBeInterpretedAsInteger($size) ?(int) $size int getUid()
Definition: AbstractFile.php:195
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Core\Resource\ResourceStorage
Definition: ResourceStorage.php:129
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\findOneByUid
‪array false findOneByUid($fileUid)
Definition: FileIndexRepository.php:73
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\insertRecord
‪insertRecord(array $data)
Definition: FileIndexRepository.php:303
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:22
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\markFileAsMissing
‪markFileAsMissing($fileUid)
Definition: FileIndexRepository.php:474
‪TYPO3\CMS\Core\Resource\File\updateProperties
‪updateProperties(array $properties)
Definition: File.php:155
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\$table
‪string $table
Definition: FileIndexRepository.php:47
‪TYPO3\CMS\Core\Resource\Event\AfterFileMarkedAsMissingEvent
Definition: AfterFileMarkedAsMissingEvent.php:27
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\findOneByStorageUidAndIdentifierHash
‪array false findOneByStorageUidAndIdentifierHash($storageUid, $identifierHash)
Definition: FileIndexRepository.php:99
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT_ARRAY
‪const PARAM_INT_ARRAY
Definition: Connection.php:72
‪TYPO3\CMS\Webhooks\Message\$identifier
‪identifier readonly string $identifier
Definition: FileAddedMessage.php:37
‪TYPO3\CMS\Core\Resource\File\_getPropertyRaw
‪mixed _getPropertyRaw($key)
Definition: File.php:314
‪TYPO3\CMS\Core\Resource\Index\FileIndexRepository\findOneByStorageAndIdentifier
‪array bool findOneByStorageAndIdentifier(ResourceStorage $storage, $identifier)
Definition: FileIndexRepository.php:124