[TASK] Allow Folder and Storage to recursively retrieve Files from Driver
authorSteffen Ritter <info@rs-websystems.de>
Fri, 23 Nov 2012 14:11:44 +0000 (15:11 +0100)
committerHelmut Hummel <helmut.hummel@typo3.org>
Sun, 25 Nov 2012 15:44:14 +0000 (16:44 +0100)
The drivers in FAL are capable of retrieving files recursively.
This might be sinful in some cases and custom usages. Anyhow,
the parameter $recursive is not passed up until Storage and
Folder objects. With that users are forced to work with the
driver directly.

As it is highly discouraged to work directly on the driver,
just pass up the parameter within the abstraction layers.

Change-Id: Ibe8f9aa9e906617a42a9a7d5edba43f24f613587
Releases: 6.0
Fixes: #43249
Reviewed-on: http://review.typo3.org/16697
Reviewed-by: Helmut Hummel
Tested-by: Helmut Hummel
typo3/sysext/core/Classes/Resource/Driver/AbstractDriver.php
typo3/sysext/core/Classes/Resource/Driver/LocalDriver.php
typo3/sysext/core/Classes/Resource/Folder.php
typo3/sysext/core/Classes/Resource/ResourceStorage.php
typo3/sysext/core/Tests/Unit/Resource/FolderTest.php
typo3/sysext/core/Tests/Unit/Resource/ResourceStorageTest.php

