[BUGFIX] Improve DataHandler handling for dbType fields 72/50672/2
authorNicole Cordes <typo3@cordes.co>
Mon, 1 Feb 2016 10:26:35 +0000 (11:26 +0100)
committerNicole Cordes <typo3@cordes.co>
Thu, 15 Dec 2016 20:56:41 +0000 (21:56 +0100)
Currently we have some issues with handling database fields with type
"date" or "datetime". Those fields can't have an empty default value
in the database but might have defined default values or null. This
patch adds proper handling for both default value cases.

Resolves: #72654
Resolves: #62660
Releases: master, 7.6, 6.2
Change-Id: I429bf4fdfa32531c0034e8346ee11d3d1fb81242
Reviewed-on: https://review.typo3.org/50672
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Nicole Cordes <typo3@cordes.co>
Tested-by: Nicole Cordes <typo3@cordes.co>
typo3/sysext/core/Classes/DataHandling/DataHandler.php
typo3/sysext/core/Tests/Unit/DataHandling/DataHandlerTest.php

index fa38a82..dd27330 100644 (file)
@@ -1023,7 +1023,7 @@ class DataHandler
                         if (isset($config['config']['dbType']) && ($config['config']['dbType'] === 'date' || $config['config']['dbType'] === 'datetime')) {
                             $emptyValue = $dateTimeFormats[$config['config']['dbType']]['empty'];
                             $format = $dateTimeFormats[$config['config']['dbType']]['format'];
-                            $incomingFieldArray[$column] = $incomingFieldArray[$column] ? gmdate($format, $incomingFieldArray[$column]) : $emptyValue;
+                            $incomingFieldArray[$column] = $incomingFieldArray[$column] && $incomingFieldArray[$column] !== $emptyValue ? gmdate($format, $incomingFieldArray[$column]) : $emptyValue;
                         }
                     }
                 }
@@ -1834,15 +1834,19 @@ class DataHandler
         $format = '';
         $emptyValue = '';
         if (isset($tcaFieldConf['dbType']) && ($tcaFieldConf['dbType'] === 'date' || $tcaFieldConf['dbType'] === 'datetime')) {
-            $isDateOrDateTimeField = true;
-            $dateTimeFormats = $this->databaseConnection->getDateTimeFormats($table);
-            // Convert the date/time into a timestamp for the sake of the checks
-            $emptyValue = $dateTimeFormats[$tcaFieldConf['dbType']]['empty'];
-            $format = $dateTimeFormats[$tcaFieldConf['dbType']]['format'];
-            // At this point in the processing, the timestamps are still based on UTC
-            $timeZone = new \DateTimeZone('UTC');
-            $dateTime = \DateTime::createFromFormat('!' . $format, $value, $timeZone);
-            $value = $value === $emptyValue ? 0 : $dateTime->getTimestamp();
+            if (empty($value)) {
+                $value = 0;
+            } else {
+                $isDateOrDateTimeField = true;
+                $dateTimeFormats = $this->databaseConnection->getDateTimeFormats($table);
+                // Convert the date/time into a timestamp for the sake of the checks
+                $emptyValue = $dateTimeFormats[$tcaFieldConf['dbType']]['empty'];
+                $format = $dateTimeFormats[$tcaFieldConf['dbType']]['format'];
+                // At this point in the processing, the timestamps are still based on UTC
+                $timeZone = new \DateTimeZone('UTC');
+                $dateTime = \DateTime::createFromFormat('!' . $format, $value, $timeZone);
+                $value = $value === $emptyValue ? 0 : $dateTime->getTimestamp();
+            }
         }
         // Secures the string-length to be less than max.
         if ((int)$tcaFieldConf['max'] > 0) {
index 1a2cd44..e0ec38e 100644 (file)
@@ -268,17 +268,42 @@ class DataHandlerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      * @dataProvider inputValueCheckCallsGetDateTimeFormatsForDatetimeFieldsDataProvider
      * @param string $dbType
      */
-    public function inputValueCheckCallsGetDateTimeFormatsForDatetimeFields($dbType)
+    public function inputValueCheckCallsNotGetDateTimeFormatsForDatetimeFieldsWithEmptyValue($dbType)
     {
         $tcaFieldConf = [
             'input' => [],
             'dbType' => $dbType
         ];
-        $this->mockDatabaseConnection->expects($this->once())->method('getDateTimeFormats');
+        $this->mockDatabaseConnection->expects($this->never())->method('getDateTimeFormats');
         $this->subject->_call('checkValueForInput', '', $tcaFieldConf, '', 0, 0, '');
     }
 
     /**
+     * @test
+     * @dataProvider inputValueCheckCallsGetDateTimeFormatsForDatetimeFieldsDataProvider
+     * @param string $dbType
+     */
+    public function inputValueCheckCallsGetDateTimeFormatsForDatetimeFieldsWithNonEmptyValue($dbType)
+    {
+        $dateTimeFormats = [
+            'date' => array(
+                'empty' => '0000-00-00',
+                'format' => 'Y-m-d'
+            ),
+            'datetime' => array(
+                'empty' => '0000-00-00 00:00:00',
+                'format' => 'Y-m-d H:i:s'
+            )
+        ];
+        $tcaFieldConf = array(
+            'input' => array(),
+            'dbType' => $dbType
+        );
+        $this->mockDatabaseConnection->expects($this->once())->method('getDateTimeFormats')->willReturn($dateTimeFormats);
+        $this->subject->_call('checkValueForInput', $dateTimeFormats[$dbType]['empty'], $tcaFieldConf, '', 0, 0, '');
+    }
+
+    /**
      * @return array
      */
     public function inputValueCheckDoesNotCallGetDateTimeFormatsForNonDatetimeFieldsDataProvider()