[TASK] Streamline return tags in phpdocs
[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 originated from the Neos.Form package (www.neos.io)
9 *
10 * It is free software; you can redistribute it and/or modify it under
11 * the terms of the GNU General Public License, either version 2
12 * of the License, or any later version.
13 *
14 * For the full copyright and license information, please read the
15 * LICENSE.txt file that was distributed with this source code.
16 *
17 * The TYPO3 project - inspiring people to share!
18 */
19
20 use TYPO3\CMS\Core\Utility\ArrayUtility;
21 use TYPO3\CMS\Extbase\Reflection\ObjectAccess;
22 use TYPO3\CMS\Form\Service\TranslationService;
23 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
24
25 /**
26 * Finisher base class.
27 *
28 * Scope: frontend
29 * **This class is meant to be sub classed by developers**
30 */
31 abstract class AbstractFinisher implements FinisherInterface
32 {
33
34 /**
35 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
36 */
37 protected $objectManager;
38
39 /**
40 * @var string
41 */
42 protected $finisherIdentifier = '';
43
44 /**
45 * @var string
46 */
47 protected $shortFinisherIdentifier = '';
48
49 /**
50 * The options which have been set from the outside. Instead of directly
51 * accessing them, you should rather use parseOption().
52 *
53 * @var array
54 */
55 protected $options = [];
56
57 /**
58 * These are the default options of the finisher.
59 * Override them in your concrete implementation.
60 * Default options should not be changed from "outside"
61 *
62 * @var array
63 */
64 protected $defaultOptions = [];
65
66 /**
67 * @var \TYPO3\CMS\Form\Domain\Finishers\FinisherContext
68 */
69 protected $finisherContext;
70
71 /**
72 * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
73 * @internal
74 */
75 public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager)
76 {
77 $this->objectManager = $objectManager;
78 }
79
80 /**
81 * @param array $options configuration options in the format ['option1' => 'value1', 'option2' => 'value2', ...]
82 * @api
83 */
84 public function setOptions(array $options)
85 {
86 $this->options = $options;
87 }
88
89 /**
90 * Sets a single finisher option (@see setOptions())
91 *
92 * @param string $optionName name of the option to be set
93 * @param mixed $optionValue value of the option
94 * @api
95 */
96 public function setOption(string $optionName, $optionValue)
97 {
98 $this->options[$optionName] = $optionValue;
99 }
100
101 /**
102 * Executes the finisher
103 *
104 * @param FinisherContext $finisherContext The Finisher context that contains the current Form Runtime and Response
105 * @api
106 */
107 final public function execute(FinisherContext $finisherContext)
108 {
109 $this->finisherIdentifier = (new \ReflectionClass($this))->getShortName();
110 $this->shortFinisherIdentifier = preg_replace('/Finisher$/', '', $this->finisherIdentifier);
111 $this->finisherContext = $finisherContext;
112 $this->executeInternal();
113 }
114
115 /**
116 * This method is called in the concrete finisher whenever self::execute() is called.
117 *
118 * Override and fill with your own implementation!
119 *
120 * @api
121 */
122 abstract protected function executeInternal();
123
124 /**
125 * Read the option called $optionName from $this->options, and parse {...}
126 * as object accessors.
127 *
128 * Then translate the value.
129 *
130 * If $optionName was not found, the corresponding default option is returned (from $this->defaultOptions)
131 *
132 * @param string $optionName
133 * @return string|array|null
134 * @api
135 */
136 protected function parseOption(string $optionName)
137 {
138 if ($optionName === 'translation') {
139 return null;
140 }
141
142 try {
143 $optionValue = ArrayUtility::getValueByPath($this->options, $optionName, '.');
144 } catch (\RuntimeException $exception) {
145 $optionValue = null;
146 }
147 try {
148 $defaultValue = ArrayUtility::getValueByPath($this->defaultOptions, $optionName, '.');
149 } catch (\RuntimeException $exception) {
150 $defaultValue = null;
151 }
152
153 if ($optionValue === null && $defaultValue !== null) {
154 $optionValue = $defaultValue;
155 }
156
157 if ($optionValue === null) {
158 return null;
159 }
160
161 if (is_array($optionValue)) {
162 return $optionValue;
163 }
164
165 $formRuntime = $this->finisherContext->getFormRuntime();
166
167 // You can encapsulate a option value with {}.
168 // This enables you to access every getable property from the
169 // TYPO3\CMS\Form\Domain\Runtime\FormRuntime.
170 //
171 // For example: {formState.formValues.<elemenIdentifier>}
172 // or {<elemenIdentifier>}
173 //
174 // Both examples are equal to "$formRuntime->getFormState()->getFormValues()[<elemenIdentifier>]"
175 // If the value is not a string nothing will be replaced.
176 // There is a special option value '{__currentTimestamp}'.
177 // This will be replaced with the current timestamp.
178 $optionValue = preg_replace_callback('/{([^}]+)}/', function ($match) use ($formRuntime) {
179 if ($match[1] === '__currentTimestamp') {
180 $value = time();
181 } else {
182 // try to resolve the path '{...}' within the FormRuntime
183 $value = ObjectAccess::getPropertyPath($formRuntime, $match[1]);
184 if ($value === null) {
185 // try to resolve the path '{...}' within the FinisherVariableProvider
186 $value = ObjectAccess::getPropertyPath(
187 $this->finisherContext->getFinisherVariableProvider(),
188 $match[1]
189 );
190 }
191 }
192 if (!is_string($value) && !is_int($value)) {
193 $value = '{' . $match[1] . '}';
194 }
195 return $value;
196 }, $optionValue);
197
198 $renderingOptions = is_array($this->options['translation'])
199 ? $this->options['translation']
200 : [];
201
202 $optionValue = TranslationService::getInstance()->translateFinisherOption(
203 $formRuntime,
204 $this->finisherIdentifier,
205 $optionName,
206 $optionValue,
207 $renderingOptions
208 );
209
210 if (empty($optionValue)) {
211 if ($defaultValue !== null) {
212 $optionValue = $defaultValue;
213 }
214 }
215 return $optionValue;
216 }
217
218 /**
219 * @return TypoScriptFrontendController
220 */
221 protected function getTypoScriptFrontendController()
222 {
223 return $GLOBALS['TSFE'];
224 }
225 }