Skip to content

Commit 06ac699

Browse files
committed
Add options to turbo stream
1 parent dec3eb3 commit 06ac699

9 files changed

+59
-7
lines changed

src/Turbo/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- Add `<twig:Turbo:Frame>` component
77
- Add support for custom actions in `TurboStream` and `TurboStreamResponse`
88
- Add support for providing multiple mercure topics to `turbo_stream_listen`
9+
- Add support for providing options to the EventSource via `turbo_stream_listen`
910

1011
## 2.21.0
1112

src/Turbo/assets/dist/turbo_stream_controller.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ export default class extends Controller {
44
topic: StringConstructor;
55
topics: ArrayConstructor;
66
hub: StringConstructor;
7+
eventSourceOptions: ObjectConstructor;
78
};
89
es: EventSource | undefined;
910
url: string | undefined;
1011
readonly topicValue: string;
1112
readonly topicsValue: string[];
13+
readonly eventSourceOptionsValue: object;
1214
readonly hubValue: string;
1315
readonly hasHubValue: boolean;
1416
readonly hasTopicValue: boolean;

src/Turbo/assets/dist/turbo_stream_controller.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class default_1 extends Controller {
2323
}
2424
connect() {
2525
if (this.url) {
26-
this.es = new EventSource(this.url);
26+
this.es = new EventSource(this.url, this.eventSourceOptionsValue);
2727
connectStreamSource(this.es);
2828
}
2929
}
@@ -38,6 +38,7 @@ default_1.values = {
3838
topic: String,
3939
topics: Array,
4040
hub: String,
41+
eventSourceOptions: Object,
4142
};
4243

4344
export { default_1 as default };

src/Turbo/assets/src/turbo_stream_controller.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ export default class extends Controller {
1818
topic: String,
1919
topics: Array,
2020
hub: String,
21+
eventSourceOptions: Object,
2122
};
2223
es: EventSource | undefined;
2324
url: string | undefined;
2425

