d26ab527649920d1c13ffc123269676613d1480a
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Tests / Unit / Mvc / Persistence / FormPersistenceManagerTest.php
1 <?php
2 namespace TYPO3\CMS\Form\Tests\Unit\Mvc\Persistence;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Resource\File;
18 use TYPO3\CMS\Core\Resource\ResourceStorage;
19 use TYPO3\CMS\Core\Resource\StorageRepository;
20 use TYPO3\CMS\Form\Mvc\Persistence\Exception\NoUniqueIdentifierException;
21 use TYPO3\CMS\Form\Mvc\Persistence\Exception\PersistenceManagerException;
22 use TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager;
23
24 /**
25 * Test case
26 */
27 class FormPersistenceManagerTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
28 {
29 /**
30 * Subject is not notice free, disable E_NOTICES
31 */
32 protected static $suppressNotices = true;
33
34 /**
35 * @test
36 */
37 public function loadThrowsExceptionIfPersistenceIdentifierHasNoYamlExtension()
38 {
39 $this->expectException(PersistenceManagerException::class);
40 $this->expectExceptionCode(1477679819);
41
42 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
43 'dummy'
44 ], [], '', false);
45
46 $input = '-1:/user_uploads/_example.php';
47 $mockFormPersistenceManager->_call('load', $input);
48 }
49
50 /**
51 * @test
52 */
53 public function loadThrowsExceptionIfPersistenceIdentifierIsAExtensionLocationWhichIsNotAllowed()
54 {
55 $this->expectException(PersistenceManagerException::class);
56 $this->expectExceptionCode(1484071985);
57
58 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
59 'dummy'
60 ], [], '', false);
61
62 $mockFormPersistenceManager->_set('formSettings', [
63 'persistenceManager' => [
64 'allowedExtensionPaths' => [],
65 ],
66 ]);
67
68 $input = 'EXT:form/Resources/Forms/_example.yaml';
69 $mockFormPersistenceManager->_call('load', $input);
70 }
71
72 /**
73 * @test
74 */
75 public function saveThrowsExceptionIfPersistenceIdentifierHasNoYamlExtension()
76 {
77 $this->expectException(PersistenceManagerException::class);
78 $this->expectExceptionCode(1477679820);
79
80 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
81 'dummy'
82 ], [], '', false);
83
84 $input = '-1:/user_uploads/_example.php';
85 $mockFormPersistenceManager->_call('save', $input, []);
86 }
87
88 /**
89 * @test
90 */
91 public function saveThrowsExceptionIfPersistenceIdentifierIsAExtensionLocationAndSaveToExtensionLocationIsNotAllowed()
92 {
93 $this->expectException(PersistenceManagerException::class);
94 $this->expectExceptionCode(1477680881);
95
96 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
97 'dummy'
98 ], [], '', false);
99
100 $mockFormPersistenceManager->_set('formSettings', [
101 'persistenceManager' => [
102 'allowSaveToExtensionPaths' => false,
103 ],
104 ]);
105
106 $input = 'EXT:form/Resources/Forms/_example.yaml';
107 $mockFormPersistenceManager->_call('save', $input, []);
108 }
109
110 /**
111 * @test
112 */
113 public function saveThrowsExceptionIfPersistenceIdentifierIsAExtensionLocationWhichIsNotAllowed()
114 {
115 $this->expectException(PersistenceManagerException::class);
116 $this->expectExceptionCode(1484073571);
117
118 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
119 'dummy'
120 ], [], '', false);
121
122 $mockFormPersistenceManager->_set('formSettings', [
123 'persistenceManager' => [
124 'allowSaveToExtensionPaths' => true,
125 'allowedExtensionPaths' => [],
126 ],
127 ]);
128
129 $input = 'EXT:form/Resources/Forms/_example.yaml';
130 $mockFormPersistenceManager->_call('save', $input, []);
131 }
132
133 /**
134 * @test
135 */
136 public function deleteThrowsExceptionIfPersistenceIdentifierHasNoYamlExtension()
137 {
138 $this->expectException(PersistenceManagerException::class);
139 $this->expectExceptionCode(1472239534);
140
141 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
142 'dummy'
143 ], [], '', false);
144
145 $input = '-1:/user_uploads/_example.php';
146 $mockFormPersistenceManager->_call('delete', $input);
147 }
148
149 /**
150 * @test
151 */
152 public function deleteThrowsExceptionIfPersistenceIdentifierFileDoesNotExists()
153 {
154 $this->expectException(PersistenceManagerException::class);
155 $this->expectExceptionCode(1472239535);
156
157 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
158 'exists'
159 ], [], '', false);
160
161 $mockFormPersistenceManager
162 ->expects($this->any())
163 ->method('exists')
164 ->willReturn(false);
165
166 $input = '-1:/user_uploads/_example.yaml';
167 $mockFormPersistenceManager->_call('delete', $input);
168 }
169
170 /**
171 * @test
172 */
173 public function deleteThrowsExceptionIfPersistenceIdentifierIsExtensionLocationAndDeleteFromExtensionLocationsIsNotAllowed()
174 {
175 $this->expectException(PersistenceManagerException::class);
176 $this->expectExceptionCode(1472239536);
177
178 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
179 'exists'
180 ], [], '', false);
181
182 $mockFormPersistenceManager
183 ->expects($this->any())
184 ->method('exists')
185 ->willReturn(true);
186
187 $mockFormPersistenceManager->_set('formSettings', [
188 'persistenceManager' => [
189 'allowDeleteFromExtensionPaths' => false,
190 ],
191 ]);
192
193 $input = 'EXT:form/Resources/Forms/_example.yaml';
194 $mockFormPersistenceManager->_call('delete', $input);
195 }
196
197 /**
198 * @test
199 */
200 public function deleteThrowsExceptionIfPersistenceIdentifierIsExtensionLocationWhichIsNotAllowed()
201 {
202 $this->expectException(PersistenceManagerException::class);
203 $this->expectExceptionCode(1484073878);
204
205 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
206 'exists'
207 ], [], '', false);
208
209 $mockFormPersistenceManager
210 ->expects($this->any())
211 ->method('exists')
212 ->willReturn(true);
213
214 $mockFormPersistenceManager->_set('formSettings', [
215 'persistenceManager' => [
216 'allowDeleteFromExtensionPaths' => true,
217 'allowedExtensionPaths' => [],
218 ],
219 ]);
220
221 $input = 'EXT:form/Resources/Forms/_example.yaml';
222 $mockFormPersistenceManager->_call('delete', $input);
223 }
224
225 /**
226 * @test
227 */
228 public function deleteThrowsExceptionIfPersistenceIdentifierIsStorageLocationAndDeleteFromStorageIsNotAllowed()
229 {
230 $this->expectException(PersistenceManagerException::class);
231 $this->expectExceptionCode(1472239516);
232
233 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
234 'getStorageByUid',
235 'exists'
236 ], [], '', false);
237
238 $mockStorage = $this->getMockBuilder(ResourceStorage::class)
239 ->disableOriginalConstructor()
240 ->getMock();
241
242 $mockStorage
243 ->expects($this->any())
244 ->method('checkFileActionPermission')
245 ->willReturn(false);
246
247 $file = new File(['identifier' => '', 'mime_type' => ''], $mockStorage);
248 $mockStorage
249 ->expects($this->any())
250 ->method('getFile')
251 ->willReturn($file);
252
253 $mockFormPersistenceManager
254 ->expects($this->any())
255 ->method('getStorageByUid')
256 ->willReturn($mockStorage);
257
258 $mockFormPersistenceManager
259 ->expects($this->any())
260 ->method('exists')
261 ->willReturn(true);
262
263 $input = '-1:/user_uploads/_example.yaml';
264 $mockFormPersistenceManager->_call('delete', $input);
265 }
266
267 /**
268 * @test
269 */
270 public function existsReturnsTrueIfPersistenceIdentifierIsExtensionLocationAndFileExistsAndFileHasYamlExtension()
271 {
272 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
273 'dummy'
274 ], [], '', false);
275
276 $mockFormPersistenceManager->_set('formSettings', [
277 'persistenceManager' => [
278 'allowedExtensionPaths' => [
279 'EXT:form/Tests/Unit/Mvc/Persistence/Fixtures/'
280 ],
281 ],
282 ]);
283
284 $input = 'EXT:form/Tests/Unit/Mvc/Persistence/Fixtures/BlankForm.yaml';
285 $this->assertTrue($mockFormPersistenceManager->_call('exists', $input));
286 }
287
288 /**
289 * @test
290 */
291 public function existsReturnsFalseIfPersistenceIdentifierIsExtensionLocationAndFileExistsAndFileHasNoYamlExtension()
292 {
293 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
294 'dummy'
295 ], [], '', false);
296
297 $input = 'EXT:form/Tests/Unit/Mvc/Persistence/Fixtures/BlankForm.txt';
298 $this->assertFalse($mockFormPersistenceManager->_call('exists', $input));
299 }
300
301 /**
302 * @test
303 */
304 public function existsReturnsFalseIfPersistenceIdentifierIsExtensionLocationAndFileExistsAndExtensionLocationIsNotAllowed()
305 {
306 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
307 'dummy'
308 ], [], '', false);
309
310 $mockFormPersistenceManager->_set('formSettings', [
311 'persistenceManager' => [
312 'allowedExtensionPaths' => [],
313 ],
314 ]);
315
316 $input = 'EXT:form/Tests/Unit/Mvc/Persistence/Fixtures/BlankForm.yaml';
317 $this->assertFalse($mockFormPersistenceManager->_call('exists', $input));
318 }
319
320 /**
321 * @test
322 */
323 public function existsReturnsFalseIfPersistenceIdentifierIsExtensionLocationAndFileNotExistsAndFileHasYamlExtension()
324 {
325 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
326 'dummy'
327 ], [], '', false);
328
329 $input = 'EXT:form/Tests/Unit/Mvc/Persistence/Fixtures/_BlankForm.yaml';
330 $this->assertFalse($mockFormPersistenceManager->_call('exists', $input));
331 }
332
333 /**
334 * @test
335 */
336 public function existsReturnsTrueIfPersistenceIdentifierIsStorageLocationAndFileExistsAndFileHasYamlExtension()
337 {
338 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
339 'getStorageByUid'
340 ], [], '', false);
341
342 $mockStorage = $this->getMockBuilder(ResourceStorage::class)
343 ->disableOriginalConstructor()
344 ->getMock();
345 $mockStorage
346 ->expects($this->any())
347 ->method('hasFile')
348 ->willReturn(true);
349
350 $mockFormPersistenceManager
351 ->expects($this->any())
352 ->method('getStorageByUid')
353 ->willReturn($mockStorage);
354
355 $input = '-1:/user_uploads/_example.yaml';
356 $this->assertTrue($mockFormPersistenceManager->_call('exists', $input));
357 }
358
359 /**
360 * @test
361 */
362 public function existsReturnsFalseIfPersistenceIdentifierIsStorageLocationAndFileExistsAndFileNoYamlExtension()
363 {
364 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
365 'getStorageByUid'
366 ], [], '', false);
367
368 $mockStorage = $this->getMockBuilder(ResourceStorage::class)
369 ->disableOriginalConstructor()
370 ->getMock();
371 $mockStorage
372 ->expects($this->any())
373 ->method('hasFile')
374 ->willReturn(true);
375
376 $mockFormPersistenceManager
377 ->expects($this->any())
378 ->method('getStorageByUid')
379 ->willReturn($mockStorage);
380
381 $input = '-1:/user_uploads/_example.php';
382 $this->assertFalse($mockFormPersistenceManager->_call('exists', $input));
383 }
384
385 /**
386 * @test
387 */
388 public function existsReturnsFalseIfPersistenceIdentifierIsStorageLocationAndFileNotExistsAndFileHasYamlExtension()
389 {
390 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
391 'getStorageByUid'
392 ], [], '', false);
393
394 $mockStorage = $this->getMockBuilder(ResourceStorage::class)
395 ->disableOriginalConstructor()
396 ->getMock();
397 $mockStorage
398 ->expects($this->any())
399 ->method('hasFile')
400 ->willReturn(false);
401
402 $mockFormPersistenceManager
403 ->expects($this->any())
404 ->method('getStorageByUid')
405 ->willReturn($mockStorage);
406
407 $input = '-1:/user_uploads/_example.yaml';
408 $this->assertFalse($mockFormPersistenceManager->_call('exists', $input));
409 }
410
411 /**
412 * @test
413 */
414 public function getUniquePersistenceIdentifierAppendNumberIfPersistenceIdentifierExists()
415 {
416 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
417 'exists'
418 ], [], '', false);
419
420 $mockFormPersistenceManager
421 ->expects($this->at(0))
422 ->method('exists')
423 ->willReturn(true);
424
425 $mockFormPersistenceManager
426 ->expects($this->at(1))
427 ->method('exists')
428 ->willReturn(true);
429
430 $mockFormPersistenceManager
431 ->expects($this->at(2))
432 ->method('exists')
433 ->willReturn(false);
434
435 $input = 'example';
436 $expected = '-1:/user_uploads/example_2.yaml';
437 $this->assertSame($expected, $mockFormPersistenceManager->_call('getUniquePersistenceIdentifier', $input, '-1:/user_uploads/'));
438 }
439
440 /**
441 * @test
442 */
443 public function getUniquePersistenceIdentifierAppendTimestampIfPersistenceIdentifierExists()
444 {
445 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
446 'exists'
447 ], [], '', false);
448
449 for ($attempts = 0; $attempts <= 99; $attempts++) {
450 $mockFormPersistenceManager
451 ->expects($this->at($attempts))
452 ->method('exists')
453 ->willReturn(true);
454 }
455
456 $mockFormPersistenceManager
457 ->expects($this->at(100))
458 ->method('exists')
459 ->willReturn(false);
460
461 $input = 'example';
462 $expected = '#^-1:/user_uploads/example_([0-9]{10}).yaml$#';
463
464 $returnValue = $mockFormPersistenceManager->_call('getUniquePersistenceIdentifier', $input, '-1:/user_uploads/');
465 $this->assertEquals(1, preg_match($expected, $returnValue));
466 }
467
468 /**
469 * @test
470 */
471 public function getUniqueIdentifierThrowsExceptionIfIdentifierExists()
472 {
473 $this->expectException(NoUniqueIdentifierException::class);
474 $this->expectExceptionCode(1477688567);
475
476 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
477 'checkForDuplicateIdentifier'
478 ], [], '', false);
479
480 $mockFormPersistenceManager
481 ->expects($this->any())
482 ->method('checkForDuplicateIdentifier')
483 ->willReturn(true);
484
485 $input = 'example';
486 $mockFormPersistenceManager->_call('getUniqueIdentifier', $input);
487 }
488
489 /**
490 * @test
491 */
492 public function getUniqueIdentifierAppendTimestampIfIdentifierExists()
493 {
494 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
495 'checkForDuplicateIdentifier'
496 ], [], '', false);
497
498 for ($attempts = 0; $attempts <= 99; $attempts++) {
499 $mockFormPersistenceManager
500 ->expects($this->at($attempts))
501 ->method('checkForDuplicateIdentifier')
502 ->willReturn(true);
503 }
504
505 $mockFormPersistenceManager
506 ->expects($this->at(100))
507 ->method('checkForDuplicateIdentifier')
508 ->willReturn(false);
509
510 $input = 'example';
511 $expected = '#^example_([0-9]{10})$#';
512
513 $returnValue = $mockFormPersistenceManager->_call('getUniqueIdentifier', $input);
514 $this->assertEquals(1, preg_match($expected, $returnValue));
515 }
516
517 /**
518 * @test
519 */
520 public function checkForDuplicateIdentifierReturnsTrueIfIdentifierIsUsed()
521 {
522 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
523 'listForms'
524 ], [], '', false);
525
526 $mockFormPersistenceManager
527 ->expects($this->at($attempts))
528 ->method('listForms')
529 ->willReturn([
530 0 => [
531 'identifier' => 'example',
532 ],
533 ]);
534
535 $input = 'example';
536 $this->assertTrue($mockFormPersistenceManager->_call('checkForDuplicateIdentifier', $input));
537 }
538
539 /**
540 * @test
541 */
542 public function checkForDuplicateIdentifierReturnsFalseIfIdentifierIsUsed()
543 {
544 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
545 'listForms'
546 ], [], '', false);
547
548 $mockFormPersistenceManager
549 ->expects($this->at($attempts))
550 ->method('listForms')
551 ->willReturn([
552 0 => [
553 'identifier' => 'example',
554 ],
555 ]);
556
557 $input = 'other-example';
558 $this->assertFalse($mockFormPersistenceManager->_call('checkForDuplicateIdentifier', $input));
559 }
560
561 /**
562 * @test
563 */
564 public function getFileByIdentifierThrowsExceptionIfReadFromStorageIsNotAllowed()
565 {
566 $this->expectException(PersistenceManagerException::class);
567 $this->expectExceptionCode(1471630578);
568
569 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
570 'getStorageByUid',
571 ], [], '', false);
572
573 $mockStorage = $this->getMockBuilder(ResourceStorage::class)
574 ->disableOriginalConstructor()
575 ->getMock();
576
577 $mockStorage
578 ->expects($this->any())
579 ->method('checkFileActionPermission')
580 ->willReturn(false);
581
582 $file = new File(['identifier' => '', 'mime_type' => ''], $mockStorage);
583 $mockStorage
584 ->expects($this->any())
585 ->method('getFile')
586 ->willReturn($file);
587
588 $mockFormPersistenceManager
589 ->expects($this->any())
590 ->method('getStorageByUid')
591 ->willReturn($mockStorage);
592
593 $input = '-1:/user_uploads/example.yaml';
594 $mockFormPersistenceManager->_call('getFileByIdentifier', $input);
595 }
596
597 /**
598 * @test
599 */
600 public function getOrCreateFileThrowsExceptionIfFolderNotExistsInStorage()
601 {
602 $this->expectException(PersistenceManagerException::class);
603 $this->expectExceptionCode(1471630579);
604
605 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
606 'getStorageByUid',
607 ], [], '', false);
608
609 $mockStorage = $this->getMockBuilder(ResourceStorage::class)
610 ->disableOriginalConstructor()
611 ->getMock();
612
613 $mockStorage
614 ->expects($this->any())
615 ->method('hasFolder')
616 ->willReturn(false);
617
618 $mockFormPersistenceManager
619 ->expects($this->any())
620 ->method('getStorageByUid')
621 ->willReturn($mockStorage);
622
623 $input = '-1:/user_uploads/example.yaml';
624 $mockFormPersistenceManager->_call('getOrCreateFile', $input);
625 }
626
627 /**
628 * @test
629 */
630 public function getOrCreateFileThrowsExceptionIfWriteToStorageIsNotAllowed()
631 {
632 $this->expectException(PersistenceManagerException::class);
633 $this->expectExceptionCode(1471630580);
634
635 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
636 'getStorageByUid',
637 ], [], '', false);
638
639 $mockStorage = $this->getMockBuilder(ResourceStorage::class)
640 ->disableOriginalConstructor()
641 ->getMock();
642
643 $mockStorage
644 ->expects($this->any())
645 ->method('hasFolder')
646 ->willReturn(true);
647
648 $mockStorage
649 ->expects($this->any())
650 ->method('checkFileActionPermission')
651 ->willReturn(false);
652
653 $file = new File(['identifier' => '', 'mime_type' => ''], $mockStorage);
654 $mockStorage
655 ->expects($this->any())
656 ->method('getFile')
657 ->willReturn($file);
658
659 $mockFormPersistenceManager
660 ->expects($this->any())
661 ->method('getStorageByUid')
662 ->willReturn($mockStorage);
663
664 $input = '-1:/user_uploads/example.yaml';
665 $mockFormPersistenceManager->_call('getOrCreateFile', $input);
666 }
667
668 /**
669 * @test
670 */
671 public function getStorageByUidThrowsExceptionIfStorageNotExists()
672 {
673 $this->expectException(PersistenceManagerException::class);
674 $this->expectExceptionCode(1471630581);
675
676 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
677 'dummy',
678 ], [], '', false);
679
680 $mockStorageRepository = $this->getMockBuilder(StorageRepository::class)
681 ->disableOriginalConstructor()
682 ->getMock();
683
684 $mockStorageRepository
685 ->expects($this->any())
686 ->method('findByUid')
687 ->willReturn(null);
688
689 $mockFormPersistenceManager->_set('storageRepository', $mockStorageRepository);
690 $mockFormPersistenceManager->_call('getStorageByUid', -1);
691 }
692
693 /**
694 * @test
695 */
696 public function getStorageByUidThrowsExceptionIfStorageIsNotBrowsable()
697 {
698 $this->expectException(PersistenceManagerException::class);
699 $this->expectExceptionCode(1471630581);
700
701 $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [
702 'dummy',
703 ], [], '', false);
704
705 $mockStorageRepository = $this->getMockBuilder(StorageRepository::class)
706 ->disableOriginalConstructor()
707 ->getMock();
708
709 $mockStorage = $this->getMockBuilder(ResourceStorage::class)
710 ->disableOriginalConstructor()
711 ->getMock();
712
713 $mockStorage
714 ->expects($this->any())
715 ->method('isBrowsable')
716 ->willReturn(false);
717
718 $mockStorageRepository
719 ->expects($this->any())
720 ->method('findByUid')
721 ->willReturn($mockStorage);
722
723 $mockFormPersistenceManager->_set('storageRepository', $mockStorageRepository);
724 $mockFormPersistenceManager->_call('getStorageByUid', -1);
725 }
726 }