Skip to content

Commit 5f516ee

Browse files
committed
feat(2.26.0): Add the ability to spread attributes from the ... attribute
1 parent bc84475 commit 5f516ee

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

src/TwigComponent/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# CHANGELOG
22

3+
## 2.26.0
4+
5+
- Add the ability to spread attributes from the `...` attribute
6+
37
## 2.25.2
48

59
- Fix `ComponentAttributes` rendering when using `StimulusAttributes` as default attributes

src/TwigComponent/src/ComponentAttributes.php

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,22 @@ final class ComponentAttributes implements \Stringable, \IteratorAggregate, \Cou
2626
private const ALPINE_REGEX = '#^x-([a-z]+):[^:]+$#';
2727
private const VUE_REGEX = '#^v-([a-z]+):[^:]+$#';
2828

29+
private const SPREADABLE_ATTRIBUTE = '...';
30+
31+
/** @var array<string, string|bool> */
32+
private array $attributes = [];
33+
2934
/** @var array<string,true> */
3035
private array $rendered = [];
3136

3237
/**
3338
* @param array<string, string|bool> $attributes
3439
*/
3540
public function __construct(
36-
private array $attributes,
41+
array $attributes,
3742
private readonly EscaperRuntime $escaper,
3843
) {
44+
$this->attributes = $this->handleAttributes($attributes);
3945
}
4046

4147
public function __toString(): string
@@ -103,6 +109,31 @@ public function __clone(): void
103109
$this->rendered = [];
104110
}
105111

112+
private function handleAttributes(array $attributes): array
113+
{
114+
$spreadAttributes = $attributes[self::SPREADABLE_ATTRIBUTE] ?? null;
115+
116+
if (!$spreadAttributes) {
117+
return $attributes;
118+
}
119+
120+
if ($spreadAttributes instanceof StimulusAttributes) {
121+
$spreadAttributes = $spreadAttributes->toArray();
122+
}
123+
124+
if ($spreadAttributes instanceof \Traversable) {
125+
$spreadAttributes = iterator_to_array($spreadAttributes);
126+
}
127+
128+
if (!\is_array($spreadAttributes)) {
129+
throw new \InvalidArgumentException(\sprintf('The "%s" attribute must be an array, "%s" given.', self::SPREADABLE_ATTRIBUTE, get_debug_type($spreadAttributes)));
130+
}
131+
132+
unset($attributes[self::SPREADABLE_ATTRIBUTE]);
133+
134+
return [...$attributes, ...$spreadAttributes];
135+
}
136+
106137
public function render(string $attribute): ?string
107138
{
108139
if (null === $value = $this->attributes[$attribute] ?? null) {

src/TwigComponent/src/ComponentFactory.php

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,6 @@ public function mountFromObject(object $component, array $data, ComponentMetadat
113113
$attributes = $data[$attributesVar] ?? [];
114114
unset($data[$attributesVar]);
115115

116-
foreach ($data as $key => $value) {
117-
if ($value instanceof \Stringable) {
118-
$data[$key] = (string) $value;
119-
}
120-
}
121-
122116
return new MountedComponent(
123117
$componentMetadata->getName(),
124118
$component,

0 commit comments

Comments
 (0)