-
Notifications
You must be signed in to change notification settings - Fork 646
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[!!!][TASK] Improve flex and TCA handling in FormEngine
The patch adapts a series of nasty form engine areas to more solid code. The evaluate condition code is rewritten and works much better in flex form scenarios. The suggest wizard and svg tree are much more solid in flex forms. The group element is rewritten towards a better readable and easier to refactor code, dropping method dbFileIcons(). A bunch of issues is resolved along the way. * TCA "default" now works in flex form section container elements * The "displayCond" parser is now strict and throws exceptions on invalid syntax and wrong referenced fields to help debugging faulty display conditions * TCA displayCond on flex fields can now be prefixed with the sheet name and can reference field values from neighbor sheets * TCA displayCond now works with flex section containers * TCA flex section container now throw an exception if select or group fields configure a MM relation - this is not supported * TCA ctrl requestUpdate field is dropped, onChange=reload is now allowed not only on flex form fields, but also on normal columns fields * TCA tree now works as section container element and initializes correctly on new records and new containers * GroupElement rewrite to drop dbFileIcons() * config option maxitems now optional for type=group and type=select and defaults to "many items allowed" * inline now works in "fancy" flex situations with "new" records by handing the final dataStructureIdentifier around * FormEngine no longer loads extJS Change-Id: Id1d081627529cc1502bb198389e5bd69372815cd Resolves: #78899 Resolves: #72307 Resolves: #75646 Resolves: #76637 Resolves: #72106 Resolves: #78824 Resolves: #76793 Resolves: #68247 Resolves: #69715 Related: #78460 Related: #67198 Related: #72294 Releases: master Reviewed-on: https://review.typo3.org/50879 Tested-by: TYPO3com <no-reply@typo3.com> Reviewed-by: Benni Mack <benni@typo3.org> Tested-by: Benni Mack <benni@typo3.org> Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de> Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
- Loading branch information
Showing
90 changed files
with
6,821 additions
and
2,835 deletions.
There are no files selected for viewing
163 changes: 163 additions & 0 deletions
163
typo3/sysext/backend/Classes/Controller/FormFlexAjaxController.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
<?php | ||
declare(strict_types=1); | ||
namespace TYPO3\CMS\Backend\Controller; | ||
|
||
/* | ||
* This file is part of the TYPO3 CMS project. | ||
* | ||
* It is free software; you can redistribute it and/or modify it under | ||
* the terms of the GNU General Public License, either version 2 | ||
* of the License, or any later version. | ||
* | ||
* For the full copyright and license information, please read the | ||
* LICENSE.txt file that was distributed with this source code. | ||
* | ||
* The TYPO3 project - inspiring people to share! | ||
*/ | ||
|
||
use Psr\Http\Message\ResponseInterface; | ||
use Psr\Http\Message\ServerRequestInterface; | ||
use TYPO3\CMS\Backend\Form\FormDataCompiler; | ||
use TYPO3\CMS\Backend\Form\FormDataGroup\TcaDatabaseRecord; | ||
use TYPO3\CMS\Backend\Form\NodeFactory; | ||
use TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools; | ||
use TYPO3\CMS\Core\Utility\GeneralUtility; | ||
use TYPO3\CMS\Core\Utility\StringUtility; | ||
|
||
/** | ||
* Handle FormEngine flex field ajax calls | ||
*/ | ||
class FormFlexAjaxController | ||
{ | ||
/** | ||
* Render a single flex form section container to add it to the DOM | ||
* | ||
* @param ServerRequestInterface $request | ||
* @param ResponseInterface $response | ||
* @return ResponseInterface | ||
*/ | ||
public function containerAdd(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface | ||
{ | ||
$queryParameters = $request->getParsedBody(); | ||
|
||
$vanillaUid = (int)$queryParameters['vanillaUid']; | ||
$databaseRowUid = $queryParameters['databaseRowUid']; | ||
$command = $queryParameters['command']; | ||
$tableName = $queryParameters['tableName']; | ||
$fieldName = $queryParameters['fieldName']; | ||
$recordTypeValue = $queryParameters['recordTypeValue']; | ||
$dataStructureIdentifier = json_encode($queryParameters['dataStructureIdentifier']); | ||
$flexFormSheetName = $queryParameters['flexFormSheetName']; | ||
$flexFormFieldName = $queryParameters['flexFormFieldName']; | ||
$flexFormContainerName = $queryParameters['flexFormContainerName']; | ||
|
||
// Prepare TCA and data values for a new section container using data providers | ||
$processedTca = $GLOBALS['TCA'][$tableName]; | ||
$flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class); | ||
$dataStructure = $flexFormTools->parseDataStructureByIdentifier($dataStructureIdentifier); | ||
$processedTca['columns'][$fieldName]['config']['ds'] = $dataStructure; | ||
$processedTca['columns'][$fieldName]['config']['dataStructureIdentifier'] = $dataStructureIdentifier; | ||
// Get a new unique id for this container. | ||
$flexFormContainerIdentifier = StringUtility::getUniqueId(); | ||
$flexSectionContainerPreparation = [ | ||
'flexFormSheetName' => $flexFormSheetName, | ||
'flexFormFieldName' => $flexFormFieldName, | ||
'flexFormContainerName' => $flexFormContainerName, | ||
'flexFormContainerIdentifier' => $flexFormContainerIdentifier, | ||
]; | ||
|
||
$formDataGroup = GeneralUtility::makeInstance(TcaDatabaseRecord::class); | ||
$formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup); | ||
$formDataCompilerInput = [ | ||
'tableName' => $tableName, | ||
'vanillaUid' => (int)$vanillaUid, | ||
'databaseRow' => [ | ||
'uid' => $databaseRowUid, | ||
], | ||
'command' => $command, | ||
'recordTypeValue' => $recordTypeValue, | ||
'processedTca' => $processedTca, | ||
'flexSectionContainerPreparation' => $flexSectionContainerPreparation, | ||
]; | ||
$formData = $formDataCompiler->compile($formDataCompilerInput); | ||
|
||
$dataStructure = $formData['processedTca']['columns'][$fieldName]['config']['ds']; | ||
$formData['fieldName'] = $fieldName; | ||
$formData['flexFormDataStructureArray'] = $dataStructure['sheets'][$flexFormSheetName]['ROOT']['el'][$flexFormFieldName]['children'][$flexFormContainerIdentifier]; | ||
$formData['flexFormDataStructureIdentifier'] = $dataStructureIdentifier; | ||
$formData['flexFormFieldName'] = $flexFormFieldName; | ||
$formData['flexFormSheetName'] = $flexFormSheetName; | ||
$formData['flexFormContainerName'] = $flexFormContainerName; | ||
$formData['flexFormContainerIdentifier'] = $flexFormContainerIdentifier; | ||
$formData['flexFormContainerElementCollapsed'] = false; | ||
|
||
$formData['flexFormFormPrefix'] = '[data][' . $flexFormSheetName . '][lDEF]' . '[' . $flexFormFieldName . ']' . '[el]'; | ||
$formData['parameterArray']['itemFormElName'] = 'data[' . $tableName . '][' . $formData['databaseRow']['uid'] . '][' . $fieldName . ']'; | ||
|
||
// JavaScript code for event handlers: | ||
// @todo: see if we can get rid of this - used in group elements, and also for the "reload" on type field changes | ||
$formData['parameterArray']['fieldChangeFunc'] = []; | ||
$formData['parameterArray']['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'TBE_EDITOR.fieldChanged(' | ||
. GeneralUtility::quoteJSvalue($tableName) | ||
. ',' . GeneralUtility::quoteJSvalue($formData['databaseRow']['uid']) | ||
. ',' . GeneralUtility::quoteJSvalue($fieldName) | ||
. ',' . GeneralUtility::quoteJSvalue($formData['parameterArray']['itemFormElName']) | ||
. ');'; | ||
|
||
// @todo: check GroupElement for usage of elementBaseName ... maybe kick that thing? | ||
// Feed resulting form data to container structure to render HTML and other result data | ||
$nodeFactory = GeneralUtility::makeInstance(NodeFactory::class); | ||
$formData['renderType'] = 'flexFormContainerContainer'; | ||
$newContainerResult = $nodeFactory->create($formData)->render(); | ||
|
||
$jsonResult = [ | ||
'html' => $newContainerResult['html'], | ||
'scriptCall' => [], | ||
]; | ||
|
||
if (!empty($newContainerResult['additionalJavaScriptSubmit'])) { | ||
$additionalJavaScriptSubmit = implode('', $newContainerResult['additionalJavaScriptSubmit']); | ||
$additionalJavaScriptSubmit = str_replace([CR, LF], '', $additionalJavaScriptSubmit); | ||
$jsonResult['scriptCall'][] = 'TBE_EDITOR.addActionChecks("submit", "' . addslashes($additionalJavaScriptSubmit) . '");'; | ||
} | ||
foreach ($newContainerResult['additionalJavaScriptPost'] as $singleAdditionalJavaScriptPost) { | ||
$jsonResult['scriptCall'][] = $singleAdditionalJavaScriptPost; | ||
} | ||
// @todo: handle stylesheetFiles, additionalInlineLanguageLabelFiles | ||
|
||
// @todo: copied from inline ajax handler - maybe extract to some abstract? | ||
if (!empty($newContainerResult['requireJsModules'])) { | ||
foreach ($newContainerResult['requireJsModules'] as $module) { | ||
$moduleName = null; | ||
$callback = null; | ||
if (is_string($module)) { | ||
// if $module is a string, no callback | ||
$moduleName = $module; | ||
$callback = null; | ||
} elseif (is_array($module)) { | ||
// if $module is an array, callback is possible | ||
foreach ($module as $key => $value) { | ||
$moduleName = $key; | ||
$callback = $value; | ||
break; | ||
} | ||
} | ||
if ($moduleName !== null) { | ||
$inlineCodeKey = $moduleName; | ||
$javaScriptCode = 'require(["' . $moduleName . '"]'; | ||
if ($callback !== null) { | ||
$inlineCodeKey .= sha1($callback); | ||
$javaScriptCode .= ', ' . $callback; | ||
} | ||
$javaScriptCode .= ');'; | ||
$jsonResult['scriptCall'][] = '/*RequireJS-Module-' . $inlineCodeKey . '*/' . LF . $javaScriptCode; | ||
} | ||
} | ||
} | ||
|
||
$response->getBody()->write(json_encode($jsonResult)); | ||
|
||
return $response; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.