registerArgument('renderable', RenderableInterface::class, 'A renderable element', true); $this->registerArgument('as', 'string', 'The name within the template', false, 'formValue'); } /** * Return array element by key */ public function render(): string { $element = $this->arguments['renderable']; if (!$element instanceof FormElementInterface || !self::isEnabled($element)) { return ''; } $renderingOptions = $element->getRenderingOptions(); if ($renderingOptions['_isSection'] ?? false) { $data = [ 'element' => $element, 'isSection' => true, ]; } elseif ($renderingOptions['_isCompositeFormElement'] ?? false) { return ''; } else { $formRuntime = $this->renderingContext ->getViewHelperVariableContainer() ->get(RenderRenderableViewHelper::class, 'formRuntime'); $value = $formRuntime[$element->getIdentifier()]; $data = [ 'element' => $element, 'value' => $value, 'processedValue' => $this->processElementValue($element, $value), 'isMultiValue' => is_iterable($value), ]; } $variableProvider = new ScopedVariableProvider($this->renderingContext->getVariableProvider(), new StandardVariableProvider([$this->arguments['as'] => $data])); $this->renderingContext->setVariableProvider($variableProvider); $output = (string)$this->renderChildren(); $this->renderingContext->setVariableProvider($variableProvider->getGlobalVariableProvider()); return $output; } /** * Converts the given value to a simple type (string or array) considering the underlying FormElement definition. * * @param mixed $value * @return mixed */ private function processElementValue( FormElementInterface $element, $value ) { $properties = $element->getProperties(); $options = $properties['options'] ?? null; if ($element->getType() === 'CountrySelect') { $country = $this->countryProvider->getByIsoCode($value ?? ''); if ($country !== null) { return (string)LocalizationUtility::translate($country->getLocalizedNameLabel()); } } if (is_array($options)) { $options = (array)$this->renderingContext->getViewHelperInvoker()->invoke( TranslateElementPropertyViewHelper::class, ['element' => $element, 'property' => 'options'], $this->renderingContext, $this->renderChildren(...), ); if (is_array($value)) { return self::mapValuesToOptions($value, $options); } return self::mapValueToOption($value, $options); } if ($value instanceof ObjectStorage) { $result = []; foreach ($value as $item) { $result[] = is_object($item) ? self::processObject($element, $item) : $item; } return $result; } if (is_object($value)) { return self::processObject($element, $value); } return $value; } /** * Replaces the given values (=keys) with the corresponding elements in $options. * * @see mapValueToOption() */ private static function mapValuesToOptions(array $value, array $options): array { $result = []; foreach ($value as $key) { $result[] = self::mapValueToOption($key, $options); } return $result; } /** * Replaces the given value (=key) with the corresponding element in $options * If the key does not exist in $options, it is returned without modification * * @param mixed $value * @return mixed */ private static function mapValueToOption($value, array $options) { return $options[$value] ?? $value; } /** * Converts the given $object to a string representation considering the $element FormElement definition. * * @param object $object */ private static function processObject(FormElementInterface $element, $object): string { if ($element instanceof StringableFormElementInterface) { return $element->valueToString($object); } if ($object instanceof \DateTime) { return $object->format(\DateTimeInterface::W3C); } if ($object instanceof File || $object instanceof FileReference) { if ($object instanceof FileReference) { $object = $object->getOriginalResource(); } return $object->getName(); } if (method_exists($object, '__toString')) { return (string)$object; } return 'Object [' . get_class($object) . ']'; } private static function isEnabled(RenderableInterface $renderable): bool { if (!$renderable->isEnabled()) { return false; } while ($renderable = $renderable->getParentRenderable()) { if (!$renderable->isEnabled()) { return false; } } return true; } }