Commit 8ae9f625 authored by Christian Kuhn's avatar Christian Kuhn
Browse files

[BUGFIX] FormEngine: Exception on inline/section in flex container

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/47369

Reviewed-by: Wouter Wolters's avatarWouter Wolters <typo3@wouterwolters.nl>
Tested-by: Wouter Wolters's avatarWouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Oliver Hader's avatarOliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Hader's avatarOliver Hader <oliver.hader@typo3.org>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
parent 940a8c01
......@@ -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);
......
......@@ -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',
......@@ -527,14 +555,6 @@ class TcaFlexProcess implements FormDataProviderInterface
return $dataStructure;
}
/**
* @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.
*
......@@ -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'];
}
}
......@@ -1132,6 +1132,122 @@ class TcaFlexProcessTest extends UnitTestCase
$this->assertEquals($expected, $this->subject->addData($input));
}
/**
* @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
*/
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment