TYPO3 CMS  TYPO3_7-6
DataHandlerTest.php
Go to the documentation of this file.
1 <?php
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 
24 
29 {
33  protected $singletonInstances = [];
34 
38  protected $subject;
39 
43  protected $backEndUser;
44 
49 
53  protected function setUp()
54  {
55  $GLOBALS['TCA'] = [];
56  $this->singletonInstances = GeneralUtility::getSingletonInstances();
57  $this->backEndUser = $this->getMock(BackendUserAuthentication::class);
58  $this->mockDatabaseConnection = $this->getMock(DatabaseConnection::class, [], [], '', false);
60  $this->subject = $this->getAccessibleMock(DataHandler::class, ['dummy']);
61  $this->subject->start([], '', $this->backEndUser);
62  }
63 
67  protected function tearDown()
68  {
69  GeneralUtility::resetSingletonInstances($this->singletonInstances);
70  parent::tearDown();
71  }
72 
74  // Tests for the basic functionality
76 
79  public function fixtureCanBeCreated()
80  {
81  $this->assertTrue($this->subject instanceof DataHandler);
82  }
83 
85  // Test concerning checkModifyAccessList
87 
91  {
92  $this->subject->admin = true;
93  $this->assertTrue($this->subject->checkModifyAccessList('tt_content'));
94  }
95 
100  {
101  $this->subject->admin = false;
102  $this->assertFalse($this->subject->checkModifyAccessList('tt_content'));
103  }
104 
109  {
110  $this->subject->admin = false;
111  $this->backEndUser->groupData['tables_modify'] = 'tt_content';
112  $this->assertTrue($this->subject->checkModifyAccessList('tt_content'));
113  }
114 
119  {
120  $this->subject->admin = true;
121  $this->assertTrue($this->subject->checkModifyAccessList('be_users'));
122  }
123 
128  {
129  $this->subject->admin = false;
130  $this->assertFalse($this->subject->checkModifyAccessList('be_users'));
131  }
132 
137  {
138  $tableName = $this->getUniqueId('aTable');
139  $GLOBALS['TCA'] = [
140  $tableName => [
141  'ctrl' => [
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 
154  public function evalCheckValueDouble2()
155  {
156  $testData = [
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, ['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 
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 
214  {
215  return [
216  '"0" returns zero as integer' => [
217  '0',
218  0
219  ],
220  '"-1999999" is interpreted correctly as -1999999 and is lot lower than -200000' => [
221  '-1999999',
222  -1999999
223  ],
224  '"3000000" is interpreted correctly as 3000000 but is higher then 200000 and set to 200000' => [
225  '3000000',
226  2000000
227  ],
228  ];
229  }
230 
237  public function inputValueCheckRecognizesStringValuesAsIntegerValuesCorrectly($value, $expectedReturnValue)
238  {
239  $tcaFieldConf = [
240  'input' => [],
241  'eval' => 'int',
242  'range' => [
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 
255  {
256  return [
257  'dbType = date' => [
258  'date'
259  ],
260  'dbType = datetime' => [
261  'datetime'
262  ]
263  ];
264  }
265 
272  {
273  $tcaFieldConf = [
274  'input' => [],
275  'dbType' => $dbType
276  ];
277  $this->mockDatabaseConnection->expects($this->never())->method('getDateTimeFormats');
278  $this->subject->_call('checkValueForInput', '', $tcaFieldConf, '', 0, 0, '');
279  }
280 
287  {
288  $dateTimeFormats = [
289  'date' => [
290  'empty' => '0000-00-00',
291  'format' => 'Y-m-d'
292  ],
293  'datetime' => [
294  'empty' => '0000-00-00 00:00:00',
295  'format' => 'Y-m-d H:i:s'
296  ]
297  ];
298  $tcaFieldConf = [
299  'input' => [],
300  'dbType' => $dbType
301  ];
302  $this->mockDatabaseConnection->expects($this->once())->method('getDateTimeFormats')->willReturn($dateTimeFormats);
303  $this->subject->_call('checkValueForInput', $dateTimeFormats[$dbType]['empty'], $tcaFieldConf, '', 0, 0, '');
304  }
305 
310  {
311  return [
312  'tca without dbType' => [
313  [
314  'input' => []
315  ]
316  ],
317  'tca with dbType != date/datetime' => [
318  [
319  'input' => [],
320  'dbType' => 'foo'
321  ]
322  ]
323  ];
324  }
325 
332  {
333  $this->mockDatabaseConnection->expects($this->never())->method('getDateTimeFormats');
334  $this->subject->_call('checkValueForInput', '', $tcaFieldConf, '', 0, 0, '');
335  }
336 
338  // Tests concerning checkModifyAccessList
340  //
348  {
349  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['checkModifyAccessList'][] = InvalidHookFixture::class;
350  $this->subject->checkModifyAccessList('tt_content');
351  }
352 
359  {
360  $hookClass = $this->getUniqueId('tx_coretest');
361  $hookMock = $this->getMock(\TYPO3\CMS\Core\DataHandling\DataHandlerCheckModifyAccessListHookInterface::class, ['checkModifyAccessList'], [], $hookClass);
362  $hookMock->expects($this->once())->method('checkModifyAccessList');
363  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['checkModifyAccessList'][] = $hookClass;
364  $GLOBALS['T3_VAR']['getUserObj'][$hookClass] = $hookMock;
365  $this->subject->checkModifyAccessList('tt_content');
366  }
367 
374  {
375  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['checkModifyAccessList'][] = AllowAccessHookFixture::class;
376  $this->assertTrue($this->subject->checkModifyAccessList('tt_content'));
377  }
378 
380  // Tests concerning process_datamap
382 
385  public function processDatamapForFrozenNonZeroWorkspaceReturnsFalse()
386  {
388  $subject = $this->getMock(DataHandler::class, ['newlog']);
389  $this->backEndUser->workspace = 1;
390  $this->backEndUser->workspaceRec = ['freeze' => true];
391  $subject->BE_USER = $this->backEndUser;
392  $this->assertFalse($subject->process_datamap());
393  }
394 
398  public function processDatamapWhenEditingRecordInWorkspaceCreatesNewRecordInWorkspace()
399  {
400  // Unset possible hooks on method under test
401  // @TODO: Can be removed if unit test boostrap is fixed to not load LocalConfiguration anymore
402  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'] = [];
403 
404  $GLOBALS['TCA'] = [
405  'pages' => [
406  'columns' => [],
407  ],
408  ];
409 
411  $subject = $this->getMock(
412  DataHandler::class,
413  ['newlog', 'checkModifyAccessList', 'tableReadOnly', 'checkRecordUpdateAccess']
414  );
415 
416  $subject->bypassWorkspaceRestrictions = false;
417  $subject->datamap = [
418  'pages' => [
419  '1' => [
420  'header' => 'demo'
421  ]
422  ]
423  ];
424  $subject->expects($this->once())->method('checkModifyAccessList')->with('pages')->will($this->returnValue(true));
425  $subject->expects($this->once())->method('tableReadOnly')->with('pages')->will($this->returnValue(false));
426  $subject->expects($this->once())->method('checkRecordUpdateAccess')->will($this->returnValue(true));
427 
429  $backEndUser = $this->getMock(BackendUserAuthentication::class);
430  $backEndUser->workspace = 1;
431  $backEndUser->workspaceRec = ['freeze' => false];
432  $backEndUser->expects($this->once())->method('workspaceAllowAutoCreation')->will($this->returnValue(true));
433  $backEndUser->expects($this->once())->method('workspaceCannotEditRecord')->will($this->returnValue(true));
434  $backEndUser->expects($this->once())->method('recordEditAccessInternals')->with('pages', 1)->will($this->returnValue(true));
435  $subject->BE_USER = $backEndUser;
436  $createdTceMain = $this->getMock(DataHandler::class, []);
437  $createdTceMain->expects($this->once())->method('start')->with([], [
438  'pages' => [
439  1 => [
440  'version' => [
441  'action' => 'new',
442  'treeLevels' => -1,
443  'label' => 'Auto-created for WS #1'
444  ]
445  ]
446  ]
447  ]);
448  $createdTceMain->expects($this->never())->method('process_datamap');
449  $createdTceMain->expects($this->once())->method('process_cmdmap');
450  GeneralUtility::addInstance(DataHandler::class, $createdTceMain);
451  $subject->process_datamap();
452  }
453 
458  {
459  $hookClass = $this->getUniqueId('tx_coretest');
460  $hookMock = $this->getMock($hookClass, ['checkFlexFormValue_beforeMerge']);
461  $hookMock->expects($this->once())->method('checkFlexFormValue_beforeMerge');
462  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['checkFlexFormValue'][] = $hookClass;
463  $GLOBALS['T3_VAR']['getUserObj'][$hookClass] = $hookMock;
464  $this->subject->_call('checkValueForFlex', [], [], [], '', 0, '', '', 0, 0, 0, [], '');
465  }
466 
468  // Tests concerning log
470 
474  {
475  $backendUser = $this->getMock(BackendUserAuthentication::class);
476  $backendUser->expects($this->once())->method('writelog');
477  $this->subject->enableLogging = true;
478  $this->subject->BE_USER = $backendUser;
479  $this->subject->log('', 23, 0, 42, 0, 'details');
480  }
481 
486  {
487  $backendUser = $this->getMock(BackendUserAuthentication::class);
488  $backendUser->expects($this->never())->method('writelog');
489  $this->subject->enableLogging = false;
490  $this->subject->BE_USER = $backendUser;
491  $this->subject->log('', 23, 0, 42, 0, 'details');
492  }
493 
498  {
499  $backendUser = $this->getMock(BackendUserAuthentication::class);
500  $this->subject->BE_USER = $backendUser;
501  $this->subject->enableLogging = true;
502  $this->subject->errorLog = [];
503  $logDetailsUnique = $this->getUniqueId('details');
504  $this->subject->log('', 23, 0, 42, 1, $logDetailsUnique);
505  $this->assertStringEndsWith($logDetailsUnique, $this->subject->errorLog[0]);
506  }
507 
512  {
513  $backendUser = $this->getMock(BackendUserAuthentication::class);
514  $this->subject->BE_USER = $backendUser;
515  $this->subject->enableLogging = true;
516  $this->subject->errorLog = [];
517  $logDetails = $this->getUniqueId('details');
518  $this->subject->log('', 23, 0, 42, 1, '%1$s' . $logDetails . '%2$s', -1, ['foo', 'bar']);
519  $expected = 'foo' . $logDetails . 'bar';
520  $this->assertStringEndsWith($expected, $this->subject->errorLog[0]);
521  }
522 
533  public function equalSubmittedAndStoredValuesAreDetermined($expected, $submittedValue, $storedValue, $storedType, $allowNull)
534  {
535  $result = $this->callInaccessibleMethod(
536  $this->subject,
537  'isSubmittedValueEqualToStoredValue',
538  $submittedValue, $storedValue, $storedType, $allowNull
539  );
540  $this->assertEquals($expected, $result);
541  }
542 
547  {
548  return [
549  // String
550  'string value "" vs. ""' => [
551  true,
552  '', '', 'string', false
553  ],
554  'string value 0 vs. "0"' => [
555  true,
556  0, '0', 'string', false
557  ],
558  'string value 1 vs. "1"' => [
559  true,
560  1, '1', 'string', false
561  ],
562  'string value "0" vs. ""' => [
563  false,
564  '0', '', 'string', false
565  ],
566  'string value 0 vs. ""' => [
567  false,
568  0, '', 'string', false
569  ],
570  'string value null vs. ""' => [
571  true,
572  null, '', 'string', false
573  ],
574  // Integer
575  'integer value 0 vs. 0' => [
576  true,
577  0, 0, 'int', false
578  ],
579  'integer value "0" vs. "0"' => [
580  true,
581  '0', '0', 'int', false
582  ],
583  'integer value 0 vs. "0"' => [
584  true,
585  0, '0', 'int', false
586  ],
587  'integer value "" vs. "0"' => [
588  true,
589  '', '0', 'int', false
590  ],
591  'integer value "" vs. 0' => [
592  true,
593  '', 0, 'int', false
594  ],
595  'integer value "0" vs. 0' => [
596  true,
597  '0', 0, 'int', false
598  ],
599  'integer value 1 vs. 1' => [
600  true,
601  1, 1, 'int', false
602  ],
603  'integer value 1 vs. "1"' => [
604  true,
605  1, '1', 'int', false
606  ],
607  'integer value "1" vs. "1"' => [
608  true,
609  '1', '1', 'int', false
610  ],
611  'integer value "1" vs. 1' => [
612  true,
613  '1', 1, 'int', false
614  ],
615  'integer value "0" vs. "1"' => [
616  false,
617  '0', '1', 'int', false
618  ],
619  // String with allowed NULL values
620  'string with allowed null value "" vs. ""' => [
621  true,
622  '', '', 'string', true
623  ],
624  'string with allowed null value 0 vs. "0"' => [
625  true,
626  0, '0', 'string', true
627  ],
628  'string with allowed null value 1 vs. "1"' => [
629  true,
630  1, '1', 'string', true
631  ],
632  'string with allowed null value "0" vs. ""' => [
633  false,
634  '0', '', 'string', true
635  ],
636  'string with allowed null value 0 vs. ""' => [
637  false,
638  0, '', 'string', true
639  ],
640  'string with allowed null value null vs. ""' => [
641  false,
642  null, '', 'string', true
643  ],
644  'string with allowed null value "" vs. null' => [
645  false,
646  '', null, 'string', true
647  ],
648  'string with allowed null value null vs. null' => [
649  true,
650  null, null, 'string', true
651  ],
652  // Integer with allowed NULL values
653  'integer with allowed null value 0 vs. 0' => [
654  true,
655  0, 0, 'int', true
656  ],
657  'integer with allowed null value "0" vs. "0"' => [
658  true,
659  '0', '0', 'int', true
660  ],
661  'integer with allowed null value 0 vs. "0"' => [
662  true,
663  0, '0', 'int', true
664  ],
665  'integer with allowed null value "" vs. "0"' => [
666  true,
667  '', '0', 'int', true
668  ],
669  'integer with allowed null value "" vs. 0' => [
670  true,
671  '', 0, 'int', true
672  ],
673  'integer with allowed null value "0" vs. 0' => [
674  true,
675  '0', 0, 'int', true
676  ],
677  'integer with allowed null value 1 vs. 1' => [
678  true,
679  1, 1, 'int', true
680  ],
681  'integer with allowed null value "1" vs. "1"' => [
682  true,
683  '1', '1', 'int', true
684  ],
685  'integer with allowed null value "1" vs. 1' => [
686  true,
687  '1', 1, 'int', true
688  ],
689  'integer with allowed null value 1 vs. "1"' => [
690  true,
691  1, '1', 'int', true
692  ],
693  'integer with allowed null value "0" vs. "1"' => [
694  false,
695  '0', '1', 'int', true
696  ],
697  'integer with allowed null value null vs. ""' => [
698  false,
699  null, '', 'int', true
700  ],
701  'integer with allowed null value "" vs. null' => [
702  false,
703  '', null, 'int', true
704  ],
705  'integer with allowed null value null vs. null' => [
706  true,
707  null, null, 'int', true
708  ],
709  'integer with allowed null value null vs. "0"' => [
710  false,
711  null, '0', 'int', true
712  ],
713  'integer with allowed null value null vs. 0' => [
714  false,
715  null, 0, 'int', true
716  ],
717  'integer with allowed null value "0" vs. null' => [
718  false,
719  '0', null, 'int', true
720  ],
721  ];
722  }
723 
730  public function getPlaceholderTitleForTableLabelReturnsLabelThatsMatchesLabelFieldConditions($expected, $eval)
731  {
732  $table = 'phpunit_dummy';
733 
735  $subject = $this->getAccessibleMock(
736  DataHandler::class,
737  ['dummy']
738  );
739 
740  $backendUser = $this->getMock(BackendUserAuthentication::class);
741  $subject->BE_USER = $backendUser;
742  $subject->BE_USER->workspace = 1;
743 
744  $GLOBALS['TCA'][$table] = [];
745  $GLOBALS['TCA'][$table]['ctrl'] = ['label' => 'dummy'];
746  $GLOBALS['TCA'][$table]['columns'] = [
747  'dummy' => [
748  'config' => [
749  'eval' => $eval
750  ]
751  ]
752  ];
753 
754  $this->assertEquals($expected, $subject->_call('getPlaceholderTitleForTableLabel', $table));
755  }
756 
761  {
762  return [
763  [
764  0.10,
765  'double2'
766  ],
767  [
768  0,
769  'int'
770  ],
771  [
772  '0',
773  'datetime'
774  ],
775  [
776  '[PLACEHOLDER, WS#1]',
777  ''
778  ]
779  ];
780  }
781 
785  public function deletePagesOnRootLevelIsDenied()
786  {
788  $dataHandlerMock = $this->getMock(DataHandler::class, ['canDeletePage', 'newlog2']);
789  $dataHandlerMock
790  ->expects($this->never())
791  ->method('canDeletePage');
792  $dataHandlerMock
793  ->expects($this->once())
794  ->method('newlog2')
795  ->with('Deleting all pages starting from the root-page is disabled.', 'pages', 0, 0, 2);
796 
797  $dataHandlerMock->deletePages(0);
798  }
799 
803  public function deleteRecord_procBasedOnFieldTypeRespectsEnableCascadingDelete()
804  {
805  $table = $this->getUniqueId('foo_');
806  $conf = [
807  'type' => 'inline',
808  'foreign_table' => $this->getUniqueId('foreign_foo_'),
809  'behaviour' => [
810  'enableCascadingDelete' => 0,
811  ]
812  ];
813 
815  $mockRelationHandler = $this->getMock(\TYPO3\CMS\Core\Database\RelationHandler::class, [], [], '', false);
816  $mockRelationHandler->itemArray = [
817  '1' => ['table' => $this->getUniqueId('bar_'), 'id' => 67]
818  ];
819 
821  $mockDataHandler = $this->getAccessibleMock(DataHandler::class, ['getInlineFieldType', 'deleteAction', 'createRelationHandlerInstance'], [], '', false);
822  $mockDataHandler->expects($this->once())->method('getInlineFieldType')->will($this->returnValue('field'));
823  $mockDataHandler->expects($this->once())->method('createRelationHandlerInstance')->will($this->returnValue($mockRelationHandler));
824  $mockDataHandler->expects($this->never())->method('deleteAction');
825  $mockDataHandler->deleteRecord_procBasedOnFieldType($table, 42, 'foo', 'bar', $conf);
826  }
827 
832  {
833  return [
834  'None item selected' => [
835  0,
836  0
837  ],
838  'All items selected' => [
839  7,
840  7
841  ],
842  'Item 1 and 2 are selected' => [
843  3,
844  3
845  ],
846  'Value is higher than allowed (all checkboxes checked)' => [
847  15,
848  7
849  ],
850  'Value is higher than allowed (some checkboxes checked)' => [
851  11,
852  3
853  ],
854  'Negative value' => [
855  -5,
856  0
857  ]
858  ];
859  }
860 
868  public function checkValue_checkReturnsExpectedValues($value, $expectedValue)
869  {
870  $expectedResult = [
871  'value' => $expectedValue
872  ];
873  $result = [];
874  $tcaFieldConfiguration = [
875  'items' => [
876  ['Item 1', 0],
877  ['Item 2', 0],
878  ['Item 3', 0]
879  ]
880  ];
881  $this->assertSame($expectedResult, $this->subject->_call('checkValueForCheck', $result, $value, $tcaFieldConfiguration, '', 0, 0, ''));
882  }
883 
888  {
889  $previousLanguageService = $GLOBALS['LANG'];
890  $GLOBALS['LANG'] = GeneralUtility::makeInstance(\TYPO3\CMS\Lang\LanguageService::class);
891  $GLOBALS['LANG']->init('default');
892  $expectedResult = ['value' => ''];
893  $this->assertSame($expectedResult, $this->subject->_call('checkValueForInput', null, ['type' => 'string', 'max' => 40], 'tt_content', 'NEW55c0e67f8f4d32.04974534', 89, 'table_caption'));
894  $GLOBALS['LANG'] = $previousLanguageService;
895  }
896 
904  public function referenceValuesAreCasted($value, array $configuration, $expected)
905  {
906  $this->assertEquals(
907  $expected,
908  $this->subject->_call('castReferenceValue', $value, $configuration)
909  );
910  }
911 
916  {
917  return [
918  'all empty' => [
919  '', [], ''
920  ],
921  'cast zero with MM table' => [
922  '', ['MM' => 'table'], 0
923  ],
924  'cast zero with MM table with default value' => [
925  '', ['MM' => 'table', 'default' => 13], 0
926  ],
927  'cast zero with foreign field' => [
928  '', ['foreign_field' => 'table', 'default' => 13], 0
929  ],
930  'cast zero with foreign field with default value' => [
931  '', ['foreign_field' => 'table'], 0
932  ],
933  'pass zero' => [
934  '0', [], '0'
935  ],
936  'pass value' => [
937  '1', ['default' => 13], '1'
938  ],
939  'use default value' => [
940  '', ['default' => 13], 13
941  ],
942  ];
943  }
944 }
static addInstance($className, $instance)
equalSubmittedAndStoredValuesAreDetermined($expected, $submittedValue, $storedValue, $storedType, $allowNull)
static resetSingletonInstances(array $newSingletonInstances)
inputValueCheckRecognizesStringValuesAsIntegerValuesCorrectly($value, $expectedReturnValue)
referenceValuesAreCasted($value, array $configuration, $expected)
getAccessibleMock( $originalClassName, $methods=[], array $arguments=[], $mockClassName='', $callOriginalConstructor=true, $callOriginalClone=true, $callAutoload=true)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
evalCheckValueDatetime($input, $serverTimezone, $expectedOutput)