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