[BUGFIX] Do not write empty array values in form definitions 44/56744/3
authorRalf Zimmermann <ralf.zimmermann@tritum.de>
Tue, 20 Feb 2018 22:44:00 +0000 (23:44 +0100)
committerOliver Hader <oliver.hader@typo3.org>
Thu, 19 Apr 2018 18:37:47 +0000 (20:37 +0200)
Symfony YAML dumps empty arrays as sequence ("{  }"). Due to this, some
JavaScript modules of the form framework fail to interpret/ set the
correct data type for those properties.

If applied, this commit will ensure that the formEditor unsets empty
array keys on load/ save.

The problem only affects the backend module, not the frontend
formDefinition interpreter.

Resolves: #83985
Releases: master, 8.7
Change-Id: I913b8954790510b4ffcc80a47f9dbb7646239ff1
Reviewed-on: https://review.typo3.org/55848
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Björn Jacob <bjoern.jacob@tritum.de>
Tested-by: Björn Jacob <bjoern.jacob@tritum.de>
Reviewed-by: Kay Strobach <typo3@kay-strobach.de>
Tested-by: Kay Strobach <typo3@kay-strobach.de>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
Reviewed-on: https://review.typo3.org/56744
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Hader <oliver.hader@typo3.org>
typo3/sysext/form/Classes/Controller/FormEditorController.php
typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/InspectorComponent.js
typo3/sysext/form/Tests/Unit/Controller/FormEditorControllerTest.php

index 91b4413..63c25eb 100644 (file)
@@ -79,6 +79,7 @@ class FormEditorController extends AbstractBackendController
             $prototypeName = isset($formDefinition['prototypeName']) ? $formDefinition['prototypeName'] : 'standard';
         }
         $formDefinition['prototypeName'] = $prototypeName;
+        $formDefinition = $this->filterEmptyArrays($formDefinition);
 
         $configurationService = $this->objectManager->get(ConfigurationService::class);
         $this->prototypeConfiguration = $configurationService->getPrototypeConfiguration($prototypeName);
@@ -153,6 +154,7 @@ class FormEditorController extends AbstractBackendController
     public function saveFormAction(string $formPersistenceIdentifier, FormDefinitionArray $formDefinition)
     {
         $formDefinition = $formDefinition->getArrayCopy();
+        $formDefinition = $this->filterEmptyArrays($formDefinition);
         if (
             isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['beforeFormSave'])
             && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['beforeFormSave'])
@@ -217,7 +219,7 @@ class FormEditorController extends AbstractBackendController
     }
 
     /**
-     * Prepare the formElements.*.formEditor section from the yaml settings.
+     * Prepare the formElements.*.formEditor section from the YAML settings.
      * Sort all formElements into groups and add additional data.
      *
      * @param array $formElementsDefinition
@@ -277,7 +279,7 @@ class FormEditorController extends AbstractBackendController
     }
 
     /**
-     * Reduce the Yaml settings by the 'formEditor' keyword.
+     * Reduce the YAML settings by the 'formEditor' keyword.
      *
      * @return array
      */
@@ -520,6 +522,31 @@ class FormEditorController extends AbstractBackendController
     }
 
     /**
+     * Remove keys from an array if the key value is an empty array
+     *
+     * @param array $array
+     * @return array
+     */
+    protected function filterEmptyArrays(array $array): array
+    {
+        foreach ($array as $key => $value) {
+            if (!is_array($value)) {
+                continue;
+            }
+            if (empty($value)) {
+                unset($array[$key]);
+                continue;
+            }
+            $array[$key] = $this->filterEmptyArrays($value);
+            if (empty($array[$key])) {
+                unset($array[$key]);
+            }
+        }
+
+        return $array;
+    }
+
+    /**
      * Returns the current BE user.
      *
      * @return BackendUserAuthentication
index 55d327a..8cd88c1 100644 (file)
@@ -1425,9 +1425,8 @@ define(['jquery',
           var that = $(this);
           if (!$.isNumeric(that.val())) {
             that.val('');
-          } else {
-            getCurrentlySelectedFormElement().set(propertyPath, that.val());
           }
+          getCurrentlySelectedFormElement().set(propertyPath, that.val());
         });
       };
 
index 3088a0e..f52df48 100644 (file)
@@ -477,4 +477,39 @@ class FormEditorControllerTest extends \TYPO3\TestingFramework\Core\Unit\UnitTes
 
         $this->assertSame($expected, $mockController->_call('transformMultiValueElementsForFormEditor', $input, $multiValueProperties));
     }
+
+    /**
+     * @test
+     */
+    public function filterEmptyArraysRemovesEmptyArrayKeys()
+    {
+        $mockController = $this->getAccessibleMock(FormEditorController::class, [
+            'dummy'
+        ], [], '', false);
+
+        $input = [
+            'heinz' => 1,
+            'klaus' => [],
+            'sabine' => [
+                'heinz' => '2',
+                'klaus' => [],
+                'horst' => [
+                    'heinz' => '',
+                    'paul' => [[]],
+                ],
+            ],
+        ];
+
+        $expected = [
+            'heinz' => 1,
+            'sabine' => [
+                'heinz' => '2',
+                'horst' => [
+                    'heinz' => '',
+                ],
+            ],
+        ];
+
+        $this->assertSame($expected, $mockController->_call('filterEmptyArrays', $input));
+    }
 }