[BUGFIX] EXT:form - exclude hidden fields within summary pages and mails
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Classes / ViewHelpers / RenderAllFormValuesViewHelper.php
1 <?php
2 declare(strict_types=1);
3 namespace TYPO3\CMS\Form\ViewHelpers;
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
20 use TYPO3\CMS\Core\Resource\File;
21 use TYPO3\CMS\Extbase\Domain\Model\FileReference;
22 use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
23 use TYPO3\CMS\Form\Domain\Model\FormElements\FormElementInterface;
24 use TYPO3\CMS\Form\Domain\Model\Renderable\CompositeRenderableInterface;
25 use TYPO3\CMS\Form\Domain\Model\Renderable\RootRenderableInterface;
26 use TYPO3\CMS\Form\Domain\Runtime\FormRuntime;
27 use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
28 use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
29
30 /**
31 * Renders the values of a form
32 *
33 * Scope: frontend
34 * @api
35 */
36 class RenderAllFormValuesViewHelper extends AbstractViewHelper
37 {
38 use CompileWithRenderStatic;
39
40 /**
41 * @var bool
42 */
43 protected $escapeOutput = false;
44
45 /**
46 * Initialize the arguments.
47 *
48 * @internal
49 */
50 public function initializeArguments()
51 {
52 parent::initializeArguments();
53 $this->registerArgument('renderable', RootRenderableInterface::class, 'A RootRenderableInterface instance', true);
54 $this->registerArgument('as', 'string', 'The name within the template', false, 'formValue');
55 }
56
57 /**
58 * Return array element by key.
59 *
60 * @param array $arguments
61 * @param \Closure $renderChildrenClosure
62 * @param RenderingContextInterface $renderingContext
63 * @return string the rendered form values
64 * @api
65 */
66 public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
67 {
68 $renderable = $arguments['renderable'];
69 $as = $arguments['as'];
70
71 if ($renderable instanceof CompositeRenderableInterface) {
72 $elements = $renderable->getRenderablesRecursively();
73 } else {
74 $elements = [$renderable];
75 }
76
77 $formRuntime = $renderingContext
78 ->getViewHelperVariableContainer()
79 ->get(RenderRenderableViewHelper::class, 'formRuntime');
80
81 $output = '';
82 foreach ($elements as $element) {
83 $renderingOptions = $element->getRenderingOptions();
84
85 if (
86 !$element instanceof FormElementInterface
87 || (
88 isset($renderingOptions['_isCompositeFormElement'])
89 && $renderingOptions['_isCompositeFormElement'] === true
90 )
91 || (
92 isset($renderingOptions['_isHiddenFormElement'])
93 && $renderingOptions['_isHiddenFormElement'] === true
94 )
95 ) {
96 continue;
97 }
98 $value = $formRuntime[$element->getIdentifier()];
99
100 $formValue = [
101 'element' => $element,
102 'value' => $value,
103 'processedValue' => self::processElementValue($element, $value, $renderChildrenClosure, $renderingContext),
104 'isMultiValue' => is_array($value) || $value instanceof \Iterator
105 ];
106 $renderingContext->getVariableProvider()->add($as, $formValue);
107 $output .= $renderChildrenClosure();
108 $renderingContext->getVariableProvider()->remove($as);
109 }
110 return $output;
111 }
112
113 /**
114 * Converts the given value to a simple type (string or array) considering the underlying FormElement definition
115 *
116 * @param FormElementInterface $element
117 * @param mixed $value
118 * @param \Closure $renderChildrenClosure
119 * @param RenderingContextInterface $renderingContext
120 * @return mixed
121 */
122 public static function processElementValue(
123 FormElementInterface $element,
124 $value,
125 \Closure $renderChildrenClosure,
126 RenderingContextInterface $renderingContext
127 ) {
128 $properties = $element->getProperties();
129 if (isset($properties['options']) && is_array($properties['options'])) {
130 $properties['options'] = TranslateElementPropertyViewHelper::renderStatic(
131 ['element' => $element, 'property' => 'options'],
132 $renderChildrenClosure,
133 $renderingContext
134 );
135 if (is_array($value)) {
136 return self::mapValuesToOptions($value, $properties['options']);
137 }
138 return self::mapValueToOption($value, $properties['options']);
139 }
140 if (is_object($value)) {
141 return self::processObject($element, $value);
142 }
143 return $value;
144 }
145
146 /**
147 * Replaces the given values (=keys) with the corresponding elements in $options
148 * @see mapValueToOption()
149 *
150 * @param array $value
151 * @param array $options
152 * @return array
153 */
154 public static function mapValuesToOptions(array $value, array $options): array
155 {
156 $result = [];
157 foreach ($value as $key) {
158 $result[] = self::mapValueToOption($key, $options);
159 }
160 return $result;
161 }
162
163 /**
164 * Replaces the given value (=key) with the corresponding element in $options
165 * If the key does not exist in $options, it is returned without modification
166 *
167 * @param mixed $value
168 * @param array $options
169 * @return mixed
170 */
171 public static function mapValueToOption($value, array $options)
172 {
173 return isset($options[$value]) ? $options[$value] : $value;
174 }
175
176 /**
177 * Converts the given $object to a string representation considering the $element FormElement definition
178 *
179 * @param FormElementInterface $element
180 * @param object $object
181 * @return string
182 */
183 public static function processObject(FormElementInterface $element, $object): string
184 {
185 $properties = $element->getProperties();
186 if ($object instanceof \DateTime) {
187 if (isset($properties['dateFormat'])) {
188 $dateFormat = $properties['dateFormat'];
189 if (isset($properties['displayTimeSelector']) && $properties['displayTimeSelector'] === true) {
190 $dateFormat .= ' H:i';
191 }
192 } else {
193 $dateFormat = \DateTime::W3C;
194 }
195 return $object->format($dateFormat);
196 }
197
198 if ($object instanceof File || $object instanceof FileReference) {
199 if ($object instanceof FileReference) {
200 $object = $object->getOriginalResource();
201 }
202 return $object->getName();
203 }
204
205 if (method_exists($object, '__toString')) {
206 return (string)$object;
207 }
208 return 'Object [' . get_class($object) . ']';
209 }
210 }