Revert "[BUGFIX] Fix date conversion of neg timestamps"
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / DataHandling / DataHandlerTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\DataHandler;
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\Core\Authentication\BackendUserAuthentication;
18 use TYPO3\CMS\Core\Database\DatabaseConnection;
19 use TYPO3\CMS\Core\DataHandling\DataHandler;
20 use TYPO3\CMS\Core\Tests\AccessibleObjectInterface;
21 use TYPO3\CMS\Core\Tests\Unit\DataHandling\Fixtures\AllowAccessHookFixture;
22 use TYPO3\CMS\Core\Tests\Unit\DataHandling\Fixtures\InvalidHookFixture;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24
25 /**
26 * Test case
27 */
28 class DataHandlerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
29 {
30 /**
31 * @var array A backup of registered singleton instances
32 */
33 protected $singletonInstances = array();
34
35 /**
36 * @var DataHandler|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface
37 */
38 protected $subject;
39
40 /**
41 * @var BackendUserAuthentication a mock logged-in back-end user
42 */
43 protected $backEndUser;
44
45 /**
46 * @var DatabaseConnection|\PHPUnit_Framework_MockObject_MockObject
47 */
48 protected $mockDatabaseConnection;
49
50 /**
51 * Set up the tests
52 */
53 protected function setUp()
54 {
55 $GLOBALS['TCA'] = array();
56 $this->singletonInstances = GeneralUtility::getSingletonInstances();
57 $this->backEndUser = $this->getMock(BackendUserAuthentication::class);
58 $this->mockDatabaseConnection = $this->getMock(DatabaseConnection::class, array(), array(), '', false);
59 $GLOBALS['TYPO3_DB'] = $this->mockDatabaseConnection;
60 $this->subject = $this->getAccessibleMock(DataHandler::class, ['dummy']);
61 $this->subject->start(array(), '', $this->backEndUser);
62 }
63
64 /**
65 * Tear down the tests
66 */
67 protected function tearDown()
68 {
69 GeneralUtility::resetSingletonInstances($this->singletonInstances);
70 parent::tearDown();
71 }
72
73 //////////////////////////////////////
74 // Tests for the basic functionality
75 //////////////////////////////////////
76 /**
77 * @test
78 */
79 public function fixtureCanBeCreated()
80 {
81 $this->assertTrue($this->subject instanceof DataHandler);
82 }
83
84 //////////////////////////////////////////
85 // Test concerning checkModifyAccessList
86 //////////////////////////////////////////
87 /**
88 * @test
89 */
90 public function adminIsAllowedToModifyNonAdminTable()
91 {
92 $this->subject->admin = true;
93 $this->assertTrue($this->subject->checkModifyAccessList('tt_content'));
94 }
95
96 /**
97 * @test
98 */
99 public function nonAdminIsNorAllowedToModifyNonAdminTable()
100 {
101 $this->subject->admin = false;
102 $this->assertFalse($this->subject->checkModifyAccessList('tt_content'));
103 }
104
105 /**
106 * @test
107 */
108 public function nonAdminWithTableModifyAccessIsAllowedToModifyNonAdminTable()
109 {
110 $this->subject->admin = false;
111 $this->backEndUser->groupData['tables_modify'] = 'tt_content';
112 $this->assertTrue($this->subject->checkModifyAccessList('tt_content'));
113 }
114
115 /**
116 * @test
117 */
118 public function adminIsAllowedToModifyAdminTable()
119 {
120 $this->subject->admin = true;
121 $this->assertTrue($this->subject->checkModifyAccessList('be_users'));
122 }
123
124 /**
125 * @test
126 */
127 public function nonAdminIsNotAllowedToModifyAdminTable()
128 {
129 $this->subject->admin = false;
130 $this->assertFalse($this->subject->checkModifyAccessList('be_users'));
131 }
132
133 /**
134 * @test
135 */
136 public function nonAdminWithTableModifyAccessIsNotAllowedToModifyAdminTable()
137 {
138 $tableName = $this->getUniqueId('aTable');
139 $GLOBALS['TCA'] = array(
140 $tableName => array(
141 'ctrl' => array(
142 'adminOnly' => true,
143 ),
144 ),
145 );
146 $this->subject->admin = false;
147 $this->backEndUser->groupData['tables_modify'] = $tableName;
148 $this->assertFalse($this->subject->checkModifyAccessList($tableName));
149 }
150
151 /**
152 * @test
153 */
154 public function evalCheckValueDouble2()
155 {
156 $testData = array(
157 '-0,5' => '-0.50',
158 '1000' => '1000.00',
159 '1000,10' => '1000.10',
160 '1000,0' => '1000.00',
161 '600.000.000,00' => '600000000.00',
162 '60aaa00' => '6000.00'
163 );
164 foreach ($testData as $value => $expectedReturnValue) {
165 $returnValue = $this->subject->checkValue_input_Eval($value, array('double2'), '');
166 $this->assertSame($returnValue['value'], $expectedReturnValue);
167 }
168 }
169
170 /**
171 * Data provider for inputValueCheckRecognizesStringValuesAsIntegerValuesCorrectly
172 *
173 * @return array
174 */
175 public function inputValuesStringsDataProvider()
176 {
177 return array(
178 '"0" returns zero as integer' => array(
179 '0',
180 0
181 ),
182 '"-1999999" is interpreted correctly as -1999999 and is lot lower than -200000' => array(
183 '-1999999',
184 -1999999
185 ),
186 '"3000000" is interpreted correctly as 3000000 but is higher then 200000 and set to 200000' => array(
187 '3000000',
188 2000000
189 ),
190 );
191 }
192
193 /**
194 * @test
195 * @dataProvider inputValuesStringsDataProvider
196 * @param string $value
197 * @param int $expectedReturnValue
198 */
199 public function inputValueCheckRecognizesStringValuesAsIntegerValuesCorrectly($value, $expectedReturnValue)
200 {
201 $tcaFieldConf = array(
202 'input' => array(),
203 'eval' => 'int',
204 'range' => array(
205 'lower' => '-2000000',
206 'upper' => '2000000'
207 )
208 );
209 $returnValue = $this->subject->_call('checkValueForInput', $value, $tcaFieldConf, '', 0, 0, '');
210 $this->assertSame($returnValue['value'], $expectedReturnValue);
211 }
212
213 /**
214 * @return array
215 */
216 public function inputValueCheckCallsGetDateTimeFormatsForDatetimeFieldsDataProvider()
217 {
218 return array(
219 'dbType = date' => array(
220 'date'
221 ),
222 'dbType = datetime' => array(
223 'datetime'
224 )
225 );
226 }
227
228 /**
229 * @test
230 * @dataProvider inputValueCheckCallsGetDateTimeFormatsForDatetimeFieldsDataProvider
231 * @param string $dbType
232 */
233 public function inputValueCheckCallsNotGetDateTimeFormatsForDatetimeFieldsWithEmptyValue($dbType)
234 {
235 $tcaFieldConf = array(
236 'input' => array(),
237 'dbType' => $dbType
238 );
239 $this->mockDatabaseConnection->expects($this->never())->method('getDateTimeFormats');
240 $this->subject->_call('checkValueForInput', '', $tcaFieldConf, '', 0, 0, '');
241 }
242
243 /**
244 * @test
245 * @dataProvider inputValueCheckCallsGetDateTimeFormatsForDatetimeFieldsDataProvider
246 * @param string $dbType
247 */
248 public function inputValueCheckCallsGetDateTimeFormatsForDatetimeFieldsWithNonEmptyValue($dbType)
249 {
250 $dateTimeFormats = [
251 'date' => array(
252 'empty' => '0000-00-00',
253 'format' => 'Y-m-d'
254 ),
255 'datetime' => array(
256 'empty' => '0000-00-00 00:00:00',
257 'format' => 'Y-m-d H:i:s'
258 )
259 ];
260 $tcaFieldConf = array(
261 'input' => array(),
262 'dbType' => $dbType
263 );
264 $this->mockDatabaseConnection->expects($this->once())->method('getDateTimeFormats')->willReturn($dateTimeFormats);
265 $this->subject->_call('checkValueForInput', $dateTimeFormats[$dbType]['empty'], $tcaFieldConf, '', 0, 0, '');
266 }
267
268 /**
269 * @return array
270 */
271 public function inputValueCheckDoesNotCallGetDateTimeFormatsForNonDatetimeFieldsDataProvider()
272 {
273 return array(
274 'tca without dbType' => array(
275 array(
276 'input' => array()
277 )
278 ),
279 'tca with dbType != date/datetime' => array(
280 array(
281 'input' => array(),
282 'dbType' => 'foo'
283 )
284 )
285 );
286 }
287
288 /**
289 * @test
290 * @param array $tcaFieldConf
291 * @dataProvider inputValueCheckDoesNotCallGetDateTimeFormatsForNonDatetimeFieldsDataProvider
292 */
293 public function inputValueCheckDoesNotCallGetDateTimeFormatsForNonDatetimeFields($tcaFieldConf)
294 {
295 $this->mockDatabaseConnection->expects($this->never())->method('getDateTimeFormats');
296 $this->subject->_call('checkValueForInput', '', $tcaFieldConf, '', 0, 0, '');
297 }
298
299 ///////////////////////////////////////////
300 // Tests concerning checkModifyAccessList
301 ///////////////////////////////////////////
302 //
303 /**
304 * Tests whether a wrong interface on the 'checkModifyAccessList' hook throws an exception.
305 *
306 * @test
307 * @expectedException \UnexpectedValueException
308 */
309 public function doesCheckModifyAccessListThrowExceptionOnWrongHookInterface()
310 {
311 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['checkModifyAccessList'][] = InvalidHookFixture::class;
312 $this->subject->checkModifyAccessList('tt_content');
313 }
314
315 /**
316 * Tests whether the 'checkModifyAccessList' hook is called correctly.
317 *
318 * @test
319 */
320 public function doesCheckModifyAccessListHookGetsCalled()
321 {
322 $hookClass = $this->getUniqueId('tx_coretest');
323 $hookMock = $this->getMock(\TYPO3\CMS\Core\DataHandling\DataHandlerCheckModifyAccessListHookInterface::class, array('checkModifyAccessList'), array(), $hookClass);
324 $hookMock->expects($this->once())->method('checkModifyAccessList');
325 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['checkModifyAccessList'][] = $hookClass;
326 $GLOBALS['T3_VAR']['getUserObj'][$hookClass] = $hookMock;
327 $this->subject->checkModifyAccessList('tt_content');
328 }
329
330 /**
331 * Tests whether the 'checkModifyAccessList' hook modifies the $accessAllowed variable.
332 *
333 * @test
334 */
335 public function doesCheckModifyAccessListHookModifyAccessAllowed()
336 {
337 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['checkModifyAccessList'][] = AllowAccessHookFixture::class;
338 $this->assertTrue($this->subject->checkModifyAccessList('tt_content'));
339 }
340
341 /////////////////////////////////////
342 // Tests concerning process_datamap
343 /////////////////////////////////////
344 /**
345 * @test
346 */
347 public function processDatamapForFrozenNonZeroWorkspaceReturnsFalse()
348 {
349 /** @var DataHandler $subject */
350 $subject = $this->getMock(DataHandler::class, array('newlog'));
351 $this->backEndUser->workspace = 1;
352 $this->backEndUser->workspaceRec = array('freeze' => true);
353 $subject->BE_USER = $this->backEndUser;
354 $this->assertFalse($subject->process_datamap());
355 }
356
357 /**
358 * @test
359 */
360 public function processDatamapWhenEditingRecordInWorkspaceCreatesNewRecordInWorkspace()
361 {
362 // Unset possible hooks on method under test
363 // @TODO: Can be removed if unit test boostrap is fixed to not load LocalConfiguration anymore
364 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'] = array();
365
366 $GLOBALS['TCA'] = array(
367 'pages' => array(
368 'columns' => array(),
369 ),
370 );
371
372 /** @var $subject DataHandler|\PHPUnit_Framework_MockObject_MockObject */
373 $subject = $this->getMock(
374 DataHandler::class,
375 array('newlog', 'checkModifyAccessList', 'tableReadOnly', 'checkRecordUpdateAccess')
376 );
377
378 $subject->bypassWorkspaceRestrictions = false;
379 $subject->datamap = array(
380 'pages' => array(
381 '1' => array(
382 'header' => 'demo'
383 )
384 )
385 );
386 $subject->expects($this->once())->method('checkModifyAccessList')->with('pages')->will($this->returnValue(true));
387 $subject->expects($this->once())->method('tableReadOnly')->with('pages')->will($this->returnValue(false));
388 $subject->expects($this->once())->method('checkRecordUpdateAccess')->will($this->returnValue(true));
389
390 /** @var BackendUserAuthentication|\PHPUnit_Framework_MockObject_MockObject $backEndUser */
391 $backEndUser = $this->getMock(BackendUserAuthentication::class);
392 $backEndUser->workspace = 1;
393 $backEndUser->workspaceRec = array('freeze' => false);
394 $backEndUser->expects($this->once())->method('workspaceAllowAutoCreation')->will($this->returnValue(true));
395 $backEndUser->expects($this->once())->method('workspaceCannotEditRecord')->will($this->returnValue(true));
396 $backEndUser->expects($this->once())->method('recordEditAccessInternals')->with('pages', 1)->will($this->returnValue(true));
397 $subject->BE_USER = $backEndUser;
398 $createdTceMain = $this->getMock(DataHandler::class, array());
399 $createdTceMain->expects($this->once())->method('start')->with(array(), array(
400 'pages' => array(
401 1 => array(
402 'version' => array(
403 'action' => 'new',
404 'treeLevels' => -1,
405 'label' => 'Auto-created for WS #1'
406 )
407 )
408 )
409 ));
410 $createdTceMain->expects($this->never())->method('process_datamap');
411 $createdTceMain->expects($this->once())->method('process_cmdmap');
412 GeneralUtility::addInstance(DataHandler::class, $createdTceMain);
413 $subject->process_datamap();
414 }
415
416 /**
417 * @test
418 */
419 public function doesCheckFlexFormValueHookGetsCalled()
420 {
421 $hookClass = $this->getUniqueId('tx_coretest');
422 $hookMock = $this->getMock($hookClass, array('checkFlexFormValue_beforeMerge'));
423 $hookMock->expects($this->once())->method('checkFlexFormValue_beforeMerge');
424 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['checkFlexFormValue'][] = $hookClass;
425 $GLOBALS['T3_VAR']['getUserObj'][$hookClass] = $hookMock;
426 $this->subject->_call('checkValueForFlex', [], [], [], '', 0, '', '', 0, 0, 0, [], '');
427 }
428
429 /////////////////////////////////////
430 // Tests concerning log
431 /////////////////////////////////////
432 /**
433 * @test
434 */
435 public function logCallsWriteLogOfBackendUserIfLoggingIsEnabled()
436 {
437 $backendUser = $this->getMock(BackendUserAuthentication::class);
438 $backendUser->expects($this->once())->method('writelog');
439 $this->subject->enableLogging = true;
440 $this->subject->BE_USER = $backendUser;
441 $this->subject->log('', 23, 0, 42, 0, 'details');
442 }
443
444 /**
445 * @test
446 */
447 public function logDoesNotCallWriteLogOfBackendUserIfLoggingIsDisabled()
448 {
449 $backendUser = $this->getMock(BackendUserAuthentication::class);
450 $backendUser->expects($this->never())->method('writelog');
451 $this->subject->enableLogging = false;
452 $this->subject->BE_USER = $backendUser;
453 $this->subject->log('', 23, 0, 42, 0, 'details');
454 }
455
456 /**
457 * @test
458 */
459 public function logAddsEntryToLocalErrorLogArray()
460 {
461 $backendUser = $this->getMock(BackendUserAuthentication::class);
462 $this->subject->BE_USER = $backendUser;
463 $this->subject->enableLogging = true;
464 $this->subject->errorLog = array();
465 $logDetailsUnique = $this->getUniqueId('details');
466 $this->subject->log('', 23, 0, 42, 1, $logDetailsUnique);
467 $this->assertStringEndsWith($logDetailsUnique, $this->subject->errorLog[0]);
468 }
469
470 /**
471 * @test
472 */
473 public function logFormatsDetailMessageWithAdditionalDataInLocalErrorArray()
474 {
475 $backendUser = $this->getMock(BackendUserAuthentication::class);
476 $this->subject->BE_USER = $backendUser;
477 $this->subject->enableLogging = true;
478 $this->subject->errorLog = array();
479 $logDetails = $this->getUniqueId('details');
480 $this->subject->log('', 23, 0, 42, 1, '%1$s' . $logDetails . '%2$s', -1, array('foo', 'bar'));
481 $expected = 'foo' . $logDetails . 'bar';
482 $this->assertStringEndsWith($expected, $this->subject->errorLog[0]);
483 }
484
485 /**
486 * @param bool $expected
487 * @param string $submittedValue
488 * @param string $storedValue
489 * @param string $storedType
490 * @param bool $allowNull
491 *
492 * @dataProvider equalSubmittedAndStoredValuesAreDeterminedDataProvider
493 * @test
494 */
495 public function equalSubmittedAndStoredValuesAreDetermined($expected, $submittedValue, $storedValue, $storedType, $allowNull)
496 {
497 $result = $this->callInaccessibleMethod(
498 $this->subject,
499 'isSubmittedValueEqualToStoredValue',
500 $submittedValue, $storedValue, $storedType, $allowNull
501 );
502 $this->assertEquals($expected, $result);
503 }
504
505 /**
506 * @return array
507 */
508 public function equalSubmittedAndStoredValuesAreDeterminedDataProvider()
509 {
510 return array(
511 // String
512 'string value "" vs. ""' => array(
513 true,
514 '', '', 'string', false
515 ),
516 'string value 0 vs. "0"' => array(
517 true,
518 0, '0', 'string', false
519 ),
520 'string value 1 vs. "1"' => array(
521 true,
522 1, '1', 'string', false
523 ),
524 'string value "0" vs. ""' => array(
525 false,
526 '0', '', 'string', false
527 ),
528 'string value 0 vs. ""' => array(
529 false,
530 0, '', 'string', false
531 ),
532 'string value null vs. ""' => array(
533 true,
534 null, '', 'string', false
535 ),
536 // Integer
537 'integer value 0 vs. 0' => array(
538 true,
539 0, 0, 'int', false
540 ),
541 'integer value "0" vs. "0"' => array(
542 true,
543 '0', '0', 'int', false
544 ),
545 'integer value 0 vs. "0"' => array(
546 true,
547 0, '0', 'int', false
548 ),
549 'integer value "" vs. "0"' => array(
550 true,
551 '', '0', 'int', false
552 ),
553 'integer value "" vs. 0' => array(
554 true,
555 '', 0, 'int', false
556 ),
557 'integer value "0" vs. 0' => array(
558 true,
559 '0', 0, 'int', false
560 ),
561 'integer value 1 vs. 1' => array(
562 true,
563 1, 1, 'int', false
564 ),
565 'integer value 1 vs. "1"' => array(
566 true,
567 1, '1', 'int', false
568 ),
569 'integer value "1" vs. "1"' => array(
570 true,
571 '1', '1', 'int', false
572 ),
573 'integer value "1" vs. 1' => array(
574 true,
575 '1', 1, 'int', false
576 ),
577 'integer value "0" vs. "1"' => array(
578 false,
579 '0', '1', 'int', false
580 ),
581 // String with allowed NULL values
582 'string with allowed null value "" vs. ""' => array(
583 true,
584 '', '', 'string', true
585 ),
586 'string with allowed null value 0 vs. "0"' => array(
587 true,
588 0, '0', 'string', true
589 ),
590 'string with allowed null value 1 vs. "1"' => array(
591 true,
592 1, '1', 'string', true
593 ),
594 'string with allowed null value "0" vs. ""' => array(
595 false,
596 '0', '', 'string', true
597 ),
598 'string with allowed null value 0 vs. ""' => array(
599 false,
600 0, '', 'string', true
601 ),
602 'string with allowed null value null vs. ""' => array(
603 false,
604 null, '', 'string', true
605 ),
606 'string with allowed null value "" vs. null' => array(
607 false,
608 '', null, 'string', true
609 ),
610 'string with allowed null value null vs. null' => array(
611 true,
612 null, null, 'string', true
613 ),
614 // Integer with allowed NULL values
615 'integer with allowed null value 0 vs. 0' => array(
616 true,
617 0, 0, 'int', true
618 ),
619 'integer with allowed null value "0" vs. "0"' => array(
620 true,
621 '0', '0', 'int', true
622 ),
623 'integer with allowed null value 0 vs. "0"' => array(
624 true,
625 0, '0', 'int', true
626 ),
627 'integer with allowed null value "" vs. "0"' => array(
628 true,
629 '', '0', 'int', true
630 ),
631 'integer with allowed null value "" vs. 0' => array(
632 true,
633 '', 0, 'int', true
634 ),
635 'integer with allowed null value "0" vs. 0' => array(
636 true,
637 '0', 0, 'int', true
638 ),
639 'integer with allowed null value 1 vs. 1' => array(
640 true,
641 1, 1, 'int', true
642 ),
643 'integer with allowed null value "1" vs. "1"' => array(
644 true,
645 '1', '1', 'int', true
646 ),
647 'integer with allowed null value "1" vs. 1' => array(
648 true,
649 '1', 1, 'int', true
650 ),
651 'integer with allowed null value 1 vs. "1"' => array(
652 true,
653 1, '1', 'int', true
654 ),
655 'integer with allowed null value "0" vs. "1"' => array(
656 false,
657 '0', '1', 'int', true
658 ),
659 'integer with allowed null value null vs. ""' => array(
660 false,
661 null, '', 'int', true
662 ),
663 'integer with allowed null value "" vs. null' => array(
664 false,
665 '', null, 'int', true
666 ),
667 'integer with allowed null value null vs. null' => array(
668 true,
669 null, null, 'int', true
670 ),
671 'integer with allowed null value null vs. "0"' => array(
672 false,
673 null, '0', 'int', true
674 ),
675 'integer with allowed null value null vs. 0' => array(
676 false,
677 null, 0, 'int', true
678 ),
679 'integer with allowed null value "0" vs. null' => array(
680 false,
681 '0', null, 'int', true
682 ),
683 );
684 }
685
686 /**
687 * @param bool $expected
688 * @param array $eval
689 * @dataProvider getPlaceholderTitleForTableLabelReturnsLabelThatsMatchesLabelFieldConditionsDataProvider
690 * @test
691 */
692 public function getPlaceholderTitleForTableLabelReturnsLabelThatsMatchesLabelFieldConditions($expected, $eval)
693 {
694 $table = 'phpunit_dummy';
695
696 /** @var DataHandler|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $subject */
697 $subject = $this->getAccessibleMock(
698 DataHandler::class,
699 array('dummy')
700 );
701
702 $backendUser = $this->getMock(BackendUserAuthentication::class);
703 $subject->BE_USER = $backendUser;
704 $subject->BE_USER->workspace = 1;
705
706 $GLOBALS['TCA'][$table] = array();
707 $GLOBALS['TCA'][$table]['ctrl'] = array('label' => 'dummy');
708 $GLOBALS['TCA'][$table]['columns'] = array(
709 'dummy' => array(
710 'config' => array(
711 'eval' => $eval
712 )
713 )
714 );
715
716 $this->assertEquals($expected, $subject->_call('getPlaceholderTitleForTableLabel', $table));
717 }
718
719 /**
720 * @return array
721 */
722 public function getPlaceholderTitleForTableLabelReturnsLabelThatsMatchesLabelFieldConditionsDataProvider()
723 {
724 return array(
725 array(
726 0.10,
727 'double2'
728 ),
729 array(
730 0,
731 'int'
732 ),
733 array(
734 '0',
735 'datetime'
736 ),
737 array(
738 '[PLACEHOLDER, WS#1]',
739 ''
740 )
741 );
742 }
743
744 /**
745 * @test
746 */
747 public function deletePagesOnRootLevelIsDenied()
748 {
749 /** @var DataHandler|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $dataHandlerMock */
750 $dataHandlerMock = $this->getMock(DataHandler::class, ['canDeletePage', 'newlog2']);
751 $dataHandlerMock
752 ->expects($this->never())
753 ->method('canDeletePage');
754 $dataHandlerMock
755 ->expects($this->once())
756 ->method('newlog2')
757 ->with('Deleting all pages starting from the root-page is disabled.', 'pages', 0, 0, 2);
758
759 $dataHandlerMock->deletePages(0);
760 }
761
762 /**
763 * @test
764 */
765 public function deleteRecord_procBasedOnFieldTypeRespectsEnableCascadingDelete()
766 {
767 $table = $this->getUniqueId('foo_');
768 $conf = array(
769 'type' => 'inline',
770 'foreign_table' => $this->getUniqueId('foreign_foo_'),
771 'behaviour' => array(
772 'enableCascadingDelete' => 0,
773 )
774 );
775
776 /** @var \TYPO3\CMS\Core\Database\RelationHandler $mockRelationHandler */
777 $mockRelationHandler = $this->getMock(\TYPO3\CMS\Core\Database\RelationHandler::class, array(), array(), '', false);
778 $mockRelationHandler->itemArray = array(
779 '1' => array('table' => $this->getUniqueId('bar_'), 'id' => 67)
780 );
781
782 /** @var DataHandler|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $mockDataHandler */
783 $mockDataHandler = $this->getAccessibleMock(DataHandler::class, array('getInlineFieldType', 'deleteAction', 'createRelationHandlerInstance'), array(), '', false);
784 $mockDataHandler->expects($this->once())->method('getInlineFieldType')->will($this->returnValue('field'));
785 $mockDataHandler->expects($this->once())->method('createRelationHandlerInstance')->will($this->returnValue($mockRelationHandler));
786 $mockDataHandler->expects($this->never())->method('deleteAction');
787 $mockDataHandler->deleteRecord_procBasedOnFieldType($table, 42, 'foo', 'bar', $conf);
788 }
789
790 /**
791 * @return array
792 */
793 public function checkValue_checkReturnsExpectedValuesDataProvider()
794 {
795 return array(
796 'None item selected' => array(
797 0,
798 0
799 ),
800 'All items selected' => array(
801 7,
802 7
803 ),
804 'Item 1 and 2 are selected' => array(
805 3,
806 3
807 ),
808 'Value is higher than allowed' => array(
809 15,
810 7
811 ),
812 'Negative value' => array(
813 -5,
814 0
815 )
816 );
817 }
818
819 /**
820 * @param string $value
821 * @param string $expectedValue
822 *
823 * @dataProvider checkValue_checkReturnsExpectedValuesDataProvider
824 * @test
825 */
826 public function checkValue_checkReturnsExpectedValues($value, $expectedValue)
827 {
828 $expectedResult = array(
829 'value' => $expectedValue
830 );
831 $result = array();
832 $tcaFieldConfiguration = array(
833 'items' => array(
834 array('Item 1', 0),
835 array('Item 2', 0),
836 array('Item 3', 0)
837 )
838 );
839 $this->assertSame($expectedResult, $this->subject->_call('checkValueForCheck', $result, $value, $tcaFieldConfiguration, '', 0, 0, ''));
840 }
841
842 /**
843 * @test
844 */
845 public function checkValueForInputConvertsNullToEmptyString()
846 {
847 $previousLanguageService = $GLOBALS['LANG'];
848 $GLOBALS['LANG'] = GeneralUtility::makeInstance(\TYPO3\CMS\Lang\LanguageService::class);
849 $GLOBALS['LANG']->init('default');
850 $expectedResult = array('value' => '');
851 $this->assertSame($expectedResult, $this->subject->_call('checkValueForInput', null, array('type' => 'string', 'max' => 40), 'tt_content', 'NEW55c0e67f8f4d32.04974534', 89, 'table_caption'));
852 $GLOBALS['LANG'] = $previousLanguageService;
853 }
854
855 /**
856 * @param mixed $value
857 * @param array $configuration
858 * @param int|string $expected
859 * @test
860 * @dataProvider referenceValuesAreCastedDataProvider
861 */
862 public function referenceValuesAreCasted($value, array $configuration, $expected)
863 {
864 $this->assertEquals(
865 $expected,
866 $this->subject->_call('castReferenceValue', $value, $configuration)
867 );
868 }
869
870 /**
871 * @return array
872 */
873 public function referenceValuesAreCastedDataProvider()
874 {
875 return array(
876 'all empty' => array(
877 '', array(), ''
878 ),
879 'cast zero with MM table' => array(
880 '', array('MM' => 'table'), 0
881 ),
882 'cast zero with MM table with default value' => array(
883 '', array('MM' => 'table', 'default' => 13), 0
884 ),
885 'cast zero with foreign field' => array(
886 '', array('foreign_field' => 'table', 'default' => 13), 0
887 ),
888 'cast zero with foreign field with default value' => array(
889 '', array('foreign_field' => 'table'), 0
890 ),
891 'pass zero' => array(
892 '0', array(), '0'
893 ),
894 'pass value' => array(
895 '1', array('default' => 13), '1'
896 ),
897 'use default value' => array(
898 '', array('default' => 13), 13
899 ),
900 );
901 }
902 }