[BUGFIX] Convert date objects to string in SaveToDatabase finisher 05/57205/6
authorRalf Zimmermann <ralf.zimmermann@tritum.de>
Tue, 12 Jun 2018 16:57:56 +0000 (18:57 +0200)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Fri, 6 Jul 2018 17:41:30 +0000 (19:41 +0200)
The SaveToDatabase now converts DateTime(Immutable) objects to strings
to make it possible to save values from "Date" or "DatePicker" form elements
into the database.

Resolves: #85246
Releases: master, 8.7
Change-Id: I1533252d462d08bf7b743884d4e8e5fab12f6423
Reviewed-on: https://review.typo3.org/57205
Reviewed-by: Björn Jacob <bjoern.jacob@tritum.de>
Tested-by: Björn Jacob <bjoern.jacob@tritum.de>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Mathias Brodala <mbrodala@pagemachine.de>
Reviewed-by: Lidia Demin <typecat@gmx.net>
Reviewed-by: Riny van Tiggelen <info@online-gamer.nl>
Tested-by: Mona Muzaffar <mona.muzaffar@gmx.de>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
typo3/sysext/form/Classes/Domain/Finishers/SaveToDatabaseFinisher.php
typo3/sysext/form/Documentation/ApiReference/Index.rst
typo3/sysext/form/Documentation/Config/proto/finishersDefinition/finishers/SaveToDatabase.rst
typo3/sysext/form/Tests/Unit/Domain/Finishers/SaveToDatabaseFinisherTest.php

index f37b9d4..1e88a41 100644 (file)
@@ -250,7 +250,11 @@ class SaveToDatabaseFinisher extends AbstractFinisher
                 }
             } elseif (is_array($elementValue)) {
                 $elementValue = implode(',', $elementValue);
+            } elseif ($elementValue instanceof \DateTimeInterface) {
+                $format = $elementsConfiguration[$elementIdentifier]['dateFormat'] ?? 'U';
+                $elementValue = $elementValue->format($format);
             }
+
             $databaseData[$elementsConfiguration[$elementIdentifier]['mapOnDatabaseColumn']] = $elementValue;
         }
         return $databaseData;
index 9454450..e48d207 100644 (file)
@@ -2767,6 +2767,28 @@ elements.<formElementIdentifier>.saveFileIdentifierInsteadOfUid
       FAL identifier (1:/user_uploads/some_uploaded_pic.jpg) instead.
 
 
