[BUGFIX] FAL: Image Processing doesn't respect GFX "thumbnails_png"
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Resource / Folder.php
index 1a87e84..c747b4f 100644 (file)
@@ -4,7 +4,7 @@ namespace TYPO3\CMS\Core\Resource;
 /***************************************************************
  *  Copyright notice
  *
- *  (c) 2011 Andreas Wolf <andreas.wolf@ikt-werk.de>
+ *  (c) 2011-2013 Andreas Wolf <andreas.wolf@ikt-werk.de>
  *  All rights reserved
  *
  *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -26,6 +26,9 @@ namespace TYPO3\CMS\Core\Resource;
  *
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
+
+use TYPO3\CMS\Core\Utility\PathUtility;
+
 /**
  * A folder that groups files in a storage. This may be a folder on the local
  * disk, a bucket in Amazon S3 or a user or a tag in Flickr.
@@ -40,15 +43,13 @@ namespace TYPO3\CMS\Core\Resource;
  *
  * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
  * @author Ingmar Schlecht <ingmar@typo3.org>
- * @package TYPO3
- * @subpackage t3lib
  */
-class Folder implements \TYPO3\CMS\Core\Resource\FolderInterface {
+class Folder implements FolderInterface {
 
        /**
         * The storage this folder belongs to.
         *
-        * @var \TYPO3\CMS\Core\Resource\ResourceStorage
+        * @var ResourceStorage
         */
        protected $storage;
 
@@ -69,13 +70,31 @@ class Folder implements \TYPO3\CMS\Core\Resource\FolderInterface {
        protected $name;
 
        /**
+        * The filters this folder should use for a file list.
+        *
+        * @var callable[]
+        */
+       protected $fileAndFolderNameFilters = array();
+
+       /**
+        * Modes for filter usage in getFiles()/getFolders()
+        */
+       const FILTER_MODE_NO_FILTERS = 0;
+       // Merge local filters into storage's filters
+       const FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS = 1;
+       // Only use the filters provided by the storage
+       const FILTER_MODE_USE_STORAGE_FILTERS = 2;
+       // Only use the filters provided by the current class
+       const FILTER_MODE_USE_OWN_FILTERS = 3;
+
+       /**
         * Initialization of the folder
         *
-        * @param \TYPO3\CMS\Core\Resource\ResourceStorage $storage
+        * @param ResourceStorage $storage
         * @param $identifier
         * @param $name
         */
-       public function __construct(\TYPO3\CMS\Core\Resource\ResourceStorage $storage, $identifier, $name) {
+       public function __construct(ResourceStorage $storage, $identifier, $name) {
                $this->storage = $storage;
                $this->identifier = rtrim($identifier, '/') . '/';
                $this->name = $name;
@@ -105,7 +124,7 @@ class Folder implements \TYPO3\CMS\Core\Resource\FolderInterface {
        /**
         * Returns the storage this folder belongs to.
         *
-        * @return \TYPO3\CMS\Core\Resource\ResourceStorage
+        * @return ResourceStorage
         */
        public function getStorage() {
                return $this->storage;
@@ -151,23 +170,46 @@ class Folder implements \TYPO3\CMS\Core\Resource\FolderInterface {
        }
 
        /**
-        * Returns a list of files in this folder, optionally filtered by the given pattern.
-        * For performance reasons the returned items can be limited to a given range
+        * Returns a list of files in this folder, optionally filtered. There are several filter modes available, see the
+        * FILTER_MODE_* constants for more information.
+        *
+        * For performance reasons the returned items can also be limited to a given range
         *
         * @param integer $start The item to start at
         * @param integer $numberOfItems The number of items to return
-        * @param boolean $useFilters
-        * @return \TYPO3\CMS\Core\Resource\File[]
+        * @param integer $filterMode The filter mode to use for the file list.
+        * @param boolean $recursive
+        * @return File[]
         */
-       public function getFiles($start = 0, $numberOfItems = 0, $useFilters = TRUE) {
-               // TODO fetch
-               /** @var $factory \TYPO3\CMS\Core\Resource\ResourceFactory */
+       public function getFiles($start = 0, $numberOfItems = 0, $filterMode = self::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS, $recursive = FALSE) {
+               $useFilters = TRUE;
+
+               // Fallback for compatibility with the old method signature variable $useFilters that was used instead of $filterMode
+               if ($filterMode === TRUE) {
+                       $filterMode = self::FILTER_MODE_USE_STORAGE_FILTERS;
+               } elseif ($filterMode === FALSE) {
+                       $useFilters = FALSE;
+               } else {
+                       list($backedUpFilters, $useFilters) = $this->prepareFiltersInStorage($filterMode);
+               }
+
+               /** @var $factory ResourceFactory */
                $factory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\ResourceFactory');
-               $fileArray = $this->storage->getFileList($this->identifier, $start, $numberOfItems, $useFilters);
+               $fileArray = $this->storage->getFileList($this->identifier, $start, $numberOfItems, $useFilters, TRUE, $recursive);
                $fileObjects = array();
                foreach ($fileArray as $fileInfo) {
-                       $fileObjects[] = $factory->createFileObject($fileInfo);
+                       $fileObject = $factory->createFileObject($fileInfo);
+
+                       // we might have duplicate filenames when fetching a recursive list, so don't use the filename as array key
+                       if ($recursive == TRUE) {
+                               $fileObjects[] = $fileObject;
+                       } else {
+                               $fileObjects[$fileInfo['name']] = $fileObject;
+                       }
                }
+
+               $this->restoreBackedUpFiltersInStorage($backedUpFilters);
+
                return $fileObjects;
        }
 
@@ -176,49 +218,56 @@ class Folder implements \TYPO3\CMS\Core\Resource\FolderInterface {
         * the given pattern
         *
         * @param array $filterMethods
+        * @param boolean $recursive
+        *
         * @return integer
         */
-       public function getFileCount(array $filterMethods = array()) {
+       public function getFileCount(array $filterMethods = array(), $recursive = FALSE) {
                // TODO replace by call to count()
-               return count($this->storage->getFileList($this->identifier, 0, 0, $filterMethods));
+               return count($this->storage->getFileList($this->identifier, 0, 0, $filterMethods, FALSE, $recursive));
        }
 
        /**
         * Returns the object for a subfolder of the current folder, if it exists.
         *
         * @param string $name Name of the subfolder
-        * @return \TYPO3\CMS\Core\Resource\Folder
+        *
+        * @throws \InvalidArgumentException
+        * @return Folder
         */
        public function getSubfolder($name) {
                if (!$this->storage->hasFolderInFolder($name, $this)) {
                        throw new \InvalidArgumentException('Folder "' . $name . '" does not exist in "' . $this->identifier . '"', 1329836110);
                }
-               // TODO this will not work with non-hierarchical storages -> the identifier for subfolders is not composed of
-               // the current item's identifier for these
-               /** @var $factory \TYPO3\CMS\Core\Resource\ResourceFactory */
-               $factory = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance();
+               /** @var $factory ResourceFactory */
+               $factory = ResourceFactory::getInstance();
                $folderObject = $factory->createFolderObject($this->storage, $this->identifier . $name . '/', $name);
                return $folderObject;
        }
 
        /**
-        * Returns a list of all subfolders
+        * Returns a list of subfolders
         *
-        * @return \TYPO3\CMS\Core\Resource\Folder[]
+        * @param integer $start The item to start at
+        * @param integer $numberOfItems The number of items to return
+        * @param integer $filterMode The filter mode to use for the file list.
+        * @return Folder[]
         */
-       public function getSubfolders() {
+       public function getSubfolders($start = 0, $numberOfItems = 0, $filterMode = self::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS) {
+               list($backedUpFilters, $useFilters) = $this->prepareFiltersInStorage($filterMode);
+
                $folderObjects = array();
-               $folderArray = $this->storage->getFolderList($this->identifier);
+               $folderArray = $this->storage->getFolderList($this->identifier, $start, $numberOfItems, $useFilters);
                if (count($folderArray) > 0) {
-                       /** @var $factory \TYPO3\CMS\Core\Resource\ResourceFactory */
+                       /** @var $factory ResourceFactory */
                        $factory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\ResourceFactory');
-                       // TODO this will not work with non-hierarchical storages
-                       // -> the identifier for subfolders is not composed of the
-                       // current item's identifier for these
                        foreach ($folderArray as $folder) {
-                               $folderObjects[] = $factory->createFolderObject($this->storage, $this->identifier . $folder['name'] . '/', $folder['name']);
+                               $folderObjects[$folder['name']] = $factory->createFolderObject($this->storage, $folder['identifier'], $folder['name']);
                        }
                }
+
+               $this->restoreBackedUpFiltersInStorage($backedUpFilters);
+
                return $folderObjects;
        }
 
@@ -229,10 +278,10 @@ class Folder implements \TYPO3\CMS\Core\Resource\FolderInterface {
         * @param string $localFilePath
         * @param string $fileName
         * @param string $conflictMode possible value are 'cancel', 'replace'
-        * @return \TYPO3\CMS\Core\Resource\File The file object
+        * @return File The file object
         */
        public function addFile($localFilePath, $fileName = NULL, $conflictMode = 'cancel') {
-               $fileName = $fileName ? $fileName : basename($localFilePath);
+               $fileName = $fileName ? $fileName : PathUtility::basename($localFilePath);
                return $this->storage->addFile($localFilePath, $this, $fileName, $conflictMode);
        }
 
@@ -241,7 +290,7 @@ class Folder implements \TYPO3\CMS\Core\Resource\FolderInterface {
         *
         * @param array $uploadedFileData contains information about the uploaded file given by $_FILES['file1']
         * @param string $conflictMode possible value are 'cancel', 'replace'
-        * @return \TYPO3\CMS\Core\Resource\File The file object
+        * @return File The file object
         */
        public function addUploadedFile(array $uploadedFileData, $conflictMode = 'cancel') {
                return $this->storage->addUploadedFile($uploadedFileData, $this, $uploadedFileData['name'], $conflictMode);
@@ -251,7 +300,7 @@ class Folder implements \TYPO3\CMS\Core\Resource\FolderInterface {
         * Renames this folder.
         *
         * @param string $newName
-        * @return \TYPO3\CMS\Core\Resource\Folder
+        * @return Folder
         */
        public function rename($newName) {
                return $this->storage->renameFolder($this, $newName);
@@ -271,7 +320,7 @@ class Folder implements \TYPO3\CMS\Core\Resource\FolderInterface {
         * Creates a new blank file
         *
         * @param string $fileName
-        * @return \TYPO3\CMS\Core\Resource\File The new file object
+        * @return File The new file object
         */
        public function createFile($fileName) {
                return $this->storage->createFile($fileName, $this);
@@ -281,7 +330,7 @@ class Folder implements \TYPO3\CMS\Core\Resource\FolderInterface {
         * Creates a new folder
         *
         * @param string $folderName
-        * @return \TYPO3\CMS\Core\Resource\Folder The new folder object
+        * @return Folder The new folder object
         */
        public function createFolder($folderName) {
                return $this->storage->createFolder($folderName, $this);
@@ -290,25 +339,25 @@ class Folder implements \TYPO3\CMS\Core\Resource\FolderInterface {
        /**
         * Copies folder to a target folder
         *
-        * @param \TYPO3\CMS\Core\Resource\Folder $targetFolder Target folder to copy to.
+        * @param Folder $targetFolder Target folder to copy to.
         * @param string $targetFolderName an optional destination fileName
         * @param string $conflictMode "overrideExistingFile", "renameNewFile" or "cancel
-        * @return \TYPO3\CMS\Core\Resource\Folder New (copied) folder object.
+        * @return Folder New (copied) folder object.
         */
-       public function copyTo(\TYPO3\CMS\Core\Resource\Folder $targetFolder, $targetFolderName = NULL, $conflictMode = 'renameNewFile') {
-               return $this->storage->copyFolder($this, $targetFolder, $targetFolderName, $conflictMode);
+       public function copyTo(Folder $targetFolder, $targetFolderName = NULL, $conflictMode = 'renameNewFile') {
+               return $targetFolder->getStorage()->copyFolder($this, $targetFolder, $targetFolderName, $conflictMode);
        }
 
        /**
         * Moves folder to a target folder
         *
-        * @param \TYPO3\CMS\Core\Resource\Folder $targetFolder Target folder to move to.
+        * @param Folder $targetFolder Target folder to move to.
         * @param string $targetFolderName an optional destination fileName
         * @param string $conflictMode "overrideExistingFile", "renameNewFile" or "cancel
-        * @return \TYPO3\CMS\Core\Resource\Folder New (copied) folder object.
+        * @return Folder New (copied) folder object.
         */
-       public function moveTo(\TYPO3\CMS\Core\Resource\Folder $targetFolder, $targetFolderName = NULL, $conflictMode = 'renameNewFile') {
-               return $this->storage->moveFolder($this, $targetFolder, $targetFolderName, $conflictMode);
+       public function moveTo(Folder $targetFolder, $targetFolderName = NULL, $conflictMode = 'renameNewFile') {
+               return $targetFolder->getStorage()->moveFolder($this, $targetFolder, $targetFolderName, $conflictMode);
        }
 
        /**
@@ -360,7 +409,77 @@ class Folder implements \TYPO3\CMS\Core\Resource\FolderInterface {
                }
        }
 
-}
+       /**
+        * Prepares the filters in this folder's storage according to a set filter mode.
+        *
+        * @param integer $filterMode The filter mode to use; one of the FILTER_MODE_* constants
+        * @return array The backed up filters as an array (NULL if filters were not backed up) and whether to use filters or not (boolean)
+        */
+       protected function prepareFiltersInStorage($filterMode) {
+               $backedUpFilters = NULL;
+               $useFilters = TRUE;
+
+               switch ($filterMode) {
+                       case self::FILTER_MODE_USE_OWN_FILTERS:
+                               $backedUpFilters = $this->storage->getFileAndFolderNameFilters();
+                               $this->storage->setFileAndFolderNameFilters($this->fileAndFolderNameFilters);
+
+                               break;
+
+                       case self::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS:
+                               if (count($this->fileAndFolderNameFilters) > 0) {
+                                       $backedUpFilters = $this->storage->getFileAndFolderNameFilters();
+                                       foreach ($this->fileAndFolderNameFilters as $filter) {
+                                               $this->storage->addFileAndFolderNameFilter($filter);
+                                       }
+                               }
+
+                               break;
+
+                       case self::FILTER_MODE_USE_STORAGE_FILTERS:
+                               // nothing to do here
+
+                               break;
+
+                       case self::FILTER_MODE_NO_FILTERS:
+                               $useFilters = FALSE;
+
+                               break;
+               }
+               return array($backedUpFilters, $useFilters);
+       }
+
+       /**
+        * Restores the filters of a storage.
+        *
+        * @param array $backedUpFilters The filters to restore; might be NULL if no filters have been backed up, in
+        *                               which case this method does nothing.
+        * @see prepareFiltersInStorage()
+        */
+       protected function restoreBackedUpFiltersInStorage($backedUpFilters) {
+               if ($backedUpFilters !== NULL) {
+                       $this->storage->setFileAndFolderNameFilters($backedUpFilters);
+               }
+       }
+
+       /**
+        * Sets the filters to use when listing files. These are only used if the filter mode is one of
+        * FILTER_MODE_USE_OWN_FILTERS and FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS
+        *
+        * @param array $filters
+        */
+       public function setFileAndFolderNameFilters(array $filters) {
+               $this->fileAndFolderNameFilters = $filters;
+       }
 
+       /**
+        * Returns the role of this folder (if any). See FolderInterface::ROLE_* constants for possible values.
+        *
+        * @return integer
+        */
+       public function getRole() {
+               return $this->storage->getRole($this);
+       }
+}
 
 ?>
\ No newline at end of file