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