e06956997deee1cabb404048a7a50eb5e5e7eb59
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Classes / Controller / FormFrontendController.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Form\Controller;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader\Configuration;
19 use TYPO3\CMS\Core\Utility\ArrayUtility;
20 use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
21 use TYPO3\CMS\Form\Domain\Configuration\ConfigurationService;
22 use TYPO3\CMS\Form\Mvc\Configuration\TypoScriptService;
23
24 /**
25 * The frontend controller
26 *
27 * Scope: frontend
28 */
29 class FormFrontendController extends ActionController
30 {
31
32 /**
33 * @var \TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface
34 */
35 protected $formPersistenceManager;
36
37 /**
38 * @param \TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface $formPersistenceManager
39 * @internal
40 */
41 public function injectFormPersistenceManager(\TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface $formPersistenceManager)
42 {
43 $this->formPersistenceManager = $formPersistenceManager;
44 }
45
46 /**
47 * Take the form which should be rendered from the plugin settings
48 * and overlay the formDefinition with additional data from
49 * flexform and typoscript settings.
50 * This method is used directly to display the first page from the
51 * formDefinition because its cached.
52 *
53 * @internal
54 */
55 public function renderAction()
56 {
57 $formDefinition = [];
58 if (!empty($this->settings['persistenceIdentifier'])) {
59 /** @var \TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader\Configuration */
60 $configuration = $this->objectManager->get(Configuration::class)
61 ->setRemoveImportsProperty(false);
62 $formDefinition = $this->formPersistenceManager->load($this->settings['persistenceIdentifier'], $configuration);
63 $formDefinition['persistenceIdentifier'] = $this->settings['persistenceIdentifier'];
64 $formDefinition = $this->overrideByTypoScriptSettings($formDefinition);
65 $formDefinition = $this->overrideByFlexFormSettings($formDefinition);
66 $formDefinition['identifier'] .= '-' . $this->configurationManager->getContentObject()->data['uid'];
67 }
68 $this->view->assign('formConfiguration', $formDefinition);
69 }
70
71 /**
72 * This method is used to display all pages / finishers except the
73 * first page because its non cached.
74 *
75 * @internal
76 */
77 public function performAction()
78 {
79 $this->forward('render');
80 }
81
82 /**
83 * Override the formDefinition with additional data from the Flexform
84 * settings. For now, only finisher settings are overridable.
85 *
86 * @param array $formDefinition
87 * @return array
88 */
89 protected function overrideByFlexFormSettings(array $formDefinition): array
90 {
91 if (isset($formDefinition['finishers'])) {
92 foreach ($formDefinition['finishers'] as &$finisherValue) {
93 $finisherIdentifier = $finisherValue['identifier'];
94 if ($this->settings['overrideFinishers'] && isset($this->settings['finishers'][$finisherIdentifier])) {
95 $prototypeName = $formDefinition['prototypeName'] ?? 'standard';
96 $configurationService = $this->objectManager->get(ConfigurationService::class);
97 $prototypeConfiguration = $configurationService->getPrototypeConfiguration($prototypeName);
98
99 foreach ($finisherValue['options'] as $optionKey => $optionValue) {
100 // If a previous overridden finisher property is excluded at some time
101 // it is still present in the flexform database row.
102 // To avoid a override from the time the property is excluded, this check is needed
103 if (!isset($prototypeConfiguration['finishersDefinition'][$finisherIdentifier]['FormEngine']['elements'][$optionKey])) {
104 continue;
105 }
106 if (isset($this->settings['finishers'][$finisherIdentifier][$optionKey])) {
107 $finisherValue['options'][$optionKey] = $this->settings['finishers'][$finisherIdentifier][$optionKey];
108 }
109 }
110 }
111 }
112 }
113 return $formDefinition;
114 }
115
116 /**
117 * Every formDefinition setting are overridable by typoscript.
118 * If the typoscript configuration path
119 * plugin.tx_form.settings.formDefinitionOverrides.<identifier>
120 * exists, this settings are merged into the formDefinition.
121 *
122 * @param array $formDefinition
123 * @return array
124 */
125 protected function overrideByTypoScriptSettings(array $formDefinition): array
126 {
127 if (
128 isset($this->settings['formDefinitionOverrides'][$formDefinition['identifier']])
129 && !empty($this->settings['formDefinitionOverrides'][$formDefinition['identifier']])
130 ) {
131 ArrayUtility::mergeRecursiveWithOverrule(
132 $formDefinition,
133 $this->settings['formDefinitionOverrides'][$formDefinition['identifier']]
134 );
135 $formDefinition = $this->objectManager->get(TypoScriptService::class)
136 ->resolvePossibleTypoScriptConfiguration($formDefinition);
137 }
138 return $formDefinition;
139 }
140 }