';
/** @var string Templates for the open/close/separators for message tags */
protected $messageCloseString = '';
/** @var string Templates for the open/close/separators for message tags */
protected $messageSeparatorString = '';
/** @var array Default attributes for the open format tag */
protected $attributes = [];
/** @var bool Whether or not to translate error messages during render. */
protected $translateErrorMessages = true;
/**
* Invoke helper as functor
*
* Proxies to {@link render()} if an element is passed.
*
* @template T as null|ElementInterface
* @psalm-param T $element
* @psalm-return (T is null ? self : string)
* @param array $attributes
* @return string|FormElementErrors
*/
public function __invoke(?ElementInterface $element = null, array $attributes = [])
{
if (! $element) {
return $this;
}
return $this->render($element, $attributes);
}
/**
* Render validation errors for the provided $element
*
* If {@link $translateErrorMessages} is true, and a translator is
* composed, messages retrieved from the element will be translated; if
* either is not the case, they will not.
*
* @param array $attributes
* @throws Exception\DomainException
*/
public function render(ElementInterface $element, array $attributes = []): string
{
$messages = $element->getMessages();
if (! $messages) {
return '';
}
// Flatten message array
$messages = $this->flattenMessages($messages);
if (! $messages) {
return '';
}
// Prepare attributes for opening tag
$attributes = array_merge($this->attributes, $attributes);
$attributes = $this->createAttributesString($attributes);
if (! empty($attributes)) {
$attributes = ' ' . $attributes;
}
$count = count($messages);
$escaper = $this->getEscapeHtmlHelper();
for ($i = 0; $i < $count; $i += 1) {
$messages[$i] = $escaper($messages[$i]);
}
// Generate markup
$markup = sprintf($this->getMessageOpenFormat(), $attributes);
$markup .= implode($this->getMessageSeparatorString(), $messages);
$markup .= $this->getMessageCloseString();
return $markup;
}
/**
* Set the attributes that will go on the message open format
*
* @param array $attributes key value pairs of attributes
* @return $this
*/
public function setAttributes(array $attributes)
{
$this->attributes = $attributes;
return $this;
}
/**
* Get the attributes that will go on the message open format
*
* @return array
*/
public function getAttributes(): array
{
return $this->attributes;
}
/**
* Set the string used to close message representation
*
* @return $this
*/
public function setMessageCloseString(string $messageCloseString)
{
$this->messageCloseString = $messageCloseString;
return $this;
}
/**
* Get the string used to close message representation
*/
public function getMessageCloseString(): string
{
return $this->messageCloseString;
}
/**
* Set the formatted string used to open message representation
*
* @return $this
*/
public function setMessageOpenFormat(string $messageOpenFormat)
{
$this->messageOpenFormat = $messageOpenFormat;
return $this;
}
/**
* Get the formatted string used to open message representation
*/
public function getMessageOpenFormat(): string
{
return $this->messageOpenFormat;
}
/**
* Set the string used to separate messages
*
* @return $this
*/
public function setMessageSeparatorString(string $messageSeparatorString)
{
$this->messageSeparatorString = $messageSeparatorString;
return $this;
}
/**
* Get the string used to separate messages
*/
public function getMessageSeparatorString(): string
{
return $this->messageSeparatorString;
}
/**
* Set the flag detailing whether or not to translate error messages.
*
* @return $this
*/
public function setTranslateMessages(bool $flag)
{
$this->translateErrorMessages = $flag;
return $this;
}
/**
* @param array $messages
* @return array
*/
private function flattenMessages(array $messages): array
{
return $this->translateErrorMessages && $this->getTranslator()
? $this->flattenMessagesWithTranslator($messages)
: $this->flattenMessagesWithoutTranslator($messages);
}
/**
* @param array $messages
* @return array
*/
private function flattenMessagesWithoutTranslator(array $messages): array
{
$messagesToPrint = [];
array_walk_recursive($messages, static function (string $item) use (&$messagesToPrint): void {
$messagesToPrint[] = $item;
});
return $messagesToPrint;
}
/**
* @param array $messages
* @return array
*/
private function flattenMessagesWithTranslator(array $messages): array
{
$translator = $this->getTranslator();
$textDomain = $this->getTranslatorTextDomain();
$messagesToPrint = [];
$messageCallback = static function ($item) use (&$messagesToPrint, $translator, $textDomain): void {
$messagesToPrint[] = $translator->translate($item, $textDomain);
};
array_walk_recursive($messages, $messageCallback);
return $messagesToPrint;
}
}