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\MathUtility
;
18 use TYPO3\CMS\Core\Utility\PathUtility
;
21 * Abstract file representation in the file abstraction layer.
23 abstract class AbstractFile
implements FileInterface
26 * Various file properties
28 * Note that all properties, which only the persisted (indexed) files have are stored in this
29 * overall properties array only. The only properties which really exist as object properties of
30 * the file object are the storage, the identifier, the fileName and the indexing status.
34 protected $properties;
37 * The storage this file is located in
39 * @var ResourceStorage
41 protected $storage = null;
44 * The identifier of this file to identify it on the storage.
45 * On some drivers, this is the path to the file, but drivers could also just
46 * provide any other unique identifier for this file on the specific storage.
50 protected $identifier;
53 * The file name of this file
60 * If set to true, this file is regarded as being deleted.
64 protected $deleted = false;
69 const FILETYPE_UNKNOWN
= 0;
73 * @see http://www.iana.org/assignments/media-types/text
75 const FILETYPE_TEXT
= 1;
79 * @see http://www.iana.org/assignments/media-types/image
81 const FILETYPE_IMAGE
= 2;
84 * Any kind of audio file
85 * @see http://www.iana.org/assignments/media-types/audio
87 const FILETYPE_AUDIO
= 3;
91 * @see http://www.iana.org/assignments/media-types/video
93 const FILETYPE_VIDEO
= 4;
96 * Any kind of application
97 * @see http://www.iana.org/assignments/media-types/application
99 const FILETYPE_APPLICATION
= 5;
102 * VARIOUS FILE PROPERTY GETTERS
105 * Returns true if the given property key exists for this file.
110 public function hasProperty($key)
112 return array_key_exists($key, $this->properties
);
116 * Returns a property value
119 * @return mixed Property value
121 public function getProperty($key)
123 if ($this->hasProperty($key)) {
124 return $this->properties
[$key];
131 * Returns the properties of this object.
135 public function getProperties()
137 return $this->properties
;
141 * Returns the identifier of this file
145 public function getIdentifier()
147 return $this->identifier
;
151 * Get hashed identifier
155 public function getHashedIdentifier()
157 return $this->properties
['identifier_hash'];
161 * Returns the name of this file
165 public function getName()
167 // Do not check if file has been deleted because we might need the
168 // name for undeleting it.
173 * Returns the basename (the name without extension) of this file.
177 public function getNameWithoutExtension()
179 return PathUtility
::pathinfo($this->getName(), PATHINFO_FILENAME
);
183 * Returns the size of this file
185 * @throws \RuntimeException
186 * @return int|null Returns null if size is not available for the file
188 public function getSize()
190 if ($this->deleted
) {
191 throw new \
RuntimeException('File has been deleted.', 1329821480);
193 if (empty($this->properties
['size'])) {
194 $size = array_pop($this->getStorage()->getFileInfoByIdentifier($this->getIdentifier(), ['size']));
196 $size = $this->properties
['size'];
198 return $size ?
(int)$size : null;
202 * Returns the uid of this file
206 public function getUid()
208 return (int)$this->getProperty('uid');
212 * Returns the Sha1 of this file
214 * @throws \RuntimeException
217 public function getSha1()
219 if ($this->deleted
) {
220 throw new \
RuntimeException('File has been deleted.', 1329821481);
222 return $this->getStorage()->hashFile($this, 'sha1');
226 * Returns the creation time of the file as Unix timestamp
228 * @throws \RuntimeException
231 public function getCreationTime()
233 if ($this->deleted
) {
234 throw new \
RuntimeException('File has been deleted.', 1329821487);
236 return (int)$this->getProperty('creation_date');
240 * Returns the date (as UNIX timestamp) the file was last modified.
242 * @throws \RuntimeException
245 public function getModificationTime()
247 if ($this->deleted
) {
248 throw new \
RuntimeException('File has been deleted.', 1329821488);
250 return (int)$this->getProperty('modification_date');
254 * Get the extension of this file in a lower-case variant
256 * @return string The file extension
258 public function getExtension()
260 $pathinfo = PathUtility
::pathinfo($this->getName());
262 $extension = strtolower($pathinfo['extension']);
268 * Get the MIME type of this file
270 * @return string mime type
272 public function getMimeType()
274 return $this->properties
['mime_type'] ?
: array_pop($this->getStorage()->getFileInfoByIdentifier($this->getIdentifier(), ['mimetype']));
278 * Returns the fileType of this file
279 * basically there are only five main "file types"
286 * see the constants in this class
288 * @return int $fileType
290 public function getType()
292 // this basically extracts the mimetype and guess the filetype based
293 // on the first part of the mimetype works for 99% of all cases, and
294 // we don't need to make an SQL statement like EXT:media does currently
295 if (!$this->properties
['type']) {
296 $mimeType = $this->getMimeType();
297 list($fileType) = explode('/', $mimeType);
298 switch (strtolower($fileType)) {
300 $this->properties
['type'] = self
::FILETYPE_TEXT
;
303 $this->properties
['type'] = self
::FILETYPE_IMAGE
;
306 $this->properties
['type'] = self
::FILETYPE_AUDIO
;
309 $this->properties
['type'] = self
::FILETYPE_VIDEO
;
314 $this->properties
['type'] = self
::FILETYPE_APPLICATION
;
317 $this->properties
['type'] = self
::FILETYPE_UNKNOWN
;
320 return (int)$this->properties
['type'];
327 * Get the contents of this file
329 * @throws \RuntimeException
330 * @return string File contents
332 public function getContents()
334 if ($this->deleted
) {
335 throw new \
RuntimeException('File has been deleted.', 1329821479);
337 return $this->getStorage()->getFileContents($this);
341 * Replace the current file contents with the given string
343 * @param string $contents The contents to write to the file.
345 * @throws \RuntimeException
346 * @return File The file object (allows chaining).
348 public function setContents($contents)
350 if ($this->deleted
) {
351 throw new \
RuntimeException('File has been deleted.', 1329821478);
353 $this->getStorage()->setFileContents($this, $contents);
357 /****************************************
358 * STORAGE AND MANAGEMENT RELATED METHDOS
359 ****************************************/
362 * Get the storage this file is located in
364 * @return ResourceStorage
365 * @throws \RuntimeException
367 public function getStorage()
369 if ($this->storage
=== null) {
370 throw new \
RuntimeException('You\'re using fileObjects without a storage.', 1381570091);
372 return $this->storage
;
376 * Checks if this file exists. This should normally always return TRUE;
377 * it might only return FALSE when this object has been created from an
378 * index record without checking for.
380 * @return bool TRUE if this file physically exists
382 public function exists()
384 if ($this->deleted
) {
387 return $this->storage
->hasFile($this->getIdentifier());
391 * Sets the storage this file is located in. This is only meant for
392 * \TYPO3\CMS\Core\Resource-internal usage; don't use it to move files.
394 * @internal Should only be used by other parts of the File API (e.g. drivers after moving a file)
395 * @param ResourceStorage $storage
398 public function setStorage(ResourceStorage
$storage)
400 $this->storage
= $storage;
401 $this->properties
['storage'] = $storage->getUid();
406 * Set the identifier of this file
408 * @internal Should only be used by other parts of the File API (e.g. drivers after moving a file)
409 * @param string $identifier
412 public function setIdentifier($identifier)
414 $this->identifier
= $identifier;
419 * Returns a combined identifier of this file, i.e. the storage UID and the
420 * folder identifier separated by a colon ":".
422 * @return string Combined storage and file identifier, e.g. StorageUID:path/and/fileName.png
424 public function getCombinedIdentifier()
426 if (is_array($this->properties
) && MathUtility
::canBeInterpretedAsInteger($this->properties
['storage'])) {
427 $combinedIdentifier = $this->properties
['storage'] . ':' . $this->getIdentifier();
429 $combinedIdentifier = $this->getStorage()->getUid() . ':' . $this->getIdentifier();
431 return $combinedIdentifier;
435 * Deletes this file from its storage. This also means that this object becomes useless.
437 * @return bool TRUE if deletion succeeded
439 public function delete()
441 // The storage will mark this file as deleted
442 return $this->getStorage()->deleteFile($this);
446 * Marks this file as deleted. This should only be used inside the
447 * File Abstraction Layer, as it is a low-level API method.
449 public function setDeleted()
451 // Unset all properties when deleting the file, as they will be stale anyway
452 $this->properties
= null;
453 $this->deleted
= true;
457 * Returns TRUE if this file has been deleted
461 public function isDeleted()
463 return $this->deleted
;
469 * @param string $newName The new file name
471 * @param string $conflictMode
472 * @return FileInterface
474 public function rename($newName, $conflictMode = DuplicationBehavior
::RENAME
)
476 if ($this->deleted
) {
477 throw new \
RuntimeException('File has been deleted.', 1329821482);
479 return $this->getStorage()->renameFile($this, $newName, $conflictMode);
483 * Copies this file into a target folder
485 * @param Folder $targetFolder Folder to copy file into.
486 * @param string $targetFileName an optional destination fileName
487 * @param string $conflictMode a value of the \TYPO3\CMS\Core\Resource\DuplicationBehavior enumeration
489 * @throws \RuntimeException
490 * @return File The new (copied) file.
492 public function copyTo(Folder
$targetFolder, $targetFileName = null, $conflictMode = DuplicationBehavior
::RENAME
)
494 if ($this->deleted
) {
495 throw new \
RuntimeException('File has been deleted.', 1329821483);
497 return $targetFolder->getStorage()->copyFile($this, $targetFolder, $targetFileName, $conflictMode);
501 * Moves the file into the target folder
503 * @param Folder $targetFolder Folder to move file into.
504 * @param string $targetFileName an optional destination fileName
505 * @param string $conflictMode a value of the \TYPO3\CMS\Core\Resource\DuplicationBehavior enumeration
507 * @throws \RuntimeException
508 * @return File This file object, with updated properties.
510 public function moveTo(Folder
$targetFolder, $targetFileName = null, $conflictMode = DuplicationBehavior
::RENAME
)
512 if ($this->deleted
) {
513 throw new \
RuntimeException('File has been deleted.', 1329821484);
515 return $targetFolder->getStorage()->moveFile($this, $targetFolder, $targetFileName, $conflictMode);
522 * Returns a publicly accessible URL for this file
524 * WARNING: Access to the file may be restricted by further means, e.g. some
525 * web-based authentication. You have to take care of this yourself.
527 * @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)
528 * @return NULL|string NULL if file is deleted, the generated URL otherwise
530 public function getPublicUrl($relativeToCurrentScript = false)
532 if ($this->deleted
) {
535 return $this->getStorage()->getPublicUrl($this, $relativeToCurrentScript);
540 * Returns a path to a local version of this file to process it locally (e.g. with some system tool).
541 * If the file is normally located on a remote storages, this creates a local copy.
542 * If the file is already on the local system, this only makes a new copy if $writable is set to TRUE.
544 * @param bool $writable Set this to FALSE if you only want to do read operations on the file.
546 * @throws \RuntimeException
549 public function getForLocalProcessing($writable = true)
551 if ($this->deleted
) {
552 throw new \
RuntimeException('File has been deleted.', 1329821486);
554 return $this->getStorage()->getFileForLocalProcessing($this, $writable);
557 /***********************
558 * INDEX RELATED METHODS
559 ***********************/
561 * Updates properties of this object.
562 * This method is used to reconstitute settings from the
563 * database into this object after being intantiated.
565 * @param array $properties
567 abstract public function updateProperties(array $properties);
570 * Returns the parent folder.
572 * @return FolderInterface
574 public function getParentFolder()
576 return $this->getStorage()->getFolder($this->getStorage()->getFolderIdentifierFromFileIdentifier($this->getIdentifier()));