157 lines
7.0 KiB
PHP
157 lines
7.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/*
|
|
* 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!
|
|
*/
|
|
|
|
namespace TYPO3\CMS\Form\Controller;
|
|
|
|
use Psr\Http\Message\ResponseInterface;
|
|
use TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools;
|
|
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface as ExtbaseConfigurationManagerInterface;
|
|
use TYPO3\CMS\Extbase\Http\ForwardResponse;
|
|
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
|
|
use TYPO3\CMS\Form\Domain\Configuration\ArrayProcessing\ArrayProcessing;
|
|
use TYPO3\CMS\Form\Domain\Configuration\ArrayProcessing\ArrayProcessor;
|
|
use TYPO3\CMS\Form\Domain\Configuration\ConfigurationService;
|
|
use TYPO3\CMS\Form\Domain\Configuration\FormDefinition\Converters\FinisherOptionsFlexFormOverridesConverter;
|
|
use TYPO3\CMS\Form\Domain\Configuration\FormDefinition\Converters\FlexFormFinisherOverridesConverterDto;
|
|
use TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface;
|
|
|
|
/**
|
|
* The frontend controller
|
|
*
|
|
* Scope: frontend
|
|
* @internal
|
|
*/
|
|
class FormFrontendController extends ActionController
|
|
{
|
|
public function __construct(
|
|
protected readonly ConfigurationService $configurationService,
|
|
protected readonly FormPersistenceManagerInterface $formPersistenceManager,
|
|
protected readonly FlexFormTools $flexFormTools,
|
|
) {}
|
|
|
|
/**
|
|
* Take the form which should be rendered from the plugin settings
|
|
* and overlay the formDefinition with additional data from
|
|
* flexform and typoscript settings.
|
|
* This method is used directly to display the first page from the
|
|
* formDefinition because its cached.
|
|
*
|
|
* @internal
|
|
*/
|
|
public function renderAction(): ResponseInterface
|
|
{
|
|
$formDefinition = [];
|
|
if (!empty($this->settings['persistenceIdentifier'])) {
|
|
$typoScriptSettings = $this->configurationManager->getConfiguration(ExtbaseConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS, 'form');
|
|
$formDefinition = $this->formPersistenceManager->load($this->settings['persistenceIdentifier'], $typoScriptSettings, $this->request);
|
|
$formDefinition['persistenceIdentifier'] = $this->settings['persistenceIdentifier'];
|
|
$formDefinition = $this->overrideByFlexFormSettings($formDefinition);
|
|
$formDefinition = ArrayUtility::setValueByPath($formDefinition, 'renderingOptions._originalIdentifier', $formDefinition['identifier'], '.');
|
|
$formDefinition['identifier'] .= '-' . ($this->request->getAttribute('currentContentObject')?->data['uid'] ?? '');
|
|
}
|
|
$this->view->assign('formConfiguration', $formDefinition);
|
|
return $this->htmlResponse();
|
|
}
|
|
|
|
/**
|
|
* This method is used to display all pages / finishers except the
|
|
* first page because its non cached.
|
|
*
|
|
* @internal
|
|
*/
|
|
public function performAction(): ResponseInterface
|
|
{
|
|
return new ForwardResponse('render');
|
|
}
|
|
|
|
/**
|
|
* Override the formDefinition with additional data from the Flexform
|
|
* settings. For now, only finisher settings are overridable.
|
|
*/
|
|
protected function overrideByFlexFormSettings(array $formDefinition): array
|
|
{
|
|
$flexFormData = $this->request->getAttribute('currentContentObject')?->data['pi_flexform'] ?? [];
|
|
if (is_string($flexFormData) && $flexFormData !== '') {
|
|
$flexFormData = GeneralUtility::xml2array($flexFormData);
|
|
}
|
|
if (!is_array($flexFormData) || $flexFormData === []) {
|
|
return $formDefinition;
|
|
}
|
|
if (isset($formDefinition['finishers'])) {
|
|
$prototypeName = $formDefinition['prototypeName'] ?? 'standard';
|
|
$prototypeConfiguration = $this->configurationService->getPrototypeConfiguration($prototypeName);
|
|
foreach ($formDefinition['finishers'] as $index => $formFinisherDefinition) {
|
|
$finisherIdentifier = $formFinisherDefinition['identifier'];
|
|
$sheetIdentifier = $this->getFlexformSheetIdentifier($formDefinition, $prototypeName, $finisherIdentifier);
|
|
$flexFormSheetSettings = $this->getFlexFormSettingsFromSheet($flexFormData, $sheetIdentifier);
|
|
if (($this->settings['overrideFinishers'] ?? false) && isset($flexFormSheetSettings['finishers'][$finisherIdentifier])) {
|
|
$prototypeFinisherDefinition = $prototypeConfiguration['finishersDefinition'][$finisherIdentifier] ?? [];
|
|
$converterDto = GeneralUtility::makeInstance(
|
|
FlexFormFinisherOverridesConverterDto::class,
|
|
$prototypeFinisherDefinition,
|
|
$formFinisherDefinition,
|
|
$finisherIdentifier,
|
|
$flexFormSheetSettings
|
|
);
|
|
// Iterate over all `prototypes.<prototypeName>.finishersDefinition.<finisherIdentifier>.FormEngine.elements` values
|
|
GeneralUtility::makeInstance(ArrayProcessor::class, $prototypeFinisherDefinition['FormEngine']['elements'])->forEach(
|
|
GeneralUtility::makeInstance(
|
|
ArrayProcessing::class,
|
|
'modifyFinisherOptionsFromFlexFormOverrides',
|
|
'^(.*)(?:\.config\.type|\.section)$',
|
|
GeneralUtility::makeInstance(FinisherOptionsFlexFormOverridesConverter::class, $converterDto)
|
|
)
|
|
);
|
|
$formDefinition['finishers'][$index] = $converterDto->getFinisherDefinition();
|
|
}
|
|
}
|
|
}
|
|
return $formDefinition;
|
|
}
|
|
|
|
protected function getFlexformSheetIdentifier(array $formDefinition, string $prototypeName, string $finisherIdentifier): string
|
|
{
|
|
return md5(
|
|
implode('', [
|
|
$formDefinition['persistenceIdentifier'],
|
|
$prototypeName,
|
|
$formDefinition['identifier'],
|
|
$finisherIdentifier,
|
|
])
|
|
);
|
|
}
|
|
|
|
protected function getFlexFormSettingsFromSheet(array $flexForm, string $sheetIdentifier): array
|
|
{
|
|
$sheetData = [];
|
|
$sheetData['data'] = array_filter(
|
|
$flexForm['data'] ?? [],
|
|
static function ($key) use ($sheetIdentifier) {
|
|
return $key === $sheetIdentifier;
|
|
},
|
|
ARRAY_FILTER_USE_KEY
|
|
);
|
|
if (empty($sheetData['data'])) {
|
|
return [];
|
|
}
|
|
$sheetDataXml = $this->flexFormTools->flexArray2Xml($sheetData);
|
|
return $this->flexFormTools->convertFlexFormContentToArray($sheetDataXml)['settings'] ?? [];
|
|
}
|
|
}
|