‪TYPO3CMS  11.5
ProcessedFile.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
22 
45 {
46  /*********************************************
47  * FILE PROCESSING CONTEXTS
48  *********************************************/
53  public const ‪CONTEXT_IMAGEPREVIEW = 'Image.Preview';
59  public const ‪CONTEXT_IMAGECROPSCALEMASK = 'Image.CropScaleMask';
60 
66  protected ‪$taskType;
67 
71  protected ‪$task;
72 
76  protected ‪$taskTypeRegistry;
77 
84 
90  protected ‪$originalFile;
91 
99  protected ‪$originalFileSha1;
100 
107  protected ‪$updated = false;
108 
115  protected ‪$processingUrl = '';
116 
126  public function ‪__construct(‪File ‪$originalFile, ‪$taskType, array ‪$processingConfiguration, array $databaseRow = null)
127  {
128  $this->originalFile = ‪$originalFile;
129  $this->originalFileSha1 = $this->originalFile->‪getSha1();
131  $this->taskType = ‪$taskType;
132  $this->processingConfiguration = ‪$processingConfiguration;
133  if (is_array($databaseRow)) {
134  $this->‪reconstituteFromDatabaseRecord($databaseRow);
135  }
136  $this->taskTypeRegistry = GeneralUtility::makeInstance(TaskTypeRegistry::class);
137  }
138 
144  protected function ‪reconstituteFromDatabaseRecord(array $databaseRow)
145  {
146  $this->taskType = $this->taskType ?: $databaseRow['task_type'];
147  // @todo In case the original configuration contained file objects the reconstitution fails. See ConfigurationService->serialize()
148  $this->processingConfiguration = $this->processingConfiguration ?: unserialize($databaseRow['configuration'] ?? '');
149 
150  $this->originalFileSha1 = $databaseRow['originalfilesha1'];
151  $this->identifier = $databaseRow['identifier'];
152  $this->name = $databaseRow['name'];
153  $this->properties = $databaseRow;
154  $this->processingUrl = $databaseRow['processing_url'] ?? '';
155 
156  if (!empty($databaseRow['storage']) && (int)$this->storage->getUid() !== (int)$databaseRow['storage']) {
157  $this->storage = GeneralUtility::makeInstance(StorageRepository::class)->findByUid($databaseRow['storage']);
158  }
159  }
160 
161  /********************************
162  * VARIOUS FILE PROPERTY GETTERS
163  ********************************/
164 
170  // @todo replace these usages with direct calls to the task object
171  public function ‪calculateChecksum()
172  {
173  return $this->‪getTask()->getConfigurationChecksum();
174  }
175 
176  /*******************
177  * CONTENTS RELATED
178  *******************/
185  public function ‪setContents($contents)
186  {
187  throw new \BadMethodCallException('Setting contents not possible for processed file.', 1305438528);
188  }
189 
196  public function ‪updateWithLocalFile($filePath)
197  {
198  if (empty($this->identifier)) {
199  throw new \RuntimeException('Cannot update original file!', 1350582054);
200  }
201  $processingFolder = $this->originalFile->getStorage()->getProcessingFolder($this->originalFile);
202  $addedFile = $this->storage->updateProcessedFile($filePath, $this, $processingFolder);
203 
204  // Update some related properties
205  $this->identifier = $addedFile->getIdentifier();
206  $this->originalFileSha1 = $this->originalFile->getSha1();
207  if ($addedFile instanceof AbstractFile) {
208  $this->‪updateProperties($addedFile->getProperties());
209  }
210  $this->deleted = false;
211  $this->updated = true;
212  }
213 
214  /*****************************************
215  * STORAGE AND MANAGEMENT RELATED METHODS
216  *****************************************/
222  public function ‪isIndexed()
223  {
224  // Processed files are never indexed; instead you might be looking for isPersisted()
225  return false;
226  }
227 
233  public function ‪isPersisted()
234  {
235  return is_array($this->properties) && array_key_exists('uid', $this->properties) && $this->properties['uid'] > 0;
236  }
237 
243  public function ‪isNew()
244  {
245  return !$this->‪isPersisted();
246  }
247 
254  public function ‪isUpdated()
255  {
257  }
258 
264  public function ‪setName(‪$name)
265  {
266  // Remove the existing file, but only we actually have a name or the name has changed
267  if (!empty($this->name) && $this->name !== ‪$name && $this->‪exists()) {
268  $this->delete();
269  }
270 
271  $this->name = ‪$name;
272  // @todo this is a *weird* hack that will fail if the storage is non-hierarchical!
273  $this->identifier = $this->storage->getProcessingFolder($this->originalFile)->getIdentifier() . ‪$this->name;
274 
275  $this->updated = true;
276  }
277 
285  public function ‪exists()
286  {
287  if ($this->‪usesOriginalFile()) {
288  return $this->originalFile->exists();
289  }
290 
291  return parent::exists();
292  }
293 
294  /******************
295  * SPECIAL METHODS
296  ******************/
297 
303  public function ‪isProcessed()
304  {
305  return $this->updated || ($this->‪isPersisted() && !$this->‪needsReprocessing());
306  }
307 
313  public function ‪getOriginalFile()
314  {
315  return ‪$this->originalFile;
316  }
317 
327  public function ‪getIdentifier()
328  {
329  return (!$this->‪usesOriginalFile()) ? $this->identifier : $this->‪getOriginalFile()->‪getIdentifier();
330  }
331 
341  public function ‪getName()
342  {
343  if ($this->‪usesOriginalFile()) {
344  return $this->originalFile->getName();
345  }
346  return ‪$this->name;
347  }
348 
355  public function ‪updateProperties(array ‪$properties)
356  {
357  if (!is_array($this->properties)) {
358  $this->properties = [];
359  }
360 
361  if (array_key_exists('uid', ‪$properties) && ‪MathUtility::canBeInterpretedAsInteger(‪$properties['uid'])) {
362  $this->properties['uid'] = ‪$properties['uid'];
363  }
364  if (isset(‪$properties['processing_url'])) {
365  $this->processingUrl = ‪$properties['processing_url'];
366  }
367 
368  // @todo we should have a blacklist of properties that might not be updated
369  $this->properties = array_merge($this->properties, ‪$properties);
370 
371  // @todo when should this update be done?
372  if (!$this->‪isUnchanged() && $this->‪exists()) {
374  if ($this->‪usesOriginalFile()) {
375  ‪$storage = $this->originalFile->getStorage();
376  }
377  $this->properties = array_merge($this->properties, ‪$storage->‪getFileInfo($this));
378  }
379  }
380 
386  public function ‪toArray()
387  {
388  if ($this->‪usesOriginalFile()) {
389  $properties = $this->originalFile->getProperties();
390  unset(‪$properties['uid']);
391  ‪$properties['identifier'] = '';
392  ‪$properties['name'] = null;
393  ‪$properties['processing_url'] = '';
394 
395  // Use width + height set in processed file
396  ‪$properties['width'] = $this->properties['width'] ?? 0;
397  ‪$properties['height'] = $this->properties['height'] ?? 0;
398  } else {
400  ‪$properties['identifier'] = $this->‪getIdentifier();
401  $properties['name'] = $this->‪getName();
402  }
403 
404  $properties['configuration'] = (new ConfigurationService())->serialize($this->processingConfiguration);
405 
406  return array_merge(‪$properties, [
407  'storage' => $this->‪getStorage()->‪getUid(),
408  'checksum' => $this->‪calculateChecksum(),
409  'task_type' => $this->taskType,
410  'configurationsha1' => sha1(‪$properties['configuration']),
411  'original' => $this->originalFile->getUid(),
412  'originalfilesha1' => $this->originalFileSha1,
413  ]);
414  }
415 
421  protected function ‪isUnchanged()
422  {
423  return !($this->properties['width'] ?? false) && $this->‪usesOriginalFile();
424  }
425 
429  public function ‪setUsesOriginalFile()
430  {
431  // @todo check if some of these properties can/should be set in a generic update method
432  $this->identifier = $this->originalFile->getIdentifier();
433  $this->updated = true;
434  $this->processingUrl = '';
435  $this->originalFileSha1 = $this->originalFile->getSha1();
436  }
437 
438  public function ‪updateProcessingUrl(string $url): void
439  {
440  $this->updated = true;
441  $this->processingUrl = $url;
442  }
443 
447  public function ‪usesOriginalFile()
448  {
449  return empty($this->identifier) || $this->identifier === $this->originalFile->getIdentifier();
450  }
451 
457  public function ‪isOutdated()
458  {
459  return $this->‪needsReprocessing();
460  }
461 
468  public function delete($force = false)
469  {
470  if (!$force && $this->‪isUnchanged()) {
471  return false;
472  }
473  // Only delete file when original isn't used
474  if (!$this->‪usesOriginalFile()) {
475  return parent::delete();
476  }
477  return true;
478  }
479 
487  public function ‪getProperty($key)
488  {
489  // The uid always (!) has to come from this file and never the original file (see getOriginalFile() to get this)
490  if ($this->‪isUnchanged() && $key !== 'uid') {
491  return $this->originalFile->getProperty($key);
492  }
493  return $this->properties[$key] ?? null;
494  }
495 
501  public function ‪getUid()
502  {
503  return $this->properties['uid'] ?? 0;
504  }
505 
511  public function ‪needsReprocessing()
512  {
513  $fileMustBeRecreated = false;
514 
515  // if original is missing we can not reprocess the file
516  if ($this->originalFile->isMissing()) {
517  return false;
518  }
519 
520  // processedFile does not exist
521  if (!$this->‪usesOriginalFile() && !$this->‪exists()) {
522  $fileMustBeRecreated = true;
523  }
524 
525  // hash does not match
526  if (array_key_exists('checksum', $this->properties) && $this->‪calculateChecksum() !== $this->properties['checksum']) {
527  $fileMustBeRecreated = true;
528  }
529 
530  // original file changed
531  if ($this->originalFile->getSha1() !== $this->originalFileSha1) {
532  $fileMustBeRecreated = true;
533  }
534 
535  if (!array_key_exists('uid', $this->properties)) {
536  $fileMustBeRecreated = true;
537  }
538 
539  // remove outdated file
540  if ($fileMustBeRecreated && $this->‪exists()) {
541  $this->delete();
542  }
543  return $fileMustBeRecreated;
544  }
545 
551  public function ‪getProcessingConfiguration()
552  {
554  }
555 
561  public function ‪getTaskIdentifier()
562  {
563  return ‪$this->taskType;
564  }
565 
572  public function ‪getTask(): Processing\TaskInterface
573  {
574  if ($this->task === null) {
575  $this->task = $this->taskTypeRegistry->getTaskForType($this->taskType, $this, $this->processingConfiguration);
576  }
577 
579  }
580 
587  {
588  ‪$name = $this->originalFile->getNameWithoutExtension();
589  ‪$name .= '_' . $this->originalFile->getUid();
590  ‪$name .= '_' . $this->‪calculateChecksum();
591 
592  return ‪$name;
593  }
594 
601  public function ‪getPublicUrl($relativeToCurrentScript = false)
602  {
603  if ($this->processingUrl) {
605  }
606  if ($this->deleted) {
607  return null;
608  }
609  // @deprecated $relativeToCurrentScript since v11, will be removed in TYPO3 v12.0
610  if ($this->‪usesOriginalFile()) {
611  return $this->‪getOriginalFile()->‪getPublicUrl($relativeToCurrentScript);
612  }
613  return $this->‪getStorage()->‪getPublicUrl($this, $relativeToCurrentScript);
614  }
615 }
‪TYPO3\CMS\Core\Resource\ProcessedFile\$taskTypeRegistry
‪Processing TaskTypeRegistry $taskTypeRegistry
Definition: ProcessedFile.php:73
‪TYPO3\CMS\Core\Resource\ProcessedFile\getOriginalFile
‪File getOriginalFile()
Definition: ProcessedFile.php:305
‪TYPO3\CMS\Core\Resource\ProcessedFile\CONTEXT_IMAGEPREVIEW
‪const CONTEXT_IMAGEPREVIEW
Definition: ProcessedFile.php:53
‪TYPO3\CMS\Core\Resource\ProcessedFile\usesOriginalFile
‪bool usesOriginalFile()
Definition: ProcessedFile.php:439
‪TYPO3\CMS\Core\Resource\ResourceStorage\getFileInfo
‪array getFileInfo(FileInterface $fileObject)
Definition: ResourceStorage.php:1506
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:74
‪TYPO3\CMS\Core\Resource\ProcessedFile\getUid
‪int getUid()
Definition: ProcessedFile.php:493
‪TYPO3\CMS\Core\Resource\AbstractFile\getIdentifier
‪string getIdentifier()
Definition: AbstractFile.php:141
‪TYPO3\CMS\Core\Resource\File\getPublicUrl
‪string null getPublicUrl($relativeToCurrentScript=false)
Definition: File.php:317
‪TYPO3\CMS\Core\Resource\ResourceStorage\getPublicUrl
‪string null getPublicUrl(ResourceInterface $resourceObject, $relativeToCurrentScript=false)
Definition: ResourceStorage.php:1374
‪TYPO3\CMS\Core\Resource\Processing\TaskInterface
Definition: TaskInterface.php:33
‪TYPO3\CMS\Core\Resource\ProcessedFile\needsReprocessing
‪bool needsReprocessing()
Definition: ProcessedFile.php:503
‪TYPO3\CMS\Core\Resource\ProcessedFile\CONTEXT_IMAGECROPSCALEMASK
‪const CONTEXT_IMAGECROPSCALEMASK
Definition: ProcessedFile.php:59
‪TYPO3\CMS\Core\Resource\ResourceStorage\getProcessingFolder
‪Folder getProcessingFolder(File $file=null)
Definition: ResourceStorage.php:2777
‪TYPO3\CMS\Core\Resource\ProcessedFile\$processingConfiguration
‪array $processingConfiguration
Definition: ProcessedFile.php:79
‪TYPO3\CMS\Core\Resource\ProcessedFile\calculateChecksum
‪string calculateChecksum()
Definition: ProcessedFile.php:163
‪TYPO3\CMS\Core\Resource\ProcessedFile\isUnchanged
‪bool isUnchanged()
Definition: ProcessedFile.php:413
‪TYPO3\CMS\Core\Resource\ProcessedFile\$originalFileSha1
‪string $originalFileSha1
Definition: ProcessedFile.php:93
‪TYPO3\CMS\Core\Resource\ProcessedFile\setName
‪setName($name)
Definition: ProcessedFile.php:256
‪TYPO3\CMS\Core\Resource\ProcessedFile\exists
‪bool exists()
Definition: ProcessedFile.php:277
‪TYPO3\CMS\Core\Resource\ProcessedFile\setUsesOriginalFile
‪setUsesOriginalFile()
Definition: ProcessedFile.php:421
‪TYPO3\CMS\Core\Resource\Processing\TaskTypeRegistry
Definition: TaskTypeRegistry.php:26
‪TYPO3\CMS\Core\Resource\ProcessedFile\$updated
‪bool $updated
Definition: ProcessedFile.php:100
‪TYPO3\CMS\Core\Resource\ProcessedFile\getProcessingConfiguration
‪array getProcessingConfiguration()
Definition: ProcessedFile.php:543
‪TYPO3\CMS\Core\Resource\File\getSha1
‪string getSha1()
Definition: File.php:122
‪TYPO3\CMS\Core\Resource\ProcessedFile\generateProcessedFileNameWithoutExtension
‪string generateProcessedFileNameWithoutExtension()
Definition: ProcessedFile.php:578
‪TYPO3\CMS\Core\Resource\Folder\getStorage
‪ResourceStorage getStorage()
Definition: Folder.php:149
‪TYPO3\CMS\Core\Resource\ProcessedFile\toArray
‪array toArray()
Definition: ProcessedFile.php:378
‪TYPO3\CMS\Core\Resource\AbstractFile
Definition: AbstractFile.php:26
‪TYPO3\CMS\Core\Resource\ProcessedFile\getTaskIdentifier
‪string getTaskIdentifier()
Definition: ProcessedFile.php:553
‪TYPO3\CMS\Core\Resource\ProcessedFile\isProcessed
‪bool isProcessed()
Definition: ProcessedFile.php:295
‪TYPO3\CMS\Core\Resource\ProcessedFile\isUpdated
‪bool isUpdated()
Definition: ProcessedFile.php:246
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:24
‪TYPO3\CMS\Core\Resource\ProcessedFile\getPublicUrl
‪string null getPublicUrl($relativeToCurrentScript=false)
Definition: ProcessedFile.php:593
‪TYPO3\CMS\Core\Resource\AbstractFile\$name
‪string $name
Definition: AbstractFile.php:55
‪TYPO3\CMS\Core\Resource\ProcessedFile\setContents
‪setContents($contents)
Definition: ProcessedFile.php:177
‪TYPO3\CMS\Core\Resource\ProcessedFile\$task
‪Processing TaskInterface $task
Definition: ProcessedFile.php:69
‪TYPO3\CMS\Core\Resource
Definition: generateMimeTypes.php:52
‪TYPO3\CMS\Core\Resource\ProcessedFile\updateWithLocalFile
‪updateWithLocalFile($filePath)
Definition: ProcessedFile.php:188
‪TYPO3\CMS\Core\Resource\ProcessedFile
Definition: ProcessedFile.php:45
‪TYPO3\CMS\Core\Resource\ProcessedFile\getProperty
‪mixed getProperty($key)
Definition: ProcessedFile.php:479
‪TYPO3\CMS\Core\Resource\ProcessedFile\getIdentifier
‪string getIdentifier()
Definition: ProcessedFile.php:319
‪TYPO3\CMS\Core\Resource\ProcessedFile\$originalFile
‪File $originalFile
Definition: ProcessedFile.php:85
‪TYPO3\CMS\Core\Resource\ProcessedFile\__construct
‪__construct(File $originalFile, $taskType, array $processingConfiguration, array $databaseRow=null)
Definition: ProcessedFile.php:118
‪TYPO3\CMS\Core\Resource\Service\ConfigurationService
Definition: ConfigurationService.php:34
‪TYPO3\CMS\Core\Resource\ProcessedFile\getTask
‪Processing TaskInterface getTask()
Definition: ProcessedFile.php:564
‪TYPO3\CMS\Core\Resource\ProcessedFile\reconstituteFromDatabaseRecord
‪reconstituteFromDatabaseRecord(array $databaseRow)
Definition: ProcessedFile.php:136
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:22
‪TYPO3\CMS\Core\Resource\AbstractFile\$properties
‪array $properties
Definition: AbstractFile.php:35
‪TYPO3\CMS\Core\Resource\ProcessedFile\isIndexed
‪bool isIndexed()
Definition: ProcessedFile.php:214
‪TYPO3\CMS\Core\Resource\ProcessedFile\isPersisted
‪bool isPersisted()
Definition: ProcessedFile.php:225
‪TYPO3\CMS\Core\Resource\AbstractFile\$storage
‪ResourceStorage null $storage
Definition: AbstractFile.php:41
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50
‪TYPO3\CMS\Core\Resource\ProcessedFile\updateProcessingUrl
‪updateProcessingUrl(string $url)
Definition: ProcessedFile.php:430
‪TYPO3\CMS\Core\Resource\ProcessedFile\updateProperties
‪updateProperties(array $properties)
Definition: ProcessedFile.php:347
‪TYPO3\CMS\Core\Resource\ProcessedFile\getName
‪string getName()
Definition: ProcessedFile.php:333
‪TYPO3\CMS\Core\Resource\ProcessedFile\$taskType
‪string $taskType
Definition: ProcessedFile.php:65
‪TYPO3\CMS\Core\Resource\ProcessedFile\isNew
‪bool isNew()
Definition: ProcessedFile.php:235
‪TYPO3\CMS\Core\Resource\AbstractFile\getStorage
‪ResourceStorage getStorage()
Definition: AbstractFile.php:395
‪TYPO3\CMS\Core\Resource\ProcessedFile\isOutdated
‪bool isOutdated()
Definition: ProcessedFile.php:449
‪TYPO3\CMS\Core\Resource\ProcessedFile\$processingUrl
‪string $processingUrl
Definition: ProcessedFile.php:107