[BUGFIX] Improve DataHandler handling for dbType fields 26/46426/3
authorNicole Cordes <typo3@cordes.co>
Mon, 1 Feb 2016 10:26:35 +0000 (11:26 +0100)
committerAndreas Wolf <andreas.wolf@typo3.org>
Sat, 5 Mar 2016 13:36:45 +0000 (14:36 +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/46426
Reviewed-by: Benni Mack <benni@typo3.org>
Reviewed-by: Mathias Schreiber <mathias.schreiber@wmdb.de>
Tested-by: Mathias Schreiber <mathias.schreiber@wmdb.de>
Reviewed-by: Andreas Wolf <andreas.wolf@typo3.org>
Tested-by: Andreas Wolf <andreas.wolf@typo3.org>
typo3/sysext/core/Classes/DataHandling/DataHandler.php
typo3/sysext/core/Tests/Unit/DataHandling/DataHandlerTest.php

index 0824d4f..56b8ef0 100644 (file)
@@ -994,7 +994,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;
                         }
                     }
                 }
@@ -1752,15 +1752,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 e675289..725ad8a 100644 (file)
@@ -230,17 +230,42 @@ class DataHandlerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
      * @dataProvider inputValueCheckCallsGetDateTimeFormatsForDatetimeFieldsDataProvider
      * @param string $dbType
      */
-    public function inputValueCheckCallsGetDateTimeFormatsForDatetimeFields($dbType)
+    public function inputValueCheckCallsNotGetDateTimeFormatsForDatetimeFieldsWithEmptyValue($dbType)
     {
         $tcaFieldConf = array(
             'input' => array(),
             '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()