Skip to content

Commit 9c29c4d

Browse files
committed
Add an attr_merge filter
1 parent 67f2586 commit 9c29c4d

File tree

1 file changed

+74
-56
lines changed

1 file changed

+74
-56
lines changed

extra/html-extra/HtmlExtension.php

Lines changed: 74 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,15 @@ public function getFilters(): array
2929
{
3030
return [
3131
new TwigFilter('data_uri', [$this, 'dataUri']),
32+
new TwigFilter('attr_merge', 'twig_attr_merge'),
3233
];
3334
}
3435

3536
public function getFunctions(): array
3637
{
3738
return [
3839
new TwigFunction('html_classes', 'twig_html_classes'),
39-
new TwigFunction('attr', [$this, 'attr'], ['needs_environment' => true, 'is_safe' => ['html']]),
40+
new TwigFunction('attr', 'twig_attr', ['needs_environment' => true, 'is_safe' => ['html']]),
4041
];
4142
}
4243

@@ -81,65 +82,11 @@ public function dataUri(string $data, string $mime = null, array $parameters = [
8182

8283
return $repr;
8384
}
84-
85-
public function attr(Environment $env, ...$args): string
86-
{
87-
$class = '';
88-
$style = '';
89-
$attr = [];
90-
91-
foreach ($args as $attrs) {
92-
if (!$attrs) {
93-
continue;
94-
}
95-
96-
$attrs = (array) $attrs;
97-
98-
if (isset($attrs['class'])) {
99-
$class .= implode(' ', (array) $attrs['class']) . ' ';
100-
unset($attrs['class']);
101-
}
102-
103-
if (isset($attrs['style'])) {
104-
foreach ((array) $attrs['style'] as $name => $value) {
105-
if (is_numeric($name)) {
106-
$style .= $value . '; ';
107-
} else {
108-
$style .= $name.': '.$value.'; ';
109-
}
110-
}
111-
unset($attrs['style']);
112-
}
113-
114-
if (isset($attrs['data'])) {
115-
foreach ($attrs['data'] as $name => $value) {
116-
$attrs['data-'.$name] = $value;
117-
}
118-
unset($attrs['data']);
119-
}
120-
121-
$attr = array_merge($attr, $attrs);
122-
}
123-
124-
if ($class) {
125-
$attr['class'] = trim($class);
126-
}
127-
128-
if ($style) {
129-
$attr['style'] = trim($style);
130-
}
131-
132-
$result = '';
133-
foreach ($attr as $name => $value) {
134-
$result .= twig_escape_filter($env, $name, 'html_attr').'="'.htmlspecialchars($value).'" ';
135-
}
136-
137-
return trim($result);
138-
}
13985
}
14086
}
14187

14288
namespace {
89+
use Twig\Environment;
14390
use Twig\Error\RuntimeError;
14491

14592
function twig_html_classes(...$args): string
@@ -165,4 +112,75 @@ function twig_html_classes(...$args): string
165112

166113
return implode(' ', array_unique($classes));
167114
}
115+
116+
function twig_attr_merge(...$arrays): array
117+
{
118+
$result = [];
119+
120+
foreach ($arrays as $argNumber => $array) {
121+
if (!$array) {
122+
continue;
123+
}
124+
125+
if (!twig_test_iterable($array)) {
126+
throw new RuntimeError(sprintf('The attr_merge filter only works with arrays or "Traversable", got "%s" for argument %d.', \gettype($array), $argNumber + 1));
127+
}
128+
129+
$array = twig_to_array($array);
130+
131+
foreach (['class', 'style', 'data'] as $deepMergeKey) {
132+
if (isset($array[$deepMergeKey])) {
133+
$value = $array[$deepMergeKey];
134+
unset($array[$deepMergeKey]);
135+
136+
if (!twig_test_iterable($value)) {
137+
$value = (array) $value;
138+
}
139+
140+
$value = twig_to_array($value);
141+
142+
$result[$deepMergeKey] = array_merge($result[$deepMergeKey] ?? [], $value);
143+
}
144+
}
145+
146+
$result = array_merge($result, $array);
147+
}
148+
149+
return $result;
150+
}
151+
152+
function twig_attr(Environment $env, ...$args): string
153+
{
154+
$attr = twig_attr_merge(...$args);
155+
156+
if (isset($attr['class'])) {
157+
$attr['class'] = trim(implode(' ', array_values($attr['class'])));
158+
}
159+
160+
if (isset($attr['style'])) {
161+
$style = '';
162+
foreach ($attr['style'] as $name => $value) {
163+
if (is_numeric($name)) {
164+
$style .= $value.'; ';
165+
} else {
166+
$style .= $name.': '.$value.'; ';
167+
}
168+
}
169+
$attr['style'] = trim($style);
170+
}
171+
172+
if (isset($attr['data'])) {
173+
foreach ($attr['data'] as $name => $value) {
174+
$attr['data-'.$name] = $value;
175+
}
176+
unset($attr['data']);
177+
}
178+
179+
$result = '';
180+
foreach ($attr as $name => $value) {
181+
$result .= twig_escape_filter($env, $name, 'html_attr').'="'.htmlspecialchars($value).'" ';
182+
}
183+
184+
return trim($result);
185+
}
168186
}

0 commit comments

Comments
 (0)