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