fae15aa29a98f84cd0d3bc3e3af36650c654b526
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Tests / Unit / Form / FormDataProvider / TcaRecordTitleTest.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\FormDataProvider\TcaRecordTitle;
20 use TYPO3\CMS\Core\Tests\UnitTestCase;
21 use TYPO3\CMS\Lang\LanguageService;
22
23 /**
24 * Test case
25 */
26 class TcaRecordTitleTest extends UnitTestCase
27 {
28 /**
29 * @var TcaRecordTitle
30 */
31 protected $subject;
32
33 /**
34 * @var string
35 */
36 protected $timeZone;
37
38 public function setUp()
39 {
40 $this->subject = new TcaRecordTitle();
41 $this->timeZone = date_default_timezone_get();
42 date_default_timezone_set('UTC');
43 }
44
45 protected function tearDown()
46 {
47 date_default_timezone_set($this->timeZone);
48 }
49
50 /**
51 * @test
52 */
53 public function addDataThrowsExceptionWithMissingLabel()
54 {
55 $input = [
56 'tableName' => 'aTable',
57 'databaseRew' => [],
58 'processedTca' => [
59 'ctrl' => [],
60 ],
61 ];
62 $this->setExpectedException(\UnexpectedValueException::class, $this->any(), 1443706103);
63 $this->subject->addData($input);
64 }
65
66 /**
67 * @test
68 */
69 public function addDataReturnsRecordTitleForLabelUserFunction()
70 {
71 $input = [
72 'tableName' => 'aTable',
73 'databaseRow' => [],
74 'processedTca' => [
75 'ctrl' => [
76 'label' => 'uid',
77 'label_userFunc' => function (&$parameters) {
78 $parameters['title'] = 'Test';
79 }
80 ],
81 'columns' => [],
82 ],
83 ];
84
85 $expected = $input;
86 $expected['recordTitle'] = 'Test';
87
88 $this->assertSame($expected, $this->subject->addData($input));
89 }
90
91 /**
92 * @test
93 */
94 public function addDataReturnsRecordTitleForUid()
95 {
96 $input = [
97 'tableName' => 'aTable',
98 'databaseRow' => [
99 'uid' => 'NEW56017ee37d10e587251374',
100 ],
101 'processedTca' => [
102 'ctrl' => [
103 'label' => 'uid'
104 ],
105 'columns' => [],
106 ]
107 ];
108
109 /** @var LanguageService|ObjectProphecy $languageService */
110 $languageService = $this->prophesize(LanguageService::class);
111 $GLOBALS['LANG'] = $languageService->reveal();
112 $languageService->sL(Argument::cetera())->willReturnArgument(0);
113
114 $expected = $input;
115 $expected['recordTitle'] = 'NEW56017ee37d10e587251374';
116 $this->assertSame($expected, $this->subject->addData($input));
117 }
118
119 /**
120 * Data provider for addDataReturnsRecordTitleForInputType
121 * Each data set is an array with the following elements:
122 * - TCA field ['config'] section
123 * - Database value for field
124 * - expected title to be generated
125 *
126 * @returns array
127 */
128 public function addDataReturnsRecordTitleForInputTypeDataProvider()
129 {
130 return [
131 'new record' => [
132 [
133 'type' => 'input',
134 ],
135 '',
136 '',
137 ],
138 'plain text input' => [
139 [
140 'type' => 'input',
141 ],
142 'aValue',
143 'aValue',
144 ],
145 'date input' => [
146 [
147 'type' => 'input',
148 'eval' => 'date'
149 ],
150 '978307261',
151 '01-01-01 (-7 days)',
152 ],
153 'date input (dbType: date)' => [
154 [
155 'type' => 'input',
156 'eval' => 'date',
157 'dbType' => 'date'
158 ],
159 '2001-01-01',
160 '01-01-01 (-7 days)',
161 ],
162 'date input (disableAgeDisplay: TRUE)' => [
163 [
164 'type' => 'input',
165 'eval' => 'date',
166 'disableAgeDisplay' => true
167 ],
168 '978307261',
169 '01-01-01',
170 ],
171 'time input' => [
172 [
173 'type' => 'input',
174 'eval' => 'time',
175 ],
176 '44100',
177 '12:15',
178 ],
179 'timesec input' => [
180 [
181 'type' => 'input',
182 'eval' => 'timesec',
183 ],
184 '44130',
185 '12:15:30',
186 ],
187 'datetime input' => [
188 [
189 'type' => 'input',
190 'eval' => 'datetime',
191 'dbType' => 'date'
192 ],
193 '978307261',
194 '01-01-01 00:01',
195 ],
196 'datetime input (dbType: datetime)' => [
197 [
198 'type' => 'input',
199 'eval' => 'datetime',
200 'dbType' => 'datetime'
201 ],
202 '2014-12-31 23:59:59',
203 '31-12-14 23:59',
204 ],
205 ];
206 }
207
208 /**
209 * @test
210 * @dataProvider addDataReturnsRecordTitleForInputTypeDataProvider
211 *
212 * @param array $fieldConfig
213 * @param string $fieldValue
214 * @param string $expectedTitle
215 */
216 public function addDataReturnsRecordTitleForInputType($fieldConfig, $fieldValue, $expectedTitle)
217 {
218 $input = [
219 'tableName' => 'aTable',
220 'databaseRow' => [
221 'uid' => '1',
222 'aField' => $fieldValue,
223 ],
224 'processedTca' => [
225 'ctrl' => [
226 'label' => 'aField'
227 ],
228 'columns' => [
229 'aField' => [
230 'config' => $fieldConfig,
231 ]
232 ],
233 ]
234 ];
235
236 /** @var LanguageService|ObjectProphecy $languageService */
237 $languageService = $this->prophesize(LanguageService::class);
238 $GLOBALS['LANG'] = $languageService->reveal();
239 $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysYears')
240 ->willReturn(' min| hrs| days| yrs| min| hour| day| year');
241 $languageService->sL(Argument::cetera())->willReturnArgument(0);
242 $GLOBALS['EXEC_TIME'] = 978912061;
243
244 $expected = $input;
245 $expected['recordTitle'] = $expectedTitle;
246 $this->assertSame($expected, $this->subject->addData($input));
247 }
248
249 /**
250 * @test
251 */
252 public function addDataReturnsRecordTitleWithAlternativeLabel()
253 {
254 $input = [
255 'tableName' => 'aTable',
256 'databaseRow' => [
257 'uid' => '1',
258 'aField' => '',
259 'anotherField' => 'anotherValue',
260 ],
261 'processedTca' => [
262 'ctrl' => [
263 'label' => 'aField',
264 'label_alt' => 'anotherField',
265 ],
266 'columns' => [
267 'aField' => [
268 'config' => [
269 'type' => 'input'
270 ]
271 ],
272 'anotherField' => [
273 'config' => [
274 'type' => 'input'
275 ]
276 ]
277 ],
278 ]
279 ];
280
281 $expected = $input;
282 $expected['recordTitle'] = 'anotherValue';
283 $this->assertSame($expected, $this->subject->addData($input));
284 }
285
286 /**
287 * @test
288 */
289 public function addDataReturnsRecordTitleWithMultipleAlternativeLabels()
290 {
291 $input = [
292 'tableName' => 'aTable',
293 'databaseRow' => [
294 'uid' => '1',
295 'aField' => '',
296 'anotherField' => '',
297 'additionalField' => 'additionalValue'
298 ],
299 'processedTca' => [
300 'ctrl' => [
301 'label' => 'aField',
302 'label_alt' => 'anotherField,additionalField',
303 ],
304 'columns' => [
305 'aField' => [
306 'config' => [
307 'type' => 'input'
308 ]
309 ],
310 'anotherField' => [
311 'config' => [
312 'type' => 'input'
313 ]
314 ],
315 'additionalField' => [
316 'config' => [
317 'type' => 'input'
318 ]
319 ],
320 ],
321 ]
322 ];
323
324 $expected = $input;
325 $expected['recordTitle'] = 'additionalValue';
326 $this->assertSame($expected, $this->subject->addData($input));
327 }
328
329 /**
330 * @test
331 */
332 public function addDataReturnsRecordTitleWithForcedAlternativeLabel()
333 {
334 $input = [
335 'tableName' => 'aTable',
336 'databaseRow' => [
337 'uid' => '1',
338 'aField' => 'aField',
339 'anotherField' => 'anotherField'
340 ],
341 'processedTca' => [
342 'ctrl' => [
343 'label' => 'aField',
344 'label_alt' => 'anotherField',
345 'label_alt_force' => true,
346 ],
347 'columns' => [
348 'aField' => [
349 'config' => [
350 'type' => 'input'
351 ]
352 ],
353 'anotherField' => [
354 'config' => [
355 'type' => 'input'
356 ]
357 ],
358 ],
359 ]
360 ];
361
362 $expected = $input;
363 $expected['recordTitle'] = 'aField, anotherField';
364 $this->assertSame($expected, $this->subject->addData($input));
365 }
366
367 /**
368 * @test
369 */
370 public function addDataReturnsRecordTitleWithMultipleForcedAlternativeLabels()
371 {
372 $input = [
373 'tableName' => 'aTable',
374 'databaseRow' => [
375 'uid' => '1',
376 'aField' => 'aField',
377 'anotherField' => 'anotherField',
378 'additionalField' => 'additionalValue'
379 ],
380 'processedTca' => [
381 'ctrl' => [
382 'label' => 'aField',
383 'label_alt' => 'anotherField,additionalField',
384 'label_alt_force' => true,
385 ],
386 'columns' => [
387 'aField' => [
388 'config' => [
389 'type' => 'input'
390 ]
391 ],
392 'anotherField' => [
393 'config' => [
394 'type' => 'input'
395 ]
396 ],
397 'additionalField' => [
398 'config' => [
399 'type' => 'input'
400 ]
401 ],
402 ],
403 ]
404 ];
405
406 $expected = $input;
407 $expected['recordTitle'] = 'aField, anotherField, additionalValue';
408 $this->assertSame($expected, $this->subject->addData($input));
409 }
410
411 /**
412 * @test
413 */
414 public function addDataReturnsRecordTitleIgnoresEmptyAlternativeLabels()
415 {
416 $input = [
417 'tableName' => 'aTable',
418 'databaseRow' => [
419 'uid' => '1',
420 'aField' => 'aField',
421 'anotherField' => '',
422 'additionalField' => 'additionalValue'
423 ],
424 'processedTca' => [
425 'ctrl' => [
426 'label' => 'aField',
427 'label_alt' => 'anotherField,additionalField',
428 'label_alt_force' => true,
429 ],
430 'columns' => [
431 'aField' => [
432 'config' => [
433 'type' => 'input'
434 ]
435 ],
436 'anotherField' => [
437 'config' => [
438 'type' => 'input'
439 ]
440 ],
441 'additionalField' => [
442 'config' => [
443 'type' => 'input'
444 ]
445 ],
446 ],
447 ]
448 ];
449
450 $expected = $input;
451 $expected['recordTitle'] = 'aField, additionalValue';
452 $this->assertSame($expected, $this->subject->addData($input));
453 }
454
455 /**
456 * @test
457 */
458 public function addDataReturnsRecordTitleForRadioType()
459 {
460 $input = [
461 'tableName' => 'aTable',
462 'databaseRow' => [
463 'uid' => '1',
464 'aField' => '2',
465 ],
466 'processedTca' => [
467 'ctrl' => [
468 'label' => 'aField'
469 ],
470 'columns' => [
471 'aField' => [
472 'config' => [
473 'type' => 'radio',
474 'items' => [
475 ['foo', 1],
476 ['bar', 2],
477 ['baz', 3],
478 ]
479 ]
480 ]
481 ],
482 ]
483 ];
484
485 $expected = $input;
486 $expected['recordTitle'] = 'bar';
487 $this->assertSame($expected, $this->subject->addData($input));
488 }
489
490 /**
491 * Data provider for addDataReturnsRecordTitleForGroupType
492 * Each data set is an array with the following elements:
493 * - TCA field configuration (merged with base config)
494 * - Database value for field
495 * - expected title to be generated
496 *
497 * @returns array
498 */
499 public function addDataReturnsRecordTitleForGroupTypeDataProvider()
500 {
501 return [
502 'new record' => [
503 [
504 'internal_type' => 'db',
505 ],
506 '',
507 ''
508 ],
509 'internal_type: file' => [
510 [
511 'internal_type' => 'file',
512 ],
513 'somePath/aFile.jpg,someOtherPath/anotherFile.png',
514 'somePath/aFile.jpg, someOtherPath/anotherFile.png',
515 ],
516 'internal_type: db, single table, single record' => [
517 [
518 'internal_type' => 'db',
519 'allowed' => 'aTable'
520 ],
521 '1|aValue',
522 'aValue',
523 ],
524 'internal_type: db, single table, multiple records' => [
525 [
526 'internal_type' => 'db',
527 'allowed' => 'aTable'
528 ],
529 '1|aValue,3|anotherValue',
530 'aValue, anotherValue',
531 ],
532 'internal_type: db, multiple tables, single record' => [
533 [
534 'internal_type' => 'db',
535 'allowed' => 'aTable,anotherTable'
536 ],
537 'anotherTable_1|anotherValue',
538 'anotherValue',
539 ],
540 'internal_type: db, multiple tables, multiple records' => [
541 [
542 'internal_type' => 'db',
543 'allowed' => 'aTable,anotherTable'
544 ],
545 'anotherTable_1|anotherValue,aTable_1|aValue',
546 'aValue, anotherValue',
547 ],
548 ];
549 }
550
551 /**
552 * @test
553 * @dataProvider addDataReturnsRecordTitleForGroupTypeDataProvider
554 *
555 * @param array $fieldConfig
556 * @param string $fieldValue
557 * @param string $expectedTitle
558 */
559 public function addDataReturnsRecordTitleForGroupType($fieldConfig, $fieldValue, $expectedTitle)
560 {
561 $input = [
562 'tableName' => 'aTable',
563 'databaseRow' => [
564 'uid' => '1',
565 'aField' => $fieldValue,
566 ],
567 'processedTca' => [
568 'ctrl' => [
569 'label' => 'aField'
570 ],
571 'columns' => [
572 'aField' => [
573 'config' => array_merge(
574 [
575 'type' => 'group',
576 ],
577 $fieldConfig
578 ),
579 ]
580 ],
581 ]
582 ];
583
584 /** @var LanguageService|ObjectProphecy $languageService */
585 $languageService = $this->prophesize(LanguageService::class);
586 $GLOBALS['LANG'] = $languageService->reveal();
587 $languageService->sL(Argument::cetera())->willReturnArgument(0);
588
589 $expected = $input;
590 $expected['recordTitle'] = $expectedTitle;
591 $this->assertSame($expected, $this->subject->addData($input));
592 }
593
594 /**
595 * @test
596 */
597 public function addDataReturnsRecordTitleForGroupTypeWithInternalTypeDb()
598 {
599 $input = [
600 'tableName' => 'aTable',
601 'databaseRow' => [
602 'uid' => '1',
603 'aField' => 'aTable_1|aValue,anotherTable_2|anotherValue',
604 ],
605 'processedTca' => [
606 'ctrl' => [
607 'label' => 'aField'
608 ],
609 'columns' => [
610 'aField' => [
611 'config' => [
612 'type' => 'group',
613 'internal_type' => 'db',
614 'allowed' => 'aTable,anotherTable',
615 ]
616 ]
617 ],
618 ]
619 ];
620
621 $expected = $input;
622 $expected['recordTitle'] = 'aValue, anotherValue';
623 $this->assertSame($expected, $this->subject->addData($input));
624 }
625
626 /**
627 * @test
628 */
629 public function addDataReturnsRecordTitleForSingleCheckboxType()
630 {
631 $input = [
632 'tableName' => 'aTable',
633 'databaseRow' => [
634 'aField' => 1,
635 ],
636 'processedTca' => [
637 'ctrl' => [
638 'label' => 'aField'
639 ],
640 'columns' => [
641 'aField' => [
642 'config' => [
643 'type' => 'check',
644 ]
645 ]
646 ],
647 ]
648 ];
649
650 /** @var LanguageService|ObjectProphecy $languageService */
651 $languageService = $this->prophesize(LanguageService::class);
652 $GLOBALS['LANG'] = $languageService->reveal();
653 $languageService->sL(Argument::cetera())->willReturnArgument(0)->shouldBeCalled();
654
655 $expected = $input;
656 $expected['recordTitle'] = 'LLL:EXT:lang/locallang_common.xlf:yes';
657 $this->assertSame($expected, $this->subject->addData($input));
658 }
659
660 /**
661 * @test
662 */
663 public function addDataReturnsRecordTitleForArrayCheckboxType()
664 {
665 $input = [
666 'tableName' => 'aTable',
667 'databaseRow' => [
668 'aField' => '5'
669 ],
670 'processedTca' => [
671 'ctrl' => [
672 'label' => 'aField'
673 ],
674 'columns' => [
675 'aField' => [
676 'config' => [
677 'type' => 'check',
678 'items' => [
679 ['foo', ''],
680 ['bar', ''],
681 ['baz', ''],
682 ]
683 ]
684 ]
685 ],
686 ]
687 ];
688
689 $expected = $input;
690 $expected['recordTitle'] = 'foo, baz';
691 $this->assertSame($expected, $this->subject->addData($input));
692 }
693
694 /**
695 * @test
696 */
697 public function addDataReturnsEmptyRecordTitleForFlexType()
698 {
699 $input = [
700 'tableName' => 'aTable',
701 'databaseRow' => [
702 'aField' => [
703 'data' => [
704 'sDEF' => [
705 'lDEF' => [
706 'aFlexField' => [
707 'vDEF' => 'aFlexValue',
708 ]
709 ]
710 ]
711 ]
712 ]
713 ],
714 'processedTca' => [
715 'ctrl' => [
716 'label' => 'aField'
717 ],
718 'columns' => [
719 'aField' => [
720 'config' => [
721 'type' => 'flex',
722 'ds' => [
723 'sheets' => [
724 'sDEF' => [
725 'ROOT' => [
726 'type' => 'array',
727 'el' => [
728 'aFlexField' => [
729 'label' => 'Some input field',
730 'config' => [
731 'type' => 'input',
732 ],
733 ],
734 ],
735 ],
736 ],
737 ],
738 ]
739
740 ]
741 ]
742 ],
743 ]
744 ];
745
746 $expected = $input;
747 $expected['recordTitle'] = '';
748 $this->assertSame($expected, $this->subject->addData($input));
749 }
750
751 /**
752 * @test
753 */
754 public function addDataReturnsRecordTitleForSelectType()
755 {
756 $input = [
757 'tableName' => 'aTable',
758 'databaseRow' => [
759 'aField' => [
760 '1',
761 '2'
762 ]
763 ],
764 'processedTca' => [
765 'ctrl' => [
766 'label' => 'aField'
767 ],
768 'columns' => [
769 'aField' => [
770 'config' => [
771 'type' => 'select',
772 'items' => [
773 ['foo', 1, null, null],
774 ['bar', 2, null, null],
775 ['baz', 4, null, null],
776 ]
777 ]
778 ]
779 ],
780 ]
781 ];
782
783 $expected = $input;
784 $expected['recordTitle'] = 'foo, bar';
785 $this->assertSame($expected, $this->subject->addData($input));
786 }
787
788 /**
789 * @test
790 */
791 public function addDataReturnsStrippedAndTrimmedValueForTextType()
792 {
793 $input = [
794 'tableName' => 'aTable',
795 'databaseRow' => [
796 'aField' => '<p> text </p>',
797 ],
798 'processedTca' => [
799 'ctrl' => [
800 'label' => 'aField',
801 ],
802 'columns' => [
803 'aField' => [
804 'config' => [
805 'type' => 'text',
806 ],
807 ],
808 ],
809 ],
810 ];
811
812 $expected = $input;
813 $expected['recordTitle'] = 'text';
814 $this->assertSame($expected, $this->subject->addData($input));
815 }
816 }