[FEATURE] Add recursive option to FolderBasedFileCollection 38/32638/15
authorFrans Saris <franssaris@gmail.com>
Wed, 24 Dec 2014 00:50:07 +0000 (01:50 +0100)
committerStefan Neufeind <typo3.neufeind@speedpartner.de>
Wed, 15 Jul 2015 19:25:24 +0000 (21:25 +0200)
Adds a new option for FolderBasedFileCollection to fetch files
recursive from selected folder.

Resolves: #45725
Releases: master
Change-Id: I2761568b488599e53594d4f9a14cfcc5842e83e7
Reviewed-on: http://review.typo3.org/32638
Reviewed-by: Daniel Goerz <ervaude@gmail.com>
Tested-by: Daniel Goerz <ervaude@gmail.com>
Reviewed-by: Alexander Opitz <opitz.alexander@googlemail.com>
Reviewed-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
Tested-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
typo3/sysext/core/Classes/Resource/Collection/FolderBasedFileCollection.php
typo3/sysext/core/Classes/Resource/Folder.php
typo3/sysext/core/Configuration/TCA/sys_file_collection.php
typo3/sysext/core/Documentation/Changelog/master/Feature-45725-AddedRecursiveOptionToFolderBasedFileCollections.rst [new file with mode: 0644]
typo3/sysext/core/Documentation/Changelog/master/Feature-67662-DataProcessorForFiles.rst
typo3/sysext/core/ext_tables.sql
typo3/sysext/frontend/Classes/ContentObject/FilesContentObject.php
typo3/sysext/frontend/Classes/DataProcessing/FilesProcessor.php
typo3/sysext/frontend/Classes/Resource/FileCollector.php
typo3/sysext/frontend/Tests/Unit/ContentObject/FilesContentObjectTest.php
typo3/sysext/lang/locallang_tca.xlf

