‪TYPO3CMS  ‪main
AbstractFormFieldViewHelper.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 
19 
27 
37 {
39  protected bool ‪$respectSubmittedDataValue = false;
40 
42  {
43  $this->configurationManager = ‪$configurationManager;
44  }
45 
46  public function ‪initializeArguments(): void
47  {
48  parent::initializeArguments();
49  $this->registerArgument('name', 'string', 'Name of input tag');
50  $this->registerArgument('value', 'mixed', 'Value of input tag');
51  $this->registerArgument(
52  'property',
53  'string',
54  'Name of Object Property. If used in conjunction with <f:form object="...">, the "name" property will be ignored, while "value" can be used to specify a default field value instead of the object property value.'
55  );
56  }
57 
61  public function ‪getRespectSubmittedDataValue(): bool
62  {
64  }
65 
70  {
71  $this->respectSubmittedDataValue = ‪$respectSubmittedDataValue;
72  }
73 
79  protected function ‪getName(): string
80  {
81  $name = $this->‪getNameWithoutPrefix();
82  return $this->‪prefixFieldName($name);
83  }
84 
90  protected function ‪getRequest(): ‪RequestInterface
91  {
93  $renderingContext = $this->renderingContext;
94  $request = $renderingContext->getRequest();
95  if (!$request instanceof ‪RequestInterface) {
96  throw new \RuntimeException(
97  'Form ViewHelpers are Extbase specific and need an Extbase Request to work',
98  1663617170
99  );
100  }
101  return $request;
102  }
103 
107  protected function ‪getNameWithoutPrefix(): string
108  {
109  if ($this->‪isObjectAccessorMode()) {
110  $formObjectName = $this->renderingContext->getViewHelperVariableContainer()->get(
111  FormViewHelper::class,
112  'formObjectName'
113  );
114  if (!empty($formObjectName)) {
115  $propertySegments = explode('.', (string)($this->arguments['property'] ?? ''));
116  $propertyPath = '';
117  foreach ($propertySegments as $segment) {
118  $propertyPath .= '[' . $segment . ']';
119  }
120  $name = $formObjectName . $propertyPath;
121  } else {
122  $name = $this->arguments['property'] ?? '';
123  }
124  } else {
125  $name = $this->arguments['name'] ?? '';
126  }
127  if ($this->hasArgument('value') && is_object($this->arguments['value'])) {
128  // @todo Use $this->persistenceManager->isNewObject() once it is implemented
129  if ($this->persistenceManager->getIdentifierByObject($this->arguments['value']) !== null) {
130  $name .= '[__identity]';
131  }
132  }
133  return (string)$name;
134  }
135 
147  protected function ‪getValueAttribute()
148  {
149  $value = null;
150 
151  if ($this->respectSubmittedDataValue) {
152  $value = $this->‪getValueFromSubmittedFormData($value);
153  } elseif ($this->hasArgument('value')) {
154  $value = $this->arguments['value'];
155  } elseif ($this->‪isObjectAccessorMode()) {
156  $value = $this->‪getPropertyValue();
157  }
158 
159  $value = $this->‪convertToPlainValue($value);
160  return $value;
161  }
162 
175  protected function ‪getValueFromSubmittedFormData($value)
176  {
177  $submittedFormData = null;
178  if ($this->‪hasMappingErrorOccurred()) {
179  $submittedFormData = $this->‪getLastSubmittedFormData();
180  }
181  if ($submittedFormData !== null) {
182  $value = $submittedFormData;
183  } elseif ($this->hasArgument('value')) {
184  $value = $this->arguments['value'];
185  } elseif ($this->‪isObjectAccessorMode()) {
186  $value = $this->‪getPropertyValue();
187  }
188 
189  return $value;
190  }
191 
198  protected function ‪convertToPlainValue($value)
199  {
200  if (is_object($value)) {
201  ‪$identifier = $this->persistenceManager->getIdentifierByObject($value);
202  if (‪$identifier !== null) {
203  $value = ‪$identifier;
204  }
205  }
206  return $value;
207  }
208 
212  protected function ‪hasMappingErrorOccurred(): bool
213  {
215  $extbaseRequestParameters = $this->‪getRequest()->getAttribute('extbase');
216  return $extbaseRequestParameters->getOriginalRequest() !== null;
217  }
218 
225  protected function ‪getLastSubmittedFormData()
226  {
227  $propertyPath = rtrim(preg_replace('/(\\]\\[|\\[|\\])/', '.', $this->‪getNameWithoutPrefix()) ?? '', '.');
229  $extbaseRequestParameters = $this->‪getRequest()->getAttribute('extbase');
231  $extbaseRequestParameters->getOriginalRequest()->getArguments(),
232  $propertyPath
233  );
234  return $value;
235  }
236 
242  {
243  if (!$this->‪isObjectAccessorMode()) {
244  return;
245  }
246 
247  $viewHelperVariableContainer = $this->renderingContext->getViewHelperVariableContainer();
248  if (!$viewHelperVariableContainer->exists(
249  FormViewHelper::class,
250  'formObject'
251  )
252  ) {
253  return;
254  }
255  $propertySegments = explode('.', (string)($this->arguments['property'] ?? ''));
256  // hierarchical property. If there is no "." inside (thus $propertySegments == 1), we do not need to do anything
257  if (count($propertySegments) < 2) {
258  return;
259  }
260  $formObject = $viewHelperVariableContainer->get(
261  FormViewHelper::class,
262  'formObject'
263  );
264  $objectName = $viewHelperVariableContainer->get(
265  FormViewHelper::class,
266  'formObjectName'
267  );
268  // If count == 2 -> we need to go through the for-loop exactly once
269  $propertySegmentsCount = count($propertySegments);
270  for ($i = 1; $i < $propertySegmentsCount; $i++) {
271  $object = ‪ObjectAccess::getPropertyPath($formObject, implode('.', array_slice($propertySegments, 0, $i)));
272  if (!is_object($object)) {
273  $object = null;
274  }
275  $objectName .= '[' . $propertySegments[$i - 1] . ']';
276  $hiddenIdentityField = $this->‪renderHiddenIdentityField($object, $objectName);
277  // Add the hidden identity field to the ViewHelperVariableContainer
278  $additionalIdentityProperties = $viewHelperVariableContainer->get(
279  FormViewHelper::class,
280  'additionalIdentityProperties'
281  );
282  $additionalIdentityProperties[$objectName] = $hiddenIdentityField;
283  $viewHelperVariableContainer->addOrUpdate(
284  FormViewHelper::class,
285  'additionalIdentityProperties',
286  $additionalIdentityProperties
287  );
288  }
289  }
290 
296  protected function ‪getPropertyValue()
297  {
298  if (!isset($this->arguments['property'])) {
299  return null;
300  }
301  $viewHelperVariableContainer = $this->renderingContext->getViewHelperVariableContainer();
302  if (!$viewHelperVariableContainer->exists(
303  FormViewHelper::class,
304  'formObject'
305  )
306  ) {
307  return null;
308  }
309  $formObject = $viewHelperVariableContainer->get(
310  FormViewHelper::class,
311  'formObject'
312  );
313  return ‪ObjectAccess::getPropertyPath($formObject, (string)$this->arguments['property']);
314  }
315 
320  protected function ‪isObjectAccessorMode(): bool
321  {
322  return $this->hasArgument('property') && $this->renderingContext->getViewHelperVariableContainer()->exists(
323  FormViewHelper::class,
324  'formObjectName'
325  );
326  }
327 
331  protected function ‪setErrorClassAttribute(): void
332  {
333  if ($this->hasArgument('class')) {
334  $cssClass = $this->arguments['class'] . ' ';
335  } else {
336  $cssClass = '';
337  }
338 
339  $mappingResultsForProperty = $this->‪getMappingResultsForProperty();
340  if ($mappingResultsForProperty->hasErrors()) {
341  if ($this->hasArgument('errorClass')) {
342  $cssClass .= $this->arguments['errorClass'];
343  } else {
344  $cssClass .= 'error';
345  }
346  $this->tag->addAttribute('class', $cssClass);
347  }
348  }
349 
354  {
355  if (!$this->‪isObjectAccessorMode()) {
356  return new ‪Result();
357  }
359  $extbaseRequestParameters = $this->‪getRequest()->getAttribute('extbase');
360  $originalRequestMappingResults = $extbaseRequestParameters->getOriginalRequestMappingResults();
361  $formObjectName = $this->renderingContext->getViewHelperVariableContainer()->get(
362  FormViewHelper::class,
363  'formObjectName'
364  );
365  return $originalRequestMappingResults->forProperty($formObjectName)->forProperty((string)$this->arguments['property']);
366  }
367 
372  protected function ‪renderHiddenFieldForEmptyValue(): string
373  {
374  $hiddenFieldNames = [];
375  $viewHelperVariableContainer = $this->renderingContext->getViewHelperVariableContainer();
376  if ($viewHelperVariableContainer->exists(
377  FormViewHelper::class,
378  'renderedHiddenFields'
379  )
380  ) {
381  $hiddenFieldNames = $viewHelperVariableContainer->get(
382  FormViewHelper::class,
383  'renderedHiddenFields'
384  );
385  }
386  $fieldName = $this->‪getName();
387  if (substr($fieldName, -2) === '[]') {
388  $fieldName = substr($fieldName, 0, -2);
389  }
390  if (!in_array($fieldName, $hiddenFieldNames, true)) {
391  $hiddenFieldNames[] = $fieldName;
392  $viewHelperVariableContainer->addOrUpdate(
393  FormViewHelper::class,
394  'renderedHiddenFields',
395  $hiddenFieldNames
396  );
397  return '<input type="hidden" name="' . htmlspecialchars($fieldName) . '" value="" />';
398  }
399  return '';
400  }
401 }
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\setErrorClassAttribute
‪setErrorClassAttribute()
Definition: AbstractFormFieldViewHelper.php:331
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\$respectSubmittedDataValue
‪bool $respectSubmittedDataValue
Definition: AbstractFormFieldViewHelper.php:39
‪TYPO3\CMS\Extbase\Reflection\ObjectAccess\getPropertyPath
‪static mixed getPropertyPath(object|array $subject, string $propertyPath)
Definition: ObjectAccess.php:128
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\convertToPlainValue
‪mixed convertToPlainValue($value)
Definition: AbstractFormFieldViewHelper.php:198
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\getMappingResultsForProperty
‪getMappingResultsForProperty()
Definition: AbstractFormFieldViewHelper.php:353
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\getPropertyValue
‪mixed getPropertyValue()
Definition: AbstractFormFieldViewHelper.php:296
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\initializeArguments
‪initializeArguments()
Definition: AbstractFormFieldViewHelper.php:46
‪TYPO3\CMS\Fluid\ViewHelpers\Form
Definition: AbstractFormFieldViewHelper.php:18
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\getLastSubmittedFormData
‪mixed getLastSubmittedFormData()
Definition: AbstractFormFieldViewHelper.php:225
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\injectConfigurationManager
‪injectConfigurationManager(ConfigurationManagerInterface $configurationManager)
Definition: AbstractFormFieldViewHelper.php:41
‪TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
Definition: ConfigurationManagerInterface.php:28
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\getRequest
‪RequestInterface getRequest()
Definition: AbstractFormFieldViewHelper.php:90
‪TYPO3\CMS\Extbase\Error\Result
Definition: Result.php:24
‪TYPO3\CMS\Extbase\Reflection\ObjectAccess
Definition: ObjectAccess.php:39
‪TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper
Definition: FormViewHelper.php:72
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\renderHiddenFieldForEmptyValue
‪renderHiddenFieldForEmptyValue()
Definition: AbstractFormFieldViewHelper.php:372
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\setRespectSubmittedDataValue
‪setRespectSubmittedDataValue(bool $respectSubmittedDataValue)
Definition: AbstractFormFieldViewHelper.php:69
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\$configurationManager
‪ConfigurationManagerInterface $configurationManager
Definition: AbstractFormFieldViewHelper.php:38
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\getNameWithoutPrefix
‪getNameWithoutPrefix()
Definition: AbstractFormFieldViewHelper.php:107
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\getName
‪getName()
Definition: AbstractFormFieldViewHelper.php:79
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormViewHelper\renderHiddenIdentityField
‪string renderHiddenIdentityField(?object $object, ?string $name)
Definition: AbstractFormViewHelper.php:75
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\getRespectSubmittedDataValue
‪getRespectSubmittedDataValue()
Definition: AbstractFormFieldViewHelper.php:61
‪TYPO3\CMS\Extbase\Mvc\RequestInterface
Definition: RequestInterface.php:24
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormViewHelper
Definition: AbstractFormViewHelper.php:35
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\getValueFromSubmittedFormData
‪mixed getValueFromSubmittedFormData($value)
Definition: AbstractFormFieldViewHelper.php:175
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\isObjectAccessorMode
‪isObjectAccessorMode()
Definition: AbstractFormFieldViewHelper.php:320
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper
Definition: AbstractFormFieldViewHelper.php:37
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\hasMappingErrorOccurred
‪hasMappingErrorOccurred()
Definition: AbstractFormFieldViewHelper.php:212
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\addAdditionalIdentityPropertiesIfNeeded
‪addAdditionalIdentityPropertiesIfNeeded()
Definition: AbstractFormFieldViewHelper.php:241
‪TYPO3\CMS\Extbase\Mvc\ExtbaseRequestParameters
Definition: ExtbaseRequestParameters.php:35
‪TYPO3\CMS\Fluid\Core\Rendering\RenderingContext
Definition: RenderingContext.php:35
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormViewHelper\prefixFieldName
‪prefixFieldName(string $fieldName)
Definition: AbstractFormViewHelper.php:46
‪TYPO3\CMS\Webhooks\Message\$identifier
‪identifier readonly string $identifier
Definition: FileAddedMessage.php:37
‪TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper\getValueAttribute
‪mixed getValueAttribute()
Definition: AbstractFormFieldViewHelper.php:147