Skip to content

Commit

Permalink
Add options to turbo stream
Browse files Browse the repository at this point in the history
  • Loading branch information
Fan2Shrek committed Dec 12, 2024
1 parent dec3eb3 commit 06ac699
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 7 deletions.
1 change: 1 addition & 0 deletions src/Turbo/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Add `<twig:Turbo:Frame>` component
- Add support for custom actions in `TurboStream` and `TurboStreamResponse`
- Add support for providing multiple mercure topics to `turbo_stream_listen`
- Add support for providing options to the EventSource via `turbo_stream_listen`

## 2.21.0

Expand Down
2 changes: 2 additions & 0 deletions src/Turbo/assets/dist/turbo_stream_controller.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ export default class extends Controller {
topic: StringConstructor;
topics: ArrayConstructor;
hub: StringConstructor;
eventSourceOptions: ObjectConstructor;
};
es: EventSource | undefined;
url: string | undefined;
readonly topicValue: string;
readonly topicsValue: string[];
readonly eventSourceOptionsValue: object;
readonly hubValue: string;
readonly hasHubValue: boolean;
readonly hasTopicValue: boolean;
Expand Down
3 changes: 2 additions & 1 deletion src/Turbo/assets/dist/turbo_stream_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class default_1 extends Controller {
}
connect() {
if (this.url) {
this.es = new EventSource(this.url);
this.es = new EventSource(this.url, this.eventSourceOptionsValue);
connectStreamSource(this.es);
}
}
Expand All @@ -38,6 +38,7 @@ default_1.values = {
topic: String,
topics: Array,
hub: String,
eventSourceOptions: Object,
};

export { default_1 as default };
4 changes: 3 additions & 1 deletion src/Turbo/assets/src/turbo_stream_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ export default class extends Controller {
topic: String,
topics: Array,
hub: String,
eventSourceOptions: Object,
};
es: EventSource | undefined;
url: string | undefined;

