[TASK] Deprecate extbase StopActionException
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Classes / ViewHelpers / RenderViewHelper.php
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
22 namespace TYPO3\CMS\Form\ViewHelpers;
23
24 use TYPO3\CMS\Core\Http\Response;
25 use TYPO3\CMS\Core\Utility\ArrayUtility;
26 use TYPO3\CMS\Core\Utility\GeneralUtility;
27 use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException;
28 use TYPO3\CMS\Extbase\Object\ObjectManager;
29 use TYPO3\CMS\Form\Domain\Factory\ArrayFormFactory;
30 use TYPO3\CMS\Form\Domain\Factory\FormFactoryInterface;
31 use TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface;
32 use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
33 use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
34 use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
35
36 /**
37 * Main Entry Point to render a Form into a Fluid Template
38 *
39 * Usage
40 * =====
41 *
42 * Default::
43 *
44 * {namespace formvh=TYPO3\CMS\Form\ViewHelpers}
45 * <formvh:render factoryClass="NameOfYourCustomFactoryClass" />
46 *
47 * The factory class must implement :php:`TYPO3\CMS\Form\Domain\Factory\FormFactoryInterface`.
48 *
49 * Scope: frontend
50 */
51 class RenderViewHelper extends AbstractViewHelper
52 {
53 use CompileWithRenderStatic;
54
55 /**
56 * @var bool
57 */
58 protected $escapeOutput = false;
59
60 /**
61 * Initialize the arguments.
62 *
63 * @internal
64 */
65 public function initializeArguments()
66 {
67 $this->registerArgument('persistenceIdentifier', 'string', 'The persistence identifier for the form.', false, null);
68 $this->registerArgument('factoryClass', 'string', 'The fully qualified class name of the factory', false, ArrayFormFactory::class);
69 $this->registerArgument('prototypeName', 'string', 'Name of the prototype to use', false, null);
70 $this->registerArgument('overrideConfiguration', 'array', 'factory specific configuration', false, []);
71 }
72
73 /**
74 * @param array $arguments
75 * @param \Closure $renderChildrenClosure
76 * @param RenderingContextInterface $renderingContext
77 * @return string
78 */
79 public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
80 {
81 $persistenceIdentifier = $arguments['persistenceIdentifier'];
82 $factoryClass = $arguments['factoryClass'];
83 $prototypeName = $arguments['prototypeName'];
84 $overrideConfiguration = $arguments['overrideConfiguration'];
85
86 if (!empty($persistenceIdentifier)) {
87 $formPersistenceManager = GeneralUtility::makeInstance(FormPersistenceManagerInterface::class);
88 $formConfiguration = $formPersistenceManager->load($persistenceIdentifier);
89 ArrayUtility::mergeRecursiveWithOverrule(
90 $formConfiguration,
91 $overrideConfiguration
92 );
93 $overrideConfiguration = $formConfiguration;
94 $overrideConfiguration['persistenceIdentifier'] = $persistenceIdentifier;
95 }
96
97 if (empty($prototypeName)) {
98 $prototypeName = $overrideConfiguration['prototypeName'] ?? 'standard';
99 }
100
101 $objectManager = GeneralUtility::makeInstance(ObjectManager::class);
102 /** @var FormFactoryInterface $factory */
103 $factory = $objectManager->get($factoryClass);
104 $formDefinition = $factory->build($overrideConfiguration, $prototypeName);
105 $response = new Response();
106 $form = $formDefinition->bind($renderingContext->getRequest(), $response);
107
108 // If the controller context does not contain a response object, this viewhelper is used in a
109 // fluid template rendered by the FluidTemplateContentObject. Handle the StopActionException
110 // as there is no extbase dispatcher involved that catches that. */
111 try {
112 return $form->render();
113 } catch (StopActionException $exception) {
114 // @deprecated since v11, will be removed in v12: StopActionException is deprecated, drop this catch block.
115 // RedirectFinisher for throws a PropagateResponseException instead which bubbles up into Middleware.
116 trigger_error(
117 'Throwing StopActionException is deprecated. If really needed, throw a (internal) PropagateResponseException'
118 . ' instead, for now. Note this is subject to change.',
119 E_USER_DEPRECATED
120 );
121 return $exception->getResponse()->getBody()->getContents();
122 }
123 }
124 }