[BUGFIX] FAL does not copy subfolders cleanly 05/22605/2
authorChristian Kuhn <lolli@schwarzbu.ch>
Fri, 26 Jul 2013 15:43:19 +0000 (17:43 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Fri, 26 Jul 2013 20:40:41 +0000 (22:40 +0200)
If full structures with sub folders are copied around in FAL
local driver, sub folders are not correctly created in the
target directory.

This is detected in unit tests after recent vfsStream updates in
ext:phpunit.

The patch adds a flag to the Iterator code to also include
directories to fix the issue.

Additionally, the existing two unit tests also tested multiple other
methods of the local driver and are functional tests. The patch moves
those two tests to the functional section and adds three simple unit
tests with correct mocking instead.

Change-Id: I30d3c8bd5c6538b3fe23405d97bcddff6c1ff405
Releases: 6.2, 6.1, 6.0
Resolves: #50472
Reviewed-on: https://review.typo3.org/22596
Reviewed-by: Wouter Wolters
Tested-by: Wouter Wolters
Reviewed-by: Christian Kuhn
Tested-by: Christian Kuhn
(cherry picked from commit b0f8bb0d15106b6f3ee2c5b3b033cbc3e1b635e2)
Reviewed-on: https://review.typo3.org/22605

typo3/sysext/core/Classes/Resource/Driver/LocalDriver.php
typo3/sysext/core/Tests/Functional/Resource/Driver/LocalDriverTest.php [new file with mode: 0644]
typo3/sysext/core/Tests/Unit/Resource/Driver/LocalDriverTest.php

index 305e5fc..ea2729b 100644 (file)
@@ -855,7 +855,7 @@ class LocalDriver extends \TYPO3\CMS\Core\Resource\Driver\AbstractDriver {
                mkdir($targetFolderPath);
                $sourceFolderPath = $this->getAbsolutePath($folderToCopy);
                /** @var $iterator \RecursiveDirectoryIterator */
                mkdir($targetFolderPath);
                $sourceFolderPath = $this->getAbsolutePath($folderToCopy);
                /** @var $iterator \RecursiveDirectoryIterator */
-               $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($sourceFolderPath));
+               $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($sourceFolderPath), \RecursiveIteratorIterator::SELF_FIRST);
                while ($iterator->valid()) {
                        /** @var $current \RecursiveDirectoryIterator */
                        $current = $iterator->current();
                while ($iterator->valid()) {
                        /** @var $current \RecursiveDirectoryIterator */
                        $current = $iterator->current();
diff --git a/typo3/sysext/core/Tests/Functional/Resource/Driver/LocalDriverTest.php b/typo3/sysext/core/Tests/Functional/Resource/Driver/LocalDriverTest.php
new file mode 100644 (file)
index 0000000..f0f25cb
--- /dev/null
@@ -0,0 +1,123 @@
+<?php
+namespace TYPO3\CMS\Core\Tests\Functional\Resource\Driver;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (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
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+require_once dirname(dirname(__FILE__)) . '/BaseTestCase.php';
+
+/**
+ * Test case
+ */
+class LocalDriverTest extends \TYPO3\CMS\Core\Tests\Functional\Resource\BaseTestCase {
+
+       /**
+        * @test
+        */
+       public function foldersCanBeCopiedWithinSameStorage() {
+               $fileContents1 = uniqid();
+               $fileContents2 = uniqid();
+               $this->addToMount(array(
+                       'targetFolder' => array(),
+                       'sourceFolder' => array(
+                               'subFolder' => array(
+                                       'file' => $fileContents1
+                               ),
+                               'file' => $fileContents2
+                       )
+               ));
+               $fixture = $this->createDriverFixture(
+                       array(
+                               'basePath' => $this->getMountRootUrl()
+                       )
+               );
+               $sourceFolder = $this->getSimpleFolderMock('/sourceFolder/');
+               $targetFolder = $this->getSimpleFolderMock('/targetFolder/');
+               $fixture->copyFolderWithinStorage($sourceFolder, $targetFolder, 'sourceFolder');
+               $this->assertTrue($fixture->folderExists('/targetFolder/sourceFolder/'));
+               $this->assertTrue($fixture->fileExists('/targetFolder/sourceFolder/file'));
+               $this->assertTrue($fixture->folderExists('/targetFolder/sourceFolder/subFolder/'));
+               $this->assertTrue($fixture->fileExists('/targetFolder/sourceFolder/subFolder/file'));
+       }
+
+       /**
+        * @test
+        */
+       public function folderNameCanBeChangedWhileCopying() {
+               $fileContents1 = uniqid();
+               $fileContents2 = uniqid();
+               $this->addToMount(array(
+                       'targetFolder' => array(),
+                       'sourceFolder' => array(
+                               'subFolder' => array(
+                                       'file' => $fileContents1
+                               ),
+                               'file' => $fileContents2
+                       )
+               ));
+               $fixture = $this->createDriverFixture(
+                       array(
+                               'basePath' => $this->getMountRootUrl()
+                       )
+               );
+               $sourceFolder = $this->getSimpleFolderMock('/sourceFolder/');
+               $targetFolder = $this->getSimpleFolderMock('/targetFolder/');
+               $fixture->copyFolderWithinStorage($sourceFolder, $targetFolder, 'newFolder');
+               $this->assertTrue($fixture->folderExists('/targetFolder/newFolder/'));
+               $this->assertTrue($fixture->fileExists('/targetFolder/newFolder/file'));
+               $this->assertFalse($fixture->folderExists('/targetFolder/sourceFolder/'));
+       }
+
+       /**
+        * Creates a driver fixture object, optionally using a given mount object.
+        *
+        * IMPORTANT: Call this only after setting up the virtual file system (with the addTo* methods)!
+        *
+        * @param $driverConfiguration
+        * @param \TYPO3\CMS\Core\Resource\ResourceStorage $storageObject
+        * @param array $mockedDriverMethods
+        * @return \TYPO3\CMS\Core\Resource\Driver\LocalDriver
+        */
+       protected function createDriverFixture($driverConfiguration, \TYPO3\CMS\Core\Resource\ResourceStorage $storageObject = NULL, $mockedDriverMethods = array()) {
+               $this->initializeVfs();
+               if ($storageObject == NULL) {
+                       $storageObject = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
+               }
+               if (count($mockedDriverMethods) == 0) {
+                       $driver = new \TYPO3\CMS\Core\Resource\Driver\LocalDriver($driverConfiguration);
+               } else {
+                       $driver = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Driver\\LocalDriver', $mockedDriverMethods, array($driverConfiguration));
+               }
+               $storageObject->setDriver($driver);
+               $driver->setStorage($storageObject);
+               $driver->processConfiguration();
+               $driver->initialize();
+               return $driver;
+       }
+}
+?>
index 6fa2a71..0205188 100644 (file)
@@ -1529,49 +1529,87 @@ class LocalDriverTest extends \TYPO3\CMS\Core\Tests\Unit\Resource\BaseTestCase {
                $this->assertTrue(file_exists($this->getUrlInMount('/targetFolder/newFolder/')));
        }
 
                $this->assertTrue(file_exists($this->getUrlInMount('/targetFolder/newFolder/')));
        }
 
-       protected function _setupFolderForCopyTest() {
-               $fileContents1 = uniqid();
-               $fileContents2 = uniqid();
-               $this->addToMount(array(
-                       'targetFolder' => array(),
+       /**
+        * @test
+        */
+       public function copyFolderWithinStorageCopiesSingleFileToNewFolderName() {
+               $vfsBasedir = uniqid('base-');
+               $vfsStructure = array(
                        'sourceFolder' => array(
                        'sourceFolder' => array(
-                               'subFolder' => array('file' => $fileContents1),
-                               'file' => $fileContents2
-                       )
-               ));
-               $fixture = $this->createDriverFixture(array(
-                       'basePath' => $this->getMountRootUrl()
-               ));
-               return $fixture;
+                               'file' => uniqid(),
+                       ),
+                       'targetFolder' => array(),
+               );
+               \vfsStream::setup($vfsBasedir);
+               \vfsStream::create($vfsStructure);
+               /** @var \TYPO3\CMS\Core\Resource\Driver\LocalDriver|\PHPUnit_Framework_MockObject_MockObject $fixture */
+               $fixture = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Driver\\LocalDriver', array('getAbsolutePath'), array(), '', FALSE);
+               $fixture->expects($this->at(0))
+                       ->method('getAbsolutePath')
+                       ->will($this->returnValue('vfs://' . $vfsBasedir . '/targetFolder/'));
+               $fixture->expects($this->at(1))
+                       ->method('getAbsolutePath')
+                       ->will($this->returnValue('vfs://' . $vfsBasedir . '/sourceFolder/'));
+               $sourceFolderMock = $this->getMock('TYPO3\CMS\Core\Resource\Folder', array(), array(), '', FALSE);
+               $targetFolderMock = $this->getMock('TYPO3\CMS\Core\Resource\Folder', array(), array(), '', FALSE);
+               $fixture->copyFolderWithinStorage($sourceFolderMock, $targetFolderMock, 'newFolderName');
+               $this->assertTrue(is_file('vfs://' . $vfsBasedir . '/targetFolder/newFolderName/file'));
        }
 
        /**
         * @test
        }
 
        /**
         * @test
-        * @see _setupFolderForCopyTest
         */
         */
-       public function foldersCanBeCopiedWithinSameStorage() {
-               $fixture = $this->_setupFolderForCopyTest();
-               $sourceFolder = $this->getSimpleFolderMock('/sourceFolder/');
-               $targetFolder = $this->getSimpleFolderMock('/targetFolder/');
-               $fixture->copyFolderWithinStorage($sourceFolder, $targetFolder, 'sourceFolder');
-               $this->assertTrue($fixture->folderExists('/targetFolder/sourceFolder/'));
-               $this->assertTrue($fixture->fileExists('/targetFolder/sourceFolder/file'));
-               $this->assertTrue($fixture->folderExists('/targetFolder/sourceFolder/subFolder/'));
-               $this->assertTrue($fixture->fileExists('/targetFolder/sourceFolder/subFolder/file'));
+       public function copyFolderWithinStorageCopiesSingleSubFolderToNewFolderName() {
+               $vfsBasedir = uniqid('base-');
+               $vfsStructure = array(
+                       'sourceFolder' => array(
+                               'subFolder' => array(),
+                       ),
+                       'targetFolder' => array(),
+               );
+               \vfsStream::setup($vfsBasedir);
+               \vfsStream::create($vfsStructure);
+               /** @var \TYPO3\CMS\Core\Resource\Driver\LocalDriver|\PHPUnit_Framework_MockObject_MockObject $fixture */
+               $fixture = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Driver\\LocalDriver', array('getAbsolutePath'), array(), '', FALSE);
+               $fixture->expects($this->at(0))
+                       ->method('getAbsolutePath')
+                       ->will($this->returnValue('vfs://' . $vfsBasedir . '/targetFolder/'));
+               $fixture->expects($this->at(1))
+                       ->method('getAbsolutePath')
+                       ->will($this->returnValue('vfs://' . $vfsBasedir . '/sourceFolder/'));
+               $sourceFolderMock = $this->getMock('TYPO3\CMS\Core\Resource\Folder', array(), array(), '', FALSE);
+               $targetFolderMock = $this->getMock('TYPO3\CMS\Core\Resource\Folder', array(), array(), '', FALSE);
+               $fixture->copyFolderWithinStorage($sourceFolderMock, $targetFolderMock, 'newFolderName');
+               $this->assertTrue(is_dir('vfs://' . $vfsBasedir . '/targetFolder/newFolderName/subFolder'));
        }
 
        /**
         * @test
        }
 
        /**
         * @test
-        * @see _setupFolderForCopyTest
         */
         */
-       public function folderNameCanBeChangedWhileCopying() {
-               $fixture = $this->_setupFolderForCopyTest();
-               $sourceFolder = $this->getSimpleFolderMock('/sourceFolder/');
-               $targetFolder = $this->getSimpleFolderMock('/targetFolder/');
-               $fixture->copyFolderWithinStorage($sourceFolder, $targetFolder, 'newFolder');
-               $this->assertTrue($fixture->folderExists('/targetFolder/newFolder/'));
-               $this->assertTrue($fixture->fileExists('/targetFolder/newFolder/file'));
-               $this->assertFalse($fixture->folderExists('/targetFolder/sourceFolder/'));
+       public function copyFolderWithinStorageCopiesFileInSingleSubFolderToNewFolderName() {
+               $vfsBasedir = uniqid('base-');
+               $vfsStructure = array(
+                       'sourceFolder' => array(
+                               'subFolder' => array(
+                                       'file' => uniqid(),
+                               ),
+                       ),
+                       'targetFolder' => array(),
+               );
+               \vfsStream::setup($vfsBasedir);
+               \vfsStream::create($vfsStructure);
+               /** @var \TYPO3\CMS\Core\Resource\Driver\LocalDriver|\PHPUnit_Framework_MockObject_MockObject $fixture */
+               $fixture = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Driver\\LocalDriver', array('getAbsolutePath'), array(), '', FALSE);
+               $fixture->expects($this->at(0))
+                       ->method('getAbsolutePath')
+                       ->will($this->returnValue('vfs://' . $vfsBasedir . '/targetFolder/'));
+               $fixture->expects($this->at(1))
+                       ->method('getAbsolutePath')
+                       ->will($this->returnValue('vfs://' . $vfsBasedir . '/sourceFolder/'));
+               $sourceFolderMock = $this->getMock('TYPO3\CMS\Core\Resource\Folder', array(), array(), '', FALSE);
+               $targetFolderMock = $this->getMock('TYPO3\CMS\Core\Resource\Folder', array(), array(), '', FALSE);
+               $fixture->copyFolderWithinStorage($sourceFolderMock, $targetFolderMock, 'newFolderName');
+               $this->assertTrue(is_file('vfs://' . $vfsBasedir . '/targetFolder/newFolderName/subFolder/file'));
        }
 
 }
        }
 
 }