declare readonly topicValue: string;
declare readonly topicsValue: string[];
declare readonly eventSourceOptionsValue: object;
declare readonly hubValue: string;
declare readonly hasHubValue: boolean;
declare readonly hasTopicValue: boolean;
Expand All @@ -50,7 +52,7 @@ export default class extends Controller {

connect() {
if (this.url) {
this.es = new EventSource(this.url);
this.es = new EventSource(this.url, this.eventSourceOptionsValue);
connectStreamSource(this.es);
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/Turbo/config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use Symfony\Component\Mercure\Authorization;
use Symfony\UX\Turbo\Broadcaster\BroadcasterInterface;
use Symfony\UX\Turbo\Broadcaster\IdAccessor;
use Symfony\UX\Turbo\Broadcaster\ImuxBroadcaster;
Expand Down Expand Up @@ -45,7 +46,12 @@
->decorate('turbo.broadcaster.imux')

->set('turbo.twig.extension', TwigExtension::class)
->args([tagged_locator('turbo.renderer.stream_listen', 'transport'), abstract_arg('default')])
->args([
tagged_locator('turbo.renderer.stream_listen', 'transport'),
abstract_arg('default'),
service(Authorization::class)->nullOnInvalid(),
service('request_stack')->nullOnInvalid(),
])
->tag('twig.extension')

->set('turbo.doctrine.event_listener', BroadcastListener::class)
Expand Down
10 changes: 9 additions & 1 deletion src/Turbo/src/Bridge/Mercure/TurboStreamListenRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,12 @@ public function __construct(
$this->stimulusHelper = $stimulus;
}

public function renderTurboStreamListen(Environment $env, $topic): string
public function renderTurboStreamListen(Environment $env, $topic /* array $eventSourceOptions = [] */): string
{
if (\func_num_args() > 2) {
$eventSourceOptions = func_get_arg(2);
}

$topics = $topic instanceof TopicSet
? array_map($this->resolveTopic(...), $topic->getTopics())
: [$this->resolveTopic($topic)];
Expand All @@ -55,6 +59,10 @@ public function renderTurboStreamListen(Environment $env, $topic): string
$controllerAttributes['topic'] = current($topics);
}

if (isset($eventSourceOptions) && !empty($eventSourceOptions)) {
$controllerAttributes['eventSourceOptions'] = $eventSourceOptions;
}

$stimulusAttributes = $this->stimulusHelper->createStimulusAttributes();
$stimulusAttributes->addController(
'symfony/ux-turbo/mercure-turbo-stream',
Expand Down
2 changes: 1 addition & 1 deletion src/Turbo/src/Twig/TurboStreamListenRendererInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ interface TurboStreamListenRendererInterface
/**
* @param string|object $topic
*/
public function renderTurboStreamListen(Environment $env, $topic): string;
public function renderTurboStreamListen(Environment $env, $topic /* , array $eventSourceOptions = [] */): string;
}
28 changes: 26 additions & 2 deletions src/Turbo/src/Twig/TwigExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,24 @@
namespace Symfony\UX\Turbo\Twig;

use Psr\Container\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Mercure\Authorization;
use Symfony\UX\Turbo\Bridge\Mercure\TopicSet;
use Twig\Environment;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

/**
* @author Kévin Dunglas <[email protected]>
* @author Pierre Ambroise <[email protected]>
*/
final class TwigExtension extends AbstractExtension
{
public function __construct(
private ContainerInterface $turboStreamListenRenderers,
private string $default,
private ?Authorization $authorization = null,
private ?RequestStack $requestStack = null,
) {
}

Expand All @@ -37,8 +42,9 @@ public function getFunctions(): array

/**
* @param object|string|array<object|string> $topic
* @param array<string, mixed> $options
*/
public function turboStreamListen(Environment $env, $topic, ?string $transport = null): string
public function turboStreamListen(Environment $env, $topic, ?string $transport = null, array $options = []): string
{
$transport ??= $this->default;

Expand All @@ -50,6 +56,24 @@ public function turboStreamListen(Environment $env, $topic, ?string $transport =
$topic = new TopicSet($topic);
}

return $this->turboStreamListenRenderers->get($transport)->renderTurboStreamListen($env, $topic);
if (
null !== $this->authorization
&& null !== $this->requestStack
&& (isset($options['subscribe']) || isset($options['publish']) || isset($options['additionalClaims']))
// @phpstan-ignore-next-line
&& null !== $request = method_exists($this->requestStack, 'getMainRequest') ? $this->requestStack->getMainRequest() : $this->requestStack->getMasterRequest()
) {
$this->authorization->setCookie(
$request,
$options['subscribe'] ?? [],
$options['publish'] ?? [],
$options['additionalClaims'] ?? [],
$transport,
);

unset($options['subscribe'], $options['publish'], $options['additionalClaims']);
}

return $this->turboStreamListenRenderers->get($transport)->renderTurboStreamListen($env, $topic, $options);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,13 @@ public static function provideTestCases(): iterable
? 'data-controller="symfony--ux-turbo--mercure-turbo-stream" data-symfony--ux-turbo--mercure-turbo-stream-hub-value="http://127.0.0.1:3000/.well-known/mercure" data-symfony--ux-turbo--mercure-turbo-stream-topics-value="[&quot;a_topic&quot;,&quot;AppEntityBook&quot;,&quot;https:\/\/symfony.com\/ux-turbo\/App%5CEntity%5CBook\/123&quot;]"'
: 'data-controller="symfony--ux-turbo--mercure-turbo-stream" data-symfony--ux-turbo--mercure-turbo-stream-hub-value="http&#x3A;&#x2F;&#x2F;127.0.0.1&#x3A;3000&#x2F;.well-known&#x2F;mercure" data-symfony--ux-turbo--mercure-turbo-stream-topics-value="&#x5B;&quot;a_topic&quot;,&quot;AppEntityBook&quot;,&quot;https&#x3A;&#x5C;&#x2F;&#x5C;&#x2F;symfony.com&#x5C;&#x2F;ux-turbo&#x5C;&#x2F;App&#x25;5CEntity&#x25;5CBook&#x5C;&#x2F;123&quot;&#x5D;"',
];

yield [
"{{ turbo_stream_listen('a_topic', 'default', { withCredentials: true }) }}",
[],
$newEscape
? 'data-controller="symfony--ux-turbo--mercure-turbo-stream" data-symfony--ux-turbo--mercure-turbo-stream-hub-value="http://127.0.0.1:3000/.well-known/mercure" data-symfony--ux-turbo--mercure-turbo-stream-topic-value="a_topic" data-symfony--ux-turbo--mercure-turbo-stream-event-source-options-value="{&quot;withCredentials&quot;:true}"'
: 'data-controller="symfony--ux-turbo--mercure-turbo-stream" data-symfony--ux-turbo--mercure-turbo-stream-hub-value="http&#x3A;&#x2F;&#x2F;127.0.0.1&#x3A;3000&#x2F;.well-known&#x2F;mercure" data-symfony--ux-turbo--mercure-turbo-stream-topic-value="a_topic" data-symfony--ux-turbo--mercure-turbo-stream-event-source-options-value="&#x7B;&quot;withCredentials&quot;&#x3A;true&#x7D;"',
];
}
}

0 comments on commit 06ac699

Please sign in to comment.