‪TYPO3CMS  ‪main
StorageRepositoryTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
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.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
34 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
35 
36 final class ‪StorageRepositoryTest extends FunctionalTestCase
37 {
38  protected function ‪tearDown(): void
39  {
41  mkdir(‪Environment::getPublicPath() . '/fileadmin');
42  ‪GeneralUtility::rmdir(‪Environment::getPublicPath() . '/typo3temp/assets/_processed_', true);
43  parent::tearDown();
44  }
45 
46  public static function ‪bestStorageIsResolvedDataProvider(): iterable
47  {
48  // `{public}` will be replaced by public project path (not having trailing slash)
49  // double slashes `//` are used on purpose for given file identifiers
50 
51  // legacy storage
52  yield ['/favicon.ico', '0:/favicon.ico'];
53  yield ['/favicon.ico', '0:/favicon.ico'];
54 
55  yield ['favicon.ico', '0:/favicon.ico'];
56  yield ['{public}//favicon.ico', '0:/favicon.ico'];
57  yield ['{public}/favicon.ico', '0:/favicon.ico'];
58 
59  // using storages with relative path
60  yield ['/fileadmin/img.png', '1:/img.png'];
61  yield ['fileadmin/img.png', '1:/img.png'];
62  yield ['/fileadmin/images/img.png', '1:/images/img.png'];
63  yield ['fileadmin/images/img.png', '1:/images/img.png'];
64  yield ['/documents/doc.pdf', '2:/doc.pdf'];
65  yield ['documents/doc.pdf', '2:/doc.pdf'];
66  yield ['/fileadmin/nested/images/img.png', '3:/images/img.png'];
67  yield ['fileadmin/nested/images/img.png', '3:/images/img.png'];
68 
69  yield ['{public}//fileadmin/img.png', '1:/img.png'];
70  yield ['{public}/fileadmin/img.png', '1:/img.png'];
71  yield ['{public}//fileadmin/images/img.png', '1:/images/img.png'];
72  yield ['{public}/fileadmin/images/img.png', '1:/images/img.png'];
73  yield ['{public}//documents/doc.pdf', '2:/doc.pdf'];
74  yield ['{public}/documents/doc.pdf', '2:/doc.pdf'];
75  yield ['{public}//fileadmin/nested/images/img.png', '3:/images/img.png'];
76  yield ['{public}/fileadmin/nested/images/img.png', '3:/images/img.png'];
77 
78  // using storages with absolute path
79  yield ['/files/img.png', '4:/img.png'];
80  yield ['files/img.png', '4:/img.png'];
81  yield ['/files/images/img.png', '4:/images/img.png'];
82  yield ['files/images/img.png', '4:/images/img.png'];
83  yield ['/docs/doc.pdf', '5:/doc.pdf'];
84  yield ['docs/doc.pdf', '5:/doc.pdf'];
85  yield ['/files/nested/images/img.png', '6:/images/img.png'];
86  yield ['files/nested/images/img.png', '6:/images/img.png'];
87 
88  yield ['{public}//files/img.png', '4:/img.png'];
89  yield ['{public}/files/img.png', '4:/img.png'];
90  yield ['{public}//files/images/img.png', '4:/images/img.png'];
91  yield ['{public}/files/images/img.png', '4:/images/img.png'];
92  yield ['{public}//docs/doc.pdf', '5:/doc.pdf'];
93  yield ['{public}/docs/doc.pdf', '5:/doc.pdf'];
94  yield ['{public}//files/nested/images/img.png', '6:/images/img.png'];
95  yield ['{public}/files/nested/images/img.png', '6:/images/img.png'];
96  }
97 
102  public function ‪bestStorageIsResolved(string $sourceIdentifier, string $expectedCombinedIdentifier): void
103  {
104  $subject = GeneralUtility::makeInstance(StorageRepository::class);
105  $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
106  $this->setUpBackendUser(1);
107  $publicPath = ‪Environment::getPublicPath();
108  $prefixDelegate = static function (string $value) use ($publicPath): string {
109  return $publicPath . '/' . $value;
110  };
111  // array indexes are not relevant here, but are those expected to be used as storage UID (`1:/file.png`)
112  // @todo it is possible to create ambiguous storages, e.g. `fileadmin/` AND `/fileadmin/`
113  $relativeNames = [1 => 'fileadmin/', 2 => 'documents/', 3 => 'fileadmin/nested/'];
114  // @todo: All these directories must exist. This is because createLocalStorage() calls testCaseSensitivity()
115  // which creates a file in each directory without checking if the directory does exist. Arguably, this
116  // should be handled in testCaseSensitivity(). For now, we create the directories in question and
117  // suppress errors so only the first test creates them and subsequent tests don't emit a warning here.
118  @mkdir($this->instancePath . '/documents');
119  @mkdir($this->instancePath . '/fileadmin/nested');
120  $absoluteNames = array_map($prefixDelegate, [4 => 'files/', 5 => 'docs/', 6 => 'files/nested']);
121  @mkdir($this->instancePath . '/files');
122  @mkdir($this->instancePath . '/docs');
123  @mkdir($this->instancePath . '/files/nested');
124  foreach ($relativeNames as $relativeName) {
125  $subject->createLocalStorage('rel:' . $relativeName, $relativeName, 'relative');
126  }
127  foreach ($absoluteNames as $absoluteName) {
128  $subject->createLocalStorage('abs:' . $absoluteName, $absoluteName, 'absolute');
129  }
130  $sourceIdentifier = str_replace('{public}', ‪Environment::getPublicPath(), $sourceIdentifier);
131  $storage = $subject->getStorageObject(0, [], $sourceIdentifier);
132  $combinedIdentifier = sprintf('%d:%s', $storage->getUid(), $sourceIdentifier);
133  self::assertSame(
134  $expectedCombinedIdentifier,
135  $combinedIdentifier,
136  sprintf('Given identifier "%s"', $sourceIdentifier)
137  );
138  }
139 
143  public function ‪getNestedProcessingFolderTest(): void
144  {
145  $this->importCSVDataSet(__DIR__ . '/../Fixtures/sys_file_storage.csv');
146  $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
147  $this->setUpBackendUser(1);
148  $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
149  $subject->setEvaluatePermissions(false);
150  mkdir(‪Environment::getPublicPath() . '/fileadmin/_processed_');
151  mkdir(‪Environment::getPublicPath() . '/fileadmin/aDirectory');
152  mkdir(‪Environment::getPublicPath() . '/typo3temp/assets/_processed_');
153  file_put_contents(‪Environment::getPublicPath() . '/fileadmin/aDirectory/bar.txt', 'myData');
154  $subject->addFileMount('/aDirectory/', ['read_only' => false]);
155  $file = GeneralUtility::makeInstance(ResourceFactory::class)->getFileObjectFromCombinedIdentifier('1:/aDirectory/bar.txt');
156  $rootProcessingFolder = $subject->getProcessingFolder();
157  $processingFolder = $subject->getProcessingFolder($file);
158  self::assertInstanceOf(Folder::class, $processingFolder);
159  self::assertNotEquals($rootProcessingFolder, $processingFolder);
160  for ($i = ‪ResourceStorage::PROCESSING_FOLDER_LEVELS; $i > 0; $i--) {
161  $processingFolder = $processingFolder->getParentFolder();
162  }
163  self::assertEquals($rootProcessingFolder, $processingFolder);
164  }
165 
166  public static function ‪isWithinFileMountBoundariesDataProvider(): array
167  {
168  return [
169  'Access to file in ro file mount denied for write request' => [
170  '$targetDirectory' => 'fooBaz',
171  '$fileMountFolder' => 'fooBaz',
172  '$isFileMountReadOnly' => true,
173  '$checkWriteAccess' => true,
174  '$expectedResult' => false,
175  ],
176  'Access to file in ro file mount allowed for read request' => [
177  '$targetDirectory' => 'fooBaz',
178  '$fileMountFolder' => 'fooBaz',
179  '$isFileMountReadOnly' => true,
180  '$checkWriteAccess' => false,
181  '$expectedResult' => true,
182  ],
183  'Access to file in rw file mount allowed for write request' => [
184  '$targetDirectory' => 'fooBaz',
185  '$fileMountFolder' => 'fooBaz',
186  '$isFileMountReadOnly' => false,
187  '$checkWriteAccess' => true,
188  '$expectedResult' => true,
189  ],
190  'Access to file in rw file mount allowed for read request' => [
191  '$targetDirectory' => 'fooBaz',
192  '$fileMountFolder' => 'fooBaz',
193  '$isFileMountReadOnly' => false,
194  '$checkWriteAccess' => false,
195  '$expectedResult' => true,
196  ],
197  'Access to file not in file mount denied for write request' => [
198  '$targetDirectory' => 'fooBaz',
199  '$fileMountFolder' => 'barBaz',
200  '$isFileMountReadOnly' => false,
201  '$checkWriteAccess' => true,
202  '$expectedResult' => false,
203  ],
204  'Access to file not in file mount denied for read request' => [
205  '$targetDirectory' => 'fooBaz',
206  '$fileMountFolder' => 'barBaz',
207  '$isFileMountReadOnly' => false,
208  '$checkWriteAccess' => false,
209  '$expectedResult' => false,
210  ],
211  ];
212  }
213 
218  public function ‪isWithinFileMountBoundariesRespectsReadOnlyFileMounts(string $targetDirectory, string $fileMountFolder, bool $isFileMountReadOnly, bool $checkWriteAccess, bool $expectedResult): void
219  {
220  $this->importCSVDataSet(__DIR__ . '/../Fixtures/sys_file_storage.csv');
221  $fileName = 'bar.txt';
222  $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
223  $this->setUpBackendUser(1);
224  mkdir(‪Environment::getPublicPath() . '/fileadmin/_processed_');
225  mkdir(‪Environment::getPublicPath() . '/fileadmin/' . $targetDirectory);
226  if ($fileMountFolder !== $targetDirectory) {
227  mkdir(‪Environment::getPublicPath() . '/fileadmin/' . $fileMountFolder);
228  }
229  file_put_contents(‪Environment::getPublicPath() . '/fileadmin/' . $targetDirectory . '/' . $fileName, 'myData');
230  $file = GeneralUtility::makeInstance(ResourceFactory::class)->getFileObjectFromCombinedIdentifier('1:/' . $targetDirectory . '/' . $fileName);
231  $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
232  $subject->setEvaluatePermissions(true);
233  // read_only = true -> no write access for user, so checking for second argument true should assert false
234  $subject->addFileMount('/' . $fileMountFolder . '/', ['read_only' => $isFileMountReadOnly]);
235  self::assertSame($expectedResult, $subject->isWithinFileMountBoundaries($file, $checkWriteAccess));
236  }
237 
241  public function ‪getProcessingRootFolderTest(): void
242  {
243  $this->importCSVDataSet(__DIR__ . '/../Fixtures/sys_file_storage.csv');
244  $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
245  $this->setUpBackendUser(1);
246  $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
247  $processingFolder = $subject->getProcessingFolder();
248  self::assertInstanceOf(Folder::class, $processingFolder);
249  }
250 
255  {
256  $folderIdentifier = ‪StringUtility::getUniqueId();
257  $this->importCSVDataSet(__DIR__ . '/../Fixtures/sys_file_storage.csv');
258  $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
259  $this->setUpBackendUser(1);
260  $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
261  $folder = new ‪Folder($subject, '/foo/' . $folderIdentifier . '/', $folderIdentifier);
262  $role = $subject->getRole($folder);
263  self::assertSame(‪FolderInterface::ROLE_DEFAULT, $role);
264  }
265 
270  {
271  $this->importCSVDataSet(__DIR__ . '/../Fixtures/sys_file_storage.csv');
272  $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
273  $this->setUpBackendUser(1);
274  $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
275  mkdir(‪Environment::getPublicPath() . '/fileadmin/foo');
276  file_put_contents(‪Environment::getPublicPath() . '/fileadmin/foo/bar.txt', 'myData');
277  $file = GeneralUtility::makeInstance(ResourceFactory::class)->getFileObjectFromCombinedIdentifier('1:/foo/bar.txt');
278  $this->expectException(\InvalidArgumentException::class);
279  $this->expectExceptionCode(1325842622);
280  $subject->replaceFile($file, ‪Environment::getPublicPath() . '/' . ‪StringUtility::getUniqueId());
281  }
282 
287  {
288  $this->importCSVDataSet(__DIR__ . '/../Fixtures/sys_file_storage.csv');
289  $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
290  $this->setUpBackendUser(1);
291  $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
292  $this->expectException(\InvalidArgumentException::class);
293  $this->expectExceptionCode(1325689164);
294  $subject->createFolder('newFolder', new ‪Folder($subject, '/foo/', 'foo'));
295  }
296 
301  {
302  $this->importCSVDataSet(__DIR__ . '/../Fixtures/sys_file_storage.csv');
303  $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
304  $this->setUpBackendUser(1);
305  $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
306  mkdir(‪Environment::getPublicPath() . '/fileadmin/foo');
307  mkdir(‪Environment::getPublicPath() . '/fileadmin/_recycler_');
308  file_put_contents(‪Environment::getPublicPath() . '/fileadmin/foo/bar.txt', 'myData');
309  $file = GeneralUtility::makeInstance(ResourceFactory::class)->getFileObjectFromCombinedIdentifier('1:/foo/bar.txt');
310  $subject->deleteFile($file);
311  self::assertFileExists(‪Environment::getPublicPath() . '/fileadmin/_recycler_/bar.txt');
312  self::assertFileDoesNotExist(‪Environment::getPublicPath() . '/fileadmin/foo/bar.txt');
313  }
314 
319  {
320  $this->importCSVDataSet(__DIR__ . '/../Fixtures/sys_file_storage.csv');
321  $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
322  $this->setUpBackendUser(1);
323  $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
324  mkdir(‪Environment::getPublicPath() . '/fileadmin/foo');
325  file_put_contents(‪Environment::getPublicPath() . '/fileadmin/foo/bar.txt', 'myData');
326  $file = GeneralUtility::makeInstance(ResourceFactory::class)->getFileObjectFromCombinedIdentifier('1:/foo/bar.txt');
327  $subject->deleteFile($file);
328  self::assertFileDoesNotExist(‪Environment::getPublicPath() . '/fileadmin/foo/bar.txt');
329  }
330 
331  public static function ‪searchFilesFindsFilesInFolderDataProvider(): array
332  {
333  return [
334  'Finds foo recursive by name' => [
335  'foo',
336  '/bar/',
337  true,
338  [],
339  [
340  '/bar/bla/foo.txt',
341  ],
342  ],
343  'Finds foo not recursive by name' => [
344  'foo',
345  '/bar/bla/',
346  false,
347  [],
348  [
349  '/bar/bla/foo.txt',
350  ],
351  ],
352  'Finds nothing when not recursive for top level folder' => [
353  'foo',
354  '/bar/',
355  false,
356  [],
357  [],
358  ],
359  'Finds foo by description' => [
360  'fodescrip',
361  '/bar/',
362  true,
363  [],
364  [
365  '/bar/bla/foo.txt',
366  ],
367  ],
368  'Finds foo by translated description' => [
369  'fotranslated',
370  '/bar/',
371  true,
372  [],
373  [
374  '/bar/bla/foo.txt',
375  ],
376  ],
377  'Finds blupp by name' => [
378  'blupp',
379  '/bar/',
380  false,
381  [],
382  [
383  '/bar/blupp.txt',
384  ],
385  ],
386  'Finds only blupp by title for non recursive' => [
387  'title',
388  '/bar/',
389  false,
390  [],
391  [
392  '/bar/blupp.txt',
393  ],
394  ],
395  'Finds foo and blupp by title for recursive' => [
396  'title',
397  '/bar/',
398  true,
399  [],
400  [
401  '/bar/blupp.txt',
402  '/bar/bla/foo.txt',
403  ],
404  ],
405  'Finds foo, baz and blupp with no folder' => [
406  'title',
407  null,
408  true,
409  [],
410  [
411  '/baz/bla/baz.txt',
412  '/bar/blupp.txt',
413  '/bar/bla/foo.txt',
414  ],
415  ],
416  'Finds nothing for not existing' => [
417  'baz',
418  '/bar/',
419  true,
420  [],
421  [],
422  ],
423  'Finds nothing in root, when not recursive' => [
424  'title',
425  '/',
426  false,
427  [],
428  [],
429  ],
430  'Finds nothing, when not recursive and no folder given' => [
431  'title',
432  null,
433  false,
434  [],
435  [],
436  ],
437  'Filter is applied to result' => [
438  'title',
439  null,
440  true,
441  [
442  static function ($itemName) {
443  return str_contains($itemName, 'blupp') ? true : -1;
444  },
445  ],
446  [
447  '/bar/blupp.txt',
448  ],
449  ],
450  ];
451  }
452 
458  public function ‪searchFilesFindsFilesInFolder(string $searchTerm, ?string $searchFolder, bool $recursive, array $filters, array $expectedIdentifiers): void
459  {
460  $this->importCSVDataSet(__DIR__ . '/../Fixtures/sys_file_storage.csv');
461  $this->importCSVDataSet(__DIR__ . '/Fixtures/FileSearch.csv');
462  $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
463  $this->setUpBackendUser(1);
464  $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
465  $subject->setFileAndFolderNameFilters($filters);
466  mkdir(‪Environment::getPublicPath() . '/fileadmin/bar');
467  mkdir(‪Environment::getPublicPath() . '/fileadmin/bar/bla');
468  mkdir(‪Environment::getPublicPath() . '/fileadmin/baz');
469  mkdir(‪Environment::getPublicPath() . '/fileadmin/baz/bla');
470  file_put_contents(‪Environment::getPublicPath() . '/fileadmin/bar/bla/foo.txt', 'myData');
471  file_put_contents(‪Environment::getPublicPath() . '/fileadmin/baz/bla/baz.txt', 'myData');
472  file_put_contents(‪Environment::getPublicPath() . '/fileadmin/bar/blupp.txt', 'myData');
473  $folder = $searchFolder ? GeneralUtility::makeInstance(ResourceFactory::class)->getFolderObjectFromCombinedIdentifier('1:' . $searchFolder) : null;
474  $search = ‪FileSearchDemand::createForSearchTerm($searchTerm);
475  if ($recursive) {
476  $search = $search->withRecursive();
477  }
478  $result = $subject->searchFiles($search, $folder);
479  $expectedFiles = array_map([$subject, 'getFile'], $expectedIdentifiers);
480  self::assertSame($expectedFiles, iterator_to_array($result));
481  // Check if search also works for non-hierarchical storages/drivers
482  // This is a hack, as capabilities is not settable from the outside
483  $objectReflection = new \ReflectionObject($subject);
484  $property = $objectReflection->getProperty('capabilities');
485  $property->setValue($subject, $subject->getCapabilities()->addCapabilities(‪Capabilities::CAPABILITY_BROWSABLE, ‪Capabilities::CAPABILITY_PUBLIC, ‪Capabilities::CAPABILITY_WRITABLE));
486  $result = $subject->searchFiles($search, $folder);
487  $expectedFiles = array_map([$subject, 'getFile'], $expectedIdentifiers);
488  self::assertSame($expectedFiles, iterator_to_array($result));
489  }
490 
495  {
497  $this->importCSVDataSet(__DIR__ . '/../Fixtures/sys_file_storage.csv');
498  $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
499  $this->setUpBackendUser(1);
500  $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
501  mkdir(‪Environment::getPublicPath() . '/fileadmin/foo');
502  $folderToCopy = GeneralUtility::makeInstance(ResourceFactory::class)->getFolderObjectFromCombinedIdentifier('1:/foo');
503  $targetParentFolder = GeneralUtility::makeInstance(ResourceFactory::class)->getFolderObjectFromCombinedIdentifier('1:/');
504  $this->expectException(InvalidTargetFolderException::class);
505  $this->expectExceptionCode(1422723059);
506  $subject->copyFolder($folderToCopy, $targetParentFolder, null, $conflictMode);
507  }
508 
513  {
515  $this->importCSVDataSet(__DIR__ . '/../Fixtures/sys_file_storage.csv');
516  $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
517  $this->setUpBackendUser(1);
518  $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
519  mkdir(‪Environment::getPublicPath() . '/fileadmin/foo');
520  $folderToCopy = GeneralUtility::makeInstance(ResourceFactory::class)->getFolderObjectFromCombinedIdentifier('1:/foo');
521  $targetParentFolder = GeneralUtility::makeInstance(ResourceFactory::class)->getFolderObjectFromCombinedIdentifier('1:/');
522  $subject->copyFolder($folderToCopy, $targetParentFolder, null, $conflictMode);
523  $newFolder = GeneralUtility::makeInstance(ResourceFactory::class)->getFolderObjectFromCombinedIdentifier('1:/foo_01');
524  self::assertInstanceOf(Folder::class, $newFolder);
525  }
526 
531  {
533  $this->importCSVDataSet(__DIR__ . '/../Fixtures/sys_file_storage.csv');
534  $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
535  $this->setUpBackendUser(1);
536  mkdir(‪Environment::getPublicPath() . '/fileadmin/foo');
537  file_put_contents(‪Environment::getPublicPath() . '/fileadmin/foo/bar.txt', 'Temp file 1');
538  file_put_contents(‪Environment::getPublicPath() . '/fileadmin/bar.txt', 'Temp file 2');
539  $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
540  $fileToCopy = GeneralUtility::makeInstance(ResourceFactory::class)->getFileObjectFromCombinedIdentifier('1:/foo/bar.txt');
541  $targetParentFolder = GeneralUtility::makeInstance(ResourceFactory::class)->getFolderObjectFromCombinedIdentifier('1:/');
542  $this->expectException(ExistingTargetFileNameException::class);
543  $this->expectExceptionCode(1320291064);
544  $subject->copyFile($fileToCopy, $targetParentFolder, null, $conflictMode);
545  }
546 
551  {
553  $this->importCSVDataSet(__DIR__ . '/../Fixtures/sys_file_storage.csv');
554  $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
555  $this->setUpBackendUser(1);
556  mkdir(‪Environment::getPublicPath() . '/fileadmin/foo');
557  file_put_contents(‪Environment::getPublicPath() . '/fileadmin/foo/bar.txt', 'Temp file 1');
558  file_put_contents(‪Environment::getPublicPath() . '/fileadmin/bar.txt', 'Temp file 2');
559  $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
560  $fileToCopy = GeneralUtility::makeInstance(ResourceFactory::class)->getFileObjectFromCombinedIdentifier('1:/foo/bar.txt');
561  $targetParentFolder = GeneralUtility::makeInstance(ResourceFactory::class)->getFolderObjectFromCombinedIdentifier('1:/');
562  $subject->copyFile($fileToCopy, $targetParentFolder, null, $conflictMode);
563  $newFile = GeneralUtility::makeInstance(ResourceFactory::class)->getFileObjectFromCombinedIdentifier('1:/bar_01.txt');
564  self::assertInstanceOf(File::class, $newFile);
565  }
566 
570  public function ‪copyFileCopiesMetadata(): void
571  {
572  $this->importCSVDataSet(__DIR__ . '/../Fixtures/sys_file_storage.csv');
573  $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
574  $this->setUpBackendUser(1);
575  mkdir(‪Environment::getPublicPath() . '/fileadmin/foo');
576  file_put_contents(‪Environment::getPublicPath() . '/fileadmin/foo/bar.txt', 'Temp file');
577  $subject = GeneralUtility::makeInstance(StorageRepository::class)->findByUid(1);
578  $fileToCopyMetaData = [
579  'title' => 'Temp file title',
580  'description' => 'Temp file description',
581  ];
583  $fileToCopy = GeneralUtility::makeInstance(ResourceFactory::class)->getFileObjectFromCombinedIdentifier('1:/foo/bar.txt');
584  $fileToCopy->getMetaData()->add($fileToCopyMetaData);
585  $targetParentFolder = GeneralUtility::makeInstance(ResourceFactory::class)->getFolderObjectFromCombinedIdentifier('1:/');
587  $newFile = $subject->copyFile($fileToCopy, $targetParentFolder);
588  self::assertNotEquals($fileToCopy->getMetaData()->get()['file'], $newFile->getMetaData()->get()['file']);
589  self::assertNotEquals($fileToCopy->getMetaData()->get()['uid'], $newFile->getMetaData()->get()['uid']);
590  self::assertEquals($fileToCopyMetaData['title'], $newFile->getMetaData()->get()['title']);
591  self::assertEquals($fileToCopyMetaData['description'], $newFile->getMetaData()->get()['description']);
592  }
593 }
‪TYPO3\CMS\Core\Resource\Capabilities\CAPABILITY_PUBLIC
‪const CAPABILITY_PUBLIC
Definition: Capabilities.php:31
‪TYPO3\CMS\Core\Resource\DuplicationBehavior
Definition: DuplicationBehavior.php:24
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest
Definition: StorageRepositoryTest.php:37
‪TYPO3\CMS\Core\Resource\DuplicationBehavior\CANCEL
‪const CANCEL
Definition: DuplicationBehavior.php:46
‪TYPO3\CMS\Core\Resource\ResourceStorage\PROCESSING_FOLDER_LEVELS
‪const PROCESSING_FOLDER_LEVELS
Definition: ResourceStorage.php:210
‪TYPO3\CMS\Core\Tests\Functional\Resource
Definition: DefaultUploadFolderResolverTest.php:18
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\bestStorageIsResolved
‪bestStorageIsResolved(string $sourceIdentifier, string $expectedCombinedIdentifier)
Definition: StorageRepositoryTest.php:102
‪TYPO3\CMS\Core\Resource\Capabilities
Definition: Capabilities.php:23
‪TYPO3\CMS\Core\Resource\FolderInterface\ROLE_DEFAULT
‪const ROLE_DEFAULT
Definition: FolderInterface.php:28
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static getPublicPath()
Definition: Environment.php:187
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\copyFileCopiesMetadata
‪copyFileCopiesMetadata()
Definition: StorageRepositoryTest.php:570
‪TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException
Definition: ExistingTargetFileNameException.php:24
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\tearDown
‪tearDown()
Definition: StorageRepositoryTest.php:38
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\replaceFileFailsIfLocalFileDoesNotExist
‪replaceFileFailsIfLocalFileDoesNotExist()
Definition: StorageRepositoryTest.php:269
‪TYPO3\CMS\Core\Resource\Exception\InvalidTargetFolderException
Definition: InvalidTargetFolderException.php:24
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\isWithinFileMountBoundariesRespectsReadOnlyFileMounts
‪isWithinFileMountBoundariesRespectsReadOnlyFileMounts(string $targetDirectory, string $fileMountFolder, bool $isFileMountReadOnly, bool $checkWriteAccess, bool $expectedResult)
Definition: StorageRepositoryTest.php:218
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\getProcessingRootFolderTest
‪getProcessingRootFolderTest()
Definition: StorageRepositoryTest.php:241
‪TYPO3\CMS\Core\Type\Enumeration\cast
‪static static cast($value)
Definition: Enumeration.php:186
‪TYPO3\CMS\Core\Resource\Capabilities\CAPABILITY_BROWSABLE
‪const CAPABILITY_BROWSABLE
Definition: Capabilities.php:27
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\createFolderThrowsExceptionIfParentFolderDoesNotExist
‪createFolderThrowsExceptionIfParentFolderDoesNotExist()
Definition: StorageRepositoryTest.php:286
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\searchFilesFindsFilesInFolderDataProvider
‪static searchFilesFindsFilesInFolderDataProvider()
Definition: StorageRepositoryTest.php:331
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\getNestedProcessingFolderTest
‪getNestedProcessingFolderTest()
Definition: StorageRepositoryTest.php:143
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\copyFileGeneratesNewFileNameWhenFileAlreadyExistsInTargetFolderAndConflictModeIsRename
‪copyFileGeneratesNewFileNameWhenFileAlreadyExistsInTargetFolderAndConflictModeIsRename()
Definition: StorageRepositoryTest.php:550
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\searchFilesFindsFilesInFolder
‪searchFilesFindsFilesInFolder(string $searchTerm, ?string $searchFolder, bool $recursive, array $filters, array $expectedIdentifiers)
Definition: StorageRepositoryTest.php:458
‪TYPO3\CMS\Core\Resource\Search\FileSearchDemand
Definition: FileSearchDemand.php:26
‪TYPO3\CMS\Core\Resource\Folder
Definition: Folder.php:37
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:41
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\copyFolderGeneratesNewFolderNameWhenFolderAlreadyExistsInTargetFolderAndConflictModeIsRename
‪copyFolderGeneratesNewFolderNameWhenFolderAlreadyExistsInTargetFolderAndConflictModeIsRename()
Definition: StorageRepositoryTest.php:512
‪TYPO3\CMS\Core\Resource\StorageRepository
Definition: StorageRepository.php:38
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:26
‪TYPO3\CMS\Core\Resource\DuplicationBehavior\RENAME
‪const RENAME
Definition: DuplicationBehavior.php:32
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\copyFileThrowsErrorWhenFileWithSameNameAlreadyExistsInTargetFolderAndConflictModeIsCancel
‪copyFileThrowsErrorWhenFileWithSameNameAlreadyExistsInTargetFolderAndConflictModeIsCancel()
Definition: StorageRepositoryTest.php:530
‪TYPO3\CMS\Core\Resource\Capabilities\CAPABILITY_WRITABLE
‪const CAPABILITY_WRITABLE
Definition: Capabilities.php:36
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\bestStorageIsResolvedDataProvider
‪static bestStorageIsResolvedDataProvider()
Definition: StorageRepositoryTest.php:46
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\copyFolderThrowsErrorWhenFolderAlreadyExistsInTargetFolderAndConflictModeIsCancel
‪copyFolderThrowsErrorWhenFolderAlreadyExistsInTargetFolderAndConflictModeIsCancel()
Definition: StorageRepositoryTest.php:494
‪TYPO3\CMS\Core\Resource\ResourceStorage
Definition: ResourceStorage.php:127
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Core\Resource\FolderInterface
Definition: FolderInterface.php:24
‪TYPO3\CMS\Core\Utility\GeneralUtility\rmdir
‪static bool rmdir($path, $removeNonEmpty=false)
Definition: GeneralUtility.php:1691
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\deleteFileUnlinksFileIfNoRecyclerFolderAvailable
‪deleteFileUnlinksFileIfNoRecyclerFolderAvailable()
Definition: StorageRepositoryTest.php:318
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Core\Resource\Search\FileSearchDemand\createForSearchTerm
‪static createForSearchTerm(string $searchTerm)
Definition: FileSearchDemand.php:70
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:24
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\getRoleReturnsDefaultForRegularFolders
‪getRoleReturnsDefaultForRegularFolders()
Definition: StorageRepositoryTest.php:254
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\deleteFileMovesFileToRecyclerFolderIfAvailable
‪deleteFileMovesFileToRecyclerFolderIfAvailable()
Definition: StorageRepositoryTest.php:300
‪TYPO3\CMS\Core\Utility\StringUtility\getUniqueId
‪static getUniqueId(string $prefix='')
Definition: StringUtility.php:57
‪TYPO3\CMS\Core\Tests\Functional\Resource\StorageRepositoryTest\isWithinFileMountBoundariesDataProvider
‪static isWithinFileMountBoundariesDataProvider()
Definition: StorageRepositoryTest.php:166