‪TYPO3CMS  10.4
DataHandlerTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Prophecy\Argument;
30 use ‪TYPO3\CMS\Core\SysLog\Error as SystemLogErrorClassification;
35 use TYPO3\TestingFramework\Core\AccessibleObjectInterface;
36 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
37 
41 class ‪DataHandlerTest extends UnitTestCase
42 {
43 
47  protected ‪$resetSingletonInstances = true;
48 
52  protected ‪$singletonInstances = [];
53 
57  protected ‪$subject;
58 
62  protected ‪$backEndUser;
63 
67  protected function ‪setUp(): void
68  {
69  parent::setUp();
70  ‪$GLOBALS['TCA'] = [];
71  $cacheManagerProphecy = $this->prophesize(CacheManager::class);
72  GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
73  $cacheFrontendProphecy = $this->prophesize(FrontendInterface::class);
74  $cacheManagerProphecy->getCache('runtime')->willReturn($cacheFrontendProphecy->reveal());
75  $this->backEndUser = $this->createMock(BackendUserAuthentication::class);
76  $this->subject = $this->getAccessibleMock(DataHandler::class, ['dummy']);
77  $this->subject->start([], '', $this->backEndUser);
78  }
79 
83  public function ‪fixtureCanBeCreated()
84  {
85  self::assertTrue($this->subject instanceof ‪DataHandler);
86  }
87 
89  // Test concerning checkModifyAccessList
91 
95  {
96  $this->subject->admin = true;
97  self::assertTrue($this->subject->checkModifyAccessList('tt_content'));
98  }
99 
104  {
105  $this->subject->admin = false;
106  self::assertFalse($this->subject->checkModifyAccessList('tt_content'));
107  }
108 
113  {
114  $this->subject->admin = false;
115  $this->backEndUser->groupData['tables_modify'] = 'tt_content';
116  self::assertTrue($this->subject->checkModifyAccessList('tt_content'));
117  }
118 
122  public function ‪adminIsAllowedToModifyAdminTable()
123  {
124  $this->subject->admin = true;
125  self::assertTrue($this->subject->checkModifyAccessList('be_users'));
126  }
127 
132  {
133  $this->subject->admin = false;
134  self::assertFalse($this->subject->checkModifyAccessList('be_users'));
135  }
136 
141  {
142  $tableName = ‪StringUtility::getUniqueId('aTable');
143  ‪$GLOBALS['TCA'] = [
144  $tableName => [
145  'ctrl' => [
146  'adminOnly' => true,
147  ],
148  ],
149  ];
150  $this->subject->admin = false;
151  $this->backEndUser->groupData['tables_modify'] = $tableName;
152  self::assertFalse($this->subject->checkModifyAccessList($tableName));
153  }
154 
158  public function ‪checkValueInputEvalWithEvalDouble2(): void
159  {
160  $testData = [
161  '-0,5' => '-0.50',
162  '1000' => '1000.00',
163  '1000,10' => '1000.10',
164  '1000,0' => '1000.00',
165  '600.000.000,00' => '600000000.00',
166  '60aaa00' => '6000.00'
167  ];
168  foreach ($testData as $value => $expectedReturnValue) {
169  $returnValue = $this->subject->checkValue_input_Eval($value, ['double2'], '');
170  self::assertSame($returnValue['value'], $expectedReturnValue);
171  }
172  }
173 
178  {
179  // Three elements: input, timezone of input, expected output (UTC)
180  return [
181  'timestamp is passed through, as it is UTC' => [
182  1457103519, 'Europe/Berlin', 1457103519
183  ],
184  'ISO date is interpreted as local date and is output as correct timestamp' => [
185  '2017-06-07T00:10:00Z', 'Europe/Berlin', 1496787000
186  ],
187  ];
188  }
189 
194  public function ‪checkValueInputEvalWithEvalDatetime($input, $serverTimezone, $expectedOutput): void
195  {
196  $oldTimezone = date_default_timezone_get();
197  date_default_timezone_set($serverTimezone);
198 
199  ‪$output = $this->subject->checkValue_input_Eval($input, ['datetime'], '');
200 
201  // set before the assertion is performed, so it is restored even for failing tests
202  date_default_timezone_set($oldTimezone);
203 
204  self::assertEquals($expectedOutput, ‪$output['value']);
205  }
206 
211  {
212  // Note the involved salted passwords are NOT mocked since the factory is static
213  ‪$subject = new ‪DataHandler();
214  $inputValue = '$1$GNu9HdMt$RwkPb28pce4nXZfnplVZY/';
215  $result = ‪$subject->‪checkValue_input_Eval($inputValue, ['saltedPassword'], '', 'be_users');
216  self::assertSame($inputValue, $result['value']);
217  }
218 
223  {
224  // Note the involved salted passwords are NOT mocked since the factory is static
225  $inputValue = 'myPassword';
226  ‪$subject = new ‪DataHandler();
227  $result = ‪$subject->‪checkValue_input_Eval($inputValue, ['saltedPassword'], '', 'be_users');
228  self::assertNotSame($inputValue, $result['value']);
229  }
230 
236  public function ‪inputValuesStringsDataProvider()
237  {
238  return [
239  '"0" returns zero as integer' => [
240  '0',
241  0
242  ],
243  '"-2000001" is interpreted correctly as -2000001 but is lower than -2000000 and set to -2000000' => [
244  '-2000001',
245  -2000000
246  ],
247  '"-2000000" is interpreted correctly as -2000000 and is equal to -2000000' => [
248  '-2000000',
249  -2000000
250  ],
251  '"2000000" is interpreted correctly as 2000000 and is equal to 2000000' => [
252  '2000000',
253  2000000
254  ],
255  '"2000001" is interpreted correctly as 2000001 but is greater then 2000000 and set to 2000000' => [
256  '2000001',
257  2000000
258  ],
259  ];
260  }
261 
268  public function ‪inputValueCheckRecognizesStringValuesAsIntegerValuesCorrectly($value, $expectedReturnValue)
269  {
270  $tcaFieldConf = [
271  'input' => [],
272  'eval' => 'int',
273  'range' => [
274  'lower' => '-2000000',
275  'upper' => '2000000'
276  ]
277  ];
278  $returnValue = $this->subject->_call('checkValueForInput', $value, $tcaFieldConf, '', 0, 0, '');
279  self::assertSame($returnValue['value'], $expectedReturnValue);
280  }
281 
287  public function ‪inputValuesRangeDoubleDataProvider()
288  {
289  return [
290  '"0" returns zero as string' => [
291  '0',
292  '0.00'
293  ],
294  '"-0.5" is interpreted correctly as -0.5 but is lower than 0 and set to 0' => [
295  '-0.5',
296  0
297  ],
298  '"0.5" is interpreted correctly as 0.5 and is equal to 0.5' => [
299  '0.5',
300  '0.50'
301  ],
302  '"39.9" is interpreted correctly as 39.9 and is equal to 39.9' => [
303  '39.9',
304  '39.90'
305  ],
306  '"42.3" is interpreted correctly as 42.3 but is greater then 42 and set to 42' => [
307  '42.3',
308  42
309  ],
310  ];
311  }
312 
319  public function ‪inputValueCheckRespectsRightLowerAndUpperLimitForDouble($value, $expectedReturnValue)
320  {
321  $tcaFieldConf = [
322  'input' => [],
323  'eval' => 'double2',
324  'range' => [
325  'lower' => '0',
326  'upper' => '42'
327  ]
328  ];
329  $returnValue = $this->subject->_call('checkValueForInput', $value, $tcaFieldConf, '', 0, 0, '');
330  self::assertSame($returnValue['value'], $expectedReturnValue);
331  }
332 
339  public function ‪inputValueCheckRespectsRightLowerAndUpperLimitWithDefaultValueForDouble($value, $expectedReturnValue)
340  {
341  $tcaFieldConf = [
342  'input' => [],
343  'eval' => 'double2',
344  'range' => [
345  'lower' => '0',
346  'upper' => '42'
347  ],
348  'default' => 0
349  ];
350  $returnValue = $this->subject->_call('checkValueForInput', $value, $tcaFieldConf, '', 0, 0, '');
351  self::assertSame($returnValue['value'], $expectedReturnValue);
352  }
353 
357  public function ‪inputValuesDataTimeDataProvider()
358  {
359  return [
360  'undershot date adjusted' => [
361  '2018-02-28T00:00:00Z',
362  1519862400,
363  ],
364  'exact lower date accepted' => [
365  '2018-03-01T00:00:00Z',
366  1519862400,
367  ],
368  'exact upper date accepted' => [
369  '2018-03-31T23:59:59Z',
370  1522540799,
371  ],
372  'exceeded date adjusted' => [
373  '2018-04-01T00:00:00Z',
374  1522540799,
375  ],
376  ];
377  }
378 
386  public function ‪inputValueCheckRecognizesDateTimeValuesAsIntegerValuesCorrectly($value, int $expected)
387  {
388  $tcaFieldConf = [
389  'input' => [],
390  'eval' => 'datetime',
391  'range' => [
392  // unix timestamp: 1519862400
393  'lower' => gmmktime(0, 0, 0, 3, 1, 2018),
394  // unix timestamp: 1522540799
395  'upper' => gmmktime(23, 59, 59, 3, 31, 2018),
396  ]
397  ];
398 
399  // @todo Switch to UTC since otherwise DataHandler removes timezone offset
400  $previousTimezone = date_default_timezone_get();
401  date_default_timezone_set('UTC');
402 
403  $returnValue = $this->subject->_call('checkValueForInput', $value, $tcaFieldConf, '', 0, 0, '');
404 
405  date_default_timezone_set($previousTimezone);
406 
407  self::assertSame($returnValue['value'], $expected);
408  }
409 
411  {
412  return [
413  'Empty string returns empty string or the number zero' => [
414  '',
415  '',
416  0
417  ],
418  'Zero returns zero as a string or the number zero' => [
419  0,
420  '0',
421  0
422  ],
423  'Zero as a string returns zero as a string or the number zero' => [
424  '0',
425  '0',
426  0
427  ]
428  ];
429  }
430 
438  public function ‪inputValueRangeCheckIsIgnoredWhenDefaultIsZeroAndInputValueIsEmpty($inputValue, $expected, $expectedEvalInt)
439  {
440  $tcaFieldConf = [
441  'type' => 'input',
442  'eval' => 'datetime',
443  'default' => 0,
444  'range' => [
445  'lower' => 1627077600
446  ]
447  ];
448 
449  $tcaFieldConfEvalInt = [
450  'type' => 'input',
451  'eval' => 'datetime,int',
452  'default' => '0',
453  'range' => [
454  'lower' => 1627077600
455  ]
456  ];
457 
458  $returnValue = $this->subject->_call('checkValueForInput', $inputValue, $tcaFieldConf, '', 0, 0, '');
459  self::assertSame($expected, $returnValue['value']);
460 
461  $returnValue = $this->subject->_call('checkValueForInput', $inputValue, $tcaFieldConfEvalInt, '', 0, 0, '');
462  self::assertSame($expectedEvalInt, $returnValue['value']);
463  }
464 
469  {
470  return [
471  'tca without dbType' => [
472  [
473  'input' => []
474  ]
475  ],
476  'tca with dbType != date/datetime/time' => [
477  [
478  'input' => [],
479  'dbType' => 'foo'
480  ]
481  ]
482  ];
483  }
484 
491  {
492  $this->subject->_call('checkValueForInput', '', $tcaFieldConf, '', 0, 0, '');
493  }
494 
499  {
500  return [
501  // Values of this kind are passed in from the inputDateTime control
502  'time from inputDateTime' => [
503  '1970-01-01T18:54:00Z',
504  'time',
505  '18:54:00',
506  ],
507  'date from inputDateTime' => [
508  '2020-11-25T00:00:00Z',
509  'date',
510  '2020-11-25',
511  ],
512  'datetime from inputDateTime' => [
513  '2020-11-25T18:54:00Z',
514  'datetime',
515  '2020-11-25 18:54:00',
516  ],
517  // Values of this kind are passed in when a data record is copied
518  'time from copying a record' => [
519  '18:54:00',
520  'time',
521  '18:54:00',
522  ],
523  'date from copying a record' => [
524  '2020-11-25',
525  'date',
526  '2020-11-25',
527  ],
528  'datetime from copying a record' => [
529  '2020-11-25 18:54:00',
530  'datetime',
531  '2020-11-25 18:54:00',
532  ],
533  ];
534  }
535 
545  public function ‪inputValueCheckDbtypeIsIndependentFromTimezone($value, $dbtype, $expectedOutput)
546  {
547  $tcaFieldConf = [
548  'input' => [],
549  'dbType' => $dbtype,
550  ];
551 
552  $oldTimezone = date_default_timezone_get();
553  date_default_timezone_set('Europe/Berlin');
554 
555  $returnValue = $this->subject->_call('checkValueForInput', $value, $tcaFieldConf, '', 0, 0, '');
556 
557  // set before the assertion is performed, so it is restored even for failing tests
558  date_default_timezone_set($oldTimezone);
559 
560  self::assertEquals($expectedOutput, $returnValue['value']);
561  }
562 
564  // Tests concerning checkModifyAccessList
566  //
572  {
573  $this->expectException(\UnexpectedValueException::class);
574  $this->expectExceptionCode(1251892472);
575 
576  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['checkModifyAccessList'][] = InvalidHookFixture::class;
577  $this->subject->checkModifyAccessList('tt_content');
578  }
579 
586  {
587  $hookClass = ‪StringUtility::getUniqueId('tx_coretest');
588  $hookMock = $this->getMockBuilder(DataHandlerCheckModifyAccessListHookInterface::class)
589  ->setMethods(['checkModifyAccessList'])
590  ->setMockClassName($hookClass)
591  ->getMock();
592  $hookMock->expects(self::once())->method('checkModifyAccessList');
593  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['checkModifyAccessList'][] = $hookClass;
594  GeneralUtility::addInstance($hookClass, $hookMock);
595  $this->subject->checkModifyAccessList('tt_content');
596  }
597 
604  {
605  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['checkModifyAccessList'][] = AllowAccessHookFixture::class;
606  self::assertTrue($this->subject->checkModifyAccessList('tt_content'));
607  }
608 
610  // Tests concerning process_datamap
612 
616  {
618  ‪$subject = $this->getMockBuilder(DataHandler::class)
619  ->setMethods(['newlog'])
620  ->getMock();
621  $this->backEndUser->workspace = 1;
622  $this->backEndUser->workspaceRec = ['freeze' => true];
624  self::assertFalse(‪$subject->‪process_datamap());
625  }
626 
631  {
632  $hookClass = ‪StringUtility::getUniqueId('tx_coretest');
633  $hookMock = $this->getMockBuilder($hookClass)
634  ->setMethods(['checkFlexFormValue_beforeMerge'])
635  ->getMock();
636  $hookMock->expects(self::once())->method('checkFlexFormValue_beforeMerge');
637  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['checkFlexFormValue'][] = $hookClass;
638  GeneralUtility::addInstance($hookClass, $hookMock);
639  $flexFormToolsProphecy = $this->prophesize(FlexFormTools::class);
640  $flexFormToolsProphecy->getDataStructureIdentifier(Argument::cetera())->willReturn('anIdentifier');
641  $flexFormToolsProphecy->parseDataStructureByIdentifier('anIdentifier')->willReturn([]);
642  GeneralUtility::addInstance(FlexFormTools::class, $flexFormToolsProphecy->reveal());
643  $this->subject->_call('checkValueForFlex', [], [], [], '', 0, '', '', 0, 0, 0, [], '');
644  }
645 
647  // Tests concerning log
649 
653  {
654  $backendUser = $this->createMock(BackendUserAuthentication::class);
655  $backendUser->expects(self::once())->method('writelog');
656  $this->subject->enableLogging = true;
657  $this->subject->BE_USER = $backendUser;
658  $this->subject->log('', 23, SystemLogGenericAction::UNDEFINED, 42, SystemLogErrorClassification::MESSAGE, 'details');
659  }
660 
665  {
666  $backendUser = $this->createMock(BackendUserAuthentication::class);
667  $backendUser->expects(self::never())->method('writelog');
668  $this->subject->enableLogging = false;
669  $this->subject->BE_USER = $backendUser;
670  $this->subject->log('', 23, SystemLogGenericAction::UNDEFINED, 42, SystemLogErrorClassification::MESSAGE, 'details');
671  }
672 
676  public function ‪logAddsEntryToLocalErrorLogArray()
677  {
678  $backendUser = $this->createMock(BackendUserAuthentication::class);
679  $this->subject->BE_USER = $backendUser;
680  $this->subject->enableLogging = true;
681  $this->subject->errorLog = [];
682  $logDetailsUnique = ‪StringUtility::getUniqueId('details');
683  $this->subject->log('', 23, SystemLogGenericAction::UNDEFINED, 42, SystemLogErrorClassification::USER_ERROR, $logDetailsUnique);
684  self::assertStringEndsWith($logDetailsUnique, $this->subject->errorLog[0]);
685  }
686 
691  {
692  $backendUser = $this->createMock(BackendUserAuthentication::class);
693  $this->subject->BE_USER = $backendUser;
694  $this->subject->enableLogging = true;
695  $this->subject->errorLog = [];
696  $logDetails = ‪StringUtility::getUniqueId('details');
697  $this->subject->log('', 23, SystemLogGenericAction::UNDEFINED, 42, SystemLogErrorClassification::USER_ERROR, '%1$s' . $logDetails . '%2$s', -1, ['foo', 'bar']);
698  $expected = 'foo' . $logDetails . 'bar';
699  self::assertStringEndsWith($expected, $this->subject->errorLog[0]);
700  }
701 
712  public function ‪equalSubmittedAndStoredValuesAreDetermined($expected, $submittedValue, $storedValue, $storedType, $allowNull)
713  {
714  $result = \Closure::bind(function () use ($submittedValue, $storedValue, $storedType, $allowNull) {
715  return $this->isSubmittedValueEqualToStoredValue($submittedValue, $storedValue, $storedType, $allowNull);
716  }, ‪$this->subject, DataHandler::class)();
717  self::assertEquals($expected, $result);
718  }
719 
724  {
725  return [
726  // String
727  'string value "" vs. ""' => [
728  true,
729  '', '', 'string', false
730  ],
731  'string value 0 vs. "0"' => [
732  true,
733  0, '0', 'string', false
734  ],
735  'string value 1 vs. "1"' => [
736  true,
737  1, '1', 'string', false
738  ],
739  'string value "0" vs. ""' => [
740  false,
741  '0', '', 'string', false
742  ],
743  'string value 0 vs. ""' => [
744  false,
745  0, '', 'string', false
746  ],
747  'string value null vs. ""' => [
748  true,
749  null, '', 'string', false
750  ],
751  // Integer
752  'integer value 0 vs. 0' => [
753  true,
754  0, 0, 'int', false
755  ],
756  'integer value "0" vs. "0"' => [
757  true,
758  '0', '0', 'int', false
759  ],
760  'integer value 0 vs. "0"' => [
761  true,
762  0, '0', 'int', false
763  ],
764  'integer value "" vs. "0"' => [
765  true,
766  '', '0', 'int', false
767  ],
768  'integer value "" vs. 0' => [
769  true,
770  '', 0, 'int', false
771  ],
772  'integer value "0" vs. 0' => [
773  true,
774  '0', 0, 'int', false
775  ],
776  'integer value 1 vs. 1' => [
777  true,
778  1, 1, 'int', false
779  ],
780  'integer value 1 vs. "1"' => [
781  true,
782  1, '1', 'int', false
783  ],
784  'integer value "1" vs. "1"' => [
785  true,
786  '1', '1', 'int', false
787  ],
788  'integer value "1" vs. 1' => [
789  true,
790  '1', 1, 'int', false
791  ],
792  'integer value "0" vs. "1"' => [
793  false,
794  '0', '1', 'int', false
795  ],
796  // String with allowed NULL values
797  'string with allowed null value "" vs. ""' => [
798  true,
799  '', '', 'string', true
800  ],
801  'string with allowed null value 0 vs. "0"' => [
802  true,
803  0, '0', 'string', true
804  ],
805  'string with allowed null value 1 vs. "1"' => [
806  true,
807  1, '1', 'string', true
808  ],
809  'string with allowed null value "0" vs. ""' => [
810  false,
811  '0', '', 'string', true
812  ],
813  'string with allowed null value 0 vs. ""' => [
814  false,
815  0, '', 'string', true
816  ],
817  'string with allowed null value null vs. ""' => [
818  false,
819  null, '', 'string', true
820  ],
821  'string with allowed null value "" vs. null' => [
822  false,
823  '', null, 'string', true
824  ],
825  'string with allowed null value null vs. null' => [
826  true,
827  null, null, 'string', true
828  ],
829  // Integer with allowed NULL values
830  'integer with allowed null value 0 vs. 0' => [
831  true,
832  0, 0, 'int', true
833  ],
834  'integer with allowed null value "0" vs. "0"' => [
835  true,
836  '0', '0', 'int', true
837  ],
838  'integer with allowed null value 0 vs. "0"' => [
839  true,
840  0, '0', 'int', true
841  ],
842  'integer with allowed null value "" vs. "0"' => [
843  true,
844  '', '0', 'int', true
845  ],
846  'integer with allowed null value "" vs. 0' => [
847  true,
848  '', 0, 'int', true
849  ],
850  'integer with allowed null value "0" vs. 0' => [
851  true,
852  '0', 0, 'int', true
853  ],
854  'integer with allowed null value 1 vs. 1' => [
855  true,
856  1, 1, 'int', true
857  ],
858  'integer with allowed null value "1" vs. "1"' => [
859  true,
860  '1', '1', 'int', true
861  ],
862  'integer with allowed null value "1" vs. 1' => [
863  true,
864  '1', 1, 'int', true
865  ],
866  'integer with allowed null value 1 vs. "1"' => [
867  true,
868  1, '1', 'int', true
869  ],
870  'integer with allowed null value "0" vs. "1"' => [
871  false,
872  '0', '1', 'int', true
873  ],
874  'integer with allowed null value null vs. ""' => [
875  false,
876  null, '', 'int', true
877  ],
878  'integer with allowed null value "" vs. null' => [
879  false,
880  '', null, 'int', true
881  ],
882  'integer with allowed null value null vs. null' => [
883  true,
884  null, null, 'int', true
885  ],
886  'integer with allowed null value null vs. "0"' => [
887  false,
888  null, '0', 'int', true
889  ],
890  'integer with allowed null value null vs. 0' => [
891  false,
892  null, 0, 'int', true
893  ],
894  'integer with allowed null value "0" vs. null' => [
895  false,
896  '0', null, 'int', true
897  ],
898  ];
899  }
900 
908  {
909  $table = 'phpunit_dummy';
910 
912  ‪$subject = $this->getAccessibleMock(
913  DataHandler::class,
914  ['dummy']
915  );
916 
917  $backendUser = $this->createMock(BackendUserAuthentication::class);
918  ‪$subject->BE_USER = $backendUser;
919  ‪$subject->BE_USER->workspace = 1;
920 
921  ‪$GLOBALS['TCA'][$table] = [];
922  ‪$GLOBALS['TCA'][$table]['ctrl'] = ['label' => 'dummy'];
923  ‪$GLOBALS['TCA'][$table]['columns'] = [
924  'dummy' => [
925  'config' => [
926  'eval' => $eval
927  ]
928  ]
929  ];
930 
931  self::assertEquals($expected, ‪$subject->_call('getPlaceholderTitleForTableLabel', $table));
932  }
933 
938  {
939  return [
940  [
941  0.10,
942  'double2'
943  ],
944  [
945  0,
946  'int'
947  ],
948  [
949  '0',
950  'datetime'
951  ],
952  [
953  '[PLACEHOLDER, WS#1]',
954  ''
955  ]
956  ];
957  }
958 
962  public function ‪deletePagesOnRootLevelIsDenied()
963  {
965  $dataHandlerMock = $this->getMockBuilder(DataHandler::class)
966  ->setMethods(['canDeletePage', 'log'])
967  ->getMock();
968  $dataHandlerMock
969  ->expects(self::never())
970  ->method('canDeletePage');
971  $dataHandlerMock
972  ->expects(self::once())
973  ->method('log')
974  ->with('pages', 0, 0, 0, 2, 'Deleting all pages starting from the root-page is disabled.', -1, [], 0);
975 
976  $dataHandlerMock->deletePages(0);
977  }
978 
983  {
984  $table = ‪StringUtility::getUniqueId('foo_');
985  $conf = [
986  'type' => 'inline',
987  'foreign_table' => ‪StringUtility::getUniqueId('foreign_foo_'),
988  'behaviour' => [
989  'enableCascadingDelete' => 0,
990  ]
991  ];
992 
994  $mockRelationHandler = $this->createMock(RelationHandler::class);
995  $mockRelationHandler->itemArray = [
996  '1' => ['table' => ‪StringUtility::getUniqueId('bar_'), 'id' => 67]
997  ];
998 
1000  $mockDataHandler = $this->getAccessibleMock(DataHandler::class, ['getInlineFieldType', 'deleteAction', 'createRelationHandlerInstance'], [], '', false);
1001  $mockDataHandler->expects(self::once())->method('getInlineFieldType')->willReturn('field');
1002  $mockDataHandler->expects(self::once())->method('createRelationHandlerInstance')->willReturn($mockRelationHandler);
1003  $mockDataHandler->expects(self::never())->method('deleteAction');
1004  $mockDataHandler->deleteRecord_procBasedOnFieldType($table, 42, 'foo', 'bar', $conf);
1005  }
1011  {
1012  return [
1013  'None item selected' => [
1014  0,
1015  0
1016  ],
1017  'All items selected' => [
1018  7,
1019  7
1020  ],
1021  'Item 1 and 2 are selected' => [
1022  3,
1023  3
1024  ],
1025  'Value is higher than allowed (all checkboxes checked)' => [
1026  15,
1027  7
1028  ],
1029  'Value is higher than allowed (some checkboxes checked)' => [
1030  11,
1031  3
1032  ],
1033  'Negative value' => [
1034  -5,
1035  0
1036  ]
1037  ];
1038  }
1039 
1047  public function ‪checkValue_checkReturnsExpectedValues($value, $expectedValue)
1048  {
1049  $expectedResult = [
1050  'value' => $expectedValue
1051  ];
1052  $result = [];
1053  $tcaFieldConfiguration = [
1054  'items' => [
1055  ['Item 1', 0],
1056  ['Item 2', 0],
1057  ['Item 3', 0]
1058  ]
1059  ];
1060  self::assertSame($expectedResult, $this->subject->_call('checkValueForCheck', $result, $value, $tcaFieldConfiguration, '', 0, 0, ''));
1061  }
1067  {
1068  $expectedResult = ['value' => ''];
1069  self::assertSame($expectedResult, $this->subject->_call('checkValueForInput', null, ['type' => 'string', 'max' => 40], 'tt_content', 'NEW55c0e67f8f4d32.04974534', 89, 'table_caption'));
1070  }
1071 
1079  public function ‪referenceValuesAreCasted($value, array $configuration, $expected)
1080  {
1081  self::assertEquals(
1082  $expected,
1083  $this->subject->_call('castReferenceValue', $value, $configuration)
1084  );
1085  }
1090  public function ‪referenceValuesAreCastedDataProvider()
1091  {
1092  return [
1093  'all empty' => [
1094  '', [], ''
1095  ],
1096  'cast zero with MM table' => [
1097  '', ['MM' => 'table'], 0
1098  ],
1099  'cast zero with MM table with default value' => [
1100  '', ['MM' => 'table', 'default' => 13], 0
1101  ],
1102  'cast zero with foreign field' => [
1103  '', ['foreign_field' => 'table', 'default' => 13], 0
1104  ],
1105  'cast zero with foreign field with default value' => [
1106  '', ['foreign_field' => 'table'], 0
1107  ],
1108  'pass zero' => [
1109  '0', [], '0'
1110  ],
1111  'pass value' => [
1112  '1', ['default' => 13], '1'
1113  ],
1114  'use default value' => [
1115  '', ['default' => 13], 13
1116  ],
1117  ];
1118  }
1123  public function ‪clearPrefixFromValueRemovesPrefixDataProvider(): array
1124  {
1125  return [
1126  'normal case' => ['Test (copy 42)', 'Test'],
1127  // all cases below look fishy and indicate bugs
1128  'with double spaces before' => ['Test (copy 42)', 'Test '],
1129  'with three spaces before' => ['Test (copy 42)', 'Test '],
1130  'with space after' => ['Test (copy 42) ', 'Test (copy 42) '],
1131  'with double spaces after' => ['Test (copy 42) ', 'Test (copy 42) '],
1132  'with three spaces after' => ['Test (copy 42) ', 'Test (copy 42) '],
1133  'with double tab before' => ['Test' . "\t" . '(copy 42)', 'Test'],
1134  'with double tab after' => ['Test (copy 42)' . "\t", 'Test (copy 42)' . "\t"],
1135  ];
1136  }
1137 
1144  public function ‪clearPrefixFromValueRemovesPrefix(string $input, string $expected)
1145  {
1146  $languageServiceProphecy = $this->prophesize(LanguageService::class);
1147  $languageServiceProphecy->sL('testLabel')->willReturn('(copy %s)');
1148  ‪$GLOBALS['LANG'] = $languageServiceProphecy->reveal();
1149  ‪$GLOBALS['TCA']['testTable']['ctrl']['prependAtCopy'] = 'testLabel';
1150  self::assertEquals($expected, (new ‪DataHandler())->clearPrefixFromValue('testTable', $input));
1151  }
1152 }
‪TYPO3\CMS\Core\DataHandling\DataHandler
Definition: DataHandler.php:84
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\inputValueCheckDoesNotCallGetDateTimeFormatsForNonDatetimeFieldsDataProvider
‪array inputValueCheckDoesNotCallGetDateTimeFormatsForNonDatetimeFieldsDataProvider()
Definition: DataHandlerTest.php:464
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\$subject
‪DataHandler PHPUnit Framework MockObject MockObject AccessibleObjectInterface $subject
Definition: DataHandlerTest.php:54
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\logFormatsDetailMessageWithAdditionalDataInLocalErrorArray
‪logFormatsDetailMessageWithAdditionalDataInLocalErrorArray()
Definition: DataHandlerTest.php:686
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\inputValueCheckRecognizesDateTimeValuesAsIntegerValuesCorrectly
‪inputValueCheckRecognizesDateTimeValuesAsIntegerValuesCorrectly($value, int $expected)
Definition: DataHandlerTest.php:382
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\doesCheckModifyAccessListHookGetsCalled
‪doesCheckModifyAccessListHookGetsCalled()
Definition: DataHandlerTest.php:581
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\nonAdminWithTableModifyAccessIsAllowedToModifyNonAdminTable
‪nonAdminWithTableModifyAccessIsAllowedToModifyNonAdminTable()
Definition: DataHandlerTest.php:108
‪TYPO3\CMS\Core\SysLog\Action
Definition: Cache.php:18
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\processDatamapForFrozenNonZeroWorkspaceReturnsFalse
‪processDatamapForFrozenNonZeroWorkspaceReturnsFalse()
Definition: DataHandlerTest.php:611
‪TYPO3\CMS\Core\Database\RelationHandler
Definition: RelationHandler.php:35
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\inputValueCheckDoesNotCallGetDateTimeFormatsForNonDatetimeFields
‪inputValueCheckDoesNotCallGetDateTimeFormatsForNonDatetimeFields($tcaFieldConf)
Definition: DataHandlerTest.php:486
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\$backEndUser
‪BackendUserAuthentication $backEndUser
Definition: DataHandlerTest.php:58
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\doesCheckModifyAccessListThrowExceptionOnWrongHookInterface
‪doesCheckModifyAccessListThrowExceptionOnWrongHookInterface()
Definition: DataHandlerTest.php:567
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\nonAdminWithTableModifyAccessIsNotAllowedToModifyAdminTable
‪nonAdminWithTableModifyAccessIsNotAllowedToModifyAdminTable()
Definition: DataHandlerTest.php:136
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\checkValueInputEvalWithSaltedPasswordReturnsHashForSaltedPassword
‪checkValueInputEvalWithSaltedPasswordReturnsHashForSaltedPassword()
Definition: DataHandlerTest.php:218
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\checkValueInputEvalWithEvalDatetimeDataProvider
‪array checkValueInputEvalWithEvalDatetimeDataProvider()
Definition: DataHandlerTest.php:173
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\logDoesNotCallWriteLogOfBackendUserIfLoggingIsDisabled
‪logDoesNotCallWriteLogOfBackendUserIfLoggingIsDisabled()
Definition: DataHandlerTest.php:660
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\getPlaceholderTitleForTableLabelReturnsLabelThatsMatchesLabelFieldConditionsDataProvider
‪array getPlaceholderTitleForTableLabelReturnsLabelThatsMatchesLabelFieldConditionsDataProvider()
Definition: DataHandlerTest.php:933
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\$singletonInstances
‪array $singletonInstances
Definition: DataHandlerTest.php:50
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\inputValueCheckRespectsRightLowerAndUpperLimitWithDefaultValueForDouble
‪inputValueCheckRespectsRightLowerAndUpperLimitWithDefaultValueForDouble($value, $expectedReturnValue)
Definition: DataHandlerTest.php:335
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\checkValueForInputConvertsNullToEmptyString
‪checkValueForInputConvertsNullToEmptyString()
Definition: DataHandlerTest.php:1062
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\checkValue_checkReturnsExpectedValues
‪checkValue_checkReturnsExpectedValues($value, $expectedValue)
Definition: DataHandlerTest.php:1043
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\Fixtures\AllowAccessHookFixture
Definition: AllowAccessHookFixture.php:25
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\doesCheckModifyAccessListHookModifyAccessAllowed
‪doesCheckModifyAccessListHookModifyAccessAllowed()
Definition: DataHandlerTest.php:599
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\fixtureCanBeCreated
‪fixtureCanBeCreated()
Definition: DataHandlerTest.php:79
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\adminIsAllowedToModifyAdminTable
‪adminIsAllowedToModifyAdminTable()
Definition: DataHandlerTest.php:118
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\referenceValuesAreCastedDataProvider
‪array referenceValuesAreCastedDataProvider()
Definition: DataHandlerTest.php:1086
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\inputValuesStringsDataProvider
‪array inputValuesStringsDataProvider()
Definition: DataHandlerTest.php:232
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\inputValuesDataTimeDataProvider
‪array inputValuesDataTimeDataProvider()
Definition: DataHandlerTest.php:353
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\checkValueInputEvalWithEvalDatetime
‪checkValueInputEvalWithEvalDatetime($input, $serverTimezone, $expectedOutput)
Definition: DataHandlerTest.php:190
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\doesCheckFlexFormValueHookGetsCalled
‪doesCheckFlexFormValueHookGetsCalled()
Definition: DataHandlerTest.php:626
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\clearPrefixFromValueRemovesPrefix
‪clearPrefixFromValueRemovesPrefix(string $input, string $expected)
Definition: DataHandlerTest.php:1140
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\nonAdminIsNorAllowedToModifyNonAdminTable
‪nonAdminIsNorAllowedToModifyNonAdminTable()
Definition: DataHandlerTest.php:99
‪TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools
Definition: FlexFormTools.php:38
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\logCallsWriteLogOfBackendUserIfLoggingIsEnabled
‪logCallsWriteLogOfBackendUserIfLoggingIsEnabled()
Definition: DataHandlerTest.php:648
‪TYPO3\CMS\Core\SysLog\Error
Definition: Error.php:24
‪TYPO3\CMS\Core\DataHandling\DataHandler\checkValue_input_Eval
‪array checkValue_input_Eval($value, $evalArray, $is_in, string $table='', $id='')
Definition: DataHandler.php:2617
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:35
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\Fixtures\InvalidHookFixture
Definition: InvalidHookFixture.php:22
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\$resetSingletonInstances
‪bool $resetSingletonInstances
Definition: DataHandlerTest.php:46
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\inputValueCheckDbtypeIsIndependentFromTimezoneDataProvider
‪inputValueCheckDbtypeIsIndependentFromTimezoneDataProvider()
Definition: DataHandlerTest.php:494
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\adminIsAllowedToModifyNonAdminTable
‪adminIsAllowedToModifyNonAdminTable()
Definition: DataHandlerTest.php:90
‪TYPO3\CMS\Core\Tests\Unit\DataHandling
Definition: DataHandlerTest.php:18
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\inputValuesRangeDoubleDataProvider
‪array inputValuesRangeDoubleDataProvider()
Definition: DataHandlerTest.php:283
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\setUp
‪setUp()
Definition: DataHandlerTest.php:63
‪$output
‪$output
Definition: annotationChecker.php:119
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:22
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\inputValueRangeCheckIsIgnoredWhenDefaultIsZeroAndInputValueIsEmptyDataProvider
‪inputValueRangeCheckIsIgnoredWhenDefaultIsZeroAndInputValueIsEmptyDataProvider()
Definition: DataHandlerTest.php:406
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\equalSubmittedAndStoredValuesAreDeterminedDataProvider
‪array equalSubmittedAndStoredValuesAreDeterminedDataProvider()
Definition: DataHandlerTest.php:719
‪TYPO3\CMS\Core\Utility\StringUtility\getUniqueId
‪static string getUniqueId($prefix='')
Definition: StringUtility.php:92
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\checkValueInputEvalWithSaltedPasswordKeepsExistingHash
‪checkValueInputEvalWithSaltedPasswordKeepsExistingHash()
Definition: DataHandlerTest.php:206
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\inputValueCheckRespectsRightLowerAndUpperLimitForDouble
‪inputValueCheckRespectsRightLowerAndUpperLimitForDouble($value, $expectedReturnValue)
Definition: DataHandlerTest.php:315
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\clearPrefixFromValueRemovesPrefixDataProvider
‪array clearPrefixFromValueRemovesPrefixDataProvider()
Definition: DataHandlerTest.php:1119
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\inputValueCheckRecognizesStringValuesAsIntegerValuesCorrectly
‪inputValueCheckRecognizesStringValuesAsIntegerValuesCorrectly($value, $expectedReturnValue)
Definition: DataHandlerTest.php:264
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\equalSubmittedAndStoredValuesAreDetermined
‪equalSubmittedAndStoredValuesAreDetermined($expected, $submittedValue, $storedValue, $storedType, $allowNull)
Definition: DataHandlerTest.php:708
‪TYPO3\CMS\Core\DataHandling\DataHandlerCheckModifyAccessListHookInterface
Definition: DataHandlerCheckModifyAccessListHookInterface.php:22
‪TYPO3\CMS\Core\DataHandling\DataHandler\process_datamap
‪bool void process_datamap()
Definition: DataHandler.php:833
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\getPlaceholderTitleForTableLabelReturnsLabelThatsMatchesLabelFieldConditions
‪getPlaceholderTitleForTableLabelReturnsLabelThatsMatchesLabelFieldConditions($expected, $eval)
Definition: DataHandlerTest.php:903
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\logAddsEntryToLocalErrorLogArray
‪logAddsEntryToLocalErrorLogArray()
Definition: DataHandlerTest.php:672
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:22
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\nonAdminIsNotAllowedToModifyAdminTable
‪nonAdminIsNotAllowedToModifyAdminTable()
Definition: DataHandlerTest.php:127
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\referenceValuesAreCasted
‪referenceValuesAreCasted($value, array $configuration, $expected)
Definition: DataHandlerTest.php:1075
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\checkValueInputEvalWithEvalDouble2
‪checkValueInputEvalWithEvalDouble2()
Definition: DataHandlerTest.php:154
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\inputValueCheckDbtypeIsIndependentFromTimezone
‪inputValueCheckDbtypeIsIndependentFromTimezone($value, $dbtype, $expectedOutput)
Definition: DataHandlerTest.php:541
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\inputValueRangeCheckIsIgnoredWhenDefaultIsZeroAndInputValueIsEmpty
‪inputValueRangeCheckIsIgnoredWhenDefaultIsZeroAndInputValueIsEmpty($inputValue, $expected, $expectedEvalInt)
Definition: DataHandlerTest.php:434
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest
Definition: DataHandlerTest.php:42
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\deleteRecord_procBasedOnFieldTypeRespectsEnableCascadingDelete
‪deleteRecord_procBasedOnFieldTypeRespectsEnableCascadingDelete()
Definition: DataHandlerTest.php:978
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\deletePagesOnRootLevelIsDenied
‪deletePagesOnRootLevelIsDenied()
Definition: DataHandlerTest.php:958
‪TYPO3\CMS\Core\Tests\Unit\DataHandling\DataHandlerTest\checkValue_checkReturnsExpectedValuesDataProvider
‪array checkValue_checkReturnsExpectedValuesDataProvider()
Definition: DataHandlerTest.php:1006