[FEATURE] EXT:form - integrate new form framework
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Classes / Domain / Finishers / AbstractFinisher.php
1 <?php
2 declare(strict_types=1);
3 namespace TYPO3\CMS\Form\Domain\Finishers;
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\Extbase\Reflection\ObjectAccess;
19 use TYPO3\CMS\Extbase\Utility\ArrayUtility;
20 use TYPO3\CMS\Form\Service\TranslationService;
21 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
22
23 /**
24 * Finisher base class.
25 *
26 * Scope: frontend
27 * **This class is meant to be sub classed by developers**
28 */
29 abstract class AbstractFinisher implements FinisherInterface
30 {
31
32 /**
33 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
34 */
35 protected $objectManager;
36
37 /**
38 * @var string
39 */
40 protected $finisherIdentifier = '';
41
42 /**
43 * The options which have been set from the outside. Instead of directly
44 * accessing them, you should rather use parseOption().
45 *
46 * @var array
47 */
48 protected $options = [];
49
50 /**
51 * These are the default options of the finisher.
52 * Override them in your concrete implementation.
53 * Default options should not be changed from "outside"
54 *
55 * @var array
56 */
57 protected $defaultOptions = [];
58
59 /**
60 * @var \TYPO3\CMS\Form\Domain\Finishers\FinisherContext
61 */
62 protected $finisherContext;
63
64 /**
65 * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
66 * @internal
67 */
68 public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager)
69 {
70 $this->objectManager = $objectManager;
71 }
72
73 /**
74 * @param array $options configuration options in the format ['option1' => 'value1', 'option2' => 'value2', ...]
75 * @return void
76 * @api
77 */
78 public function setOptions(array $options)
79 {
80 $this->options = $options;
81 }
82
83 /**
84 * Sets a single finisher option (@see setOptions())
85 *
86 * @param string $optionName name of the option to be set
87 * @param mixed $optionValue value of the option
88 * @return void
89 * @api
90 */
91 public function setOption(string $optionName, $optionValue)
92 {
93 $this->options[$optionName] = $optionValue;
94 }
95
96 /**
97 * Executes the finisher
98 *
99 * @param FinisherContext $finisherContext The Finisher context that contains the current Form Runtime and Response
100 * @return void
101 * @api
102 */
103 final public function execute(FinisherContext $finisherContext)
104 {
105 $this->finisherIdentifier = (new \ReflectionClass($this))->getShortName();
106 $this->finisherContext = $finisherContext;
107 $this->executeInternal();
108 }
109
110 /**
111 * This method is called in the concrete finisher whenever self::execute() is called.
112 *
113 * Override and fill with your own implementation!
114 *
115 * @return void
116 * @api
117 */
118 abstract protected function executeInternal();
119
120 /**
121 * Read the option called $optionName from $this->options, and parse {...}
122 * as object accessors.
123 *
124 * Then translate the value.
125 *
126 * If $optionName was not found, the corresponding default option is returned (from $this->defaultOptions)
127 *
128 * @param string $optionName
129 * @return string|array|null
130 * @api
131 */
132 protected function parseOption(string $optionName)
133 {
134 if ($optionName === 'translation') {
135 return null;
136 }
137
138 $optionValue = ArrayUtility::getValueByPath($this->options, $optionName);
139 $defaultValue = ArrayUtility::getValueByPath($this->defaultOptions, $optionName);
140
141 if ($optionValue === null && $defaultValue !== null) {
142 $optionValue = $defaultValue;
143 }
144
145 if ($optionValue === null) {
146 return null;
147 }
148
149 if (is_array($optionValue)) {
150 return $optionValue;
151 }
152
153 $formRuntime = $this->finisherContext->getFormRuntime();
154 $optionToCompare = $optionValue;
155
156 // You can encapsulate a option value with {}.
157 // This enables you to access every getable property from the
158 // TYPO3\CMS\Form\Domain\Runtime.
159 //
160 // For example: {formState.formValues.<elemenIdentifier>}
161 // This is equal to "$formRuntime->getFormState()->getFormValues()[<elemenIdentifier>]"
162 $optionValue = preg_replace_callback('/{([^}]+)}/', function ($match) use ($formRuntime) {
163 return ObjectAccess::getPropertyPath($formRuntime, $match[1]);
164 }, $optionValue);
165
166 if ($optionToCompare === $optionValue) {
167
168 // This is just a shortcut for a {formState.formValues.<elementIdentifier>} notation.
169 // If one of the finisher option values is equal
170 // to a identifier from the form definition then
171 // the value of the submitted form element is used
172 // insteed.
173 // Lets say you have a textfield in your form with the
174 // identifier "Text1". If you put "Text1"
175 // in the email finisher option "subject" then the submited value
176 // from the "Text1" element is used as the email subject.
177 $formValues = $this->finisherContext->getFormValues();
178 if (!is_bool($optionValue) && array_key_exists($optionValue, $formValues)) {
179 $optionValue = $formRuntime[$optionValue];
180 }
181 }
182
183 if (isset($this->options['translation']['translationFile'])) {
184 $optionValue = TranslationService::getInstance()->translateFinisherOption(
185 $formRuntime,
186 $this->finisherIdentifier,
187 $optionName,
188 $optionValue,
189 $this->options['translation']
190 );
191 }
192
193 if (empty($optionValue)) {
194 if ($defaultValue !== null) {
195 $optionValue = $defaultValue;
196 }
197 }
198 return $optionValue;
199 }
200
201 /**
202 * @return TypoScriptFrontendController
203 */
204 protected function getTypoScriptFrontendController()
205 {
206 return $GLOBALS['TSFE'];
207 }
208 }