From eaf0d1bd2537f6ca7628e77832363c5e7b1f1dcf Mon Sep 17 00:00:00 2001
From: Andreas Fernandez <a.fernandez@scripting-base.de>
Date: Wed, 9 Aug 2017 12:11:47 +0200
Subject: [PATCH] [BUGFIX] Implode array values in SaveToDatabaseFinisher

Array values being processed by SaveToDatabaseFinisher are now
imploded by a comma. This may happen when using a `MultiCheckbox` element.

Resolves: #82061
Releases: master, 8.7
Change-Id: Ic84af11ba00611aa89b043cd3b1c36dedb356c68
Reviewed-on: https://review.typo3.org/53664
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Joerg Boesche <typo3@joergboesche.de>
Tested-by: Joerg Boesche <typo3@joergboesche.de>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
---
 .../Finishers/SaveToDatabaseFinisher.php      | 63 ++++++++++++-------
 .../Finishers/SaveToDatabaseFinisherTest.php  | 25 ++++++++
 2 files changed, 64 insertions(+), 24 deletions(-)

diff --git a/typo3/sysext/form/Classes/Domain/Finishers/SaveToDatabaseFinisher.php b/typo3/sysext/form/Classes/Domain/Finishers/SaveToDatabaseFinisher.php
index ef6ddb38ce88..7f53c91ca007 100644
--- a/typo3/sysext/form/Classes/Domain/Finishers/SaveToDatabaseFinisher.php
+++ b/typo3/sysext/form/Classes/Domain/Finishers/SaveToDatabaseFinisher.php
@@ -209,33 +209,14 @@ class SaveToDatabaseFinisher extends AbstractFinisher
     }
 
     /**
-     * Perform the current database operation
+     * Prepare data for saving to database
      *
-     * @param int $iterationCount
+     * @param array $elementsConfiguration
+     * @param array $databaseData
+     * @return mixed
      */
-    protected function process(int $iterationCount)
+    protected function prepareData(array $elementsConfiguration, array $databaseData)
     {
-        $this->throwExceptionOnInconsistentConfiguration();
-
-        $table = $this->parseOption('table');
-        $elementsConfiguration = $this->parseOption('elements');
-        $databaseColumnMappingsConfiguration = $this->parseOption('databaseColumnMappings');
-
-        $this->databaseConnection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
-
-        $databaseData = [];
-        foreach ($databaseColumnMappingsConfiguration as $databaseColumnName => $databaseColumnConfiguration) {
-            $value = $this->parseOption('databaseColumnMappings.' . $databaseColumnName . '.value');
-            if (
-                empty($value)
-                && $databaseColumnConfiguration['skipIfValueIsEmpty'] === true
-            ) {
-                continue;
-            }
-
-            $databaseData[$databaseColumnName] = $value;
-        }
-
         foreach ($this->getFormValues() as $elementIdentifier => $elementValue) {
             if (
                 $elementValue === null
@@ -267,9 +248,43 @@ class SaveToDatabaseFinisher extends AbstractFinisher
                 } else {
                     $elementValue = $elementValue->getOriginalResource()->getProperty('uid_local');
                 }
+            } elseif (is_array($elementValue)) {
+                $elementValue = implode(',', $elementValue);
             }
             $databaseData[$elementsConfiguration[$elementIdentifier]['mapOnDatabaseColumn']] = $elementValue;
         }
+        return $databaseData;
+    }
+
+    /**
+     * Perform the current database operation
+     *
+     * @param int $iterationCount
+     */
+    protected function process(int $iterationCount)
+    {
+        $this->throwExceptionOnInconsistentConfiguration();
+
+        $table = $this->parseOption('table');
+        $elementsConfiguration = $this->parseOption('elements');
+        $databaseColumnMappingsConfiguration = $this->parseOption('databaseColumnMappings');
+
+        $this->databaseConnection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
+
+        $databaseData = [];
+        foreach ($databaseColumnMappingsConfiguration as $databaseColumnName => $databaseColumnConfiguration) {
+            $value = $this->parseOption('databaseColumnMappings.' . $databaseColumnName . '.value');
+            if (
+                empty($value)
+                && $databaseColumnConfiguration['skipIfValueIsEmpty'] === true
+            ) {
+                continue;
+            }
+
+            $databaseData[$databaseColumnName] = $value;
+        }
+
+        $databaseData = $this->prepareData($elementsConfiguration, $databaseData);
 
         $this->saveToDatabase($databaseData, $table, $iterationCount);
     }
diff --git a/typo3/sysext/form/Tests/Unit/Domain/Finishers/SaveToDatabaseFinisherTest.php b/typo3/sysext/form/Tests/Unit/Domain/Finishers/SaveToDatabaseFinisherTest.php
index ba4dfd9b393c..7e12d3a95f06 100644
--- a/typo3/sysext/form/Tests/Unit/Domain/Finishers/SaveToDatabaseFinisherTest.php
+++ b/typo3/sysext/form/Tests/Unit/Domain/Finishers/SaveToDatabaseFinisherTest.php
@@ -16,6 +16,7 @@ namespace TYPO3\CMS\Form\Tests\Unit\Domain\Finishers;
 
 use TYPO3\CMS\Form\Domain\Finishers\Exception\FinisherException;
 use TYPO3\CMS\Form\Domain\Finishers\SaveToDatabaseFinisher;
+use TYPO3\CMS\Form\Domain\Model\FormElements\FormElementInterface;
 
 /**
  * Test case
@@ -42,4 +43,28 @@ class SaveToDatabaseFinisherTest extends \TYPO3\TestingFramework\Core\Unit\UnitT
 
         $mockSaveToDatabaseFinisher->_call('throwExceptionOnInconsistentConfiguration');
     }
+
+    /**
+     * @test
+     */
+    public function prepareDataConvertsArrayValuesToCsv()
+    {
+        $elementsConfiguration = [
+            'foo' => [
+                'mapOnDatabaseColumn' => 'bar'
+            ]
+        ];
+
+        $saveToDatabaseFinisher = $this->getAccessibleMock(SaveToDatabaseFinisher::class, ['getFormValues', 'getElementByIdentifier']);
+        $saveToDatabaseFinisher->method('getFormValues')->willReturn([
+            'foo' => [
+                'one',
+                'two'
+            ]
+        ]);
+        $saveToDatabaseFinisher->method('getElementByIdentifier')->willReturn($this->prophesize(FormElementInterface::class)->reveal());
+        $databaseData = $saveToDatabaseFinisher->_call('prepareData', $elementsConfiguration, []);
+
+        self::assertSame('one,two', $databaseData['bar']);
+    }
 }
-- 
GitLab