+.. _apireference-finisheroptions-savetodatabasefinisher-options-elements-<formelementidentifier>-dateformat:
+
+elements.<formElementIdentifier>.dateFormat
++++++++++++++++++++++++++++++++++++++++++++
+
+:aspect:`Data type`
+      string
+
+:aspect:`Mandatory`
+      No
+
+:aspect:`Default value`
+      'U'
+
+:aspect:`Description`
+      If the internal datatype is :php:`\DateTime` which is true for the form element types
+      :yaml:`DatePicker` and :yaml:`Date`, the object needs to be converted into a string value.
+      This option allows you to define the format of the date in case of such a conversion.
+      You can use every format accepted by the PHP :php:`date()` function (http://php.net/manual/en/function.date.php#refsect1-function.date-parameters).
+      The default value is "U" which leads to a Unix timestamp.
+
+
 .. _apireference-finisheroptions-savetodatabasefinisher-options-databasecolumnmappings:
 
 databaseColumnMappings
index d7a8000..3156ecb 100644 (file)
@@ -192,13 +192,13 @@ options.elements.<formElementIdentifier>.mapOnDatabaseColumn
       The value from the submitted form element with the identifier ``<formElementIdentifier>`` will be written into this database column.
 
 
-.. _typo3.cms.form.prototypes.<prototypeIdentifier>.finishersdefinition.savetodatabase.options.elements.<formelementidentifier>.mapondatabasecolumn.savefileidentifierinsteadofuid:
+.. _typo3.cms.form.prototypes.<prototypeIdentifier>.finishersdefinition.savetodatabase.options.elements.<formelementidentifier>.savefileidentifierinsteadofuid:
 
-options.elements.<formElementIdentifier>.mapOnDatabaseColumn.saveFileIdentifierInsteadOfUid
+options.elements.<formElementIdentifier>.saveFileIdentifierInsteadOfUid
 -------------------------------------------------------------------------------------------
 
 :aspect:`Option path`
-      TYPO3.CMS.Form.prototypes.<prototypeIdentifier>.finishersDefinition.SaveToDatabase.options.elements.<formElementIdentifier>.mapOnDatabaseColumn.saveFileIdentifierInsteadOfUid
+      TYPO3.CMS.Form.prototypes.<prototypeIdentifier>.finishersDefinition.SaveToDatabase.options.elements.<formElementIdentifier>.saveFileIdentifierInsteadOfUid
 
 :aspect:`Data type`
       bool
@@ -225,13 +225,13 @@ options.elements.<formElementIdentifier>.mapOnDatabaseColumn.saveFileIdentifierI
       FAL identifier (1:/user_uploads/some_uploaded_pic.jpg) instead.
 
 
-.. _typo3.cms.form.prototypes.<prototypeIdentifier>.finishersdefinition.savetodatabase.options.elements.<formelementidentifier>.mapondatabasecolumn.skipifvalueisempty:
+.. _typo3.cms.form.prototypes.<prototypeIdentifier>.finishersdefinition.savetodatabase.options.elements.<formelementidentifier>.skipifvalueisempty:
 
-options.elements.<formElementIdentifier>.mapOnDatabaseColumn.skipIfValueIsEmpty
+options.elements.<formElementIdentifier>.skipIfValueIsEmpty
 -------------------------------------------------------------------------------
 
 :aspect:`Option path`
-      TYPO3.CMS.Form.prototypes.<prototypeIdentifier>.finishersDefinition.SaveToDatabase.options.elements.<formElementIdentifier>.mapOnDatabaseColumn.skipIfValueIsEmpty
+      TYPO3.CMS.Form.prototypes.<prototypeIdentifier>.finishersDefinition.SaveToDatabase.options.elements.<formElementIdentifier>.skipIfValueIsEmpty
 
 :aspect:`Data type`
       bool
@@ -255,6 +255,38 @@ options.elements.<formElementIdentifier>.mapOnDatabaseColumn.skipIfValueIsEmpty
       is valid content.
 
 
+.. _typo3.cms.form.prototypes.<prototypeIdentifier>.finishersdefinition.savetodatabase.options.elements.<formelementidentifier>.dateformat:
+
+options.elements.<formElementIdentifier>.dateFormat
+---------------------------------------------------
+
+:aspect:`Option path`
+      TYPO3.CMS.Form.prototypes.<prototypeIdentifier>.finishersDefinition.SaveToDatabase.options.elements.<formElementIdentifier>.dateFormat
+
+:aspect:`Data type`
+      string
+
+:aspect:`Needed by`
+      Frontend
+
+:aspect:`Mandatory`
+      No
+
+:aspect:`Default value`
+      'U'
+
+:aspect:`Good to know`
+      - :ref:`"SaveToDatabase finisher"<apireference-finisheroptions-savetodatabasefinisher>`
+      - :ref:`"Accessing form runtime values"<concepts-frontendrendering-codecomponents-customfinisherimplementations-accessingoptions-formruntimeaccessor>`
+
+:aspect:`Description`
+      If the internal Datatype is \DateTime which is true for the form element types "DatePicker" and "Date",
+      the object needs to be converted into a string value.
+      This option allows you to define the format of the date.
+      You can use every format accepted by PHP's date() function (http://php.net/manual/en/function.date.php#refsect1-function.date-parameters).
+      The default value is "U" which means a Unix timestamp.
+
+
 .. _typo3.cms.form.prototypes.<prototypeIdentifier>.finishersdefinition.savetodatabase.options.databasecolumnmappings:
 
 options.databaseColumnMappings
index b61c46d..c81d48e 100644 (file)
@@ -174,4 +174,48 @@ class SaveToDatabaseFinisherTest extends \TYPO3\TestingFramework\Core\Unit\UnitT
 
         $saveToDatabaseFinisher->execute($this->prophesize(FinisherContext::class)->reveal());
     }
+
+    /**
+     * @test
+     */
+    public function prepareDataConvertsDateTimeToUnixTimestamp()
+    {
+        $elementsConfiguration = [
+            'date' => [
+                'mapOnDatabaseColumn' => 'date'
+            ]
+        ];
+
+        $saveToDatabaseFinisher = $this->getAccessibleMock(SaveToDatabaseFinisher::class, ['getFormValues', 'getElementByIdentifier']);
+        $saveToDatabaseFinisher->method('getFormValues')->willReturn([
+            'date' => new \DateTime,
+        ]);
+        $saveToDatabaseFinisher->method('getElementByIdentifier')->willReturn($this->prophesize(FormElementInterface::class)->reveal());
+        $databaseData = $saveToDatabaseFinisher->_call('prepareData', $elementsConfiguration, []);
+
+        $expected = '#^([0-9]{10})$#';
+        $this->assertEquals(1, preg_match($expected, $databaseData['date']));
+    }
+
+    /**
+     * @test
+     */
+    public function prepareDataConvertsDateTimeToFormat()
+    {
+        $elementsConfiguration = [
+            'date' => [
+                'mapOnDatabaseColumn' => 'date',
+                'dateFormat' => 'Y.m.d',
+            ]
+        ];
+
+        $saveToDatabaseFinisher = $this->getAccessibleMock(SaveToDatabaseFinisher::class, ['getFormValues', 'getElementByIdentifier']);
+        $saveToDatabaseFinisher->method('getFormValues')->willReturn([
+            'date' => new \DateTime('2018-06-12'),
+        ]);
+        $saveToDatabaseFinisher->method('getElementByIdentifier')->willReturn($this->prophesize(FormElementInterface::class)->reveal());
+        $databaseData = $saveToDatabaseFinisher->_call('prepareData', $elementsConfiguration, []);
+
+        self::assertSame('2018.06.12', $databaseData['date']);
+    }
 }