a302e04a40694042cdc71b0ebeebc370031c4822
[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 || $element->getType() === 'Honeypot'
88 || (
89 isset($renderingOptions['_isCompositeFormElement'])
90 && $renderingOptions['_isCompositeFormElement'] = true
91 )
92 ) {
93 continue;
94 }
95 $value = $formRuntime[$element->getIdentifier()];
96
97 $formValue = [
98 'element' => $element,
99 'value' => $value,
100 'processedValue' => self::processElementValue($element, $value, $renderChildrenClosure, $renderingContext),
101 'isMultiValue' => is_array($value) || $value instanceof \Iterator
102 ];
103 $renderingContext->getVariableProvider()->add($as, $formValue);
104 $output .= $renderChildrenClosure();
105 $renderingContext->getVariableProvider()->remove($as);
106 }
107 return $output;
108 }
109
110 /**
111 * Converts the given value to a simple type (string or array) considering the underlying FormElement definition
112 *
113 * @param FormElementInterface $element
114 * @param mixed $value
115 * @param \Closure $renderChildrenClosure
116 * @param RenderingContextInterface $renderingContext
117 * @return mixed
118 */
119 public static function processElementValue(
120 FormElementInterface $element,
121 $value,
122 \Closure $renderChildrenClosure,
123 RenderingContextInterface $renderingContext
124 ) {
125 $properties = $element->getProperties();
126 if (isset($properties['options']) && is_array($properties['options'])) {
127 $properties['options'] = TranslateElementPropertyViewHelper::renderStatic(
128 ['element' => $element, 'property' => 'options'],
129 $renderChildrenClosure,
130 $renderingContext
131 );
132 if (is_array($value)) {
133 return self::mapValuesToOptions($value, $properties['options']);
134 } else {
135 return self::mapValueToOption($value, $properties['options']);
136 }
137 }
138 if (is_object($value)) {
139 return self::processObject($element, $value);
140 }
141 return $value;
142 }
143
144 /**
145 * Replaces the given values (=keys) with the corresponding elements in $options
146 * @see mapValueToOption()
147 *
148 * @param array $value
149 * @param array $options
150 * @return array
151 */
152 public static function mapValuesToOptions(array $value, array $options): array
153 {
154 $result = [];
155 foreach ($value as $key) {
156 $result[] = self::mapValueToOption($key, $options);
157 }
158 return $result;
159 }
160
161 /**
162 * Replaces the given value (=key) with the corresponding element in $options
163 * If the key does not exist in $options, it is returned without modification
164 *
165 * @param mixed $value
166 * @param array $options
167 * @return mixed
168 */
169 public static function mapValueToOption($value, array $options)
170 {
171 return isset($options[$value]) ? $options[$value] : $value;
172 }
173
174 /**
175 * Converts the given $object to a string representation considering the $element FormElement definition
176 *
177 * @param FormElementInterface $element
178 * @param object $object
179 * @return string
180 */
181 public static function processObject(FormElementInterface $element, $object): string
182 {
183 $properties = $element->getProperties();
184 if ($object instanceof \DateTime) {
185 if (isset($properties['dateFormat'])) {
186 $dateFormat = $properties['dateFormat'];
187 if (isset($properties['displayTimeSelector']) && $properties['displayTimeSelector'] === true) {
188 $dateFormat .= ' H:i';
189 }
190 } else {
191 $dateFormat = \DateTime::W3C;
192 }
193 return $object->format($dateFormat);
194 }
195
196 if ($object instanceof File || $object instanceof FileReference) {
197 if ($object instanceof FileReference) {
198 $object = $object->getOriginalResource();
199 }
200 return $object->getName();
201 }
202
203 if (method_exists($object, '__toString')) {
204 return (string)$object;
205 }
206 return 'Object [' . get_class($object) . ']';
207 }
208 }