2526
declare readonly topicValue: string;
2627
declare readonly topicsValue: string[];
28+
declare readonly eventSourceOptionsValue: object;
2729
declare readonly hubValue: string;
2830
declare readonly hasHubValue: boolean;
2931
declare readonly hasTopicValue: boolean;
@@ -50,7 +52,7 @@ export default class extends Controller {
5052

5153
connect() {
5254
if (this.url) {
53-
this.es = new EventSource(this.url);
55+
this.es = new EventSource(this.url, this.eventSourceOptionsValue);
5456
connectStreamSource(this.es);
5557
}
5658
}

src/Turbo/config/services.php

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

1212
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
1313

14+
use Symfony\Component\Mercure\Authorization;
1415
use Symfony\UX\Turbo\Broadcaster\BroadcasterInterface;
1516
use Symfony\UX\Turbo\Broadcaster\IdAccessor;
1617
use Symfony\UX\Turbo\Broadcaster\ImuxBroadcaster;
@@ -45,7 +46,12 @@
4546
->decorate('turbo.broadcaster.imux')
4647

4748
->set('turbo.twig.extension', TwigExtension::class)
48-
->args([tagged_locator('turbo.renderer.stream_listen', 'transport'), abstract_arg('default')])
49+
->args([
50+
tagged_locator('turbo.renderer.stream_listen', 'transport'),
51+
abstract_arg('default'),
52+
service(Authorization::class)->nullOnInvalid(),
53+
service('request_stack')->nullOnInvalid(),
54+
])
4955
->tag('twig.extension')
5056

5157
->set('turbo.doctrine.event_listener', BroadcastListener::class)

src/Turbo/src/Bridge/Mercure/TurboStreamListenRenderer.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,12 @@ public function __construct(
4242
$this->stimulusHelper = $stimulus;
4343
}
4444

45-
public function renderTurboStreamListen(Environment $env, $topic): string
45+
public function renderTurboStreamListen(Environment $env, $topic /* array $eventSourceOptions = [] */): string
4646
{
47+
if (\func_num_args() > 2) {
48+
$eventSourceOptions = func_get_arg(2);
49+
}
50+
4751
$topics = $topic instanceof TopicSet
4852
? array_map($this->resolveTopic(...), $topic->getTopics())
4953
: [$this->resolveTopic($topic)];
@@ -55,6 +59,10 @@ public function renderTurboStreamListen(Environment $env, $topic): string
5559
$controllerAttributes['topic'] = current($topics);
5660
}
5761

62+
if (isset($eventSourceOptions) && !empty($eventSourceOptions)) {
63+
$controllerAttributes['eventSourceOptions'] = $eventSourceOptions;
64+
}
65+
5866
$stimulusAttributes = $this->stimulusHelper->createStimulusAttributes();
5967
$stimulusAttributes->addController(
6068
'symfony/ux-turbo/mercure-turbo-stream',

src/Turbo/src/Twig/TurboStreamListenRendererInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ interface TurboStreamListenRendererInterface
2323
/**
2424
* @param string|object $topic
2525
*/
26-
public function renderTurboStreamListen(Environment $env, $topic): string;
26+
public function renderTurboStreamListen(Environment $env, $topic /* , array $eventSourceOptions = [] */): string;
2727
}

src/Turbo/src/Twig/TwigExtension.php

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,24 @@
1212
namespace Symfony\UX\Turbo\Twig;
1313

1414
use Psr\Container\ContainerInterface;
15+
use Symfony\Component\HttpFoundation\RequestStack;
16+
use Symfony\Component\Mercure\Authorization;
1517
use Symfony\UX\Turbo\Bridge\Mercure\TopicSet;
1618
use Twig\Environment;
1719
use Twig\Extension\AbstractExtension;
1820
use Twig\TwigFunction;
1921

2022
/**
2123
* @author Kévin Dunglas <kevin@dunglas.fr>
24+
* @author Pierre Ambroise <pierre27.ambroise@gmail.com>
2225
*/
2326
final class TwigExtension extends AbstractExtension
2427
{
2528
public function __construct(
2629
private ContainerInterface $turboStreamListenRenderers,
2730
private string $default,
31+
private ?Authorization $authorization = null,
32+
private ?RequestStack $requestStack = null,
2833
) {
2934
}
3035

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

3843
/**
3944
* @param object|string|array<object|string> $topic
45+
* @param array<string, mixed> $options
4046
*/
41-
public function turboStreamListen(Environment $env, $topic, ?string $transport = null): string
47+
public function turboStreamListen(Environment $env, $topic, ?string $transport = null, array $options = []): string
4248
{
4349
$transport ??= $this->default;
4450

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

53-
return $this->turboStreamListenRenderers->get($transport)->renderTurboStreamListen($env, $topic);
59+
if (
60+
null !== $this->authorization
61+
&& null !== $this->requestStack
62+
&& (isset($options['subscribe']) || isset($options['publish']) || isset($options['additionalClaims']))
63+
// @phpstan-ignore-next-line
64+
&& null !== $request = method_exists($this->requestStack, 'getMainRequest') ? $this->requestStack->getMainRequest() : $this->requestStack->getMasterRequest()
65+
) {
66+
$this->authorization->setCookie(
67+
$request,
68+
$options['subscribe'] ?? [],
69+
$options['publish'] ?? [],
70+
$options['additionalClaims'] ?? [],
71+
$transport,
72+
);
73+
74+
unset($options['subscribe'], $options['publish'], $options['additionalClaims']);
75+
}
76+
77+
return $this->turboStreamListenRenderers->get($transport)->renderTurboStreamListen($env, $topic, $options);
5478
}
5579
}

src/Turbo/tests/Bridge/Mercure/TurboStreamListenRendererTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,13 @@ public static function provideTestCases(): iterable
7171
? '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;]"'
7272
: '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;"',
7373
];
74+
75+
yield [
76+
"{{ turbo_stream_listen('a_topic', 'default', { withCredentials: true }) }}",
77+
[],
78+
$newEscape
79+
? '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}"'
80+
: '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;"',
81+
];
7482
}
7583
}

0 commit comments

Comments
 (0)