index 30ddd4f..09405ba 100644 (file)
@@ -14,6 +14,8 @@ namespace TYPO3\CMS\Core\Resource\Collection;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Resource\Folder;
+
 /**
  * A collection containing a a set files to be represented as a (virtual) folder.
  * This collection is persisted to the database with the accordant folder reference.
@@ -43,6 +45,11 @@ class FolderBasedFileCollection extends \TYPO3\CMS\Core\Resource\Collection\Abst
        protected $folder;
 
        /**
+        * @var bool
+        */
+       protected $recursive;
+
+       /**
         * Populates the content-entries of the storage
         *
         * Queries the underlying storage for entries of the collection
@@ -55,8 +62,8 @@ class FolderBasedFileCollection extends \TYPO3\CMS\Core\Resource\Collection\Abst
         * @return void
         */
        public function loadContents() {
-               if ($this->folder instanceof \TYPO3\CMS\Core\Resource\Folder) {
-                       $entries = $this->folder->getFiles();
+               if ($this->folder instanceof Folder) {
+                       $entries = $this->folder->getFiles(0, 0, Folder::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS, $this->recursive);
                        foreach ($entries as $entry) {
                                $this->add($entry);
                        }
@@ -99,6 +106,7 @@ class FolderBasedFileCollection extends \TYPO3\CMS\Core\Resource\Collection\Abst
                $this->uid = $array['uid'];
                $this->title = $array['title'];
                $this->description = $array['description'];
+               $this->recursive = (bool)$array['recursive'];
                if (!empty($array['folder']) && !empty($array['storage'])) {
                        /** @var $storageRepository \TYPO3\CMS\Core\Resource\StorageRepository */
                        $storageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\StorageRepository::class);
index d178aa6..4675fb8 100644 (file)
@@ -245,11 +245,12 @@ class Folder implements FolderInterface {
         * @param int $start The item to start at
         * @param int $numberOfItems The number of items to return
         * @param int $filterMode The filter mode to use for the file list.
+        * @param bool $recursive
         * @return Folder[]
         */
-       public function getSubfolders($start = 0, $numberOfItems = 0, $filterMode = self::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS) {
+       public function getSubfolders($start = 0, $numberOfItems = 0, $filterMode = self::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS, $recursive = FALSE) {
                list($backedUpFilters, $useFilters) = $this->prepareFiltersInStorage($filterMode);
-               $folderObjects = $this->storage->getFoldersInFolder($this, $start, $numberOfItems, $useFilters);
+               $folderObjects = $this->storage->getFoldersInFolder($this, $start, $numberOfItems, $useFilters, $recursive);
                $this->restoreBackedUpFiltersInStorage($backedUpFilters);
                return $folderObjects;
        }
index 5534f5f..9c00d98 100644 (file)
@@ -156,6 +156,14 @@ return array(
                                'itemsProcFunc' => 'typo3/sysext/core/Classes/Resource/Service/UserFileMountService.php:TYPO3\CMS\Core\Resource\Service\UserFileMountService->renderTceformsSelectDropdown',
                        )
                ),
+               'recursive' => array(
+                       'exclude' => 0,
+                       'label' => 'LLL:EXT:lang/locallang_tca.xlf:sys_file_collection.recursive',
+                       'config' => array(
+                               'type' => 'check',
+                               'default' => 0
+                       )
+               ),
                'category' => array(
                        'exclude' => 0,
                        'label' => 'LLL:EXT:lang/locallang_tca.xlf:sys_file_collection.category',
@@ -184,7 +192,7 @@ return array(
                        'showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, title, --palette--;;1, type, files',
                ),
                'folder' => array(
-                       'showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, title, --palette--;;1, type, storage, folder',
+                       'showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, title, --palette--;;1, type, storage, folder, recursive',
                ),
                'category' => array(
                        'showitem' => 'sys_language_uid, l10n_parent, l10n_diffsource, title, --palette--;;1, type, category',
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-45725-AddedRecursiveOptionToFolderBasedFileCollections.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-45725-AddedRecursiveOptionToFolderBasedFileCollections.rst
new file mode 100644 (file)
index 0000000..afee6e7
--- /dev/null
@@ -0,0 +1,24 @@
+=========================================================================
+Feature: #45725 - Added recursive option to folder based file collections
+=========================================================================
+
+Description
+===========
+
+Folder based file collections have now an option to fetch all files recursively for
+the given folder. The option is also available in the TypoScript Object ``FILES``.
+
+Usage:
+
+.. code-block:: typoscript
+
+       filecollection = FILES
+       filecollection {
+               folders = 1:images/
+               folders.recursive = 1
+
+               renderObj = IMAGE
+               renderObj {
+                       file.import.data = file:current:uid
+               }
+       }
index 43ba0d0..aa72c1d 100644 (file)
@@ -35,9 +35,10 @@ over processed data automatically.
                        # + stdWrap
                        collections = 13,14
 
-                       # A list of FAL Folder identifiers
+                       # A list of FAL Folder identifiers and files fetched recursive from all folders
                        # + stdWrap
                        folders = 1:introduction/images/,1:introduction/posters/
+                       folders.recursive = 1
 
                        # Property of which the files should be sorted after they have been accumulated
                        # can be any property of sys_file, sys_file_metadata
index f48c6a6..08b68a2 100644 (file)
@@ -461,6 +461,7 @@ CREATE TABLE sys_file_collection (
        # for type=folder:
        storage int(11) DEFAULT '0' NOT NULL,
        folder text NOT NULL,
+       recursive tinyint(4) DEFAULT '0' NOT NULL,
 
        # for type=category:
        category int(11) DEFAULT '0' NOT NULL,
index fc395cc..e36b97f 100644 (file)
@@ -130,7 +130,7 @@ class FilesContentObject extends AbstractContentObject {
 
                if ($conf['folders'] || $conf['folders.']) {
                        $folderIdentifiers = GeneralUtility::trimExplode(',', $this->cObj->stdWrapValue('folders', $conf));
-                       $fileCollector->addFilesFromFolders($folderIdentifiers);
+                       $fileCollector->addFilesFromFolders($folderIdentifiers, !empty($conf['folders.']['recursive']));
                }
 
                // Enable sorting for multiple fileObjects
index c2d8678..5a13937 100644 (file)
@@ -90,7 +90,7 @@ class FilesProcessor implements DataProcessorInterface {
                $folders = $cObj->stdWrapValue('folders', $processorConfiguration);
                if (!empty($folders)) {
                        $folders = GeneralUtility::trimExplode(',', $folders, TRUE);
-                       $fileCollector->addFilesFromFolders($folders);
+                       $fileCollector->addFilesFromFolders($folders, !empty($processorConfiguration['folders.']['recursive']));
                }
 
                // make sure to sort the files
index 7b17862..63da21c 100644 (file)
@@ -158,11 +158,12 @@ class FileCollector implements \Countable {
         * Add files to the collection from multiple folders
         *
         * @param array $folderIdentifiers The folder identifiers
+        * @param bool $recursive Add files recursive from given folders
         * @return void
         */
-       public function addFilesFromFolders(array $folderIdentifiers = array()) {
+       public function addFilesFromFolders(array $folderIdentifiers = array(), $recursive = FALSE) {
                foreach ($folderIdentifiers as $folderIdentifier) {
-                       $this->addFilesFromFolder($folderIdentifier);
+                       $this->addFilesFromFolder($folderIdentifier, $recursive);
                }
        }
 
@@ -170,15 +171,15 @@ class FileCollector implements \Countable {
         * Add files to the collection from one single folder
         *
         * @param string $folderIdentifier The folder identifier
+        * @param bool $recursive Add files recursive from given folders
         */
-       public function addFilesFromFolder($folderIdentifier) {
+       public function addFilesFromFolder($folderIdentifier, $recursive = FALSE) {
                if ($folderIdentifier) {
                        try {
                                $folder = $this->getResourceFactory()->getFolderObjectFromCombinedIdentifier($folderIdentifier);
                                if ($folder instanceof Folder) {
-                                       $files = array_values($folder->getFiles());
-
-                                       $this->addFileObjects($files);
+                                       $files = $folder->getFiles(0, 0, Folder::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS, $recursive);
+                                       $this->addFileObjects(array_values($files));
                                }
                        } catch (Exception $e) {
                                $this->getLogger()->warning(
index fff3eab..ad0a67b 100644 (file)
@@ -13,6 +13,8 @@ namespace TYPO3\CMS\Frontend\Tests\Unit\ContentObject;
  *
  * The TYPO3 project - inspiring people to share!
  */
+use TYPO3\CMS\Core\Resource\File;
+use TYPO3\CMS\Core\Resource\Folder;
 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
 use TYPO3\CMS\Frontend\ContentObject\FilesContentObject;
 use TYPO3\CMS\Frontend\ContentObject\TextContentObject;
@@ -807,6 +809,37 @@ class FilesContentObjectTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                                ),
                                '<p>File 1</p><p>File 2</p><p>File 3</p><p>File 4</p><p>File 5</p><p>File 6</p><p>File 7</p><p>File 8</p><p>File 9</p>',
                        ),
+                       'Multiple folders recursively' => array(
+                               array(
+                                       'folders' => '1:myfolder/',
+                                       'folders.' => array(
+                                               'recursive' => '1'
+                                       ),
+                                       'renderObj' => 'TEXT',
+                                       'renderObj.' => array(
+                                               'data' => 'file:current:name',
+                                               'wrap' => '<p>|</p>',
+                                       ),
+                               ),
+                               '<p>File 7</p><p>File 8</p><p>File 9</p><p>File 1</p><p>File 2</p><p>File 3</p><p>File 4</p><p>File 5</p><p>File 6</p>',
+                               TRUE
+                       ),
+                       'Multiple folders recursively, sorted by name' => array(
+                               array(
+                                       'folders' => '1:myfolder/',
+                                       'folders.' => array(
+                                               'recursive' => '1'
+                                       ),
+                                       'sorting' => 'name',
+                                       'renderObj' => 'TEXT',
+                                       'renderObj.' => array(
+                                               'data' => 'file:current:name',
+                                               'wrap' => '<p>|</p>',
+                                       ),
+                               ),
+                               '<p>File 1</p><p>File 2</p><p>File 3</p><p>File 4</p><p>File 5</p><p>File 6</p><p>File 7</p><p>File 8</p><p>File 9</p>',
+                               TRUE
+                       ),
                );
        }
 
@@ -814,13 +847,15 @@ class FilesContentObjectTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
         * @test
         * @dataProvider renderReturnsFilesForFoldersDataProvider
         */
-       public function renderReturnsFilesForFolders($configuration, $expected) {
+       public function renderReturnsFilesForFolders($configuration, $expected, $recursive = FALSE) {
                $folderMap = array();
+               $folders = array();
                $fileCount = 1;
+               $filesArrayForFolder = [];
                for ($i = 1; $i < 4; $i++) {
-                       $fileArray = array();
+                       $filesArrayForFolder[$i] = [];
                        for ($j = 1; $j < 4; $j++) {
-                               $file = $this->getMock(\TYPO3\CMS\Core\Resource\File::class, array(), array(), '', FALSE);
+                               $file = $this->getMock(File::class, [], [], '', FALSE);
                                $file->expects($this->any())
                                        ->method('getName')
                                        ->will($this->returnValue('File ' . $fileCount));
@@ -833,16 +868,37 @@ class FilesContentObjectTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                                        ->with('name')
                                        ->will($this->returnValue('File ' . $fileCount));
 
-                               $fileArray[] = $file;
+                               $filesArrayForFolder[$i][] = $file;
                                $fileCount++;
                        }
 
-                       $folder = $this->getMock(\TYPO3\CMS\Core\Resource\Folder::class, array(), array(), '', FALSE);
-                       $folder->expects($this->any())
-                               ->method('getFiles')
-                               ->will($this->returnValue($fileArray));
-
-                       $folderMap[] = array($i . ':myfolder/', $folder);
+                       $folder = $this->getMock(Folder::class, array(), array(), '', FALSE);
+
+                       if ($recursive) {
+                               if ($i < 3) {
+                                       $folders[$i] = $folder;
+                                       $folderMap[$i] = array('1:myfolder/mysubfolder-' . $i . '/', $folder);
+                               } else {
+                                       $folder->expects($this->any())
+                                               ->method('getSubfolders')
+                                               ->will($this->returnValue($folders));
+                                       $folderMap[$i] = array('1:myfolder/', $folder);
+                               }
+                       } else {
+                               $folderMap[$i] = array($i . ':myfolder/', $folder);
+                       }
+               }
+               foreach ($folderMap as $i => $folderMapInfo) {
+                       if ($i < 3 || !$recursive) {
+                               $folderMapInfo[1]->expects($this->any())
+                                       ->method('getFiles')
+                                       ->will($this->returnValue($filesArrayForFolder[$i]));
+                       } else {
+                               $recursiveFiles = array_merge($filesArrayForFolder[3], $filesArrayForFolder[1], $filesArrayForFolder[2]);
+                               $folderMapInfo[1]->expects($this->any())
+                                       ->method('getFiles')
+                                       ->will($this->returnValue($recursiveFiles));
+                       }
                }
 
                $resourceFactory = $this->getMock(\TYPO3\CMS\Core\Resource\ResourceFactory::class);
index c2c733f..215e31d 100644 (file)
                        <trans-unit id="sys_file_collection.folder">
                                <source>Folder</source>
                        </trans-unit>
+                       <trans-unit id="sys_file_collection.recursive">
+                               <source>Recursive</source>
+                       </trans-unit>
                        <trans-unit id="sys_file_collection.category">
                                <source>Category</source>
                        </trans-unit>