index 77369cf..af4117b 100644 (file)
@@ -167,9 +167,10 @@ abstract class AbstractDriver {
         * @param array $filterMethods The filter methods used to filter the directory items
         * @param string $itemHandlerMethod
         * @param array $itemRows
         * @param array $filterMethods The filter methods used to filter the directory items
         * @param string $itemHandlerMethod
         * @param array $itemRows
+        * @param boolean $recursive
         * @return array
         */
         * @return array
         */
-       protected function getDirectoryItemList($path, $start, $numberOfItems, array $filterMethods, $itemHandlerMethod, $itemRows = array()) {
+       protected function getDirectoryItemList($path, $start, $numberOfItems, array $filterMethods, $itemHandlerMethod, $itemRows = array(), $recursive = FALSE) {
 
        }
 
 
        }
 
@@ -469,11 +470,12 @@ abstract class AbstractDriver {
         * @param integer $numberOfItems The number of items to list; if not set, return all items
         * @param array $filenameFilterCallbacks The method callbacks to use for filtering the items
         * @param array $fileData Two-dimensional, identifier-indexed array of file index records from the database
         * @param integer $numberOfItems The number of items to list; if not set, return all items
         * @param array $filenameFilterCallbacks The method callbacks to use for filtering the items
         * @param array $fileData Two-dimensional, identifier-indexed array of file index records from the database
+        * @param boolean $recursive
         * @return array
         */
        // TODO add unit tests
         * @return array
         */
        // TODO add unit tests
-       public function getFileList($path, $start = 0, $numberOfItems = 0, array $filenameFilterCallbacks = array(), $fileData = array()) {
-               return $this->getDirectoryItemList($path, $start, $numberOfItems, $filenameFilterCallbacks, $this->fileListCallbackMethod, $fileData);
+       public function getFileList($path, $start = 0, $numberOfItems = 0, array $filenameFilterCallbacks = array(), $fileData = array(), $recursive = FALSE) {
+               return $this->getDirectoryItemList($path, $start, $numberOfItems, $filenameFilterCallbacks, $this->fileListCallbackMethod, $fileData, $recursive);
        }
 
        /**
        }
 
        /**
@@ -610,10 +612,11 @@ abstract class AbstractDriver {
         * @param integer $start The position to start the listing; if not set, start from the beginning
         * @param integer $numberOfItems The number of items to list; if not set, return all items
         * @param array $foldernameFilterCallbacks The method callbacks to use for filtering the items
         * @param integer $start The position to start the listing; if not set, start from the beginning
         * @param integer $numberOfItems The number of items to list; if not set, return all items
         * @param array $foldernameFilterCallbacks The method callbacks to use for filtering the items
+        * @param boolean $recursive
         * @return array
         */
         * @return array
         */
-       public function getFolderList($path, $start = 0, $numberOfItems = 0, array $foldernameFilterCallbacks = array()) {
-               return $this->getDirectoryItemList($path, $start, $numberOfItems, $foldernameFilterCallbacks, $this->folderListCallbackMethod);
+       public function getFolderList($path, $start = 0, $numberOfItems = 0, array $foldernameFilterCallbacks = array(), $recursive = FALSE) {
+               return $this->getDirectoryItemList($path, $start, $numberOfItems, $foldernameFilterCallbacks, $this->folderListCallbackMethod, $recursive);
        }
 
        /**
        }
 
        /**
index 61976eb..48e85b6 100644 (file)
@@ -288,10 +288,11 @@ class LocalDriver extends \TYPO3\CMS\Core\Resource\Driver\AbstractDriver {
         * @param array $filterMethods The filter methods used to filter the directory items
         * @param string $itemHandlerMethod The method (in this class) that handles the single iterator elements.
         * @param array $itemRows
         * @param array $filterMethods The filter methods used to filter the directory items
         * @param string $itemHandlerMethod The method (in this class) that handles the single iterator elements.
         * @param array $itemRows
+        * @param boolean $recursive
         * @return array
         */
        // TODO add unit tests
         * @return array
         */
        // TODO add unit tests
-       protected function getDirectoryItemList($path, $start, $numberOfItems, array $filterMethods, $itemHandlerMethod, $itemRows = array()) {
+       protected function getDirectoryItemList($path, $start, $numberOfItems, array $filterMethods, $itemHandlerMethod, $itemRows = array(), $recursive = FALSE) {
                $realPath = rtrim(($this->absoluteBasePath . trim($path, '/')), '/') . '/';
                if (!is_dir($realPath)) {
                        throw new \InvalidArgumentException('Cannot list items in directory ' . $path . ' - does not exist or is no directory', 1314349666);
                $realPath = rtrim(($this->absoluteBasePath . trim($path, '/')), '/') . '/';
                if (!is_dir($realPath)) {
                        throw new \InvalidArgumentException('Cannot list items in directory ' . $path . ' - does not exist or is no directory', 1314349666);
@@ -302,7 +303,7 @@ class LocalDriver extends \TYPO3\CMS\Core\Resource\Driver\AbstractDriver {
                // Fetch the files and folders and sort them by name; we have to do
                // this here because the directory iterator does return them in
                // an arbitrary order
                // Fetch the files and folders and sort them by name; we have to do
                // this here because the directory iterator does return them in
                // an arbitrary order
-               $items = $this->getFileAndFoldernamesInPath($realPath);
+               $items = $this->getFileAndFoldernamesInPath($realPath, $recursive);
                natcasesort($items);
                $iterator = new \ArrayIterator($items);
                if ($iterator->count() == 0) {
                natcasesort($items);
                $iterator = new \ArrayIterator($items);
                if ($iterator->count() == 0) {
index 8688886..8f480b3 100644 (file)
@@ -175,9 +175,10 @@ class Folder implements \TYPO3\CMS\Core\Resource\FolderInterface {
         * @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.
         * @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.
+        * @param boolean $recursive
         * @return \TYPO3\CMS\Core\Resource\File[]
         */
         * @return \TYPO3\CMS\Core\Resource\File[]
         */
-       public function getFiles($start = 0, $numberOfItems = 0, $filterMode = self::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS) {
+       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
                $useFilters = TRUE;
 
                // Fallback for compatibility with the old method signature variable $useFilters that was used instead of $filterMode
@@ -191,7 +192,7 @@ class Folder implements \TYPO3\CMS\Core\Resource\FolderInterface {
 
                /** @var $factory \TYPO3\CMS\Core\Resource\ResourceFactory */
                $factory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\ResourceFactory');
 
                /** @var $factory \TYPO3\CMS\Core\Resource\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[$fileInfo['name']] = $factory->createFileObject($fileInfo);
                $fileObjects = array();
                foreach ($fileArray as $fileInfo) {
                        $fileObjects[$fileInfo['name']] = $factory->createFileObject($fileInfo);
@@ -209,9 +210,9 @@ class Folder implements \TYPO3\CMS\Core\Resource\FolderInterface {
         * @param array $filterMethods
         * @return integer
         */
         * @param array $filterMethods
         * @return integer
         */
-       public function getFileCount(array $filterMethods = array()) {
+       public function getFileCount(array $filterMethods = array(), $recursive = FALSE) {
                // TODO replace by call to count()
                // 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));
        }
 
        /**
        }
 
        /**
index c0e8ce6..ce5f9b9 100644 (file)
@@ -850,11 +850,12 @@ class ResourceStorage {
         * @param integer $numberOfItems The number of items to list; if not set, return all items
         * @param bool $useFilters If FALSE, the list is returned without any filtering; otherwise, the filters defined for this storage are used.
         * @param bool $loadIndexRecords If set to TRUE, the index records for all files are loaded from the database. This can greatly improve performance of this method, especially with a lot of files.
         * @param integer $numberOfItems The number of items to list; if not set, return all items
         * @param bool $useFilters If FALSE, the list is returned without any filtering; otherwise, the filters defined for this storage are used.
         * @param bool $loadIndexRecords If set to TRUE, the index records for all files are loaded from the database. This can greatly improve performance of this method, especially with a lot of files.
+        * @param boolean $recursive
         * @return array Information about the files found.
         */
        // TODO check if we should use a folder object instead of $path
        // TODO add unit test for $loadIndexRecords
         * @return array Information about the files found.
         */
        // TODO check if we should use a folder object instead of $path
        // TODO add unit test for $loadIndexRecords
-       public function getFileList($path, $start = 0, $numberOfItems = 0, $useFilters = TRUE, $loadIndexRecords = TRUE) {
+       public function getFileList($path, $start = 0, $numberOfItems = 0, $useFilters = TRUE, $loadIndexRecords = TRUE, $recursive = FALSE) {
                $rows = array();
                if ($loadIndexRecords) {
                        /** @var $repository \TYPO3\CMS\Core\Resource\FileRepository */
                $rows = array();
                if ($loadIndexRecords) {
                        /** @var $repository \TYPO3\CMS\Core\Resource\FileRepository */
@@ -862,7 +863,7 @@ class ResourceStorage {
                        $rows = $repository->getFileIndexRecordsForFolder($this->getFolder($path));
                }
                $filters = $useFilters == TRUE ? $this->fileAndFolderNameFilters : array();
                        $rows = $repository->getFileIndexRecordsForFolder($this->getFolder($path));
                }
                $filters = $useFilters == TRUE ? $this->fileAndFolderNameFilters : array();
-               $items = $this->driver->getFileList($path, $start, $numberOfItems, $filters, $rows);
+               $items = $this->driver->getFileList($path, $start, $numberOfItems, $filters, $rows, $recursive);
                uksort($items, 'strnatcasecmp');
                return $items;
        }
                uksort($items, 'strnatcasecmp');
                return $items;
        }
@@ -1471,10 +1472,11 @@ class ResourceStorage {
         * @param int $start
         * @param int $numberOfItems
         * @param array $folderFilterCallbacks
         * @param int $start
         * @param int $numberOfItems
         * @param array $folderFilterCallbacks
+        * @param boolean $recursive
         * @return array
         */
         * @return array
         */
-       public function fetchFolderListFromDriver($path, $start = 0, $numberOfItems = 0, array $folderFilterCallbacks = array()) {
-               $items = $this->driver->getFolderList($path, $start, $numberOfItems, $folderFilterCallbacks);
+       public function fetchFolderListFromDriver($path, $start = 0, $numberOfItems = 0, array $folderFilterCallbacks = array(), $recursive = FALSE) {
+               $items = $this->driver->getFolderList($path, $start, $numberOfItems, $folderFilterCallbacks, $recursive);
                // Exclude the _processed_ folder, so it won't get indexed etc
                $processingFolder = $this->getProcessingFolder();
                if ($processingFolder && $path == '/') {
                // Exclude the _processed_ folder, so it won't get indexed etc
                $processingFolder = $this->getProcessingFolder();
                if ($processingFolder && $path == '/') {
index d59af84..1c54a11 100644 (file)
@@ -115,6 +115,36 @@ class FolderTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
        /**
         * @test
         */
        /**
         * @test
         */
+       public function getFilesHandsOverRecursiveFALSEifNotExplicitlySet() {
+               $mockedStorage = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
+               $mockedStorage
+                       ->expects($this->once())
+                       ->method('getFileList')
+                       ->with($this->anything(), $this->anything(), $this->anything(), $this->anything(), $this->anything(), FALSE)
+                       ->will($this->returnValue(array()));
+
+               $fixture = $this->createFolderFixture('/somePath', 'someName', $mockedStorage);
+               $fixture->getFiles();
+       }
+
+       /**
+        * @test
+        */
+       public function getFilesHandsOverRecursiveTRUEifSet() {
+               $mockedStorage = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
+               $mockedStorage
+                       ->expects($this->once())
+                       ->method('getFileList')
+                       ->with($this->anything(), $this->anything(), $this->anything(), $this->anything(), $this->anything(), TRUE)
+                       ->will($this->returnValue(array()));
+
+               $fixture = $this->createFolderFixture('/somePath', 'someName', $mockedStorage);
+               $fixture->getFiles(0, 0, \TYPO3\CMS\Core\Resource\Folder::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS, TRUE);
+       }
+
+       /**
+        * @test
+        */
        public function getSubfolderCallsFactoryWithCorrectArguments() {
                $mockedStorage = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
                $mockedStorage->expects($this->once())->method('hasFolderInFolder')->with($this->equalTo('someSubfolder'))->will($this->returnValue(TRUE));
        public function getSubfolderCallsFactoryWithCorrectArguments() {
                $mockedStorage = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
                $mockedStorage->expects($this->once())->method('hasFolderInFolder')->with($this->equalTo('someSubfolder'))->will($this->returnValue(TRUE));
index e531316..af4cc1c 100644 (file)
@@ -615,6 +615,33 @@ class ResourceStorageTest extends \TYPO3\CMS\Core\Tests\Unit\Resource\BaseTestCa
                $this->fixture->replaceFile($mockedFile, PATH_site . uniqid());
        }
 
                $this->fixture->replaceFile($mockedFile, PATH_site . uniqid());
        }
 
+       /**
+        * @test
+        */
+       public function getFileListHandsOverRecursiveFALSEifNotExplicitlySet() {
+               $this->prepareFixture(array());
+               $driver = $this->createDriverMock(array('basePath' => $this->getMountRootUrl()), $this->fixture, array('getFileList'));
+               $driver->expects($this->once())
+                       ->method('getFileList')
+                       ->with($this->anything(), $this->anything(), $this->anything(), $this->anything(), $this->anything(), FALSE)
+                       ->will($this->returnValue(array()));
+               $this->fixture->getFileList('/');
+       }
+
+       /**
+        * @test
+        */
+       public function getFileListHandsOverRecursiveTRUEifSet() {
+
+               $this->prepareFixture(array());
+               $driver = $this->createDriverMock(array('basePath' => $this->getMountRootUrl()), $this->fixture, array('getFileList'));
+               $driver->expects($this->once())
+                       ->method('getFileList')
+                       ->with($this->anything(), $this->anything(), $this->anything(), $this->anything(), $this->anything(), TRUE)
+                       ->will($this->returnValue(array()));
+               $this->fixture->getFileList('/', 0, 0, TRUE, TRUE, TRUE);
+       }
+
 }
 
 ?>
\ No newline at end of file
 }
 
 ?>
\ No newline at end of file