Skip to content

Commit b680b5f

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

File tree

1 file changed

+74
-1
lines changed

1 file changed

+74
-1
lines changed

extra/html-extra/HtmlExtension.php

Lines changed: 74 additions & 1 deletion
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

@@ -140,6 +141,7 @@ public function attr(Environment $env, ...$args): string
140141
}
141142

142143
namespace {
144+
use Twig\Environment;
143145
use Twig\Error\RuntimeError;
144146

145147
function twig_html_classes(...$args): string
@@ -165,4 +167,75 @@ function twig_html_classes(...$args): string
165167

166168
return implode(' ', array_unique($classes));
167169
}
170+
171+
function twig_attr_merge(...$arrays): array
172+
{
173+
$result = [];
174+
175+
foreach ($arrays as $argNumber => $array) {
176+
if (!$array) {
177+
continue;
178+
}
179+
180+
if (!twig_test_iterable($array)) {
181+
throw new RuntimeError(sprintf('The attr_merge filter only works with arrays or "Traversable", got "%s" for argument %d.', \gettype($array), $argNumber + 1));
182+
}
183+
184+
$array = twig_to_array($array);
185+
186+
foreach (['class', 'style', 'data'] as $deepMergeKey) {
187+
if (isset($array[$deepMergeKey])) {
188+
$value = $array[$deepMergeKey];
189+
unset($array[$deepMergeKey]);
190+
191+
if (!twig_test_iterable($value)) {
192+
$value = (array) $value;
193+
}
194+
195+
$value = twig_to_array($value);
196+
197+
$result[$deepMergeKey] = array_merge($result[$deepMergeKey] ?? [], $value);
198+
}
199+
}
200+
201+
$result = array_merge($result, $array);
202+
}
203+
204+
return $result;
205+
}
206+
207+
function twig_attr(Environment $env, ...$args): string
208+
{
209+
$attr = twig_attr_merge(...$args);
210+
211+
if (isset($attr['class'])) {
212+
$attr['class'] = trim(implode(' ', array_values($attr['class'])));
213+
}
214+
215+
if (isset($attr['style'])) {
216+
$style = '';
217+
foreach ($attr['style'] as $name => $value) {
218+
if (is_numeric($name)) {
219+
$style .= $value.'; ';
220+
} else {
221+
$style .= $name.': '.$value.'; ';
222+
}
223+
}
224+
$attr['style'] = trim($style);
225+
}
226+
227+
if (isset($attr['data'])) {
228+
foreach ($attr['data'] as $name => $value) {
229+
$attr['data-'.$name] = $value;
230+
}
231+
unset($attr['data']);
232+
}
233+
234+
$result = '';
235+
foreach ($attr as $name => $value) {
236+
$result .= twig_escape_filter($env, $name, 'html_attr').'="'.htmlspecialchars($value).'" ';
237+
}
238+
239+
return trim($result);
240+
}
168241
}

0 commit comments

Comments
 (0)