7a96acb36448a8ca0ce46c0f88e6bf6d0de2cec4
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Tests / Unit / Form / FormDataProvider / TcaInlineConfigurationTest.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 TYPO3\CMS\Backend\Form\FormDataProvider\TcaInlineConfiguration;
18
19 /**
20 * Test case
21 */
22 class TcaInlineConfigurationTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
23 {
24 /**
25 * Subject is not notice free, disable E_NOTICES
26 */
27 protected static $suppressNotices = true;
28
29 /**
30 * @var TcaInlineConfiguration
31 */
32 protected $subject;
33
34 protected function setUp()
35 {
36 $this->subject = new TcaInlineConfiguration();
37 }
38
39 /**
40 * @var array Set of default controls
41 */
42 protected $defaultConfig = [
43 'type' => 'inline',
44 'foreign_table' => 'aForeignTableName',
45 'minitems' => 0,
46 'maxitems' => 99999,
47 'appearance' => [
48 'levelLinksPosition' => 'top',
49 'showPossibleLocalizationRecords' => false,
50 'showRemovedLocalizationRecords' => false,
51 'enabledControls' => [
52 'info' => true,
53 'new' => true,
54 'dragdrop' => true,
55 'sort' => true,
56 'hide' => true,
57 'delete' => true,
58 'localize' => true,
59 ],
60 ],
61 ];
62
63 /**
64 * @test
65 */
66 public function addDataThrowsExceptionForInlineFieldWithoutForeignTableConfig()
67 {
68 $input = [
69 'databaseRow' => [],
70 'processedTca' => [
71 'columns' => [
72 'aField' => [
73 'config' => [
74 'type' => 'inline',
75 ],
76 ],
77 ],
78 ],
79 ];
80 $this->expectException(\UnexpectedValueException::class);
81 $this->expectExceptionCode(1443793404);
82 $this->subject->addData($input);
83 }
84
85 /**
86 * @test
87 */
88 public function addDataSetsDefaults()
89 {
90 $input = [
91 'processedTca' => [
92 'columns' => [
93 'aField' => [
94 'config' => [
95 'type' => 'inline',
96 'foreign_table' => 'aForeignTableName',
97 ],
98 ],
99 ],
100 ],
101 ];
102 $expected['processedTca']['columns']['aField']['config'] = $this->defaultConfig;
103 $this->assertEquals($expected, $this->subject->addData($input));
104 }
105
106 /**
107 * @test
108 */
109 public function addDataKeepsGivenMinitems()
110 {
111 $input = [
112 'processedTca' => [
113 'columns' => [
114 'aField' => [
115 'config' => [
116 'type' => 'inline',
117 'foreign_table' => 'aForeignTableName',
118 'minitems' => 23,
119 ],
120 ],
121 ],
122 ],
123 ];
124 $expected['processedTca']['columns']['aField']['config'] = $this->defaultConfig;
125 $expected['processedTca']['columns']['aField']['config']['minitems'] = 23;
126 $this->assertEquals($expected, $this->subject->addData($input));
127 }
128
129 /**
130 * @test
131 */
132 public function addDataForcesMinitemsPositive()
133 {
134 $input = [
135 'processedTca' => [
136 'columns' => [
137 'aField' => [
138 'config' => [
139 'type' => 'inline',
140 'foreign_table' => 'aForeignTableName',
141 'minitems' => -23,
142 ],
143 ],
144 ],
145 ],
146 ];
147 $expected['processedTca']['columns']['aField']['config'] = $this->defaultConfig;
148 $expected['processedTca']['columns']['aField']['config']['minitems'] = 0;
149 $this->assertEquals($expected, $this->subject->addData($input));
150 }
151
152 /**
153 * @test
154 */
155 public function addDataKeepsGivenMaxitems()
156 {
157 $input = [
158 'processedTca' => [
159 'columns' => [
160 'aField' => [
161 'config' => [
162 'type' => 'inline',
163 'foreign_table' => 'aForeignTableName',
164 'maxitems' => 23,
165 ],
166 ],
167 ],
168 ],
169 ];
170 $expected['processedTca']['columns']['aField']['config'] = $this->defaultConfig;
171 $expected['processedTca']['columns']['aField']['config']['maxitems'] = 23;
172 $this->assertEquals($expected, $this->subject->addData($input));
173 }
174
175 /**
176 * @test
177 */
178 public function addDataForcesMaxitemsPositive()
179 {
180 $input = [
181 'processedTca' => [
182 'columns' => [
183 'aField' => [
184 'config' => [
185 'type' => 'inline',
186 'foreign_table' => 'aForeignTableName',
187 'maxitems' => '-23',
188 ],
189 ],
190 ],
191 ],
192 ];
193 $expected['processedTca']['columns']['aField']['config'] = $this->defaultConfig;
194 $expected['processedTca']['columns']['aField']['config']['maxitems'] = 1;
195 $this->assertEquals($expected, $this->subject->addData($input));
196 }
197
198 /**
199 * @test
200 */
201 public function addDataMergesWithGivenAppearanceSettings()
202 {
203 $input = [
204 'processedTca' => [
205 'columns' => [
206 'aField' => [
207 'config' => [
208 'type' => 'inline',
209 'foreign_table' => 'aForeignTableName',
210 'appearance' => [
211 'levelLinksPosition' => 'both',
212 'enabledControls' => [
213 'dragdrop' => false,
214 ],
215 ],
216 ],
217 ],
218 ],
219 ],
220 ];
221 $expected['processedTca']['columns']['aField']['config'] = $this->defaultConfig;
222 $expected['processedTca']['columns']['aField']['config']['appearance']['levelLinksPosition'] = 'both';
223 $expected['processedTca']['columns']['aField']['config']['appearance']['enabledControls']['dragdrop'] = false;
224 $this->assertEquals($expected, $this->subject->addData($input));
225 }
226
227 /**
228 * @test
229 */
230 public function addDataForcesLevelLinksPositionWithForeignSelector()
231 {
232 $input = [
233 'processedTca' => [
234 'columns' => [
235 'aField' => [
236 'config' => [
237 'type' => 'inline',
238 'foreign_table' => 'aForeignTableName',
239 'foreign_selector' => 'aField',
240 'appearance' => [
241 'levelLinksPosition' => 'both',
242 ],
243 ],
244 ],
245 ],
246 ],
247 ];
248 $GLOBALS['TCA']['aForeignTableName']['columns']['aField']['config'] = [
249 'type' => 'select',
250 'foreign_table' => 'anotherForeignTableName',
251 ];
252 $expected['processedTca']['columns']['aField']['config'] = $this->defaultConfig;
253 $expected['processedTca']['columns']['aField']['config']['foreign_selector'] = 'aField';
254 $expected['processedTca']['columns']['aField']['config']['selectorOrUniqueConfiguration'] = [
255 'fieldName' => 'aField',
256 'isSelector' => true,
257 'isUnique' => false,
258 'config' => [
259 'type' => 'select',
260 'foreign_table' => 'anotherForeignTableName',
261 ],
262 'foreignTable' => 'anotherForeignTableName',
263 ];
264 $expected['processedTca']['columns']['aField']['config']['appearance']['levelLinksPosition'] = 'none';
265 $this->assertEquals($expected, $this->subject->addData($input));
266 }
267
268 /**
269 * @test
270 */
271 public function addDataKeepsLevelLinksPositionWithForeignSelectorAndUseCombination()
272 {
273 $input = [
274 'processedTca' => [
275 'columns' => [
276 'aField' => [
277 'config' => [
278 'type' => 'inline',
279 'foreign_table' => 'aForeignTableName',
280 'foreign_selector' => 'aField',
281 'appearance' => [
282 'useCombination' => true,
283 'levelLinksPosition' => 'both',
284 ],
285 ],
286 ],
287 ],
288 ],
289 ];
290 $GLOBALS['TCA']['aForeignTableName']['columns']['aField']['config'] = [
291 'type' => 'select',
292 'foreign_table' => 'anotherForeignTableName',
293 ];
294 $expected['processedTca']['columns']['aField']['config'] = $this->defaultConfig;
295 $expected['processedTca']['columns']['aField']['config']['foreign_selector'] = 'aField';
296 $expected['processedTca']['columns']['aField']['config']['selectorOrUniqueConfiguration'] = [
297 'fieldName' => 'aField',
298 'isSelector' => true,
299 'isUnique' => false,
300 'config' => [
301 'type' => 'select',
302 'foreign_table' => 'anotherForeignTableName',
303 ],
304 'foreignTable' => 'anotherForeignTableName',
305 ];
306 $expected['processedTca']['columns']['aField']['config']['appearance']['useCombination'] = true;
307 $expected['processedTca']['columns']['aField']['config']['appearance']['levelLinksPosition'] = 'both';
308 $this->assertEquals($expected, $this->subject->addData($input));
309 }
310
311 /**
312 * @test
313 */
314 public function addDataKeepsShowPossibleLocalizationRecordsButForcesBooleanTrue()
315 {
316 $input = [
317 'processedTca' => [
318 'columns' => [
319 'aField' => [
320 'config' => [
321 'type' => 'inline',
322 'foreign_table' => 'aForeignTableName',
323 'appearance' => [
324 'showPossibleLocalizationRecords' => '1',
325 ],
326 ],
327 ],
328 ],
329 ],
330 ];
331 $expected['processedTca']['columns']['aField']['config'] = $this->defaultConfig;
332 $expected['processedTca']['columns']['aField']['config']['appearance']['showPossibleLocalizationRecords'] = true;
333 $this->assertEquals($expected, $this->subject->addData($input));
334 }
335
336 /**
337 * @test
338 */
339 public function addDataKeepsShowPossibleLocalizationRecordsButForcesBooleanFalse()
340 {
341 $input = [
342 'processedTca' => [
343 'columns' => [
344 'aField' => [
345 'config' => [
346 'type' => 'inline',
347 'foreign_table' => 'aForeignTableName',
348 'appearance' => [
349 'showPossibleLocalizationRecords' => 0,
350 ],
351 ],
352 ],
353 ],
354 ],
355 ];
356 $expected['processedTca']['columns']['aField']['config'] = $this->defaultConfig;
357 $expected['processedTca']['columns']['aField']['config']['appearance']['showPossibleLocalizationRecords'] = false;
358 $this->assertEquals($expected, $this->subject->addData($input));
359 }
360
361 /**
362 * @test
363 */
364 public function addDataKeepshowRemovedLocalizationRecordsButForcesBooleanTrue()
365 {
366 $input = [
367 'processedTca' => [
368 'columns' => [
369 'aField' => [
370 'config' => [
371 'type' => 'inline',
372 'foreign_table' => 'aForeignTableName',
373 'appearance' => [
374 'showRemovedLocalizationRecords' => 1,
375 ],
376 ],
377 ],
378 ],
379 ],
380 ];
381 $expected['processedTca']['columns']['aField']['config'] = $this->defaultConfig;
382 $expected['processedTca']['columns']['aField']['config']['appearance']['showRemovedLocalizationRecords'] = true;
383 $this->assertEquals($expected, $this->subject->addData($input));
384 }
385
386 /**
387 * @test
388 */
389 public function addDataKeepsShowRemovedLocalizationRecordsButForcesBooleanFalse()
390 {
391 $input = [
392 'processedTca' => [
393 'columns' => [
394 'aField' => [
395 'config' => [
396 'type' => 'inline',
397 'foreign_table' => 'aForeignTableName',
398 'appearance' => [
399 'showRemovedLocalizationRecords' => '',
400 ],
401 ],
402 ],
403 ],
404 ],
405 ];
406 $expected['processedTca']['columns']['aField']['config'] = $this->defaultConfig;
407 $expected['processedTca']['columns']['aField']['config']['appearance']['showRemovedLocalizationRecords'] = false;
408 $this->assertEquals($expected, $this->subject->addData($input));
409 }
410
411 /**
412 * @test
413 */
414 public function addDataThrowsExceptionIfForeignSelectorAndForeignUniquePointToDifferentFields()
415 {
416 $input = [
417 'processedTca' => [
418 'columns' => [
419 'aField' => [
420 'config' => [
421 'type' => 'inline',
422 'foreign_table' => 'aForeignTableName',
423 'foreign_selector' => 'aField',
424 'foreign_unique' => 'aDifferentField',
425 ],
426 ],
427 ],
428 ],
429 ];
430 $this->expectException(\UnexpectedValueException::class);
431 $this->expectExceptionCode(1444995464);
432 $this->subject->addData($input);
433 }
434
435 /**
436 * @test
437 */
438 public function addDataThrowsExceptionIfForeignSelectorPointsToANotExistingField()
439 {
440 $input = [
441 'processedTca' => [
442 'columns' => [
443 'aField' => [
444 'config' => [
445 'type' => 'inline',
446 'foreign_table' => 'aForeignTableName',
447 'foreign_selector' => 'aField',
448 ],
449 ],
450 ],
451 ],
452 ];
453 $this->expectException(\UnexpectedValueException::class);
454 $this->expectExceptionCode(1444996537);
455 $this->subject->addData($input);
456 }
457
458 /**
459 * @test
460 */
461 public function addDataThrowsExceptionIfForeignUniquePointsToANotExistingField()
462 {
463 $input = [
464 'processedTca' => [
465 'columns' => [
466 'aField' => [
467 'config' => [
468 'type' => 'inline',
469 'foreign_table' => 'aForeignTableName',
470 'foreign_unique' => 'aField',
471 ],
472 ],
473 ],
474 ],
475 ];
476 $this->expectException(\UnexpectedValueException::class);
477 $this->expectExceptionCode(1444996537);
478 $this->subject->addData($input);
479 }
480
481 /**
482 * @test
483 */
484 public function addDataThrowsExceptionIfForeignUniqueTargetIsNotTypeSelectOrGroup()
485 {
486 $input = [
487 'processedTca' => [
488 'columns' => [
489 'aField' => [
490 'config' => [
491 'type' => 'inline',
492 'foreign_table' => 'aForeignTableName',
493 'foreign_unique' => 'aField',
494 ],
495 ],
496 ],
497 ],
498 ];
499 $GLOBALS['TCA']['aForeignTableName']['columns']['aField']['config'] = [
500 'type' => 'notSelectOrGroup',
501 ];
502 $this->expectException(\UnexpectedValueException::class);
503 $this->expectExceptionCode(1444996537);
504 $this->subject->addData($input);
505 }
506
507 /**
508 * @test
509 */
510 public function addDataThrowsExceptionForForeignSelectorGroupWithoutInternalTypeDb()
511 {
512 $input = [
513 'processedTca' => [
514 'columns' => [
515 'aField' => [
516 'config' => [
517 'type' => 'inline',
518 'foreign_table' => 'aForeignTableName',
519 'foreign_unique' => 'aField',
520 ],
521 ],
522 ],
523 ],
524 ];
525 $GLOBALS['TCA']['aForeignTableName']['columns']['aField']['config'] = [
526 'type' => 'group',
527 'internal_type' => 'notDb'
528 ];
529 $this->expectException(\UnexpectedValueException::class);
530 $this->expectExceptionCode(1444999130);
531 $this->subject->addData($input);
532 }
533
534 /**
535 * @test
536 */
537 public function addDataThrowsExceptionIfForeignUniqueSelectDoesNotDefineForeignTable()
538 {
539 $input = [
540 'processedTca' => [
541 'columns' => [
542 'aField' => [
543 'config' => [
544 'type' => 'inline',
545 'foreign_table' => 'aForeignTableName',
546 'foreign_unique' => 'aField',
547 ],
548 ],
549 ],
550 ],
551 ];
552 $GLOBALS['TCA']['aForeignTableName']['columns']['aField']['config'] = [
553 'type' => 'select',
554 ];
555 $this->expectException(\UnexpectedValueException::class);
556 $this->expectExceptionCode(1445078627);
557 $this->subject->addData($input);
558 }
559
560 /**
561 * @test
562 */
563 public function addDataThrowsExceptionIfForeignUniqueGroupDoesNotDefineForeignTable()
564 {
565 $input = [
566 'processedTca' => [
567 'columns' => [
568 'aField' => [
569 'config' => [
570 'type' => 'inline',
571 'foreign_table' => 'aForeignTableName',
572 'foreign_unique' => 'aField',
573 ],
574 ],
575 ],
576 ],
577 ];
578 $GLOBALS['TCA']['aForeignTableName']['columns']['aField']['config'] = [
579 'type' => 'group',
580 'internal_type' => 'db',
581 ];
582 $this->expectException(\UnexpectedValueException::class);
583 $this->expectExceptionCode(1445078628);
584 $this->subject->addData($input);
585 }
586
587 /**
588 * @test
589 */
590 public function addDataAddsSelectorOrUniqueConfigurationForForeignUnique()
591 {
592 $input = [
593 'processedTca' => [
594 'columns' => [
595 'aField' => [
596 'config' => [
597 'type' => 'inline',
598 'foreign_table' => 'aForeignTableName',
599 'foreign_unique' => 'aField',
600 ],
601 ],
602 ],
603 ],
604 ];
605 $GLOBALS['TCA']['aForeignTableName']['columns']['aField']['config'] = [
606 'type' => 'select',
607 'foreign_table' => 'anotherForeignTableName',
608 ];
609 $expected['processedTca']['columns']['aField']['config'] = $this->defaultConfig;
610 $expected['processedTca']['columns']['aField']['config']['foreign_unique'] = 'aField';
611 $expected['processedTca']['columns']['aField']['config']['selectorOrUniqueConfiguration'] = [
612 'fieldName' => 'aField',
613 'isSelector' => false,
614 'isUnique' => true,
615 'config' => [
616 'type' => 'select',
617 'foreign_table' => 'anotherForeignTableName',
618 ],
619 'foreignTable' => 'anotherForeignTableName',
620 ];
621 $this->assertEquals($expected, $this->subject->addData($input));
622 }
623
624 /**
625 * @test
626 */
627 public function addDataMergesForeignSelectorFieldTcaOverride()
628 {
629 $input = [
630 'processedTca' => [
631 'columns' => [
632 'aField' => [
633 'config' => [
634 'type' => 'inline',
635 'foreign_table' => 'aForeignTableName',
636 'foreign_selector' => 'aField',
637 'overrideChildTca' => [
638 'columns' => [
639 'aField' => [
640 'config' => [
641 'aGivenSetting' => 'aOverrideValue',
642 'aNewSetting' => 'aNewSetting',
643 'appearance' => [
644 'elementBrowserType' => 'file',
645 'elementBrowserAllowed' => 'jpg,png',
646 ],
647 ],
648 ],
649 ],
650 ],
651 ],
652 ],
653 ],
654 ],
655 ];
656 $GLOBALS['TCA']['aForeignTableName']['columns']['aField']['config'] = [
657 'type' => 'group',
658 'internal_type' => 'db',
659 'allowed' => 'anotherForeignTableName',
660 'doNotChangeMe' => 'doNotChangeMe',
661 'aGivenSetting' => 'aGivenValue',
662 ];
663
664 $expected['processedTca']['columns']['aField']['config'] = $this->defaultConfig;
665 $expected['processedTca']['columns']['aField']['config']['appearance']['levelLinksPosition'] = 'none';
666 $expected['processedTca']['columns']['aField']['config']['foreign_selector'] = 'aField';
667 $expected['processedTca']['columns']['aField']['config']['overrideChildTca']['columns']['aField'] = [
668 'config' => [
669 'aGivenSetting' => 'aOverrideValue',
670 'aNewSetting' => 'aNewSetting',
671 'appearance' => [
672 'elementBrowserType' => 'file',
673 'elementBrowserAllowed' => 'jpg,png',
674 ],
675 ],
676 ];
677
678 $expected['processedTca']['columns']['aField']['config']['selectorOrUniqueConfiguration'] = [
679 'fieldName' => 'aField',
680 'isSelector' => true,
681 'isUnique' => false,
682 'config' => [
683 'type' => 'group',
684 'internal_type' => 'db',
685 'allowed' => 'anotherForeignTableName',
686 'doNotChangeMe' => 'doNotChangeMe',
687 'aGivenSetting' => 'aOverrideValue',
688 'aNewSetting' => 'aNewSetting',
689 'appearance' => [
690 'elementBrowserType' => 'file',
691 'elementBrowserAllowed' => 'jpg,png',
692 ],
693 ],
694 'foreignTable' => 'anotherForeignTableName',
695 ];
696 $this->assertEquals($expected, $this->subject->addData($input));
697 }
698 }