[TASK] Drop eval() from BackendUtility test
[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\ExcludeFieldsReturnsCorrectFieldListFixture;
21 use TYPO3\CMS\Backend\Tests\Unit\Utility\Fixtures\ExcludeFieldsReturnsCorrectListWithFlexFormFieldsFixture;
22 use TYPO3\CMS\Backend\Tests\Unit\Utility\Fixtures\LabelFromItemListMergedReturnsCorrectFieldsFixture;
23 use TYPO3\CMS\Backend\Tests\Unit\Utility\Fixtures\ProcessedValueForGroupWithMultipleAllowedTablesFixture;
24 use TYPO3\CMS\Backend\Tests\Unit\Utility\Fixtures\ProcessedValueForGroupWithOneAllowedTableFixture;
25 use TYPO3\CMS\Backend\Tests\Unit\Utility\Fixtures\ProcessedValueForSelectWithMMRelationFixture;
26 use TYPO3\CMS\Backend\Utility\BackendUtility;
27 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
28 use TYPO3\CMS\Core\Charset\CharsetConverter;
29 use TYPO3\CMS\Core\Database\DatabaseConnection;
30 use TYPO3\CMS\Core\Tests\UnitTestCase;
31 use TYPO3\CMS\Core\Utility\GeneralUtility;
32 use TYPO3\CMS\Lang\LanguageService;
33
34 /**
35 * Test case
36 */
37 class BackendUtilityTest extends UnitTestCase {
38
39 ///////////////////////////////////////
40 // Tests concerning calcAge
41 ///////////////////////////////////////
42 /**
43 * Data provider for calcAge function
44 *
45 * @return array
46 */
47 public function calcAgeDataProvider() {
48 return array(
49 'Single year' => array(
50 'seconds' => 60 * 60 * 24 * 365,
51 'expectedLabel' => '1 year'
52 ),
53 'Plural years' => array(
54 'seconds' => 60 * 60 * 24 * 365 * 2,
55 'expectedLabel' => '2 yrs'
56 ),
57 'Single negative year' => array(
58 'seconds' => 60 * 60 * 24 * 365 * -1,
59 'expectedLabel' => '-1 year'
60 ),
61 'Plural negative years' => array(
62 'seconds' => 60 * 60 * 24 * 365 * 2 * -1,
63 'expectedLabel' => '-2 yrs'
64 ),
65 'Single day' => array(
66 'seconds' => 60 * 60 * 24,
67 'expectedLabel' => '1 day'
68 ),
69 'Plural days' => array(
70 'seconds' => 60 * 60 * 24 * 2,
71 'expectedLabel' => '2 days'
72 ),
73 'Single negative day' => array(
74 'seconds' => 60 * 60 * 24 * -1,
75 'expectedLabel' => '-1 day'
76 ),
77 'Plural negative days' => array(
78 'seconds' => 60 * 60 * 24 * 2 * -1,
79 'expectedLabel' => '-2 days'
80 ),
81 'Single hour' => array(
82 'seconds' => 60 * 60,
83 'expectedLabel' => '1 hour'
84 ),
85 'Plural hours' => array(
86 'seconds' => 60 * 60 * 2,
87 'expectedLabel' => '2 hrs'
88 ),
89 'Single negative hour' => array(
90 'seconds' => 60 * 60 * -1,
91 'expectedLabel' => '-1 hour'
92 ),
93 'Plural negative hours' => array(
94 'seconds' => 60 * 60 * 2 * -1,
95 'expectedLabel' => '-2 hrs'
96 ),
97 'Single minute' => array(
98 'seconds' => 60,
99 'expectedLabel' => '1 min'
100 ),
101 'Plural minutes' => array(
102 'seconds' => 60 * 2,
103 'expectedLabel' => '2 min'
104 ),
105 'Single negative minute' => array(
106 'seconds' => 60 * -1,
107 'expectedLabel' => '-1 min'
108 ),
109 'Plural negative minutes' => array(
110 'seconds' => 60 * 2 * -1,
111 'expectedLabel' => '-2 min'
112 ),
113 'Zero seconds' => array(
114 'seconds' => 0,
115 'expectedLabel' => '0 min'
116 )
117 );
118 }
119
120 /**
121 * @test
122 * @dataProvider calcAgeDataProvider
123 *
124 * @param int $seconds
125 * @param string $expectedLabel
126 */
127 public function calcAgeReturnsExpectedValues($seconds, $expectedLabel) {
128 $this->assertSame($expectedLabel, BackendUtility::calcAge($seconds));
129 }
130
131 ///////////////////////////////////////
132 // Tests concerning getProcessedValue
133 ///////////////////////////////////////
134 /**
135 * @test
136 * @see http://forge.typo3.org/issues/20994
137 */
138 public function getProcessedValueForZeroStringIsZero() {
139 $GLOBALS['TCA'] = array(
140 'tt_content' => array(
141 'columns' => array(
142 'header' => array(
143 'config' => array(
144 'type' => 'input',
145 ),
146 ),
147 ),
148 ),
149 );
150 $this->assertEquals('0', BackendUtility::getProcessedValue('tt_content', 'header', '0'));
151 }
152
153 /**
154 * @test
155 */
156 public function getProcessedValueForGroup() {
157 $GLOBALS['TCA'] = array(
158 'tt_content' => array(
159 'columns' => array(
160 'multimedia' => array(
161 'config' => array(
162 'type' => 'group',
163 ),
164 ),
165 ),
166 ),
167 );
168 $this->assertSame('1, 2', BackendUtility::getProcessedValue('tt_content', 'multimedia', '1,2'));
169 }
170
171 /**
172 * @test
173 */
174 public function getProcessedValueForGroupWithOneAllowedTable() {
175 $GLOBALS['TCA'] = array(
176 'tt_content' => array(
177 'columns' => array(
178 'pages' => array(
179 'config' => array(
180 'type' => 'group',
181 'allowed' => 'pages',
182 'internal_type' => 'db',
183 'maxitems' => 22,
184 'minitems' => 0,
185 'show_thumbs' => 1,
186 'size' => 3,
187 ),
188 ),
189 ),
190 ),
191 );
192
193 $this->assertSame('Page 1, Page 2', ProcessedValueForGroupWithOneAllowedTableFixture::getProcessedValue('tt_content', 'pages', '1,2'));
194 }
195
196 /**
197 * @test
198 */
199 public function getProcessedValueForGroupWithMultipleAllowedTables() {
200 $GLOBALS['TCA'] = array(
201 'index_config' => array(
202 'columns' => array(
203 'indexcfgs' => array(
204 'config' => array(
205 'type' => 'group',
206 'internal_type' => 'db',
207 'allowed' => 'index_config,pages',
208 'size' => 5,
209 ),
210 ),
211 ),
212 ),
213 );
214
215 $this->assertSame('Page 1, Configuration 2', ProcessedValueForGroupWithMultipleAllowedTablesFixture::getProcessedValue('index_config', 'indexcfgs', 'pages_1,index_config_2'));
216 }
217
218 /**
219 * @test
220 */
221 public function getProcessedValueForSelectWithMMRelation() {
222 $GLOBALS['TYPO3_DB'] = $this->getMock(DatabaseConnection::class, array(), array(), '', FALSE);
223 $GLOBALS['TYPO3_DB']->expects($this->any())->method('fullQuoteStr')
224 ->will($this->returnCallback(
225 function ($quoteStr) {
226 return "'" . $quoteStr . "'";
227 }
228 )
229 );
230 $GLOBALS['TYPO3_DB']->expects($this->any())->method('exec_SELECTquery')->will($this->returnValue(0));
231 $GLOBALS['TYPO3_DB']->expects($this->any())->method('sql_free_result');
232 $GLOBALS['TYPO3_DB']->expects($this->any())->method('sql_fetch_assoc')
233 ->will($this->returnCallback(
234 function () {
235 static $called = 0;
236 ++$called;
237 switch ($called) {
238 // SELECT * FROM sys_category_record_mm
239 case 1:
240 return array(
241 'uid_local' => 1, // uid of a sys_category record
242 'uid_foreign' => 1, // uid of a pages record
243 );
244 case 2:
245 return array(
246 'uid_local' => 2, // uid of a sys_category record
247 'uid_foreign' => 1, // uid of a pages record
248 );
249 case 3:
250 return NULL;
251 // SELECT * FROM sys_catgory
252 case 4:
253 return array(
254 'uid' => 1,
255 'title' => 'Category 1',
256 );
257 case 5:
258 return array(
259 'uid' => 2,
260 'title' => 'Category 2',
261 );
262 case 6:
263 return NULL;
264 }
265 return NULL;
266 }
267 )
268 );
269
270 $GLOBALS['TCA'] = array(
271 'pages' => array(
272 'columns' => array(
273 'categories' => array(
274 'config' => array(
275 'type' => 'select',
276 'foreign_table' => 'sys_category',
277 'MM' => 'sys_category_record_mm',
278 'MM_match_fields' => array(
279 'fieldname' => 'categories',
280 'tablesnames' => 'pages',
281 ),
282 'MM_opposite_field' => 'items',
283 ),
284 ),
285 ),
286 ),
287 'sys_category' => array(
288 'columns' => array(
289 'items' => array(
290 'config' => array(
291 'type' => 'group',
292 'internal_type' => 'db',
293 'allowed' => '*',
294 'MM' => 'sys_category_record_mm',
295 'MM_oppositeUsage' => array(),
296 )
297 )
298 ),
299 ),
300 );
301
302 $this->assertSame('Category 1; Category 2', ProcessedValueForSelectWithMMRelationFixture::getProcessedValue('pages', 'categories', '2', 0, FALSE, FALSE, 1));
303 }
304
305 /**
306 * @test
307 */
308 public function getProcessedValueDisplaysAgeForDateInputFieldsIfSettingAbsent() {
309 /** @var ObjectProphecy $languageServiceProphecy */
310 $languageServiceProphecy = $this->prophesize(LanguageService::class);
311 $languageServiceProphecy->sL(Argument::cetera())->willReturn(' min| hrs| days| yrs| min| hour| day| year');
312 $GLOBALS['LANG'] = $languageServiceProphecy->reveal();
313
314 $GLOBALS['EXEC_TIME'] = mktime(0, 0, 0, 8, 30, 2015);
315
316 $GLOBALS['TCA'] = [
317 'tt_content' => [
318 'columns' => [
319 'date' => [
320 'config' => [
321 'type' => 'input',
322 'eval' => 'date',
323 ],
324 ],
325 ],
326 ],
327 ];
328 $this->assertSame('28-08-15 (-2 days)', BackendUtility::getProcessedValue('tt_content', 'date', mktime(0, 0, 0, 8, 28, 2015)));
329 }
330
331 /**
332 * @return array
333 */
334 public function inputTypeDateDisplayOptions() {
335 return [
336 'typeSafe Setting' => [
337 TRUE,
338 '28-08-15',
339 ],
340 'non typesafe setting' => [
341 1,
342 '28-08-15',
343 ],
344 'setting disabled typesafe' => [
345 FALSE,
346 '28-08-15 (-2 days)',
347 ],
348 'setting disabled not typesafe' => [
349 0,
350 '28-08-15 (-2 days)',
351 ],
352 ];
353 }
354
355 /**
356 * @test
357 *
358 * @dataProvider inputTypeDateDisplayOptions
359 *
360 * @param string $input
361 * @param string $expected
362 */
363 public function getProcessedValueHandlesAgeDisplayCorrectly($input, $expected) {
364 /** @var ObjectProphecy $languageServiceProphecy */
365 $languageServiceProphecy = $this->prophesize(LanguageService::class);
366 $languageServiceProphecy->sL(Argument::cetera())->willReturn(' min| hrs| days| yrs| min| hour| day| year');
367 $GLOBALS['LANG'] = $languageServiceProphecy->reveal();
368
369 $GLOBALS['EXEC_TIME'] = mktime(0, 0, 0, 8, 30, 2015);
370
371 $GLOBALS['TCA'] = [
372 'tt_content' => [
373 'columns' => [
374 'date' => [
375 'config' => [
376 'type' => 'input',
377 'eval' => 'date',
378 'disableAgeDisplay' => $input,
379 ],
380 ],
381 ],
382 ],
383 ];
384 $this->assertSame($expected, BackendUtility::getProcessedValue('tt_content', 'date', mktime(0, 0, 0, 8, 28, 2015)));
385 }
386
387 /**
388 * Tests concerning getCommonSelectFields
389 */
390
391 /**
392 * Data provider for getCommonSelectFieldsReturnsCorrectFields
393 *
394 * @return array The test data with $table, $prefix, $presetFields, $tca, $expectedFields
395 */
396 public function getCommonSelectFieldsReturnsCorrectFieldsDataProvider() {
397 return array(
398 'only uid' => array(
399 'table' => 'test_table',
400 'prefix' => '',
401 'presetFields' => array(),
402 'tca' => array(),
403 'expectedFields' => 'uid'
404 ),
405 'label set' => array(
406 'table' => 'test_table',
407 'prefix' => '',
408 'presetFields' => array(),
409 'tca' => array(
410 'ctrl' => array(
411 'label' => 'label'
412 )
413 ),
414 'expectedFields' => 'uid,label'
415 ),
416 'label_alt set' => array(
417 'table' => 'test_table',
418 'prefix' => '',
419 'presetFields' => array(),
420 'tca' => array(
421 'ctrl' => array(
422 'label_alt' => 'label,label2'
423 )
424 ),
425 'expectedFields' => 'uid,label,label2'
426 ),
427 'versioningWS set' => array(
428 'table' => 'test_table',
429 'prefix' => '',
430 'presetFields' => array(),
431 'tca' => array(
432 'ctrl' => array(
433 'versioningWS' => '2'
434 )
435 ),
436 'expectedFields' => 'uid,t3ver_id,t3ver_state,t3ver_wsid,t3ver_count'
437 ),
438 'selicon_field set' => array(
439 'table' => 'test_table',
440 'prefix' => '',
441 'presetFields' => array(),
442 'tca' => array(
443 'ctrl' => array(
444 'selicon_field' => 'field'
445 )
446 ),
447 'expectedFields' => 'uid,field'
448 ),
449 'typeicon_column set' => array(
450 'table' => 'test_table',
451 'prefix' => '',
452 'presetFields' => array(),
453 'tca' => array(
454 'ctrl' => array(
455 'typeicon_column' => 'field'
456 )
457 ),
458 'expectedFields' => 'uid,field'
459 ),
460 'enablecolumns set' => array(
461 'table' => 'test_table',
462 'prefix' => '',
463 'presetFields' => array(),
464 'tca' => array(
465 'ctrl' => array(
466 'enablecolumns' => array(
467 'disabled' => 'hidden',
468 'starttime' => 'start',
469 'endtime' => 'stop',
470 'fe_group' => 'groups'
471 )
472 )
473 ),
474 'expectedFields' => 'uid,hidden,start,stop,groups'
475 ),
476 'label set to uid' => array(
477 'table' => 'test_table',
478 'prefix' => '',
479 'presetFields' => array(),
480 'tca' => array(
481 'ctrl' => array(
482 'label' => 'uid'
483 )
484 ),
485 'expectedFields' => 'uid'
486 )
487 );
488 }
489
490 /**
491 * @test
492 * @dataProvider getCommonSelectFieldsReturnsCorrectFieldsDataProvider
493 *
494 * @param string $table
495 * @param string $prefix
496 * @param array $presetFields
497 * @param array $tca
498 * @param string $expectedFields
499 */
500 public function getCommonSelectFieldsReturnsCorrectFields($table, $prefix = '', array $presetFields, array $tca, $expectedFields = '') {
501 $GLOBALS['TCA'][$table] = $tca;
502 $selectFields = BackendUtility::getCommonSelectFields($table, $prefix, $presetFields);
503 $this->assertEquals($selectFields, $expectedFields);
504 }
505
506 /**
507 * Tests concerning getLabelFromItemlist
508 */
509
510 /**
511 * Data provider for getLabelFromItemlistReturnsCorrectFields
512 *
513 * @return array The test data with $table, $col, $key, $expectedLabel
514 */
515 public function getLabelFromItemlistReturnsCorrectFieldsDataProvider() {
516 return array(
517 'item set' => array(
518 'table' => 'tt_content',
519 'col' => 'menu_type',
520 'key' => '1',
521 'tca' => array(
522 'columns' => array(
523 'menu_type' => array(
524 'config' => array(
525 'items' => array(
526 array('Item 1', '0'),
527 array('Item 2', '1'),
528 array('Item 3', '3')
529 )
530 )
531 )
532 )
533 ),
534 'expectedLabel' => 'Item 2'
535 ),
536 'item set twice' => array(
537 'table' => 'tt_content',
538 'col' => 'menu_type',
539 'key' => '1',
540 'tca' => array(
541 'columns' => array(
542 'menu_type' => array(
543 'config' => array(
544 'items' => array(
545 array('Item 1', '0'),
546 array('Item 2a', '1'),
547 array('Item 2b', '1'),
548 array('Item 3', '3')
549 )
550 )
551 )
552 )
553 ),
554 'expectedLabel' => 'Item 2a'
555 ),
556 'item not found' => array(
557 'table' => 'tt_content',
558 'col' => 'menu_type',
559 'key' => '5',
560 'tca' => array(
561 'columns' => array(
562 'menu_type' => array(
563 'config' => array(
564 'items' => array(
565 array('Item 1', '0'),
566 array('Item 2', '1'),
567 array('Item 3', '2')
568 )
569 )
570 )
571 )
572 ),
573 'expectedLabel' => NULL
574 )
575 );
576 }
577
578 /**
579 * @test
580 * @dataProvider getLabelFromItemlistReturnsCorrectFieldsDataProvider
581 *
582 * @param string $table
583 * @param string $col
584 * @param string $key
585 * @param array $tca
586 * @param string $expectedLabel
587 */
588 public function getLabelFromItemlistReturnsCorrectFields($table, $col = '', $key = '', array $tca, $expectedLabel = '') {
589 $GLOBALS['TCA'][$table] = $tca;
590 $label = BackendUtility::getLabelFromItemlist($table, $col, $key);
591 $this->assertEquals($label, $expectedLabel);
592 }
593
594 /**
595 * Tests concerning getLabelFromItemListMerged
596 */
597
598 /**
599 * Data provider for getLabelFromItemListMerged
600 *
601 * @return array The test data with $pageId, $table, $column, $key, $expectedLabel
602 */
603 public function getLabelFromItemListMergedReturnsCorrectFieldsDataProvider() {
604 return array(
605 'no field found' => array(
606 'pageId' => '123',
607 'table' => 'tt_content',
608 'col' => 'menu_type',
609 'key' => '10',
610 'tca' => array(
611 'columns' => array(
612 'menu_type' => array(
613 'config' => array(
614 'items' => array(
615 array('Item 1', '0'),
616 array('Item 2', '1'),
617 array('Item 3', '3')
618 )
619 )
620 )
621 )
622 ),
623 'expectedLabel' => ''
624 ),
625 'no tsconfig set' => array(
626 'pageId' => '123',
627 'table' => 'tt_content',
628 'col' => 'menu_type',
629 'key' => '1',
630 'tca' => array(
631 'columns' => array(
632 'menu_type' => array(
633 'config' => array(
634 'items' => array(
635 array('Item 1', '0'),
636 array('Item 2', '1'),
637 array('Item 3', '3')
638 )
639 )
640 )
641 )
642 ),
643 'expectedLabel' => 'Item 2'
644 )
645 );
646 }
647
648 /**
649 * @test
650 * @dataProvider getLabelFromItemListMergedReturnsCorrectFieldsDataProvider
651 *
652 * @param int $pageId
653 * @param string $table
654 * @param string $column
655 * @param string $key
656 * @param array $tca
657 * @param string $expectedLabel
658 */
659 public function getLabelFromItemListMergedReturnsCorrectFields($pageId, $table, $column = '', $key = '', array $tca, $expectedLabel = '') {
660 $GLOBALS['TCA'][$table] = $tca;
661
662 $this->assertEquals($expectedLabel, LabelFromItemListMergedReturnsCorrectFieldsFixture::getLabelFromItemListMerged($pageId, $table, $column, $key));
663 }
664
665 /**
666 * Tests concerning getFuncCheck
667 */
668
669 /**
670 * @test
671 */
672 public function getFuncCheckReturnsInputTagWithValueAttribute() {
673 $this->assertStringMatchesFormat('<input %Svalue="1"%S/>', BackendUtility::getFuncCheck('params', 'test', TRUE));
674 }
675
676 /*
677 * Tests concerning getLabelsFromItemsList
678 */
679
680 /**
681 * @return array
682 */
683 public function getLabelsFromItemsListDataProvider() {
684 return array(
685 'return value if found' => array(
686 'foobar', // table
687 'someColumn', // col
688 'foo, bar', // keyList
689 array( // TCA
690 'columns' => array(
691 'someColumn' => array(
692 'config' => array(
693 'items' => array(
694 '0' => array('aFooLabel', 'foo'),
695 '1' => array('aBarLabel', 'bar')
696 )
697 )
698 )
699 )
700 ),
701 array(), // page TSconfig
702 'aFooLabel, aBarLabel' // expected
703 ),
704 'page TSconfig overrules TCA' => array(
705 'foobar', // table
706 'someColumn', // col
707 'foo,bar, add', // keyList
708 array( // TCA
709 'columns' => array(
710 'someColumn' => array(
711 'config' => array(
712 'items' => array(
713 '0' => array('aFooLabel', 'foo'),
714 '1' => array('aBarLabel', 'bar')
715 )
716 )
717 )
718 )
719 ),
720 array( // page TSconfig
721 'addItems.' => array('add' => 'aNewLabel'),
722 'altLabels.' => array('bar' => 'aBarDiffLabel'),
723 ),
724 'aFooLabel, aBarDiffLabel, aNewLabel' // expected
725 )
726 );
727 }
728
729 /**
730 * @test
731 * @dataProvider getLabelsFromItemsListDataProvider
732 *
733 * @param string $table
734 * @param string $col
735 * @param string $keyList
736 * @param array $tca
737 * @param array $pageTsConfig
738 * @param string $expectedLabel
739 */
740 public function getLabelsFromItemsListReturnsCorrectValue($table, $col, $keyList, $tca, array $pageTsConfig, $expectedLabel) {
741 // Stub LanguageService and let sL() return the same value that came in again
742 $GLOBALS['LANG'] = $this->getMock(LanguageService::class, array(), array(), '', FALSE);
743 $GLOBALS['LANG']->expects($this->any())->method('sL')->will($this->returnArgument(0));
744
745 $GLOBALS['TCA'][$table] = $tca;
746 $label = BackendUtility::getLabelsFromItemsList($table, $col, $keyList, $pageTsConfig);
747 $this->assertEquals($expectedLabel, $label);
748 }
749
750 /**
751 * @test
752 */
753 public function getProcessedValueReturnsLabelsForExistingValuesSolely() {
754 $table = 'foobar';
755 $col = 'someColumn';
756 $tca = array(
757 'columns' => array(
758 'someColumn' => array(
759 'config' => array(
760 'type' => 'select',
761 'items' => array(
762 '0' => array('aFooLabel', 'foo'),
763 '1' => array('aBarLabel', 'bar')
764 )
765 )
766 )
767 )
768 );
769 // Stub LanguageService and let sL() return the same value that came in again
770 $GLOBALS['LANG'] = $this->getMock(LanguageService::class, array(), array(), '', FALSE);
771 $GLOBALS['LANG']->charSet = 'utf-8';
772 $GLOBALS['LANG']->csConvObj = $this->getMock(CharsetConverter::class);
773 $GLOBALS['LANG']->expects($this->any())->method('sL')->will($this->returnArgument(0));
774
775 $GLOBALS['LANG']->csConvObj->expects($this->any())->method('crop')->will($this->returnArgument(1));
776
777 $GLOBALS['TCA'][$table] = $tca;
778 $label = BackendUtility::getProcessedValue($table, $col, 'foo,invalidKey,bar');
779 $this->assertEquals('aFooLabel, aBarLabel', $label);
780 }
781
782 /**
783 * @test
784 */
785 public function getProcessedValueReturnsPlainValueIfItemIsNotFound() {
786 $table = 'foobar';
787 $col = 'someColumn';
788 $tca = array(
789 'columns' => array(
790 'someColumn' => array(
791 'config' => array(
792 'type' => 'select',
793 'items' => array(
794 '0' => array('aFooLabel', 'foo')
795 )
796 )
797 )
798 )
799 );
800 // Stub LanguageService and let sL() return the same value that came in again
801 $GLOBALS['LANG'] = $this->getMock(LanguageService::class, array(), array(), '', FALSE);
802 $GLOBALS['LANG']->charSet = 'utf-8';
803 $GLOBALS['LANG']->csConvObj = $this->getMock(CharsetConverter::class);
804 $GLOBALS['LANG']->expects($this->any())->method('sL')->will($this->returnArgument(0));
805
806 $GLOBALS['LANG']->csConvObj->expects($this->any())->method('crop')->will($this->returnArgument(1));
807
808 $GLOBALS['TCA'][$table] = $tca;
809 $label = BackendUtility::getProcessedValue($table, $col, 'invalidKey');
810 $this->assertEquals('invalidKey', $label);
811 }
812
813 /**
814 * Tests concerning viewOnClick
815 */
816
817 /**
818 * @test
819 */
820 public function viewOnClickReturnsOnClickCodeWithAlternativeUrl() {
821 // Make sure the hook inside viewOnClick is not fired. This may be removed if unit tests
822 // bootstrap does not initialize TYPO3_CONF_VARS anymore.
823 unset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['viewOnClickClass']);
824
825 $alternativeUrl = 'https://typo3.org/about/typo3-the-cms/the-history-of-typo3/#section';
826 $onclickCode = 'var previewWin = window.open(' . GeneralUtility::quoteJSvalue($alternativeUrl) . ',\'newTYPO3frontendWindow\');';
827 $this->assertStringMatchesFormat(
828 $onclickCode,
829 BackendUtility::viewOnClick(NULL, NULL, NULL, NULL, $alternativeUrl, NULL, FALSE)
830 );
831 }
832
833 /**
834 * @test
835 */
836 public function getModTSconfigIgnoresValuesFromUserTsConfigIfNoSet() {
837 $completeConfiguration = array(
838 'value' => 'bar',
839 'properties' => array(
840 'permissions.' => array(
841 'file.' => array(
842 'default.' => array('readAction' => '1'),
843 '1.' => array('writeAction' => '1'),
844 '0.' => array('readAction' => '0'),
845 ),
846 )
847 )
848 );
849
850 $GLOBALS['BE_USER'] = $this->getMock(BackendUserAuthentication::class, array(), array(), '', FALSE);
851 $GLOBALS['BE_USER']->expects($this->at(0))->method('getTSConfig')->will($this->returnValue($completeConfiguration));
852 $GLOBALS['BE_USER']->expects($this->at(1))->method('getTSConfig')->will($this->returnValue(array('value' => NULL, 'properties' => NULL)));
853
854 $this->assertSame($completeConfiguration, BackendUtilityFixture::getModTSconfig(42, 'notrelevant'));
855 }
856
857 /**
858 * Data provider for replaceL10nModeFieldsReplacesFields
859 *
860 * @return array
861 */
862 public function replaceL10nModeFieldsReplacesFieldsDataProvider() {
863 return array(
864 'same table: mergeIfNotBlank' => array(
865 'foo',
866 array(
867 'origUid' => 1,
868 'field2' => 'fdas',
869 'field3' => 'trans',
870 ),
871 array(
872 'foo' => array(
873 'ctrl' => array(
874 'transOrigPointerTable' => '',
875 'transOrigPointerField' => 'origUid'
876 ),
877 'columns' => array(
878 'field2' => array('l10n_mode' => 'mergeIfNotBlank'),
879 'field3' => array('l10n_mode' => 'mergeIfNotBlank')
880 )
881 )
882 ),
883 array(
884 'origUid' => 0,
885 'field2' => 'basic',
886 'field3' => '',
887 ),
888 array(
889 'origUid' => 1,
890 'field2' => 'fdas',
891 'field3' => 'trans',
892 )
893 ),
894 'other table: mergeIfNotBlank' => array(
895 'foo',
896 array(
897 'origUid' => 1,
898 'field2' => '',
899 'field3' => 'trans',
900 ),
901 array(
902 'foo' => array(
903 'ctrl' => array(
904 'transOrigPointerTable' => 'bar',
905 'transOrigPointerField' => 'origUid'
906 )
907 ),
908 'bar' => array(
909 'columns' => array(
910 'field2' => array('l10n_mode' => 'mergeIfNotBlank'),
911 'field3' => array('l10n_mode' => 'mergeIfNotBlank')
912 )
913 )
914 ),
915 array(
916 'origUid' => 0,
917 'field2' => 'basic',
918 'field3' => '',
919 ),
920 array(
921 'origUid' => 1,
922 'field2' => 'basic',
923 'field3' => 'trans',
924 )
925 ),
926 'same table: exclude' => array(
927 'foo',
928 array(
929 'origUid' => 1,
930 'field2' => 'fdas',
931 'field3' => 'trans',
932 ),
933 array(
934 'foo' => array(
935 'ctrl' => array(
936 'transOrigPointerTable' => '',
937 'transOrigPointerField' => 'origUid'
938 ),
939 'columns' => array(
940 'field2' => array('l10n_mode' => 'exclude'),
941 'field3' => array('l10n_mode' => 'exclude')
942 )
943 )
944 ),
945 array(
946 'origUid' => 0,
947 'field2' => 'basic',
948 'field3' => '',
949 ),
950 array(
951 'origUid' => 1,
952 'field2' => 'basic',
953 'field3' => '',
954 )
955 ),
956 'other table: exclude' => array(
957 'foo',
958 array(
959 'origUid' => 1,
960 'field2' => 'fdas',
961 'field3' => 'trans',
962 ),
963 array(
964 'foo' => array(
965 'ctrl' => array(
966 'transOrigPointerTable' => 'bar',
967 'transOrigPointerField' => 'origUid'
968 )
969 ),
970 'bar' => array(
971 'columns' => array(
972 'field2' => array('l10n_mode' => 'exclude'),
973 'field3' => array('l10n_mode' => 'exclude')
974 )
975 )
976 ),
977 array(
978 'origUid' => 0,
979 'field2' => 'basic',
980 'field3' => '',
981 ),
982 array(
983 'origUid' => 1,
984 'field2' => 'basic',
985 'field3' => '',
986 )
987 ),
988 );
989 }
990
991 /**
992 * @test
993 * @dataProvider replaceL10nModeFieldsReplacesFieldsDataProvider
994 *
995 * @param string $table
996 * @param array $row
997 * @param array $tca
998 * @param array $originalRow
999 * @param array $expected
1000 *
1001 * @throws \InvalidArgumentException
1002 * @throws \PHPUnit_Framework_Exception
1003 */
1004 public function replaceL10nModeFieldsReplacesFields($table, array $row, array $tca, array $originalRow, $expected) {
1005 $GLOBALS['TCA'] = $tca;
1006 $GLOBALS['TYPO3_DB'] = $this->getMock(DatabaseConnection::class);
1007 $GLOBALS['TYPO3_DB']->expects($this->any())->method('exec_SELECTgetSingleRow')->will($this->returnValue($originalRow));
1008
1009 /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface|BackendUtility $subject */
1010 $subject = $this->getAccessibleMock(BackendUtility::class, array('dummy'));
1011 $this->assertSame($expected, $subject->_call('replaceL10nModeFields', $table, $row));
1012 }
1013
1014 /**
1015 * @test
1016 */
1017 public function getRecordTitleHavingLabelUserFuncCachesValue() {
1018 $table = 'tx_mytable';
1019 $row = ['uid' => 1];
1020
1021 $mock = $this->getMock('stdClass', ['labelUserFunc']);
1022 $mock->expects($this->once())->method('labelUserFunc')->willReturn('Test');
1023
1024 // Use wrapping closure for GeneralUtility::callUserFunction()
1025 $GLOBALS['TCA'][$table]['ctrl']['label_userFunc'] = function(&$parameters) use ($mock) {
1026 $parameters['title'] = $mock->labelUserFunc();
1027 };
1028
1029 $this->assertEquals('Test', BackendUtility::getRecordTitle($table, $row));
1030
1031 // Call a second time to make sure labelUserFunc is not called again ($this->once())
1032 $this->assertEquals('Test', BackendUtility::getRecordTitle($table, $row));
1033 }
1034
1035 /**
1036 * @test
1037 */
1038 public function getSpecConfPartsSplitsDefaultExtras() {
1039 $defaultExtras = 'nowrap:wizards[foo|bar]:anotherDefaultExtras:some[other|setting|with|parameters]';
1040 $expected = array(
1041 'nowrap' => 1,
1042 'wizards' => array(
1043 'parameters' => array(
1044 0 => 'foo',
1045 1 => 'bar',
1046 ),
1047 ),
1048 'anotherDefaultExtras' => 1,
1049 'some' => array(
1050 'parameters' => array(
1051 0 => 'other',
1052 1 => 'setting',
1053 2 => 'with',
1054 3 => 'parameters',
1055 ),
1056 ),
1057 );
1058 $this->assertEquals($expected, BackendUtility::getSpecConfParts($defaultExtras));
1059 }
1060 }