[TASK] Deprecate $GLOBALS['TYPO3_LOADED_EXT']
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Tests / Unit / ContentObject / FilesContentObjectTest.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Frontend\Tests\Unit\ContentObject;
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
18 use TYPO3\CMS\Core\Package\PackageManager;
19 use TYPO3\CMS\Core\Resource\Collection\StaticFileCollection;
20 use TYPO3\CMS\Core\Resource\File;
21 use TYPO3\CMS\Core\Resource\FileCollectionRepository;
22 use TYPO3\CMS\Core\Resource\FileReference;
23 use TYPO3\CMS\Core\Resource\Folder;
24 use TYPO3\CMS\Core\Resource\ResourceFactory;
25 use TYPO3\CMS\Core\TypoScript\TemplateService;
26 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
27 use TYPO3\CMS\Frontend\ContentObject\FilesContentObject;
28 use TYPO3\CMS\Frontend\ContentObject\TextContentObject;
29 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
30 use TYPO3\CMS\Frontend\Resource\FileCollector;
31 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
32
33 /**
34 * Test case
35 */
36 class FilesContentObjectTest extends UnitTestCase
37 {
38
39 /**
40 * @var bool Reset singletons created by subject
41 */
42 protected $resetSingletonInstances = true;
43
44 /**
45 * @var \TYPO3\CMS\Frontend\ContentObject\FilesContentObject|\PHPUnit_Framework_MockObject_MockObject
46 */
47 protected $subject;
48
49 /**
50 * Set up
51 */
52 protected function setUp()
53 {
54 $GLOBALS['SIM_ACCESS_TIME'] = 0;
55 $packageManagerMock = $this->getMockBuilder(PackageManager::class)
56 ->disableOriginalConstructor()
57 ->getMock();
58 $templateService = $this->getMockBuilder(TemplateService::class)
59 ->setConstructorArgs([null, $packageManagerMock])
60 ->setMethods(['getFileName', 'linkData'])
61 ->getMock();
62 $tsfe = $this->getMockBuilder(TypoScriptFrontendController::class)
63 ->setMethods(['dummy'])
64 ->disableOriginalConstructor()
65 ->getMock();
66 $tsfe->tmpl = $templateService;
67
68 $contentObjectRenderer = new ContentObjectRenderer($tsfe);
69 $contentObjectRenderer->setContentObjectClassMap([
70 'FILES' => FilesContentObject::class,
71 'TEXT' => TextContentObject::class,
72 ]);
73 $this->subject = $this->getMockBuilder(FilesContentObject::class)
74 ->setMethods(['getFileCollector'])
75 ->setConstructorArgs([$contentObjectRenderer])
76 ->getMock();
77 }
78
79 /**
80 * @return array
81 */
82 public function renderReturnsFilesForFileReferencesDataProvider(): array
83 {
84 return [
85 'One file reference' => [
86 [
87 'references' => '1',
88 'renderObj' => 'TEXT',
89 'renderObj.' => [
90 'data' => 'file:current:name',
91 'wrap' => '<p>|</p>',
92 ],
93 ],
94 '<p>File 1</p>',
95 ],
96 'One file reference with begin higher than allowed' => [
97 [
98 'references' => '1',
99 'begin' => '1',
100 'renderObj' => 'TEXT',
101 'renderObj.' => [
102 'data' => 'file:current:name',
103 'wrap' => '<p>|</p>',
104 ],
105 ],
106 '',
107 ],
108 'One file reference with maxItems higher than allowed' => [
109 [
110 'references' => '1',
111 'maxItems' => '2',
112 'renderObj' => 'TEXT',
113 'renderObj.' => [
114 'data' => 'file:current:name',
115 'wrap' => '<p>|</p>',
116 ],
117 ],
118 '<p>File 1</p>',
119 ],
120 'Multiple file references' => [
121 [
122 'references' => '1,2,3',
123 'renderObj' => 'TEXT',
124 'renderObj.' => [
125 'data' => 'file:current:name',
126 'wrap' => '<p>|</p>',
127 ],
128 ],
129 '<p>File 1</p><p>File 2</p><p>File 3</p>',
130 ],
131 'Multiple file references with begin' => [
132 [
133 'references' => '1,2,3',
134 'begin' => '1',
135 'renderObj' => 'TEXT',
136 'renderObj.' => [
137 'data' => 'file:current:name',
138 'wrap' => '<p>|</p>',
139 ],
140 ],
141 '<p>File 2</p><p>File 3</p>',
142 ],
143 'Multiple file references with negative begin' => [
144 [
145 'references' => '1,2,3',
146 'begin' => '-1',
147 'renderObj' => 'TEXT',
148 'renderObj.' => [
149 'data' => 'file:current:name',
150 'wrap' => '<p>|</p>',
151 ],
152 ],
153 '<p>File 1</p><p>File 2</p><p>File 3</p>',
154 ],
155 'Multiple file references with maxItems' => [
156 [
157 'references' => '1,2,3',
158 'maxItems' => '2',
159 'renderObj' => 'TEXT',
160 'renderObj.' => [
161 'data' => 'file:current:name',
162 'wrap' => '<p>|</p>',
163 ],
164 ],
165 '<p>File 1</p><p>File 2</p>',
166 ],
167 'Multiple file references with negative maxItems' => [
168 [
169 'references' => '1,2,3',
170 'maxItems' => '-2',
171 'renderObj' => 'TEXT',
172 'renderObj.' => [
173 'data' => 'file:current:name',
174 'wrap' => '<p>|</p>',
175 ],
176 ],
177 '',
178 ],
179 'Multiple file references with begin and maxItems' => [
180 [
181 'references' => '1,2,3',
182 'begin' => '1',
183 'maxItems' => '1',
184 'renderObj' => 'TEXT',
185 'renderObj.' => [
186 'data' => 'file:current:name',
187 'wrap' => '<p>|</p>',
188 ],
189 ],
190 '<p>File 2</p>',
191 ],
192 'Multiple file references unsorted' => [
193 [
194 'references' => '1,3,2',
195 'renderObj' => 'TEXT',
196 'renderObj.' => [
197 'data' => 'file:current:name',
198 'wrap' => '<p>|</p>',
199 ],
200 ],
201 '<p>File 1</p><p>File 3</p><p>File 2</p>',
202 ],
203 'Multiple file references sorted by name' => [
204 [
205 'references' => '3,1,2',
206 'sorting' => 'name',
207 'renderObj' => 'TEXT',
208 'renderObj.' => [
209 'data' => 'file:current:name',
210 'wrap' => '<p>|</p>',
211 ],
212 ],
213 '<p>File 1</p><p>File 2</p><p>File 3</p>',
214 ],
215 ];
216 }
217
218 /**
219 * @test
220 * @dataProvider renderReturnsFilesForFileReferencesDataProvider
221 * @param array $configuration
222 * @param string $expected
223 */
224 public function renderReturnsFilesForFileReferences(array $configuration, string $expected): void
225 {
226 $fileReferenceMap = [];
227 for ($i = 1; $i < 4; $i++) {
228 $fileReference = $this->createMock(FileReference::class);
229 $fileReference->expects($this->any())
230 ->method('getName')
231 ->will($this->returnValue('File ' . $i));
232 $fileReference->expects($this->any())
233 ->method('hasProperty')
234 ->with('name')
235 ->will($this->returnValue(true));
236 $fileReference->expects($this->any())
237 ->method('getProperty')
238 ->with('name')
239 ->will($this->returnValue('File ' . $i));
240
241 $fileReferenceMap[] = [$i, $fileReference];
242 }
243
244 $fileRepository = $this->getMockBuilder(\TYPO3\CMS\Core\Resource\FileRepository::class)->getMock();
245 $fileRepository->expects($this->any())
246 ->method('findFileReferenceByUid')
247 ->will($this->returnValueMap($fileReferenceMap));
248 $fileCollector = $this->getMockBuilder(FileCollector::class)
249 ->setMethods(['getFileRepository'])
250 ->getMock();
251 $fileCollector->expects($this->any())
252 ->method('getFileRepository')
253 ->will($this->returnValue($fileRepository));
254
255 $this->subject->expects($this->any())
256 ->method('getFileCollector')
257 ->will($this->returnValue($fileCollector));
258
259 $this->assertSame($expected, $this->subject->render($configuration));
260 }
261
262 /**
263 * @return array
264 */
265 public function renderReturnsFilesForFilesDataProvider(): array
266 {
267 return [
268 'One file' => [
269 [
270 'files' => '1',
271 'renderObj' => 'TEXT',
272 'renderObj.' => [
273 'data' => 'file:current:name',
274 'wrap' => '<p>|</p>',
275 ],
276 ],
277 '<p>File 1</p>',
278 ],
279 'One file with begin higher than allowed' => [
280 [
281 'files' => '1',
282 'begin' => '1',
283 'renderObj' => 'TEXT',
284 'renderObj.' => [
285 'data' => 'file:current:name',
286 'wrap' => '<p>|</p>',
287 ],
288 ],
289 '',
290 ],
291 'One file with maxItems higher than allowed' => [
292 [
293 'files' => '1',
294 'maxItems' => '2',
295 'renderObj' => 'TEXT',
296 'renderObj.' => [
297 'data' => 'file:current:name',
298 'wrap' => '<p>|</p>',
299 ],
300 ],
301 '<p>File 1</p>',
302 ],
303 'Multiple files' => [
304 [
305 'files' => '1,2,3',
306 'renderObj' => 'TEXT',
307 'renderObj.' => [
308 'data' => 'file:current:name',
309 'wrap' => '<p>|</p>',
310 ],
311 ],
312 '<p>File 1</p><p>File 2</p><p>File 3</p>',
313 ],
314 'Multiple files with begin' => [
315 [
316 'files' => '1,2,3',
317 'begin' => '1',
318 'renderObj' => 'TEXT',
319 'renderObj.' => [
320 'data' => 'file:current:name',
321 'wrap' => '<p>|</p>',
322 ],
323 ],
324 '<p>File 2</p><p>File 3</p>',
325 ],
326 'Multiple files with negative begin' => [
327 [
328 'files' => '1,2,3',
329 'begin' => '-1',
330 'renderObj' => 'TEXT',
331 'renderObj.' => [
332 'data' => 'file:current:name',
333 'wrap' => '<p>|</p>',
334 ],
335 ],
336 '<p>File 1</p><p>File 2</p><p>File 3</p>',
337 ],
338 'Multiple files with maxItems' => [
339 [
340 'files' => '1,2,3',
341 'maxItems' => '2',
342 'renderObj' => 'TEXT',
343 'renderObj.' => [
344 'data' => 'file:current:name',
345 'wrap' => '<p>|</p>',
346 ],
347 ],
348 '<p>File 1</p><p>File 2</p>',
349 ],
350 'Multiple files with negative maxItems' => [
351 [
352 'files' => '1,2,3',
353 'maxItems' => '-2',
354 'renderObj' => 'TEXT',
355 'renderObj.' => [
356 'data' => 'file:current:name',
357 'wrap' => '<p>|</p>',
358 ],
359 ],
360 '',
361 ],
362 'Multiple files with begin and maxItems' => [
363 [
364 'files' => '1,2,3',
365 'begin' => '1',
366 'maxItems' => '1',
367 'renderObj' => 'TEXT',
368 'renderObj.' => [
369 'data' => 'file:current:name',
370 'wrap' => '<p>|</p>',
371 ],
372 ],
373 '<p>File 2</p>',
374 ],
375 'Multiple files unsorted' => [
376 [
377 'files' => '1,3,2',
378 'renderObj' => 'TEXT',
379 'renderObj.' => [
380 'data' => 'file:current:name',
381 'wrap' => '<p>|</p>',
382 ],
383 ],
384 '<p>File 1</p><p>File 3</p><p>File 2</p>',
385 ],
386 'Multiple files sorted by name' => [
387 [
388 'files' => '3,1,2',
389 'sorting' => 'name',
390 'renderObj' => 'TEXT',
391 'renderObj.' => [
392 'data' => 'file:current:name',
393 'wrap' => '<p>|</p>',
394 ],
395 ],
396 '<p>File 1</p><p>File 2</p><p>File 3</p>',
397 ],
398 ];
399 }
400
401 /**
402 * @test
403 * @dataProvider renderReturnsFilesForFilesDataProvider
404 * @param array $configuration
405 * @param string $expected
406 */
407 public function renderReturnsFilesForFiles(array $configuration, string $expected): void
408 {
409 $fileMap = [];
410 for ($i = 1; $i < 4; $i++) {
411 $file = $this->createMock(File::class);
412 $file->expects($this->any())
413 ->method('getName')
414 ->will($this->returnValue('File ' . $i));
415 $file->expects($this->any())
416 ->method('hasProperty')
417 ->with('name')
418 ->will($this->returnValue(true));
419 $file->expects($this->any())
420 ->method('getProperty')
421 ->with('name')
422 ->will($this->returnValue('File ' . $i));
423
424 $fileMap[] = [$i, [], $file];
425 }
426
427 $resourceFactory = $this->getMockBuilder(ResourceFactory::class)->getMock();
428 $resourceFactory->expects($this->any())
429 ->method('getFileObject')
430 ->will($this->returnValueMap($fileMap));
431 $fileCollector = $this->getMockBuilder(FileCollector::class)
432 ->setMethods(['getResourceFactory'])
433 ->getMock();
434 $fileCollector->expects($this->any())
435 ->method('getResourceFactory')
436 ->will($this->returnValue($resourceFactory));
437
438 $this->subject->expects($this->any())
439 ->method('getFileCollector')
440 ->will($this->returnValue($fileCollector));
441
442 $this->assertSame($expected, $this->subject->render($configuration));
443 }
444
445 /**
446 * @return array
447 */
448 public function renderReturnsFilesForCollectionsDataProvider(): array
449 {
450 return [
451 'One collection' => [
452 [
453 'collections' => '1',
454 'renderObj' => 'TEXT',
455 'renderObj.' => [
456 'data' => 'file:current:name',
457 'wrap' => '<p>|</p>',
458 ],
459 ],
460 '<p>File 1</p><p>File 2</p><p>File 3</p>',
461 ],
462 'One collection with begin' => [
463 [
464 'collections' => '1',
465 'begin' => '1',
466 'renderObj' => 'TEXT',
467 'renderObj.' => [
468 'data' => 'file:current:name',
469 'wrap' => '<p>|</p>',
470 ],
471 ],
472 '<p>File 2</p><p>File 3</p>',
473 ],
474 'One collection with begin higher than allowed' => [
475 [
476 'collections' => '1',
477 'begin' => '3',
478 'renderObj' => 'TEXT',
479 'renderObj.' => [
480 'data' => 'file:current:name',
481 'wrap' => '<p>|</p>',
482 ],
483 ],
484 '',
485 ],
486 'One collection with maxItems' => [
487 [
488 'collections' => '1',
489 'maxItems' => '2',
490 'renderObj' => 'TEXT',
491 'renderObj.' => [
492 'data' => 'file:current:name',
493 'wrap' => '<p>|</p>',
494 ],
495 ],
496 '<p>File 1</p><p>File 2</p>',
497 ],
498 'One collection with maxItems higher than allowed' => [
499 [
500 'collections' => '1',
501 'maxItems' => '4',
502 'renderObj' => 'TEXT',
503 'renderObj.' => [
504 'data' => 'file:current:name',
505 'wrap' => '<p>|</p>',
506 ],
507 ],
508 '<p>File 1</p><p>File 2</p><p>File 3</p>',
509 ],
510 'One collections with begin and maxItems' => [
511 [
512 'collections' => '1',
513 'begin' => '1',
514 'maxItems' => '1',
515 'renderObj' => 'TEXT',
516 'renderObj.' => [
517 'data' => 'file:current:name',
518 'wrap' => '<p>|</p>',
519 ],
520 ],
521 '<p>File 2</p>',
522 ],
523 'Multiple collections' => [
524 [
525 'collections' => '1,2,3',
526 'renderObj' => 'TEXT',
527 'renderObj.' => [
528 'data' => 'file:current:name',
529 'wrap' => '<p>|</p>',
530 ],
531 ],
532 '<p>File 1</p><p>File 2</p><p>File 3</p><p>File 4</p><p>File 5</p><p>File 6</p><p>File 7</p><p>File 8</p><p>File 9</p>',
533 ],
534 'Multiple collections with begin' => [
535 [
536 'collections' => '1,2,3',
537 'begin' => '3',
538 'renderObj' => 'TEXT',
539 'renderObj.' => [
540 'data' => 'file:current:name',
541 'wrap' => '<p>|</p>',
542 ],
543 ],
544 '<p>File 4</p><p>File 5</p><p>File 6</p><p>File 7</p><p>File 8</p><p>File 9</p>',
545 ],
546 'Multiple collections with negative begin' => [
547 [
548 'collections' => '1,2,3',
549 'begin' => '-3',
550 'renderObj' => 'TEXT',
551 'renderObj.' => [
552 'data' => 'file:current:name',
553 'wrap' => '<p>|</p>',
554 ],
555 ],
556 '<p>File 1</p><p>File 2</p><p>File 3</p><p>File 4</p><p>File 5</p><p>File 6</p><p>File 7</p><p>File 8</p><p>File 9</p>',
557 ],
558 'Multiple collections with maxItems' => [
559 [
560 'collections' => '1,2,3',
561 'maxItems' => '5',
562 'renderObj' => 'TEXT',
563 'renderObj.' => [
564 'data' => 'file:current:name',
565 'wrap' => '<p>|</p>',
566 ],
567 ],
568 '<p>File 1</p><p>File 2</p><p>File 3</p><p>File 4</p><p>File 5</p>',
569 ],
570 'Multiple collections with negative maxItems' => [
571 [
572 'collections' => '1,2,3',
573 'maxItems' => '-5',
574 'renderObj' => 'TEXT',
575 'renderObj.' => [
576 'data' => 'file:current:name',
577 'wrap' => '<p>|</p>',
578 ],
579 ],
580 '',
581 ],
582 'Multiple collections with begin and maxItems' => [
583 [
584 'collections' => '1,2,3',
585 'begin' => '4',
586 'maxItems' => '3',
587 'renderObj' => 'TEXT',
588 'renderObj.' => [
589 'data' => 'file:current:name',
590 'wrap' => '<p>|</p>',
591 ],
592 ],
593 '<p>File 5</p><p>File 6</p><p>File 7</p>',
594 ],
595 'Multiple collections unsorted' => [
596 [
597 'collections' => '1,3,2',
598 'renderObj' => 'TEXT',
599 'renderObj.' => [
600 'data' => 'file:current:name',
601 'wrap' => '<p>|</p>',
602 ],
603 ],
604 '<p>File 1</p><p>File 2</p><p>File 3</p><p>File 7</p><p>File 8</p><p>File 9</p><p>File 4</p><p>File 5</p><p>File 6</p>',
605 ],
606 'Multiple collections sorted by name' => [
607 [
608 'collections' => '3,1,2',
609 'sorting' => 'name',
610 'renderObj' => 'TEXT',
611 'renderObj.' => [
612 'data' => 'file:current:name',
613 'wrap' => '<p>|</p>',
614 ],
615 ],
616 '<p>File 1</p><p>File 2</p><p>File 3</p><p>File 4</p><p>File 5</p><p>File 6</p><p>File 7</p><p>File 8</p><p>File 9</p>',
617 ],
618 ];
619 }
620
621 /**
622 * @test
623 * @dataProvider renderReturnsFilesForCollectionsDataProvider
624 * @param array $configuration
625 * @param string $expected
626 */
627 public function renderReturnsFilesForCollections(array $configuration, string $expected): void
628 {
629 $collectionMap = [];
630 $fileCount = 1;
631 for ($i = 1; $i < 4; $i++) {
632 $fileReferenceArray = [];
633 for ($j = 1; $j < 4; $j++) {
634 $fileReference = $this->createMock(FileReference::class);
635 $fileReference->expects($this->any())
636 ->method('getName')
637 ->will($this->returnValue('File ' . $fileCount));
638 $fileReference->expects($this->any())
639 ->method('hasProperty')
640 ->with('name')
641 ->will($this->returnValue(true));
642 $fileReference->expects($this->any())
643 ->method('getProperty')
644 ->with('name')
645 ->will($this->returnValue('File ' . $fileCount));
646
647 $fileReferenceArray[] = $fileReference;
648 $fileCount++;
649 }
650
651 $collection = $this->createMock(StaticFileCollection::class);
652 $collection->expects($this->any())
653 ->method('getItems')
654 ->will($this->returnValue($fileReferenceArray));
655
656 $collectionMap[] = [$i, $collection];
657 }
658
659 $collectionRepository = $this->getMockBuilder(FileCollectionRepository::class)->getMock();
660 $collectionRepository->expects($this->any())
661 ->method('findByUid')
662 ->will($this->returnValueMap($collectionMap));
663 $fileCollector = $this->getMockBuilder(FileCollector::class)
664 ->setMethods(['getFileCollectionRepository'])
665 ->getMock();
666 $fileCollector->expects($this->any())
667 ->method('getFileCollectionRepository')
668 ->will($this->returnValue($collectionRepository));
669 $this->subject->expects($this->any())
670 ->method('getFileCollector')
671 ->will($this->returnValue($fileCollector));
672
673 $this->assertSame($expected, $this->subject->render($configuration));
674 }
675
676 /**
677 * @return array
678 */
679 public function renderReturnsFilesForFoldersDataProvider(): array
680 {
681 return [
682 'One folder' => [
683 [
684 'folders' => '1:myfolder/',
685 'renderObj' => 'TEXT',
686 'renderObj.' => [
687 'data' => 'file:current:name',
688 'wrap' => '<p>|</p>',
689 ],
690 ],
691 '<p>File 1</p><p>File 2</p><p>File 3</p>',
692 ],
693 'One folder with begin' => [
694 [
695 'folders' => '1:myfolder/',
696 'begin' => '1',
697 'renderObj' => 'TEXT',
698 'renderObj.' => [
699 'data' => 'file:current:name',
700 'wrap' => '<p>|</p>',
701 ],
702 ],
703 '<p>File 2</p><p>File 3</p>',
704 ],
705 'One folder with begin higher than allowed' => [
706 [
707 'folders' => '1:myfolder/',
708 'begin' => '3',
709 'renderObj' => 'TEXT',
710 'renderObj.' => [
711 'data' => 'file:current:name',
712 'wrap' => '<p>|</p>',
713 ],
714 ],
715 '',
716 ],
717 'One folder with maxItems' => [
718 [
719 'folders' => '1:myfolder/',
720 'maxItems' => '2',
721 'renderObj' => 'TEXT',
722 'renderObj.' => [
723 'data' => 'file:current:name',
724 'wrap' => '<p>|</p>',
725 ],
726 ],
727 '<p>File 1</p><p>File 2</p>',
728 ],
729 'One folder with maxItems higher than allowed' => [
730 [
731 'folders' => '1:myfolder/',
732 'maxItems' => '4',
733 'renderObj' => 'TEXT',
734 'renderObj.' => [
735 'data' => 'file:current:name',
736 'wrap' => '<p>|</p>',
737 ],
738 ],
739 '<p>File 1</p><p>File 2</p><p>File 3</p>',
740 ],
741 'One folder with begin and maxItems' => [
742 [
743 'folders' => '1:myfolder/',
744 'begin' => '1',
745 'maxItems' => '1',
746 'renderObj' => 'TEXT',
747 'renderObj.' => [
748 'data' => 'file:current:name',
749 'wrap' => '<p>|</p>',
750 ],
751 ],
752 '<p>File 2</p>',
753 ],
754 'Multiple folders' => [
755 [
756 'folders' => '1:myfolder/,2:myfolder/,3:myfolder/',
757 'renderObj' => 'TEXT',
758 'renderObj.' => [
759 'data' => 'file:current:name',
760 'wrap' => '<p>|</p>',
761 ],
762 ],
763 '<p>File 1</p><p>File 2</p><p>File 3</p><p>File 4</p><p>File 5</p><p>File 6</p><p>File 7</p><p>File 8</p><p>File 9</p>',
764 ],
765 'Multiple folders with begin' => [
766 [
767 'folders' => '1:myfolder/,2:myfolder/,3:myfolder/',
768 'begin' => '3',
769 'renderObj' => 'TEXT',
770 'renderObj.' => [
771 'data' => 'file:current:name',
772 'wrap' => '<p>|</p>',
773 ],
774 ],
775 '<p>File 4</p><p>File 5</p><p>File 6</p><p>File 7</p><p>File 8</p><p>File 9</p>',
776 ],
777 'Multiple folders with negative begin' => [
778 [
779 'folders' => '1:myfolder/,2:myfolder/,3:myfolder/',
780 'begin' => '-3',
781 'renderObj' => 'TEXT',
782 'renderObj.' => [
783 'data' => 'file:current:name',
784 'wrap' => '<p>|</p>',
785 ],
786 ],
787 '<p>File 1</p><p>File 2</p><p>File 3</p><p>File 4</p><p>File 5</p><p>File 6</p><p>File 7</p><p>File 8</p><p>File 9</p>',
788 ],
789 'Multiple folders with maxItems' => [
790 [
791 'folders' => '1:myfolder/,2:myfolder/,3:myfolder/',
792 'maxItems' => '5',
793 'renderObj' => 'TEXT',
794 'renderObj.' => [
795 'data' => 'file:current:name',
796 'wrap' => '<p>|</p>',
797 ],
798 ],
799 '<p>File 1</p><p>File 2</p><p>File 3</p><p>File 4</p><p>File 5</p>',
800 ],
801 'Multiple folders with negative maxItems' => [
802 [
803 'folders' => '1:myfolder/,2:myfolder/,3:myfolder/',
804 'maxItems' => '-5',
805 'renderObj' => 'TEXT',
806 'renderObj.' => [
807 'data' => 'file:current:name',
808 'wrap' => '<p>|</p>',
809 ],
810 ],
811 '',
812 ],
813 'Multiple folders with begin and maxItems' => [
814 [
815 'folders' => '1:myfolder/,2:myfolder/,3:myfolder/',
816 'begin' => '4',
817 'maxItems' => '3',
818 'renderObj' => 'TEXT',
819 'renderObj.' => [
820 'data' => 'file:current:name',
821 'wrap' => '<p>|</p>',
822 ],
823 ],
824 '<p>File 5</p><p>File 6</p><p>File 7</p>',
825 ],
826 'Multiple folders unsorted' => [
827 [
828 'folders' => '1:myfolder/,3:myfolder/,2:myfolder/',
829 'renderObj' => 'TEXT',
830 'renderObj.' => [
831 'data' => 'file:current:name',
832 'wrap' => '<p>|</p>',
833 ],
834 ],
835 '<p>File 1</p><p>File 2</p><p>File 3</p><p>File 7</p><p>File 8</p><p>File 9</p><p>File 4</p><p>File 5</p><p>File 6</p>',
836 ],
837 'Multiple folders sorted by name' => [
838 [
839 'folders' => '3:myfolder/,1:myfolder/,2:myfolder/',
840 'sorting' => 'name',
841 'renderObj' => 'TEXT',
842 'renderObj.' => [
843 'data' => 'file:current:name',
844 'wrap' => '<p>|</p>',
845 ],
846 ],
847 '<p>File 1</p><p>File 2</p><p>File 3</p><p>File 4</p><p>File 5</p><p>File 6</p><p>File 7</p><p>File 8</p><p>File 9</p>',
848 ],
849 'Multiple folders recursively' => [
850 [
851 'folders' => '1:myfolder/',
852 'folders.' => [
853 'recursive' => '1'
854 ],
855 'renderObj' => 'TEXT',
856 'renderObj.' => [
857 'data' => 'file:current:name',
858 'wrap' => '<p>|</p>',
859 ],
860 ],
861 '<p>File 7</p><p>File 8</p><p>File 9</p><p>File 1</p><p>File 2</p><p>File 3</p><p>File 4</p><p>File 5</p><p>File 6</p>',
862 true
863 ],
864 'Multiple folders recursively, sorted by name' => [
865 [
866 'folders' => '1:myfolder/',
867 'folders.' => [
868 'recursive' => '1'
869 ],
870 'sorting' => 'name',
871 'renderObj' => 'TEXT',
872 'renderObj.' => [
873 'data' => 'file:current:name',
874 'wrap' => '<p>|</p>',
875 ],
876 ],
877 '<p>File 1</p><p>File 2</p><p>File 3</p><p>File 4</p><p>File 5</p><p>File 6</p><p>File 7</p><p>File 8</p><p>File 9</p>',
878 true
879 ],
880 ];
881 }
882
883 /**
884 * @test
885 * @dataProvider renderReturnsFilesForFoldersDataProvider
886 * @param array $configuration
887 * @param string $expected
888 * @param bool $recursive
889 */
890 public function renderReturnsFilesForFolders(array $configuration, string $expected, bool $recursive = false): void
891 {
892 $folderMap = [];
893 $folders = [];
894 $fileCount = 1;
895 $filesArrayForFolder = [];
896 for ($i = 1; $i < 4; $i++) {
897 $filesArrayForFolder[$i] = [];
898 for ($j = 1; $j < 4; $j++) {
899 $file = $this->createMock(File::class);
900 $file->expects($this->any())
901 ->method('getName')
902 ->will($this->returnValue('File ' . $fileCount));
903 $file->expects($this->any())
904 ->method('hasProperty')
905 ->with('name')
906 ->will($this->returnValue(true));
907 $file->expects($this->any())
908 ->method('getProperty')
909 ->with('name')
910 ->will($this->returnValue('File ' . $fileCount));
911
912 $filesArrayForFolder[$i][] = $file;
913 $fileCount++;
914 }
915
916 $folder = $this->createMock(Folder::class);
917
918 if ($recursive) {
919 if ($i < 3) {
920 $folders[$i] = $folder;
921 $folderMap[$i] = ['1:myfolder/mysubfolder-' . $i . '/', $folder];
922 } else {
923 $folder->expects($this->any())
924 ->method('getSubfolders')
925 ->will($this->returnValue($folders));
926 $folderMap[$i] = ['1:myfolder/', $folder];
927 }
928 } else {
929 $folderMap[$i] = [$i . ':myfolder/', $folder];
930 }
931 }
932 foreach ($folderMap as $i => $folderMapInfo) {
933 if ($i < 3 || !$recursive) {
934 $folderMapInfo[1]->expects($this->any())
935 ->method('getFiles')
936 ->will($this->returnValue($filesArrayForFolder[$i]));
937 } else {
938 $recursiveFiles = array_merge(
939 $filesArrayForFolder[3],
940 $filesArrayForFolder[1],
941 $filesArrayForFolder[2]
942 );
943 $folderMapInfo[1]->expects($this->any())
944 ->method('getFiles')
945 ->will($this->returnValue($recursiveFiles));
946 }
947 }
948
949 $resourceFactory = $this->getMockBuilder(ResourceFactory::class)->getMock();
950 $resourceFactory->expects($this->any())
951 ->method('getFolderObjectFromCombinedIdentifier')
952 ->will($this->returnValueMap($folderMap));
953 $fileCollector = $this->getMockBuilder(FileCollector::class)
954 ->setMethods(['getResourceFactory'])
955 ->getMock();
956 $fileCollector->expects($this->any())
957 ->method('getResourceFactory')
958 ->will($this->returnValue($resourceFactory));
959
960 $this->subject->expects($this->any())
961 ->method('getFileCollector')
962 ->will($this->returnValue($fileCollector));
963
964 $this->assertSame($expected, $this->subject->render($configuration));
965 }
966 }