[BUGFIX] Follow up: Moving files and folders doesn't update hashes
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Resource / ResourceStorageTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Resource;
3
4 use TYPO3\CMS\Core\Resource\ResourceStorage;
5
6 /***************************************************************
7 * Copyright notice
8 *
9 * (c) 2011-2013 Andreas Wolf <andreas.wolf@ikt-werk.de>
10 * All rights reserved
11 *
12 * This script is part of the TYPO3 project. The TYPO3 project is
13 * free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * The GNU General Public License can be found at
19 * http://www.gnu.org/copyleft/gpl.html.
20 *
21 * This script is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * This copyright notice MUST APPEAR in all copies of the script!
27 ***************************************************************/
28
29 /**
30 * Testcase for the VFS mount class
31 *
32 * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
33 */
34 class ResourceStorageTest extends \TYPO3\CMS\Core\Tests\Unit\Resource\BaseTestCase {
35
36 /**
37 * @var array A backup of registered singleton instances
38 */
39 protected $singletonInstances = array();
40
41 /**
42 * @var \TYPO3\CMS\Core\Resource\ResourceStorage
43 */
44 private $fixture;
45
46 public function setUp() {
47 parent::setUp();
48 $this->singletonInstances = \TYPO3\CMS\Core\Utility\GeneralUtility::getSingletonInstances();
49 \TYPO3\CMS\Core\Utility\GeneralUtility::purgeInstances();
50 \TYPO3\CMS\Core\Utility\GeneralUtility::setSingletonInstance(
51 'TYPO3\\CMS\\Core\\Resource\\FileRepository',
52 $this->getMock('TYPO3\\CMS\\Core\\Resource\\FileRepository')
53 );
54
55 }
56
57 public function tearDown() {
58 parent::tearDown();
59 \TYPO3\CMS\Core\Utility\GeneralUtility::resetSingletonInstances($this->singletonInstances);
60 }
61
62 /**
63 * Prepare fixture
64 *
65 * @param array $configuration
66 * @param boolean $mockPermissionChecks
67 * @return void
68 */
69 protected function prepareFixture($configuration, $mockPermissionChecks = FALSE, $driverObject = NULL, array $storageRecord = array()) {
70 $permissionMethods = array('assureFileAddPermissions', 'checkFolderActionPermission', 'checkFileActionPermission', 'checkUserActionPermission', 'checkFileExtensionPermission', 'isWithinFileMountBoundaries');
71 $mockedMethods = NULL;
72 $configuration = $this->convertConfigurationArrayToFlexformXml($configuration);
73 $storageRecord = \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule($storageRecord, array(
74 'configuration' => $configuration
75 ));
76 if ($driverObject == NULL) {
77 /** @var $mockedDriver \TYPO3\CMS\Core\Resource\Driver\AbstractDriver */
78 $driverObject = $this->getMockForAbstractClass('TYPO3\\CMS\\Core\\Resource\\Driver\\AbstractDriver', array(), '', FALSE);
79 }
80 if ($mockPermissionChecks) {
81 $mockedMethods = $permissionMethods;
82 }
83 if ($mockedMethods === NULL) {
84 $this->fixture = new \TYPO3\CMS\Core\Resource\ResourceStorage($driverObject, $storageRecord);
85 } else {
86 $this->fixture = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', $mockedMethods, array($driverObject, $storageRecord));
87 foreach ($permissionMethods as $method) {
88 $this->fixture->expects($this->any())->method($method)->will($this->returnValue(TRUE));
89 }
90 }
91 }
92
93 /**
94 * Converts a simple configuration array into a FlexForm data structure serialized as XML
95 *
96 * @param array $configuration
97 * @return string
98 * @see \TYPO3\CMS\Core\Utility\GeneralUtility::array2xml()
99 */
100 protected function convertConfigurationArrayToFlexformXml(array $configuration) {
101 $flexformArray = array('data' => array('sDEF' => array('lDEF' => array())));
102 foreach ($configuration as $key => $value) {
103 $flexformArray['data']['sDEF']['lDEF'][$key] = array('vDEF' => $value);
104 }
105 $configuration = \TYPO3\CMS\Core\Utility\GeneralUtility::array2xml($flexformArray);
106 return $configuration;
107 }
108
109 /**
110 * Creates a driver fixture object, optionally using a given mount object.
111 *
112 * IMPORTANT: Call this only after setting up the virtual file system (with the addTo* methods)!
113 *
114 * @param $driverConfiguration
115 * @param \TYPO3\CMS\Core\Resource\ResourceStorage $storageObject
116 * @param array $mockedDriverMethods
117 * @return \TYPO3\CMS\Core\Resource\Driver\LocalDriver
118 */
119 protected function createDriverMock($driverConfiguration, \TYPO3\CMS\Core\Resource\ResourceStorage $storageObject = NULL, $mockedDriverMethods = array()) {
120 $this->initializeVfs();
121 if ($storageObject == NULL) {
122 $storageObject = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
123 }
124
125 if (!isset($driverConfiguration['basePath'])) {
126 $driverConfiguration['basePath'] = $this->getMountRootUrl();
127 }
128
129 if ($mockedDriverMethods === NULL) {
130 $driver = new \TYPO3\CMS\Core\Resource\Driver\LocalDriver($driverConfiguration);
131 } else {
132 // We are using the LocalDriver here because PHPUnit can't mock concrete methods in abstract classes, so
133 // when using the AbstractDriver we would be in trouble when wanting to mock away some concrete method
134 $driver = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Driver\\LocalDriver', $mockedDriverMethods, array($driverConfiguration));
135 }
136 $storageObject->setDriver($driver);
137 $driver->setStorage($storageObject);
138 $driver->processConfiguration();
139 $driver->initialize();
140 return $driver;
141 }
142
143 /**
144 * @test
145 */
146 public function baseUriGetsSlashAppended() {
147 $uri = 'http://example.org/somewhere/else';
148 $this->prepareFixture(array('baseUri' => $uri));
149 $this->assertEquals($uri . '/', $this->fixture->getBaseUri());
150 }
151
152 /**
153 * @return array
154 */
155 public function capabilitiesDataProvider() {
156 return array(
157 'only public' => array(
158 array(
159 'public' => TRUE,
160 'writable' => FALSE,
161 'browsable' => FALSE
162 )
163 ),
164 'only writable' => array(
165 array(
166 'public' => FALSE,
167 'writable' => TRUE,
168 'browsable' => FALSE
169 )
170 ),
171 'only browsable' => array(
172 array(
173 'public' => FALSE,
174 'writable' => FALSE,
175 'browsable' => TRUE
176 )
177 ),
178 'all capabilities' => array(
179 array(
180 'public' => TRUE,
181 'writable' => TRUE,
182 'browsable' => TRUE
183 )
184 ),
185 'none' => array(
186 array(
187 'public' => FALSE,
188 'writable' => FALSE,
189 'browsable' => FALSE
190 )
191 )
192 );
193 }
194
195 /**
196 * @test
197 * @dataProvider capabilitiesDataProvider
198 */
199 public function capabilitiesOfStorageObjectAreCorrectlySet(array $capabilites) {
200 $storageRecord = array(
201 'is_public' => $capabilites['public'],
202 'is_writable' => $capabilites['writable'],
203 'is_browsable' => $capabilites['browsable'],
204 'is_online' => TRUE
205 );
206 $mockedDriver = $this->createDriverMock(array(), $this->fixture, array('hasCapability'));
207 $mockedDriver->expects($this->any())->method('hasCapability')->will($this->returnValue(TRUE));
208 $this->prepareFixture(array(), FALSE, $mockedDriver, $storageRecord);
209 $this->assertEquals($capabilites['public'], $this->fixture->isPublic(), 'Capability "public" is not correctly set.');
210 $this->assertEquals($capabilites['writable'], $this->fixture->isWritable(), 'Capability "writable" is not correctly set.');
211 $this->assertEquals($capabilites['browsable'], $this->fixture->isBrowsable(), 'Capability "browsable" is not correctly set.');
212 }
213
214 /**
215 * @test
216 */
217 public function fileAndFolderListFiltersAreInitializedWithDefaultFilters() {
218 $this->prepareFixture(array());
219 $this->assertEquals($GLOBALS['TYPO3_CONF_VARS']['SYS']['fal']['defaultFilterCallbacks'], $this->fixture->getFileAndFolderNameFilters());
220 }
221
222 /**
223 * @test
224 */
225 public function addFileFailsIfFileDoesNotExist() {
226 $mockedFolder = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Folder', array(), array(), '', FALSE);
227 $this->setExpectedException('InvalidArgumentException', '', 1319552745);
228 $this->prepareFixture(array());
229 $this->fixture->addFile('/some/random/file', $mockedFolder);
230 }
231
232 /**
233 * @test
234 */
235 public function addFileCallsDriverWithCorrectArguments() {
236 $mockedFolder = $this->getSimpleFolderMock('/targetFolder/');
237 $this->addToMount(array(
238 'targetFolder' => array(),
239 'file.ext' => 'ajslkd'
240 ));
241 $this->initializeVfs();
242 $localFilePath = $this->getUrlInMount('file.ext');
243 $this->prepareFixture(array(), TRUE);
244 /** @var $file \TYPO3\CMS\Core\Resource\FileInterface */
245 $file = $this->getMock('TYPO3\\CMS\\Core\\Resource\\FileInterface', array(), array(), '', FALSE);
246 /** @var $driver \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
247 $driver = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Driver\\LocalDriver', array('addFile'), array(array('basePath' => $this->getUrlInMount('targetFolder/'))));
248 $driver->expects($this->once())->method('addFile')->with($this->equalTo($localFilePath), $this->anything(), $this->equalTo('file.ext'))->will($this->returnValue($file));
249 $this->fixture->setDriver($driver);
250 $this->fixture->addFile($localFilePath, $mockedFolder);
251 }
252
253 /**
254 * @test
255 */
256 public function addFileChangesFilenameIfFileExists() {
257 $mockedFolder = $this->getSimpleFolderMock('/');
258 $this->addToMount(array(
259 'targetFolder' => array(
260 'file.ext' => 'asdf',
261 'file_01.ext' => 'asjdlkajs'
262 ),
263 'file.ext' => 'ajslkd'
264 ));
265 $this->initializeVfs();
266 $this->prepareFixture(array(), TRUE);
267 /** @var $file \TYPO3\CMS\Core\Resource\FileInterface */
268 $file = $this->getMock('TYPO3\\CMS\\Core\\Resource\\FileInterface', array(), array(), '', FALSE);
269 /** @var $driver \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
270 $driver = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Driver\\LocalDriver', array('addFile', 'fileExistsInFolder'), array(array('basePath' => $this->getUrlInMount('targetFolder/'))));
271 $driver->expects($this->once())->method('addFile')->with($this->anything(), $this->anything(), $this->equalTo('file_02.ext'))->will($this->returnValue($file));
272 $driver->expects($this->exactly(3))->method('fileExistsInFolder')->will($this->onConsecutiveCalls($this->returnValue(TRUE), $this->returnValue(TRUE), $this->returnValue(FALSE)));
273 $this->fixture->setDriver($driver);
274 $this->fixture->addFile($this->getUrlInMount('file.ext'), $mockedFolder);
275 }
276
277 /**
278 * @test
279 */
280 public function getPublicUrlReturnsNullIfStorageIsNotOnline() {
281 /** @var $driver \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
282 $driver = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Driver\\LocalDriver', array(), array(array('basePath' => $this->getMountRootUrl())));
283 /** @var $fixture \TYPO3\CMS\Core\Resource\ResourceStorage */
284 $fixture = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array('isOnline'), array($driver, array('configuration' => array())));
285 $fixture->expects($this->once())->method('isOnline')->will($this->returnValue(FALSE));
286
287 $sourceFileIdentifier = '/sourceFile.ext';
288 $sourceFile = $this->getSimpleFileMock($sourceFileIdentifier);
289 $result = $fixture->getPublicUrl($sourceFile);
290 $this->assertSame($result, NULL);
291 }
292
293 /**
294 * Data provider for checkFolderPermissionsRespectsFilesystemPermissions
295 *
296 * @return array
297 */
298 public function checkFolderPermissionsFilesystemPermissionsDataProvider() {
299 return array(
300 'read action on readable/writable folder' => array(
301 'read',
302 array('r' => TRUE, 'w' => TRUE),
303 TRUE
304 ),
305 'read action on unreadable folder' => array(
306 'read',
307 array('r' => FALSE, 'w' => TRUE),
308 FALSE
309 ),
310 'write action on read-only folder' => array(
311 'write',
312 array('r' => TRUE, 'w' => FALSE),
313 FALSE
314 )
315 );
316 }
317
318 /**
319 * @test
320 * @dataProvider checkFolderPermissionsFilesystemPermissionsDataProvider
321 * @param string $action 'read' or 'write'
322 * @param array $permissionsFromDriver The permissions as returned from the driver
323 * @param boolean $expectedResult
324 */
325 public function checkFolderPermissionsRespectsFilesystemPermissions($action, $permissionsFromDriver, $expectedResult) {
326 $mockedDriver = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Driver\\LocalDriver');
327 $mockedDriver->expects($this->any())->method('getFolderPermissions')->will($this->returnValue($permissionsFromDriver));
328 $mockedFolder = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Folder', array(), array(), '', FALSE);
329 // Let all other checks pass
330 /** @var $fixture \TYPO3\CMS\Core\Resource\ResourceStorage */
331 $fixture = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array('isWritable', 'isBrowsable', 'checkUserActionPermission'), array($mockedDriver, array()), '', FALSE);
332 $fixture->expects($this->any())->method('isWritable')->will($this->returnValue(TRUE));
333 $fixture->expects($this->any())->method('isBrowsable')->will($this->returnValue(TRUE));
334 $fixture->expects($this->any())->method('checkUserActionPermission')->will($this->returnValue(TRUE));
335 $fixture->setDriver($mockedDriver);
336
337 $this->assertSame($expectedResult, $fixture->checkFolderActionPermission($action, $mockedFolder));
338 }
339
340 /**
341 * @test
342 */
343 public function checkUserActionPermissionsAlwaysReturnsTrueIfNoUserPermissionsAreSet() {
344 $this->prepareFixture(array());
345 $this->assertTrue($this->fixture->checkUserActionPermission('read', 'folder'));
346 }
347
348 /**
349 * @test
350 */
351 public function checkUserActionPermissionReturnsFalseIfPermissionIsSetToZero() {
352 $this->prepareFixture(array());
353 $this->fixture->setUserPermissions(array('readFolder' => TRUE, 'writeFile' => TRUE));
354 $this->assertTrue($this->fixture->checkUserActionPermission('read', 'folder'));
355 }
356
357 public function checkUserActionPermission_arbitraryPermissionDataProvider() {
358 return array(
359 'all lower cased' => array(
360 array('readFolder' => TRUE),
361 'read',
362 'folder'
363 ),
364 'all upper case' => array(
365 array('readFolder' => TRUE),
366 'READ',
367 'FOLDER'
368 ),
369 'mixed case' => array(
370 array('readFolder' => TRUE),
371 'ReaD',
372 'FoLdEr'
373 )
374 );
375 }
376
377 /**
378 * @test
379 * @dataProvider checkUserActionPermission_arbitraryPermissionDataProvider
380 */
381 public function checkUserActionPermissionAcceptsArbitrarilyCasedArguments($permissions, $action, $type) {
382 $this->prepareFixture(array());
383 $this->fixture->setUserPermissions($permissions);
384 $this->assertTrue($this->fixture->checkUserActionPermission($action, $type));
385 }
386
387 /**
388 * @test
389 */
390 public function userActionIsDisallowedIfPermissionIsSetToFalse() {
391 $this->prepareFixture(array());
392 $this->fixture->setEvaluatePermissions(TRUE);
393 $this->fixture->setUserPermissions(array('readFolder' => FALSE));
394 $this->assertFalse($this->fixture->checkUserActionPermission('read', 'folder'));
395 }
396
397 /**
398 * @test
399 */
400 public function userActionIsDisallowedIfPermissionIsNotSet() {
401 $this->prepareFixture(array());
402 $this->fixture->setEvaluatePermissions(TRUE);
403 $this->fixture->setUserPermissions(array('readFolder' => TRUE));
404 $this->assertFalse($this->fixture->checkUserActionPermission('write', 'folder'));
405 }
406
407 /**
408 * @test
409 * @group integration
410 */
411 public function setFileContentsUpdatesObjectProperties() {
412 $this->initializeVfs();
413 $driverObject = $this->getMockForAbstractClass('TYPO3\\CMS\\Core\\Resource\\Driver\\AbstractDriver', array(), '', FALSE);
414 $this->fixture = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array('getFileIndexRepository', 'checkFileActionPermission'), array($driverObject, array()));
415 $this->fixture->expects($this->any())->method('checkFileActionPermission')->will($this->returnValue(TRUE));
416 $fileInfo = array(
417 'storage' => 'A',
418 'identifier' => 'B',
419 'mtime' => 'C',
420 'ctime' => 'D',
421 'mimetype' => 'E',
422 'size' => 'F',
423 'name' => 'G',
424 );
425 $newProperties = array(
426 'storage' => $fileInfo['storage'],
427 'identifier' => $fileInfo['identifier'],
428 'tstamp' => $fileInfo['mtime'],
429 'crdate' => $fileInfo['ctime'],
430 'mime_type' => $fileInfo['mimetype'],
431 'size' => $fileInfo['size'],
432 'name' => $fileInfo['name']
433 );
434 $hash = 'asdfg';
435 $driver = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Driver\\LocalDriver', array(), array(array('basePath' => $this->getMountRootUrl())));
436 $driver->expects($this->once())->method('getFileInfoByIdentifier')->will($this->returnValue($fileInfo));
437 $driver->expects($this->once())->method('hash')->will($this->returnValue($hash));
438 $this->fixture->setDriver($driver);
439 $indexFileRepositoryMock = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Index\\FileIndexRepository');
440 $this->fixture->expects($this->any())->method('getFileIndexRepository')->will($this->returnValue($indexFileRepositoryMock));
441 $mockedFile = $this->getMock('TYPO3\\CMS\\Core\\Resource\\File', array(), array(), '', FALSE);
442 $mockedFile->expects($this->any())->method('getIdentifier')->will($this->returnValue($fileInfo['identifier']));
443 // called by indexer because the properties are updated
444 $this->fixture->expects($this->any())->method('getFileInfoByIdentifier')->will($this->returnValue($newProperties));
445 $mockedFile->expects($this->any())->method('getStorage')->will($this->returnValue($this->fixture));
446 $mockedFile->expects($this->any())->method('getProperties')->will($this->returnValue(array_keys($fileInfo)));
447 $mockedFile->expects($this->any())->method('getUpdatedProperties')->will($this->returnValue(array_keys($newProperties)));
448 // do not update directly; that's up to the indexer
449 $indexFileRepositoryMock->expects($this->never())->method('update');
450 $this->fixture->setFileContents($mockedFile, uniqid());
451 }
452
453 /**
454 * @test
455 * @group integration
456 */
457 public function moveFileCallsDriversRawMethodsWithCorrectArguments() {
458 $localFilePath = '/path/to/localFile';
459 $sourceFileIdentifier = '/sourceFile.ext';
460 $fileInfoDummy = array(
461 'storage' => 'A',
462 'identifier' => 'B',
463 'mtime' => 'C',
464 'ctime' => 'D',
465 'mimetype' => 'E',
466 'size' => 'F',
467 'name' => 'G',
468 );
469 $this->addToMount(array(
470 'targetFolder' => array()
471 ));
472 $this->initializeVfs();
473 $targetFolder = $this->getSimpleFolderMock('/targetFolder/');
474 $sourceDriver = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Driver\\LocalDriver');
475 $sourceDriver->expects($this->once())->method('deleteFileRaw')->with($this->equalTo($sourceFileIdentifier));
476 $configuration = $this->convertConfigurationArrayToFlexformXml(array());
477 $sourceStorage = new \TYPO3\CMS\Core\Resource\ResourceStorage($sourceDriver, array('configuration' => $configuration));
478 $sourceFile = $this->getSimpleFileMock($sourceFileIdentifier);
479 $sourceFile->expects($this->once())->method('getForLocalProcessing')->will($this->returnValue($localFilePath));
480 $sourceFile->expects($this->any())->method('getStorage')->will($this->returnValue($sourceStorage));
481 $sourceFile->expects($this->once())->method('getUpdatedProperties')->will($this->returnValue(array_keys($fileInfoDummy)));
482 $sourceFile->expects($this->once())->method('getProperties')->will($this->returnValue($fileInfoDummy));
483 /** @var $driver \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
484 $driver = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Driver\\LocalDriver', array(), array(array('basePath' => $this->getMountRootUrl())));
485 $driver->expects($this->once())->method('getFileInfoByIdentifier')->will($this->returnValue($fileInfoDummy));
486 $driver->expects($this->once())->method('addFileRaw')->with($localFilePath, $targetFolder, $this->equalTo('file.ext'))->will($this->returnValue('/targetFolder/file.ext'));
487 /** @var $fixture \TYPO3\CMS\Core\Resource\ResourceStorage */
488 $fixture = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array('assureFileMovePermissions'), array($driver, array('configuration' => $configuration)));
489 $fixture->moveFile($sourceFile, $targetFolder, 'file.ext');
490 }
491
492 /**
493 * @test
494 * @group integration
495 */
496 public function copyFileCallsDriversRawMethodsWithCorrectArguments() {
497 $localFilePath = '/path/to/localFile';
498 $sourceFileIdentifier = '/sourceFile.ext';
499 $this->addToMount(array(
500 'targetFolder' => array()
501 ));
502 $this->initializeVfs();
503 $targetFolder = $this->getSimpleFolderMock('/targetFolder/');
504 $storageConfiguration = $this->convertConfigurationArrayToFlexformXml(array());
505 $sourceStorage = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
506 $sourceFile = $this->getSimpleFileMock($sourceFileIdentifier);
507 $sourceFile->expects($this->once())->method('getForLocalProcessing')->will($this->returnValue($localFilePath));
508 $sourceFile->expects($this->any())->method('getStorage')->will($this->returnValue($sourceStorage));
509 /** @var $driver \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
510 $driver = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Driver\\LocalDriver', array(), array(array('basePath' => $this->getMountRootUrl())));
511 $driver->expects($this->once())->method('addFile')->with($localFilePath, $targetFolder, $this->equalTo('file.ext'));
512 /** @var $fixture \TYPO3\CMS\Core\Resource\ResourceStorage */
513 $fixture = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array('assureFileCopyPermissions'), array($driver, array('configuration' => $storageConfiguration)));
514 $fixture->copyFile($sourceFile, $targetFolder, 'file.ext');
515 }
516
517 /**
518 * @test
519 * @group integration
520 */
521 public function storageUsesInjectedFilemountsToCheckForMountBoundaries() {
522 $mockedFile = $this->getSimpleFileMock('/mountFolder/file');
523 $this->addToMount(array(
524 'mountFolder' => array(
525 'file' => 'asdfg'
526 )
527 ));
528 $mockedDriver = $this->createDriverMock(array('basePath' => $this->getMountRootUrl()), NULL, NULL);
529 $this->initializeVfs();
530 $this->prepareFixture(array(), NULL, $mockedDriver);
531 $this->fixture->addFileMount('/mountFolder');
532 $this->assertEquals(1, count($this->fixture->getFileMounts()));
533 $this->fixture->isWithinFileMountBoundaries($mockedFile);
534 }
535
536 /**
537 * This test is also valid for folders
538 *
539 * @test
540 */
541 public function getFileListReturnsFilesInCorrectOrder() {
542 $fileList = array(
543 'file10' => '',
544 'file2' => '',
545 'File' => '',
546 'fail' => ''
547 );
548 $this->prepareFixture(array(), TRUE);
549 $driver = $this->createDriverMock(array('basePath' => $this->getMountRootUrl()), $this->fixture, array('getFileList'));
550 $driver->expects($this->once())->method('getFileList')->will($this->returnValue($fileList));
551 $fileList = $this->fixture->getFileList('/');
552 $this->assertEquals(array('fail', 'File', 'file2', 'file10'), array_keys($fileList));
553 }
554
555 /**
556 * @test
557 */
558 public function getFileListIgnoresCasingWhenSortingFilenames() {
559 $fileList = array(
560 'aFile' => 'dfsdg',
561 'zFile' => 'werw',
562 'BFile' => 'asd',
563 '12345' => 'fdsa',
564 'IMG_1234.jpg' => 'asdf'
565 );
566 $this->prepareFixture(array(), TRUE);
567 $driver = $this->createDriverMock(array(), $this->fixture, array('getFileList'));
568 $driver->expects($this->once())->method('getFileList')->will($this->returnValue($fileList));
569 $fileList = $this->fixture->getFileList('/');
570 $this->assertEquals(array('12345', 'aFile', 'BFile', 'IMG_1234.jpg', 'zFile'), array_keys($fileList));
571 }
572
573 /**
574 * @test
575 */
576 public function createFolderChecksIfParentFolderExistsBeforeCreatingFolder() {
577 $mockedParentFolder = $this->getSimpleFolderMock('/someFolder/');
578 $mockedDriver = $this->createDriverMock(array());
579 $mockedDriver->expects($this->once())->method('folderExists')->with($this->equalTo('/someFolder/'))->will($this->returnValue(TRUE));
580 $mockedDriver->expects($this->once())->method('createFolder')->with($this->equalTo('newFolder'))->will($this->returnValue($mockedParentFolder));
581 $this->prepareFixture(array(), TRUE);
582 $this->fixture->setDriver($mockedDriver);
583 $this->fixture->createFolder('newFolder', $mockedParentFolder);
584 }
585
586 /**
587 * @test
588 * @expectedException \RuntimeException
589 */
590 public function deleteFolderThrowsExceptionIfFolderIsNotEmptyAndRecursiveDeleteIsDisabled() {
591 /** @var \TYPO3\CMS\Core\Resource\Folder|\PHPUnit_Framework_MockObject_MockObject $folderMock */
592 $folderMock = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Folder', array(), array(), '', FALSE);
593 /** @var \TYPO3\CMS\Core\Resource\Driver\AbstractDriver|\PHPUnit_Framework_MockObject_MockObject $driverMock */
594 $driverMock = $this->getMockForAbstractClass('TYPO3\\CMS\\Core\\Resource\\Driver\\AbstractDriver');
595 $driverMock->expects($this->once())->method('isFolderEmpty')->will($this->returnValue(FALSE));
596 /** @var \TYPO3\CMS\Core\Resource\ResourceStorage|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $fixture */
597 $fixture = $this->getAccessibleMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array('checkFolderActionPermission'), array(), '', FALSE);
598 $fixture->expects($this->any())->method('checkFolderActionPermission')->will($this->returnValue(TRUE));
599 $fixture->_set('driver', $driverMock);
600 $fixture->deleteFolder($folderMock, FALSE);
601 }
602
603 /**
604 * @test
605 */
606 public function createFolderCallsDriverForFolderCreation() {
607 $mockedParentFolder = $this->getSimpleFolderMock('/someFolder/');
608 $this->prepareFixture(array(), TRUE);
609 $mockedDriver = $this->createDriverMock(array(), $this->fixture);
610 $mockedDriver->expects($this->once())->method('createFolder')->with($this->equalTo('newFolder'), $this->equalTo($mockedParentFolder))->will($this->returnValue(TRUE));
611 $mockedDriver->expects($this->once())->method('folderExists')->with($this->equalTo('/someFolder/'))->will($this->returnValue(TRUE));
612 $this->fixture->createFolder('newFolder', $mockedParentFolder);
613 }
614
615 /**
616 * @test
617 */
618 public function createFolderCanRecursivelyCreateFolders() {
619 $this->addToMount(array('someFolder' => array()));
620 $mockedDriver = $this->createDriverMock(array('basePath' => $this->getMountRootUrl()), NULL, NULL);
621 $this->prepareFixture(array(), TRUE, $mockedDriver);
622 $parentFolder = $this->fixture->getFolder('/someFolder/');
623 $newFolder = $this->fixture->createFolder('subFolder/secondSubfolder', $parentFolder);
624 $this->assertEquals('secondSubfolder', $newFolder->getName());
625 $this->assertFileExists($this->getUrlInMount('/someFolder/subFolder/'));
626 $this->assertFileExists($this->getUrlInMount('/someFolder/subFolder/secondSubfolder/'));
627 }
628
629 /**
630 * @test
631 */
632 public function createFolderIgnoresLeadingAndTrailingSlashesWithFoldername() {
633 $mockedParentFolder = $this->getSimpleFolderMock('/someFolder/');
634 $this->prepareFixture(array(), TRUE);
635 $mockedDriver = $this->createDriverMock(array(), $this->fixture);
636 $mockedDriver->expects($this->once())->method('folderExists')->with($this->equalTo('/someFolder/'))->will($this->returnValue(TRUE));
637 $mockedDriver->expects($this->once())->method('createFolder')->with($this->equalTo('subFolder'));
638 $this->fixture->createFolder('/subFolder/', $mockedParentFolder);
639 }
640
641 /**
642 * @test
643 */
644 public function createFolderUsesRootFolderAsParentFolderIfNotGiven() {
645 $mockedRootFolder = $this->getSimpleFolderMock('/');
646 $this->prepareFixture(array(), TRUE);
647 $mockedDriver = $this->createDriverMock(array(), $this->fixture);
648 $mockedDriver->expects($this->once())->method('getRootLevelFolder')->with()->will($this->returnValue($mockedRootFolder));
649 $mockedDriver->expects($this->once())->method('folderExists')->with($this->equalTo('/'))->will($this->returnValue(TRUE));
650 $mockedDriver->expects($this->once())->method('createFolder')->with($this->equalTo('someFolder'));
651 $this->fixture->createFolder('someFolder');
652 }
653
654 /**
655 * @test
656 */
657 public function createFolderCreatesNestedStructureEvenIfPartsAlreadyExist() {
658 $this->addToMount(array(
659 'existingFolder' => array()
660 ));
661 $this->initializeVfs();
662 $mockedDriver = $this->createDriverMock(array('basePath' => $this->getMountRootUrl()), NULL, NULL);
663 $this->prepareFixture(array(), TRUE, $mockedDriver);
664 $rootFolder = $this->fixture->getFolder('/');
665 $newFolder = $this->fixture->createFolder('existingFolder/someFolder', $rootFolder);
666 $this->assertEquals('someFolder', $newFolder->getName());
667 $this->assertFileExists($this->getUrlInMount('existingFolder/someFolder'));
668 }
669
670 /**
671 * @test
672 */
673 public function createFolderThrowsExceptionIfParentFolderDoesNotExist() {
674 $this->setExpectedException('InvalidArgumentException', '', 1325689164);
675 $mockedParentFolder = $this->getSimpleFolderMock('/someFolder/');
676 $this->prepareFixture(array(), TRUE);
677 $mockedDriver = $this->createDriverMock(array(), $this->fixture);
678 $mockedDriver->expects($this->once())->method('folderExists')->with($this->equalTo('/someFolder/'))->will($this->returnValue(FALSE));
679 $this->fixture->createFolder('newFolder', $mockedParentFolder);
680 }
681
682 /**
683 * @test
684 */
685 public function replaceFileFailsIfLocalFileDoesNotExist() {
686 $this->setExpectedException('InvalidArgumentException', '', 1325842622);
687 $this->prepareFixture(array(), TRUE);
688 $mockedFile = $this->getSimpleFileMock('/someFile');
689 $this->fixture->replaceFile($mockedFile, PATH_site . uniqid());
690 }
691
692 /**
693 * @test
694 */
695 public function getFileListHandsOverRecursiveFALSEifNotExplicitlySet() {
696 $this->prepareFixture(array(), TRUE);
697 $driver = $this->createDriverMock(array('basePath' => $this->getMountRootUrl()), $this->fixture, array('getFileList'));
698 $driver->expects($this->once())
699 ->method('getFileList')
700 ->with($this->anything(), $this->anything(), $this->anything(), $this->anything(), $this->anything(), FALSE)
701 ->will($this->returnValue(array()));
702 $this->fixture->getFileList('/');
703 }
704
705 /**
706 * @test
707 */
708 public function getFileListHandsOverRecursiveTRUEifSet() {
709
710 $this->prepareFixture(array(), TRUE);
711 $driver = $this->createDriverMock(array('basePath' => $this->getMountRootUrl()), $this->fixture, array('getFileList'));
712 $driver->expects($this->once())
713 ->method('getFileList')
714 ->with($this->anything(), $this->anything(), $this->anything(), $this->anything(), $this->anything(), TRUE)
715 ->will($this->returnValue(array()));
716 $this->fixture->getFileList('/', 0, 0, TRUE, TRUE, TRUE);
717 }
718
719 /**
720 * @test
721 */
722 public function getRoleReturnsDefaultForRegularFolders() {
723 $folderIdentifier = uniqid();
724 $this->addToMount(array(
725 $folderIdentifier => array()
726 ));
727 $this->prepareFixture(array());
728
729 $role = $this->fixture->getRole($this->getSimpleFolderMock('/' . $folderIdentifier . '/'));
730
731 $this->assertSame(\TYPO3\CMS\Core\Resource\FolderInterface::ROLE_DEFAULT, $role);
732 }
733
734 /**
735 * @test
736 */
737 public function getRoleReturnsCorrectValueForDefaultProcessingFolder() {
738 $this->prepareFixture(array());
739
740 $role = $this->fixture->getRole($this->getSimpleFolderMock('/' . ResourceStorage::DEFAULT_ProcessingFolder . '/'));
741
742 $this->assertSame(\TYPO3\CMS\Core\Resource\FolderInterface::ROLE_PROCESSING, $role);
743 }
744
745 /**
746 * @test
747 */
748 public function getRoleReturnsCorrectValueForConfiguredProcessingFolder() {
749 $folderIdentifier = uniqid();
750 $this->addToMount(array(
751 $folderIdentifier => array()
752 ));
753 $this->prepareFixture(array(), FALSE, NULL, array('processingfolder' => '/' . $folderIdentifier . '/'));
754
755 $role = $this->fixture->getRole($this->getSimpleFolderMock('/' . $folderIdentifier . '/'));
756
757 $this->assertSame(\TYPO3\CMS\Core\Resource\FolderInterface::ROLE_PROCESSING, $role);
758 }
759
760 /**
761 * Data provider for fetchFolderListFromDriverReturnsFolderWithoutProcessedFolder function
762 */
763 public function fetchFolderListFromDriverReturnsFolderWithoutProcessedFolderDataProvider() {
764 return array(
765 'Empty folderList returned' => array(
766 'path' => '/',
767 'processingFolder' => '_processed_',
768 'folderList' => array(),
769 'expectedItems' => array()
770 ),
771 'Empty _processed_ folder' => array(
772 'path' => '/',
773 'processingFolder' => '',
774 'folderList' => array(
775 '_processed_' => array(),
776 '_temp_' => array(),
777 'user_upload' => array()
778 ),
779 'expectedItems' => array(
780 'user_upload' => array(),
781 '_temp_' => array()
782 )
783 ),
784 '_processed_ folder not in folder list' => array(
785 'path' => '/',
786 'processingFolder' => '_processed_',
787 'folderList' => array(
788 '_temp_' => array()
789 ),
790 'expectedItems' => array(
791 '_temp_' => array()
792 )
793 ),
794 '_processed_ folder on root level' => array(
795 'path' => '/',
796 'processingFolder' => '_processed_',
797 'folderList' => array(
798 '_processed_' => array(),
799 '_temp_' => array(),
800 'user_upload' => array()
801 ),
802 'expectedItems' => array(
803 'user_upload' => array(),
804 '_temp_' => array()
805 )
806 ),
807 '_processed_ folder on second level' => array(
808 'path' => 'Public/',
809 'processingFolder' => 'Public/_processed_',
810 'folderList' => array(
811 '_processed_' => array(),
812 '_temp_' => array(),
813 'user_upload' => array()
814 ),
815 'expectedItems' => array(
816 'user_upload' => array(),
817 '_temp_' => array()
818 )
819 ),
820 '_processed_ folder on third level' => array(
821 'path' => 'Public/Files/',
822 'processingFolder' => 'Public/Files/_processed_',
823 'folderList' => array(
824 '_processed_' => array(),
825 '_temp_' => array(),
826 'user_upload' => array()
827 ),
828 'expectedItems' => array(
829 'user_upload' => array(),
830 '_temp_' => array()
831 )
832 )
833 );
834 }
835
836 /**
837 * @test
838 * @dataProvider fetchFolderListFromDriverReturnsFolderWithoutProcessedFolderDataProvider
839 */
840 public function fetchFolderListFromDriverReturnsFolderWithoutProcessedFolder($path, $processingFolder, $folderList, $expectedItems) {
841 $driverMock = $this->createDriverMock(array(), NULL, array('getFolderList', 'folderExists'));
842 $driverMock->expects($this->once())->method('getFolderList')->will($this->returnValue($folderList));
843 $driverMock->expects($this->any())->method('folderExists')->will($this->returnValue(TRUE));
844
845 $this->prepareFixture(array(), TRUE, $driverMock, array('processingfolder' => $processingFolder));
846
847 $this->assertSame($expectedItems, $this->fixture->fetchFolderListFromDriver($path));
848 }
849 }