diff --git a/extra/html-extra/HtmlExtension.php b/extra/html-extra/HtmlExtension.php index ed740b47187..658fc64a161 100644 --- a/extra/html-extra/HtmlExtension.php +++ b/extra/html-extra/HtmlExtension.php @@ -11,6 +11,7 @@ namespace Twig\Extra\Html { use Symfony\Component\Mime\MimeTypes; +use Twig\Environment; use Twig\Extension\AbstractExtension; use Twig\TwigFilter; use Twig\TwigFunction; @@ -35,6 +36,7 @@ public function getFunctions(): array { return [ new TwigFunction('html_classes', 'twig_html_classes'), + new TwigFunction('attr', [$this, 'attr'], ['needs_environment' => true, 'is_safe' => ['html']]), ]; } @@ -79,6 +81,61 @@ public function dataUri(string $data, string $mime = null, array $parameters = [ return $repr; } + + public function attr(Environment $env, ...$args): string + { + $class = ''; + $style = ''; + $attr = []; + + foreach ($args as $attrs) { + if (!$attrs) { + continue; + } + + $attrs = (array) $attrs; + + if (isset($attrs['class'])) { + $class .= implode(' ', (array) $attrs['class']) . ' '; + unset($attrs['class']); + } + + if (isset($attrs['style'])) { + foreach ((array) $attrs['style'] as $name => $value) { + if (is_numeric($name)) { + $style .= $value . '; '; + } else { + $style .= $name.': '.$value.'; '; + } + } + unset($attrs['style']); + } + + if (isset($attrs['data'])) { + foreach ($attrs['data'] as $name => $value) { + $attrs['data-'.$name] = $value; + } + unset($attrs['data']); + } + + $attr = array_merge($attr, $attrs); + } + + if ($class) { + $attr['class'] = trim($class); + } + + if ($style) { + $attr['style'] = trim($style); + } + + $result = ''; + foreach ($attr as $name => $value) { + $result .= twig_escape_filter($env, $name, 'html_attr').'="'.htmlspecialchars($value).'" '; + } + + return trim($result); + } } }