TYPO3 CMS  TYPO3_8-7
AbstractFinisher.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
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 
26 
33 abstract class AbstractFinisher implements FinisherInterface
34 {
35 
39  protected $objectManager;
40 
44  protected $finisherIdentifier = '';
45 
49  protected $shortFinisherIdentifier = '';
50 
57  protected $options = [];
58 
66  protected $defaultOptions = [];
67 
71  protected $finisherContext;
72 
77  public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager)
78  {
79  $this->objectManager = $objectManager;
80  }
81 
85  public function __construct(string $finisherIdentifier = '')
86  {
87  if (empty($finisherIdentifier)) {
88  $this->finisherIdentifier = (new \ReflectionClass($this))->getShortName();
89  } else {
90  $this->finisherIdentifier = $finisherIdentifier;
91  }
92 
93  $this->shortFinisherIdentifier = preg_replace('/Finisher$/', '', $this->finisherIdentifier);
94  }
95 
100  public function setOptions(array $options)
101  {
102  $this->options = $options;
103  }
104 
112  public function setOption(string $optionName, $optionValue)
113  {
114  $this->options[$optionName] = $optionValue;
115  }
116 
124  final public function execute(FinisherContext $finisherContext)
125  {
126  $this->finisherContext = $finisherContext;
127  return $this->executeInternal();
128  }
129 
138  abstract protected function executeInternal();
139 
152  protected function parseOption(string $optionName)
153  {
154  if ($optionName === 'translation') {
155  return null;
156  }
157 
158  try {
159  $optionValue = ArrayUtility::getValueByPath($this->options, $optionName, '.');
160  } catch (\Exception $exception) {
161  $optionValue = null;
162  }
163  try {
164  $defaultValue = ArrayUtility::getValueByPath($this->defaultOptions, $optionName, '.');
165  } catch (\Exception $exception) {
166  $defaultValue = null;
167  }
168 
169  if ($optionValue === null && $defaultValue !== null) {
170  $optionValue = $defaultValue;
171  }
172 
173  if ($optionValue === null) {
174  return null;
175  }
176 
177  if (!is_string($optionValue) && !is_array($optionValue)) {
178  return $optionValue;
179  }
180 
181  $formRuntime = $this->finisherContext->getFormRuntime();
182  $optionValue = $this->substituteRuntimeReferences($optionValue, $formRuntime);
183 
184  if (is_string($optionValue)) {
185  $translationOptions = isset($this->options['translation']) && \is_array($this->options['translation'])
186  ? $this->options['translation']
187  : [];
188 
189  $optionValue = $this->translateFinisherOption(
190  $optionValue,
191  $formRuntime,
192  $optionName,
193  $optionValue,
194  $translationOptions
195  );
196 
197  $optionValue = $this->substituteRuntimeReferences($optionValue, $formRuntime);
198  }
199 
200  if (empty($optionValue)) {
201  if ($defaultValue !== null) {
202  $optionValue = $defaultValue;
203  }
204  }
205  return $optionValue;
206  }
207 
220  protected function translateFinisherOption(
221  $subject,
222  FormRuntime $formRuntime,
223  string $optionName,
224  $optionValue,
225  array $translationOptions
226  ) {
227  if (is_array($subject)) {
228  foreach ($subject as $key => $value) {
229  $subject[$key] = $this->translateFinisherOption(
230  $value,
231  $formRuntime,
232  $optionName . '.' . $value,
233  $value,
234  $translationOptions
235  );
236  }
237  return $subject;
238  }
239 
240  return TranslationService::getInstance()->translateFinisherOption(
241  $formRuntime,
242  $this->finisherIdentifier,
243  $optionName,
244  $optionValue,
245  $translationOptions
246  );
247  }
248 
265  protected function substituteRuntimeReferences($needle, FormRuntime $formRuntime)
266  {
267  // neither array nor string, directly return
268  if (!is_array($needle) && !is_string($needle)) {
269  return $needle;
270  }
271 
272  // resolve (recursively) all array items
273  if (is_array($needle)) {
274  return array_map(
275  function ($item) use ($formRuntime) {
276  return $this->substituteRuntimeReferences($item, $formRuntime);
277  },
278  $needle
279  );
280  }
281 
282  // substitute one(!) variable in string which either could result
283  // again in a string or an array representing multiple values
284  if (preg_match('/^{([^}]+)}$/', $needle, $matches)) {
285  return $this->resolveRuntimeReference(
286  $matches[1],
287  $formRuntime
288  );
289  }
290 
291  // in case string contains more than just one variable or just a static
292  // value that does not need to be substituted at all, candidates are:
293  // * "prefix{variable}suffix
294  // * "{variable-1},{variable-2}"
295  // * "some static value"
296  // * mixed cases of the above
297  return preg_replace_callback(
298  '/{([^}]+)}/',
299  function ($matches) use ($formRuntime) {
300  $value = $this->resolveRuntimeReference(
301  $matches[1],
302  $formRuntime
303  );
304 
305  // substitute each match by returning the resolved value
306  if (!is_array($value)) {
307  return $value;
308  }
309 
310  // now the resolve value is an array that shall substitute
311  // a variable in a string that probably is not the only one
312  // or is wrapped with other static string content (see above)
313  // ... which is just not possible
314  throw new FinisherException(
315  'Cannot convert array to string',
316  1519239265
317  );
318  },
319  $needle
320  );
321  }
322 
330  protected function resolveRuntimeReference(string $property, FormRuntime $formRuntime)
331  {
332  if ($property === '__currentTimestamp') {
333  return time();
334  }
335  // try to resolve the path '{...}' within the FormRuntime
336  $value = ObjectAccess::getPropertyPath($formRuntime, $property);
337  if ($value === null) {
338  // try to resolve the path '{...}' within the FinisherVariableProvider
340  $this->finisherContext->getFinisherVariableProvider(),
341  $property
342  );
343  }
344  if ($value !== null) {
345  return $value;
346  }
347  // in case no value could be resolved
348  return '{' . $property . '}';
349  }
350 
354  protected function getTypoScriptFrontendController()
355  {
356  return $GLOBALS['TSFE'];
357  }
358 }
static getValueByPath(array $array, $path, $delimiter='/')
injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager)
substituteRuntimeReferences($needle, FormRuntime $formRuntime)
setOption(string $optionName, $optionValue)
translateFinisherOption( $subject, FormRuntime $formRuntime, string $optionName, $optionValue, array $translationOptions)
resolveRuntimeReference(string $property, FormRuntime $formRuntime)
static getPropertyPath($subject, $propertyPath)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']