[!!!][TASK] Remove BE/fileExtensions/webspace
[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 Prophecy\Argument;
18 use TYPO3\CMS\Core\Resource\Driver\AbstractDriver;
19 use TYPO3\CMS\Core\Resource\Driver\LocalDriver;
20 use TYPO3\CMS\Core\Resource\DuplicationBehavior;
21 use TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException;
22 use TYPO3\CMS\Core\Resource\File;
23 use TYPO3\CMS\Core\Resource\FileInterface;
24 use TYPO3\CMS\Core\Resource\FileRepository;
25 use TYPO3\CMS\Core\Resource\Folder;
26 use TYPO3\CMS\Core\Resource\Index\FileIndexRepository;
27 use TYPO3\CMS\Core\Resource\ResourceFactory;
28 use TYPO3\CMS\Core\Resource\ResourceStorage;
29 use TYPO3\CMS\Core\Utility\ArrayUtility;
30 use TYPO3\CMS\Core\Utility\GeneralUtility;
31
32 /**
33 * Test case for ResourceStorage class
34 */
35 class ResourceStorageTest extends BaseTestCase
36 {
37 /**
38 * @var array A backup of registered singleton instances
39 */
40 protected $singletonInstances = [];
41
42 /**
43 * @var ResourceStorage|\PHPUnit_Framework_MockObject_MockObject
44 */
45 protected $subject;
46
47 protected function setUp()
48 {
49 parent::setUp();
50 $this->singletonInstances = GeneralUtility::getSingletonInstances();
51 /** @var FileRepository|\PHPUnit_Framework_MockObject_MockObject $fileRepositoryMock */
52 $fileRepositoryMock = $this->createMock(FileRepository::class);
53 GeneralUtility::setSingletonInstance(
54 FileRepository::class,
55 $fileRepositoryMock
56 );
57 }
58
59 protected function tearDown()
60 {
61 GeneralUtility::resetSingletonInstances($this->singletonInstances);
62 parent::tearDown();
63 }
64
65 /**
66 * Prepare ResourceStorage
67 *
68 * @param array $configuration
69 * @param bool $mockPermissionChecks
70 * @param AbstractDriver|\PHPUnit_Framework_MockObject_MockObject $driverObject
71 * @param array $storageRecord
72 * @param array $mockedMethods
73 */
74 protected function prepareSubject(array $configuration, $mockPermissionChecks = false, AbstractDriver $driverObject = null, array $storageRecord = [], array $mockedMethods = [])
75 {
76 $permissionMethods = ['assureFileAddPermissions', 'checkFolderActionPermission', 'checkFileActionPermission', 'checkUserActionPermission', 'checkFileExtensionPermission', 'isWithinFileMountBoundaries', 'assureFileRenamePermissions'];
77 $configuration = $this->convertConfigurationArrayToFlexformXml($configuration);
78 $overruleArray = ['configuration' => $configuration];
79 ArrayUtility::mergeRecursiveWithOverrule($storageRecord, $overruleArray);
80 if ($driverObject == null) {
81 $driverObject = $this->getMockForAbstractClass(AbstractDriver::class, [], '', false);
82 }
83 if ($mockPermissionChecks) {
84 $mockedMethods = array_merge($mockedMethods, $permissionMethods);
85 }
86 $mockedMethods[] = 'getIndexer';
87
88 $this->subject = $this->getMockBuilder(ResourceStorage::class)
89 ->setMethods(array_unique($mockedMethods))
90 ->setConstructorArgs([$driverObject, $storageRecord])
91 ->getMock();
92 $this->subject->expects($this->any())->method('getIndexer')->will($this->returnValue($this->createMock(\TYPO3\CMS\Core\Resource\Index\Indexer::class)));
93 if ($mockPermissionChecks) {
94 foreach ($permissionMethods as $method) {
95 $this->subject->expects($this->any())->method($method)->will($this->returnValue(true));
96 }
97 }
98 }
99
100 /**
101 * Converts a simple configuration array into a FlexForm data structure serialized as XML
102 *
103 * @param array $configuration
104 * @return string
105 * @see GeneralUtility::array2xml()
106 */
107 protected function convertConfigurationArrayToFlexformXml(array $configuration)
108 {
109 $flexFormArray = ['data' => ['sDEF' => ['lDEF' => []]]];
110 foreach ($configuration as $key => $value) {
111 $flexFormArray['data']['sDEF']['lDEF'][$key] = ['vDEF' => $value];
112 }
113 $configuration = GeneralUtility::array2xml($flexFormArray);
114 return $configuration;
115 }
116
117 /**
118 * Creates a driver fixture object, optionally using a given mount object.
119 *
120 * IMPORTANT: Call this only after setting up the virtual file system (with the addTo* methods)!
121 *
122 * @param $driverConfiguration
123 * @param ResourceStorage $storageObject
124 * @param array $mockedDriverMethods
125 * @return \TYPO3\CMS\Core\Resource\Driver\LocalDriver|\PHPUnit_Framework_MockObject_MockObject
126 */
127 protected function createDriverMock($driverConfiguration, ResourceStorage $storageObject = null, $mockedDriverMethods = [])
128 {
129 $this->initializeVfs();
130
131 if (!isset($driverConfiguration['basePath'])) {
132 $driverConfiguration['basePath'] = $this->getMountRootUrl();
133 }
134
135 if ($mockedDriverMethods === null) {
136 $driver = new LocalDriver($driverConfiguration);
137 } else {
138 // We are using the LocalDriver here because PHPUnit can't mock concrete methods in abstract classes, so
139 // when using the AbstractDriver we would be in trouble when wanting to mock away some concrete method
140 $driver = $this->getMockBuilder(LocalDriver::class)
141 ->setMethods($mockedDriverMethods)
142 ->setConstructorArgs([$driverConfiguration])
143 ->getMock();
144 }
145 if ($storageObject !== null) {
146 $storageObject->setDriver($driver);
147 }
148 $driver->setStorageUid(6);
149 $driver->processConfiguration();
150 $driver->initialize();
151 return $driver;
152 }
153
154 /**
155 * @return array
156 */
157 public function capabilitiesDataProvider()
158 {
159 return [
160 'only public' => [
161 [
162 'public' => true,
163 'writable' => false,
164 'browsable' => false
165 ]
166 ],
167 'only writable' => [
168 [
169 'public' => false,
170 'writable' => true,
171 'browsable' => false
172 ]
173 ],
174 'only browsable' => [
175 [
176 'public' => false,
177 'writable' => false,
178 'browsable' => true
179 ]
180 ],
181 'all capabilities' => [
182 [
183 'public' => true,
184 'writable' => true,
185 'browsable' => true
186 ]
187 ],
188 'none' => [
189 [
190 'public' => false,
191 'writable' => false,
192 'browsable' => false
193 ]
194 ]
195 ];
196 }
197
198 /**
199 * @test
200 * @dataProvider capabilitiesDataProvider
201 * @TODO: Rewrite or move to functional suite
202 */
203 public function capabilitiesOfStorageObjectAreCorrectlySet(array $capabilities)
204 {
205 $this->markTestSkipped('This test does way to much and is mocked incomplete. Skipped for now.');
206 $storageRecord = [
207 'is_public' => $capabilities['public'],
208 'is_writable' => $capabilities['writable'],
209 'is_browsable' => $capabilities['browsable'],
210 'is_online' => true
211 ];
212 $mockedDriver = $this->createDriverMock(
213 [
214 'pathType' => 'relative',
215 'basePath' => 'fileadmin/',
216 ],
217 $this->subject,
218 null
219 );
220 $this->prepareSubject([], false, $mockedDriver, $storageRecord);
221 $this->assertEquals($capabilities['public'], $this->subject->isPublic(), 'Capability "public" is not correctly set.');
222 $this->assertEquals($capabilities['writable'], $this->subject->isWritable(), 'Capability "writable" is not correctly set.');
223 $this->assertEquals($capabilities['browsable'], $this->subject->isBrowsable(), 'Capability "browsable" is not correctly set.');
224 }
225
226 /**
227 * @test
228 * @TODO: Rewrite or move to functional suite
229 */
230 public function fileAndFolderListFiltersAreInitializedWithDefaultFilters()
231 {
232 $this->markTestSkipped('This test does way to much and is mocked incomplete. Skipped for now.');
233 $this->prepareSubject([]);
234 $this->assertEquals($GLOBALS['TYPO3_CONF_VARS']['SYS']['fal']['defaultFilterCallbacks'], $this->subject->getFileAndFolderNameFilters());
235 }
236
237 /**
238 * @test
239 */
240 public function addFileFailsIfFileDoesNotExist()
241 {
242 /** @var Folder|\PHPUnit_Framework_MockObject_MockObject $mockedFolder */
243 $mockedFolder = $this->createMock(Folder::class);
244 $this->expectException(\InvalidArgumentException::class);
245 $this->expectExceptionCode(1319552745);
246 $this->prepareSubject([]);
247 $this->subject->addFile('/some/random/file', $mockedFolder);
248 }
249
250 /**
251 * @test
252 */
253 public function getPublicUrlReturnsNullIfStorageIsNotOnline()
254 {
255 /** @var $driver LocalDriver|\PHPUnit_Framework_MockObject_MockObject */
256 $driver = $this->getMockBuilder(LocalDriver::class)
257 ->setConstructorArgs([['basePath' => $this->getMountRootUrl()]])
258 ->getMock();
259 /** @var $subject ResourceStorage|\PHPUnit_Framework_MockObject_MockObject */
260 $subject = $this->getMockBuilder(ResourceStorage::class)
261 ->setMethods(['isOnline'])
262 ->setConstructorArgs([$driver, ['configuration' => []]])
263 ->getMock();
264 $subject->expects($this->once())->method('isOnline')->will($this->returnValue(false));
265
266 $sourceFileIdentifier = '/sourceFile.ext';
267 $sourceFile = $this->getSimpleFileMock($sourceFileIdentifier);
268 $result = $subject->getPublicUrl($sourceFile);
269 $this->assertSame($result, null);
270 }
271
272 /**
273 * Data provider for checkFolderPermissionsRespectsFilesystemPermissions
274 *
275 * @return array
276 */
277 public function checkFolderPermissionsFilesystemPermissionsDataProvider()
278 {
279 return [
280 'read action on readable/writable folder' => [
281 'read',
282 ['r' => true, 'w' => true],
283 true
284 ],
285 'read action on unreadable folder' => [
286 'read',
287 ['r' => false, 'w' => true],
288 false
289 ],
290 'write action on read-only folder' => [
291 'write',
292 ['r' => true, 'w' => false],
293 false
294 ]
295 ];
296 }
297
298 /**
299 * @test
300 * @dataProvider checkFolderPermissionsFilesystemPermissionsDataProvider
301 * @param string $action 'read' or 'write'
302 * @param array $permissionsFromDriver The permissions as returned from the driver
303 * @param bool $expectedResult
304 */
305 public function checkFolderPermissionsRespectsFilesystemPermissions($action, $permissionsFromDriver, $expectedResult)
306 {
307 /** @var $mockedDriver LocalDriver|\PHPUnit_Framework_MockObject_MockObject */
308 $mockedDriver = $this->createMock(LocalDriver::class);
309 $mockedDriver->expects($this->any())->method('getPermissions')->will($this->returnValue($permissionsFromDriver));
310 /** @var $mockedFolder Folder|\PHPUnit_Framework_MockObject_MockObject */
311 $mockedFolder = $this->createMock(Folder::class);
312 // Let all other checks pass
313 /** @var $subject ResourceStorage|\PHPUnit_Framework_MockObject_MockObject */
314 $subject = $this->getMockBuilder(ResourceStorage::class)
315 ->setMethods(['isWritable', 'isBrowsable', 'checkUserActionPermission'])
316 ->setConstructorArgs([$mockedDriver, []])
317 ->getMock();
318 $subject->expects($this->any())->method('isWritable')->will($this->returnValue(true));
319 $subject->expects($this->any())->method('isBrowsable')->will($this->returnValue(true));
320 $subject->expects($this->any())->method('checkUserActionPermission')->will($this->returnValue(true));
321 $subject->setDriver($mockedDriver);
322
323 $this->assertSame($expectedResult, $subject->checkFolderActionPermission($action, $mockedFolder));
324 }
325
326 /**
327 * @test
328 */
329 public function checkUserActionPermissionsAlwaysReturnsTrueIfNoUserPermissionsAreSet()
330 {
331 $this->prepareSubject([]);
332 $this->assertTrue($this->subject->checkUserActionPermission('read', 'folder'));
333 }
334
335 /**
336 * @test
337 */
338 public function checkUserActionPermissionReturnsFalseIfPermissionIsSetToZero()
339 {
340 $this->prepareSubject([]);
341 $this->subject->setUserPermissions(['readFolder' => true, 'writeFile' => true]);
342 $this->assertTrue($this->subject->checkUserActionPermission('read', 'folder'));
343 }
344
345 public function checkUserActionPermission_arbitraryPermissionDataProvider()
346 {
347 return [
348 'all lower cased' => [
349 ['readFolder' => true],
350 'read',
351 'folder'
352 ],
353 'all upper case' => [
354 ['readFolder' => true],
355 'READ',
356 'FOLDER'
357 ],
358 'mixed case' => [
359 ['readFolder' => true],
360 'ReaD',
361 'FoLdEr'
362 ]
363 ];
364 }
365
366 /**
367 * @param array $permissions
368 * @param string $action
369 * @param string $type
370 * @test
371 * @dataProvider checkUserActionPermission_arbitraryPermissionDataProvider
372 */
373 public function checkUserActionPermissionAcceptsArbitrarilyCasedArguments(array $permissions, $action, $type)
374 {
375 $this->prepareSubject([]);
376 $this->subject->setUserPermissions($permissions);
377 $this->assertTrue($this->subject->checkUserActionPermission($action, $type));
378 }
379
380 /**
381 * @test
382 */
383 public function userActionIsDisallowedIfPermissionIsSetToFalse()
384 {
385 $this->prepareSubject([]);
386 $this->subject->setEvaluatePermissions(true);
387 $this->subject->setUserPermissions(['readFolder' => false]);
388 $this->assertFalse($this->subject->checkUserActionPermission('read', 'folder'));
389 }
390
391 /**
392 * @test
393 */
394 public function userActionIsDisallowedIfPermissionIsNotSet()
395 {
396 $this->prepareSubject([]);
397 $this->subject->setEvaluatePermissions(true);
398 $this->subject->setUserPermissions(['readFolder' => true]);
399 $this->assertFalse($this->subject->checkUserActionPermission('write', 'folder'));
400 }
401
402 /**
403 * @test
404 */
405 public function getEvaluatePermissionsWhenSetFalse()
406 {
407 $this->prepareSubject([]);
408 $this->subject->setEvaluatePermissions(false);
409 $this->assertFalse($this->subject->getEvaluatePermissions());
410 }
411
412 /**
413 * @test
414 */
415 public function getEvaluatePermissionsWhenSetTrue()
416 {
417 $this->prepareSubject([]);
418 $this->subject->setEvaluatePermissions(true);
419 $this->assertTrue($this->subject->getEvaluatePermissions());
420 }
421
422 /**
423 * @test
424 * @group integration
425 * @TODO: Rewrite or move to functional suite
426 */
427 public function setFileContentsUpdatesObjectProperties()
428 {
429 $this->markTestSkipped('This test does way to much and is mocked incomplete. Skipped for now.');
430 $this->initializeVfs();
431 $driverObject = $this->getMockForAbstractClass(AbstractDriver::class, [], '', false);
432 $this->subject = $this->getMockBuilder(ResourceStorage::class)
433 ->setMethods(['getFileIndexRepository', 'checkFileActionPermission'])
434 ->setConstructorArgs([$driverObject, []])
435 ->getMock();
436 $this->subject->expects($this->any())->method('checkFileActionPermission')->will($this->returnValue(true));
437 $fileInfo = [
438 'storage' => 'A',
439 'identifier' => 'B',
440 'mtime' => 'C',
441 'ctime' => 'D',
442 'mimetype' => 'E',
443 'size' => 'F',
444 'name' => 'G',
445 ];
446 $newProperties = [
447 'storage' => $fileInfo['storage'],
448 'identifier' => $fileInfo['identifier'],
449 'tstamp' => $fileInfo['mtime'],
450 'crdate' => $fileInfo['ctime'],
451 'mime_type' => $fileInfo['mimetype'],
452 'size' => $fileInfo['size'],
453 'name' => $fileInfo['name']
454 ];
455 $hash = 'asdfg';
456 /** @var $mockedDriver LocalDriver|\PHPUnit_Framework_MockObject_MockObject */
457 $mockedDriver = $this->getMockBuilder(LocalDriver::class)
458 ->setConstructorArgs([['basePath' => $this->getMountRootUrl()]])
459 ->getMock();
460 $mockedDriver->expects($this->once())->method('getFileInfoByIdentifier')->will($this->returnValue($fileInfo));
461 $mockedDriver->expects($this->once())->method('hash')->will($this->returnValue($hash));
462 $this->subject->setDriver($mockedDriver);
463 $indexFileRepositoryMock = $this->createMock(FileIndexRepository::class);
464 $this->subject->expects($this->any())->method('getFileIndexRepository')->will($this->returnValue($indexFileRepositoryMock));
465 /** @var $mockedFile File|\PHPUnit_Framework_MockObject_MockObject */
466 $mockedFile = $this->createMock(File::class);
467 $mockedFile->expects($this->any())->method('getIdentifier')->will($this->returnValue($fileInfo['identifier']));
468 // called by indexer because the properties are updated
469 $this->subject->expects($this->any())->method('getFileInfoByIdentifier')->will($this->returnValue($newProperties));
470 $mockedFile->expects($this->any())->method('getStorage')->will($this->returnValue($this->subject));
471 $mockedFile->expects($this->any())->method('getProperties')->will($this->returnValue(array_keys($fileInfo)));
472 $mockedFile->expects($this->any())->method('getUpdatedProperties')->will($this->returnValue(array_keys($newProperties)));
473 // do not update directly; that's up to the indexer
474 $indexFileRepositoryMock->expects($this->never())->method('update');
475 $this->subject->setFileContents($mockedFile, $this->getUniqueId());
476 }
477
478 /**
479 * @test
480 * @group integration
481 * @TODO: Rewrite or move to functional suite
482 */
483 public function moveFileCallsDriversMethodsWithCorrectArguments()
484 {
485 $this->markTestSkipped('This test does way to much and is mocked incomplete. Skipped for now.');
486 $localFilePath = '/path/to/localFile';
487 $sourceFileIdentifier = '/sourceFile.ext';
488 $fileInfoDummy = [
489 'storage' => 'A',
490 'identifier' => 'B',
491 'mtime' => 'C',
492 'ctime' => 'D',
493 'mimetype' => 'E',
494 'size' => 'F',
495 'name' => 'G',
496 ];
497 $this->addToMount([
498 'targetFolder' => []
499 ]);
500 $this->initializeVfs();
501 $targetFolder = $this->getSimpleFolderMock('/targetFolder/');
502 /** @var $sourceDriver LocalDriver|\PHPUnit_Framework_MockObject_MockObject */
503 $sourceDriver = $this->createMock(LocalDriver::class);
504 $sourceDriver->expects($this->once())->method('deleteFile')->with($this->equalTo($sourceFileIdentifier));
505 $configuration = $this->convertConfigurationArrayToFlexformXml([]);
506 $sourceStorage = new ResourceStorage($sourceDriver, ['configuration' => $configuration]);
507 $sourceFile = $this->getSimpleFileMock($sourceFileIdentifier);
508 $sourceFile->expects($this->once())->method('getForLocalProcessing')->will($this->returnValue($localFilePath));
509 $sourceFile->expects($this->any())->method('getStorage')->will($this->returnValue($sourceStorage));
510 $sourceFile->expects($this->once())->method('getUpdatedProperties')->will($this->returnValue(array_keys($fileInfoDummy)));
511 $sourceFile->expects($this->once())->method('getProperties')->will($this->returnValue($fileInfoDummy));
512 /** @var $mockedDriver \TYPO3\CMS\Core\Resource\Driver\LocalDriver|\PHPUnit_Framework_MockObject_MockObject */
513 $mockedDriver = $this->getMockBuilder(LocalDriver::class)
514 ->setConstructorArgs([['basePath' => $this->getMountRootUrl()]])
515 ->getMock();
516 $mockedDriver->expects($this->once())->method('getFileInfoByIdentifier')->will($this->returnValue($fileInfoDummy));
517 $mockedDriver->expects($this->once())->method('addFile')->with($localFilePath, '/targetFolder/', $this->equalTo('file.ext'))->will($this->returnValue('/targetFolder/file.ext'));
518 /** @var $subject ResourceStorage */
519 $subject = $this->getMockBuilder(ResourceStorage::class)
520 ->setMethods(['assureFileMovePermissions'])
521 ->setConstructorArgs([$mockedDriver, ['configuration' => $configuration]])
522 ->getMock();
523 $subject->moveFile($sourceFile, $targetFolder, 'file.ext');
524 }
525
526 /**
527 * @test
528 * @group integration
529 * @TODO: Rewrite or move to functional suite
530 */
531 public function storageUsesInjectedFilemountsToCheckForMountBoundaries()
532 {
533 $this->markTestSkipped('This test does way to much and is mocked incomplete. Skipped for now.');
534 $mockedFile = $this->getSimpleFileMock('/mountFolder/file');
535 $this->addToMount([
536 'mountFolder' => [
537 'file' => 'asdfg'
538 ]
539 ]);
540 $mockedDriver = $this->createDriverMock(['basePath' => $this->getMountRootUrl()], null, null);
541 $this->initializeVfs();
542 $this->prepareSubject([], null, $mockedDriver);
543 $this->subject->addFileMount('/mountFolder');
544 $this->assertEquals(1, count($this->subject->getFileMounts()));
545 $this->subject->isWithinFileMountBoundaries($mockedFile);
546 }
547
548 /**
549 * @test
550 * @TODO: Rewrite or move to functional suite
551 */
552 public function createFolderChecksIfParentFolderExistsBeforeCreatingFolder()
553 {
554 $this->markTestSkipped('This test does way to much and is mocked incomplete. Skipped for now.');
555 $mockedParentFolder = $this->getSimpleFolderMock('/someFolder/');
556 $mockedDriver = $this->createDriverMock([]);
557 $mockedDriver->expects($this->once())->method('folderExists')->with($this->equalTo('/someFolder/'))->will($this->returnValue(true));
558 $mockedDriver->expects($this->once())->method('createFolder')->with($this->equalTo('newFolder'))->will($this->returnValue($mockedParentFolder));
559 $this->prepareSubject([], true);
560 $this->subject->setDriver($mockedDriver);
561 $this->subject->createFolder('newFolder', $mockedParentFolder);
562 }
563
564 /**
565 * @test
566 */
567 public function deleteFolderThrowsExceptionIfFolderIsNotEmptyAndRecursiveDeleteIsDisabled()
568 {
569 $this->expectException(\RuntimeException::class);
570 $this->expectExceptionCode(1325952534);
571
572 /** @var \TYPO3\CMS\Core\Resource\Folder|\PHPUnit_Framework_MockObject_MockObject $folderMock */
573 $folderMock = $this->createMock(Folder::class);
574 /** @var $mockedDriver \TYPO3\CMS\Core\Resource\Driver\AbstractDriver|\PHPUnit_Framework_MockObject_MockObject */
575 $mockedDriver = $this->getMockForAbstractClass(AbstractDriver::class);
576 $mockedDriver->expects($this->once())->method('isFolderEmpty')->will($this->returnValue(false));
577 /** @var $subject ResourceStorage|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface */
578 $subject = $this->getAccessibleMock(ResourceStorage::class, ['checkFolderActionPermission'], [], '', false);
579 $subject->expects($this->any())->method('checkFolderActionPermission')->will($this->returnValue(true));
580 $subject->_set('driver', $mockedDriver);
581 $subject->deleteFolder($folderMock, false);
582 }
583
584 /**
585 * @test
586 * @TODO: Rewrite or move to functional suite
587 */
588 public function createFolderCallsDriverForFolderCreation()
589 {
590 $this->markTestSkipped('This test does way to much and is mocked incomplete. Skipped for now.');
591 $mockedParentFolder = $this->getSimpleFolderMock('/someFolder/');
592 $this->prepareSubject([], true);
593 $mockedDriver = $this->createDriverMock([], $this->subject);
594 $mockedDriver->expects($this->once())->method('createFolder')->with($this->equalTo('newFolder'), $this->equalTo('/someFolder/'))->will($this->returnValue(true));
595 $mockedDriver->expects($this->once())->method('folderExists')->with($this->equalTo('/someFolder/'))->will($this->returnValue(true));
596 $this->subject->createFolder('newFolder', $mockedParentFolder);
597 }
598
599 /**
600 * @test
601 * @TODO: Rewrite or move to functional suite
602 */
603 public function createFolderCanRecursivelyCreateFolders()
604 {
605 $this->markTestSkipped('This test does way to much and is mocked incomplete. Skipped for now.');
606 $this->addToMount(['someFolder' => []]);
607 $mockedDriver = $this->createDriverMock(['basePath' => $this->getMountRootUrl()], null, null);
608 $this->prepareSubject([], true, $mockedDriver);
609 $parentFolder = $this->subject->getFolder('/someFolder/');
610 $newFolder = $this->subject->createFolder('subFolder/secondSubfolder', $parentFolder);
611 $this->assertEquals('secondSubfolder', $newFolder->getName());
612 $this->assertFileExists($this->getUrlInMount('/someFolder/subFolder/'));
613 $this->assertFileExists($this->getUrlInMount('/someFolder/subFolder/secondSubfolder/'));
614 }
615
616 /**
617 * @test
618 * @TODO: Rewrite or move to functional suite
619 */
620 public function createFolderUsesRootFolderAsParentFolderIfNotGiven()
621 {
622 $this->markTestSkipped('This test does way to much and is mocked incomplete. Skipped for now.');
623 $this->prepareSubject([], true);
624 $mockedDriver = $this->createDriverMock([], $this->subject);
625 $mockedDriver->expects($this->once())->method('getRootLevelFolder')->with()->will($this->returnValue('/'));
626 $mockedDriver->expects($this->once())->method('createFolder')->with($this->equalTo('someFolder'));
627 $this->subject->createFolder('someFolder');
628 }
629
630 /**
631 * @test
632 * @TODO: Rewrite or move to functional suite
633 */
634 public function createFolderCreatesNestedStructureEvenIfPartsAlreadyExist()
635 {
636 $this->markTestSkipped('This test does way to much and is mocked incomplete. Skipped for now.');
637 $this->addToMount([
638 'existingFolder' => []
639 ]);
640 $this->initializeVfs();
641 $mockedDriver = $this->createDriverMock(['basePath' => $this->getMountRootUrl()], null, null);
642 $this->prepareSubject([], true, $mockedDriver);
643 $rootFolder = $this->subject->getFolder('/');
644 $newFolder = $this->subject->createFolder('existingFolder/someFolder', $rootFolder);
645 $this->assertEquals('someFolder', $newFolder->getName());
646 $this->assertFileExists($this->getUrlInMount('existingFolder/someFolder'));
647 }
648
649 /**
650 * @test
651 */
652 public function createFolderThrowsExceptionIfParentFolderDoesNotExist()
653 {
654 $this->expectException(\InvalidArgumentException::class);
655 $this->expectExceptionCode(1325689164);
656 $mockedParentFolder = $this->getSimpleFolderMock('/someFolder/');
657 $this->prepareSubject([], true);
658 $mockedDriver = $this->createDriverMock([], $this->subject);
659 $mockedDriver->expects($this->once())->method('folderExists')->with($this->equalTo('/someFolder/'))->will($this->returnValue(false));
660 $this->subject->createFolder('newFolder', $mockedParentFolder);
661 }
662
663 /**
664 * @test
665 */
666 public function renameFileRenamesFileAsRequested()
667 {
668 $mockedDriver = $this->createDriverMock([], $this->subject);
669 $mockedDriver->expects($this->once())->method('renameFile')->will($this->returnValue('bar'));
670 $this->prepareSubject([], true, $mockedDriver, [], ['emitPreFileRenameSignal', 'emitPostFileRenameSignal']);
671 /** @var File $file */
672 $file = new File(['identifier' => 'foo', 'name' => 'foo'], $this->subject);
673 $result = $this->subject->renameFile($file, 'bar');
674 // fake what the indexer does in updateIndexEntry
675 $result->updateProperties(['name' => $result->getIdentifier()]);
676 $this->assertSame('bar', $result->getName());
677 }
678
679 /**
680 * @test
681 */
682 public function renameFileRenamesWithUniqueNameIfConflictAndConflictModeIsRename()
683 {
684 $mockedDriver = $this->createDriverMock([], $this->subject);
685 $mockedDriver->expects($this->any())->method('renameFile')->will($this->onConsecutiveCalls($this->throwException(new ExistingTargetFileNameException('foo', 1489593090)), 'bar_01'));
686 //$mockedDriver->expects($this->at(1))->method('renameFile')->will($this->returnValue('bar_01'));
687 $mockedDriver->expects($this->any())->method('sanitizeFileName')->will($this->onConsecutiveCalls('bar', 'bar_01'));
688 $this->prepareSubject([], true, $mockedDriver, [], ['emitPreFileRenameSignal', 'emitPostFileRenameSignal', 'getUniqueName']);
689 /** @var File $file */
690 $file = new File(['identifier' => 'foo', 'name' => 'foo'], $this->subject);
691 $this->subject->expects($this->once())->method('getUniqueName')->will($this->returnValue('bar_01'));
692 $result = $this->subject->renameFile($file, 'bar');
693 // fake what the indexer does in updateIndexEntry
694 $result->updateProperties(['name' => $result->getIdentifier()]);
695 $this->assertSame('bar_01', $result->getName());
696 }
697
698 /**
699 * @test
700 */
701 public function renameFileThrowsExceptionIfConflictAndConflictModeIsCancel()
702 {
703 $mockedDriver = $this->createDriverMock([], $this->subject);
704 $mockedDriver->expects($this->once())->method('renameFile')->will($this->throwException(new ExistingTargetFileNameException('foo', 1489593099)));
705 $this->prepareSubject([], true, $mockedDriver, [], ['emitPreFileRenameSignal', 'emitPostFileRenameSignal']);
706 /** @var File $file */
707 $file = new File(['identifier' => 'foo', 'name' => 'foo'], $this->subject);
708 $this->expectException(ExistingTargetFileNameException::class);
709 $this->subject->renameFile($file, 'bar', DuplicationBehavior::CANCEL);
710 }
711
712 /**
713 * @test
714 */
715 public function renameFileReplacesIfConflictAndConflictModeIsReplace()
716 {
717 $mockedDriver = $this->createDriverMock([], $this->subject);
718 $mockedDriver->expects($this->once())->method('renameFile')->will($this->throwException(new ExistingTargetFileNameException('foo', 1489593098)));
719 $mockedDriver->expects($this->any())->method('sanitizeFileName')->will($this->returnValue('bar'));
720 $this->prepareSubject([], true, $mockedDriver, [], ['emitPreFileRenameSignal', 'emitPostFileRenameSignal', 'replaceFile', 'getPublicUrl', 'getResourceFactoryInstance']);
721 $this->subject->expects($this->once())->method('getPublicUrl')->will($this->returnValue('somePath'));
722 $resourceFactory = $this->prophesize(ResourceFactory::class);
723 $file = $this->prophesize(FileInterface::class);
724 $resourceFactory->getFileObjectFromCombinedIdentifier(Argument::any())->willReturn($file->reveal());
725 $this->subject->expects($this->once())->method('replaceFile')->will($this->returnValue($file->reveal()));
726 $this->subject->expects($this->any())->method('getResourceFactoryInstance')->will(self::returnValue($resourceFactory->reveal()));
727 /** @var File $file */
728 $file = new File(['identifier' => 'foo', 'name' => 'foo', 'missing' => false], $this->subject);
729 $this->subject->renameFile($file, 'bar', DuplicationBehavior::REPLACE);
730 }
731 }