[BUGFIX] FormEngine: Exception on inline/section in flex container 79/47379/2
authorChristian Kuhn <lolli@schwarzbu.ch>
Wed, 23 Mar 2016 15:18:41 +0000 (16:18 +0100)
committerChristian Kuhn <lolli@schwarzbu.ch>
Thu, 24 Mar 2016 11:01:59 +0000 (12:01 +0100)
Nesting flex form sections or inline within section containers is
not supported. To not let developers run into hard to track issues
the patch adds an exception to detect these cases.

Additionally, GroupElement contains a preparation that is done by
TcaGroup data provider already, so this part is cleaned up along
the way since this is unreachable code if FormEngine is used without
nested sections.

Change-Id: I2af9140ad0fe1d60d85439bd5598775904b70e52
Resolves: #73125
Releases: master, 7.6
Reviewed-on: https://review.typo3.org/47379
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/backend/Classes/Form/Element/GroupElement.php
typo3/sysext/backend/Classes/Form/FormDataProvider/TcaFlexProcess.php
typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaFlexProcessTest.php

index 7945436..206965e 100644 (file)
@@ -247,7 +247,6 @@ class GroupElement extends AbstractFormElement
             case 'db':
                 // If the element is of the internal type "db":
                 // Creating string showing allowed types:
-                $onlySingleTableAllowed = false;
                 $languageService = $this->getLanguageService();
 
                 $allowedTables = array();
