Skip to content

Commit 7445555

Browse files
committed
Check for attributes overlapping with the reserved ones (action, targets), use the same rendering for the reserved and user-defined attributes.
1 parent 69fcf9f commit 7445555

File tree

2 files changed

+41
-8
lines changed

2 files changed

+41
-8
lines changed

src/Turbo/src/Helper/TurboStream.php

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ public static function prepend(string $target, string $html): string
3737
*/
3838
public static function replace(string $target, string $html, bool $morph = false): string
3939
{
40-
return self::custom('replace', $target, $html, $morph ? ['method="morph"'] : []);
40+
return self::custom('replace', $target, $html, $morph ? ['method' => 'morph'] : []);
4141
}
4242

4343
/**
4444
* Updates the content of the element(s) designated by the target CSS selector.
4545
*/
4646
public static function update(string $target, string $html, bool $morph = false): string
4747
{
48-
return self::custom('update', $target, $html, $morph ? ['method="morph"'] : []);
48+
return self::custom('update', $target, $html, $morph ? ['method' => 'morph'] : []);
4949
}
5050

5151
/**
@@ -87,17 +87,32 @@ public static function refresh(?string $requestId = null): string
8787
}
8888

8989
/**
90-
* @param array<string> $attr
90+
* Custom action and attributes
91+
* @param array<string, string|int|null> $attr
9192
*/
9293
public static function custom(string $action, string $target, string $html, array $attr = []): string
9394
{
94-
// Join array elements with a space and prepend a leading space
95-
$atrrString = empty($attr) ? '' : ' '.implode(' ', $attr);
95+
if (array_key_exists('action', $attr) || array_key_exists('targets', $attr)) {
96+
throw new \InvalidArgumentException('The "action" and "targets" attributes are reserved and cannot be used.');
97+
}
98+
99+
$attr['action'] = $action;
100+
$attr['targets'] = $target;
101+
$attr = array_merge(['action' => $action, 'targets' => $target], $attr);
102+
103+
$attrString = '';
104+
foreach ($attr as $key => $value) {
105+
if ($value === null) {
106+
$attrString .= sprintf(' %s', $key);
107+
}else{
108+
$attrString .= sprintf(' %s="%s"', $key, htmlspecialchars($value));
109+
}
110+
}
96111

97112
return \sprintf(<<<EOHTML
98-
<turbo-stream action="%s" targets="%s"%s>
113+
<turbo-stream%s>
99114
<template>%s</template>
100115
</turbo-stream>
101-
EOHTML, $action, htmlspecialchars($target), $atrrString, $html);
116+
EOHTML, $attrString, $html);
102117
}
103118
}

src/Turbo/tests/Helper/TurboStreamTest.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\UX\Turbo\Tests\Helper;
1313

14+
use PHPUnit\Framework\Attributes\DataProvider;
15+
use PHPUnit\Framework\Attributes\TestWith;
1416
use PHPUnit\Framework\TestCase;
1517
use Symfony\UX\Turbo\Helper\TurboStream;
1618

@@ -84,7 +86,23 @@ public function testCustom(): void
8486
<template><div>content</div></template>
8587
</turbo-stream>
8688
EOHTML,
87-
TurboStream::custom('customAction', 'some["selector"]', '<div>content</div>', ['someAttr="someValue"', 'boolAttr'])
89+
TurboStream::custom('customAction', 'some["selector"]', '<div>content</div>', ['someAttr' => 'someValue', 'boolAttr' => null])
8890
);
8991
}
92+
93+
/**
94+
* @dataProvider customThrowsExceptionDataProvider
95+
* @param array<string, string|int|null> $attr
96+
*/
97+
public function testCustomThrowsException(string $action, string $target, string $html, array $attr): void
98+
{
99+
$this->expectException(\InvalidArgumentException::class);
100+
TurboStream::custom($action, $target, $html, $attr);
101+
}
102+
103+
public static function customThrowsExceptionDataProvider(): \Generator
104+
{
105+
yield ['customAction', 'some["selector"]', '<div>content</div>', ['action' => 'someAction']];
106+
yield ['customAction', 'some["selector"]', '<div>content</div>', ['targets' => 'someTargets']];
107+
}
90108
}

0 commit comments

Comments
 (0)