‪TYPO3CMS  10.4
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 
21 
44 {
45  /*********************************************
46  * FILE PROCESSING CONTEXTS
47  *********************************************/
52  const ‪CONTEXT_IMAGEPREVIEW = 'Image.Preview';
58  const ‪CONTEXT_IMAGECROPSCALEMASK = 'Image.CropScaleMask';
59 
65  protected ‪$taskType;
66 
70  protected ‪$task;
71 
75  protected ‪$taskTypeRegistry;
76 
83 
89  protected ‪$originalFile;
90 
98  protected ‪$originalFileSha1;
99 
106  protected ‪$updated = false;
107 
114  protected ‪$processingUrl = '';
115 
125  public function ‪__construct(‪File ‪$originalFile, ‪$taskType, array ‪$processingConfiguration, array $databaseRow = null)
126  {
127  $this->originalFile = ‪$originalFile;
128  $this->originalFileSha1 = $this->originalFile->‪getSha1();
130  $this->taskType = ‪$taskType;
131  $this->processingConfiguration = ‪$processingConfiguration;
132  if (is_array($databaseRow)) {
133  $this->‪reconstituteFromDatabaseRecord($databaseRow);
134  }
135  $this->taskTypeRegistry = GeneralUtility::makeInstance(TaskTypeRegistry::class);
136  }
137 
143  protected function ‪reconstituteFromDatabaseRecord(array $databaseRow)
144  {
145  $this->taskType = $this->taskType ?: $databaseRow['task_type'];
146  $this->processingConfiguration = $this->processingConfiguration ?: unserialize($databaseRow['configuration']);
147 
148  $this->originalFileSha1 = $databaseRow['originalfilesha1'];
149  $this->identifier = $databaseRow['identifier'];
150  $this->name = $databaseRow['name'];
151  $this->properties = $databaseRow;
152  $this->processingUrl = $databaseRow['processing_url'] ?? '';
153 
154  if (!empty($databaseRow['storage']) && (int)$this->storage->getUid() !== (int)$databaseRow['storage']) {
155  $this->storage = GeneralUtility::makeInstance(ResourceFactory::class)->getStorageObject($databaseRow['storage']);
156  }
157  }
158 
159  /********************************
160  * VARIOUS FILE PROPERTY GETTERS
161  ********************************/
162 
168  // @todo replace these usages with direct calls to the task object
169  public function ‪calculateChecksum()
170  {
171  return $this->‪getTask()->getConfigurationChecksum();
172  }
173 
174  /*******************
175  * CONTENTS RELATED
176  *******************/
183  public function ‪setContents($contents)
184  {
185  throw new \BadMethodCallException('Setting contents not possible for processed file.', 1305438528);
186  }
187 
194  public function ‪updateWithLocalFile($filePath)
195  {
196  if (empty($this->identifier)) {
197  throw new \RuntimeException('Cannot update original file!', 1350582054);
198  }
199  $processingFolder = $this->originalFile->getStorage()->getProcessingFolder($this->originalFile);
200  $addedFile = $this->storage->updateProcessedFile($filePath, $this, $processingFolder);
201 
202  // Update some related properties
203  $this->identifier = $addedFile->getIdentifier();
204  $this->originalFileSha1 = $this->originalFile->getSha1();
205  if ($addedFile instanceof AbstractFile) {
206  $this->‪updateProperties($addedFile->getProperties());
207  }
208  $this->deleted = false;
209  $this->updated = true;
210  }
211 
212  /*****************************************
213  * STORAGE AND MANAGEMENT RELATED METHODS
214  *****************************************/
220  public function ‪isIndexed()
221  {
222  // Processed files are never indexed; instead you might be looking for isPersisted()
223  return false;
224  }
225 
231  public function ‪isPersisted()
232  {
233  return is_array($this->properties) && array_key_exists('uid', $this->properties) && $this->properties['uid'] > 0;
234  }
235 
241  public function ‪isNew()
242  {
243  return !$this->‪isPersisted();
244  }
245 
252  public function ‪isUpdated()
253  {
255  }
256 
262  public function ‪setName(‪$name)
263  {
264  // Remove the existing file, but only we actually have a name or the name has changed
265  if (!empty($this->name) && $this->name !== ‪$name && $this->‪exists()) {
266  $this->delete();
267  }
268 
269  $this->name = ‪$name;
270  // @todo this is a *weird* hack that will fail if the storage is non-hierarchical!
271  $this->identifier = $this->storage->getProcessingFolder($this->originalFile)->getIdentifier() . ‪$this->name;
272 
273  $this->updated = true;
274  }
275 
283  public function ‪exists()
284  {
285  if ($this->‪usesOriginalFile()) {
286  return $this->originalFile->exists();
287  }
288 
289  return parent::exists();
290  }
291 
292  /******************
293  * SPECIAL METHODS
294  ******************/
295 
301  public function ‪isProcessed()
302  {
303  return $this->updated || ($this->‪isPersisted() && !$this->‪needsReprocessing());
304  }
305 
311  public function ‪getOriginalFile()
312  {
313  return ‪$this->originalFile;
314  }
315 
325  public function ‪getIdentifier()
326  {
327  return (!$this->‪usesOriginalFile()) ? $this->identifier : $this->‪getOriginalFile()->‪getIdentifier();
328  }
329 
339  public function ‪getName()
340  {
341  if ($this->‪usesOriginalFile()) {
342  return $this->originalFile->getName();
343  }
344  return ‪$this->name;
345  }
346 
353  public function ‪updateProperties(array ‪$properties)
354  {
355  if (!is_array($this->properties)) {
356  $this->properties = [];
357  }
358 
359  if (array_key_exists('uid', ‪$properties) && ‪MathUtility::canBeInterpretedAsInteger(‪$properties['uid'])) {
360  $this->properties['uid'] = ‪$properties['uid'];
361  }
362  if (isset(‪$properties['processing_url'])) {
363  $this->processingUrl = ‪$properties['processing_url'];
364  }
365 
366  // @todo we should have a blacklist of properties that might not be updated
367  $this->properties = array_merge($this->properties, ‪$properties);
368 
369  // @todo when should this update be done?
370  if (!$this->‪isUnchanged() && $this->‪exists()) {
372  if ($this->‪usesOriginalFile()) {
373  ‪$storage = $this->originalFile->getStorage();
374  }
375  $this->properties = array_merge($this->properties, ‪$storage->‪getFileInfo($this));
376  }
377  }
378 
384  public function ‪toArray()
385  {
386  if ($this->‪usesOriginalFile()) {
387  $properties = $this->originalFile->getProperties();
388  unset(‪$properties['uid']);
389  ‪$properties['identifier'] = '';
390  ‪$properties['name'] = null;
391  ‪$properties['processing_url'] = '';
392 
393  // Use width + height set in processed file
394  ‪$properties['width'] = $this->properties['width'];
395  ‪$properties['height'] = $this->properties['height'];
396  } else {
398  ‪$properties['identifier'] = $this->‪getIdentifier();
399  $properties['name'] = $this->‪getName();
400  }
401 
402  $properties['configuration'] = serialize($this->processingConfiguration);
403 
404  return array_merge(‪$properties, [
405  'storage' => $this->‪getStorage()->‪getUid(),
406  'checksum' => $this->‪calculateChecksum(),
407  'task_type' => $this->taskType,
408  'configurationsha1' => sha1(‪$properties['configuration']),
409  'original' => $this->originalFile->getUid(),
410  'originalfilesha1' => $this->originalFileSha1
411  ]);
412  }
413 
419  protected function ‪isUnchanged()
420  {
421  return !$this->properties['width'] && $this->‪usesOriginalFile();
422  }
423 
427  public function ‪setUsesOriginalFile()
428  {
429  // @todo check if some of these properties can/should be set in a generic update method
430  $this->identifier = $this->originalFile->getIdentifier();
431  $this->updated = true;
432  $this->processingUrl = '';
433  $this->originalFileSha1 = $this->originalFile->getSha1();
434  }
435 
436  public function ‪updateProcessingUrl(string $url): void
437  {
438  $this->updated = true;
439  $this->processingUrl = $url;
440  }
441 
445  public function ‪usesOriginalFile()
446  {
447  return empty($this->identifier) || $this->identifier === $this->originalFile->getIdentifier();
448  }
449 
455  public function ‪isOutdated()
456  {
457  return $this->‪needsReprocessing();
458  }
459 
466  public function delete($force = false)
467  {
468  if (!$force && $this->‪isUnchanged()) {
469  return false;
470  }
471  // Only delete file when original isn't used
472  if (!$this->‪usesOriginalFile()) {
473  return parent::delete();
474  }
475  return true;
476  }
477 
485  public function ‪getProperty($key)
486  {
487  // The uid always (!) has to come from this file and never the original file (see getOriginalFile() to get this)
488  if ($this->‪isUnchanged() && $key !== 'uid') {
489  return $this->originalFile->getProperty($key);
490  }
491  return $this->properties[$key];
492  }
493 
499  public function ‪getUid()
500  {
501  return $this->properties['uid'];
502  }
503 
509  public function ‪needsReprocessing()
510  {
511  $fileMustBeRecreated = false;
512 
513  // if original is missing we can not reprocess the file
514  if ($this->originalFile->isMissing()) {
515  return false;
516  }
517 
518  // processedFile does not exist
519  if (!$this->‪usesOriginalFile() && !$this->‪exists()) {
520  $fileMustBeRecreated = true;
521  }
522 
523  // hash does not match
524  if (array_key_exists('checksum', $this->properties) && $this->‪calculateChecksum() !== $this->properties['checksum']) {
525  $fileMustBeRecreated = true;
526  }
527 
528  // original file changed
529  if ($this->originalFile->getSha1() !== $this->originalFileSha1) {
530  $fileMustBeRecreated = true;
531  }
532 
533  if (!array_key_exists('uid', $this->properties)) {
534  $fileMustBeRecreated = true;
535  }
536 
537  // remove outdated file
538  if ($fileMustBeRecreated && $this->‪exists()) {
539  $this->delete();
540  }
541  return $fileMustBeRecreated;
542  }
543 
549  public function ‪getProcessingConfiguration()
550  {
552  }
553 
559  public function ‪getTaskIdentifier()
560  {
561  return ‪$this->taskType;
562  }
563 
570  public function ‪getTask(): Processing\TaskInterface
571  {
572  if ($this->task === null) {
573  $this->task = $this->taskTypeRegistry->getTaskForType($this->taskType, $this, $this->processingConfiguration);
574  }
575 
577  }
578 
585  {
586  ‪$name = $this->originalFile->getNameWithoutExtension();
587  ‪$name .= '_' . $this->originalFile->getUid();
588  ‪$name .= '_' . $this->‪calculateChecksum();
589 
590  return ‪$name;
591  }
592 
599  public function ‪getPublicUrl($relativeToCurrentScript = false)
600  {
601  if ($this->processingUrl) {
603  }
604  if ($this->deleted) {
605  return null;
606  }
607  if ($this->‪usesOriginalFile()) {
608  return $this->‪getOriginalFile()->‪getPublicUrl($relativeToCurrentScript);
609  }
610  return $this->‪getStorage()->‪getPublicUrl($this, $relativeToCurrentScript);
611  }
612 }
‪TYPO3\CMS\Core\Resource\ProcessedFile\$taskTypeRegistry
‪Processing TaskTypeRegistry $taskTypeRegistry
Definition: ProcessedFile.php:72
‪TYPO3\CMS\Core\Resource\ProcessedFile\getOriginalFile
‪File getOriginalFile()
Definition: ProcessedFile.php:303
‪TYPO3\CMS\Core\Resource\ProcessedFile\CONTEXT_IMAGEPREVIEW
‪const CONTEXT_IMAGEPREVIEW
Definition: ProcessedFile.php:52
‪TYPO3\CMS\Core\Resource\ProcessedFile\usesOriginalFile
‪bool usesOriginalFile()
Definition: ProcessedFile.php:437
‪TYPO3\CMS\Core\Resource\ResourceStorage\getFileInfo
‪array getFileInfo(FileInterface $fileObject)
Definition: ResourceStorage.php:1473
‪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:491
‪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:333
‪TYPO3\CMS\Core\Resource\ResourceStorage\getPublicUrl
‪string null getPublicUrl(ResourceInterface $resourceObject, $relativeToCurrentScript=false)
Definition: ResourceStorage.php:1369
‪TYPO3\CMS\Core\Resource\Processing\TaskInterface
Definition: TaskInterface.php:33
‪TYPO3\CMS\Core\Resource\ProcessedFile\needsReprocessing
‪bool needsReprocessing()
Definition: ProcessedFile.php:501
‪TYPO3\CMS\Core\Resource\ProcessedFile\CONTEXT_IMAGECROPSCALEMASK
‪const CONTEXT_IMAGECROPSCALEMASK
Definition: ProcessedFile.php:58
‪TYPO3\CMS\Core\Resource\ResourceStorage\getProcessingFolder
‪Folder getProcessingFolder(File $file=null)
Definition: ResourceStorage.php:2738
‪TYPO3\CMS\Core\Resource\ProcessedFile\$processingConfiguration
‪array $processingConfiguration
Definition: ProcessedFile.php:78
‪TYPO3\CMS\Core\Resource\ProcessedFile\calculateChecksum
‪string calculateChecksum()
Definition: ProcessedFile.php:161
‪TYPO3\CMS\Core\Resource\ProcessedFile\isUnchanged
‪bool isUnchanged()
Definition: ProcessedFile.php:411
‪TYPO3\CMS\Core\Resource\ProcessedFile\$originalFileSha1
‪string $originalFileSha1
Definition: ProcessedFile.php:92
‪TYPO3\CMS\Core\Resource\ProcessedFile\setName
‪setName($name)
Definition: ProcessedFile.php:254
‪TYPO3\CMS\Core\Resource\ProcessedFile\exists
‪bool exists()
Definition: ProcessedFile.php:275
‪TYPO3\CMS\Core\Resource\ProcessedFile\setUsesOriginalFile
‪setUsesOriginalFile()
Definition: ProcessedFile.php:419
‪TYPO3\CMS\Core\Resource\Processing\TaskTypeRegistry
Definition: TaskTypeRegistry.php:26
‪TYPO3\CMS\Core\Resource\ProcessedFile\$updated
‪bool $updated
Definition: ProcessedFile.php:99
‪TYPO3\CMS\Core\Resource\ProcessedFile\getProcessingConfiguration
‪array getProcessingConfiguration()
Definition: ProcessedFile.php:541
‪TYPO3\CMS\Core\Resource\File\getSha1
‪string getSha1()
Definition: File.php:138
‪TYPO3\CMS\Core\Resource\ProcessedFile\generateProcessedFileNameWithoutExtension
‪string generateProcessedFileNameWithoutExtension()
Definition: ProcessedFile.php:576
‪TYPO3\CMS\Core\Resource\Folder\getStorage
‪ResourceStorage getStorage()
Definition: Folder.php:149
‪TYPO3\CMS\Core\Resource\ProcessedFile\toArray
‪array toArray()
Definition: ProcessedFile.php:376
‪TYPO3\CMS\Core\Resource\AbstractFile
Definition: AbstractFile.php:26
‪TYPO3\CMS\Core\Resource\ProcessedFile\getTaskIdentifier
‪string getTaskIdentifier()
Definition: ProcessedFile.php:551
‪TYPO3\CMS\Core\Resource\ProcessedFile\isProcessed
‪bool isProcessed()
Definition: ProcessedFile.php:293
‪TYPO3\CMS\Core\Resource\ProcessedFile\isUpdated
‪bool isUpdated()
Definition: ProcessedFile.php:244
‪TYPO3\CMS\Core\Resource\AbstractFile\$storage
‪ResourceStorage $storage
Definition: AbstractFile.php:41
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:24
‪TYPO3\CMS\Core\Resource\ProcessedFile\getPublicUrl
‪string null getPublicUrl($relativeToCurrentScript=false)
Definition: ProcessedFile.php:591
‪TYPO3\CMS\Core\Resource\AbstractFile\$name
‪string $name
Definition: AbstractFile.php:55
‪TYPO3\CMS\Core\Resource\ProcessedFile\setContents
‪setContents($contents)
Definition: ProcessedFile.php:175
‪TYPO3\CMS\Core\Resource\ProcessedFile\$task
‪Processing TaskInterface $task
Definition: ProcessedFile.php:68
‪TYPO3\CMS\Core\Resource
Definition: generateMimeTypes.php:52
‪TYPO3\CMS\Core\Resource\ProcessedFile\updateWithLocalFile
‪updateWithLocalFile($filePath)
Definition: ProcessedFile.php:186
‪TYPO3\CMS\Core\Resource\ProcessedFile
Definition: ProcessedFile.php:44
‪TYPO3\CMS\Core\Resource\ProcessedFile\getProperty
‪mixed getProperty($key)
Definition: ProcessedFile.php:477
‪TYPO3\CMS\Core\Resource\ProcessedFile\getIdentifier
‪string getIdentifier()
Definition: ProcessedFile.php:317
‪TYPO3\CMS\Core\Resource\ProcessedFile\$originalFile
‪File $originalFile
Definition: ProcessedFile.php:84
‪TYPO3\CMS\Core\Resource\ProcessedFile\__construct
‪__construct(File $originalFile, $taskType, array $processingConfiguration, array $databaseRow=null)
Definition: ProcessedFile.php:117
‪TYPO3\CMS\Core\Resource\ProcessedFile\getTask
‪Processing TaskInterface getTask()
Definition: ProcessedFile.php:562
‪TYPO3\CMS\Core\Resource\ProcessedFile\reconstituteFromDatabaseRecord
‪reconstituteFromDatabaseRecord(array $databaseRow)
Definition: ProcessedFile.php:135
‪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:212
‪TYPO3\CMS\Core\Resource\ProcessedFile\isPersisted
‪bool isPersisted()
Definition: ProcessedFile.php:223
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Resource\ProcessedFile\updateProcessingUrl
‪updateProcessingUrl(string $url)
Definition: ProcessedFile.php:428
‪TYPO3\CMS\Core\Resource\ProcessedFile\updateProperties
‪updateProperties(array $properties)
Definition: ProcessedFile.php:345
‪TYPO3\CMS\Core\Resource\ProcessedFile\getName
‪string getName()
Definition: ProcessedFile.php:331
‪TYPO3\CMS\Core\Resource\ProcessedFile\$taskType
‪string $taskType
Definition: ProcessedFile.php:64
‪TYPO3\CMS\Core\Resource\ProcessedFile\isNew
‪bool isNew()
Definition: ProcessedFile.php:233
‪TYPO3\CMS\Core\Resource\AbstractFile\getStorage
‪ResourceStorage getStorage()
Definition: AbstractFile.php:390
‪TYPO3\CMS\Core\Resource\ProcessedFile\isOutdated
‪bool isOutdated()
Definition: ProcessedFile.php:447
‪TYPO3\CMS\Core\Resource\ProcessedFile\$processingUrl
‪string $processingUrl
Definition: ProcessedFile.php:106