Skip to content

Commit

Permalink
Custom action support
Browse files Browse the repository at this point in the history
  • Loading branch information
DRaichev committed Oct 30, 2024
1 parent 01839ab commit bb8aeed
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 2 deletions.
37 changes: 35 additions & 2 deletions src/Turbo/src/Helper/TurboStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,45 @@ public static function refresh(?string $requestId = null): string
return \sprintf('<turbo-stream action="refresh" request-id="%s"></turbo-stream>', htmlspecialchars($requestId));
}

/**
* Custom action and attributes.
* When passing attributes use null value to for boolean attributes (e.g. disabled).
*
* @param array<string, string|int|float|null> $attr
*/
public static function custom(string $action, string $target, string $html, array $attr = []): string
{
if (\array_key_exists('action', $attr) || \array_key_exists('targets', $attr)) {
throw new \InvalidArgumentException('The "action" and "targets" attributes are reserved and cannot be used.');
}

$attrString = '';
foreach ($attr as $key => $value) {
$key = htmlspecialchars($key);
if (null === $value) {
$attrString .= \sprintf(' %s', $key);
} elseif (\is_int($value) || \is_float($value)) {
$attrString .= \sprintf(' %s="%s"', $key, $value);
} else {
$attrString .= \sprintf(' %s="%s"', $key, htmlspecialchars($value));
}
}

return self::wrap(htmlspecialchars($action), $target, $html, $attrString);
}

private static function wrap(string $action, string $target, string $html, string $attr = ''): string
{
return \sprintf(<<<EOHTML
return \sprintf(
<<<EOHTML
<turbo-stream action="%s" targets="%s"%s>
<template>%s</template>
</turbo-stream>
EOHTML, $action, htmlspecialchars($target), $attr, $html);
EOHTML,
$action,
htmlspecialchars($target),
$attr,
$html
);
}
}
12 changes: 12 additions & 0 deletions src/Turbo/src/TurboStreamResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,16 @@ public function refresh(?string $requestId = null): static

return $this;
}

/**
* @param array<string, string|int|float|null> $attr
*
* @return $this
*/
public function action(string $action, string $target, string $html, array $attr = []): static
{
$this->setContent($this->getContent().TurboStream::custom($action, $target, $html, $attr));

return $this;
}
}
28 changes: 28 additions & 0 deletions src/Turbo/tests/Helper/TurboStreamTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,32 @@ public function testRefreshWithId(): void
TurboStream::refresh('a"b')
);
}

public function testCustom(): void
{
$this->assertSame(<<<EOHTML
<turbo-stream action="customAction" targets="some[&quot;selector&quot;]" someAttr="someValue" boolAttr intAttr="0" floatAttr="3.14">
<template><div>content</div></template>
</turbo-stream>
EOHTML,
TurboStream::custom('customAction', 'some["selector"]', '<div>content</div>', ['someAttr' => 'someValue', 'boolAttr' => null, 'intAttr' => 0, 'floatAttr' => 3.14])
);
}

/**
* @dataProvider customThrowsExceptionDataProvider
*
* @param array<string, string|int|float|null> $attr
*/
public function testCustomThrowsException(string $action, string $target, string $html, array $attr): void
{
$this->expectException(\InvalidArgumentException::class);
TurboStream::custom($action, $target, $html, $attr);
}

public static function customThrowsExceptionDataProvider(): \Generator
{
yield ['customAction', 'some["selector"]', '<div>content</div>', ['action' => 'someAction']];
yield ['customAction', 'some["selector"]', '<div>content</div>', ['targets' => 'someTargets']];
}
}

0 comments on commit bb8aeed

Please sign in to comment.