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