2 namespace TYPO3\CMS\Core\Resource
;
5 * This file is part of the TYPO3 CMS project.
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.
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
14 * The TYPO3 project - inspiring people to share!
17 use TYPO3\CMS\Core\Utility\PathUtility
;
20 * Abstract file representation in the file abstraction layer.
22 abstract class AbstractFile
implements FileInterface
25 * Various file properties
27 * Note that all properties, which only the persisted (indexed) files have are stored in this
28 * overall properties array only. The only properties which really exist as object properties of
29 * the file object are the storage, the identifier, the fileName and the indexing status.
33 protected $properties;
36 * The storage this file is located in
38 * @var ResourceStorage
40 protected $storage = null
;
43 * The identifier of this file to identify it on the storage.
44 * On some drivers, this is the path to the file, but drivers could also just
45 * provide any other unique identifier for this file on the specific storage.
49 protected $identifier;
52 * The file name of this file
59 * If set to true, this file is regarded as being deleted.
63 protected $deleted = false
;
68 const FILETYPE_UNKNOWN
= 0;
72 * @see http://www.iana.org/assignments/media-types/text
74 const FILETYPE_TEXT
= 1;
78 * @see http://www.iana.org/assignments/media-types/image
80 const FILETYPE_IMAGE
= 2;
83 * Any kind of audio file
84 * @see http://www.iana.org/assignments/media-types/audio
86 const FILETYPE_AUDIO
= 3;
90 * @see http://www.iana.org/assignments/media-types/video
92 const FILETYPE_VIDEO
= 4;
95 * Any kind of application
96 * @see http://www.iana.org/assignments/media-types/application
98 const FILETYPE_APPLICATION
= 5;
101 * VARIOUS FILE PROPERTY GETTERS
104 * Returns true if the given property key exists for this file.
109 public function hasProperty($key)
111 return array_key_exists($key, $this->properties
);
115 * Returns a property value
118 * @return mixed Property value
120 public function getProperty($key)
122 if ($this->hasProperty($key)) {
123 return $this->properties
[$key];
130 * Returns the properties of this object.
134 public function getProperties()
136 return $this->properties
;
140 * Returns the identifier of this file
144 public function getIdentifier()
146 return $this->identifier
;
150 * Get hashed identifier
154 public function getHashedIdentifier()
156 return $this->properties
['identifier_hash'];
160 * Returns the name of this file
164 public function getName()
166 // Do not check if file has been deleted because we might need the
167 // name for undeleting it.
172 * Returns the basename (the name without extension) of this file.
176 public function getNameWithoutExtension()
178 return PathUtility
::pathinfo($this->getName(), PATHINFO_FILENAME
);
182 * Returns the size of this file
184 * @throws \RuntimeException
187 public function getSize()
189 if ($this->deleted
) {
190 throw new \
RuntimeException('File has been deleted.', 1329821480);
192 return $this->properties
['size'] ?
: array_pop($this->getStorage()->getFileInfoByIdentifier($this->getIdentifier(), array('size')));
196 * Returns the uid of this file
200 public function getUid()
202 return $this->getProperty('uid');
206 * Returns the Sha1 of this file
208 * @throws \RuntimeException
211 public function getSha1()
213 if ($this->deleted
) {
214 throw new \
RuntimeException('File has been deleted.', 1329821481);
216 return $this->getStorage()->hashFile($this, 'sha1');
220 * Returns the creation time of the file as Unix timestamp
222 * @throws \RuntimeException
225 public function getCreationTime()
227 if ($this->deleted
) {
228 throw new \
RuntimeException('File has been deleted.', 1329821487);
230 return $this->getProperty('creation_date');
234 * Returns the date (as UNIX timestamp) the file was last modified.
236 * @throws \RuntimeException
239 public function getModificationTime()
241 if ($this->deleted
) {
242 throw new \
RuntimeException('File has been deleted.', 1329821488);
244 return $this->getProperty('modification_date');
248 * Get the extension of this file in a lower-case variant
250 * @return string The file extension
252 public function getExtension()
254 $pathinfo = PathUtility
::pathinfo($this->getName());
256 $extension = strtolower($pathinfo['extension']);
262 * Get the MIME type of this file
264 * @return string mime type
266 public function getMimeType()
268 return $this->properties
['mime_type'] ?
: array_pop($this->getStorage()->getFileInfoByIdentifier($this->getIdentifier(), array('mimetype')));
272 * Returns the fileType of this file
273 * basically there are only five main "file types"
280 * see the constants in this class
282 * @return int $fileType
284 public function getType()
286 // this basically extracts the mimetype and guess the filetype based
287 // on the first part of the mimetype works for 99% of all cases, and
288 // we don't need to make an SQL statement like EXT:media does currently
289 if (!$this->properties
['type']) {
290 $mimeType = $this->getMimeType();
291 list($fileType) = explode('/', $mimeType);
292 switch (strtolower($fileType)) {
294 $this->properties
['type'] = self
::FILETYPE_TEXT
;
297 $this->properties
['type'] = self
::FILETYPE_IMAGE
;
300 $this->properties
['type'] = self
::FILETYPE_AUDIO
;
303 $this->properties
['type'] = self
::FILETYPE_VIDEO
;
308 $this->properties
['type'] = self
::FILETYPE_APPLICATION
;
311 $this->properties
['type'] = self
::FILETYPE_UNKNOWN
;
314 return (int)$this->properties
['type'];
321 * Get the contents of this file
323 * @throws \RuntimeException
324 * @return string File contents
326 public function getContents()
328 if ($this->deleted
) {
329 throw new \
RuntimeException('File has been deleted.', 1329821479);
331 return $this->getStorage()->getFileContents($this);
335 * Replace the current file contents with the given string
337 * @param string $contents The contents to write to the file.
339 * @throws \RuntimeException
340 * @return File The file object (allows chaining).
342 public function setContents($contents)
344 if ($this->deleted
) {
345 throw new \
RuntimeException('File has been deleted.', 1329821478);
347 $this->getStorage()->setFileContents($this, $contents);
351 /****************************************
352 * STORAGE AND MANAGEMENT RELATED METHDOS
353 ****************************************/
356 * Get the storage this file is located in
358 * @return ResourceStorage
359 * @throws \RuntimeException
361 public function getStorage()
363 if ($this->storage
=== null
) {
364 throw new \
RuntimeException('You\'re using fileObjects without a storage.', 1381570091);
366 return $this->storage
;
370 * Checks if this file exists. This should normally always return TRUE;
371 * it might only return FALSE when this object has been created from an
372 * index record without checking for.
374 * @return bool TRUE if this file physically exists
376 public function exists()
378 if ($this->deleted
) {
381 return $this->storage
->hasFile($this->getIdentifier());
385 * Sets the storage this file is located in. This is only meant for
386 * \TYPO3\CMS\Core\Resource-internal usage; don't use it to move files.
388 * @internal Should only be used by other parts of the File API (e.g. drivers after moving a file)
389 * @param ResourceStorage $storage
392 public function setStorage(ResourceStorage
$storage)
394 $this->storage
= $storage;
395 $this->properties
['storage'] = $storage->getUid();
400 * Set the identifier of this file
402 * @internal Should only be used by other parts of the File API (e.g. drivers after moving a file)
403 * @param string $identifier
406 public function setIdentifier($identifier)
408 $this->identifier
= $identifier;
413 * Returns a combined identifier of this file, i.e. the storage UID and the
414 * folder identifier separated by a colon ":".
416 * @return string Combined storage and file identifier, e.g. StorageUID:path/and/fileName.png
418 public function getCombinedIdentifier()
420 if (is_array($this->properties
) && \TYPO3\CMS\Core\Utility\MathUtility
::canBeInterpretedAsInteger($this->properties
['storage'])) {
421 $combinedIdentifier = $this->properties
['storage'] . ':' . $this->getIdentifier();
423 $combinedIdentifier = $this->getStorage()->getUid() . ':' . $this->getIdentifier();
425 return $combinedIdentifier;
429 * Deletes this file from its storage. This also means that this object becomes useless.
431 * @return bool TRUE if deletion succeeded
433 public function delete()
435 // The storage will mark this file as deleted
436 return $this->getStorage()->deleteFile($this);
440 * Marks this file as deleted. This should only be used inside the
441 * File Abstraction Layer, as it is a low-level API method.
445 public function setDeleted()
447 $this->deleted
= true
;
451 * Returns TRUE if this file has been deleted
455 public function isDeleted()
457 return $this->deleted
;
463 * @param string $newName The new file name
465 * @throws \RuntimeException
468 public function rename($newName)
470 if ($this->deleted
) {
471 throw new \
RuntimeException('File has been deleted.', 1329821482);
473 return $this->getStorage()->renameFile($this, $newName);
477 * Copies this file into a target folder
479 * @param Folder $targetFolder Folder to copy file into.
480 * @param string $targetFileName an optional destination fileName
481 * @param string $conflictMode a value of the \TYPO3\CMS\Core\Resource\DuplicationBehavior enumeration
483 * @throws \RuntimeException
484 * @return File The new (copied) file.
486 public function copyTo(Folder
$targetFolder, $targetFileName = null
, $conflictMode = DuplicationBehavior
::RENAME
)
488 if ($this->deleted
) {
489 throw new \
RuntimeException('File has been deleted.', 1329821483);
491 return $targetFolder->getStorage()->copyFile($this, $targetFolder, $targetFileName, $conflictMode);
495 * Moves the file into the target folder
497 * @param Folder $targetFolder Folder to move file into.
498 * @param string $targetFileName an optional destination fileName
499 * @param string $conflictMode a value of the \TYPO3\CMS\Core\Resource\DuplicationBehavior enumeration
501 * @throws \RuntimeException
502 * @return File This file object, with updated properties.
504 public function moveTo(Folder
$targetFolder, $targetFileName = null
, $conflictMode = DuplicationBehavior
::RENAME
)
506 if ($this->deleted
) {
507 throw new \
RuntimeException('File has been deleted.', 1329821484);
509 return $targetFolder->getStorage()->moveFile($this, $targetFolder, $targetFileName, $conflictMode);
516 * Returns a publicly accessible URL for this file
518 * WARNING: Access to the file may be restricted by further means, e.g. some
519 * web-based authentication. You have to take care of this yourself.
521 * @param bool $relativeToCurrentScript Determines whether the URL returned should be relative to the current script, in case it is relative at all (only for the LocalDriver)
522 * @return NULL|string NULL if file is deleted, the generated URL otherwise
524 public function getPublicUrl($relativeToCurrentScript = false
)
526 if ($this->deleted
) {
529 return $this->getStorage()->getPublicUrl($this, $relativeToCurrentScript);
534 * Returns a path to a local version of this file to process it locally (e.g. with some system tool).
535 * If the file is normally located on a remote storages, this creates a local copy.
536 * If the file is already on the local system, this only makes a new copy if $writable is set to TRUE.
538 * @param bool $writable Set this to FALSE if you only want to do read operations on the file.
540 * @throws \RuntimeException
543 public function getForLocalProcessing($writable = true
)
545 if ($this->deleted
) {
546 throw new \
RuntimeException('File has been deleted.', 1329821486);
548 return $this->getStorage()->getFileForLocalProcessing($this, $writable);
551 /***********************
552 * INDEX RELATED METHODS
553 ***********************/
555 * Updates properties of this object.
556 * This method is used to reconstitute settings from the
557 * database into this object after being intantiated.
559 * @param array $properties
561 abstract public function updateProperties(array $properties);
564 * Returns the parent folder.
566 * @return FolderInterface
568 public function getParentFolder()
570 return $this->getStorage()->getFolder($this->getStorage()->getFolderIdentifierFromFileIdentifier($this->getIdentifier()));