Skip to content

Commit 8334195

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

File tree

3 files changed

+38
-8
lines changed

3 files changed

+38
-8
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: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,23 @@ 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,
38-
) {
43+
)
44+
{
45+
$this->attributes = $this->handleAttributes($attributes);
3946
}
4047

4148
public function __toString(): string
@@ -103,6 +110,31 @@ public function __clone(): void
103110
$this->rendered = [];
104111
}
105112

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