@@ -256,7 +255,6 @@ class GroupElement extends AbstractFormElement
                         'name' => htmlspecialchars($languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.allTables'))
                     );
                 } elseif ($allowed) {
-                    $onlySingleTableAllowed = count($allowed) === 1;
                     foreach ($allowed as $allowedTable) {
                         $allowedTables[] = array(
                             // @todo: access to globals!
@@ -275,10 +273,6 @@ class GroupElement extends AbstractFormElement
                 foreach ($temp_itemArray as $dbRead) {
                     $recordParts = explode('|', $dbRead);
                     list($this_table, $this_uid) = BackendUtility::splitTable_Uid($recordParts[0]);
-                    // For the case that no table was found and only a single table is defined to be allowed, use that one:
-                    if (!$this_table && $onlySingleTableAllowed) {
-                        $this_table = $allowed;
-                    }
                     $itemArray[] = array('table' => $this_table, 'id' => $this_uid);
                     if (!$disabled && $show_thumbs) {
                         $rr = BackendUtility::getRecordWSOL($this_table, $this_uid);
index b199ae3..dc37f59 100644 (file)
@@ -235,6 +235,7 @@ class TcaFlexProcess implements FormDataProviderInterface
      * @param string $fieldName Current handle field name
      * @param array $pageTsConfig Given pageTsConfig of this flex form
      * @return array Modified item array
+     * @throws \UnexpectedValueException
      */
     protected function modifyDataStructureAndDataValuesByFlexFormSegmentGroup(array $result, $fieldName, $pageTsConfig)
     {
@@ -263,8 +264,11 @@ class TcaFlexProcess implements FormDataProviderInterface
                 $pageTsConfig['TCEFORM.'][$tableName . '.'] = $pageTsConfig[$dataStructureSheetName . '.'];
             }
 
+            // List of "new" tca fields that have no value within the flexform, yet. Those will be compiled in one go later.
             $tcaNewColumns = [];
+            // List of "edit" tca fields that have a value in flexform, already. Those will be compiled in one go later.
             $tcaEditColumns = [];
+            // Contains the data values for the "edit" tca fields.
             $tcaValueArray = [
                 'uid' => $result['databaseRow']['uid'],
             ];
@@ -389,6 +393,30 @@ class TcaFlexProcess implements FormDataProviderInterface
                                 [$possibleContainerName]['el']
                                     = [];
                                 foreach ($possibleContainerConfiguration['el'] as $singleFieldName => $singleFieldConfiguration) {
+
+                                    // Nesting type=inline in container sections is not supported. Throw an exception if configured.
+                                    if (isset($singleFieldConfiguration['config']['type']) && $singleFieldConfiguration['config']['type'] === 'inline') {
+                                        throw new \UnexpectedValueException(
+                                            'Invalid flex form data structure on field name "' . $fieldName . '" with element "' . $singleFieldName . '"'
+                                                . ' in section container "' . $possibleContainerName . '": Nesting inline elements in flex form'
+                                                . ' sections is not allowed.',
+                                            1458745468
+                                        );
+                                    }
+
+                                    // Nesting sections is not supported. Throw an exception if configured.
+                                    if (is_array($singleFieldConfiguration)
+                                        && isset($singleFieldConfiguration['type']) && $singleFieldConfiguration['type'] === 'array'
+                                        && isset($singleFieldConfiguration['section']) && (string)$singleFieldConfiguration['section'] === '1'
+                                    ) {
+                                        throw new \UnexpectedValueException(
+                                            'Invalid flex form data structure on field name "' . $fieldName . '" with element "' . $singleFieldName . '"'
+                                                . ' in section container "' . $possibleContainerName . '": Nesting sections in container elements'
+                                                . ' sections is not allowed.',
+                                            1458745712
+                                        );
+                                    }
+
                                     $inputToFlexFormSegment = [
                                         'tableName' => $result['tableName'],
                                         'command' => 'new',
@@ -528,14 +556,6 @@ class TcaFlexProcess implements FormDataProviderInterface
     }
 
     /**
-     * @return BackendUserAuthentication
-     */
-    protected function getBackendUser()
-    {
-        return $GLOBALS['BE_USER'];
-    }
-
-    /**
      * Add fields and values used by ds_pointerField to the meta data array so they can be used in AJAX context during rendering.
      *
      * @todo: This method is a stopgap measure to get required information into the AJAX controller
@@ -566,4 +586,13 @@ class TcaFlexProcess implements FormDataProviderInterface
         $result['processedTca']['columns'][$fieldName]['config']['ds']['meta']['dataStructurePointers'] = $dsPointers;
         return $result;
     }
+
+    /**
+     * @return BackendUserAuthentication
+     */
+    protected function getBackendUser()
+    {
+        return $GLOBALS['BE_USER'];
+    }
+
 }
index 08c60eb..de98b15 100644 (file)
@@ -1135,6 +1135,122 @@ class TcaFlexProcessTest extends UnitTestCase
     /**
      * @test
      */
+    public function addDataThrowsExceptionForInlineElementsNestedInSectionContainers()
+    {
+        $input = [
+            'tableName' => 'aTable',
+            'databaseRow' => [
+                'aField' => [
+                    'data' => [],
+                ],
+                'pointerField' => 'aFlex',
+            ],
+            'processedTca' => [
+                'columns' => [
+                    'aField' => [
+                        'config' => [
+                            'type' => 'flex',
+                            'ds' => [
+                                'sheets' => [
+                                    'sDEF' => [
+                                        'ROOT' => [
+                                            'type' => 'array',
+                                            'el' => [
+                                                'section_1' => [
+                                                    'section' => '1',
+                                                    'type' => 'array',
+                                                    'el' => [
+                                                        'container_1' => [
+                                                            'type' => 'array',
+                                                            'el' => [
+                                                                'aFlexField' => [
+                                                                    'label' => 'aFlexFieldLabel',
+                                                                    'config' => [
+                                                                        'type' => 'inline',
+                                                                    ],
+                                                                ],
+                                                            ],
+                                                        ],
+                                                    ],
+                                                ],
+                                            ],
+                                        ],
+                                    ],
+                                ],
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+            'pageTsConfig' => [],
+        ];
+
+        $this->setExpectedException(\UnexpectedValueException::class, $this->anything(), 1458745468);
+
+        $this->subject->addData($input);
+    }
+
+    /**
+     * @test
+     */
+    public function addDataThrowsExceptionForNestedSectionContainers()
+    {
+        $input = [
+            'tableName' => 'aTable',
+            'databaseRow' => [
+                'aField' => [
+                    'data' => [],
+                ],
+                'pointerField' => 'aFlex',
+            ],
+            'processedTca' => [
+                'columns' => [
+                    'aField' => [
+                        'config' => [
+                            'type' => 'flex',
+                            'ds' => [
+                                'sheets' => [
+                                    'sDEF' => [
+                                        'ROOT' => [
+                                            'type' => 'array',
+                                            'el' => [
+                                                'section_1' => [
+                                                    'section' => '1',
+                                                    'type' => 'array',
+                                                    'el' => [
+                                                        'container_1' => [
+                                                            'type' => 'array',
+                                                            'el' => [
+                                                                'section_nested' => [
+                                                                    'section' => '1',
+                                                                    'type' => 'array',
+                                                                    'el' => [
+                                                                    ],
+                                                                ],
+                                                            ],
+                                                        ],
+                                                    ],
+                                                ],
+                                            ],
+                                        ],
+                                    ],
+                                ],
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+            'pageTsConfig' => [],
+        ];
+
+        $this->setExpectedException(\UnexpectedValueException::class, $this->anything(), 1458745712);
+
+        $this->subject->addData($input);
+    }
+
+    /**
+     * @test
+     */
     public function addDataCallsFlexFormSegmentGroupForFieldAndAddsFlexParentDatabaseRow()
     {
         $input = [