‪TYPO3CMS  10.4
AbstractFinisher.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
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 /*
19  * Inspired by and partially taken from the Neos.Form package (www.neos.io)
20  */
21 
23 
33 
40 abstract class ‪AbstractFinisher implements ‪FinisherInterface
41 {
42 
46  protected ‪$objectManager;
47 
51  protected ‪$finisherIdentifier = '';
52 
56  protected ‪$shortFinisherIdentifier = '';
57 
64  protected ‪$options = [];
65 
73  protected ‪$defaultOptions = [];
74 
79 
85  {
86  $this->objectManager = ‪$objectManager;
87  }
88 
92  public function ‪__construct(string ‪$finisherIdentifier = '')
93  {
94  if (empty(‪$finisherIdentifier)) {
95  $this->finisherIdentifier = (new \ReflectionClass($this))->getShortName();
96  } else {
97  $this->finisherIdentifier = ‪$finisherIdentifier;
98  }
99 
100  $this->shortFinisherIdentifier = preg_replace('/Finisher$/', '', $this->finisherIdentifier);
101  }
102 
106  public function ‪getFinisherIdentifier(): string
107  {
109  }
110 
114  public function ‪setOptions(array ‪$options)
115  {
116  $this->options = ‪$options;
117  }
118 
125  public function ‪setOption(string $optionName, $optionValue)
126  {
127  $this->options[$optionName] = $optionValue;
128  }
129 
136  final public function ‪execute(FinisherContext ‪$finisherContext)
137  {
138  $this->finisherContext = ‪$finisherContext;
139 
140  if (!$this->‪isEnabled()) {
141  return null;
142  }
143 
144  return $this->‪executeInternal();
145  }
146 
154  abstract protected function ‪executeInternal();
155 
167  protected function ‪parseOption(string $optionName)
168  {
169  if ($optionName === 'translation') {
170  return null;
171  }
172 
173  try {
174  $optionValue = ‪ArrayUtility::getValueByPath($this->options, $optionName, '.');
175  } catch (MissingArrayPathException $exception) {
176  $optionValue = null;
177  }
178  try {
179  $defaultValue = ‪ArrayUtility::getValueByPath($this->defaultOptions, $optionName, '.');
180  } catch (MissingArrayPathException $exception) {
181  $defaultValue = null;
182  }
183 
184  if ($optionValue === null && $defaultValue !== null) {
185  $optionValue = $defaultValue;
186  }
187 
188  if ($optionValue === null) {
189  return null;
190  }
191 
192  if (!is_string($optionValue) && !is_array($optionValue)) {
193  return $optionValue;
194  }
195 
196  $formRuntime = $this->finisherContext->getFormRuntime();
197  $optionValue = $this->‪substituteRuntimeReferences($optionValue, $formRuntime);
198 
199  if (is_string($optionValue)) {
200  $translationOptions = isset($this->options['translation']) && \is_array($this->options['translation'])
201  ? $this->options['translation']
202  : [];
203 
204  $optionValue = $this->‪translateFinisherOption(
205  $optionValue,
206  $formRuntime,
207  $optionName,
208  $optionValue,
209  $translationOptions
210  );
211 
212  $optionValue = $this->‪substituteRuntimeReferences($optionValue, $formRuntime);
213  }
214 
215  if (empty($optionValue)) {
216  if ($defaultValue !== null) {
217  $optionValue = $defaultValue;
218  }
219  }
220  return $optionValue;
221  }
222 
235  protected function ‪translateFinisherOption(
236  $subject,
237  FormRuntime $formRuntime,
238  string $optionName,
239  $optionValue,
240  array $translationOptions
241  ) {
242  if (is_array($subject)) {
243  foreach ($subject as $key => $value) {
244  $subject[$key] = $this->‪translateFinisherOption(
245  $value,
246  $formRuntime,
247  $optionName . '.' . $value,
248  $value,
249  $translationOptions
250  );
251  }
252  return $subject;
253  }
254 
256  $formRuntime,
257  $this->finisherIdentifier,
258  $optionName,
259  $optionValue,
260  $translationOptions
261  );
262  }
263 
280  protected function ‪substituteRuntimeReferences($needle, FormRuntime $formRuntime)
281  {
282  // neither array nor string, directly return
283  if (!is_array($needle) && !is_string($needle)) {
284  return $needle;
285  }
286 
287  // resolve (recursively) all array items
288  if (is_array($needle)) {
289  $substitutedNeedle = [];
290  foreach ($needle as $key => $item) {
291  $key = $this->‪substituteRuntimeReferences($key, $formRuntime);
292  $item = $this->‪substituteRuntimeReferences($item, $formRuntime);
293  $substitutedNeedle[$key] = $item;
294  }
295  return $substitutedNeedle;
296  }
297 
298  // substitute one(!) variable in string which either could result
299  // again in a string or an array representing multiple values
300  if (preg_match('/^{([^}]+)}$/', $needle, $matches)) {
301  return $this->‪resolveRuntimeReference(
302  $matches[1],
303  $formRuntime
304  );
305  }
306 
307  // in case string contains more than just one variable or just a static
308  // value that does not need to be substituted at all, candidates are:
309  // * "prefix{variable}suffix
310  // * "{variable-1},{variable-2}"
311  // * "some static value"
312  // * mixed cases of the above
313  return preg_replace_callback(
314  '/{([^}]+)}/',
315  function ($matches) use ($formRuntime) {
316  $value = $this->‪resolveRuntimeReference(
317  $matches[1],
318  $formRuntime
319  );
320 
321  // substitute each match by returning the resolved value
322  if (!is_array($value)) {
323  return $value;
324  }
325 
326  // now the resolve value is an array that shall substitute
327  // a variable in a string that probably is not the only one
328  // or is wrapped with other static string content (see above)
329  // ... which is just not possible
330  throw new FinisherException(
331  'Cannot convert array to string',
332  1519239265
333  );
334  },
335  $needle
336  );
337  }
338 
346  protected function ‪resolveRuntimeReference(string $property, FormRuntime $formRuntime)
347  {
348  if ($property === '__currentTimestamp') {
349  return time();
350  }
351 
352  // try to resolve the path '{...}' within the FormRuntime
353  $value = ‪ObjectAccess::getPropertyPath($formRuntime, $property);
354 
355  if (is_object($value)) {
356  $element = $formRuntime->getFormDefinition()->getElementByIdentifier($property);
357 
358  if (!$element instanceof StringableFormElementInterface) {
359  throw new FinisherException(
360  sprintf('Cannot convert object value of "%s" to string', $property),
361  1574362327
362  );
363  }
364 
365  $value = $element->valueToString($value);
366  }
367 
368  if ($value === null) {
369  // try to resolve the path '{...}' within the FinisherVariableProvider
371  $this->finisherContext->getFinisherVariableProvider(),
372  $property
373  );
374  }
375 
376  if ($value !== null) {
377  return $value;
378  }
379 
380  // in case no value could be resolved
381  return '{' . $property . '}';
382  }
383 
389  public function ‪isEnabled(): bool
390  {
391  return !isset($this->options['renderingOptions']['enabled']) || (bool)$this->‪parseOption('renderingOptions.enabled') === true;
392  }
393 
397  protected function ‪getTypoScriptFrontendController()
398  {
399  return ‪$GLOBALS['TSFE'];
400  }
401 }
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\$finisherIdentifier
‪string $finisherIdentifier
Definition: AbstractFinisher.php:49
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime
Definition: FormRuntime.php:103
‪TYPO3\CMS\Form\Service\TranslationService\getInstance
‪static TranslationService getInstance()
Definition: TranslationService.php:83
‪TYPO3\CMS\Form\Domain\Finishers\FinisherInterface
Definition: FinisherInterface.php:31
‪TYPO3\CMS\Form\Service\TranslationService
Definition: TranslationService.php:44
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\getFinisherIdentifier
‪string getFinisherIdentifier()
Definition: AbstractFinisher.php:100
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\translateFinisherOption
‪array string translateFinisherOption( $subject, FormRuntime $formRuntime, string $optionName, $optionValue, array $translationOptions)
Definition: AbstractFinisher.php:229
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\substituteRuntimeReferences
‪mixed substituteRuntimeReferences($needle, FormRuntime $formRuntime)
Definition: AbstractFinisher.php:274
‪TYPO3\CMS\Core\Utility\Exception\MissingArrayPathException
Definition: MissingArrayPathException.php:28
‪TYPO3\CMS\Form\Service\TranslationService\translateFinisherOption
‪string translateFinisherOption(FormRuntime $formRuntime, string $finisherIdentifier, string $optionKey, string $optionValue, array $renderingOptions=[])
Definition: TranslationService.php:242
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\$objectManager
‪TYPO3 CMS Extbase Object ObjectManagerInterface $objectManager
Definition: AbstractFinisher.php:45
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\injectObjectManager
‪injectObjectManager(ObjectManagerInterface $objectManager)
Definition: AbstractFinisher.php:78
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\isEnabled
‪bool isEnabled()
Definition: AbstractFinisher.php:383
‪TYPO3\CMS\Form\Domain\Model\FormDefinition\getElementByIdentifier
‪FormElementInterface getElementByIdentifier(string $elementIdentifier)
Definition: FormDefinition.php:571
‪TYPO3\CMS\Form\Domain\Finishers
Definition: AbstractFinisher.php:22
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\$finisherContext
‪TYPO3 CMS Form Domain Finishers FinisherContext $finisherContext
Definition: AbstractFinisher.php:72
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\__construct
‪__construct(string $finisherIdentifier='')
Definition: AbstractFinisher.php:86
‪TYPO3\CMS\Extbase\Reflection\ObjectAccess
Definition: ObjectAccess.php:38
‪TYPO3\CMS\Extbase\Object\ObjectManagerInterface
Definition: ObjectManagerInterface.php:26
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\setOptions
‪setOptions(array $options)
Definition: AbstractFinisher.php:108
‪TYPO3\CMS\Core\Utility\ArrayUtility\getValueByPath
‪static mixed getValueByPath(array $array, $path, $delimiter='/')
Definition: ArrayUtility.php:180
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher
Definition: AbstractFinisher.php:41
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\$shortFinisherIdentifier
‪string $shortFinisherIdentifier
Definition: AbstractFinisher.php:53
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\resolveRuntimeReference
‪int string array resolveRuntimeReference(string $property, FormRuntime $formRuntime)
Definition: AbstractFinisher.php:340
‪TYPO3\CMS\Form\Domain\Finishers\Exception\FinisherException
Definition: FinisherException.php:26
‪TYPO3\CMS\Form\Domain\Model\FormElements\StringableFormElementInterface
Definition: StringableFormElementInterface.php:30
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\$options
‪array $options
Definition: AbstractFinisher.php:60
‪TYPO3\CMS\Form\Domain\Finishers\FinisherContext
Definition: FinisherContext.php:37
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
Definition: TypoScriptFrontendController.php:98
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime
Definition: FormSession.php:18
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:24
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\execute
‪string null execute(FinisherContext $finisherContext)
Definition: AbstractFinisher.php:130
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getFormDefinition
‪FormDefinition getFormDefinition()
Definition: FormRuntime.php:1066
‪TYPO3\CMS\Extbase\Reflection\ObjectAccess\getPropertyPath
‪static mixed getPropertyPath($subject, string $propertyPath)
Definition: ObjectAccess.php:139
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\setOption
‪setOption(string $optionName, $optionValue)
Definition: AbstractFinisher.php:119
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\parseOption
‪string array null parseOption(string $optionName)
Definition: AbstractFinisher.php:161
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\$defaultOptions
‪array $defaultOptions
Definition: AbstractFinisher.php:68
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\executeInternal
‪string null executeInternal()
‪TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher\getTypoScriptFrontendController
‪TypoScriptFrontendController getTypoScriptFrontendController()
Definition: AbstractFinisher.php:391