2 declare(strict_types
= 1);
3 namespace TYPO3\CMS\Core\Tests\Unit\
Resource\Driver
;
6 * This file is part of the TYPO3 CMS project.
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
15 * The TYPO3 project - inspiring people to share!
18 use org\bovigo\vfs\vfsStream
;
19 use org\bovigo\vfs\vfsStreamContent
;
20 use org\bovigo\vfs\vfsStreamWrapper
;
21 use TYPO3\CMS\Core\Core\Environment
;
22 use TYPO3\CMS\Core\
Resource\Driver\LocalDriver
;
23 use TYPO3\CMS\Core\
Resource\Exception\ExistingTargetFileNameException
;
24 use TYPO3\CMS\Core\
Resource\Exception\FileOperationErrorException
;
25 use TYPO3\CMS\Core\
Resource\Exception\InvalidFileNameException
;
26 use TYPO3\CMS\Core\
Resource\ResourceStorage
;
27 use TYPO3\CMS\Core\Tests\Unit\
Resource\BaseTestCase
;
28 use TYPO3\CMS\Core\Tests\Unit\
Resource\Driver\Fixtures\LocalDriverFilenameFilter
;
29 use TYPO3\CMS\Core\Utility\GeneralUtility
;
30 use TYPO3\TestingFramework\Core\FileStreamWrapper
;
35 class LocalDriverTest
extends BaseTestCase
38 * @var bool Reset singletons created by subject
40 protected $resetSingletonInstances = true;
45 protected $localDriver;
50 protected $testDirs = [];
55 protected $iso88591GreaterThan127 = '';
60 protected $utf8Latin1Supplement = '';
65 protected $utf8Latin1ExtendedA = '';
70 protected function tearDown(): void
72 foreach ($this->testDirs
as $dir) {
74 GeneralUtility
::rmdir($dir, true);
80 * Creates a "real" directory for doing tests. This is necessary because some file system properties (e.g. permissions)
81 * cannot be reflected by vfsStream, and some methods (like touch()) don't work there either.
83 * Created directories are automatically destroyed during tearDown()
87 protected function createRealTestdir(): string
89 $basedir = Environment
::getVarPath() . '/tests/' . $this->getUniqueId('fal-test-');
91 $this->testDirs
[] = $basedir;
96 * Create a "real" directory together with a driver configured
99 * @return array With path to base directory and driver
101 protected function prepareRealTestEnvironment(): array
103 $basedir = $this->createRealTestdir();
104 $subject = $this->createDriver([
105 'basePath' => $basedir
107 return [$basedir, $subject];
111 * Creates a mocked driver object as test subject, optionally using a given mount object.
113 * IMPORTANT: Call this only after setting up the virtual file system (with the addTo* methods)!
115 * @param array $driverConfiguration
116 * @param array $mockedDriverMethods
117 * @return LocalDriver
119 protected function createDriver(array $driverConfiguration = [], array $mockedDriverMethods = []): LocalDriver
121 // it's important to do that here, so vfsContents could have been set before
122 if (!isset($driverConfiguration['basePath'])) {
123 $this->initializeVfs();
124 $driverConfiguration['basePath'] = $this->getMountRootUrl();
126 /** @var LocalDriver $driver */
127 $mockedDriverMethods[] = 'isPathValid';
128 $driver = $this->getAccessibleMock(LocalDriver
::class, $mockedDriverMethods, [$driverConfiguration]);
129 $driver->expects($this->any())
130 ->method('isPathValid')
132 $this->returnValue(true)
135 $driver->setStorageUid(5);
136 $driver->processConfiguration();
137 $driver->initialize();
144 public function calculatedBasePathRelativeIsSane(): void
146 $subject = $this->createDriver();
148 // This would cause problems if you fill "/fileadmin/" into the base path field of a sys_file_storage record and select "relative" as path type
149 $relativeDriverConfiguration = [
150 'pathType' => 'relative',
151 'basePath' => '/typo3temp/var/tests/',
153 $basePath = $subject->_call('calculateBasePath', $relativeDriverConfiguration);
155 $this->assertNotContains('//', $basePath);
161 public function calculatedBasePathAbsoluteIsSane(): void
163 $subject = $this->createDriver();
165 // This test checks if "/../" are properly filtered out (i.e. from "Base path" field of sys_file_storage)
166 $relativeDriverConfiguration = [
167 'basePath' => Environment
::getVarPath() . '/tests/../../../typo3temp/var/tests/',
169 $basePath = $subject->_call('calculateBasePath', $relativeDriverConfiguration);
171 $this->assertNotContains('/../', $basePath);
177 public function createFolderRecursiveSanitizesFilename(): void
179 /** @var LocalDriver|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface $driver */
180 $driver = $this->createDriver([], ['sanitizeFilename']);
181 $driver->expects($this->exactly(2))
182 ->method('sanitizeFileName')
184 $this->returnValue('sanitized')
186 $driver->createFolder('newFolder/andSubfolder', '/', true);
187 $this->assertFileExists($this->getUrlInMount('/sanitized/sanitized/'));
193 public function determineBaseUrlUrlEncodesUriParts(): void
195 /** @var LocalDriver|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface $driver */
196 $driver = $this->getAccessibleMock(LocalDriver
::class, ['hasCapability'], [], '', false);
197 $driver->expects($this->once())
198 ->method('hasCapability')
199 ->with(ResourceStorage
::CAPABILITY_PUBLIC
)
201 $this->returnValue(true)
203 $driver->_set('absoluteBasePath', Environment
::getPublicPath() . '/un encö/ded %path/');
204 $driver->_call('determineBaseUrl');
205 $baseUri = $driver->_get('baseUri');
206 $this->assertEquals(rawurlencode('un encö') . '/' . rawurlencode('ded %path') . '/', $baseUri);
212 public function getDefaultFolderReturnsFolderForUserUploadPath(): void
214 $subject = $this->createDriver();
215 $folderIdentifier = $subject->getDefaultFolder();
216 $this->assertEquals('/user_upload/', $folderIdentifier);
222 public function defaultLevelFolderFolderIsCreatedIfItDoesntExist(): void
224 $subject = $this->createDriver();
225 $this->assertFileExists($this->getUrlInMount($subject->getDefaultFolder()));
231 public function getFolderInFolderReturnsCorrectFolderObject(): void
238 $subject = $this->createDriver();
239 $folder = $subject->getFolderInFolder('someSubdir', '/someDir/');
240 $this->assertEquals('/someDir/someSubdir/', $folder);
246 public function createFolderCreatesFolderOnDisk(): void
248 $this->addToMount(['some' => ['folder' => []]]);
249 $subject = $this->createDriver();
250 $subject->createFolder('path', '/some/folder/');
251 $this->assertFileExists($this->getUrlInMount('/some/folder/'));
252 $this->assertFileExists($this->getUrlInMount('/some/folder/path'));
258 public function createFolderReturnsFolderObject(): void
260 $this->addToMount(['some' => ['folder' => []]]);
261 $subject = $this->createDriver();
262 $createdFolder = $subject->createFolder('path', '/some/folder/');
263 $this->assertEquals('/some/folder/path/', $createdFolder);
269 public static function createFolderSanitizesFolderNameBeforeCreationDataProvider(): array
272 'folder name with NULL character' => [
273 'some' . chr(0) . 'Folder',
276 'folder name with directory part' => [
285 * @dataProvider createFolderSanitizesFolderNameBeforeCreationDataProvider
286 * @param string $newFolderName
287 * @param string $expectedFolderName
289 public function createFolderSanitizesFolderNameBeforeCreation(string $newFolderName, string $expectedFolderName): void
291 $this->addToMount(['some' => ['folder' => []]]);
292 $subject = $this->createDriver();
293 $subject->createFolder($newFolderName, '/some/folder/');
294 $this->assertFileExists($this->getUrlInMount('/some/folder/' . $expectedFolderName));
300 public function basePathIsNormalizedWithTrailingSlash(): void
302 $subject = $this->createDriver();
303 $this->assertEquals('/', substr($subject->_call('getAbsoluteBasePath'), -1));
309 public function noSecondSlashIsAddedIfBasePathAlreadyHasTrailingSlash(): void
311 $subject = $this->createDriver();
312 $this->assertNotEquals('/', substr($subject->_call('getAbsoluteBasePath'), -2, 1));
318 public function getSpecificFileInformationDataProvider(): array
322 'expectedValue' => filesize(__DIR__
. '/Fixtures/Dummy.html'),
323 'propertyName' => 'size'
326 'expectedValue' => 'WILL_BE_REPLACED_BY_VFS_TIME',
327 'propertyName' => 'atime'
330 'expectedValue' => 'WILL_BE_REPLACED_BY_VFS_TIME',
331 'propertyName' => 'mtime'
334 'expectedValue' => 'WILL_BE_REPLACED_BY_VFS_TIME',
335 'propertyName' => 'ctime'
338 'expectedValue' => 'Dummy.html',
339 'propertyName' => 'name'
342 'expectedValue' => 'text/html',
343 'propertyName' => 'mimetype'
346 'expectedValue' => '/Dummy.html',
347 'propertyName' => 'identifier'
350 'expectedValue' => 5,
351 'propertyName' => 'storage'
353 'identifier_hash' => [
354 'expectedValue' => 'b11efa5d7c0556a65c6aa261343b9807cac993bc',
355 'propertyName' => 'identifier_hash'
358 'expectedValue' => '42099b4af021e53fd8fd4e056c2568d7c2e3ffa8',
359 'propertyName' => 'folder_hash'
366 * @dataProvider getSpecificFileInformationDataProvider
367 * @param $expectedValue
368 * @param string $property
370 public function getSpecificFileInformationReturnsRequestedFileInformation($expectedValue, string $property): void
372 $root = vfsStream
::setup();
373 $subFolder = vfsStream
::newDirectory('fileadmin');
374 $root->addChild($subFolder);
375 // Load fixture files and folders from disk
376 $directory = vfsStream
::copyFromFileSystem(__DIR__
. '/Fixtures/', $subFolder, 1024*1024);
377 if (in_array($property, ['mtime', 'ctime', 'atime'])) {
378 $expectedValue = $directory->getChild('Dummy.html')->filemtime();
380 FileStreamWrapper
::init(Environment
::getPublicPath() . '/');
381 FileStreamWrapper
::registerOverlayPath('fileadmin', 'vfs://root/fileadmin', false);
383 $subject = $this->createDriver(['basePath' => Environment
::getPublicPath() . '/fileadmin']);
386 $subject->getSpecificFileInformation(Environment
::getPublicPath() . '/fileadmin/Dummy.html', '/', $property)
389 FileStreamWrapper
::destroy();
395 public function getAbsolutePathReturnsCorrectPath(): void
399 'file1.ext' => 'asdfg'
402 $subject = $this->createDriver();
403 $path = $subject->_call('getAbsolutePath', '/someFolder/file1.ext');
404 $this->assertTrue(file_exists($path));
405 $this->assertEquals($this->getUrlInMount('/someFolder/file1.ext'), $path);
411 public function addFileMovesFileToCorrectLocation(): void
413 $this->addToMount(['targetFolder' => []]);
419 $subject = $this->createDriver(
421 ['getMimeTypeOfFile']
423 $this->assertTrue(file_exists($this->getUrl('sourceFolder/file')));
424 $subject->addFile($this->getUrl('sourceFolder/file'), '/targetFolder/', 'file');
425 $this->assertTrue(file_exists($this->getUrlInMount('/targetFolder/file')));
431 public function addFileUsesFilenameIfGiven(): void
433 $this->addToMount(['targetFolder' => []]);
439 $subject = $this->createDriver(
441 ['getMimeTypeOfFile']
443 $this->assertTrue(file_exists($this->getUrl('sourceFolder/file')));
444 $subject->addFile($this->getUrl('sourceFolder/file'), '/targetFolder/', 'targetFile');
445 $this->assertTrue(file_exists($this->getUrlInMount('/targetFolder/targetFile')));
451 public function addFileFailsIfFileIsInDriverStorage(): void
453 $this->expectException(\InvalidArgumentException
::class);
454 $this->expectExceptionCode(1314778269);
460 $subject = $this->createDriver();
461 $subject->addFile($this->getUrlInMount('/targetFolder/file'), '/targetFolder/', 'file');
467 public function addFileReturnsFileIdentifier(): void
469 $this->addToMount(['targetFolder' => []]);
475 $subject = $this->createDriver(
477 ['getMimeTypeOfFile']
479 $this->assertTrue(file_exists($this->getUrl('sourceFolder/file')));
480 $fileIdentifier = $subject->addFile($this->getUrl('sourceFolder/file'), '/targetFolder/', 'file');
481 $this->assertEquals('file', basename($fileIdentifier));
482 $this->assertEquals('/targetFolder/file', $fileIdentifier);
488 public function existenceChecksWorkForFilesAndFolders(): void
494 $subject = $this->createDriver();
495 // Using slashes at the beginning of paths because they will be stored in the DB this way.
496 $this->assertTrue($subject->fileExists('/file'));
497 $this->assertTrue($subject->folderExists('/folder/'));
498 $this->assertFalse($subject->fileExists('/nonexistingFile'));
499 $this->assertFalse($subject->folderExists('/nonexistingFolder/'));
505 public function existenceChecksInFolderWorkForFilesAndFolders(): void
513 $subject = $this->createDriver();
514 $this->assertTrue($subject->fileExistsInFolder('file', '/subfolder/'));
515 $this->assertTrue($subject->folderExistsInFolder('folder', '/subfolder/'));
516 $this->assertFalse($subject->fileExistsInFolder('nonexistingFile', '/subfolder/'));
517 $this->assertFalse($subject->folderExistsInFolder('nonexistingFolder', '/subfolder/'));
523 public function getPublicUrlReturnsCorrectUriForConfiguredBaseUri(): void
525 $baseUri = 'http://example.org/foobar/' . $this->getUniqueId();
527 'file.ext' => 'asdf',
529 'file2.ext' => 'asdf'
532 $subject = $this->createDriver([
533 'baseUri' => $baseUri
535 $this->assertEquals($baseUri . '/file.ext', $subject->getPublicUrl('/file.ext'));
536 $this->assertEquals($baseUri . '/subfolder/file2.ext', $subject->getPublicUrl('/subfolder/file2.ext'));
540 * Data provider for getPublicUrlReturnsValidUrlContainingSpecialCharacters().
544 public function getPublicUrlReturnsValidUrlContainingSpecialCharacters_dataProvider(): array
547 ['/single file with some special chars äüö!.txt'],
548 ['/on subfolder/with special chars äüö!.ext'],
549 ['/who names a file like !"§$%&()=?*+~"#\'´`<>-.ext'],
550 ['no leading slash !"§$%&()=?*+~#\'"´`"<>-.txt']
556 * @dataProvider getPublicUrlReturnsValidUrlContainingSpecialCharacters_dataProvider
557 * @param string $fileIdentifier
559 public function getPublicUrlReturnsValidUrlContainingSpecialCharacters(string $fileIdentifier): void
561 $baseUri = 'http://example.org/foobar/' . $this->getUniqueId();
562 $subject = $this->createDriver([
563 'baseUri' => $baseUri
565 $publicUrl = $subject->getPublicUrl($fileIdentifier);
566 $this->assertTrue(GeneralUtility
::isValidUrl($publicUrl), 'getPublicUrl did not return a valid URL:' . $publicUrl);
572 public function fileContentsCanBeWrittenAndRead(): void
574 $fileContents = 'asdf';
576 'file.ext' => $fileContents
578 $subject = $this->createDriver();
579 $this->assertEquals($fileContents, $subject->getFileContents('/file.ext'), 'File contents could not be read');
580 $newFileContents = 'asdfgh';
581 $subject->setFileContents('/file.ext', $newFileContents);
582 $this->assertEquals($newFileContents, $subject->getFileContents('/file.ext'), 'New file contents could not be read.');
588 public function setFileContentsReturnsNumberOfBytesWrittenToFile(): void
590 $fileContents = 'asdf';
592 'file.ext' => $fileContents
594 $subject = $this->createDriver();
595 $newFileContents = 'asdfgh';
596 $bytesWritten = $subject->setFileContents('/file.ext', $newFileContents);
597 $this->assertEquals(strlen($newFileContents), $bytesWritten);
602 * @see http://phpmagazin.de/vfsStream-1.1.0-nutzt-PHP-5.4-M%C3%B6glichkeiten-064406.html
604 public function newFilesCanBeCreated(): void
606 $subject = $this->createDriver();
607 $subject->createFile('testfile.txt', '/');
608 $this->assertTrue($subject->fileExists('/testfile.txt'));
613 * @see http://phpmagazin.de/vfsStream-1.1.0-nutzt-PHP-5.4-M%C3%B6glichkeiten-064406.html
615 public function createdFilesAreEmpty(): void
617 $subject = $this->createDriver();
618 $subject->createFile('testfile.txt', '/');
619 $this->assertTrue($subject->fileExists('/testfile.txt'));
620 $fileData = $subject->getFileContents('/testfile.txt');
621 $this->assertEquals(0, strlen($fileData));
627 public function createFileFixesPermissionsOnCreatedFile(): void
629 if (Environment
::isWindows()) {
630 $this->markTestSkipped('createdFilesHaveCorrectRights() tests not available on Windows');
633 // No one will use this as his default file create mask so we hopefully don't get any false positives
634 $testpattern = '0646';
635 $GLOBALS['TYPO3_CONF_VARS']['SYS']['fileCreateMask'] = $testpattern;
642 /** @var $subject LocalDriver */
643 list($basedir, $subject) = $this->prepareRealTestEnvironment();
644 mkdir($basedir . '/someDir');
645 $subject->createFile('testfile.txt', '/someDir');
646 $this->assertEquals((int)$testpattern, (int)(decoct(fileperms($basedir . '/someDir/testfile.txt') & 0777)));
649 /**********************************
650 * File and directory listing
651 **********************************/
655 public function getFileReturnsCorrectIdentifier(): void
657 $root = vfsStream
::setup();
658 $subFolder = vfsStream
::newDirectory('fileadmin');
659 $root->addChild($subFolder);
660 // Load fixture files and folders from disk
661 vfsStream
::copyFromFileSystem(__DIR__
. '/Fixtures/', $subFolder, 1024*1024);
662 FileStreamWrapper
::init(Environment
::getPublicPath() . '/');
663 FileStreamWrapper
::registerOverlayPath('fileadmin/', 'vfs://root/fileadmin/', false);
665 $subject = $this->createDriver(['basePath' => Environment
::getPublicPath() . '/fileadmin']);
667 $subdirFileInfo = $subject->getFileInfoByIdentifier('Dummy.html');
668 $this->assertEquals('/Dummy.html', $subdirFileInfo['identifier']);
669 $rootFileInfo = $subject->getFileInfoByIdentifier('LocalDriverFilenameFilter.php');
670 $this->assertEquals('/LocalDriverFilenameFilter.php', $rootFileInfo['identifier']);
672 FileStreamWrapper
::destroy();
678 public function getFileThrowsExceptionIfFileDoesNotExist(): void
680 $this->expectException(\InvalidArgumentException
::class);
681 $this->expectExceptionCode(1314516809);
682 $subject = $this->createDriver();
683 $subject->getFileInfoByIdentifier('/some/file/at/a/random/path');
689 public function getFilesInFolderReturnsEmptyArrayForEmptyDirectory(): void
691 $subject = $this->createDriver();
692 $fileList = $subject->getFilesInFolder('/');
693 $this->assertEmpty($fileList);
699 public function getFileListReturnsAllFilesInDirectory(): void
706 $this->addToMount($dirStructure);
707 $subject = $this->createDriver(
709 // Mocked because finfo() can not deal with vfs streams and throws warnings
710 ['getMimeTypeOfFile']
712 $fileList = $subject->getFilesInFolder('/');
713 $this->assertEquals(['/file1', '/file2'], array_keys($fileList));
719 public function getFileListReturnsAllFilesInSubdirectoryIfRecursiveParameterIsSet(): void
725 'file4' => 'asklfjklasjkl'
731 $this->addToMount($dirStructure);
732 $subject = $this->createDriver(
734 // Mocked because finfo() can not deal with vfs streams and throws warnings
735 ['getMimeTypeOfFile']
737 $fileList = $subject->getFilesInFolder('/', 0, 0, true);
738 $this->assertEquals(['/file1', '/file2', '/aDir/file3', '/aDir/subdir/file4'], array_keys($fileList));
744 public function getFileListFailsIfDirectoryDoesNotExist(): void
746 $this->expectException(\InvalidArgumentException
::class);
747 $this->expectExceptionCode(1314349666);
748 $this->addToMount(['somefile' => '']);
749 $subject = $this->createDriver();
750 $subject->getFilesInFolder('somedir/');
756 public function getFileInFolderCallsConfiguredCallbackFunctionWithGivenItemName(): void
761 // register static callback to self
765 'callbackStaticTestFunction'
768 $this->addToMount($dirStructure);
769 $subject = $this->createDriver();
770 // the callback function will throw an exception used to check if it was called with correct $itemName
771 $this->expectException(\InvalidArgumentException
::class);
772 $this->expectExceptionCode(1336159604);
773 $subject->getFilesInFolder('/', 0, 0, false, $callback);
777 * Static callback function used to test if the filter callbacks work
778 * As it is static we are using an exception to test if it is really called and works
781 * @param string $itemName
782 * @throws \InvalidArgumentException
783 * @see getFileListCallsConfiguredCallbackFunction
785 public static function callbackStaticTestFunction(string $itemName): void
787 if ($itemName === 'file2') {
788 throw new \
InvalidArgumentException('$itemName', 1336159604);
795 public function getFileListFiltersItemsWithGivenFilterMethods(): void
801 $this->addToMount($dirStructure);
802 $subject = $this->createDriver(
804 // Mocked because finfo() can not deal with vfs streams and throws warnings
805 ['getMimeTypeOfFile']
809 LocalDriverFilenameFilter
::class,
813 $fileList = $subject->getFilesInFolder('/', 0, 0, false, $filterCallbacks);
814 $this->assertNotContains('/fileA', array_keys($fileList));
820 public function getFolderListReturnsAllDirectoriesInDirectory(): void
827 $this->addToMount($dirStructure);
828 $subject = $this->createDriver();
829 $fileList = $subject->getFoldersInFolder('/');
830 $this->assertEquals(['/dir1/', '/dir2/'], array_keys($fileList));
836 public function getFolderListReturnsHiddenFoldersByDefault(): void
839 '.someHiddenDir' => [],
843 $this->addToMount($dirStructure);
844 $subject = $this->createDriver();
846 $fileList = $subject->getFoldersInFolder('/');
848 $this->assertEquals(['/.someHiddenDir/', '/aDir/'], array_keys($fileList));
852 * Checks if the folder names . and .. are ignored when listing subdirectories
856 public function getFolderListLeavesOutNavigationalEntries(): void
858 // we have to add .. and . manually, as these are not included in vfsStream directory listings (as opposed
859 // to normal filelistings)
864 $subject = $this->createDriver();
865 $fileList = $subject->getFoldersInFolder('/');
866 $this->assertEmpty($fileList);
872 public function getFolderListFiltersItemsWithGivenFilterMethods(): void
878 $this->addToMount($dirStructure);
879 $subject = $this->createDriver();
882 LocalDriverFilenameFilter
::class,
886 $folderList = $subject->getFoldersInFolder('/', 0, 0, $filterCallbacks);
887 $this->assertNotContains('folderA', array_keys($folderList));
893 public function getFolderListFailsIfDirectoryDoesNotExist(): void
895 $this->expectException(\InvalidArgumentException
::class);
896 $this->expectExceptionCode(1314349666);
897 $subject = $this->createDriver();
898 vfsStream
::create([$this->basedir
=> ['somefile' => '']]);
899 $subject->getFoldersInFolder('somedir/');
905 public function hashReturnsCorrectHashes(): void
907 $contents = '68b329da9893e34099c7d8ad5cb9c940';
908 $expectedMd5Hash = '8c67dbaf0ba22f2e7fbc26413b86051b';
909 $expectedSha1Hash = 'a60cd808ba7a0bcfa37fa7f3fb5998e1b8dbcd9d';
910 $this->addToMount(['hashFile' => $contents]);
911 $subject = $this->createDriver();
912 $this->assertEquals($expectedSha1Hash, $subject->hash('/hashFile', 'sha1'));
913 $this->assertEquals($expectedMd5Hash, $subject->hash('/hashFile', 'md5'));
919 public function hashingWithUnsupportedAlgorithmFails(): void
921 $this->expectException(\InvalidArgumentException
::class);
922 $this->expectExceptionCode(1304964032);
923 $subject = $this->createDriver();
924 $subject->hash('/hashFile', $this->getUniqueId());
929 * @covers LocalDriver::getFileForLocalProcessing
931 public function getFileForLocalProcessingCreatesCopyOfFileByDefault(): void
933 $fileContents = 'asdfgh';
936 'someFile' => $fileContents
939 $subject = $this->createDriver([], ['copyFileToTemporaryPath']);
940 $subject->expects($this->once())->method('copyFileToTemporaryPath');
941 $subject->getFileForLocalProcessing('/someDir/someFile');
947 public function getFileForLocalProcessingReturnsOriginalFilepathForReadonlyAccess(): void
949 $fileContents = 'asdfgh';
952 'someFile' => $fileContents
955 $subject = $this->createDriver();
956 $filePath = $subject->getFileForLocalProcessing('/someDir/someFile', false);
957 $this->assertEquals($filePath, $this->getUrlInMount('someDir/someFile'));
963 public function filesCanBeCopiedToATemporaryPath(): void
965 $fileContents = 'asdfgh';
968 'someFile.ext' => $fileContents
971 $subject = $this->createDriver();
972 $filePath = GeneralUtility
::fixWindowsFilePath($subject->_call('copyFileToTemporaryPath', '/someDir/someFile.ext'));
973 $this->testFilesToDelete
[] = $filePath;
974 $this->assertContains('/typo3temp/var/transient/', $filePath);
975 $this->assertEquals($fileContents, file_get_contents($filePath));
981 public function permissionsAreCorrectlyRetrievedForAllowedFile(): void
983 /** @var $subject LocalDriver */
984 list($basedir, $subject) = $this->prepareRealTestEnvironment();
985 touch($basedir . '/someFile');
986 chmod($basedir . '/someFile', 448);
988 $this->assertEquals(['r' => true, 'w' => true], $subject->getPermissions('/someFile'));
994 public function permissionsAreCorrectlyRetrievedForForbiddenFile(): void
996 if (function_exists('posix_getegid') && posix_getegid() === 0) {
997 $this->markTestSkipped('Test skipped if run on linux as root');
998 } elseif (Environment
::isWindows()) {
999 $this->markTestSkipped('Test skipped if run on Windows system');
1001 /** @var $subject LocalDriver */
1002 list($basedir, $subject) = $this->prepareRealTestEnvironment();
1003 touch($basedir . '/someForbiddenFile');
1004 chmod($basedir . '/someForbiddenFile', 0);
1006 $this->assertEquals(['r' => false, 'w' => false], $subject->getPermissions('/someForbiddenFile'));
1012 public function permissionsAreCorrectlyRetrievedForAllowedFolder(): void
1014 /** @var $subject LocalDriver */
1015 list($basedir, $subject) = $this->prepareRealTestEnvironment();
1016 mkdir($basedir . '/someFolder');
1017 chmod($basedir . '/someFolder', 448);
1019 $this->assertEquals(['r' => true, 'w' => true], $subject->getPermissions('/someFolder'));
1025 public function permissionsAreCorrectlyRetrievedForForbiddenFolder(): void
1027 if (function_exists('posix_getegid') && posix_getegid() === 0) {
1028 $this->markTestSkipped('Test skipped if run on linux as root');
1029 } elseif (Environment
::isWindows()) {
1030 $this->markTestSkipped('Test skipped if run on Windows system');
1032 /** @var $subject LocalDriver */
1033 list($basedir, $subject) = $this->prepareRealTestEnvironment();
1034 mkdir($basedir . '/someForbiddenFolder');
1035 chmod($basedir . '/someForbiddenFolder', 0);
1037 $result = $subject->getPermissions('/someForbiddenFolder');
1038 // Change permissions back to writable, so the sub-folder can be removed in tearDown
1039 chmod($basedir . '/someForbiddenFolder', 0777);
1040 $this->assertEquals(['r' => false, 'w' => false], $result);
1044 * Dataprovider for getFilePermissionsReturnsCorrectPermissionsForFilesNotOwnedByCurrentUser test
1046 * @return array group, filemode and expected result
1048 public function getFilePermissionsReturnsCorrectPermissionsForFilesNotOwnedByCurrentUser_dataProvider(): array
1051 // On some OS, the posix_* functions do not exits
1052 if (function_exists('posix_getgid')) {
1054 'current group, readable/writable' => [
1057 ['r' => true, 'w' => true]
1059 'current group, readable/not writable' => [
1062 ['r' => true, 'w' => false]
1064 'current group, not readable/not writable' => [
1067 ['r' => false, 'w' => false]
1071 $data = array_merge_recursive($data, [
1072 'arbitrary group, readable/writable' => [
1073 vfsStream
::GROUP_USER_1
,
1075 ['r' => true, 'w' => true]
1077 'arbitrary group, readable/not writable' => [
1078 vfsStream
::GROUP_USER_1
,
1080 ['r' => true, 'w' => false]
1082 'arbitrary group, not readable/not writable' => [
1083 vfsStream
::GROUP_USER_1
,
1085 ['r' => false, 'w' => false]
1093 * @dataProvider getFilePermissionsReturnsCorrectPermissionsForFilesNotOwnedByCurrentUser_dataProvider
1095 * @param int $permissions
1096 * @param array $expectedResult
1098 public function getFilePermissionsReturnsCorrectPermissionsForFilesNotOwnedByCurrentUser(int $group, int $permissions, array $expectedResult): void
1100 if (Environment
::isWindows()) {
1101 $this->markTestSkipped('Test skipped if run on Windows system');
1104 'testfile' => 'asdfg'
1106 $subject = $this->createDriver();
1107 /** @var $fileObject vfsStreamContent */
1108 $fileObject = vfsStreamWrapper
::getRoot()->getChild($this->mountDir
)->getChild('testfile');
1109 // just use an "arbitrary" user here - it is only important that
1110 $fileObject->chown(vfsStream
::OWNER_USER_1
);
1111 $fileObject->chgrp($group);
1112 $fileObject->chmod($permissions);
1113 $this->assertEquals($expectedResult, $subject->getPermissions('/testfile'));
1119 public function isWithinRecognizesFilesWithinFolderAndInOtherFolders(): void
1121 $subject = $this->createDriver();
1122 $this->assertTrue($subject->isWithin('/someFolder/', '/someFolder/test.jpg'));
1123 $this->assertTrue($subject->isWithin('/someFolder/', '/someFolder/subFolder/test.jpg'));
1124 $this->assertFalse($subject->isWithin('/someFolder/', '/someFolderWithALongName/test.jpg'));
1130 public function isWithinAcceptsFileAndFolderObjectsAsContent(): void
1132 $subject = $this->createDriver();
1133 $this->assertTrue($subject->isWithin('/someFolder/', '/someFolder/test.jpg'));
1134 $this->assertTrue($subject->isWithin('/someFolder/', '/someFolder/subfolder/'));
1137 /**********************************
1139 **********************************/
1144 public function filesCanBeCopiedWithinStorage(): void
1146 $fileContents = $this->getUniqueId();
1148 'someFile' => $fileContents,
1149 'targetFolder' => []
1151 $subject = $this->createDriver(
1153 ['getMimeTypeOfFile']
1155 $subject->copyFileWithinStorage('/someFile', '/targetFolder/', 'someFile');
1156 $this->assertFileEquals($this->getUrlInMount('/someFile'), $this->getUrlInMount('/targetFolder/someFile'));
1162 public function filesCanBeMovedWithinStorage(): void
1164 $fileContents = $this->getUniqueId();
1166 'targetFolder' => [],
1167 'someFile' => $fileContents
1169 $subject = $this->createDriver();
1170 $newIdentifier = $subject->moveFileWithinStorage('/someFile', '/targetFolder/', 'file');
1171 $this->assertEquals($fileContents, file_get_contents($this->getUrlInMount('/targetFolder/file')));
1172 $this->assertFileNotExists($this->getUrlInMount('/someFile'));
1173 $this->assertEquals('/targetFolder/file', $newIdentifier);
1179 public function fileMetadataIsChangedAfterMovingFile(): void
1181 $fileContents = $this->getUniqueId();
1183 'targetFolder' => [],
1184 'someFile' => $fileContents
1186 $subject = $this->createDriver(
1188 // Mocked because finfo() can not deal with vfs streams and throws warnings
1189 ['getMimeTypeOfFile']
1191 $newIdentifier = $subject->moveFileWithinStorage('/someFile', '/targetFolder/', 'file');
1192 $fileMetadata = $subject->getFileInfoByIdentifier($newIdentifier);
1193 $this->assertEquals($newIdentifier, $fileMetadata['identifier']);
1196 public function renamingFiles_dataProvider(): array
1199 'file in subfolder' => [
1201 'targetFolder' => ['file' => '']
1203 '/targetFolder/file',
1205 '/targetFolder/newFile'
1207 'file in rootfolder' => [
1220 * @dataProvider renamingFiles_dataProvider
1221 * @param array $filesystemStructure
1222 * @param string $oldFileIdentifier
1223 * @param string $newFileName
1224 * @param string $expectedNewIdentifier
1226 public function renamingFilesChangesFilenameOnDisk(array $filesystemStructure, string $oldFileIdentifier, string $newFileName, string $expectedNewIdentifier)
1228 $this->addToMount($filesystemStructure);
1229 $subject = $this->createDriver();
1230 $newIdentifier = $subject->renameFile($oldFileIdentifier, $newFileName);
1231 $this->assertFalse($subject->fileExists($oldFileIdentifier));
1232 $this->assertTrue($subject->fileExists($newIdentifier));
1233 $this->assertEquals($expectedNewIdentifier, $newIdentifier);
1239 public function renamingFilesFailsIfTargetFileExists(): void
1241 $this->expectException(ExistingTargetFileNameException
::class);
1242 $this->expectExceptionCode(1320291063);
1244 'targetFolder' => ['file' => '', 'newFile' => '']
1246 $subject = $this->createDriver();
1247 $subject->renameFile('/targetFolder/file', 'newFile');
1251 * We use this data provider for testing move methods because there are some issues with the
1255 public function renamingFolders_dataProvider(): array
1258 'folder in root folder' => [
1266 'file in subfolder' => [
1272 '/subfolder/someFolder/',
1274 '/subfolder/newFolder/'
1281 * @dataProvider renamingFolders_dataProvider
1282 * @param array $filesystemStructure
1283 * @param string $oldFolderIdentifier
1284 * @param string $newFolderName
1285 * @param string $expectedNewIdentifier
1287 public function renamingFoldersChangesFolderNameOnDisk(array $filesystemStructure, string $oldFolderIdentifier, string $newFolderName, string $expectedNewIdentifier)
1289 $this->addToMount($filesystemStructure);
1290 $subject = $this->createDriver();
1291 $mapping = $subject->renameFolder($oldFolderIdentifier, $newFolderName);
1292 $this->assertFalse($subject->folderExists($oldFolderIdentifier));
1293 $this->assertTrue($subject->folderExists($expectedNewIdentifier));
1294 $this->assertEquals($expectedNewIdentifier, $mapping[$oldFolderIdentifier]);
1300 public function renameFolderReturnsCorrectMappingInformationForAllFiles(): void
1302 $fileContents = 'asdfg';
1305 'subFolder' => ['file' => $fileContents],
1309 $subject = $this->createDriver();
1310 $mappingInformation = $subject->renameFolder('/sourceFolder/', 'newFolder');
1311 $this->assertTrue(is_array($mappingInformation));
1312 $this->assertEquals('/newFolder/', $mappingInformation['/sourceFolder/']);
1313 $this->assertEquals('/newFolder/file2', $mappingInformation['/sourceFolder/file2']);
1314 $this->assertEquals('/newFolder/subFolder/file', $mappingInformation['/sourceFolder/subFolder/file']);
1315 $this->assertEquals('/newFolder/subFolder/', $mappingInformation['/sourceFolder/subFolder/']);
1321 public function renameFolderRevertsRenamingIfFilenameMapCannotBeCreated(): void
1323 $this->expectException(\RuntimeException
::class);
1324 $this->expectExceptionCode(1334160746);
1330 $subject = $this->createDriver([], ['createIdentifierMap']);
1331 $subject->expects($this->atLeastOnce())->method('createIdentifierMap')->will(
1332 $this->throwException(
1333 new FileOperationErrorException('testing', 1476045666)
1336 $subject->renameFolder('/sourceFolder/', 'newFolder');
1337 $this->assertFileExists($this->getUrlInMount('/sourceFolder/file'));
1343 public function isFolderEmptyReturnsTrueForEmptyFolder()
1345 // This also prepares the next few tests, so add more info than required for this test
1349 $subject = $this->createDriver();
1350 $this->assertTrue($subject->isFolderEmpty('/emptyFolder/'));
1357 public function isFolderEmptyReturnsFalseIfFolderHasFile(): void
1360 'folderWithFile' => [
1364 $subject = $this->createDriver();
1365 $this->assertFalse($subject->isFolderEmpty('/folderWithFile/'));
1371 public function isFolderEmptyReturnsFalseIfFolderHasSubfolder(): void
1374 'folderWithSubfolder' => [
1378 $subject = $this->createDriver();
1379 $this->assertFalse($subject->isFolderEmpty('/folderWithSubfolder/'));
1382 /**********************************
1384 **********************************/
1388 public function foldersCanBeMovedWithinStorage(): void
1390 $fileContents = $this->getUniqueId();
1393 'file' => $fileContents,
1395 'targetFolder' => [],
1397 $subject = $this->createDriver();
1398 /** @var LocalDriver $subject */
1399 $subject->moveFolderWithinStorage('/sourceFolder/', '/targetFolder/', 'someFolder');
1400 $this->assertTrue(file_exists($this->getUrlInMount('/targetFolder/someFolder/')));
1401 $this->assertEquals($fileContents, file_get_contents($this->getUrlInMount('/targetFolder/someFolder/file')));
1402 $this->assertFileNotExists($this->getUrlInMount('/sourceFolder'));
1408 public function moveFolderWithinStorageReturnsCorrectMappingInformationForAllFiles(): void
1410 $fileContents = 'asdfg';
1412 'targetFolder' => [],
1414 'subFolder' => ['file' => $fileContents],
1418 $subject = $this->createDriver();
1419 $mappingInformation = $subject->moveFolderWithinStorage('/sourceFolder/', '/targetFolder/', 'sourceFolder');
1420 $this->assertEquals('/targetFolder/sourceFolder/file', $mappingInformation['/sourceFolder/file']);
1421 $this->assertEquals('/targetFolder/sourceFolder/subFolder/file', $mappingInformation['/sourceFolder/subFolder/file']);
1422 $this->assertEquals('/targetFolder/sourceFolder/subFolder/', $mappingInformation['/sourceFolder/subFolder/']);
1428 public function folderCanBeRenamedWhenMoving(): void
1432 'file' => $this->getUniqueId(),
1434 'targetFolder' => [],
1436 $subject = $this->createDriver();
1437 $subject->moveFolderWithinStorage('/sourceFolder/', '/targetFolder/', 'newFolder');
1438 $this->assertTrue(file_exists($this->getUrlInMount('/targetFolder/newFolder/')));
1444 public function copyFolderWithinStorageCopiesSingleFileToNewFolderName(): void
1448 'file' => $this->getUniqueId(),
1450 'targetFolder' => [],
1452 $subject = $this->createDriver();
1453 $subject->copyFolderWithinStorage('/sourceFolder/', '/targetFolder/', 'newFolderName');
1454 $this->assertTrue(is_file($this->getUrlInMount('/targetFolder/newFolderName/file')));
1460 public function copyFolderWithinStorageCopiesSingleSubFolderToNewFolderName(): void
1462 list($basePath, $subject) = $this->prepareRealTestEnvironment();
1463 GeneralUtility
::mkdir_deep($basePath . '/sourceFolder/subFolder');
1464 GeneralUtility
::mkdir_deep($basePath . '/targetFolder');
1466 $subject->copyFolderWithinStorage('/sourceFolder/', '/targetFolder/', 'newFolderName');
1467 $this->assertTrue(is_dir($basePath . '/targetFolder/newFolderName/subFolder'));
1473 public function copyFolderWithinStorageCopiesFileInSingleSubFolderToNewFolderName(): void
1475 list($basePath, $subject) = $this->prepareRealTestEnvironment();
1476 GeneralUtility
::mkdir_deep($basePath . '/sourceFolder/subFolder');
1477 GeneralUtility
::mkdir_deep($basePath . '/targetFolder');
1478 file_put_contents($basePath . '/sourceFolder/subFolder/file', $this->getUniqueId());
1479 GeneralUtility
::fixPermissions($basePath . '/sourceFolder/subFolder/file');
1481 $subject->copyFolderWithinStorage('/sourceFolder/', '/targetFolder/', 'newFolderName');
1482 $this->assertTrue(is_file($basePath . '/targetFolder/newFolderName/subFolder/file'));
1485 ///////////////////////
1486 // Tests concerning sanitizeFileName
1487 ///////////////////////
1490 * Set up data for sanitizeFileName tests
1492 public function setUpCharacterStrings(): void
1494 // Generate string containing all characters for the iso8859-1 charset, charcode greater than 127
1495 $this->iso88591GreaterThan127
= '';
1496 for ($i = 0xA0; $i <= 0xFF; $i++
) {
1497 $this->iso88591GreaterThan127
.= chr($i);
1500 // Generate string containing all characters for the utf-8 Latin-1 Supplement (U+0080 to U+00FF)
1501 // without U+0080 to U+009F: control characters
1502 // Based on http://www.utf8-chartable.de/unicode-utf8-table.pl
1503 $this->utf8Latin1Supplement
= '';
1504 for ($i = 0xA0; $i <= 0xBF; $i++
) {
1505 $this->utf8Latin1Supplement
.= chr(0xC2) . chr($i);
1507 for ($i = 0x80; $i <= 0xBF; $i++
) {
1508 $this->utf8Latin1Supplement
.= chr(0xC3) . chr($i);
1511 // Generate string containing all characters for the utf-8 Latin-1 Extended-A (U+0100 to U+017F)
1512 $this->utf8Latin1ExtendedA
= '';
1513 for ($i = 0x80; $i <= 0xBF; $i++
) {
1514 $this->utf8Latin1ExtendedA
.= chr(0xC4) . chr($i);
1516 for ($i = 0x80; $i <= 0xBF; $i++
) {
1517 $this->utf8Latin1ExtendedA
.= chr(0xC5) . chr($i);
1522 * Data provider for sanitizeFileNameUTF8FilesystemDataProvider
1524 * Every array splits into:
1525 * - String value fileName
1526 * - String value charset (none = '', utf-8, latin1, etc.)
1527 * - Expected result (cleaned fileName)
1531 public function sanitizeFileNameUTF8FilesystemDataProvider(): array
1533 $this->setUpCharacterStrings();
1535 // Characters ordered by ASCII table
1536 'allowed characters utf-8 (ASCII part)' => [
1537 '-.0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz',
1538 '-.0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'
1540 // Characters ordered by ASCII table (except for space-character, because space-character ist trimmed)
1541 'replace special characters with _ (not allowed characters) utf-8 (ASCII part)' => [
1542 '! "#$%&\'()*+,/:;<=>?[\\]^`{|}~',
1543 '_____________________________'
1545 'utf-8 (Latin-1 Supplement)' => [
1546 $this->utf8Latin1Supplement
,
1547 '________________________________ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
1549 'trim leading and tailing spaces utf-8' => [
1553 'remove tailing dot' => [
1562 * @dataProvider sanitizeFileNameUTF8FilesystemDataProvider
1563 * @param string $fileName
1564 * @param string $expectedResult
1566 public function sanitizeFileNameUTF8Filesystem(string $fileName, string $expectedResult): void
1568 $GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem'] = 1;
1569 $this->assertEquals(
1571 $this->createDriver()->sanitizeFileName($fileName)
1576 * Data provider for sanitizeFileNameNonUTF8Filesystem
1578 * Every array splits into:
1579 * - String value fileName
1580 * - String value charset (none = '', utf-8, latin1, etc.)
1581 * - Expected result (cleaned fileName)
1585 public function sanitizeFileNameNonUTF8FilesystemDataProvider(): array
1587 $this->setUpCharacterStrings();
1589 // Characters ordered by ASCII table
1590 'allowed characters iso-8859-1' => [
1591 '-.0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz',
1593 '-.0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'
1595 // Characters ordered by ASCII table
1596 'allowed characters utf-8' => [
1597 '-.0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz',
1599 '-.0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'
1601 // Characters ordered by ASCII table (except for space-character, because space-character ist trimmed)
1602 'replace special characters with _ (not allowed characters) iso-8859-1' => [
1603 '! "#$%&\'()*+,/:;<=>?[\\]^`{|}~',
1605 '_____________________________'
1607 // Characters ordered by ASCII table (except for space-character, because space-character ist trimmed)
1608 'replace special characters with _ (not allowed characters) utf-8' => [
1609 '! "#$%&\'()*+,/:;<=>?[\\]^`{|}~',
1611 '_____________________________'
1613 'iso-8859-1 (code > 127)' => [
1614 // http://de.wikipedia.org/wiki/ISO_8859-1
1615 // chr(0xA0) = NBSP (no-break space) => gets trimmed
1616 $this->iso88591GreaterThan127
,
1618 '_centpound_yen____c_a_____R_____-23_u___1o__1_41_23_4_AAAAAEAAAECEEEEIIIIDNOOOOOExOEUUUUEYTHssaaaaaeaaaeceeeeiiiidnoooooe_oeuuuueythy'
1620 'utf-8 (Latin-1 Supplement)' => [
1621 // chr(0xC2) . chr(0x0A) = NBSP (no-break space) => gets trimmed
1622 $this->utf8Latin1Supplement
,
1624 '_centpound__yen______c_a_______R_______-23__u_____1o__1_41_23_4_AAAAAEAAAECEEEEIIIIDNOOOOOExOEUUUUEYTHssaaaaaeaaaeceeeeiiiidnoooooe_oeuuuueythy'
1626 'utf-8 (Latin-1 Extended A)' => [
1627 $this->utf8Latin1ExtendedA
,
1629 'AaAaAaCcCcCcCcDdDdEeEeEeEeEeGgGgGgGgHhHhIiIiIiIiIiIJijJjKk__LlLlLlL_l_LlNnNnNn_n____OOooOoOoOEoeRrRrRrSsSsSsSsTtTtTtUuUuUuUuUuUuWwYyYZzZzZzs'
1631 'trim leading and tailing spaces iso-8859-1' => [
1636 'trim leading and tailing spaces utf-8' => [
1641 'remove tailing dot iso-8859-1' => [
1646 'remove tailing dot utf-8' => [
1656 * @dataProvider sanitizeFileNameNonUTF8FilesystemDataProvider
1657 * @param string $fileName
1658 * @param string $charset
1659 * @param string $expectedResult
1661 public function sanitizeFileNameNonUTF8Filesystem(string $fileName, string $charset, string $expectedResult): void
1663 $GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem'] = 0;
1664 $this->assertEquals(
1666 $this->createDriver()->sanitizeFileName($fileName, $charset)
1673 public function sanitizeFileNameThrowsExceptionOnInvalidFileName(): void
1675 $this->expectException(InvalidFileNameException
::class);
1676 $this->expectExceptionCode(1320288991);
1678 $GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem'] = 1;
1679 $this->createDriver()->sanitizeFileName('');
1685 public function applyFilterMethodsToDirectoryItemCallsFilterMethodIfClosure(): void
1687 $this->expectException(\Exception
::class);
1688 $this->expectExceptionCode(1463073434);
1689 $closure = function () {
1690 throw new \
Exception('I was called!', 1463073434);
1697 $this->createDriver()->_call('applyFilterMethodsToDirectoryItem', $filterMethods, '', '', '');
1703 public function applyFilterMethodsToDirectoryItemCallsFilterMethodIfName(): void
1705 $dummyObject = $this
1706 ->getMockBuilder(LocalDriver
::class)
1707 ->setMethods(['dummy'])
1708 ->disableOriginalConstructor()
1714 $dummyObject->expects($this->once())->method('dummy');
1718 $this->createDriver()->_call('applyFilterMethodsToDirectoryItem', $filterMethods, '', '', '');