Revert "[TASK] Rebuild the calcAge functionality"
[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 TYPO3\CMS\Backend\Utility\BackendUtility;
18
19 /**
20 * Test case
21 *
22 * @author Oliver Klee <typo3-coding@oliverklee.de>
23 */
24 class BackendUtilityTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
25
26 ///////////////////////////////////////
27 // Tests concerning calcAge
28 ///////////////////////////////////////
29 /**
30 * Data provider for calcAge function
31 *
32 * @return array
33 */
34 public function calcAgeDataProvider() {
35 return array(
36 'Single year' => array(
37 'seconds' => 60 * 60 * 24 * 365,
38 'expectedLabel' => '1 year'
39 ),
40 'Plural years' => array(
41 'seconds' => 60 * 60 * 24 * 365 * 2,
42 'expectedLabel' => '2 yrs'
43 ),
44 'Single negative year' => array(
45 'seconds' => 60 * 60 * 24 * 365 * -1,
46 'expectedLabel' => '-1 year'
47 ),
48 'Plural negative years' => array(
49 'seconds' => 60 * 60 * 24 * 365 * 2 * -1,
50 'expectedLabel' => '-2 yrs'
51 ),
52 'Single day' => array(
53 'seconds' => 60 * 60 * 24,
54 'expectedLabel' => '1 day'
55 ),
56 'Plural days' => array(
57 'seconds' => 60 * 60 * 24 * 2,
58 'expectedLabel' => '2 days'
59 ),
60 'Single negative day' => array(
61 'seconds' => 60 * 60 * 24 * -1,
62 'expectedLabel' => '-1 day'
63 ),
64 'Plural negative days' => array(
65 'seconds' => 60 * 60 * 24 * 2 * -1,
66 'expectedLabel' => '-2 days'
67 ),
68 'Single hour' => array(
69 'seconds' => 60 * 60,
70 'expectedLabel' => '1 hour'
71 ),
72 'Plural hours' => array(
73 'seconds' => 60 * 60 * 2,
74 'expectedLabel' => '2 hrs'
75 ),
76 'Single negative hour' => array(
77 'seconds' => 60 * 60 * -1,
78 'expectedLabel' => '-1 hour'
79 ),
80 'Plural negative hours' => array(
81 'seconds' => 60 * 60 * 2 * -1,
82 'expectedLabel' => '-2 hrs'
83 ),
84 'Single minute' => array(
85 'seconds' => 60,
86 'expectedLabel' => '1 min'
87 ),
88 'Plural minutes' => array(
89 'seconds' => 60 * 2,
90 'expectedLabel' => '2 min'
91 ),
92 'Single negative minute' => array(
93 'seconds' => 60 * -1,
94 'expectedLabel' => '-1 min'
95 ),
96 'Plural negative minutes' => array(
97 'seconds' => 60 * 2 * -1,
98 'expectedLabel' => '-2 min'
99 ),
100 'Zero seconds' => array(
101 'seconds' => 0,
102 'expectedLabel' => '0 min'
103 )
104 );
105 }
106
107 /**
108 * @test
109 * @dataProvider calcAgeDataProvider
110 */
111 public function calcAgeReturnsExpectedValues($seconds, $expectedLabel) {
112 $this->assertSame($expectedLabel, BackendUtility::calcAge($seconds));
113 }
114
115 ///////////////////////////////////////
116 // Tests concerning getProcessedValue
117 ///////////////////////////////////////
118 /**
119 * @test
120 * @see http://forge.typo3.org/issues/20994
121 */
122 public function getProcessedValueForZeroStringIsZero() {
123 $GLOBALS['TCA'] = array(
124 'tt_content' => array(
125 'columns' => array(
126 'header' => array(
127 'config' => array(
128 'type' => 'input',
129 ),
130 ),
131 ),
132 ),
133 );
134 $this->assertEquals('0', BackendUtility::getProcessedValue('tt_content', 'header', '0'));
135 }
136
137 /**
138 * @test
139 */
140 public function getProcessedValueForGroup() {
141 $GLOBALS['TCA'] = array(
142 'tt_content' => array(
143 'columns' => array(
144 'multimedia' => array(
145 'config' => array(
146 'type' => 'group',
147 ),
148 ),
149 ),
150 ),
151 );
152 $this->assertSame('1, 2', BackendUtility::getProcessedValue('tt_content', 'multimedia', '1,2'));
153 }
154
155 /**
156 * @test
157 */
158 public function getProcessedValueForGroupWithOneAllowedTable() {
159 // Disable getRecordWSOL and getRecordTitle dependency by returning stable results
160 /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Backend\Utility\BackendUtility $subject */
161 $className = uniqid('BackendUtility');
162 $subject = __NAMESPACE__ . '\\' . $className;
163 eval(
164 'namespace ' . __NAMESPACE__ . ';' .
165 'class ' . $className . ' extends \\TYPO3\\CMS\\Backend\\Utility\\BackendUtility {' .
166 ' static public function getRecordWSOL() {' .
167 ' static $called = 0;' .
168 ' ++$called;' .
169 ' if ($called === 1) {' .
170 ' return array(\'title\' => \'Page 1\');' .
171 ' }' .
172 ' if ($called === 2) {' .
173 ' return array(\'title\' => \'Page 2\');' .
174 ' }' .
175 ' }' .
176 ' static public function getRecordTitle() {' .
177 ' static $called = 0;' .
178 ' ++$called;' .
179 ' if ($called === 1) {' .
180 ' return \'Page 1\';' .
181 ' }' .
182 ' if ($called === 2) {' .
183 ' return \'Page 2\';' .
184 ' }' .
185 ' }' .
186 '}'
187 );
188
189 $GLOBALS['TCA'] = array(
190 'tt_content' => array(
191 'columns' => array(
192 'pages' => array(
193 'config' => array(
194 'type' => 'group',
195 'allowed' => 'pages',
196 'internal_type' => 'db',
197 'maxitems' => 22,
198 'minitems' => 0,
199 'show_thumbs' => 1,
200 'size' => 3,
201 ),
202 ),
203 ),
204 ),
205 );
206
207 $this->assertSame('Page 1, Page 2', $subject::getProcessedValue('tt_content', 'pages', '1,2'));
208 }
209
210 /**
211 * @test
212 */
213 public function getProcessedValueForGroupWithMultipleAllowedTables() {
214 // Disable getRecordWSOL and getRecordTitle dependency by returning stable results
215 /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Backend\Utility\BackendUtility $subject */
216 $className = uniqid('BackendUtility');
217 $subject = __NAMESPACE__ . '\\' . $className;
218 eval(
219 'namespace ' . __NAMESPACE__ . ';' .
220 'class ' . $className . ' extends \\TYPO3\\CMS\\Backend\\Utility\\BackendUtility {' .
221 ' static public function getRecordWSOL() {' .
222 ' static $called = 0;' .
223 ' ++$called;' .
224 ' if ($called === 1) {' .
225 ' return array(\'title\' => \'Page 1\');' .
226 ' }' .
227 ' if ($called === 2) {' .
228 ' return array(\'header\' => \'Content 2\');' .
229 ' }' .
230 ' }' .
231 ' static public function getRecordTitle() {' .
232 ' static $called = 0;' .
233 ' ++$called;' .
234 ' if ($called === 1) {' .
235 ' return \'Page 1\';' .
236 ' }' .
237 ' if ($called === 2) {' .
238 ' return \'Content 2\';' .
239 ' }' .
240 ' }' .
241 '}'
242 );
243
244 $GLOBALS['TCA'] = array(
245 'sys_category' => array(
246 'columns' => array(
247 'items' => array(
248 'config' => array(
249 'allowed' => '*',
250 'internal_type' => 'db',
251 'MM' => 'sys_category_record_mm',
252 'size' => 10,
253 'type' => 'group',
254 ),
255 ),
256 ),
257 ),
258 );
259
260 $this->assertSame('Page 1, Content 2', $subject::getProcessedValue('sys_category', 'items', 'pages_1,tt_content_2'));
261 }
262
263 /**
264 * Tests concerning getCommonSelectFields
265 */
266
267 /**
268 * Data provider for getCommonSelectFieldsReturnsCorrectFields
269 *
270 * @return array The test data with $table, $prefix, $presetFields, $tca, $expectedFields
271 */
272 public function getCommonSelectFieldsReturnsCorrectFieldsDataProvider() {
273 return array(
274 'only uid' => array(
275 'table' => 'test_table',
276 'prefix' => '',
277 'presetFields' => array(),
278 'tca' => array(),
279 'expectedFields' => 'uid'
280 ),
281 'label set' => array(
282 'table' => 'test_table',
283 'prefix' => '',
284 'presetFields' => array(),
285 'tca' => array(
286 'ctrl' => array(
287 'label' => 'label'
288 )
289 ),
290 'expectedFields' => 'uid,label'
291 ),
292 'label_alt set' => array(
293 'table' => 'test_table',
294 'prefix' => '',
295 'presetFields' => array(),
296 'tca' => array(
297 'ctrl' => array(
298 'label_alt' => 'label,label2'
299 )
300 ),
301 'expectedFields' => 'uid,label,label2'
302 ),
303 'versioningWS set' => array(
304 'table' => 'test_table',
305 'prefix' => '',
306 'presetFields' => array(),
307 'tca' => array(
308 'ctrl' => array(
309 'versioningWS' => '2'
310 )
311 ),
312 'expectedFields' => 'uid,t3ver_id,t3ver_state,t3ver_wsid,t3ver_count'
313 ),
314 'selicon_field set' => array(
315 'table' => 'test_table',
316 'prefix' => '',
317 'presetFields' => array(),
318 'tca' => array(
319 'ctrl' => array(
320 'selicon_field' => 'field'
321 )
322 ),
323 'expectedFields' => 'uid,field'
324 ),
325 'typeicon_column set' => array(
326 'table' => 'test_table',
327 'prefix' => '',
328 'presetFields' => array(),
329 'tca' => array(
330 'ctrl' => array(
331 'typeicon_column' => 'field'
332 )
333 ),
334 'expectedFields' => 'uid,field'
335 ),
336 'enablecolumns set' => array(
337 'table' => 'test_table',
338 'prefix' => '',
339 'presetFields' => array(),
340 'tca' => array(
341 'ctrl' => array(
342 'enablecolumns' => array(
343 'disabled' => 'hidden',
344 'starttime' => 'start',
345 'endtime' => 'stop',
346 'fe_group' => 'groups'
347 )
348 )
349 ),
350 'expectedFields' => 'uid,hidden,start,stop,groups'
351 ),
352 'label set to uid' => array(
353 'table' => 'test_table',
354 'prefix' => '',
355 'presetFields' => array(),
356 'tca' => array(
357 'ctrl' => array(
358 'label' => 'uid'
359 )
360 ),
361 'expectedFields' => 'uid'
362 )
363 );
364 }
365
366 /**
367 * @test
368 * @dataProvider getCommonSelectFieldsReturnsCorrectFieldsDataProvider
369 */
370 public function getCommonSelectFieldsReturnsCorrectFields($table, $prefix = '', array $presetFields, array $tca, $expectedFields = '') {
371 $GLOBALS['TCA'][$table] = $tca;
372 $selectFields = BackendUtility::getCommonSelectFields($table, $prefix, $presetFields);
373 $this->assertEquals($selectFields, $expectedFields);
374 }
375
376 /**
377 * Tests concerning getLabelFromItemlist
378 */
379
380 /**
381 * Data provider for getLabelFromItemlistReturnsCorrectFields
382 *
383 * @return array The test data with $table, $col, $key, $expectedLabel
384 */
385 public function getLabelFromItemlistReturnsCorrectFieldsDataProvider() {
386 return array(
387 'item set' => array(
388 'table' => 'tt_content',
389 'col' => 'menu_type',
390 'key' => '1',
391 'tca' => array(
392 'columns' => array(
393 'menu_type' => array(
394 'config' => array(
395 'items' => array(
396 array('Item 1', '0'),
397 array('Item 2', '1'),
398 array('Item 3', '3')
399 )
400 )
401 )
402 )
403 ),
404 'expectedLabel' => 'Item 2'
405 ),
406 'item set twice' => array(
407 'table' => 'tt_content',
408 'col' => 'menu_type',
409 'key' => '1',
410 'tca' => array(
411 'columns' => array(
412 'menu_type' => array(
413 'config' => array(
414 'items' => array(
415 array('Item 1', '0'),
416 array('Item 2a', '1'),
417 array('Item 2b', '1'),
418 array('Item 3', '3')
419 )
420 )
421 )
422 )
423 ),
424 'expectedLabel' => 'Item 2a'
425 ),
426 'item not found' => array(
427 'table' => 'tt_content',
428 'col' => 'menu_type',
429 'key' => '5',
430 'tca' => array(
431 'columns' => array(
432 'menu_type' => array(
433 'config' => array(
434 'items' => array(
435 array('Item 1', '0'),
436 array('Item 2', '1'),
437 array('Item 3', '2')
438 )
439 )
440 )
441 )
442 ),
443 'expectedLabel' => NULL
444 )
445 );
446 }
447
448 /**
449 * @test
450 * @dataProvider getLabelFromItemlistReturnsCorrectFieldsDataProvider
451 */
452 public function getLabelFromItemlistReturnsCorrectFields($table, $col = '', $key = '', array $tca, $expectedLabel = '') {
453 $GLOBALS['TCA'][$table] = $tca;
454 $label = BackendUtility::getLabelFromItemlist($table, $col, $key);
455 $this->assertEquals($label, $expectedLabel);
456 }
457
458 /**
459 * Tests concerning getLabelFromItemListMerged
460 */
461
462 /**
463 * Data provider for getLabelFromItemListMerged
464 *
465 * @return array The test data with $pageId, $table, $column, $key, $expectedLabel
466 */
467 public function getLabelFromItemListMergedReturnsCorrectFieldsDataProvider() {
468 return array(
469 'no field found' => array(
470 'pageId' => '123',
471 'table' => 'tt_content',
472 'col' => 'menu_type',
473 'key' => '10',
474 'tca' => array(
475 'columns' => array(
476 'menu_type' => array(
477 'config' => array(
478 'items' => array(
479 array('Item 1', '0'),
480 array('Item 2', '1'),
481 array('Item 3', '3')
482 )
483 )
484 )
485 )
486 ),
487 'expectedLabel' => ''
488 ),
489 'no tsconfig set' => array(
490 'pageId' => '123',
491 'table' => 'tt_content',
492 'col' => 'menu_type',
493 'key' => '1',
494 'tca' => array(
495 'columns' => array(
496 'menu_type' => array(
497 'config' => array(
498 'items' => array(
499 array('Item 1', '0'),
500 array('Item 2', '1'),
501 array('Item 3', '3')
502 )
503 )
504 )
505 )
506 ),
507 'expectedLabel' => 'Item 2'
508 )
509 );
510 }
511
512 /**
513 * @test
514 * @dataProvider getLabelFromItemListMergedReturnsCorrectFieldsDataProvider
515 */
516 public function getLabelFromItemListMergedReturnsCorrectFields($pageId, $table, $column = '', $key = '', array $tca, $expectedLabel = '') {
517 // Disable getPagesTSconfig by returning stable result
518 /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Backend\Utility\BackendUtility $subject */
519 $className = uniqid('BackendUtility');
520 $subject = __NAMESPACE__ . '\\' . $className;
521 eval(
522 'namespace ' . __NAMESPACE__ . ';' .
523 'class ' . $className . ' extends \\TYPO3\\CMS\\Backend\\Utility\\BackendUtility {' .
524 ' static public function getPagesTSconfig() {' .
525 ' return array();' .
526 ' }' .
527 '}'
528 );
529
530 $GLOBALS['TCA'][$table] = $tca;
531
532 $this->assertEquals($expectedLabel, $subject::getLabelFromItemListMerged($pageId, $table, $column, $key));
533 }
534
535 /**
536 * Tests concerning getFuncCheck
537 */
538
539 /**
540 * @test
541 */
542 public function getFuncCheckReturnsInputTagWithValueAttribute() {
543 $this->assertStringMatchesFormat('<input %Svalue="1"%S/>', BackendUtility::getFuncCheck('params', 'test', TRUE));
544 }
545
546 /**
547 * Tests concerning getLabelsFromItemsList
548 */
549
550 /**
551 * @test
552 */
553 public function getLabelsFromItemsListReturnsValueIfItemIsFound() {
554 $table = 'foobar';
555 $col = 'someColumn';
556 $tca = array(
557 'columns' => array(
558 'someColumn' => array(
559 'config' => array(
560 'items' => array(
561 '0' => array('aFooLabel', 'foo'),
562 '1' => array('aBarLabel', 'bar')
563 )
564 )
565 )
566 )
567 );
568 // Stub LanguageService and let sL() return the same value that came in again
569 $GLOBALS['LANG'] = $this->getMock('TYPO3\\CMS\\Lang\\LanguageService', array(), array(), '', FALSE);
570 $GLOBALS['LANG']->expects($this->any())->method('sL')
571 ->will($this->returnCallback(
572 function($name) {
573 return $name;
574 }
575 ));
576
577 $GLOBALS['TCA'][$table] = $tca;
578 $label = BackendUtility::getLabelsFromItemsList($table, $col, 'foo,bar');
579 $this->assertEquals('aFooLabel, aBarLabel', $label);
580 }
581
582 /**
583 * @test
584 */
585 public function getProcessedValueReturnsLabelsForExistingValuesSolely() {
586 $table = 'foobar';
587 $col = 'someColumn';
588 $tca = array(
589 'columns' => array(
590 'someColumn' => array(
591 'config' => array(
592 'type' => 'select',
593 'items' => array(
594 '0' => array('aFooLabel', 'foo'),
595 '1' => array('aBarLabel', 'bar')
596 )
597 )
598 )
599 )
600 );
601 // Stub LanguageService and let sL() return the same value that came in again
602 $GLOBALS['LANG'] = $this->getMock('TYPO3\\CMS\\Lang\\LanguageService', array(), array(), '', FALSE);
603 $GLOBALS['LANG']->charSet = 'utf-8';
604 $GLOBALS['LANG']->csConvObj = $this->getMock('TYPO3\\CMS\\Core\\Charset\\CharsetConverter');
605 $GLOBALS['LANG']->expects($this->any())->method('sL')
606 ->will($this->returnCallback(
607 function($name) {
608 return $name;
609 }
610 ));
611 $GLOBALS['LANG']->csConvObj->expects($this->any())->method('crop')
612 ->will($this->returnCallback(
613 function($charset, $string, $len, $crop = '') {
614 return $string;
615 }
616 ));
617
618 $GLOBALS['TCA'][$table] = $tca;
619 $label = BackendUtility::getProcessedValue($table, $col, 'foo,invalidKey,bar');
620 $this->assertEquals('aFooLabel, aBarLabel', $label);
621 }
622
623 /**
624 * @test
625 */
626 public function getProcessedValueReturnsPlainValueIfItemIsNotFound() {
627 $table = 'foobar';
628 $col = 'someColumn';
629 $tca = array(
630 'columns' => array(
631 'someColumn' => array(
632 'config' => array(
633 'type' => 'select',
634 'items' => array(
635 '0' => array('aFooLabel', 'foo')
636 )
637 )
638 )
639 )
640 );
641 // Stub LanguageService and let sL() return the same value that came in again
642 $GLOBALS['LANG'] = $this->getMock('TYPO3\\CMS\\Lang\\LanguageService', array(), array(), '', FALSE);
643 $GLOBALS['LANG']->charSet = 'utf-8';
644 $GLOBALS['LANG']->csConvObj = $this->getMock('TYPO3\\CMS\\Core\\Charset\\CharsetConverter');
645 $GLOBALS['LANG']->expects($this->any())->method('sL')
646 ->will($this->returnCallback(
647 function($name) {
648 return $name;
649 }
650 ));
651 $GLOBALS['LANG']->csConvObj->expects($this->any())->method('crop')
652 ->will($this->returnCallback(
653 function($charset, $string, $len, $crop = '') {
654 return $string;
655 }
656 ));
657
658 $GLOBALS['TCA'][$table] = $tca;
659 $label = BackendUtility::getProcessedValue($table, $col, 'invalidKey');
660 $this->assertEquals('invalidKey', $label);
661 }
662
663 /**
664 * Tests concerning getExcludeFields
665 */
666
667 /**
668 * @return array
669 */
670 public function getExcludeFieldsDataProvider() {
671 return array(
672 'getExcludeFields does not return fields not configured as exclude field' => array(
673 array(
674 'tx_foo' => array(
675 'ctrl' => array(
676 'title' => 'foo',
677 ),
678 'columns' => array(
679 'bar' => array(
680 'label' => 'bar',
681 'exclude' => 1
682 ),
683 'baz' => array(
684 'label' => 'bar',
685 ),
686 )
687 )
688 ),
689 array(
690 array(
691 'foo: bar',
692 'tx_foo:bar',
693 ),
694 )
695 ),
696 'getExcludeFields returns fields from root level tables if root level restriction should be ignored' => array(
697 array(
698 'tx_foo' => array(
699 'ctrl' => array(
700 'title' => 'foo',
701 'rootLevel' => TRUE,
702 'security' => array(
703 'ignoreRootLevelRestriction' => TRUE,
704 ),
705 ),
706 'columns' => array(
707 'bar' => array(
708 'label' => 'bar',
709 'exclude' => 1
710 ),
711 )
712 )
713 ),
714 array(
715 array(
716 'foo: bar',
717 'tx_foo:bar',
718 ),
719 )
720 ),
721 'getExcludeFields does not return fields from root level tables' => array(
722 array(
723 'tx_foo' => array(
724 'ctrl' => array(
725 'title' => 'foo',
726 'rootLevel' => TRUE,
727 ),
728 'columns' => array(
729 'bar' => array(
730 'label' => 'bar',
731 'exclude' => 1
732 ),
733 )
734 )
735 ),
736 array()
737 ),
738 'getExcludeFields does not return fields from admin only level tables' => array(
739 array(
740 'tx_foo' => array(
741 'ctrl' => array(
742 'title' => 'foo',
743 'adminOnly' => TRUE,
744 ),
745 'columns' => array(
746 'bar' => array(
747 'label' => 'bar',
748 'exclude' => 1
749 ),
750 )
751 )
752 ),
753 array()
754 ),
755 );
756 }
757
758 /**
759 * @param $tca
760 * @param $expected
761 *
762 * @test
763 * @dataProvider getExcludeFieldsDataProvider
764 */
765 public function getExcludeFieldsReturnsCorrectFieldList($tca, $expected) {
766 /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Backend\Utility\BackendUtility $subject */
767 $className = uniqid('BackendUtility');
768 $subject = __NAMESPACE__ . '\\' . $className;
769 eval(
770 'namespace ' . __NAMESPACE__ . ';' .
771 'class ' . $className . ' extends \\TYPO3\\CMS\\Backend\\Utility\\BackendUtility {' .
772 ' static public function getRegisteredFlexForms() {' .
773 ' return array();' .
774 ' }' .
775 '}'
776 );
777
778 $GLOBALS['TCA'] = $tca;
779
780 // Stub LanguageService and let sL() return the same value that came in again
781 $GLOBALS['LANG'] = $this->getMock('TYPO3\\CMS\\Lang\\LanguageService', array(), array(), '', FALSE);
782 $GLOBALS['LANG']->expects($this->any())->method('sL')
783 ->will($this->returnCallback(
784 function($name) {
785 return $name;
786 }
787 ));
788
789 $this->assertSame($expected, $subject::getExcludeFields());
790 }
791
792 /**
793 * @test
794 */
795 public function getExcludeFieldsReturnsCorrectListWithFlexFormFields() {
796 $GLOBALS['TCA'] = array(
797 'tx_foo' => array(
798 'ctrl' => array(
799 'title' => 'foo'
800 ),
801 'columns' => array(
802 'foo' => array(
803 'label' => 'foo',
804 'exclude' => 1
805 ),
806 'bar' => array(
807 'label' => 'bar',
808 'exclude' => 1
809 ),
810 'abarfoo' => array(
811 'label' => 'abarfoo',
812 'config' => array(
813 'type' => 'flex',
814 'ds' => array(
815 '*,dummy' => '',
816 )
817 )
818 )
819 )
820 ),
821 'tx_foobar' => array(
822 'ctrl' => array(
823 'title' => 'foobar'
824 ),
825 'columns' => array(
826 'foo' => array(
827 'label' => 'foo',
828 'exclude' => 1
829 ),
830 'bar' => array(
831 'label' => 'bar',
832 'exclude' => 1
833 )
834 )
835 ),
836 'tx_bar' => array(
837 'ctrl' => array(
838 'title' => 'bar'
839 ),
840 'columns' => array(
841 'foo' => array(
842 'label' => 'foo',
843 'exclude' => 1
844 ),
845 'bar' => array(
846 'label' => 'bar',
847 'exclude' => 1
848 )
849 )
850 )
851 );
852
853 $expectedResult = array(
854 array(
855 'bar: bar',
856 'tx_bar:bar'
857 ),
858 array(
859 'bar: foo',
860 'tx_bar:foo'
861 ),
862 array(
863 'abarfoo dummy: The Title:',
864 'tx_foo:abarfoo;dummy;sGeneral;xmlTitle'
865 ),
866 array(
867 'foo: bar',
868 'tx_foo:bar'
869 ),
870 array(
871 'foo: foo',
872 'tx_foo:foo'
873 ),
874 array(
875 'foobar: bar',
876 'tx_foobar:bar'
877 ),
878 array(
879 'foobar: foo',
880 'tx_foobar:foo'
881 ),
882 );
883
884 // Stub LanguageService and let sL() return the same value that came in again
885 $GLOBALS['LANG'] = $this->getMock('TYPO3\\CMS\\Lang\\LanguageService', array(), array(), '', FALSE);
886 $GLOBALS['LANG']->expects($this->any())->method('sL')
887 ->will($this->returnCallback(
888 function($name) {
889 return $name;
890 }
891 ));
892
893 /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Backend\Utility\BackendUtility $subject */
894 $className = uniqid('BackendUtility');
895 $subject = __NAMESPACE__ . '\\' . $className;
896 eval(
897 'namespace ' . __NAMESPACE__ . ';' .
898 'class ' . $className . ' extends \\TYPO3\\CMS\\Backend\\Utility\\BackendUtility {' .
899 ' static public function getRegisteredFlexForms($table) {' .
900 ' static $called = 0;' .
901 ' ++$called;' .
902 ' if ($called === 1) {' .
903 ' return array();' .
904 ' }' .
905 ' if ($called === 2) {' .
906 ' if ($table !== \'tx_foo\') {' .
907 ' throw new Exception(\'Expected tx_foo as argument on call 2\', 1399638572);' .
908 ' }' .
909 ' $parsedFlexForm = array(' .
910 ' \'abarfoo\' => array(' .
911 ' \'dummy\' => array(' .
912 ' \'title\' => \'dummy\',' .
913 ' \'ds\' => array(' .
914 ' \'sheets\' => array(' .
915 ' \'sGeneral\' => array(' .
916 ' \'ROOT\' => array(' .
917 ' \'type\' => \'array\',' .
918 ' \'el\' => array(' .
919 ' \'xmlTitle\' => array(' .
920 ' \'TCEforms\' => array(' .
921 ' \'exclude\' => 1,' .
922 ' \'label\' => \'The Title:\',' .
923 ' \'config\' => array(' .
924 ' \'type\' => \'input\',' .
925 ' \'size\' => 48,' .
926 ' ),' .
927 ' ),' .
928 ' ),' .
929 ' ),' .
930 ' ),' .
931 ' ),' .
932 ' ),' .
933 ' ),' .
934 ' ),' .
935 ' ),' .
936 ' );' .
937 ' return $parsedFlexForm;' .
938 ' }' .
939 ' if ($called === 3) {' .
940 ' return array();' .
941 ' }' .
942 ' }' .
943 '}'
944 );
945
946 $this->assertSame($expectedResult, $subject::getExcludeFields());
947 }
948
949 /**
950 * Tests concerning viewOnClick
951 */
952
953 /**
954 * @test
955 */
956 public function viewOnClickReturnsOnClickCodeWithAlternativeUrl() {
957 // Make sure the hook inside viewOnClick is not fired. This may be removed if unit tests
958 // bootstrap does not initialize TYPO3_CONF_VARS anymore.
959 unset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['viewOnClickClass']);
960
961 $alternativeUrl = 'https://typo3.org/about/typo3-the-cms/the-history-of-typo3/#section';
962 $onclickCode = 'var previewWin = window.open(\'' . $alternativeUrl . '\',\'newTYPO3frontendWindow\');';
963 $this->assertStringMatchesFormat(
964 $onclickCode,
965 BackendUtility::viewOnClick(NULL, NULL, NULL, NULL, $alternativeUrl, NULL, FALSE)
966 );
967 }
968
969 /**
970 * Tests concerning replaceMarkersInWhereClause
971 */
972
973 /**
974 * @return array
975 */
976 public function replaceMarkersInWhereClauseDataProvider() {
977 return array(
978 'replaceMarkersInWhereClause replaces record field marker with quoted string' => array(
979 ' AND dummytable.title=\'###REC_FIELD_dummyfield###\'',
980 array(
981 '_THIS_ROW' => array(
982 'dummyfield' => 'Hello World'
983 )
984 ),
985 ' AND dummytable.title=\'Hello World\''
986 ),
987 'replaceMarkersInWhereClause replaces record field marker with fullquoted string' => array(
988 ' AND dummytable.title=###REC_FIELD_dummyfield###',
989 array(
990 '_THIS_ROW' => array(
991 'dummyfield' => 'Hello World'
992 )
993 ),
994 ' AND dummytable.title=\'Hello World\''
995 ),
996 'replaceMarkersInWhereClause replaces multiple record field markers' => array(
997 ' AND dummytable.title=\'###REC_FIELD_dummyfield###\' AND dummytable.pid=###REC_FIELD_pid###',
998 array(
999 '_THIS_ROW' => array(
1000 'dummyfield' => 'Hello World',
1001 'pid' => 42
1002 )
1003 ),
1004 ' AND dummytable.title=\'Hello World\' AND dummytable.pid=\'42\''
1005 ),
1006 'replaceMarkersInWhereClause replaces current pid with integer' => array(
1007 ' AND dummytable.uid=###CURRENT_PID###',
1008 array(
1009 '_CURRENT_PID' => 42
1010 ),
1011 ' AND dummytable.uid=42'
1012 ),
1013 'replaceMarkersInWhereClause replaces current pid with string' => array(
1014 ' AND dummytable.uid=###CURRENT_PID###',
1015 array(
1016 '_CURRENT_PID' => '42string'
1017 ),
1018 ' AND dummytable.uid=42'
1019 ),
1020 'replaceMarkersInWhereClause replaces current record uid with integer' => array(
1021 ' AND dummytable.uid=###THIS_UID###',
1022 array(
1023 '_THIS_UID' => 42
1024 ),
1025 ' AND dummytable.uid=42'
1026 ),
1027 'replaceMarkersInWhereClause replaces current record uid with string' => array(
1028 ' AND dummytable.uid=###THIS_UID###',
1029 array(
1030 '_THIS_UID' => '42string'
1031 ),
1032 ' AND dummytable.uid=42'
1033 ),
1034 'replaceMarkersInWhereClause replaces current record cid with integer' => array(
1035 ' AND dummytable.uid=###THIS_CID###',
1036 array(
1037 '_THIS_CID' => 42
1038 ),
1039 ' AND dummytable.uid=42'
1040 ),
1041 'replaceMarkersInWhereClause replaces current record cid with string' => array(
1042 ' AND dummytable.uid=###THIS_CID###',
1043 array(
1044 '_THIS_CID' => '42string'
1045 ),
1046 ' AND dummytable.uid=42'
1047 ),
1048 'replaceMarkersInWhereClause replaces storage pid with integer' => array(
1049 ' AND dummytable.uid=###STORAGE_PID###',
1050 array(
1051 '_STORAGE_PID' => 42
1052 ),
1053 ' AND dummytable.uid=42'
1054 ),
1055 'replaceMarkersInWhereClause replaces storage pid with string' => array(
1056 ' AND dummytable.uid=###STORAGE_PID###',
1057 array(
1058 '_STORAGE_PID' => '42string'
1059 ),
1060 ' AND dummytable.uid=42'
1061 ),
1062 'replaceMarkersInWhereClause replaces siteroot uid with integer' => array(
1063 ' AND dummytable.uid=###SITEROOT###',
1064 array(
1065 '_SITEROOT' => 42
1066 ),
1067 ' AND dummytable.uid=42'
1068 ),
1069 'replaceMarkersInWhereClause replaces siteroot uid with string' => array(
1070 ' AND dummytable.uid=###SITEROOT###',
1071 array(
1072 '_SITEROOT' => '42string'
1073 ),
1074 ' AND dummytable.uid=42'
1075 ),
1076 'replaceMarkersInWhereClause replaces page tsconfig id with integer' => array(
1077 ' AND dummytable.uid=###PAGE_TSCONFIG_ID###',
1078 array(
1079 'dummyfield' => array(
1080 'PAGE_TSCONFIG_ID' => 42
1081 )
1082 ),
1083 ' AND dummytable.uid=42'
1084 ),
1085 'replaceMarkersInWhereClause replaces page tsconfig id with string' => array(
1086 ' AND dummytable.uid=###PAGE_TSCONFIG_ID###',
1087 array(
1088 'dummyfield' => array(
1089 'PAGE_TSCONFIG_ID' => '42string'
1090 )
1091 ),
1092 ' AND dummytable.uid=42'
1093 ),
1094 'replaceMarkersInWhereClause replaces page tsconfig string' => array(
1095 ' AND dummytable.title=\'###PAGE_TSCONFIG_STR###\'',
1096 array(
1097 'dummyfield' => array(
1098 'PAGE_TSCONFIG_STR' => '42'
1099 )
1100 ),
1101 ' AND dummytable.title=\'42\''
1102 ),
1103 'replaceMarkersInWhereClause replaces all markers' => array(
1104 ' AND dummytable.title=\'###REC_FIELD_dummyfield###\'' .
1105 ' AND dummytable.uid=###REC_FIELD_uid###' .
1106 ' AND dummytable.pid=###CURRENT_PID###' .
1107 ' AND dummytable.l18n_parent=###THIS_UID###' .
1108 ' AND dummytable.cid=###THIS_CID###' .
1109 ' AND dummytable.storage_pid=###STORAGE_PID###' .
1110 ' AND dummytable.siteroot=###SITEROOT###' .
1111 ' AND dummytable.config_uid=###PAGE_TSCONFIG_ID###' .
1112 ' AND dummytable.idlist IN (###PAGE_TSCONFIG_IDLIST###)' .
1113 ' AND dummytable.string=\'###PAGE_TSCONFIG_STR###\'',
1114 array(
1115 '_THIS_ROW' => array(
1116 'dummyfield' => 'Hello World',
1117 'uid' => 42
1118 ),
1119 '_CURRENT_PID' => '1',
1120 '_THIS_UID' => 2,
1121 '_THIS_CID' => 3,
1122 '_STORAGE_PID' => 4,
1123 '_SITEROOT' => 5,
1124 'dummyfield' => array(
1125 'PAGE_TSCONFIG_ID' => 6,
1126 'PAGE_TSCONFIG_IDLIST' => '1,2,3',
1127 'PAGE_TSCONFIG_STR' => 'string'
1128 )
1129 ),
1130 ' AND dummytable.title=\'Hello World\' AND dummytable.uid=\'42\' AND dummytable.pid=1' .
1131 ' AND dummytable.l18n_parent=2 AND dummytable.cid=3 AND dummytable.storage_pid=4' .
1132 ' AND dummytable.siteroot=5 AND dummytable.config_uid=6 AND dummytable.idlist IN (1,2,3)' .
1133 ' AND dummytable.string=\'string\'',
1134 ),
1135 );
1136 }
1137
1138 /**
1139 * @test
1140 * @dataProvider replaceMarkersInWhereClauseDataProvider
1141 */
1142 public function replaceMarkersInWhereClauseReturnsValidWhereClause($whereClause, $tsConfig, $expected) {
1143 // Mock TYPO3_DB and let it return same values that came in
1144 $GLOBALS['TYPO3_DB'] = $this->getMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array(), array(), '', FALSE);
1145 $GLOBALS['TYPO3_DB']->expects($this->any())->method('quoteStr')
1146 ->will($this->returnCallback(
1147 function($quoteStr, $table) {
1148 return $quoteStr;
1149 }
1150 ));
1151 $GLOBALS['TYPO3_DB']->expects($this->any())->method('fullQuoteStr')
1152 ->will($this->returnCallback(
1153 function($quoteStr, $table) {
1154 return "'" . $quoteStr . "'";
1155 }
1156 ));
1157 $GLOBALS['TYPO3_DB']->expects($this->any())->method('cleanIntList')
1158 ->will($this->returnCallback(
1159 function($intList) {
1160 return $intList;
1161 }
1162 ));
1163 $this->assertSame($expected, BackendUtility::replaceMarkersInWhereClause($whereClause, 'dummytable', 'dummyfield', $tsConfig));
1164 }
1165
1166 /**
1167 * @test
1168 */
1169 public function replaceMarkersInWhereClauseCleansIdList() {
1170 $GLOBALS['TYPO3_DB'] = $this->getMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection', array(), array(), '', FALSE);
1171 $GLOBALS['TYPO3_DB']->expects($this->once())->method('cleanIntList')->with('1,a,2,b,3,c');
1172 $where = ' AND dummytable.uid IN (###PAGE_TSCONFIG_IDLIST###)';
1173 $tsConfig = array(
1174 'dummyfield' => array(
1175 'PAGE_TSCONFIG_IDLIST' => '1,a,2,b,3,c'
1176 ),
1177 );
1178 BackendUtility::replaceMarkersInWhereClause($where, 'dummytable', 'dummyfield', $tsConfig);
1179 }
1180
1181 /**
1182 * @test
1183 */
1184 public function getModTSconfigIgnoresValuesFromUserTsConfigIfNoSet() {
1185 $completeConfiguration = array(
1186 'value' => 'bar',
1187 'properties' => array(
1188 'permissions.' => array(
1189 'file.' => array(
1190 'default.' => array('readAction' => '1'),
1191 '1.' => array('writeAction' => '1'),
1192 '0.' => array('readAction' => '0'),
1193 ),
1194 )
1195 )
1196 );
1197
1198 $GLOBALS['BE_USER'] = $this->getMock('TYPO3\\CMS\\Core\\Authentication\\BackendUserAuthentication', array(), array(), '', FALSE);
1199 $GLOBALS['BE_USER']->expects($this->at(0))->method('getTSConfig')->will($this->returnValue($completeConfiguration));
1200 $GLOBALS['BE_USER']->expects($this->at(1))->method('getTSConfig')->will($this->returnValue(array('value' => NULL, 'properties' => NULL)));
1201
1202 /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Backend\Utility\BackendUtility $subject */
1203 $className = uniqid('BackendUtility');
1204 $subject = __NAMESPACE__ . '\\' . $className;
1205 eval(
1206 'namespace ' . __NAMESPACE__ . ';' .
1207 'class ' . $className . ' extends \\TYPO3\\CMS\\Backend\\Utility\\BackendUtility {' .
1208 ' static public function getPagesTSconfig() {' .
1209 ' return array();' .
1210 ' }' .
1211 '}'
1212 );
1213
1214 $this->assertSame($completeConfiguration, $subject::getModTSconfig(42, 'notrelevant'));
1215 }
1216
1217 /**
1218 * Data provider for replaceL10nModeFieldsReplacesFields
1219 * @return array
1220 */
1221 public function replaceL10nModeFieldsReplacesFieldsDataProvider() {
1222 return array(
1223 'same table: mergeIfNotBlank' => array(
1224 'foo',
1225 array(
1226 'origUid' => 1,
1227 'field2' => 'fdas',
1228 'field3' => 'trans',
1229 ),
1230 array(
1231 'foo' => array(
1232 'ctrl' => array(
1233 'transOrigPointerTable' => '',
1234 'transOrigPointerField' => 'origUid'
1235 ),
1236 'columns' => array(
1237 'field2' => array('l10n_mode' => 'mergeIfNotBlank'),
1238 'field3' => array('l10n_mode' => 'mergeIfNotBlank')
1239 )
1240 )
1241 ),
1242 array(
1243 'origUid' => 0,
1244 'field2' => 'basic',
1245 'field3' => '',
1246 ),
1247 array(
1248 'origUid' => 1,
1249 'field2' => 'basic',
1250 'field3' => 'trans',
1251 )
1252 ),
1253 'other table: mergeIfNotBlank' => array(
1254 'foo',
1255 array(
1256 'origUid' => 1,
1257 'field2' => 'fdas',
1258 'field3' => 'trans',
1259 ),
1260 array(
1261 'foo' => array(
1262 'ctrl' => array(
1263 'transOrigPointerTable' => 'bar',
1264 'transOrigPointerField' => 'origUid'
1265 )
1266 ),
1267 'bar' => array(
1268 'columns' => array(
1269 'field2' => array('l10n_mode' => 'mergeIfNotBlank'),
1270 'field3' => array('l10n_mode' => 'mergeIfNotBlank')
1271 )
1272 )
1273 ),
1274 array(
1275 'origUid' => 0,
1276 'field2' => 'basic',
1277 'field3' => '',
1278 ),
1279 array(
1280 'origUid' => 1,
1281 'field2' => 'basic',
1282 'field3' => 'trans',
1283 )
1284 ),
1285 'same table: exclude' => array(
1286 'foo',
1287 array(
1288 'origUid' => 1,
1289 'field2' => 'fdas',
1290 'field3' => 'trans',
1291 ),
1292 array(
1293 'foo' => array(
1294 'ctrl' => array(
1295 'transOrigPointerTable' => '',
1296 'transOrigPointerField' => 'origUid'
1297 ),
1298 'columns' => array(
1299 'field2' => array('l10n_mode' => 'exclude'),
1300 'field3' => array('l10n_mode' => 'exclude')
1301 )
1302 )
1303 ),
1304 array(
1305 'origUid' => 0,
1306 'field2' => 'basic',
1307 'field3' => '',
1308 ),
1309 array(
1310 'origUid' => 1,
1311 'field2' => 'basic',
1312 'field3' => '',
1313 )
1314 ),
1315 'other table: exclude' => array(
1316 'foo',
1317 array(
1318 'origUid' => 1,
1319 'field2' => 'fdas',
1320 'field3' => 'trans',
1321 ),
1322 array(
1323 'foo' => array(
1324 'ctrl' => array(
1325 'transOrigPointerTable' => 'bar',
1326 'transOrigPointerField' => 'origUid'
1327 )
1328 ),
1329 'bar' => array(
1330 'columns' => array(
1331 'field2' => array('l10n_mode' => 'exclude'),
1332 'field3' => array('l10n_mode' => 'exclude')
1333 )
1334 )
1335 ),
1336 array(
1337 'origUid' => 0,
1338 'field2' => 'basic',
1339 'field3' => '',
1340 ),
1341 array(
1342 'origUid' => 1,
1343 'field2' => 'basic',
1344 'field3' => '',
1345 )
1346 ),
1347 );
1348 }
1349
1350 /**
1351 * @test
1352 * @dataProvider replaceL10nModeFieldsReplacesFieldsDataProvider
1353 */
1354 public function replaceL10nModeFieldsReplacesFields($table, $row, $tca, $originalRow, $expected) {
1355 $GLOBALS['TCA'] = $tca;
1356 $GLOBALS['TYPO3_DB'] = $this->getMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection');
1357 $GLOBALS['TYPO3_DB']->expects($this->any())->method('sql_fetch_assoc')->will($this->returnValue($originalRow));
1358
1359 /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface|\TYPO3\CMS\Backend\Utility\BackendUtility $subject */
1360 $subject = $this->getAccessibleMock('TYPO3\\CMS\\Backend\\Utility\\BackendUtility', array('dummy'));
1361 $this->assertSame($expected, $subject->_call('replaceL10nModeFields', $table, $row));
1362 }
1363 }