6fa2a71c012d3dea36599e496d8667987aca848d
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Resource / Driver / LocalDriverTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Resource\Driver;
3 use TYPO3\CMS\Core\Utility\GeneralUtility;
4
5 /***************************************************************
6 * Copyright notice
7 *
8 * (c) 2011-2013 Andreas Wolf <andreas.wolf@ikt-werk.de>
9 * All rights reserved
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 * A copy is found in the textfile GPL.txt and important notices to the license
20 * from the author is found in LICENSE.txt distributed with these scripts.
21 *
22 *
23 * This script is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * This copyright notice MUST APPEAR in all copies of the script!
29 ***************************************************************/
30
31 require_once dirname(dirname(__FILE__)) . '/BaseTestCase.php';
32 require_once dirname(__FILE__) . '/Fixtures/LocalDriverFilenameFilter.php';
33
34 /**
35 * Testcase for the local storage driver class of the TYPO3 VFS
36 *
37 * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
38 */
39 class LocalDriverTest extends \TYPO3\CMS\Core\Tests\Unit\Resource\BaseTestCase {
40
41 /**
42 * @var array A backup of registered singleton instances
43 */
44 protected $singletonInstances = array();
45
46 /**
47 * @var array
48 */
49 static private $testDirs = array();
50
51 public function setUp() {
52 parent::setUp();
53 // use a mocked file repository to avoid updating the index when doing property update tests
54 $mockedRepository = $this->getMock('TYPO3\\CMS\\Core\\Resource\\FileRepository');
55 $this->singletonInstances = \TYPO3\CMS\Core\Utility\GeneralUtility::getSingletonInstances();
56 \TYPO3\CMS\Core\Utility\GeneralUtility::purgeInstances();
57 \TYPO3\CMS\Core\Utility\GeneralUtility::setSingletonInstance('TYPO3\\CMS\\Core\\Resource\\FileRepository', $mockedRepository);
58 }
59
60 public function tearDown() {
61 \TYPO3\CMS\Core\Utility\GeneralUtility::resetSingletonInstances($this->singletonInstances);
62 parent::tearDown();
63 }
64
65 static public function tearDownAfterClass() {
66 foreach (self::$testDirs as $dir) {
67 chmod($dir, 0777);
68 \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir($dir, TRUE);
69 }
70 }
71
72 /**
73 * Creates a "real" directory for doing tests. This is neccessary because some file system properties (e.g. permissions)
74 * cannot be reflected by vfsStream, and some methods (like touch()) don't work there either.
75 *
76 * Created directories are automatically destroyed by the tearDownAfterClass() method.
77 *
78 * @return string
79 */
80 protected function createRealTestdir() {
81 $basedir = PATH_site . 'typo3temp/' . uniqid('fal-test-');
82 mkdir($basedir);
83 self::$testDirs[] = $basedir;
84 return $basedir;
85 }
86
87 /**
88 * Create a "real" directory together with a driverFixture configured
89 * for this directory.
90 *
91 * @return array With path to base directory and driver fixture
92 */
93 protected function prepareRealTestEnvironment() {
94 $basedir = $this->createRealTestdir();
95 $fixture = $this->createDriverFixture(array(
96 'basePath' => $basedir
97 ));
98 return array($basedir, $fixture);
99 }
100
101 /**
102 * Creates a driver fixture object, optionally using a given mount object.
103 *
104 * IMPORTANT: Call this only after setting up the virtual file system (with the addTo* methods)!
105 *
106 * @param $driverConfiguration
107 * @param \TYPO3\CMS\Core\Resource\ResourceStorage $storageObject
108 * @param array $mockedDriverMethods
109 * @return \TYPO3\CMS\Core\Resource\Driver\LocalDriver
110 */
111 protected function createDriverFixture($driverConfiguration, \TYPO3\CMS\Core\Resource\ResourceStorage $storageObject = NULL, $mockedDriverMethods = array()) {
112 $this->initializeVfs();
113 if ($storageObject == NULL) {
114 $storageObject = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
115 }
116 if (count($mockedDriverMethods) == 0) {
117 $driver = new \TYPO3\CMS\Core\Resource\Driver\LocalDriver($driverConfiguration);
118 } else {
119 $driver = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Driver\\LocalDriver', $mockedDriverMethods, array($driverConfiguration));
120 }
121 $storageObject->setDriver($driver);
122 $driver->setStorage($storageObject);
123 $driver->processConfiguration();
124 $driver->initialize();
125 return $driver;
126 }
127
128 /**
129 * @test
130 */
131 public function rootLevelFolderIsCreatedWithCorrectArguments() {
132 $mockedMount = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
133 $fixture = $this->createDriverFixture(array('basePath' => $this->getMountRootUrl()), $mockedMount);
134 $mockedFactory = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceFactory');
135 $mockedFactory->expects($this->once())->method('createFolderObject')->with($this->equalTo($mockedMount), $this->equalTo('/'), $this->equalTo(''));
136 \TYPO3\CMS\Core\Utility\GeneralUtility::setSingletonInstance('TYPO3\\CMS\\Core\\Resource\\ResourceFactory', $mockedFactory);
137 $fixture->getRootLevelFolder();
138 \TYPO3\CMS\Core\Utility\GeneralUtility::setSingletonInstance('TYPO3\\CMS\\Core\\Resource\\ResourceFactory', new \TYPO3\CMS\Core\Resource\ResourceFactory());
139 }
140
141 /**
142 * @test
143 */
144 public function getDefaultFolderReturnsFolderForUserUploadPath() {
145 $fixture = $this->createDriverFixture(array(
146 'basePath' => $this->getMountRootUrl()
147 ));
148 $folder = $fixture->getDefaultFolder();
149 $this->assertStringEndsWith('user_upload/', $folder->getIdentifier());
150 }
151
152 /**
153 * @test
154 */
155 public function defaultLevelFolderFolderIsCreatedIfItDoesntExist() {
156 $fixture = $this->createDriverFixture(array(
157 'basePath' => $this->getMountRootUrl()
158 ));
159 $fixture->getDefaultFolder();
160 $this->assertFileExists($this->getUrlInMount('/user_upload/'));
161 }
162
163 /**
164 * @test
165 */
166 public function getFolderInFolderReturnsCorrectFolderObject() {
167 $this->addToMount(array(
168 'someDir' => array(
169 'someSubdir' => array()
170 )
171 ));
172 $fixture = $this->createDriverFixture(array(
173 'basePath' => $this->getMountRootUrl()
174 ));
175 $parentFolder = $fixture->getFolder('/someDir');
176 $folder = $fixture->getFolderInFolder('someSubdir', $parentFolder);
177 $this->assertEquals('/someDir/someSubdir/', $folder->getIdentifier());
178 }
179
180 /**
181 * @test
182 */
183 public function createFolderCreatesFolderOnDisk() {
184 $this->addToMount(array('some' => array('folder' => array())));
185 $fixture = $this->createDriverFixture(array(
186 'basePath' => $this->getMountRootUrl()
187 ));
188 $mockedFolder = $this->getSimpleFolderMock('/some/folder/');
189 $fixture->createFolder('path', $mockedFolder);
190 $this->assertFileExists($this->getUrlInMount('/some/folder/'));
191 $this->assertFileExists($this->getUrlInMount('/some/folder/path'));
192 }
193
194 /**
195 * @test
196 */
197 public function createFolderReturnsFolderObject() {
198 $this->addToMount(array('some' => array('folder' => array())));
199 $fixture = $this->createDriverFixture(array(
200 'basePath' => $this->getMountRootUrl()
201 ));
202 $mockedFolder = $this->getSimpleFolderMock('/some/folder/');
203 $createdFolder = $fixture->createFolder('path', $mockedFolder);
204 $this->assertEquals('/some/folder/path/', $createdFolder->getIdentifier());
205 }
206
207 public function createFolderSanitizesFolderNameBeforeCreationDataProvider() {
208 return array(
209 'folder name with NULL character' => array(
210 'some' . chr(0) . 'Folder',
211 'some_Folder'
212 ),
213 'folder name with directory part' => array(
214 '../someFolder',
215 '.._someFolder'
216 )
217 );
218 }
219
220 /**
221 * @test
222 * @dataProvider createFolderSanitizesFolderNameBeforeCreationDataProvider
223 */
224 public function createFolderSanitizesFolderNameBeforeCreation($newFolderName, $expectedFolderName) {
225 $this->addToMount(array('some' => array('folder' => array())));
226 $fixture = $this->createDriverFixture(array(
227 'basePath' => $this->getMountRootUrl()
228 ));
229 $mockedFolder = $this->getSimpleFolderMock('/some/folder/');
230 $fixture->createFolder($newFolderName, $mockedFolder);
231 $this->assertFileExists($this->getUrlInMount('/some/folder/' . $expectedFolderName));
232 }
233
234 /**
235 * @test
236 */
237 public function driverConfigVerificationFailsIfConfiguredBasePathDoesNotExist() {
238 $this->setExpectedException('TYPO3\\CMS\\Core\\Resource\\Exception\\InvalidConfigurationException', '', 1299233097);
239 $driverConfiguration = array(
240 'basePath' => \vfsStream::url($this->basedir . 'doesntexist/')
241 );
242 $this->assertFalse(file_exists($driverConfiguration['basePath']));
243 \TYPO3\CMS\Core\Resource\Driver\LocalDriver::verifyConfiguration($driverConfiguration);
244 }
245
246 /**
247 * @test
248 */
249 public function basePathIsNormalizedWithTrailingSlash() {
250 $driverConfiguration = array(
251 'basePath' => $this->getMountRootUrl()
252 );
253 $fixture = $this->createDriverFixture($driverConfiguration);
254 $this->assertEquals('/', substr($fixture->getAbsoluteBasePath(), -1));
255 }
256
257 /**
258 * @test
259 */
260 public function noSecondSlashIsAddedIfBasePathAlreadyHasTrailingSlash() {
261 $driverConfiguration = array(
262 'basePath' => $this->getMountRootUrl()
263 );
264 $fixture = $this->createDriverFixture($driverConfiguration);
265 $this->assertNotEquals('/', substr($fixture->getAbsoluteBasePath(), -2, 1));
266 }
267
268 /**
269 * @test
270 */
271 public function getAbsolutePathReturnsCorrectPath() {
272 $this->addToMount(array(
273 'someFolder' => array(
274 'file1.ext' => 'asdfg'
275 )
276 ));
277 $mockedFile = $this->getSimpleFileMock('someFolder/file1.ext');
278 $fixture = $this->createDriverFixture(array(
279 'basePath' => $this->getMountRootUrl()
280 ));
281 $path = $fixture->getAbsolutePath($mockedFile);
282 $this->assertTrue(file_exists($path));
283 $this->assertEquals($this->getUrlInMount('/someFolder/file1.ext'), $path);
284 }
285
286 /**
287 * @test
288 */
289 public function getLowLevelFileInfoReturnsCorrectFileSize() {
290 $contents = uniqid('foo');
291 $this->addToMount(array('file1.ext' => $contents));
292 $mockedFile = $this->getSimpleFileMock('file1.ext');
293 $fixture = $this->createDriverFixture(
294 array('basePath' => $this->getMountRootUrl()),
295 NULL,
296 // Mocked because finfo() can not deal with vfs streams and throws warnings
297 array('getMimeTypeOfFile')
298 );
299 $stat = $fixture->getLowLevelFileInfo($mockedFile);
300 $this->assertEquals(strlen($contents), $stat['size']);
301 }
302
303 /**
304 * @test
305 */
306 public function getLowLevelFileInfoReturnsCorrectFileCtime() {
307 $contents = uniqid('foo');
308 $this->addToMount(array('file1.ext' => $contents));
309 $mockedFile = $this->getSimpleFileMock('file1.ext');
310 $fixture = $this->createDriverFixture(
311 array('basePath' => $this->getMountRootUrl()),
312 NULL,
313 // Mocked because finfo() can not deal with vfs streams and throws warnings
314 array('getMimeTypeOfFile')
315 );
316 $path = $fixture->getAbsolutePath($mockedFile);
317 $stat = $fixture->getLowLevelFileInfo($mockedFile);
318 $this->assertEquals(filectime($path), $stat['ctime']);
319 }
320
321 /**
322 * @test
323 */
324 public function getLowLevelFileInfoReturnsCorrectFileMtime() {
325 $contents = uniqid('foo');
326 $this->addToMount(array('file1.ext' => $contents));
327 $mockedFile = $this->getSimpleFileMock('file1.ext');
328 $fixture = $this->createDriverFixture(
329 array('basePath' => $this->getMountRootUrl()),
330 NULL,
331 // Mocked because finfo() can not deal with vfs streams and throws warnings
332 array('getMimeTypeOfFile')
333 );
334 $path = $fixture->getAbsolutePath($mockedFile);
335 $stat = $fixture->getLowLevelFileInfo($mockedFile);
336 $this->assertEquals(fileatime($path), $stat['mtime']);
337 }
338
339 /**
340 * @test
341 */
342 public function getLowLevelFileInfoReturnsCorrectFileAtime() {
343 $contents = uniqid('foo');
344 $this->addToMount(array('file1.ext' => $contents));
345 $mockedFile = $this->getSimpleFileMock('file1.ext');
346 $fixture = $this->createDriverFixture(
347 array('basePath' => $this->getMountRootUrl()),
348 NULL,
349 // Mocked because finfo() can not deal with vfs streams and throws warnings
350 array('getMimeTypeOfFile')
351 );
352 $path = $fixture->getAbsolutePath($mockedFile);
353 $stat = $fixture->getLowLevelFileInfo($mockedFile);
354 $this->assertEquals(filemtime($path), $stat['atime']);
355 }
356
357 /**
358 * @test
359 */
360 public function getLowLevelFileInfoReturnsCorrectFileMimeType() {
361 $baseDir = $this->createRealTestdir();
362 /** @var $driverFixture \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
363 $driverFixture = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Driver\\LocalDriver', array('getAbsolutePath'), array());
364 $fileMock = $this->getMock('TYPO3\\CMS\\Core\\Resource\\FileInterface');
365 copy(__DIR__ . '/Fixtures/Dummy.html', $baseDir . '/Dummy.html');
366 $driverFixture->expects($this->once())->method('getAbsolutePath')->will($this->returnValue($baseDir . '/Dummy.html'));
367 $stats = $driverFixture->getLowLevelFileInfo($fileMock);
368 $this->assertEquals('text/html', $stats['mimetype']);
369 }
370
371 /**
372 * @test
373 */
374 public function addFileMovesFileToCorrectLocation() {
375 $mockedFolder = $this->getSimpleFolderMock('/targetFolder/');
376 $this->addToMount(array('targetFolder' => array()));
377 $this->addToVfs(array(
378 'sourceFolder' => array(
379 'file' => 'asdf'
380 )
381 ));
382 $fixture = $this->createDriverFixture(
383 array('basePath' => $this->getMountRootUrl()),
384 NULL,
385 // Mocked because finfo() can not deal with vfs streams and throws warnings
386 array('getMimeTypeOfFile')
387 );
388 $this->assertTrue(file_exists($this->getUrl('sourceFolder/file')));
389 $fixture->addFile($this->getUrl('sourceFolder/file'), $mockedFolder, 'file');
390 $this->assertTrue(file_exists($this->getUrlInMount('/targetFolder/file')));
391 }
392
393 /**
394 * @test
395 */
396 public function addFileUsesFilenameIfGiven() {
397 $mockedFolder = $this->getSimpleFolderMock('/targetFolder/');
398 $this->addToMount(array('targetFolder' => array()));
399 $this->addToVfs(array(
400 'sourceFolder' => array(
401 'file' => 'asdf'
402 )
403 ));
404 $fixture = $this->createDriverFixture(
405 array('basePath' => $this->getMountRootUrl()),
406 NULL,
407 // Mocked because finfo() can not deal with vfs streams and throws warnings
408 array('getMimeTypeOfFile')
409 );
410 $this->assertTrue(file_exists($this->getUrl('sourceFolder/file')));
411 $fixture->addFile($this->getUrl('sourceFolder/file'), $mockedFolder, 'targetFile');
412 $this->assertTrue(file_exists($this->getUrlInMount('/targetFolder/targetFile')));
413 }
414
415 /**
416 * @test
417 */
418 public function addFileFailsIfFileIsInDriverStorage() {
419 $mockedFolder = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Folder', array(), array(), '', FALSE);
420 $mockedFolder->expects($this->any())->method('getIdentifier')->will($this->returnValue('/targetFolder/'));
421 $this->setExpectedException('InvalidArgumentException', '', 1314778269);
422 $this->addToMount(array(
423 'targetFolder' => array(
424 'file' => 'asdf'
425 )
426 ));
427 $storageObject = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
428 $storageObject->expects($this->any())->method('getUid')->will($this->returnValue('1'));
429 $fixture = $this->createDriverFixture(
430 array('basePath' => $this->getMountRootUrl()),
431 $storageObject
432 );
433 $fixture->addFile($this->getUrlInMount('/targetFolder/file'), $mockedFolder, 'file');
434 }
435
436 /**
437 * @test
438 */
439 public function addFileReturnsFileObject() {
440 $mockedFolder = $this->getMock('TYPO3\\CMS\\Core\\Resource\\Folder', array(), array(), '', FALSE);
441 $mockedFolder->expects($this->any())->method('getIdentifier')->will($this->returnValue('/targetFolder/'));
442 $this->addToMount(array('targetFolder' => array()));
443 $this->addToVfs(array(
444 'sourceFolder' => array(
445 'file' => 'asdf'
446 )
447 ));
448 $fixture = $this->createDriverFixture(
449 array('basePath' => $this->getMountRootUrl()),
450 NULL,
451 // Mocked because finfo() can not deal with vfs streams and throws warnings
452 array('getMimeTypeOfFile')
453 );
454 $this->assertTrue(file_exists($this->getUrl('sourceFolder/file')));
455 $fileObject = $fixture->addFile($this->getUrl('sourceFolder/file'), $mockedFolder, 'file');
456 $this->assertInstanceOf('TYPO3\\CMS\\Core\\Resource\\File', $fileObject);
457 $this->assertEquals('file', $fileObject->getName());
458 $this->assertEquals('/targetFolder/file', $fileObject->getIdentifier());
459 }
460
461 /**
462 * @test
463 */
464 public function addFileRawCreatesCopyOfFile() {
465 $this->addToMount(array('targetFolder' => array()));
466 $this->addToVfs(array(
467 'sourceFolder' => array(
468 'file' => 'asdf'
469 )
470 ));
471 $fixture = $this->createDriverFixture(array(
472 'basePath' => $this->getMountRootUrl()
473 ));
474 $this->assertTrue(file_exists($this->getUrl('sourceFolder/file')));
475 $fileIdentifier = $fixture->addFileRaw($this->getUrl('sourceFolder/file'), $this->getSimpleFolderMock('/targetFolder/'), 'somefile');
476 $this->assertTrue(file_exists($this->getUrl('sourceFolder/file')));
477 $this->assertTrue(file_exists($this->getUrlInMount('targetFolder/somefile')));
478 $this->assertEquals('/targetFolder/somefile', $fileIdentifier);
479 }
480
481 /**
482 * @test
483 */
484 public function deleteFileRawRemovesFile() {
485 $this->addToMount(array(
486 'targetFolder' => array(
487 'file' => 'asdjlkfa'
488 )
489 ));
490 $fixture = $this->createDriverFixture(array(
491 'basePath' => $this->getMountRootUrl()
492 ));
493 $this->assertTrue(file_exists($this->getUrlInMount('targetFolder/file')));
494 $fixture->deleteFileRaw('/targetFolder/file');
495 $this->assertFalse(file_exists($this->getUrlInMount('targetFolder/file')));
496 }
497
498 /**
499 * @test
500 */
501 public function replacingFileUpdatesMetadataInFileObject() {
502 $this->addToMount(array(
503 'targetFolder' => array(
504 'file' => 'asdjlkfa'
505 )
506 ));
507 $this->addToVfs(array(
508 'sourceFolder' => array(
509 'file' => 'asjdalks'
510 )
511 ));
512 $fixture = $this->createDriverFixture(
513 array('basePath' => $this->getMountRootUrl()),
514 NULL,
515 // Mocked because finfo() can not deal with vfs streams and throws warnings
516 array('getMimeTypeOfFile')
517 );
518 $mockedFile = $this->getSimpleFileMock('/targetFolder/file', array('updateProperties'));
519 $mockedFile->expects($this->once())->method('updateProperties');
520 $fixture->replaceFile($mockedFile, $this->getUrl('sourceFolder/file'));
521 }
522
523 /**
524 * @test
525 */
526 public function existenceChecksWorkForFilesAndFolders() {
527 $this->addToMount(array(
528 'file' => 'asdf',
529 'folder' => array()
530 ));
531 $fixture = $this->createDriverFixture(array(
532 'basePath' => $this->getMountRootUrl()
533 ));
534 // Using slashes at the beginning of paths because they will be stored in the DB this way.
535 $this->assertTrue($fixture->fileExists('/file'));
536 $this->assertTrue($fixture->folderExists('/folder/'));
537 $this->assertFalse($fixture->fileExists('/nonexistingFile'));
538 $this->assertFalse($fixture->folderExists('/nonexistingFolder/'));
539 }
540
541 /**
542 * @test
543 */
544 public function existenceChecksInFolderWorkForFilesAndFolders() {
545 $mockedFolder = $this->getSimpleFolderMock('/subfolder/');
546 $this->addToMount(array(
547 'subfolder' => array(
548 'file' => 'asdf',
549 'folder' => array()
550 )
551 ));
552 $fixture = $this->createDriverFixture(array(
553 'basePath' => $this->getMountRootUrl()
554 ));
555 $this->assertTrue($fixture->fileExistsInFolder('file', $mockedFolder));
556 $this->assertTrue($fixture->folderExistsInFolder('folder', $mockedFolder));
557 $this->assertFalse($fixture->fileExistsInFolder('nonexistingFile', $mockedFolder));
558 $this->assertFalse($fixture->folderExistsInFolder('nonexistingFolder', $mockedFolder));
559 }
560
561 /**
562 * @test
563 */
564 public function getPublicUrlReturnsCorrectUriForConfiguredBaseUri() {
565 $baseUri = 'http://example.org/foobar/' . uniqid();
566 $this->addToMount(array(
567 'file.ext' => 'asdf',
568 'subfolder' => array(
569 'file2.ext' => 'asdf'
570 )
571 ));
572 $fixture = $this->createDriverFixture(array(
573 'basePath' => $this->getMountRootUrl(),
574 'baseUri' => $baseUri
575 ));
576 $mockedFile1 = $this->getMock('TYPO3\\CMS\\Core\\Resource\\File', array(), array(), '', FALSE);
577 $mockedFile1->expects($this->any())->method('getIdentifier')->will($this->returnValue('/file.ext'));
578 $mockedFile2 = $this->getMock('TYPO3\\CMS\\Core\\Resource\\File', array(), array(), '', FALSE);
579 $mockedFile2->expects($this->any())->method('getIdentifier')->will($this->returnValue('/subfolder/file2.ext'));
580 $this->assertEquals($baseUri . '/file.ext', $fixture->getPublicUrl($mockedFile1));
581 $this->assertEquals($baseUri . '/subfolder/file2.ext', $fixture->getPublicUrl($mockedFile2));
582 }
583
584 /**
585 * @test
586 */
587 public function fileContentsCanBeWrittenAndRead() {
588 $fileContents = 'asdf';
589 $this->addToMount(array(
590 'file.ext' => $fileContents
591 ));
592 $fixture = $this->createDriverFixture(array(
593 'basePath' => $this->getMountRootUrl()
594 ));
595 $mockedFile = $this->getMock('TYPO3\\CMS\\Core\\Resource\\File', array(), array(), '', FALSE);
596 $mockedFile->expects($this->any())->method('getIdentifier')->will($this->returnValue('/file.ext'));
597 $this->assertEquals($fileContents, $fixture->getFileContents($mockedFile), 'File contents could not be read');
598 $newFileContents = 'asdfgh';
599 $fixture->setFileContents($mockedFile, $newFileContents);
600 $this->assertEquals($newFileContents, $fixture->getFileContents($mockedFile), 'New file contents could not be read.');
601 }
602
603 /**
604 * @test
605 */
606 public function setFileContentsReturnsNumberOfBytesWrittenToFile() {
607 $fileContents = 'asdf';
608 $this->addToMount(array(
609 'file.ext' => $fileContents
610 ));
611 $fixture = $this->createDriverFixture(array(
612 'basePath' => $this->getMountRootUrl()
613 ));
614 $mockedFile = $this->getSimpleFileMock('/file.ext');
615 $newFileContents = 'asdfgh';
616 $bytesWritten = $fixture->setFileContents($mockedFile, $newFileContents);
617 $this->assertEquals(strlen($newFileContents), $bytesWritten);
618 }
619
620 /**
621 * @test
622 * @depends existenceChecksWorkForFilesAndFolders
623 * @return array The driver fixture, the mocked file
624 */
625 public function newFilesCanBeCreated() {
626 $this->addToMount(array(
627 'someDir' => array()
628 ));
629 /** @var $fixture \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
630 list($basedir, $fixture) = $this->prepareRealTestEnvironment();
631 mkdir($basedir . '/someDir');
632 $fixture->createFile('testfile.txt', $fixture->getFolder('someDir'));
633 $mockedFile = $this->getSimpleFileMock('/someDir/testfile.txt');
634 $this->assertTrue($fixture->fileExists('/someDir/testfile.txt'));
635 return array($fixture, $mockedFile);
636 }
637
638 /**
639 * @test
640 * @depends newFilesCanBeCreated
641 */
642 public function createdFilesAreEmpty(array $arguments) {
643 /** @var $fixture \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
644 list($fixture, $mockedFile) = $arguments;
645 $fileData = $fixture->getFileContents($mockedFile);
646 $this->assertEquals(0, strlen($fileData));
647 }
648
649 /**
650 * @test
651 */
652 public function createFileFixesPermissionsOnCreatedFile() {
653 if (TYPO3_OS == 'WIN') {
654 $this->markTestSkipped('createdFilesHaveCorrectRights() tests not available on Windows');
655 }
656
657 // No one will use this as his default file create mask so we hopefully don't get any false positives
658 $testpattern = '0646';
659 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = $testpattern;
660
661 $this->addToMount(
662 array(
663 'someDir' => array()
664 )
665 );
666 /** @var $fixture \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
667 list($basedir, $fixture) = $this->prepareRealTestEnvironment();
668 mkdir($basedir . '/someDir');
669 $fixture->createFile('testfile.txt', $fixture->getFolder('/someDir'));
670 $this->assertEquals($testpattern, decoct(fileperms($basedir . '/someDir/testfile.txt') & 0777));
671 }
672
673 /**********************************
674 * File and directory listing
675 **********************************/
676 /**
677 * @test
678 */
679 public function getFileReturnsCorrectIdentifier() {
680 $this->addToMount(array(
681 'someDir' => array(
682 'someFile' => 'asdfg'
683 ),
684 'someFileAtRootLevel' => 'foobar'
685 ));
686 $fixture = $this->createDriverFixture(
687 array('basePath' => $this->getMountRootUrl()),
688 NULL,
689 // Mocked because finfo() can not deal with vfs streams and throws warnings
690 array('getMimeTypeOfFile')
691 );
692 $subdirFileInfo = $fixture->getFileInfoByIdentifier('/someDir/someFile');
693 $this->assertEquals('/someDir/someFile', $subdirFileInfo['identifier']);
694 $rootFileInfo = $fixture->getFileInfoByIdentifier('/someFileAtRootLevel');
695 $this->assertEquals('/someFileAtRootLevel', $rootFileInfo['identifier']);
696 }
697
698 /**
699 * @test
700 */
701 public function getFileThrowsExceptionIfFileDoesNotExist() {
702 $this->setExpectedException('InvalidArgumentException', '', 1314516809);
703 $fixture = $this->createDriverFixture(array(
704 'basePath' => $this->getMountRootUrl()
705 ));
706 $fixture->getFileInfoByIdentifier('/some/file/at/a/random/path');
707 }
708
709 /**
710 * @test
711 */
712 public function getFileListReturnsEmptyArrayForEmptyDirectory() {
713 $fixture = $this->createDriverFixture(array(
714 'basePath' => $this->getMountRootUrl()
715 ));
716 $fileList = $fixture->getFileList('/');
717 $this->assertEmpty($fileList);
718 }
719
720 /**
721 * @test
722 */
723 public function getFileListReturnsAllFilesInDirectory() {
724 $dirStructure = array(
725 'aDir' => array(),
726 'file1' => 'asdfg',
727 'file2' => 'fdsa'
728 );
729 $this->addToMount($dirStructure);
730 $fixture = $this->createDriverFixture(
731 array('basePath' => $this->getMountRootUrl()),
732 NULL,
733 // Mocked because finfo() can not deal with vfs streams and throws warnings
734 array('getMimeTypeOfFile')
735 );
736 $fileList = $fixture->getFileList('/');
737 $this->assertEquals(array('file1', 'file2'), array_keys($fileList));
738 }
739
740 /**
741 * @test
742 */
743 public function getFileListFailsIfDirectoryDoesNotExist() {
744 $this->setExpectedException('InvalidArgumentException', '', 1314349666);
745 $this->addToMount(array('somefile' => ''));
746 $fixture = $this->createDriverFixture(array(
747 'basePath' => $this->getMountRootUrl()
748 ));
749 $fixture->getFileList('somedir/');
750 }
751
752 /**
753 * @test
754 */
755 public function getFileListCallsConfiguredCallbackFunctionWithGivenItemName() {
756 $dirStructure = array(
757 'file2' => 'fdsa'
758 );
759 // register static callback to self
760 $callback = array(
761 array(
762 get_class($this),
763 'callbackStaticTestFunction'
764 )
765 );
766 $this->addToMount($dirStructure);
767 $fixture = $this->createDriverFixture(array(
768 'basePath' => $this->getMountRootUrl()
769 ));
770 // the callback function will throw an exception used to check if it was called with correct $itemName
771 $this->setExpectedException('InvalidArgumentException', '$itemName', 1336159604);
772 $fixture->getFileList('/', 0, 0, $callback);
773 }
774
775 /**
776 * Static callback function used to test if the filter callbacks work
777 * As it is static we are using an exception to test if it is really called and works
778 *
779 * @static
780 * @throws \InvalidArgumentException
781 * @see getFileListCallsConfiguredCallbackFunction
782 */
783 static public function callbackStaticTestFunction() {
784 list($itemName) = func_get_args();
785 if ($itemName === 'file2') {
786 throw new \InvalidArgumentException('$itemName', 1336159604);
787 }
788 }
789
790 /**
791 * @test
792 */
793 public function getFileListFiltersItemsWithGivenFilterMethods() {
794 $dirStructure = array(
795 'fileA' => 'asdfg',
796 'fileB' => 'fdsa'
797 );
798 $this->addToMount($dirStructure);
799 $fixture = $this->createDriverFixture(
800 array('basePath' => $this->getMountRootUrl()),
801 NULL,
802 // Mocked because finfo() can not deal with vfs streams and throws warnings
803 array('getMimeTypeOfFile')
804 );
805 $filterCallbacks = array(
806 array(
807 'TYPO3\CMS\Core\Tests\Unit\Resource\Driver\Fixtures\LocalDriverFilenameFilter',
808 'filterFilename',
809 ),
810 );
811 $fileList = $fixture->getFileList('/', 0, 0, $filterCallbacks);
812 $this->assertNotContains('fileA', array_keys($fileList));
813 }
814
815 /**
816 * @test
817 */
818 public function getFolderListReturnsAllDirectoriesInDirectory() {
819 $dirStructure = array(
820 'dir1' => array(),
821 'dir2' => array(),
822 'file' => 'asdfg'
823 );
824 $this->addToMount($dirStructure);
825 $fixture = $this->createDriverFixture(array(
826 'basePath' => $this->getMountRootUrl()
827 ));
828 $fileList = $fixture->getFolderList('/');
829 $this->assertEquals(array('dir1', 'dir2'), array_keys($fileList));
830 }
831
832 /**
833 * @test
834 */
835 public function getFolderListReturnsHiddenFoldersByDefault() {
836 $dirStructure = array(
837 '.someHiddenDir' => array(),
838 'aDir' => array(),
839 'file1' => ''
840 );
841 $this->addToMount($dirStructure);
842 $fixture = $this->createDriverFixture(array(
843 'basePath' => $this->getMountRootUrl()
844 ));
845 $fileList = $fixture->getFolderList('/');
846 $this->assertEquals(array('.someHiddenDir', 'aDir'), array_keys($fileList));
847 }
848
849 /**
850 * @test
851 */
852 public function getFolderListUsesCorrectPathForItems() {
853 $this->addToMount(array(
854 'dir1' => array(
855 'subdir1' => array()
856 )
857 ));
858 $fixture = $this->createDriverFixture(array(
859 'basePath' => $this->getMountRootUrl()
860 ));
861 $FolderList = $fixture->getFolderList('/');
862 $this->assertEquals('/dir1/', $FolderList['dir1']['identifier']);
863 $FolderList = $fixture->getFolderList('/dir1/');
864 $this->assertEquals('/dir1/subdir1/', $FolderList['subdir1']['identifier']);
865 }
866
867 /**
868 * Checks if the folder names . and .. are ignored when listing subdirectories
869 *
870 * @test
871 */
872 public function getFolderListLeavesOutNavigationalEntries() {
873 // we have to add .. and . manually, as these are not included in vfsStream directory listings (as opposed
874 // to normal file listings)
875 $this->addToMount(array(
876 '..' => array(),
877 '.' => array()
878 ));
879 $fixture = $this->createDriverFixture(array(
880 'basePath' => $this->getMountRootUrl()
881 ));
882 $fileList = $fixture->getFolderList('/');
883 $this->assertEmpty($fileList);
884 }
885
886 /**
887 * @test
888 */
889 public function getFolderListFiltersItemsWithGivenFilterMethods() {
890 $dirStructure = array(
891 'folderA' => array(),
892 'folderB' => array()
893 );
894 $this->addToMount($dirStructure);
895 $fixture = $this->createDriverFixture(array(
896 'basePath' => $this->getMountRootUrl()
897 ));
898 $filterCallbacks = array(
899 array(
900 'TYPO3\CMS\Core\Tests\Unit\Resource\Driver\Fixtures\LocalDriverFilenameFilter',
901 'filterFilename',
902 ),
903 );
904 $folderList = $fixture->getFolderList('/', 0, 0, $filterCallbacks);
905 $this->assertNotContains('folderA', array_keys($folderList));
906 }
907
908 /**
909 * @test
910 */
911 public function getFolderListFailsIfDirectoryDoesNotExist() {
912 $this->setExpectedException('InvalidArgumentException', '', 1314349666);
913 $fixture = $this->createDriverFixture(array(
914 'basePath' => $this->getMountRootUrl()
915 ));
916 \vfsStream::create(array($this->basedir => array('somefile' => '')));
917 $fixture->getFolderList('somedir/');
918 }
919
920 /**
921 * @test
922 */
923 public function hashReturnsCorrectHashes() {
924 $contents = '68b329da9893e34099c7d8ad5cb9c940';
925 $expectedMd5Hash = '8c67dbaf0ba22f2e7fbc26413b86051b';
926 $expectedSha1Hash = 'a60cd808ba7a0bcfa37fa7f3fb5998e1b8dbcd9d';
927 $mockedFile = $this->getSimpleFileMock('/hashFile');
928 $this->addToMount(array('hashFile' => $contents));
929 $fixture = $this->createDriverFixture(array(
930 'basePath' => $this->getMountRootUrl()
931 ));
932 $this->assertEquals($expectedSha1Hash, $fixture->hash($mockedFile, 'sha1'));
933 $this->assertEquals($expectedMd5Hash, $fixture->hash($mockedFile, 'md5'));
934 }
935
936 /**
937 * @test
938 */
939 public function hashingWithUnsupportedAlgorithmFails() {
940 $this->setExpectedException('InvalidArgumentException', '', 1304964032);
941 $fixture = $this->createDriverFixture(array(
942 'basePath' => $this->getMountRootUrl()
943 ));
944 $fixture->hash($this->getSimpleFileMock('/hashFile'), uniqid());
945 }
946
947 /**
948 * @test
949 * @covers TYPO3\CMS\Core\Resource\Driver\LocalDriver::getFileForLocalProcessing
950 */
951 public function getFileForLocalProcessingCreatesCopyOfFileByDefault() {
952 $fileContents = 'asdfgh';
953 $this->addToMount(array(
954 'someDir' => array(
955 'someFile' => $fileContents
956 )
957 ));
958 $fixture = $this->createDriverFixture(array(
959 'basePath' => $this->getMountRootUrl()
960 ), NULL, array('copyFileToTemporaryPath'));
961 $mockedFile = $this->getSimpleFileMock('/someDir/someFile');
962 // TODO add parameter expectation for $mockedFile as soon as PHPUnit supports object identity matching in parameter expectations
963 $fixture->expects($this->once())->method('copyFileToTemporaryPath');
964 $fixture->getFileForLocalProcessing($mockedFile);
965 }
966
967 /**
968 * @test
969 */
970 public function getFileForLocalProcessingReturnsOriginalFilepathForReadonlyAccess() {
971 $fileContents = 'asdfgh';
972 $this->addToMount(array(
973 'someDir' => array(
974 'someFile' => $fileContents
975 )
976 ));
977 $fixture = $this->createDriverFixture(array(
978 'basePath' => $this->getMountRootUrl()
979 ));
980 $mockedFile = $this->getSimpleFileMock('/someDir/someFile');
981 $filePath = $fixture->getFileForLocalProcessing($mockedFile, FALSE);
982 $this->assertEquals($filePath, $this->getMountRootUrl() . 'someDir/someFile');
983 }
984
985 /**
986 * @test
987 */
988 public function filesCanBeCopiedToATemporaryPath() {
989 $fileContents = 'asdfgh';
990 $this->addToMount(array(
991 'someDir' => array(
992 'someFile' => $fileContents
993 )
994 ));
995 $fixture = $this->createDriverFixture(array(
996 'basePath' => $this->getMountRootUrl()
997 ));
998 $mockedFile = $this->getSimpleFileMock('/someDir/someFile');
999 $filePath = GeneralUtility::fixWindowsFilePath($fixture->copyFileToTemporaryPath($mockedFile));
1000 $this->assertContains('/typo3temp/', $filePath);
1001 $this->assertEquals($fileContents, file_get_contents($filePath));
1002 }
1003
1004 /**
1005 * @test
1006 */
1007 public function permissionsAreCorrectlyRetrievedForAllowedFile() {
1008 /** @var $fixture \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
1009 list($basedir, $fixture) = $this->prepareRealTestEnvironment();
1010 touch($basedir . '/someFile');
1011 chmod($basedir . '/someFile', 448);
1012 clearstatcache();
1013 $this->assertEquals(array('r' => TRUE, 'w' => TRUE), $fixture->getFilePermissions($this->getSimpleFileMock('/someFile')));
1014 }
1015
1016 /**
1017 * @test
1018 */
1019 public function permissionsAreCorrectlyRetrievedForForbiddenFile() {
1020 if (function_exists('posix_getegid') && posix_getegid() === 0) {
1021 $this->markTestSkipped('Test skipped if run on linux as root');
1022 } elseif (TYPO3_OS === 'WIN') {
1023 $this->markTestSkipped('Test skipped if run on Windows system');
1024 }
1025 /** @var $fixture \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
1026 list($basedir, $fixture) = $this->prepareRealTestEnvironment();
1027 touch($basedir . '/someForbiddenFile');
1028 chmod($basedir . '/someForbiddenFile', 0);
1029 clearstatcache();
1030 $this->assertEquals(array('r' => FALSE, 'w' => FALSE), $fixture->getFilePermissions($this->getSimpleFileMock('/someForbiddenFile')));
1031 }
1032
1033 /**
1034 * @test
1035 */
1036 public function permissionsAreCorrectlyRetrievedForAllowedFolder() {
1037 /** @var $fixture \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
1038 list($basedir, $fixture) = $this->prepareRealTestEnvironment();
1039 mkdir($basedir . '/someFolder');
1040 chmod($basedir . '/someFolder', 448);
1041 clearstatcache();
1042 $this->assertEquals(array('r' => TRUE, 'w' => TRUE), $fixture->getFolderPermissions($this->getSimpleFolderMock('/someFolder')));
1043 }
1044
1045 /**
1046 * @test
1047 */
1048 public function permissionsAreCorrectlyRetrievedForForbiddenFolder() {
1049 if (function_exists('posix_getegid') && posix_getegid() === 0) {
1050 $this->markTestSkipped('Test skipped if run on linux as root');
1051 } elseif (TYPO3_OS === 'WIN') {
1052 $this->markTestSkipped('Test skipped if run on Windows system');
1053 }
1054 /** @var $fixture \TYPO3\CMS\Core\Resource\Driver\LocalDriver */
1055 list($basedir, $fixture) = $this->prepareRealTestEnvironment();
1056 mkdir($basedir . '/someForbiddenFolder');
1057 chmod($basedir . '/someForbiddenFolder', 0);
1058 clearstatcache();
1059 $result = $fixture->getFolderPermissions($this->getSimpleFolderMock('/someForbiddenFolder'));
1060 // Change permissions back to writable, so the sub-folder can be removed in tearDown
1061 chmod($basedir . '/someForbiddenFolder', 0777);
1062 $this->assertEquals(array('r' => FALSE, 'w' => FALSE), $result);
1063 }
1064
1065 /**
1066 * Dataprovider for getFilePermissionsReturnsCorrectPermissionsForFilesNotOwnedByCurrentUser test
1067 *
1068 * @return array group, filemode and expected result
1069 */
1070 public function getFilePermissionsReturnsCorrectPermissionsForFilesNotOwnedByCurrentUser_dataProvider() {
1071 $data = array();
1072 // On some OS, the posix_* functions do not exits
1073 if (function_exists('posix_getgid')) {
1074 $data = array(
1075 'current group, readable/writable' => array(
1076 posix_getgid(),
1077 48,
1078 array('r' => TRUE, 'w' => TRUE)
1079 ),
1080 'current group, readable/not writable' => array(
1081 posix_getgid(),
1082 32,
1083 array('r' => TRUE, 'w' => FALSE)
1084 ),
1085 'current group, not readable/not writable' => array(
1086 posix_getgid(),
1087 0,
1088 array('r' => FALSE, 'w' => FALSE)
1089 )
1090 );
1091 }
1092 $data = array_merge_recursive($data, array(
1093 'arbitrary group, readable/writable' => array(
1094 \vfsStream::GROUP_USER_1,
1095 6,
1096 array('r' => TRUE, 'w' => TRUE)
1097 ),
1098 'arbitrary group, readable/not writable' => array(
1099 \vfsStream::GROUP_USER_1,
1100 436,
1101 array('r' => TRUE, 'w' => FALSE)
1102 ),
1103 'arbitrary group, not readable/not writable' => array(
1104 \vfsStream::GROUP_USER_1,
1105 432,
1106 array('r' => FALSE, 'w' => FALSE)
1107 )
1108 ));
1109 return $data;
1110 }
1111
1112 /**
1113 * @test
1114 * @dataProvider getFilePermissionsReturnsCorrectPermissionsForFilesNotOwnedByCurrentUser_dataProvider
1115 */
1116 public function getFilePermissionsReturnsCorrectPermissionsForFilesNotOwnedByCurrentUser($group, $permissions, $expectedResult) {
1117 if (TYPO3_OS === 'WIN') {
1118 $this->markTestSkipped('Test skipped if run on Windows system');
1119 }
1120 $this->addToMount(array(
1121 'testfile' => 'asdfg'
1122 ));
1123 $fixture = $this->createDriverFixture(array(
1124 'basePath' => $this->getMountRootUrl()
1125 ));
1126 /** @var $fileObject vfsStreamContent */
1127 $fileObject = \vfsStreamWrapper::getRoot()->getChild($this->mountDir)->getChild('testfile');
1128 // just use an "arbitrary" user here - it is only important that
1129 $fileObject->chown(\vfsStream::OWNER_USER_1);
1130 $fileObject->chgrp($group);
1131 $fileObject->chmod($permissions);
1132 $this->assertEquals($expectedResult, $fixture->getFilePermissions($this->getSimpleFileMock('/testfile')));
1133 }
1134
1135 /**
1136 * @test
1137 */
1138 public function isWithinRecognizesFilesWithinFolderAndInOtherFolders() {
1139 $mockedStorage = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
1140 $mockedFolder = new \TYPO3\CMS\Core\Resource\Folder($mockedStorage, '/someFolder/', 'someFolder');
1141 $fixture = $this->createDriverFixture(array(
1142 'basePath' => $this->getMountRootUrl()
1143 ), $mockedStorage);
1144 $this->assertTrue($fixture->isWithin($mockedFolder, '/someFolder/test.jpg'));
1145 $this->assertTrue($fixture->isWithin($mockedFolder, '/someFolder/subFolder/test.jpg'));
1146 $this->assertFalse($fixture->isWithin($mockedFolder, '/someFolderWithALongName/test.jpg'));
1147 }
1148
1149 /**
1150 * @test
1151 */
1152 public function isWithinAcceptsFileAndFolderObjectsAsContent() {
1153 $mockedStorage = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
1154 $mockedFolder = new \TYPO3\CMS\Core\Resource\Folder($mockedStorage, '/someFolder/', 'someFolder');
1155 $fixture = $this->createDriverFixture(array(
1156 'basePath' => $this->getMountRootUrl()
1157 ), $mockedStorage);
1158 $mockedSubfolder = $this->getSimpleFolderMock('/someFolder/subfolder/');
1159 $mockedFile = $this->getSimpleFileMock('/someFolder/test.jpg');
1160 $this->assertTrue($fixture->isWithin($mockedFolder, $mockedFile));
1161 $this->assertTrue($fixture->isWithin($mockedFolder, $mockedSubfolder));
1162 }
1163
1164 /**
1165 * @test
1166 */
1167 public function isWithinAlwaysReturnsFalseIfFolderIsWithinDifferentStorage() {
1168 $mockedStorage1 = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
1169 $mockedStorage2 = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
1170 $mockedFolder = new \TYPO3\CMS\Core\Resource\Folder($mockedStorage1, '/someFolder/', 'someFolder');
1171 $fixture = $this->createDriverFixture(array(
1172 'basePath' => $this->getMountRootUrl()
1173 ), $mockedStorage2);
1174 $fileIdentifier = '/someFolder/test.jpg';
1175 $subfolderIdentifier = '/someFolder/subfolder/';
1176 $mockedFile = $this->getSimpleFileMock($fileIdentifier);
1177 $mockedSubfolder = $this->getSimpleFolderMock($subfolderIdentifier);
1178 $this->assertFalse($fixture->isWithin($mockedFolder, $mockedFile));
1179 $this->assertFalse($fixture->isWithin($mockedFolder, $fileIdentifier));
1180 $this->assertFalse($fixture->isWithin($mockedFolder, $mockedSubfolder));
1181 $this->assertFalse($fixture->isWithin($mockedFolder, $subfolderIdentifier));
1182 }
1183
1184 /**********************************
1185 * Copy/move file
1186 **********************************/
1187 /**
1188 * @param $identifier
1189 * @param null|\TYPO3\CMS\Core\Resource\ResourceStorage $storage
1190 * @return \TYPO3\CMS\Core\Resource\File
1191 */
1192 protected function mockFileForCopyingAndMoving($identifier, \TYPO3\CMS\Core\Resource\ResourceStorage $storage = NULL) {
1193 if (!$storage) {
1194 $storage = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
1195 }
1196 $fileObject = new \TYPO3\CMS\Core\Resource\File(array('identifier' => $identifier, 'name' => basename($identifier), 'storage' => $storage));
1197 return $fileObject;
1198 }
1199
1200 /**
1201 * @param $identifier
1202 * @param null|\TYPO3\CMS\Core\Resource\ResourceStorage $storage
1203 * @return \TYPO3\CMS\Core\Resource\Folder
1204 */
1205 protected function mockFolderForCopyingAndMoving($identifier, \TYPO3\CMS\Core\Resource\ResourceStorage $storage = NULL) {
1206 if (!$storage) {
1207 $storage = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
1208 }
1209 $folderObject = new \TYPO3\CMS\Core\Resource\Folder($storage, $identifier, basename($identifier), 0);
1210 return $folderObject;
1211 }
1212
1213 /**
1214 * Prepares a simple two-folder environment with /someFolder/ and /targetFolder/. /someFolder contains a file with random
1215 * contents
1216 *
1217 * @return array $mockedFolder, $sourceFolder, $fileContents, $fixture
1218 */
1219 protected function _prepareFolderEnvironmentForMoveTest() {
1220 $mockedFolder = $this->getSimpleFolderMock('/targetFolder/');
1221 $sourceFolder = $this->getSimpleFolderMock('/someFolder/');
1222 $fileContents = uniqid();
1223 $this->addToMount(array(
1224 'targetFolder' => array(),
1225 'someFolder' => array('file' => $fileContents)
1226 ));
1227 $fixture = $this->createDriverFixture(array(
1228 'basePath' => $this->getMountRootUrl()
1229 ));
1230 return array($mockedFolder, $sourceFolder, $fileContents, $fixture);
1231 }
1232
1233 /**
1234 * @test
1235 */
1236 public function filesCanBeCopiedWithinStorage() {
1237 $fileContents = uniqid();
1238 $this->addToMount(array(
1239 'someFile' => $fileContents,
1240 'targetFolder' => array()
1241 ));
1242 $fixture = $this->createDriverFixture(
1243 array('basePath' => $this->getMountRootUrl()),
1244 NULL,
1245 // Mocked because finfo() can not deal with vfs streams and throws warnings
1246 array('getMimeTypeOfFile')
1247 );
1248 $storage = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
1249 $sourceFile = $this->mockFileForCopyingAndMoving('/someFile', $storage);
1250 $targetFolder = $this->mockFolderForCopyingAndMoving('/targetFolder/', $storage);
1251 $fixture->copyFileWithinStorage($sourceFile, $targetFolder, 'someFile');
1252 $this->assertFileEquals($this->getUrlInMount('/someFile'), $this->getUrlInMount('/targetFolder/someFile'));
1253 }
1254
1255 /**
1256 * @test
1257 */
1258 public function filesCanBeMovedWithinStorage() {
1259 $mockedFolder = $this->getSimpleFolderMock('/targetFolder/');
1260 $storage = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
1261 $sourceFile = $this->mockFileForCopyingAndMoving('/someFile', $storage);
1262 $fileContents = uniqid();
1263 $this->addToMount(array(
1264 'targetFolder' => array(),
1265 'someFile' => $fileContents
1266 ));
1267 $fixture = $this->createDriverFixture(array(
1268 'basePath' => $this->getMountRootUrl()
1269 ));
1270 $newIdentifier = $fixture->moveFileWithinStorage($sourceFile, $mockedFolder, 'file');
1271 $this->assertEquals($fileContents, file_get_contents($this->getUrlInMount('/targetFolder/file')));
1272 $this->assertFileNotExists($this->getUrlInMount('/someFile'));
1273 $this->assertEquals('/targetFolder/file', $newIdentifier);
1274 }
1275
1276 /**
1277 * @test
1278 */
1279 public function fileMetadataIsChangedAfterMovingFile() {
1280 $mockedFolder = $this->getSimpleFolderMock('/targetFolder/');
1281 $storage = $this->getMock('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', array(), array(), '', FALSE);
1282 $sourceFile = $this->mockFileForCopyingAndMoving('/someFile', $storage);
1283 $fileContents = uniqid();
1284 $this->addToMount(array(
1285 'targetFolder' => array(),
1286 'someFile' => $fileContents
1287 ));
1288 $fixture = $this->createDriverFixture(
1289 array('basePath' => $this->getMountRootUrl()),
1290 NULL,
1291 // Mocked because finfo() can not deal with vfs streams and throws warnings
1292 array('getMimeTypeOfFile')
1293 );
1294 $newIdentifier = $fixture->moveFileWithinStorage($sourceFile, $mockedFolder, 'file');
1295 $fileMetadata = $fixture->getFileInfoByIdentifier($newIdentifier);
1296 $this->assertEquals($newIdentifier, $fileMetadata['identifier']);
1297 }
1298
1299 public function renamingFiles_dataProvider() {
1300 return array(
1301 'file in subfolder' => array(
1302 array(
1303 'targetFolder' => array('file' => '')
1304 ),
1305 '/targetFolder/file',
1306 'newFile',
1307 '/targetFolder/newFile'
1308 ),
1309 'file in rootfolder' => array(
1310 array(
1311 'fileInRoot' => ''
1312 ),
1313 '/fileInRoot',
1314 'newFile',
1315 '/newFile'
1316 )
1317 );
1318 }
1319
1320 /**
1321 * @test
1322 * @dataProvider renamingFiles_dataProvider
1323 */
1324 public function renamingFilesChangesFilenameOnDisk(array $filesystemStructure, $oldFileIdentifier, $newFileName, $expectedNewIdentifier) {
1325 $this->addToMount($filesystemStructure);
1326 $fixture = $this->createDriverFixture(array(
1327 'basePath' => $this->getMountRootUrl()
1328 ));
1329 $file = $this->getSimpleFileMock($oldFileIdentifier);
1330 $newIdentifier = $fixture->renameFile($file, $newFileName);
1331 $this->assertFalse($fixture->fileExists($oldFileIdentifier));
1332 $this->assertTrue($fixture->fileExists($newIdentifier));
1333 $this->assertEquals($expectedNewIdentifier, $newIdentifier);
1334 }
1335
1336 /**
1337 * @test
1338 */
1339 public function renamingFilesFailsIfTargetFileExists() {
1340 $this->setExpectedException('TYPO3\\CMS\\Core\\Resource\\Exception\\ExistingTargetFileNameException', '', 1320291063);
1341 $this->addToMount(array(
1342 'targetFolder' => array('file' => '', 'newFile' => '')
1343 ));
1344 $fixture = $this->createDriverFixture(array(
1345 'basePath' => $this->getMountRootUrl()
1346 ));
1347 $file = $this->getSimpleFileMock('/targetFolder/file');
1348 $fixture->renameFile($file, 'newFile');
1349 }
1350
1351 /**
1352 * We use this data provider for testing move methods because there are some issues with the
1353 *
1354 * @return array
1355 */
1356 public function renamingFolders_dataProvider() {
1357 return array(
1358 'folder in root folder' => array(
1359 array(
1360 'someFolder' => array()
1361 ),
1362 '/someFolder/',
1363 'newFolder',
1364 '/newFolder/'
1365 ),
1366 'file in subfolder' => array(
1367 array(
1368 'subfolder' => array(
1369 'someFolder' => array()
1370 )
1371 ),
1372 '/subfolder/someFolder/',
1373 'newFolder',
1374 '/subfolder/newFolder/'
1375 )
1376 );
1377 }
1378
1379 /**
1380 * @test
1381 * @dataProvider renamingFolders_dataProvider
1382 */
1383 public function renamingFoldersChangesFolderNameOnDisk(array $filesystemStructure, $oldFolderIdentifier, $newFolderName, $expectedNewIdentifier) {
1384 $this->addToMount($filesystemStructure);
1385 $fixture = $this->createDriverFixture(array(
1386 'basePath' => $this->getMountRootUrl()
1387 ));
1388 $mockedFolder = $this->getSimpleFolderMock($oldFolderIdentifier);
1389 $mapping = $fixture->renameFolder($mockedFolder, $newFolderName);
1390 $this->assertFalse($fixture->folderExists($oldFolderIdentifier));
1391 $this->assertTrue($fixture->folderExists($expectedNewIdentifier));
1392 $this->assertEquals($expectedNewIdentifier, $mapping[$oldFolderIdentifier]);
1393 }
1394
1395 /**
1396 * @test
1397 */
1398 public function renameFolderReturnsCorrectMappingInformationForAllFiles() {
1399 $fileContents = 'asdfg';
1400 $this->addToMount(array(
1401 'sourceFolder' => array(
1402 'subFolder' => array('file' => $fileContents),
1403 'file' => 'asdfg'
1404 )
1405 ));
1406 $fixture = $this->createDriverFixture(array(
1407 'basePath' => $this->getMountRootUrl()
1408 ));
1409 $sourceFolder = $this->getSimpleFolderMock('/sourceFolder/');
1410 $mappingInformation = $fixture->renameFolder($sourceFolder, 'newFolder');
1411 $this->assertEquals('/newFolder/', $mappingInformation['/sourceFolder/']);
1412 $this->assertEquals('/newFolder/file', $mappingInformation['/sourceFolder/file']);
1413 $this->assertEquals('/newFolder/subFolder/file', $mappingInformation['/sourceFolder/subFolder/file']);
1414 $this->assertEquals('/newFolder/subFolder/', $mappingInformation['/sourceFolder/subFolder/']);
1415 }
1416
1417 /**
1418 * @test
1419 */
1420 public function renameFolderRevertsRenamingIfFilenameMapCannotBeCreated() {
1421 $this->setExpectedException('\RuntimeException', '', 1334160746);
1422 $this->addToMount(array(
1423 'sourceFolder' => array(
1424 'file' => 'asdfg'
1425 )
1426 ));
1427 $fixture = $this->createDriverFixture(array(
1428 'basePath' => $this->getMountRootUrl()
1429 ), NULL, array('createIdentifierMap'));
1430 $fixture->expects($this->atLeastOnce())->method('createIdentifierMap')->will($this->throwException(new \TYPO3\CMS\Core\Resource\Exception\FileOperationErrorException()));
1431 $sourceFolder = $this->getSimpleFolderMock('/sourceFolder/');
1432 $fixture->renameFolder($sourceFolder, 'newFolder');
1433 $this->assertFileExists($this->getUrlInMount('/sourceFolder/file'));
1434 }
1435
1436 /**
1437 * @test
1438 */
1439 public function isFolderEmptyReturnsTrueForEmptyFolder() {
1440 // This also prepares the next few tests, so add more info than required for this test
1441 $this->addToMount(array(
1442 'emptyFolder' => array()
1443 ));
1444 $fixture = $this->createDriverFixture(array(
1445 'basePath' => $this->getMountRootUrl()
1446 ));
1447 $mockedFolder = $this->getSimpleFolderMock('/emptyFolder/');
1448 $this->assertTrue($fixture->isFolderEmpty($mockedFolder));
1449 return $fixture;
1450 }
1451
1452 /**
1453 * @test
1454 */
1455 public function isFolderEmptyReturnsFalseIfFolderHasFile() {
1456 $this->addToMount(array(
1457 'folderWithFile' => array(
1458 'someFile' => ''
1459 )
1460 ));
1461 $fixture = $this->createDriverFixture(array(
1462 'basePath' => $this->getMountRootUrl()
1463 ));
1464 $mockedFolder = $this->getSimpleFolderMock('/folderWithFile/');
1465 $this->assertFalse($fixture->isFolderEmpty($mockedFolder));
1466 }
1467
1468 /**
1469 * @test
1470 */
1471 public function isFolderEmptyReturnsFalseIfFolderHasSubfolder() {
1472 $this->addToMount(array(
1473 'folderWithSubfolder' => array(
1474 'someFolder' => array()
1475 )
1476 ));
1477 $fixture = $this->createDriverFixture(array(
1478 'basePath' => $this->getMountRootUrl()
1479 ));
1480 $mockedFolder = $this->getSimpleFolderMock('/folderWithSubfolder/');
1481 $this->assertFalse($fixture->isFolderEmpty($mockedFolder));
1482 }
1483
1484 /**********************************
1485 * Copy/move folder
1486 **********************************/
1487 /**
1488 * @test
1489 */
1490 public function foldersCanBeMovedWithinStorage() {
1491 /** @var \TYPO3\CMS\Core\Resource\Driver\LocalDriver $fixture */
1492 list($mockedFolder, $sourceFolder, $fileContents, $fixture) = $this->_prepareFolderEnvironmentForMoveTest();
1493 $fixture->moveFolderWithinStorage($sourceFolder, $mockedFolder, 'someFolder');
1494 $this->assertTrue(file_exists($this->getUrlInMount('/targetFolder/someFolder/')));
1495 $this->assertEquals($fileContents, file_get_contents($this->getUrlInMount('/targetFolder/someFolder/file')));
1496 $this->assertFileNotExists($this->getUrlInMount('/someFile'));
1497 }
1498
1499 /**
1500 * @test
1501 */
1502 public function moveFolderWithinStorageReturnsCorrectMappingInformationForAllFiles() {
1503 $fileContents = 'asdfg';
1504 $this->addToMount(array(
1505 'targetFolder' => array(),
1506 'sourceFolder' => array(
1507 'subFolder' => array('file' => $fileContents),
1508 'file' => 'asdfg'
1509 )
1510 ));
1511 $fixture = $this->createDriverFixture(array(
1512 'basePath' => $this->getMountRootUrl()
1513 ));
1514 $sourceFolder = $this->getSimpleFolderMock('/sourceFolder/');
1515 $targetFolder = $this->getSimpleFolderMock('/targetFolder/');
1516 $mappingInformation = $fixture->moveFolderWithinStorage($sourceFolder, $targetFolder, 'sourceFolder');
1517 $this->assertEquals('/targetFolder/sourceFolder/file', $mappingInformation['/sourceFolder/file']);
1518 $this->assertEquals('/targetFolder/sourceFolder/subFolder/file', $mappingInformation['/sourceFolder/subFolder/file']);
1519 $this->assertEquals('/targetFolder/sourceFolder/subFolder/', $mappingInformation['/sourceFolder/subFolder/']);
1520 }
1521
1522 /**
1523 * @test
1524 */
1525 public function folderCanBeRenamedWhenMoving() {
1526 /** @var \TYPO3\CMS\Core\Resource\Driver\LocalDriver $fixture */
1527 list($mockedFolder, $sourceFolder, $fileContents, $fixture) = $this->_prepareFolderEnvironmentForMoveTest();
1528 $fixture->moveFolderWithinStorage($sourceFolder, $mockedFolder, 'newFolder');
1529 $this->assertTrue(file_exists($this->getUrlInMount('/targetFolder/newFolder/')));
1530 }
1531
1532 protected function _setupFolderForCopyTest() {
1533 $fileContents1 = uniqid();
1534 $fileContents2 = uniqid();
1535 $this->addToMount(array(
1536 'targetFolder' => array(),
1537 'sourceFolder' => array(
1538 'subFolder' => array('file' => $fileContents1),
1539 'file' => $fileContents2
1540 )
1541 ));
1542 $fixture = $this->createDriverFixture(array(
1543 'basePath' => $this->getMountRootUrl()
1544 ));
1545 return $fixture;
1546 }
1547
1548 /**
1549 * @test
1550 * @see _setupFolderForCopyTest
1551 */
1552 public function foldersCanBeCopiedWithinSameStorage() {
1553 $fixture = $this->_setupFolderForCopyTest();
1554 $sourceFolder = $this->getSimpleFolderMock('/sourceFolder/');
1555 $targetFolder = $this->getSimpleFolderMock('/targetFolder/');
1556 $fixture->copyFolderWithinStorage($sourceFolder, $targetFolder, 'sourceFolder');
1557 $this->assertTrue($fixture->folderExists('/targetFolder/sourceFolder/'));
1558 $this->assertTrue($fixture->fileExists('/targetFolder/sourceFolder/file'));
1559 $this->assertTrue($fixture->folderExists('/targetFolder/sourceFolder/subFolder/'));
1560 $this->assertTrue($fixture->fileExists('/targetFolder/sourceFolder/subFolder/file'));
1561 }
1562
1563 /**
1564 * @test
1565 * @see _setupFolderForCopyTest
1566 */
1567 public function folderNameCanBeChangedWhileCopying() {
1568 $fixture = $this->_setupFolderForCopyTest();
1569 $sourceFolder = $this->getSimpleFolderMock('/sourceFolder/');
1570 $targetFolder = $this->getSimpleFolderMock('/targetFolder/');
1571 $fixture->copyFolderWithinStorage($sourceFolder, $targetFolder, 'newFolder');
1572 $this->assertTrue($fixture->folderExists('/targetFolder/newFolder/'));
1573 $this->assertTrue($fixture->fileExists('/targetFolder/newFolder/file'));
1574 $this->assertFalse($fixture->folderExists('/targetFolder/sourceFolder/'));
1575 }
1576
1577 }
1578 ?>