[TASK] Make BackendUtilityTest notice free
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Tests / Unit / Utility / BackendUtilityTest.php
1 <?php
2 namespace TYPO3\CMS\Backend\Tests\Unit\Utility;
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\Tests\Unit\Utility\Fixtures\BackendUtilityFixture;
20 use TYPO3\CMS\Backend\Tests\Unit\Utility\Fixtures\LabelFromItemListMergedReturnsCorrectFieldsFixture;
21 use TYPO3\CMS\Backend\Tests\Unit\Utility\Fixtures\ProcessedValueForGroupWithMultipleAllowedTablesFixture;
22 use TYPO3\CMS\Backend\Tests\Unit\Utility\Fixtures\ProcessedValueForGroupWithOneAllowedTableFixture;
23 use TYPO3\CMS\Backend\Tests\Unit\Utility\Fixtures\ProcessedValueForSelectWithMMRelationFixture;
24 use TYPO3\CMS\Backend\Utility\BackendUtility;
25 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
26 use TYPO3\CMS\Core\Database\Connection;
27 use TYPO3\CMS\Core\Database\ConnectionPool;
28 use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
29 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
30 use TYPO3\CMS\Core\Database\Query\Restriction\DefaultRestrictionContainer;
31 use TYPO3\CMS\Core\Database\RelationHandler;
32 use TYPO3\CMS\Core\Localization\LanguageService;
33 use TYPO3\CMS\Core\Utility\GeneralUtility;
34
35 /**
36 * Test case
37 */
38 class BackendUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
39 {
40 ///////////////////////////////////////
41 // Tests concerning calcAge
42 ///////////////////////////////////////
43 /**
44 * Data provider for calcAge function
45 *
46 * @return array
47 */
48 public function calcAgeDataProvider()
49 {
50 return [
51 'Single year' => [
52 'seconds' => 60 * 60 * 24 * 365,
53 'expectedLabel' => '1 year'
54 ],
55 'Plural years' => [
56 'seconds' => 60 * 60 * 24 * 365 * 2,
57 'expectedLabel' => '2 yrs'
58 ],
59 'Single negative year' => [
60 'seconds' => 60 * 60 * 24 * 365 * -1,
61 'expectedLabel' => '-1 year'
62 ],
63 'Plural negative years' => [
64 'seconds' => 60 * 60 * 24 * 365 * 2 * -1,
65 'expectedLabel' => '-2 yrs'
66 ],
67 'Single day' => [
68 'seconds' => 60 * 60 * 24,
69 'expectedLabel' => '1 day'
70 ],
71 'Plural days' => [
72 'seconds' => 60 * 60 * 24 * 2,
73 'expectedLabel' => '2 days'
74 ],
75 'Single negative day' => [
76 'seconds' => 60 * 60 * 24 * -1,
77 'expectedLabel' => '-1 day'
78 ],
79 'Plural negative days' => [
80 'seconds' => 60 * 60 * 24 * 2 * -1,
81 'expectedLabel' => '-2 days'
82 ],
83 'Single hour' => [
84 'seconds' => 60 * 60,
85 'expectedLabel' => '1 hour'
86 ],
87 'Plural hours' => [
88 'seconds' => 60 * 60 * 2,
89 'expectedLabel' => '2 hrs'
90 ],
91 'Single negative hour' => [
92 'seconds' => 60 * 60 * -1,
93 'expectedLabel' => '-1 hour'
94 ],
95 'Plural negative hours' => [
96 'seconds' => 60 * 60 * 2 * -1,
97 'expectedLabel' => '-2 hrs'
98 ],
99 'Single minute' => [
100 'seconds' => 60,
101 'expectedLabel' => '1 min'
102 ],
103 'Plural minutes' => [
104 'seconds' => 60 * 2,
105 'expectedLabel' => '2 min'
106 ],
107 'Single negative minute' => [
108 'seconds' => 60 * -1,
109 'expectedLabel' => '-1 min'
110 ],
111 'Plural negative minutes' => [
112 'seconds' => 60 * 2 * -1,
113 'expectedLabel' => '-2 min'
114 ],
115 'Zero seconds' => [
116 'seconds' => 0,
117 'expectedLabel' => '0 min'
118 ]
119 ];
120 }
121
122 /**
123 * @test
124 * @dataProvider calcAgeDataProvider
125 *
126 * @param int $seconds
127 * @param string $expectedLabel
128 */
129 public function calcAgeReturnsExpectedValues($seconds, $expectedLabel)
130 {
131 $this->assertSame($expectedLabel, BackendUtility::calcAge($seconds));
132 }
133
134 ///////////////////////////////////////
135 // Tests concerning getProcessedValue
136 ///////////////////////////////////////
137 /**
138 * @test
139 * @see http://forge.typo3.org/issues/20994
140 */
141 public function getProcessedValueForZeroStringIsZero()
142 {
143 $GLOBALS['TCA'] = [
144 'tt_content' => [
145 'columns' => [
146 'header' => [
147 'config' => [
148 'type' => 'input',
149 ],
150 ],
151 ],
152 ],
153 ];
154 $GLOBALS['LANG'] = [];
155 $this->assertEquals('0', BackendUtility::getProcessedValue('tt_content', 'header', '0'));
156 }
157
158 /**
159 * @test
160 */
161 public function getProcessedValueForGroup()
162 {
163 $GLOBALS['TCA'] = [
164 'tt_content' => [
165 'columns' => [
166 'multimedia' => [
167 'config' => [
168 'type' => 'group',
169 ],
170 ],
171 ],
172 ],
173 ];
174 $GLOBALS['LANG'] = [];
175 $this->assertSame('1, 2', BackendUtility::getProcessedValue('tt_content', 'multimedia', '1,2'));
176 }
177
178 /**
179 * @test
180 */
181 public function getProcessedValueForGroupWithOneAllowedTable()
182 {
183 $GLOBALS['TCA'] = [
184 'tt_content' => [
185 'columns' => [
186 'pages' => [
187 'config' => [
188 'type' => 'group',
189 'allowed' => 'pages',
190 'internal_type' => 'db',
191 'maxitems' => 22,
192 'minitems' => 0,
193 'size' => 3,
194 ],
195 ],
196 ],
197 ],
198 ];
199 $GLOBALS['LANG'] = [];
200 $this->assertSame('Page 1, Page 2', ProcessedValueForGroupWithOneAllowedTableFixture::getProcessedValue('tt_content', 'pages', '1,2'));
201 }
202
203 /**
204 * @test
205 */
206 public function getProcessedValueForGroupWithMultipleAllowedTables()
207 {
208 $GLOBALS['TCA'] = [
209 'index_config' => [
210 'columns' => [
211 'indexcfgs' => [
212 'config' => [
213 'type' => 'group',
214 'internal_type' => 'db',
215 'allowed' => 'index_config,pages',
216 'size' => 5,
217 ],
218 ],
219 ],
220 ],
221 ];
222 $GLOBALS['LANG'] = [];
223 $this->assertSame('Page 1, Configuration 2', ProcessedValueForGroupWithMultipleAllowedTablesFixture::getProcessedValue('index_config', 'indexcfgs', 'pages_1,index_config_2'));
224 }
225
226 /**
227 * Prepare a mock database setup for a Doctrine connection
228 * and return an array of all prophets to set expectations upon.
229 *
230 * @param string $tableName
231 * @return array
232 */
233 protected function mockDatabaseConnection($tableName = 'sys_category')
234 {
235 $connectionProphet = $this->prophesize(Connection::class);
236 $connectionProphet->quote(Argument::cetera())->will(function ($arguments) {
237 return "'" . $arguments[0] . "'";
238 });
239 $connectionProphet->quoteIdentifier(Argument::cetera())->will(function ($arguments) {
240 return '`' . $arguments[0] . '`';
241 });
242
243 $restrictionProphet = $this->prophesize(DefaultRestrictionContainer::class);
244 $restrictionProphet->removeAll()->willReturn($restrictionProphet->reveal());
245 $restrictionProphet->add(Argument::cetera())->willReturn($restrictionProphet->reveal());
246
247 $queryBuilderProphet = $this->prophesize(QueryBuilder::class);
248 $queryBuilderProphet->expr()->willReturn(
249 GeneralUtility::makeInstance(ExpressionBuilder::class, $connectionProphet->reveal())
250 );
251 $queryBuilderProphet->getRestrictions()->willReturn($restrictionProphet->reveal());
252 $queryBuilderProphet->quoteIdentifier(Argument::cetera())->will(function ($arguments) {
253 return '`' . $arguments[0] . '`';
254 });
255
256 $connectionPoolProphet = $this->prophesize(ConnectionPool::class);
257 $connectionPoolProphet->getConnectionForTable($tableName)
258 ->willReturn($connectionProphet->reveal());
259 $connectionPoolProphet->getQueryBuilderForTable($tableName)
260 ->shouldBeCalled()
261 ->willReturn($queryBuilderProphet->reveal());
262
263 return [$queryBuilderProphet, $connectionPoolProphet, $connectionProphet, $restrictionProphet];
264 }
265
266 /**
267 * @test
268 */
269 public function getProcessedValueForSelectWithMMRelation()
270 {
271 /** @var RelationHandler|ObjectProphecy $relationHandlerProphet */
272 $relationHandlerProphet = $this->prophesize(RelationHandler::class);
273 $relationHandlerProphet->start(Argument::cetera())->shouldBeCalled();
274
275 $relationHandlerInstance = $relationHandlerProphet->reveal();
276 $relationHandlerInstance->tableArray['sys_category'] = [1, 2];
277
278 list($queryBuilderProphet, $connectionPoolProphet) = $this->mockDatabaseConnection('sys_category');
279 $statementProphet = $this->prophesize(\Doctrine\DBAL\Driver\Statement::class);
280 $statementProphet->fetch()->shouldBeCalled()->willReturn(
281 [
282 'uid' => 1,
283 'title' => 'Category 1',
284 ],
285 [
286 'uid' => 2,
287 'title' => 'Category 2',
288 ],
289 false
290 );
291
292 /** @var QueryBuilder|ObjectProphecy $queryBuilderProphet */
293 $queryBuilderProphet->select('uid', 'sys_category.title')->willReturn($queryBuilderProphet->reveal());
294 $queryBuilderProphet->from('sys_category')->willReturn($queryBuilderProphet->reveal());
295 $queryBuilderProphet->where('`uid` IN (:dcValue1)')->willReturn($queryBuilderProphet->reveal());
296 $queryBuilderProphet->createNamedParameter([1, 2], Connection::PARAM_INT_ARRAY)->willReturn(':dcValue1');
297 $queryBuilderProphet->execute()->willReturn($statementProphet->reveal());
298
299 GeneralUtility::addInstance(RelationHandler::class, $relationHandlerInstance);
300 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
301
302 $GLOBALS['TCA'] = [
303 'pages' => [
304 'columns' => [
305 'categories' => [
306 'config' => [
307 'type' => 'select',
308 'foreign_table' => 'sys_category',
309 'MM' => 'sys_category_record_mm',
310 'MM_match_fields' => [
311 'fieldname' => 'categories',
312 'tablesnames' => 'pages',
313 ],
314 'MM_opposite_field' => 'items',
315 ],
316 ],
317 ],
318 ],
319 'sys_category' => [
320 'ctrl' => ['label' => 'title'],
321 'columns' => [
322 'items' => [
323 'config' => [
324 'type' => 'group',
325 'internal_type' => 'db',
326 'allowed' => '*',
327 'MM' => 'sys_category_record_mm',
328 'MM_oppositeUsage' => [],
329 ]
330 ]
331 ],
332 ],
333 ];
334 $GLOBALS['LANG'] = [];
335
336 $this->assertSame(
337 'Category 1; Category 2',
338 ProcessedValueForSelectWithMMRelationFixture::getProcessedValue(
339 'pages',
340 'categories',
341 '2',
342 0,
343 false,
344 false,
345 1
346 )
347 );
348 }
349
350 /**
351 * @test
352 */
353 public function getProcessedValueDisplaysAgeForDateInputFieldsIfSettingAbsent()
354 {
355 /** @var ObjectProphecy $languageServiceProphecy */
356 $languageServiceProphecy = $this->prophesize(LanguageService::class);
357 $languageServiceProphecy->sL(Argument::cetera())->willReturn(' min| hrs| days| yrs| min| hour| day| year');
358 $GLOBALS['LANG'] = $languageServiceProphecy->reveal();
359
360 $GLOBALS['EXEC_TIME'] = mktime(0, 0, 0, 8, 30, 2015);
361
362 $GLOBALS['TCA'] = [
363 'tt_content' => [
364 'columns' => [
365 'date' => [
366 'config' => [
367 'type' => 'input',
368 'eval' => 'date',
369 ],
370 ],
371 ],
372 ],
373 ];
374 $this->assertSame('28-08-15 (-2 days)', BackendUtility::getProcessedValue('tt_content', 'date', mktime(0, 0, 0, 8, 28, 2015)));
375 }
376
377 /**
378 * @return array
379 */
380 public function inputTypeDateDisplayOptions()
381 {
382 return [
383 'typeSafe Setting' => [
384 true,
385 '28-08-15',
386 ],
387 'non typesafe setting' => [
388 1,
389 '28-08-15',
390 ],
391 'setting disabled typesafe' => [
392 false,
393 '28-08-15 (-2 days)',
394 ],
395 'setting disabled not typesafe' => [
396 0,
397 '28-08-15 (-2 days)',
398 ],
399 ];
400 }
401
402 /**
403 * @test
404 *
405 * @dataProvider inputTypeDateDisplayOptions
406 *
407 * @param string $input
408 * @param string $expected
409 */
410 public function getProcessedValueHandlesAgeDisplayCorrectly($input, $expected)
411 {
412 /** @var ObjectProphecy $languageServiceProphecy */
413 $languageServiceProphecy = $this->prophesize(LanguageService::class);
414 $languageServiceProphecy->sL(Argument::cetera())->willReturn(' min| hrs| days| yrs| min| hour| day| year');
415 $GLOBALS['LANG'] = $languageServiceProphecy->reveal();
416
417 $GLOBALS['EXEC_TIME'] = mktime(0, 0, 0, 8, 30, 2015);
418
419 $GLOBALS['TCA'] = [
420 'tt_content' => [
421 'columns' => [
422 'date' => [
423 'config' => [
424 'type' => 'input',
425 'eval' => 'date',
426 'disableAgeDisplay' => $input,
427 ],
428 ],
429 ],
430 ],
431 ];
432 $this->assertSame($expected, BackendUtility::getProcessedValue('tt_content', 'date', mktime(0, 0, 0, 8, 28, 2015)));
433 }
434
435 /**
436 * Tests concerning getCommonSelectFields
437 */
438
439 /**
440 * Data provider for getCommonSelectFieldsReturnsCorrectFields
441 *
442 * @return array The test data with $table, $prefix, $presetFields, $tca, $expectedFields
443 */
444 public function getCommonSelectFieldsReturnsCorrectFieldsDataProvider()
445 {
446 return [
447 'only uid' => [
448 'table' => 'test_table',
449 'prefix' => '',
450 'presetFields' => [],
451 'tca' => [],
452 'expectedFields' => 'uid'
453 ],
454 'label set' => [
455 'table' => 'test_table',
456 'prefix' => '',
457 'presetFields' => [],
458 'tca' => [
459 'ctrl' => [
460 'label' => 'label'
461 ]
462 ],
463 'expectedFields' => 'uid,label'
464 ],
465 'label_alt set' => [
466 'table' => 'test_table',
467 'prefix' => '',
468 'presetFields' => [],
469 'tca' => [
470 'ctrl' => [
471 'label_alt' => 'label,label2'
472 ]
473 ],
474 'expectedFields' => 'uid,label,label2'
475 ],
476 'versioningWS set' => [
477 'table' => 'test_table',
478 'prefix' => '',
479 'presetFields' => [],
480 'tca' => [
481 'ctrl' => [
482 'versioningWS' => true
483 ]
484 ],
485 'expectedFields' => 'uid,t3ver_id,t3ver_state,t3ver_wsid,t3ver_count'
486 ],
487 'selicon_field set' => [
488 'table' => 'test_table',
489 'prefix' => '',
490 'presetFields' => [],
491 'tca' => [
492 'ctrl' => [
493 'selicon_field' => 'field'
494 ]
495 ],
496 'expectedFields' => 'uid,field'
497 ],
498 'typeicon_column set' => [
499 'table' => 'test_table',
500 'prefix' => '',
501 'presetFields' => [],
502 'tca' => [
503 'ctrl' => [
504 'typeicon_column' => 'field'
505 ]
506 ],
507 'expectedFields' => 'uid,field'
508 ],
509 'enablecolumns set' => [
510 'table' => 'test_table',
511 'prefix' => '',
512 'presetFields' => [],
513 'tca' => [
514 'ctrl' => [
515 'enablecolumns' => [
516 'disabled' => 'hidden',
517 'starttime' => 'start',
518 'endtime' => 'stop',
519 'fe_group' => 'groups'
520 ]
521 ]
522 ],
523 'expectedFields' => 'uid,hidden,start,stop,groups'
524 ],
525 'label set to uid' => [
526 'table' => 'test_table',
527 'prefix' => '',
528 'presetFields' => [],
529 'tca' => [
530 'ctrl' => [
531 'label' => 'uid'
532 ]
533 ],
534 'expectedFields' => 'uid'
535 ]
536 ];
537 }
538
539 /**
540 * @test
541 * @dataProvider getCommonSelectFieldsReturnsCorrectFieldsDataProvider
542 *
543 * @param string $table
544 * @param string $prefix
545 * @param array $presetFields
546 * @param array $tca
547 * @param string $expectedFields
548 */
549 public function getCommonSelectFieldsReturnsCorrectFields($table, $prefix = '', array $presetFields, array $tca, $expectedFields = '')
550 {
551 $GLOBALS['TCA'][$table] = $tca;
552 $selectFields = BackendUtility::getCommonSelectFields($table, $prefix, $presetFields);
553 $this->assertEquals($selectFields, $expectedFields);
554 }
555
556 /**
557 * Tests concerning getLabelFromItemlist
558 */
559
560 /**
561 * Data provider for getLabelFromItemlistReturnsCorrectFields
562 *
563 * @return array The test data with $table, $col, $key, $expectedLabel
564 */
565 public function getLabelFromItemlistReturnsCorrectFieldsDataProvider()
566 {
567 return [
568 'item set' => [
569 'table' => 'tt_content',
570 'col' => 'menu_type',
571 'key' => '1',
572 'tca' => [
573 'columns' => [
574 'menu_type' => [
575 'config' => [
576 'items' => [
577 ['Item 1', '0'],
578 ['Item 2', '1'],
579 ['Item 3', '3']
580 ]
581 ]
582 ]
583 ]
584 ],
585 'expectedLabel' => 'Item 2'
586 ],
587 'item set twice' => [
588 'table' => 'tt_content',
589 'col' => 'menu_type',
590 'key' => '1',
591 'tca' => [
592 'columns' => [
593 'menu_type' => [
594 'config' => [
595 'items' => [
596 ['Item 1', '0'],
597 ['Item 2a', '1'],
598 ['Item 2b', '1'],
599 ['Item 3', '3']
600 ]
601 ]
602 ]
603 ]
604 ],
605 'expectedLabel' => 'Item 2a'
606 ],
607 'item not found' => [
608 'table' => 'tt_content',
609 'col' => 'menu_type',
610 'key' => '5',
611 'tca' => [
612 'columns' => [
613 'menu_type' => [
614 'config' => [
615 'items' => [
616 ['Item 1', '0'],
617 ['Item 2', '1'],
618 ['Item 3', '2']
619 ]
620 ]
621 ]
622 ]
623 ],
624 'expectedLabel' => null
625 ]
626 ];
627 }
628
629 /**
630 * @test
631 * @dataProvider getLabelFromItemlistReturnsCorrectFieldsDataProvider
632 *
633 * @param string $table
634 * @param string $col
635 * @param string $key
636 * @param array $tca
637 * @param string $expectedLabel
638 */
639 public function getLabelFromItemlistReturnsCorrectFields($table, $col = '', $key = '', array $tca, $expectedLabel = '')
640 {
641 $GLOBALS['TCA'][$table] = $tca;
642 $label = BackendUtility::getLabelFromItemlist($table, $col, $key);
643 $this->assertEquals($label, $expectedLabel);
644 }
645
646 /**
647 * Tests concerning getLabelFromItemListMerged
648 */
649
650 /**
651 * Data provider for getLabelFromItemListMerged
652 *
653 * @return array The test data with $pageId, $table, $column, $key, $expectedLabel
654 */
655 public function getLabelFromItemListMergedReturnsCorrectFieldsDataProvider()
656 {
657 return [
658 'no field found' => [
659 'pageId' => '123',
660 'table' => 'tt_content',
661 'col' => 'menu_type',
662 'key' => '10',
663 'tca' => [
664 'columns' => [
665 'menu_type' => [
666 'config' => [
667 'items' => [
668 ['Item 1', '0'],
669 ['Item 2', '1'],
670 ['Item 3', '3']
671 ]
672 ]
673 ]
674 ]
675 ],
676 'expectedLabel' => ''
677 ],
678 'no tsconfig set' => [
679 'pageId' => '123',
680 'table' => 'tt_content',
681 'col' => 'menu_type',
682 'key' => '1',
683 'tca' => [
684 'columns' => [
685 'menu_type' => [
686 'config' => [
687 'items' => [
688 ['Item 1', '0'],
689 ['Item 2', '1'],
690 ['Item 3', '3']
691 ]
692 ]
693 ]
694 ]
695 ],
696 'expectedLabel' => 'Item 2'
697 ]
698 ];
699 }
700
701 /**
702 * @test
703 * @dataProvider getLabelFromItemListMergedReturnsCorrectFieldsDataProvider
704 *
705 * @param int $pageId
706 * @param string $table
707 * @param string $column
708 * @param string $key
709 * @param array $tca
710 * @param string $expectedLabel
711 */
712 public function getLabelFromItemListMergedReturnsCorrectFields($pageId, $table, $column = '', $key = '', array $tca, $expectedLabel = '')
713 {
714 $GLOBALS['TCA'][$table] = $tca;
715
716 $this->assertEquals($expectedLabel, LabelFromItemListMergedReturnsCorrectFieldsFixture::getLabelFromItemListMerged($pageId, $table, $column, $key));
717 }
718
719 /**
720 * Tests concerning getFuncCheck
721 */
722
723 /**
724 * @test
725 */
726 public function getFuncCheckReturnsInputTagWithValueAttribute()
727 {
728 $this->assertStringMatchesFormat('<input %Svalue="1"%S/>', BackendUtility::getFuncCheck('params', 'test', true));
729 }
730
731 /*
732 * Tests concerning getLabelsFromItemsList
733 */
734
735 /**
736 * @return array
737 */
738 public function getLabelsFromItemsListDataProvider()
739 {
740 return [
741 'return value if found' => [
742 'foobar', // table
743 'someColumn', // col
744 'foo, bar', // keyList
745 [ // TCA
746 'columns' => [
747 'someColumn' => [
748 'config' => [
749 'items' => [
750 '0' => ['aFooLabel', 'foo'],
751 '1' => ['aBarLabel', 'bar']
752 ]
753 ]
754 ]
755 ]
756 ],
757 [], // page TSconfig
758 'aFooLabel, aBarLabel' // expected
759 ],
760 'page TSconfig overrules TCA' => [
761 'foobar', // table
762 'someColumn', // col
763 'foo,bar, add', // keyList
764 [ // TCA
765 'columns' => [
766 'someColumn' => [
767 'config' => [
768 'items' => [
769 '0' => ['aFooLabel', 'foo'],
770 '1' => ['aBarLabel', 'bar']
771 ]
772 ]
773 ]
774 ]
775 ],
776 [ // page TSconfig
777 'addItems.' => ['add' => 'aNewLabel'],
778 'altLabels.' => ['bar' => 'aBarDiffLabel'],
779 ],
780 'aFooLabel, aBarDiffLabel, aNewLabel' // expected
781 ]
782 ];
783 }
784
785 /**
786 * @test
787 * @dataProvider getLabelsFromItemsListDataProvider
788 *
789 * @param string $table
790 * @param string $col
791 * @param string $keyList
792 * @param array $tca
793 * @param array $pageTsConfig
794 * @param string $expectedLabel
795 */
796 public function getLabelsFromItemsListReturnsCorrectValue($table, $col, $keyList, $tca, array $pageTsConfig, $expectedLabel)
797 {
798 // Stub LanguageService and let sL() return the same value that came in again
799 $GLOBALS['LANG'] = $this->createMock(LanguageService::class);
800 $GLOBALS['LANG']->expects($this->any())->method('sL')->will($this->returnArgument(0));
801
802 $GLOBALS['TCA'][$table] = $tca;
803 $label = BackendUtility::getLabelsFromItemsList($table, $col, $keyList, $pageTsConfig);
804 $this->assertEquals($expectedLabel, $label);
805 }
806
807 /**
808 * @test
809 */
810 public function getProcessedValueReturnsLabelsForExistingValuesSolely()
811 {
812 $table = 'foobar';
813 $col = 'someColumn';
814 $tca = [
815 'columns' => [
816 'someColumn' => [
817 'config' => [
818 'type' => 'select',
819 'items' => [
820 '0' => ['aFooLabel', 'foo'],
821 '1' => ['aBarLabel', 'bar']
822 ]
823 ]
824 ]
825 ]
826 ];
827 // Stub LanguageService and let sL() return the same value that came in again
828 $GLOBALS['LANG'] = $this->createMock(LanguageService::class);
829 $GLOBALS['LANG']->expects($this->any())->method('sL')->will($this->returnArgument(0));
830
831 $GLOBALS['TCA'][$table] = $tca;
832 $label = BackendUtility::getProcessedValue($table, $col, 'foo,invalidKey,bar');
833 $this->assertEquals('aFooLabel, aBarLabel', $label);
834 }
835
836 /**
837 * @test
838 */
839 public function getProcessedValueReturnsPlainValueIfItemIsNotFound()
840 {
841 $table = 'foobar';
842 $col = 'someColumn';
843 $tca = [
844 'columns' => [
845 'someColumn' => [
846 'config' => [
847 'type' => 'select',
848 'items' => [
849 '0' => ['aFooLabel', 'foo']
850 ]
851 ]
852 ]
853 ]
854 ];
855 // Stub LanguageService and let sL() return the same value that came in again
856 $GLOBALS['LANG'] = $this->createMock(LanguageService::class);
857 $GLOBALS['LANG']->expects($this->any())->method('sL')->will($this->returnArgument(0));
858
859 $GLOBALS['TCA'][$table] = $tca;
860 $label = BackendUtility::getProcessedValue($table, $col, 'invalidKey');
861 $this->assertEquals('invalidKey', $label);
862 }
863
864 /**
865 * Tests concerning viewOnClick
866 */
867
868 /**
869 * @test
870 */
871 public function viewOnClickReturnsOnClickCodeWithAlternativeUrl()
872 {
873 // Make sure the hook inside viewOnClick is not fired. This may be removed if unit tests
874 // bootstrap does not initialize TYPO3_CONF_VARS anymore.
875 unset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['viewOnClickClass']);
876
877 $alternativeUrl = 'https://typo3.org/about/typo3-the-cms/the-history-of-typo3/#section';
878 $onclickCode = 'var previewWin = window.open(' . GeneralUtility::quoteJSvalue($alternativeUrl) . ',\'newTYPO3frontendWindow\');' . LF
879 . 'if (previewWin.location.href === ' . GeneralUtility::quoteJSvalue($alternativeUrl) . ') { previewWin.location.reload(); };';
880 $this->assertStringMatchesFormat(
881 $onclickCode,
882 BackendUtility::viewOnClick(null, null, null, null, $alternativeUrl, null, false)
883 );
884 }
885
886 /**
887 * @test
888 */
889 public function getModTSconfigIgnoresValuesFromUserTsConfigIfNoSet()
890 {
891 $completeConfiguration = [
892 'value' => 'bar',
893 'properties' => [
894 'permissions.' => [
895 'file.' => [
896 'default.' => ['readAction' => '1'],
897 '1.' => ['writeAction' => '1'],
898 '0.' => ['readAction' => '0'],
899 ],
900 ]
901 ]
902 ];
903
904 $GLOBALS['BE_USER'] = $this->createMock(BackendUserAuthentication::class);
905 $GLOBALS['BE_USER']->expects($this->at(0))->method('getTSConfig')->will($this->returnValue($completeConfiguration));
906 $GLOBALS['BE_USER']->expects($this->at(1))->method('getTSConfig')->will($this->returnValue(['value' => null, 'properties' => null]));
907
908 $this->assertSame($completeConfiguration, BackendUtilityFixture::getModTSconfig(42, 'notrelevant'));
909 }
910
911 /**
912 * @test
913 */
914 public function dateTimeAgeReturnsCorrectValues()
915 {
916 /** @var ObjectProphecy|LanguageService $languageServiceProphecy */
917 $languageServiceProphecy = $this->prophesize(LanguageService::class);
918 $languageServiceProphecy->sL(Argument::cetera())->willReturn(' min| hrs| days| yrs| min| hour| day| year');
919 $GLOBALS['LANG'] = $languageServiceProphecy->reveal();
920 $GLOBALS['EXEC_TIME'] = mktime(0, 0, 0, 3, 23, 2016);
921
922 $this->assertSame('24-03-16 00:00 (-1 day)', BackendUtility::dateTimeAge($GLOBALS['EXEC_TIME'] + 86400));
923 $this->assertSame('24-03-16 (-1 day)', BackendUtility::dateTimeAge($GLOBALS['EXEC_TIME'] + 86400, 1, 'date'));
924 }
925
926 ///////////////////////////////////////
927 // Tests concerning getTCAtypes
928 ///////////////////////////////////////
929
930 /**
931 * @test
932 */
933 public function getTCAtypesReturnsCorrectValuesDataProvider()
934 {
935 return [
936 'no input' => [
937 '', // table
938 [], // rec
939 '', // useFieldNameAsKey
940 null // expected
941 ],
942 'non-existant table' => [
943 'fooBar', // table
944 [], // rec
945 '', // useFieldNameAsKey
946 null // expected
947 ],
948 'Doktype=1: one simple field' => [
949 'pages',
950 [
951 'uid' => '1',
952 'doktype' => '1'
953 ],
954 false,
955 [
956 0 => [
957 'field' => 'title',
958 'title' => null,
959 'palette' => null,
960 'spec' => [],
961 'origString' => 'title'
962 ]
963 ]
964 ],
965 'non-existant type given: Return for type 1' => [
966 'pages', // table
967 [
968 'uid' => '1',
969 'doktype' => '999'
970 ], // rec
971 '', // useFieldNameAsKey
972 [
973 0 => [
974 'field' => 'title',
975 'title' => null,
976 'palette' => null,
977 'spec' => [],
978 'origString' => 'title'
979 ]
980 ] // expected
981 ],
982 'Doktype=1: one simple field, useFieldNameAsKey=true' => [
983 'pages',
984 [
985 'uid' => '1',
986 'doktype' => '1'
987 ],
988 true,
989 [
990 'title' => [
991 'field' => 'title',
992 'title' => null,
993 'palette' => null,
994 'spec' => [],
995 'origString' => 'title'
996 ]
997 ]
998 ],
999 'Empty showitem Field' => [
1000 'test',
1001 [
1002 'uid' => '1',
1003 'fooBar' => '99'
1004 ],
1005 true,
1006 [
1007 '' => [
1008 'field' => '',
1009 'title' => null,
1010 'palette' => null,
1011 'spec' => [],
1012 'origString' => ''
1013 ]
1014 ]
1015 ],
1016 'RTE field within a palette' => [
1017 'pages',
1018 [
1019 'uid' => '1',
1020 'doktype' => '10',
1021 ],
1022 false,
1023 [
1024 0 => [
1025 'field' => '--div--',
1026 'title' => 'General',
1027 'palette' => null,
1028 'spec' => [],
1029 'origString' => '--div--;General'
1030 ],
1031 1 => [
1032 'field' => '--palette--',
1033 'title' => 'Palette',
1034 'palette' => '123',
1035 'spec' => [],
1036 'origString' => '--palette--;Palette;123'
1037 ],
1038 2 => [
1039 'field' => 'title',
1040 'title' => null,
1041 'palette' => null,
1042 'spec' => [],
1043 'origString' => 'title'
1044 ],
1045 3 => [
1046 'field' => 'text',
1047 'title' => null,
1048 'palette' => null,
1049 'spec' => [],
1050 'origString' => 'text'
1051 ],
1052 4 => [
1053 'field' => 'select',
1054 'title' => 'Select field',
1055 'palette' => null,
1056 'spec' => [],
1057 'origString' => 'select;Select field'
1058 ]
1059 ]
1060 ],
1061 'RTE field with more settings within a palette' => [
1062 'pages',
1063 [
1064 'uid' => 1,
1065 'doktype' => 2
1066 ],
1067 false,
1068 [
1069 0 => [
1070 'field' => '--div--',
1071 'title' => 'General',
1072 'palette' => null,
1073 'spec' => [],
1074 'origString' => '--div--;General'
1075 ],
1076 1 => [
1077 'field' => '--palette--',
1078 'title' => 'RTE palette',
1079 'palette' => '456',
1080 'spec' => [],
1081 'origString' => '--palette--;RTE palette;456'
1082 ],
1083 2 => [
1084 'field' => 'text2',
1085 'title' => null,
1086 'palette' => null,
1087 'spec' => [],
1088 'origString' => 'text2'
1089 ]
1090 ]
1091 ]
1092 ];
1093 }
1094
1095 /**
1096 * @test
1097 * @dataProvider getTCAtypesReturnsCorrectValuesDataProvider
1098 *
1099 * @param string $table
1100 * @param array $rec
1101 * @param bool $useFieldNameAsKey
1102 * @param array $expected
1103 */
1104 public function getTCAtypesReturnsCorrectValues($table, $rec, $useFieldNameAsKey, $expected)
1105 {
1106 $GLOBALS['TCA'] = [
1107 'pages' => [
1108 'ctrl' => [
1109 'type' => 'doktype'
1110 ],
1111 'columns' => [
1112 'title' => [
1113 'label' => 'Title test',
1114 'config' => [
1115 'type' => 'input'
1116 ]
1117 ],
1118 'text' => [
1119 'label' => 'RTE Text',
1120 'config' => [
1121 'type' => 'text',
1122 'cols' => 40,
1123 'rows' => 5
1124 ],
1125 ],
1126 'text2' => [
1127 'label' => 'RTE Text 2',
1128 'config' => [
1129 'type' => 'text',
1130 'cols' => 40,
1131 'rows' => 5
1132 ],
1133 ],
1134 'select' => [
1135 'label' => 'Select test',
1136 'config' => [
1137 'items' => [
1138 ['Please select', 0],
1139 ['Option 1', 1],
1140 ['Option 2', 2]
1141 ]
1142 ],
1143 'maxitems' => 1,
1144 'renderType' => 'selectSingle'
1145 ]
1146 ],
1147 'types' => [
1148 '1' => [
1149 'showitem' => 'title'
1150 ],
1151 '2' => [
1152 'showitem' => '--div--;General,--palette--;RTE palette;456'
1153 ],
1154 '10' => [
1155 'showitem' => '--div--;General,--palette--;Palette;123,title'
1156 ],
1157 '14' => [
1158 'showitem' => '--div--;General,title'
1159 ]
1160 ],
1161 'palettes' => [
1162 '123' => [
1163 'showitem' => 'text,select;Select field'
1164 ],
1165 '456' => [
1166 'showitem' => 'text2'
1167 ]
1168 ]
1169 ],
1170 'test' => [
1171 'ctrl' => [
1172 'type' => 'fooBar'
1173 ],
1174 'types' => [
1175 '99' => [ 'showitem' => '']
1176 ]
1177 ]
1178 ];
1179
1180 $return = BackendUtility::getTCAtypes($table, $rec, $useFieldNameAsKey);
1181 $this->assertSame($expected, $return);
1182 }
1183
1184 /**
1185 * @test
1186 */
1187 public function purgeComputedPropertyNamesRemovesPropertiesStartingWithUnderscore()
1188 {
1189 $propertyNames = [
1190 'uid',
1191 'pid',
1192 '_ORIG_PID'
1193 ];
1194 $computedPropertyNames = BackendUtility::purgeComputedPropertyNames($propertyNames);
1195 self::assertSame(['uid', 'pid'], $computedPropertyNames);
1196 }
1197
1198 /**
1199 * @test
1200 */
1201 public function purgeComputedPropertiesFromRecordRemovesPropertiesStartingWithUnderscore()
1202 {
1203 $record = [
1204 'uid' => 1,
1205 'pid' => 2,
1206 '_ORIG_PID' => 1
1207 ];
1208 $expected = [
1209 'uid' => 1,
1210 'pid' => 2
1211 ];
1212 $computedProperties = BackendUtility::purgeComputedPropertiesFromRecord($record);
1213 self::assertSame($expected, $computedProperties);
1214 }
1215 }