[BUGFIX] FormEngine: Exception on inline/section in flex container
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Tests / Unit / Form / FormDataProvider / TcaFlexProcessTest.php
1 <?php
2 namespace TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider;
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 Prophecy\Argument;
18 use Prophecy\Prophecy\ObjectProphecy;
19 use TYPO3\CMS\Backend\Form\FormDataGroup\FlexFormSegment;
20 use TYPO3\CMS\Backend\Form\FormDataProvider\TcaFlexProcess;
21 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
22 use TYPO3\CMS\Core\Tests\UnitTestCase;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24 use TYPO3\CMS\Lang\LanguageService;
25
26 /**
27 * Test case
28 */
29 class TcaFlexProcessTest extends UnitTestCase
30 {
31 /**
32 * @var TcaFlexProcess
33 */
34 protected $subject;
35
36 /**
37 * @var BackendUserAuthentication|ObjectProphecy
38 */
39 protected $backendUserProphecy;
40
41 protected function setUp()
42 {
43 /** @var BackendUserAuthentication|ObjectProphecy backendUserProphecy */
44 $this->backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
45 $GLOBALS['BE_USER'] = $this->backendUserProphecy->reveal();
46 $GLOBALS['BE_USER']->groupData['non_exclude_fields'] = '';
47
48 // Some tests call FormDataCompiler for sub elements. Those tests have functional test characteristics.
49 // This is ok for the time being, but this settings takes care only parts of the compiler are called
50 // to have less dependencies.
51 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['flexFormSegment'] = [];
52
53 $this->subject = new TcaFlexProcess();
54 }
55
56 /**
57 * @test
58 */
59 public function addDataRemovesSheetIfDisabledByPageTsConfig()
60 {
61 $input = [
62 'tableName' => 'aTable',
63 'databaseRow' => [
64 'aField' => [
65 'data' => [],
66 ],
67 'pointerField' => 'aFlex',
68 ],
69 'processedTca' => [
70 'columns' => [
71 'aField' => [
72 'config' => [
73 'type' => 'flex',
74 'ds_pointerField' => 'pointerField',
75 'ds' => [
76 'sheets' => [
77 'aSheet' => [
78 'ROOT' => [
79 'type' => 'array',
80 'el' => [
81 'aFlexField' => [
82 'label' => 'aFlexFieldLabel',
83 'config' => [
84 'type' => 'input',
85 ],
86 ]
87 ],
88 ],
89 ],
90 ],
91 ],
92 ],
93 ],
94 ],
95 ],
96 'pageTsConfig' => [
97 'TCEFORM.' => [
98 'aTable.' => [
99 'aField.' => [
100 'aFlex.' => [
101 'aSheet.' => [
102 'disabled' => 1,
103 ],
104 ],
105 ],
106 ],
107 ],
108 ],
109 ];
110
111 $expected = $input;
112 $expected['processedTca']['columns']['aField']['config']['ds'] = [
113 'sheets' => [],
114 'meta' => [
115 'dataStructurePointers' => [
116 'pointerField' => 'aFlex',
117 ],
118 ],
119 ];
120
121 $this->assertEquals($expected, $this->subject->addData($input));
122 }
123
124 /**
125 * @test
126 */
127 public function addDataSetsSheetTitleFromPageTsConfig()
128 {
129 $input = [
130 'tableName' => 'aTable',
131 'databaseRow' => [
132 'aField' => [
133 'data' => [],
134 ],
135 'pointerField' => 'aFlex',
136 ],
137 'processedTca' => [
138 'columns' => [
139 'aField' => [
140 'config' => [
141 'type' => 'flex',
142 'ds_pointerField' => 'pointerField',
143 'ds' => [
144 'sheets' => [
145 'aSheet' => [
146 'ROOT' => [
147 'type' => 'array',
148 'el' => [
149 'aFlexField' => [
150 'label' => 'aFlexFieldLabel',
151 'config' => [
152 'type' => 'input',
153 ],
154 ]
155 ],
156 ],
157 ],
158 ],
159 ],
160 ],
161 ],
162 ],
163 ],
164 'pageTsConfig' => [
165 'TCEFORM.' => [
166 'aTable.' => [
167 'aField.' => [
168 'aFlex.' => [
169 'aSheet.' => [
170 'sheetTitle' => 'aTitle',
171 ],
172 ],
173 ],
174 ],
175 ],
176 ],
177 ];
178
179 $expected = $input;
180 $expected['processedTca']['columns']['aField']['config']['ds'] = [
181 'sheets' => [
182 'aSheet' => [
183 'ROOT' => [
184 'type' => 'array',
185 'el' => [
186 'aFlexField' => [
187 'label' => 'aFlexFieldLabel',
188 'config' => [
189 'type' => 'input',
190 ],
191 ],
192 ],
193 'sheetTitle' => 'aTitle',
194 ],
195 ],
196 ],
197 'meta' => [
198 'dataStructurePointers' => [
199 'pointerField' => 'aFlex',
200 ],
201 ],
202 ];
203
204 $this->assertEquals($expected, $this->subject->addData($input));
205 }
206
207 /**
208 * @test
209 */
210 public function addDataSetsSheetDescriptionFromPageTsConfig()
211 {
212 $input = [
213 'tableName' => 'aTable',
214 'databaseRow' => [
215 'aField' => [
216 'data' => [],
217 ],
218 'pointerField' => 'aFlex',
219 ],
220 'processedTca' => [
221 'columns' => [
222 'aField' => [
223 'config' => [
224 'type' => 'flex',
225 'ds_pointerField' => 'pointerField',
226 'ds' => [
227 'sheets' => [
228 'aSheet' => [
229 'ROOT' => [
230 'type' => 'array',
231 'el' => [
232 'aFlexField' => [
233 'label' => 'aFlexFieldLabel',
234 'config' => [
235 'type' => 'input',
236 ],
237 ]
238 ],
239 ],
240 ],
241 ],
242 ],
243 ],
244 ],
245 ],
246 ],
247 'pageTsConfig' => [
248 'TCEFORM.' => [
249 'aTable.' => [
250 'aField.' => [
251 'aFlex.' => [
252 'aSheet.' => [
253 'sheetDescription' => 'aDescription',
254 ],
255 ],
256 ],
257 ],
258 ],
259 ],
260 ];
261
262 $expected = $input;
263 $expected['processedTca']['columns']['aField']['config']['ds'] = [
264 'sheets' => [
265 'aSheet' => [
266 'ROOT' => [
267 'type' => 'array',
268 'el' => [
269 'aFlexField' => [
270 'label' => 'aFlexFieldLabel',
271 'config' => [
272 'type' => 'input',
273 ],
274 ],
275 ],
276 'sheetDescription' => 'aDescription',
277 ],
278 ],
279 ],
280 'meta' => [
281 'dataStructurePointers' => [
282 'pointerField' => 'aFlex',
283 ],
284 ],
285 ];
286
287 $this->assertEquals($expected, $this->subject->addData($input));
288 }
289
290 /**
291 * @test
292 */
293 public function addDataSetsSheetShortDescriptionFromPageTsConfig()
294 {
295 $input = [
296 'tableName' => 'aTable',
297 'databaseRow' => [
298 'aField' => [
299 'data' => [],
300 ],
301 'pointerField' => 'aFlex',
302 ],
303 'processedTca' => [
304 'columns' => [
305 'aField' => [
306 'config' => [
307 'type' => 'flex',
308 'ds_pointerField' => 'pointerField',
309 'ds' => [
310 'sheets' => [
311 'aSheet' => [
312 'ROOT' => [
313 'type' => 'array',
314 'el' => [
315 'aFlexField' => [
316 'label' => 'aFlexFieldLabel',
317 'config' => [
318 'type' => 'input',
319 ],
320 ]
321 ],
322 ],
323 ],
324 ],
325 ],
326 ],
327 ],
328 ],
329 ],
330 'pageTsConfig' => [
331 'TCEFORM.' => [
332 'aTable.' => [
333 'aField.' => [
334 'aFlex.' => [
335 'aSheet.' => [
336 'sheetDescription' => 'sheetShortDescr',
337 ],
338 ],
339 ],
340 ],
341 ],
342 ],
343 ];
344
345 $expected = $input;
346 $expected['processedTca']['columns']['aField']['config']['ds'] = [
347 'sheets' => [
348 'aSheet' => [
349 'ROOT' => [
350 'type' => 'array',
351 'el' => [
352 'aFlexField' => [
353 'label' => 'aFlexFieldLabel',
354 'config' => [
355 'type' => 'input',
356 ],
357 ],
358 ],
359 'sheetDescription' => 'sheetShortDescr',
360 ],
361 ],
362 ],
363 'meta' => [
364 'dataStructurePointers' => [
365 'pointerField' => 'aFlex',
366 ],
367 ],
368 ];
369
370 $this->assertEquals($expected, $this->subject->addData($input));
371 }
372
373 /**
374 * @test
375 */
376 public function addDataSetsSheetShortDescriptionForSingleSheetFromPageTsConfig()
377 {
378 $input = [
379 'tableName' => 'aTable',
380 'databaseRow' => [
381 'aField' => [
382 'data' => [],
383 ],
384 'pointerField' => 'aFlex',
385 ],
386 'processedTca' => [
387 'columns' => [
388 'aField' => [
389 'config' => [
390 'type' => 'flex',
391 'ds_pointerField' => 'pointerField',
392 'ds' => [
393 'sheets' => [
394 'sDEF' => [
395 'ROOT' => [
396 'type' => 'array',
397 'el' => [
398 'aFlexField' => [
399 'label' => 'aFlexFieldLabel',
400 'config' => [
401 'type' => 'input',
402 ],
403 ]
404 ],
405 ],
406 ],
407 ],
408 ],
409 ],
410 ],
411 ],
412 ],
413 'pageTsConfig' => [
414 'TCEFORM.' => [
415 'aTable.' => [
416 'aField.' => [
417 'aFlex.' => [
418 'sDEF.' => [
419 'sheetDescription' => 'sheetShortDescr',
420 ],
421 ],
422 ],
423 ],
424 ],
425 ],
426 ];
427
428 $expected = $input;
429 $expected['processedTca']['columns']['aField']['config']['ds'] = [
430 'sheets' => [
431 'sDEF' => [
432 'ROOT' => [
433 'type' => 'array',
434 'el' => [
435 'aFlexField' => [
436 'label' => 'aFlexFieldLabel',
437 'config' => [
438 'type' => 'input',
439 ],
440 ],
441 ],
442 'sheetDescription' => 'sheetShortDescr',
443 ],
444 ],
445 ],
446 'meta' => [
447 'dataStructurePointers' => [
448 'pointerField' => 'aFlex',
449 ],
450 ],
451 ];
452
453 $this->assertEquals($expected, $this->subject->addData($input));
454 }
455
456 /**
457 * @test
458 */
459 public function addDataRemovesExcludeFieldFromDataStructure()
460 {
461 $input = [
462 'tableName' => 'aTable',
463 'databaseRow' => [
464 'aField' => [
465 'data' => [],
466 ],
467 'pointerField' => 'aFlex',
468 ],
469 'processedTca' => [
470 'columns' => [
471 'aField' => [
472 'config' => [
473 'type' => 'flex',
474 'ds_pointerField' => 'pointerField',
475 'ds' => [
476 'sheets' => [
477 'sDEF' => [
478 'ROOT' => [
479 'type' => 'array',
480 'el' => [
481 'aFlexField' => [
482 'label' => 'aFlexFieldLabel',
483 'exclude' => '1',
484 'config' => [
485 'type' => 'input',
486 ],
487 ]
488 ],
489 ],
490 ],
491 ],
492 ],
493 ],
494 ],
495 ],
496 ],
497 'pageTsConfig' => [],
498 ];
499
500 $this->backendUserProphecy->isAdmin()->shouldBeCalled()->willReturn(false);
501 $GLOBALS['BE_USER']->groupData['non_exclude_fields'] = '';
502
503 $expected = $input;
504 $expected['processedTca']['columns']['aField']['config']['ds'] = [
505 'sheets' => [
506 'sDEF' => [
507 'ROOT' => [
508 'type' => 'array',
509 'el' => [],
510 ],
511 ],
512 ],
513 'meta' => [
514 'dataStructurePointers' => [
515 'pointerField' => 'aFlex',
516 ],
517 ],
518 ];
519
520 $this->assertEquals($expected, $this->subject->addData($input));
521 }
522
523 /**
524 * @test
525 */
526 public function addDataKeepsExcludeFieldInDataStructureWithUserAccess()
527 {
528 $input = [
529 'tableName' => 'aTable',
530 'databaseRow' => [
531 'aField' => [
532 'data' => [],
533 ],
534 'pointerField' => 'aFlex',
535 ],
536 'processedTca' => [
537 'columns' => [
538 'aField' => [
539 'config' => [
540 'type' => 'flex',
541 'ds_pointerField' => 'pointerField',
542 'ds' => [
543 'sheets' => [
544 'sDEF' => [
545 'ROOT' => [
546 'type' => 'array',
547 'el' => [
548 'aFlexField' => [
549 'label' => 'aFlexFieldLabel',
550 'exclude' => '1',
551 'config' => [
552 'type' => 'input',
553 ],
554 ]
555 ],
556 ],
557 ],
558 ],
559 ],
560 ],
561 ],
562 ],
563 ],
564 'pageTsConfig' => [],
565 ];
566
567 $this->backendUserProphecy->isAdmin()->shouldBeCalled()->willReturn(false);
568 $GLOBALS['BE_USER']->groupData['non_exclude_fields'] = 'aTable:aField;aFlex;sDEF;aFlexField';
569
570 $expected = $input;
571 $expected['processedTca']['columns']['aField']['config']['ds'] = [
572 'sheets' => [
573 'sDEF' => [
574 'ROOT' => [
575 'type' => 'array',
576 'el' => [
577 'aFlexField' => [
578 'label' => 'aFlexFieldLabel',
579 'config' => [
580 'type' => 'input',
581 ],
582 'exclude' => '1',
583 ],
584 ],
585 ],
586 ],
587 ],
588 'meta' => [
589 'dataStructurePointers' => [
590 'pointerField' => 'aFlex',
591 ],
592 ],
593 ];
594
595 $this->assertEquals($expected, $this->subject->addData($input));
596 }
597
598 /**
599 * @test
600 */
601 public function addDataKeepsExcludeFieldInDataStructureForAdminUser()
602 {
603 $input = [
604 'tableName' => 'aTable',
605 'databaseRow' => [
606 'aField' => [
607 'data' => [],
608 ],
609 'pointerField' => 'aFlex',
610 ],
611 'processedTca' => [
612 'columns' => [
613 'aField' => [
614 'config' => [
615 'type' => 'flex',
616 'ds_pointerField' => 'pointerField',
617 'ds' => [
618 'sheets' => [
619 'sDEF' => [
620 'ROOT' => [
621 'type' => 'array',
622 'el' => [
623 'aFlexField' => [
624 'label' => 'aFlexFieldLabel',
625 'exclude' => '1',
626 'config' => [
627 'type' => 'input',
628 ],
629 ]
630 ],
631 ],
632 ],
633 ],
634 ],
635 ],
636 ],
637 ],
638 ],
639 'pageTsConfig' => [],
640 ];
641
642 $this->backendUserProphecy->isAdmin()->shouldBeCalled()->willReturn(true);
643 $GLOBALS['BE_USER']->groupData['non_exclude_fields'] = '';
644
645 $expected = $input;
646 $expected['processedTca']['columns']['aField']['config']['ds'] = [
647 'sheets' => [
648 'sDEF' => [
649 'ROOT' => [
650 'type' => 'array',
651 'el' => [
652 'aFlexField' => [
653 'label' => 'aFlexFieldLabel',
654 'config' => [
655 'type' => 'input',
656 ],
657 'exclude' => '1',
658 ],
659 ],
660 ],
661 ],
662 ],
663 'meta' => [
664 'dataStructurePointers' => [
665 'pointerField' => 'aFlex',
666 ],
667 ],
668 ];
669
670 $this->assertEquals($expected, $this->subject->addData($input));
671 }
672
673 /**
674 * @test
675 */
676 public function addDataRemovesPageTsDisabledFieldFromDataStructure()
677 {
678 $input = [
679 'tableName' => 'aTable',
680 'databaseRow' => [
681 'aField' => [
682 'data' => [],
683 ],
684 'pointerField' => 'aFlex',
685 ],
686 'processedTca' => [
687 'columns' => [
688 'aField' => [
689 'config' => [
690 'type' => 'flex',
691 'ds_pointerField' => 'pointerField',
692 'ds' => [
693 'sheets' => [
694 'sDEF' => [
695 'ROOT' => [
696 'type' => 'array',
697 'el' => [
698 'aFlexField' => [
699 'label' => 'aFlexFieldLabel',
700 'config' => [
701 'type' => 'input',
702 ],
703 ]
704 ],
705 ],
706 ],
707 ],
708 ],
709 ],
710 ],
711 ],
712 ],
713 'pageTsConfig' => [
714 'TCEFORM.' => [
715 'aTable.' => [
716 'aField.' => [
717 'aFlex.' => [
718 'sDEF.' => [
719 'aFlexField.' => [
720 'disabled' => 1,
721 ],
722 ],
723 ],
724 ],
725 ],
726 ],
727 ],
728 ];
729
730 $expected = $input;
731 $expected['processedTca']['columns']['aField']['config']['ds'] = [
732 'sheets' => [
733 'sDEF' => [
734 'ROOT' => [
735 'type' => 'array',
736 'el' => [],
737 ],
738 ],
739 ],
740 'meta' => [
741 'dataStructurePointers' => [
742 'pointerField' => 'aFlex',
743 ],
744 ],
745 ];
746
747 $this->assertEquals($expected, $this->subject->addData($input));
748 }
749
750 /**
751 * @test
752 */
753 public function addDataHandlesPageTsConfigSettingsOfSingleFlexField()
754 {
755 $input = [
756 'tableName' => 'aTable',
757 'databaseRow' => [
758 'aField' => [
759 'data' => [],
760 ],
761 'pointerField' => 'aFlex',
762 ],
763 'processedTca' => [
764 'columns' => [
765 'aField' => [
766 'config' => [
767 'type' => 'flex',
768 'ds_pointerField' => 'pointerField',
769 'ds' => [
770 'sheets' => [
771 'sDEF' => [
772 'ROOT' => [
773 'type' => 'array',
774 'el' => [
775 'aFlexField' => [
776 'label' => 'aFlexFieldLabel',
777 'config' => [
778 'type' => 'radio',
779 'items' => [
780 0 => [
781 0 => 'aLabel',
782 1 => 'aValue',
783 ],
784 ],
785 ],
786 ],
787 ],
788 ],
789 ],
790 ],
791 ],
792 ],
793 ],
794 ],
795 ],
796 'pageTsConfig' => [
797 'TCEFORM.' => [
798 'aTable.' => [
799 'aField.' => [
800 'aFlex.' => [
801 'sDEF.' => [
802 'aFlexField.' => [
803 'altLabels.' => [
804 '0' => 'labelOverride',
805 ],
806 ],
807 ],
808 ],
809 ],
810 ],
811 ],
812 ],
813 ];
814
815 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['flexFormSegment'] = [
816 \TYPO3\CMS\Backend\Form\FormDataProvider\TcaRadioItems::class => [],
817 ];
818
819 /** @var LanguageService|ObjectProphecy $languageService */
820 $languageService = $this->prophesize(LanguageService::class);
821 $GLOBALS['LANG'] = $languageService->reveal();
822 $languageService->sL(Argument::cetera())->willReturnArgument(0);
823
824 $this->backendUserProphecy->isAdmin()->willReturn(true);
825 $this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(true);
826
827 $expected = $input;
828 $expected['processedTca']['columns']['aField']['config']['ds'] = [
829 'sheets' => [
830 'sDEF' => [
831 'ROOT' => [
832 'type' => 'array',
833 'el' => [
834 'aFlexField' => [
835 'label' => 'aFlexFieldLabel',
836 'config' => [
837 'type' => 'radio',
838 'items' => [
839 0 => [
840 0 => 'labelOverride',
841 1 => 'aValue',
842 ],
843 ],
844 ],
845 ],
846 ],
847 ],
848 ],
849 ],
850 'meta' => [
851 'dataStructurePointers' => [
852 'pointerField' => 'aFlex',
853 ],
854 ],
855 ];
856
857 $this->assertEquals($expected, $this->subject->addData($input));
858 }
859
860 /**
861 * @test
862 */
863 public function addDataSetsDefaultValueFromFlexTcaForField()
864 {
865 $input = [
866 'tableName' => 'aTable',
867 'databaseRow' => [
868 'aField' => [
869 'data' => [],
870 ],
871 'pointerField' => 'aFlex',
872 ],
873 'processedTca' => [
874 'columns' => [
875 'aField' => [
876 'config' => [
877 'type' => 'flex',
878 'ds_pointerField' => 'pointerField',
879 'ds' => [
880 'sheets' => [
881 'sDEF' => [
882 'ROOT' => [
883 'type' => 'array',
884 'el' => [
885 'aFlexField' => [
886 'label' => 'aFlexFieldLabel',
887 'config' => [
888 'type' => 'input',
889 'default' => 'defaultValue',
890 ],
891 ],
892 ],
893 ],
894 ],
895 ],
896 ],
897 ],
898 ],
899 ],
900 ],
901 'pageTsConfig' => [],
902 ];
903
904 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['flexFormSegment'] = [
905 \TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRowDefaultValues::class => [],
906 ];
907
908 /** @var LanguageService|ObjectProphecy $languageService */
909 $languageService = $this->prophesize(LanguageService::class);
910 $GLOBALS['LANG'] = $languageService->reveal();
911 $languageService->sL(Argument::cetera())->willReturnArgument(0);
912
913 $this->backendUserProphecy->isAdmin()->willReturn(true);
914 $this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(true);
915
916 $expected = $input;
917 $expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
918 'dataStructurePointers' => [
919 'pointerField' => 'aFlex'
920 ],
921 ];
922 $expected['databaseRow']['aField']['data']['sDEF']['lDEF']['aFlexField']['vDEF'] = 'defaultValue';
923
924 $this->assertEquals($expected, $this->subject->addData($input));
925 }
926
927 /**
928 * @test
929 */
930 public function addDataThrowsExceptionForDataStructureTypeArrayWithoutSection()
931 {
932 $input = [
933 'tableName' => 'aTable',
934 'databaseRow' => [
935 'aField' => [
936 'data' => [],
937 'meta' => [],
938 ],
939 ],
940 'processedTca' => [
941 'columns' => [
942 'aField' => [
943 'config' => [
944 'type' => 'flex',
945 'ds' => [
946 'sheets' => [
947 'sDEF' => [
948 'ROOT' => [
949 'type' => 'array',
950 'el' => [
951 'aFlexField' => [
952 'type' => 'array',
953 ],
954 ],
955 ],
956 ],
957 ],
958 ],
959 ],
960 ],
961 ],
962 ],
963 'pageTsConfig' => [],
964 ];
965
966 $this->backendUserProphecy->isAdmin()->willReturn(true);
967 $this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(true);
968
969 $this->setExpectedException(\UnexpectedValueException::class, $this->anything(), 1440685208);
970
971 $this->subject->addData($input);
972 }
973
974 /**
975 * @test
976 */
977 public function addDataThrowsExceptionForDataStructureSectionWithoutTypeArray()
978 {
979 $input = [
980 'tableName' => 'aTable',
981 'databaseRow' => [
982 'aField' => [
983 'data' => [],
984 'meta' => [],
985 ],
986 ],
987 'processedTca' => [
988 'columns' => [
989 'aField' => [
990 'config' => [
991 'type' => 'flex',
992 'ds' => [
993 'sheets' => [
994 'sDEF' => [
995 'ROOT' => [
996 'type' => 'array',
997 'el' => [
998 'aFlexField' => [
999 'section' => '1',
1000 ],
1001 ],
1002 ],
1003 ],
1004 ],
1005 ],
1006 ],
1007 ],
1008 ],
1009 ],
1010 'pageTsConfig' => [],
1011 ];
1012
1013 $this->backendUserProphecy->isAdmin()->willReturn(true);
1014 $this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(true);
1015
1016 $this->setExpectedException(\UnexpectedValueException::class, $this->anything(), 1440685208);
1017
1018 $this->subject->addData($input);
1019 }
1020
1021 /**
1022 * @test
1023 */
1024 public function addDataSetsValuesAndStructureForSectionContainerElements()
1025 {
1026 $input = [
1027 'tableName' => 'aTable',
1028 'databaseRow' => [
1029 'aField' => [
1030 'data' => [
1031 'sDEF' => [
1032 'lDEF' => [
1033 'section_1' => [
1034 'el' => [
1035 '1' => [
1036 'container_1' => [
1037 // It should set the default value for aFlexField here
1038 'el' => [
1039 ],
1040 ],
1041 ],
1042 '2' => [
1043 'container_1' => [
1044 'el' => [
1045 'aFlexField' => [
1046 // It should keep this value
1047 'vDEF' => 'dbValue',
1048 ],
1049 ],
1050 ],
1051 ],
1052 ],
1053 ],
1054 ],
1055 'lEN' => [
1056 'section_1' => [
1057 'el' => [
1058 '1' => [
1059 'container_1' => [
1060 // It should add the default value for aFlexField here
1061 ],
1062 ],
1063 ],
1064 ],
1065 ],
1066 ],
1067 ],
1068 'meta' => [],
1069 ],
1070 ],
1071 'processedTca' => [
1072 'columns' => [
1073 'aField' => [
1074 'config' => [
1075 'type' => 'flex',
1076 'ds' => [
1077 'sheets' => [
1078 'sDEF' => [
1079 'ROOT' => [
1080 'type' => 'array',
1081 'el' => [
1082 'section_1' => [
1083 'section' => '1',
1084 'type' => 'array',
1085 'el' => [
1086 'container_1' => [
1087 'type' => 'array',
1088 'el' => [
1089 'aFlexField' => [
1090 'label' => 'aFlexFieldLabel',
1091 'config' => [
1092 'type' => 'input',
1093 'default' => 'defaultValue',
1094 ],
1095 ],
1096 ],
1097 ],
1098 ],
1099 ],
1100 ],
1101 ],
1102 ],
1103 ],
1104 ],
1105 ],
1106 ],
1107 ],
1108 ],
1109 'pageTsConfig' => [],
1110 ];
1111
1112 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['flexFormSegment'] = [
1113 \TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRowDefaultValues::class => [],
1114 ];
1115
1116 /** @var LanguageService|ObjectProphecy $languageService */
1117 $languageService = $this->prophesize(LanguageService::class);
1118 $GLOBALS['LANG'] = $languageService->reveal();
1119 $languageService->sL(Argument::cetera())->willReturnArgument(0);
1120
1121 $this->backendUserProphecy->isAdmin()->willReturn(true);
1122 $this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(true);
1123
1124 $expected = $input;
1125
1126 // A default value for existing container field aFlexField should have been set
1127 $expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['el']['1']['container_1']['el']['aFlexField']['vDEF'] = 'defaultValue';
1128
1129 // Dummy row values for container_1 on lDEF sheet
1130 $expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['templateRows']['container_1']['el']['aFlexField']['vDEF'] = 'defaultValue';
1131
1132 $this->assertEquals($expected, $this->subject->addData($input));
1133 }
1134
1135 /**
1136 * @test
1137 */
1138 public function addDataThrowsExceptionForInlineElementsNestedInSectionContainers()
1139 {
1140 $input = [
1141 'tableName' => 'aTable',
1142 'databaseRow' => [
1143 'aField' => [
1144 'data' => [],
1145 ],
1146 'pointerField' => 'aFlex',
1147 ],
1148 'processedTca' => [
1149 'columns' => [
1150 'aField' => [
1151 'config' => [
1152 'type' => 'flex',
1153 'ds' => [
1154 'sheets' => [
1155 'sDEF' => [
1156 'ROOT' => [
1157 'type' => 'array',
1158 'el' => [
1159 'section_1' => [
1160 'section' => '1',
1161 'type' => 'array',
1162 'el' => [
1163 'container_1' => [
1164 'type' => 'array',
1165 'el' => [
1166 'aFlexField' => [
1167 'label' => 'aFlexFieldLabel',
1168 'config' => [
1169 'type' => 'inline',
1170 ],
1171 ],
1172 ],
1173 ],
1174 ],
1175 ],
1176 ],
1177 ],
1178 ],
1179 ],
1180 ],
1181 ],
1182 ],
1183 ],
1184 ],
1185 'pageTsConfig' => [],
1186 ];
1187
1188 $this->setExpectedException(\UnexpectedValueException::class, $this->anything(), 1458745468);
1189
1190 $this->subject->addData($input);
1191 }
1192
1193 /**
1194 * @test
1195 */
1196 public function addDataThrowsExceptionForNestedSectionContainers()
1197 {
1198 $input = [
1199 'tableName' => 'aTable',
1200 'databaseRow' => [
1201 'aField' => [
1202 'data' => [],
1203 ],
1204 'pointerField' => 'aFlex',
1205 ],
1206 'processedTca' => [
1207 'columns' => [
1208 'aField' => [
1209 'config' => [
1210 'type' => 'flex',
1211 'ds' => [
1212 'sheets' => [
1213 'sDEF' => [
1214 'ROOT' => [
1215 'type' => 'array',
1216 'el' => [
1217 'section_1' => [
1218 'section' => '1',
1219 'type' => 'array',
1220 'el' => [
1221 'container_1' => [
1222 'type' => 'array',
1223 'el' => [
1224 'section_nested' => [
1225 'section' => '1',
1226 'type' => 'array',
1227 'el' => [
1228 ],
1229 ],
1230 ],
1231 ],
1232 ],
1233 ],
1234 ],
1235 ],
1236 ],
1237 ],
1238 ],
1239 ],
1240 ],
1241 ],
1242 ],
1243 'pageTsConfig' => [],
1244 ];
1245
1246 $this->setExpectedException(\UnexpectedValueException::class, $this->anything(), 1458745712);
1247
1248 $this->subject->addData($input);
1249 }
1250
1251 /**
1252 * @test
1253 */
1254 public function addDataCallsFlexFormSegmentGroupForFieldAndAddsFlexParentDatabaseRow()
1255 {
1256 $input = [
1257 'tableName' => 'aTable',
1258 'databaseRow' => [
1259 'aField' => [
1260 'data' => [],
1261 ],
1262 'pointerField' => 'aFlex',
1263 ],
1264 'processedTca' => [
1265 'columns' => [
1266 'aField' => [
1267 'config' => [
1268 'type' => 'flex',
1269 'ds_pointerField' => 'pointerField',
1270 'ds' => [
1271 'sheets' => [
1272 'sDEF' => [
1273 'ROOT' => [
1274 'type' => 'array',
1275 'el' => [
1276 'aFlexField' => [
1277 'label' => 'aFlexFieldLabel',
1278 'config' => [
1279 'type' => 'input',
1280 ],
1281 ],
1282 ],
1283 ],
1284 ],
1285 ],
1286 ],
1287 ],
1288 ],
1289 ],
1290 ],
1291 'pageTsConfig' => [],
1292 ];
1293
1294 /** @var FlexFormSegment|ObjectProphecy $dummyGroup */
1295 $dummyGroup = $this->prophesize(FlexFormSegment::class);
1296 GeneralUtility::addInstance(FlexFormSegment::class, $dummyGroup->reveal());
1297
1298 // Check array given to flex group contains databaseRow as flexParentDatabaseRow and check compile is called
1299 $dummyGroup->compile(Argument::that(function ($result) use ($input) {
1300 if ($result['flexParentDatabaseRow'] === $input['databaseRow']) {
1301 return true;
1302 }
1303 return false;
1304 }))->shouldBeCalled()->willReturnArgument(0);
1305
1306 $this->subject->addData($input);
1307 }
1308
1309 /**
1310 * @test
1311 */
1312 public function addDataCallsFlexFormSegmentGroupForDummyContainerAndAddsFlexParentDatabaseRow()
1313 {
1314 $input = [
1315 'tableName' => 'aTable',
1316 'databaseRow' => [
1317 'aField' => [
1318 'data' => [],
1319 ],
1320 'pointerField' => 'aFlex',
1321 ],
1322 'processedTca' => [
1323 'columns' => [
1324 'aField' => [
1325 'config' => [
1326 'type' => 'flex',
1327 'ds_pointerField' => 'pointerField',
1328 'ds' => [
1329 'sheets' => [
1330 'sDEF' => [
1331 'ROOT' => [
1332 'type' => 'array',
1333 'el' => [
1334 'aFlexField' => [
1335 'label' => 'aFlexFieldLabel',
1336 'config' => [
1337 'type' => 'input',
1338 ],
1339 ],
1340 ],
1341 ],
1342 ],
1343 ],
1344 ],
1345 ],
1346 ],
1347 ],
1348 ],
1349 'pageTsConfig' => [],
1350 ];
1351
1352 /** @var FlexFormSegment|ObjectProphecy $dummyGroupExisting */
1353 $dummyGroupExisting = $this->prophesize(FlexFormSegment::class);
1354 GeneralUtility::addInstance(FlexFormSegment::class, $dummyGroupExisting->reveal());
1355 // Check array given to flex group contains databaseRow as flexParentDatabaseRow and check compile is called
1356 $dummyGroupExisting->compile(Argument::that(function ($result) use ($input) {
1357 if ($result['flexParentDatabaseRow'] === $input['databaseRow']) {
1358 return true;
1359 }
1360 return false;
1361 }))->shouldBeCalled()->willReturnArgument(0);
1362
1363 $this->subject->addData($input);
1364 }
1365 }