TYPO3 CMS  TYPO3_7-6
FormViewHelper.php
Go to the documentation of this file.
1 <?php
3 
4 /* *
5  * This script is backported from the TYPO3 Flow package "TYPO3.Fluid". *
6  * *
7  * It is free software; you can redistribute it and/or modify it under *
8  * the terms of the GNU General Public License as published by the Free *
9  * Software Foundation, either version 3 of the License, or (at your *
10  * *
11  * *
12  * This script is distributed in the hope that it will be useful, but *
13  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- *
14  * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
15  * Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with the script. *
19  * If not, see http://www.gnu.org/licenses/gpl.html *
20  * *
21  * The TYPO3 project - inspiring people to share! *
22  * */
51 {
55  protected $tagName = 'form';
56 
60  protected $hashService;
61 
66 
70  protected $extensionService;
71 
79 
83  public function injectHashService(\TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService)
84  {
85  $this->hashService = $hashService;
86  }
87 
91  public function injectMvcPropertyMappingConfigurationService(\TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService $mvcPropertyMappingConfigurationService)
92  {
93  $this->mvcPropertyMappingConfigurationService = $mvcPropertyMappingConfigurationService;
94  }
95 
99  public function injectExtensionService(\TYPO3\CMS\Extbase\Service\ExtensionService $extensionService)
100  {
101  $this->extensionService = $extensionService;
102  }
103 
109  public function initializeArguments()
110  {
111  $this->registerTagAttribute('enctype', 'string', 'MIME type with which the form is submitted');
112  $this->registerTagAttribute('method', 'string', 'Transfer type (GET or POST)');
113  $this->registerTagAttribute('name', 'string', 'Name of form');
114  $this->registerTagAttribute('onreset', 'string', 'JavaScript: On reset of the form');
115  $this->registerTagAttribute('onsubmit', 'string', 'JavaScript: On submit of the form');
116  $this->registerTagAttribute('target', 'string', 'Target attribute of the form');
118  }
119 
146  public function render($action = null, array $arguments = [], $controller = null, $extensionName = null, $pluginName = null, $pageUid = null, $object = null, $pageType = 0, $noCache = false, $noCacheHash = false, $section = '', $format = '', array $additionalParams = [], $absolute = false, $addQueryString = false, array $argumentsToBeExcludedFromQueryString = [], $fieldNamePrefix = null, $actionUri = null, $objectName = null, $hiddenFieldClassName = null, $addQueryStringMethod = '')
147  {
148  $this->setFormActionUri();
149  if (strtolower($this->arguments['method']) === 'get') {
150  $this->tag->addAttribute('method', 'get');
151  } else {
152  $this->tag->addAttribute('method', 'post');
153  }
158  $formContent = $this->renderChildren();
159 
160  if ($this->arguments['hiddenFieldClassName'] !== null) {
161  $content = LF . '<div class="' . htmlspecialchars($this->arguments['hiddenFieldClassName']) . '">';
162  } else {
163  $content = LF . '<div>';
164  }
165 
166  $content .= $this->renderHiddenIdentityField($this->arguments['object'], $this->getFormObjectName());
167  $content .= $this->renderAdditionalIdentityFields();
168  $content .= $this->renderHiddenReferrerFields();
169  $content .= $this->renderHiddenSecuredReferrerField();
170 
171  // Render the trusted list of all properties after everything else has been rendered
172  $content .= $this->renderTrustedPropertiesField();
173 
174  $content .= LF . '</div>' . LF;
175  $content .= $formContent;
176  $this->tag->setContent($content);
183  return $this->tag->render();
184  }
185 
191  protected function setFormActionUri()
192  {
193  if ($this->hasArgument('actionUri')) {
194  $formActionUri = $this->arguments['actionUri'];
195  } else {
196  $uriBuilder = $this->controllerContext->getUriBuilder();
197  $pageUid = (int)$this->arguments['pageUid'] > 0 ? (int)$this->arguments['pageUid'] : null;
198  $formActionUri = $uriBuilder
199  ->reset()
200  ->setTargetPageUid($pageUid)
201  ->setTargetPageType($this->arguments['pageType'])
202  ->setNoCache($this->arguments['noCache'])
203  ->setUseCacheHash(!$this->arguments['noCacheHash'])
204  ->setSection($this->arguments['section'])
205  ->setCreateAbsoluteUri($this->arguments['absolute'])
206  ->setArguments((array)$this->arguments['additionalParams'])
207  ->setAddQueryString($this->arguments['addQueryString'])
208  ->setAddQueryStringMethod($this->arguments['addQueryStringMethod'])
209  ->setArgumentsToBeExcludedFromQueryString((array)$this->arguments['argumentsToBeExcludedFromQueryString'])
210  ->setFormat($this->arguments['format'])
211  ->uriFor(
212  $this->arguments['action'],
213  $this->arguments['arguments'],
214  $this->arguments['controller'],
215  $this->arguments['extensionName'],
216  $this->arguments['pluginName']
217  );
218  $this->formActionUriArguments = $uriBuilder->getArguments();
219  }
220  $this->tag->addAttribute('action', $formActionUri);
221  }
222 
229  protected function renderAdditionalIdentityFields()
230  {
231  if ($this->viewHelperVariableContainer->exists(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'additionalIdentityProperties')) {
232  $additionalIdentityProperties = $this->viewHelperVariableContainer->get(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'additionalIdentityProperties');
233  $output = '';
234  foreach ($additionalIdentityProperties as $identity) {
235  $output .= LF . $identity;
236  }
237  return $output;
238  }
239  return '';
240  }
241 
249  protected function renderHiddenReferrerFields()
250  {
251  $request = $this->controllerContext->getRequest();
252  $extensionName = $request->getControllerExtensionName();
253  $vendorName = $request->getControllerVendorName();
254  $controllerName = $request->getControllerName();
255  $actionName = $request->getControllerActionName();
256  $result = LF;
257  $result .= '<input type="hidden" name="' . $this->prefixFieldName('__referrer[@extension]') . '" value="' . $extensionName . '" />' . LF;
258  if ($vendorName !== null) {
259  $result .= '<input type="hidden" name="' . $this->prefixFieldName('__referrer[@vendor]') . '" value="' . $vendorName . '" />' . LF;
260  }
261  $result .= '<input type="hidden" name="' . $this->prefixFieldName('__referrer[@controller]') . '" value="' . $controllerName . '" />' . LF;
262  $result .= '<input type="hidden" name="' . $this->prefixFieldName('__referrer[@action]') . '" value="' . $actionName . '" />' . LF;
263  $result .= '<input type="hidden" name="' . $this->prefixFieldName('__referrer[arguments]') . '" value="' . htmlspecialchars($this->hashService->appendHmac(base64_encode(serialize($request->getArguments())))) . '" />' . LF;
264  $result .= $this->renderHiddenSecuredReferrerField();
265 
266  return $result;
267  }
268 
276  protected function renderHiddenSecuredReferrerField()
277  {
278  if ($this->hasSecuredHiddenFieldsRendered()) {
279  return '';
280  }
281  $request = $this->renderingContext->getControllerContext()->getRequest();
282  $extensionName = $request->getControllerExtensionName();
283  $vendorName = $request->getControllerVendorName();
284  $controllerName = $request->getControllerName();
285  $actionName = $request->getControllerActionName();
286  $actionRequest = [
287  '@extension' => $extensionName,
288  '@controller' => $controllerName,
289  '@action' => $actionName,
290  ];
291  if ($vendorName !== null) {
292  $actionRequest['@vendor'] = $vendorName;
293  }
294  $result = '<input type="hidden" name="' . $this->prefixFieldName('__referrer[@request]') . '" value="' . htmlspecialchars($this->hashService->appendHmac(serialize($actionRequest))) . '" />' . LF;
296  return $result;
297  }
298 
305  {
306  $formObjectName = $this->getFormObjectName();
307  if ($formObjectName !== null) {
308  $this->viewHelperVariableContainer->add(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'formObjectName', $formObjectName);
309  }
310  }
311 
318  {
319  $formObjectName = $this->getFormObjectName();
320  if ($formObjectName !== null) {
321  $this->viewHelperVariableContainer->remove(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'formObjectName');
322  }
323  }
324 
332  protected function getFormObjectName()
333  {
334  $formObjectName = null;
335  if ($this->hasArgument('objectName')) {
336  $formObjectName = $this->arguments['objectName'];
337  } elseif ($this->hasArgument('name')) {
338  $formObjectName = $this->arguments['name'];
339  }
340  return $formObjectName;
341  }
342 
349  {
350  if ($this->hasArgument('object')) {
351  $this->viewHelperVariableContainer->add(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'formObject', $this->arguments['object']);
352  $this->viewHelperVariableContainer->add(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'additionalIdentityProperties', []);
353  }
354  }
355 
362  {
363  if ($this->hasArgument('object')) {
364  $this->viewHelperVariableContainer->remove(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'formObject');
365  $this->viewHelperVariableContainer->remove(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'additionalIdentityProperties');
366  }
367  }
368 
375  {
376  $fieldNamePrefix = $this->getFieldNamePrefix();
377  $this->viewHelperVariableContainer->add(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'fieldNamePrefix', $fieldNamePrefix);
378  }
379 
385  protected function getFieldNamePrefix()
386  {
387  if ($this->hasArgument('fieldNamePrefix')) {
388  return $this->arguments['fieldNamePrefix'];
389  } else {
390  return $this->getDefaultFieldNamePrefix();
391  }
392  }
393 
400  {
401  $this->viewHelperVariableContainer->remove(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'fieldNamePrefix');
402  }
403 
410  {
411  $this->viewHelperVariableContainer->add(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'formFieldNames', []);
412  }
413 
420  {
421  $this->viewHelperVariableContainer->remove(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'formFieldNames');
422  if ($this->viewHelperVariableContainer->exists(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'renderedHiddenFields')) {
423  $this->viewHelperVariableContainer->remove(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'renderedHiddenFields');
424  }
425  }
426 
431  {
432  $this->viewHelperVariableContainer->add(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'securedHiddenFieldsRendered', true);
433  }
434 
440  protected function hasSecuredHiddenFieldsRendered()
441  {
442  return $this->viewHelperVariableContainer->exists(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'securedHiddenFieldsRendered');
443  }
444 
449  {
450  $this->viewHelperVariableContainer->remove(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'securedHiddenFieldsRendered');
451  }
452 
458  protected function renderRequestHashField()
459  {
460  $formFieldNames = $this->viewHelperVariableContainer->get(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'formFieldNames');
461  $this->postProcessUriArgumentsForRequesthash($this->formActionUriArguments, $formFieldNames);
462  $requestHash = $this->requestHashService->generateRequestHash($formFieldNames, $this->getFieldNamePrefix());
463  // in v4, we need to prefix __hmac as well to make it show up in the request object.
464  return '<input type="hidden" name="' . $this->prefixFieldName('__hmac') . '" value="' . htmlspecialchars($requestHash) . '" />';
465  }
466 
470  protected function postProcessUriArgumentsForRequestHash($arguments, &$results, $currentPrefix = '', $level = 0)
471  {
472  if (!count($arguments)) {
473  return;
474  }
475  foreach ($arguments as $argumentName => $argumentValue) {
476  if (is_array($argumentValue)) {
477  $prefix = $level == 0 ? $argumentName : $currentPrefix . '[' . $argumentName . ']';
478  $this->postProcessUriArgumentsForRequestHash($argumentValue, $results, $prefix, $level + 1);
479  } else {
480  $results[] = $level == 0 ? $argumentName : $currentPrefix . '[' . $argumentName . ']';
481  }
482  }
483  }
484 
490  protected function getDefaultFieldNamePrefix()
491  {
492  $request = $this->controllerContext->getRequest();
493  if ($this->hasArgument('extensionName')) {
494  $extensionName = $this->arguments['extensionName'];
495  } else {
496  $extensionName = $request->getControllerExtensionName();
497  }
498  if ($this->hasArgument('pluginName')) {
499  $pluginName = $this->arguments['pluginName'];
500  } else {
501  $pluginName = $request->getPluginName();
502  }
503  if ($extensionName !== null && $pluginName != null) {
504  return $this->extensionService->getPluginNamespace($extensionName, $pluginName);
505  } else {
506  return '';
507  }
508  }
509 
514  {
515  if ($this->viewHelperVariableContainer->exists(\TYPO3\CMS\Fluid\ViewHelpers\Form\CheckboxViewHelper::class, 'checkboxFieldNames')) {
516  $this->viewHelperVariableContainer->remove(\TYPO3\CMS\Fluid\ViewHelpers\Form\CheckboxViewHelper::class, 'checkboxFieldNames');
517  }
518  }
519 
525  protected function renderTrustedPropertiesField()
526  {
527  $formFieldNames = $this->viewHelperVariableContainer->get(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'formFieldNames');
528  $requestHash = $this->mvcPropertyMappingConfigurationService->generateTrustedPropertiesToken($formFieldNames, $this->getFieldNamePrefix());
529  return '<input type="hidden" name="' . $this->prefixFieldName('__trustedProperties') . '" value="' . htmlspecialchars($requestHash) . '" />';
530  }
531 }
injectMvcPropertyMappingConfigurationService(\TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService $mvcPropertyMappingConfigurationService)
registerTagAttribute($name, $type, $description, $required=false, $default=null)
render($action=null, array $arguments=[], $controller=null, $extensionName=null, $pluginName=null, $pageUid=null, $object=null, $pageType=0, $noCache=false, $noCacheHash=false, $section='', $format='', array $additionalParams=[], $absolute=false, $addQueryString=false, array $argumentsToBeExcludedFromQueryString=[], $fieldNamePrefix=null, $actionUri=null, $objectName=null, $hiddenFieldClassName=null, $addQueryStringMethod='')
injectHashService(\TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService)
injectExtensionService(\TYPO3\CMS\Extbase\Service\ExtensionService $extensionService)
postProcessUriArgumentsForRequestHash($arguments, &$results, $currentPrefix='', $level=0)