TYPO3 CMS  TYPO3_6-2
ProcessedFile.php
Go to the documentation of this file.
1 <?php
3 
40 class ProcessedFile extends AbstractFile {
41 
42  /*********************************************
43  * FILE PROCESSING CONTEXTS
44  *********************************************/
49  const CONTEXT_IMAGEPREVIEW = 'Image.Preview';
55  const CONTEXT_IMAGECROPSCALEMASK = 'Image.CropScaleMask';
56 
62  protected $taskType;
63 
67  protected $task;
68 
72  protected $taskTypeRegistry;
73 
80 
86  protected $originalFile;
87 
95  protected $originalFileSha1;
96 
103  protected $updated = FALSE;
104 
114  public function __construct(File $originalFile, $taskType, array $processingConfiguration, array $databaseRow = NULL) {
115  $this->originalFile = $originalFile;
116  $this->storage = $originalFile->getStorage()->getProcessingFolder()->getStorage();
117  $this->taskType = $taskType;
118  $this->processingConfiguration = $processingConfiguration;
119  if (is_array($databaseRow)) {
120  $this->reconstituteFromDatabaseRecord($databaseRow);
121  }
122  $this->taskTypeRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\Processing\\TaskTypeRegistry');
123  }
124 
131  protected function reconstituteFromDatabaseRecord(array $databaseRow) {
132  $this->taskType = $this->taskType ?: $databaseRow['task_type'];
133  $this->processingConfiguration = $this->processingConfiguration ?: unserialize($databaseRow['configuration']);
134 
135  $this->originalFileSha1 = $databaseRow['originalfilesha1'];
136  $this->identifier = $databaseRow['identifier'];
137  $this->name = $databaseRow['name'];
138  $this->properties = $databaseRow;
139  }
140 
141  /********************************
142  * VARIOUS FILE PROPERTY GETTERS
143  ********************************/
144 
150  // TODO replace these usages with direct calls to the task object
151  public function calculateChecksum() {
152  return $this->getTask()->getConfigurationChecksum();
153  }
154 
155  /*******************
156  * CONTENTS RELATED
157  *******************/
165  public function setContents($contents) {
166  throw new \BadMethodCallException('Setting contents not possible for processed file.', 1305438528);
167  }
168 
176  public function updateWithLocalFile($filePath) {
177  if ($this->identifier === NULL) {
178  throw new \RuntimeException('Cannot update original file!', 1350582054);
179  }
180  $processingFolder = $this->originalFile->getStorage()->getProcessingFolder();
181  $addedFile = $this->storage->updateProcessedFile($filePath, $this, $processingFolder);
182 
183  // Update some related properties
184  $this->identifier = $addedFile->getIdentifier();
185  $this->originalFileSha1 = $this->originalFile->getSha1();
186  $this->updateProperties($addedFile->getProperties());
187  $this->deleted = FALSE;
188  $this->updated = TRUE;
189  }
190 
191  /*****************************************
192  * STORAGE AND MANAGEMENT RELATED METHDOS
193  *****************************************/
199  public function isIndexed() {
200  // Processed files are never indexed; instead you might be looking for isPersisted()
201  return FALSE;
202  }
203 
209  public function isPersisted() {
210  return is_array($this->properties) && array_key_exists('uid', $this->properties) && $this->properties['uid'] > 0;
211  }
212 
218  public function isNew() {
219  return !$this->isPersisted();
220  }
221 
228  public function isUpdated() {
229  return $this->updated;
230  }
231 
237  public function setName($name) {
238  // Remove the existing file
239  if ($this->name !== $name && $this->name !== '' && $this->exists()) {
240  $this->delete();
241  }
242 
243  $this->name = $name;
244  // TODO this is a *weird* hack that will fail if the storage is non-hierarchical!
245  $this->identifier = $this->storage->getProcessingFolder()->getIdentifier() . $this->name;
246 
247  $this->updated = TRUE;
248  }
249 
250  /******************
251  * SPECIAL METHODS
252  ******************/
253 
259  public function isProcessed() {
260  return $this->updated || ($this->isPersisted() && !$this->needsReprocessing());
261  }
262 
268  public function getOriginalFile() {
269  return $this->originalFile;
270  }
271 
281  public function getIdentifier() {
282  return (!$this->usesOriginalFile()) ? $this->identifier : $this->getOriginalFile()->getIdentifier();
283  }
284 
294  public function getName() {
295  if ($this->usesOriginalFile()) {
296  return $this->originalFile->getName();
297  } else {
298  return $this->name;
299  }
300  }
301 
308  public function updateProperties(array $properties) {
309  if (!is_array($this->properties)) {
310  $this->properties = array();
311  }
312 
313  if (array_key_exists('uid', $properties) && \TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($properties['uid'])) {
314  $this->properties['uid'] = $properties['uid'];
315  }
316 
317  // TODO we should have a blacklist of properties that might not be updated
318  $this->properties = array_merge($this->properties, $properties);
319 
320  // TODO when should this update be done?
321  if (!$this->isUnchanged() && $this->exists()) {
322  $this->properties = array_merge($this->properties, $this->storage->getFileInfo($this));
323  }
324 
325  }
326 
332  public function toArray() {
333  if ($this->usesOriginalFile()) {
334  $properties = $this->originalFile->getProperties();
335  unset($properties['uid']);
336  unset($properties['pid']);
337  unset($properties['identifier']);
338  unset($properties['name']);
339  unset($properties['width']);
340  unset($properties['height']);
341  } else {
343  $properties['identifier'] = $this->getIdentifier();
344  $properties['name'] = $this->getName();
345  }
346 
347  $properties['configuration'] = serialize($this->processingConfiguration);
348 
349  return array_merge($properties, array(
350  'storage' => $this->getStorage()->getUid(),
351  'checksum' => $this->calculateChecksum(),
352  'task_type' => $this->taskType,
353  'configurationsha1' => sha1($properties['configuration']),
354  'original' => $this->originalFile->getUid(),
355  'originalfilesha1' => $this->originalFileSha1
356  ));
357  }
358 
364  protected function isUnchanged() {
365  return $this->identifier == NULL || $this->identifier === $this->originalFile->getIdentifier();
366  }
367 
371  public function setUsesOriginalFile() {
372  // TODO check if some of these properties can/should be set in a generic update method
373  $this->identifier = $this->originalFile->getIdentifier();
374  $this->updated = TRUE;
375  $this->originalFileSha1 = $this->originalFile->getSha1();
376  }
377 
381  public function usesOriginalFile() {
382  return $this->isUnchanged();
383  }
384 
390  public function isOutdated() {
391  return $this->needsReprocessing();
392  }
393 
400  public function delete($force = FALSE) {
401  if (!$force && $this->isUnchanged()) {
402  return FALSE;
403  }
404  // Only delete file when original isn't used
405  if (!$this->usesOriginalFile()) {
406  return parent::delete();
407  } else {
408  return TRUE;
409  }
410  }
411 
419  public function getProperty($key) {
420  // The uid always (!) has to come from this file and never the original file (see getOriginalFile() to get this)
421  if ($this->isUnchanged() && $key !== 'uid') {
422  return $this->originalFile->getProperty($key);
423  } else {
424  return $this->properties[$key];
425  }
426  }
427 
433  public function getUid() {
434  return $this->properties['uid'];
435  }
436 
437 
443  public function needsReprocessing() {
444  $fileMustBeRecreated = FALSE;
445 
446  // if original is missing we can not reprocess the file
447  if ($this->originalFile->isMissing()) {
448  return FALSE;
449  }
450 
451  // processedFile does not exist
452  if (!$this->usesOriginalFile() && !$this->exists()) {
453  $fileMustBeRecreated = TRUE;
454  }
455 
456  // hash does not match
457  if (array_key_exists('checksum', $this->properties) && $this->calculateChecksum() !== $this->properties['checksum']) {
458  $fileMustBeRecreated = TRUE;
459  }
460 
461  // original file changed
462  if ($this->originalFile->getSha1() !== $this->originalFileSha1) {
463  $fileMustBeRecreated = TRUE;
464  }
465 
466  if (!array_key_exists('uid', $this->properties)) {
467  $fileMustBeRecreated = TRUE;
468  }
469 
470  // remove outdated file
471  if ($fileMustBeRecreated && $this->exists()) {
472  $this->delete();
473  }
474  return $fileMustBeRecreated;
475  }
476 
482  public function getProcessingConfiguration() {
484  }
485 
491  public function getTaskIdentifier() {
492  return $this->taskType;
493  }
494 
501  public function getTask() {
502  if ($this->task == NULL) {
503  $this->task = $this->taskTypeRegistry->getTaskForType($this->taskType, $this, $this->processingConfiguration);
504  }
505 
506  return $this->task;
507  }
508 
515  $name = $this->originalFile->getNameWithoutExtension();
516  $name .= '_' . $this->originalFile->getUid();
517  $name .= '_' . $this->calculateChecksum();
518 
519  return $name;
520  }
521 
528  public function getPublicUrl($relativeToCurrentScript = FALSE) {
529  if ($this->deleted) {
530  return NULL;
531  } elseif ($this->usesOriginalFile()) {
532  return $this->getOriginalFile()->getPublicUrl($relativeToCurrentScript);
533  } else {
534  return $this->getStorage()->getPublicUrl($this, $relativeToCurrentScript);
535  }
536  }
537 }
__construct(File $originalFile, $taskType, array $processingConfiguration, array $databaseRow=NULL)
reconstituteFromDatabaseRecord(array $databaseRow)
getPublicUrl($relativeToCurrentScript=FALSE)