[TASK] Doctrine: Migrate DatabaseConnection::getDateTimeFormats()
[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->createMock(BackendUserAuthentication::class);
58 $this->mockDatabaseConnection = $this->createMock(DatabaseConnection::class);
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 public function dataProviderDatetime()
171 {
172 // Three elements: input, timezone of input, expected output (UTC)
173 return [
174 // German standard time (without DST) is one hour ahead of UTC
175 'date in 2016 in German timezone' => [
176 1457103519, 'Europe/Berlin', 1457103519 - 3600
177 ],
178 'date in 1969 in German timezone' => [
179 -7200, 'Europe/Berlin', -10800
180 ],
181 // Los Angeles is 8 hours behind UTC
182 'date in 2016 in Los Angeles timezone' => [
183 1457103519, 'America/Los_Angeles', 1457103519 + 28800
184 ],
185 'date in UTC' => [
186 1457103519, 'UTC', 1457103519
187 ]
188 ];
189 }
190
191 /**
192 * @test
193 * @dataProvider dataProviderDatetime
194 */
195 public function evalCheckValueDatetime($input, $serverTimezone, $expectedOutput)
196 {
197 $oldTimezone = date_default_timezone_get();
198 date_default_timezone_set($serverTimezone);
199
200 $output = $this->subject->checkValue_input_Eval($input, ['datetime'], '');
201
202 // set before the assertion is performed, so it is restored even for failing tests
203 date_default_timezone_set($oldTimezone);
204
205 $this->assertEquals($expectedOutput, $output['value']);
206 }
207
208 /**
209 * Data provider for inputValueCheckRecognizesStringValuesAsIntegerValuesCorrectly
210 *
211 * @return array
212 */
213 public function inputValuesStringsDataProvider()
214 {
215 return array(
216 '"0" returns zero as integer' => array(
217 '0',
218 0
219 ),
220 '"-1999999" is interpreted correctly as -1999999 and is lot lower than -200000' => array(
221 '-1999999',
222 -1999999
223 ),
224 '"3000000" is interpreted correctly as 3000000 but is higher then 200000 and set to 200000' => array(
225 '3000000',
226 2000000
227 ),
228 );
229 }
230
231 /**
232 * @test
233 * @dataProvider inputValuesStringsDataProvider
234 * @param string $value
235 * @param int $expectedReturnValue
236 */
237 public function inputValueCheckRecognizesStringValuesAsIntegerValuesCorrectly($value, $expectedReturnValue)
238 {
239 $tcaFieldConf = array(
240 'input' => array(),
241 'eval' => 'int',
242 'range' => array(
243 'lower' => '-2000000',
244 'upper' => '2000000'
245 )
246 );
247 $returnValue = $this->subject->_call('checkValueForInput', $value, $tcaFieldConf, '', 0, 0, '');
248 $this->assertSame($returnValue['value'], $expectedReturnValue);
249 }
250
251 /**
252 * @return array
253 */
254 public function inputValueCheckDoesNotCallGetDateTimeFormatsForNonDatetimeFieldsDataProvider()
255 {
256 return array(
257 'tca without dbType' => array(
258 array(
259 'input' => array()
260 )
261 ),
262 'tca with dbType != date/datetime' => array(
263 array(
264 'input' => array(),
265 'dbType' => 'foo'
266 )
267 )
268 );
269 }
270
271 /**
272 * @test
273 * @param array $tcaFieldConf
274 * @dataProvider inputValueCheckDoesNotCallGetDateTimeFormatsForNonDatetimeFieldsDataProvider
275 */
276 public function inputValueCheckDoesNotCallGetDateTimeFormatsForNonDatetimeFields($tcaFieldConf)
277 {
278 $this->mockDatabaseConnection->expects($this->never())->method('getDateTimeFormats');
279 $this->subject->_call('checkValueForInput', '', $tcaFieldConf, '', 0, 0, '');
280 }
281
282 ///////////////////////////////////////////
283 // Tests concerning checkModifyAccessList
284 ///////////////////////////////////////////
285 //
286 /**
287 * Tests whether a wrong interface on the 'checkModifyAccessList' hook throws an exception.
288 * @test
289 */
290 public function doesCheckModifyAccessListThrowExceptionOnWrongHookInterface()
291 {
292 $this->expectException(\UnexpectedValueException::class);
293 $this->expectExceptionCode(1251892472);
294
295 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['checkModifyAccessList'][] = InvalidHookFixture::class;
296 $this->subject->checkModifyAccessList('tt_content');
297 }
298
299 /**
300 * Tests whether the 'checkModifyAccessList' hook is called correctly.
301 *
302 * @test
303 */
304 public function doesCheckModifyAccessListHookGetsCalled()
305 {
306 $hookClass = $this->getUniqueId('tx_coretest');
307 $hookMock = $this->getMockBuilder(\TYPO3\CMS\Core\DataHandling\DataHandlerCheckModifyAccessListHookInterface::class)
308 ->setMethods(array('checkModifyAccessList'))
309 ->setMockClassName($hookClass)
310 ->getMock();
311 $hookMock->expects($this->once())->method('checkModifyAccessList');
312 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['checkModifyAccessList'][] = $hookClass;
313 GeneralUtility::addInstance($hookClass, $hookMock);
314 $this->subject->checkModifyAccessList('tt_content');
315 }
316
317 /**
318 * Tests whether the 'checkModifyAccessList' hook modifies the $accessAllowed variable.
319 *
320 * @test
321 */
322 public function doesCheckModifyAccessListHookModifyAccessAllowed()
323 {
324 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['checkModifyAccessList'][] = AllowAccessHookFixture::class;
325 $this->assertTrue($this->subject->checkModifyAccessList('tt_content'));
326 }
327
328 /////////////////////////////////////
329 // Tests concerning process_datamap
330 /////////////////////////////////////
331 /**
332 * @test
333 */
334 public function processDatamapForFrozenNonZeroWorkspaceReturnsFalse()
335 {
336 /** @var DataHandler $subject */
337 $subject = $this->getMockBuilder(DataHandler::class)
338 ->setMethods(array('newlog'))
339 ->getMock();
340 $this->backEndUser->workspace = 1;
341 $this->backEndUser->workspaceRec = array('freeze' => true);
342 $subject->BE_USER = $this->backEndUser;
343 $this->assertFalse($subject->process_datamap());
344 }
345
346 /**
347 * @test
348 */
349 public function processDatamapWhenEditingRecordInWorkspaceCreatesNewRecordInWorkspace()
350 {
351 $GLOBALS['TCA'] = array(
352 'pages' => array(
353 'columns' => array(),
354 ),
355 );
356
357 /** @var $subject DataHandler|\PHPUnit_Framework_MockObject_MockObject */
358 $subject = $this->getMockBuilder(DataHandler::class)
359 ->setMethods(array('newlog', 'checkModifyAccessList', 'tableReadOnly', 'checkRecordUpdateAccess', 'recordInfo'))
360 ->getMock();
361
362 $subject->bypassWorkspaceRestrictions = false;
363 $subject->datamap = array(
364 'pages' => array(
365 '1' => array(
366 'header' => 'demo'
367 )
368 )
369 );
370 $subject->expects($this->once())->method('recordInfo')->will($this->returnValue(null));
371 $subject->expects($this->once())->method('checkModifyAccessList')->with('pages')->will($this->returnValue(true));
372 $subject->expects($this->once())->method('tableReadOnly')->with('pages')->will($this->returnValue(false));
373 $subject->expects($this->once())->method('checkRecordUpdateAccess')->will($this->returnValue(true));
374
375 /** @var BackendUserAuthentication|\PHPUnit_Framework_MockObject_MockObject $backEndUser */
376 $backEndUser = $this->createMock(BackendUserAuthentication::class);
377 $backEndUser->workspace = 1;
378 $backEndUser->workspaceRec = array('freeze' => false);
379 $backEndUser->expects($this->once())->method('workspaceAllowAutoCreation')->will($this->returnValue(true));
380 $backEndUser->expects($this->once())->method('workspaceCannotEditRecord')->will($this->returnValue(true));
381 $backEndUser->expects($this->once())->method('recordEditAccessInternals')->with('pages', 1)->will($this->returnValue(true));
382 $subject->BE_USER = $backEndUser;
383 $createdTceMain = $this->createMock(DataHandler::class);
384 $createdTceMain->expects($this->once())->method('start')->with(array(), array(
385 'pages' => array(
386 1 => array(
387 'version' => array(
388 'action' => 'new',
389 'treeLevels' => -1,
390 'label' => 'Auto-created for WS #1'
391 )
392 )
393 )
394 ));
395 $createdTceMain->expects($this->never())->method('process_datamap');
396 $createdTceMain->expects($this->once())->method('process_cmdmap');
397 GeneralUtility::addInstance(DataHandler::class, $createdTceMain);
398 $subject->process_datamap();
399 }
400
401 /**
402 * @test
403 */
404 public function doesCheckFlexFormValueHookGetsCalled()
405 {
406 $hookClass = $this->getUniqueId('tx_coretest');
407 $hookMock = $this->getMockBuilder($hookClass)
408 ->setMethods(array('checkFlexFormValue_beforeMerge'))
409 ->getMock();
410 $hookMock->expects($this->once())->method('checkFlexFormValue_beforeMerge');
411 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['checkFlexFormValue'][] = $hookClass;
412 GeneralUtility::addInstance($hookClass, $hookMock);
413 $this->subject->_call('checkValueForFlex', [], [], [], '', 0, '', '', 0, 0, 0, [], '');
414 }
415
416 /////////////////////////////////////
417 // Tests concerning log
418 /////////////////////////////////////
419 /**
420 * @test
421 */
422 public function logCallsWriteLogOfBackendUserIfLoggingIsEnabled()
423 {
424 $backendUser = $this->createMock(BackendUserAuthentication::class);
425 $backendUser->expects($this->once())->method('writelog');
426 $this->subject->enableLogging = true;
427 $this->subject->BE_USER = $backendUser;
428 $this->subject->log('', 23, 0, 42, 0, 'details');
429 }
430
431 /**
432 * @test
433 */
434 public function logDoesNotCallWriteLogOfBackendUserIfLoggingIsDisabled()
435 {
436 $backendUser = $this->createMock(BackendUserAuthentication::class);
437 $backendUser->expects($this->never())->method('writelog');
438 $this->subject->enableLogging = false;
439 $this->subject->BE_USER = $backendUser;
440 $this->subject->log('', 23, 0, 42, 0, 'details');
441 }
442
443 /**
444 * @test
445 */
446 public function logAddsEntryToLocalErrorLogArray()
447 {
448 $backendUser = $this->createMock(BackendUserAuthentication::class);
449 $this->subject->BE_USER = $backendUser;
450 $this->subject->enableLogging = true;
451 $this->subject->errorLog = array();
452 $logDetailsUnique = $this->getUniqueId('details');
453 $this->subject->log('', 23, 0, 42, 1, $logDetailsUnique);
454 $this->assertStringEndsWith($logDetailsUnique, $this->subject->errorLog[0]);
455 }
456
457 /**
458 * @test
459 */
460 public function logFormatsDetailMessageWithAdditionalDataInLocalErrorArray()
461 {
462 $backendUser = $this->createMock(BackendUserAuthentication::class);
463 $this->subject->BE_USER = $backendUser;
464 $this->subject->enableLogging = true;
465 $this->subject->errorLog = array();
466 $logDetails = $this->getUniqueId('details');
467 $this->subject->log('', 23, 0, 42, 1, '%1$s' . $logDetails . '%2$s', -1, array('foo', 'bar'));
468 $expected = 'foo' . $logDetails . 'bar';
469 $this->assertStringEndsWith($expected, $this->subject->errorLog[0]);
470 }
471
472 /**
473 * @param bool $expected
474 * @param string $submittedValue
475 * @param string $storedValue
476 * @param string $storedType
477 * @param bool $allowNull
478 *
479 * @dataProvider equalSubmittedAndStoredValuesAreDeterminedDataProvider
480 * @test
481 */
482 public function equalSubmittedAndStoredValuesAreDetermined($expected, $submittedValue, $storedValue, $storedType, $allowNull)
483 {
484 $result = $this->callInaccessibleMethod(
485 $this->subject,
486 'isSubmittedValueEqualToStoredValue',
487 $submittedValue, $storedValue, $storedType, $allowNull
488 );
489 $this->assertEquals($expected, $result);
490 }
491
492 /**
493 * @return array
494 */
495 public function equalSubmittedAndStoredValuesAreDeterminedDataProvider()
496 {
497 return array(
498 // String
499 'string value "" vs. ""' => array(
500 true,
501 '', '', 'string', false
502 ),
503 'string value 0 vs. "0"' => array(
504 true,
505 0, '0', 'string', false
506 ),
507 'string value 1 vs. "1"' => array(
508 true,
509 1, '1', 'string', false
510 ),
511 'string value "0" vs. ""' => array(
512 false,
513 '0', '', 'string', false
514 ),
515 'string value 0 vs. ""' => array(
516 false,
517 0, '', 'string', false
518 ),
519 'string value null vs. ""' => array(
520 true,
521 null, '', 'string', false
522 ),
523 // Integer
524 'integer value 0 vs. 0' => array(
525 true,
526 0, 0, 'int', false
527 ),
528 'integer value "0" vs. "0"' => array(
529 true,
530 '0', '0', 'int', false
531 ),
532 'integer value 0 vs. "0"' => array(
533 true,
534 0, '0', 'int', false
535 ),
536 'integer value "" vs. "0"' => array(
537 true,
538 '', '0', 'int', false
539 ),
540 'integer value "" vs. 0' => array(
541 true,
542 '', 0, 'int', false
543 ),
544 'integer value "0" vs. 0' => array(
545 true,
546 '0', 0, 'int', false
547 ),
548 'integer value 1 vs. 1' => array(
549 true,
550 1, 1, 'int', false
551 ),
552 'integer value 1 vs. "1"' => array(
553 true,
554 1, '1', 'int', false
555 ),
556 'integer value "1" vs. "1"' => array(
557 true,
558 '1', '1', 'int', false
559 ),
560 'integer value "1" vs. 1' => array(
561 true,
562 '1', 1, 'int', false
563 ),
564 'integer value "0" vs. "1"' => array(
565 false,
566 '0', '1', 'int', false
567 ),
568 // String with allowed NULL values
569 'string with allowed null value "" vs. ""' => array(
570 true,
571 '', '', 'string', true
572 ),
573 'string with allowed null value 0 vs. "0"' => array(
574 true,
575 0, '0', 'string', true
576 ),
577 'string with allowed null value 1 vs. "1"' => array(
578 true,
579 1, '1', 'string', true
580 ),
581 'string with allowed null value "0" vs. ""' => array(
582 false,
583 '0', '', 'string', true
584 ),
585 'string with allowed null value 0 vs. ""' => array(
586 false,
587 0, '', 'string', true
588 ),
589 'string with allowed null value null vs. ""' => array(
590 false,
591 null, '', 'string', true
592 ),
593 'string with allowed null value "" vs. null' => array(
594 false,
595 '', null, 'string', true
596 ),
597 'string with allowed null value null vs. null' => array(
598 true,
599 null, null, 'string', true
600 ),
601 // Integer with allowed NULL values
602 'integer with allowed null value 0 vs. 0' => array(
603 true,
604 0, 0, 'int', true
605 ),
606 'integer with allowed null value "0" vs. "0"' => array(
607 true,
608 '0', '0', 'int', true
609 ),
610 'integer with allowed null value 0 vs. "0"' => array(
611 true,
612 0, '0', 'int', true
613 ),
614 'integer with allowed null value "" vs. "0"' => array(
615 true,
616 '', '0', 'int', true
617 ),
618 'integer with allowed null value "" vs. 0' => array(
619 true,
620 '', 0, 'int', true
621 ),
622 'integer with allowed null value "0" vs. 0' => array(
623 true,
624 '0', 0, 'int', true
625 ),
626 'integer with allowed null value 1 vs. 1' => array(
627 true,
628 1, 1, 'int', true
629 ),
630 'integer with allowed null value "1" vs. "1"' => array(
631 true,
632 '1', '1', 'int', true
633 ),
634 'integer with allowed null value "1" vs. 1' => array(
635 true,
636 '1', 1, 'int', true
637 ),
638 'integer with allowed null value 1 vs. "1"' => array(
639 true,
640 1, '1', 'int', true
641 ),
642 'integer with allowed null value "0" vs. "1"' => array(
643 false,
644 '0', '1', 'int', true
645 ),
646 'integer with allowed null value null vs. ""' => array(
647 false,
648 null, '', 'int', true
649 ),
650 'integer with allowed null value "" vs. null' => array(
651 false,
652 '', null, 'int', true
653 ),
654 'integer with allowed null value null vs. null' => array(
655 true,
656 null, null, 'int', true
657 ),
658 'integer with allowed null value null vs. "0"' => array(
659 false,
660 null, '0', 'int', true
661 ),
662 'integer with allowed null value null vs. 0' => array(
663 false,
664 null, 0, 'int', true
665 ),
666 'integer with allowed null value "0" vs. null' => array(
667 false,
668 '0', null, 'int', true
669 ),
670 );
671 }
672
673 /**
674 * @param bool $expected
675 * @param array $eval
676 * @dataProvider getPlaceholderTitleForTableLabelReturnsLabelThatsMatchesLabelFieldConditionsDataProvider
677 * @test
678 */
679 public function getPlaceholderTitleForTableLabelReturnsLabelThatsMatchesLabelFieldConditions($expected, $eval)
680 {
681 $table = 'phpunit_dummy';
682
683 /** @var DataHandler|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $subject */
684 $subject = $this->getAccessibleMock(
685 DataHandler::class,
686 array('dummy')
687 );
688
689 $backendUser = $this->createMock(BackendUserAuthentication::class);
690 $subject->BE_USER = $backendUser;
691 $subject->BE_USER->workspace = 1;
692
693 $GLOBALS['TCA'][$table] = array();
694 $GLOBALS['TCA'][$table]['ctrl'] = array('label' => 'dummy');
695 $GLOBALS['TCA'][$table]['columns'] = array(
696 'dummy' => array(
697 'config' => array(
698 'eval' => $eval
699 )
700 )
701 );
702
703 $this->assertEquals($expected, $subject->_call('getPlaceholderTitleForTableLabel', $table));
704 }
705
706 /**
707 * @return array
708 */
709 public function getPlaceholderTitleForTableLabelReturnsLabelThatsMatchesLabelFieldConditionsDataProvider()
710 {
711 return array(
712 array(
713 0.10,
714 'double2'
715 ),
716 array(
717 0,
718 'int'
719 ),
720 array(
721 '0',
722 'datetime'
723 ),
724 array(
725 '[PLACEHOLDER, WS#1]',
726 ''
727 )
728 );
729 }
730
731 /**
732 * @test
733 */
734 public function deletePagesOnRootLevelIsDenied()
735 {
736 /** @var DataHandler|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $dataHandlerMock */
737 $dataHandlerMock = $this->getMockBuilder(DataHandler::class)
738 ->setMethods(['canDeletePage', 'newlog2'])
739 ->getMock();
740 $dataHandlerMock
741 ->expects($this->never())
742 ->method('canDeletePage');
743 $dataHandlerMock
744 ->expects($this->once())
745 ->method('newlog2')
746 ->with('Deleting all pages starting from the root-page is disabled.', 'pages', 0, 0, 2);
747
748 $dataHandlerMock->deletePages(0);
749 }
750
751 /**
752 * @test
753 */
754 public function deleteRecord_procBasedOnFieldTypeRespectsEnableCascadingDelete()
755 {
756 $table = $this->getUniqueId('foo_');
757 $conf = array(
758 'type' => 'inline',
759 'foreign_table' => $this->getUniqueId('foreign_foo_'),
760 'behaviour' => array(
761 'enableCascadingDelete' => 0,
762 )
763 );
764
765 /** @var \TYPO3\CMS\Core\Database\RelationHandler $mockRelationHandler */
766 $mockRelationHandler = $this->createMock(\TYPO3\CMS\Core\Database\RelationHandler::class);
767 $mockRelationHandler->itemArray = array(
768 '1' => array('table' => $this->getUniqueId('bar_'), 'id' => 67)
769 );
770
771 /** @var DataHandler|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $mockDataHandler */
772 $mockDataHandler = $this->getAccessibleMock(DataHandler::class, array('getInlineFieldType', 'deleteAction', 'createRelationHandlerInstance'), array(), '', false);
773 $mockDataHandler->expects($this->once())->method('getInlineFieldType')->will($this->returnValue('field'));
774 $mockDataHandler->expects($this->once())->method('createRelationHandlerInstance')->will($this->returnValue($mockRelationHandler));
775 $mockDataHandler->expects($this->never())->method('deleteAction');
776 $mockDataHandler->deleteRecord_procBasedOnFieldType($table, 42, 'foo', 'bar', $conf);
777 }
778
779 /**
780 * @return array
781 */
782 public function checkValue_checkReturnsExpectedValuesDataProvider()
783 {
784 return array(
785 'None item selected' => array(
786 0,
787 0
788 ),
789 'All items selected' => array(
790 7,
791 7
792 ),
793 'Item 1 and 2 are selected' => array(
794 3,
795 3
796 ),
797 'Value is higher than allowed (all checkboxes checked)' => array(
798 15,
799 7
800 ),
801 'Value is higher than allowed (some checkboxes checked)' => array(
802 11,
803 3
804 ),
805 'Negative value' => array(
806 -5,
807 0
808 )
809 );
810 }
811
812 /**
813 * @param string $value
814 * @param string $expectedValue
815 *
816 * @dataProvider checkValue_checkReturnsExpectedValuesDataProvider
817 * @test
818 */
819 public function checkValue_checkReturnsExpectedValues($value, $expectedValue)
820 {
821 $expectedResult = array(
822 'value' => $expectedValue
823 );
824 $result = array();
825 $tcaFieldConfiguration = array(
826 'items' => array(
827 array('Item 1', 0),
828 array('Item 2', 0),
829 array('Item 3', 0)
830 )
831 );
832 $this->assertSame($expectedResult, $this->subject->_call('checkValueForCheck', $result, $value, $tcaFieldConfiguration, '', 0, 0, ''));
833 }
834
835 /**
836 * @test
837 */
838 public function checkValueForInputConvertsNullToEmptyString()
839 {
840 $previousLanguageService = $GLOBALS['LANG'];
841 $GLOBALS['LANG'] = GeneralUtility::makeInstance(\TYPO3\CMS\Lang\LanguageService::class);
842 $GLOBALS['LANG']->init('default');
843 $expectedResult = array('value' => '');
844 $this->assertSame($expectedResult, $this->subject->_call('checkValueForInput', null, array('type' => 'string', 'max' => 40), 'tt_content', 'NEW55c0e67f8f4d32.04974534', 89, 'table_caption'));
845 $GLOBALS['LANG'] = $previousLanguageService;
846 }
847
848 /**
849 * @param mixed $value
850 * @param array $configuration
851 * @param int|string $expected
852 * @test
853 * @dataProvider referenceValuesAreCastedDataProvider
854 */
855 public function referenceValuesAreCasted($value, array $configuration, $expected)
856 {
857 $this->assertEquals(
858 $expected,
859 $this->subject->_call('castReferenceValue', $value, $configuration)
860 );
861 }
862
863 /**
864 * @return array
865 */
866 public function referenceValuesAreCastedDataProvider()
867 {
868 return array(
869 'all empty' => array(
870 '', array(), ''
871 ),
872 'cast zero with MM table' => array(
873 '', array('MM' => 'table'), 0
874 ),
875 'cast zero with MM table with default value' => array(
876 '', array('MM' => 'table', 'default' => 13), 0
877 ),
878 'cast zero with foreign field' => array(
879 '', array('foreign_field' => 'table', 'default' => 13), 0
880 ),
881 'cast zero with foreign field with default value' => array(
882 '', array('foreign_field' => 'table'), 0
883 ),
884 'pass zero' => array(
885 '0', array(), '0'
886 ),
887 'pass value' => array(
888 '1', array('default' => 13), '1'
889 ),
890 'use default value' => array(
891 '', array('default' => 13), 13
892 ),
893 );
894 }
895 }