|
13 | 13 |
|
14 | 14 | namespace Symfony\Component\Mercure\Twig;
|
15 | 15 |
|
16 |
| -use Twig\Extension\AbstractExtension; |
17 |
| -use Twig\TwigFunction; |
| 16 | +use Symfony\Component\HttpFoundation\RequestStack; |
| 17 | +use Symfony\Component\Mercure\Authorization; |
| 18 | +use Symfony\Component\Mercure\HubRegistry; |
| 19 | +use Twig\Attribute\AsTwigFunction; |
18 | 20 |
|
19 | 21 | /**
|
20 | 22 | * Registers the Twig helper function.
|
21 | 23 | *
|
22 | 24 | * @author Kévin Dunglas <[email protected]>
|
23 | 25 | */
|
24 |
| -final class MercureExtension extends AbstractExtension |
| 26 | +final class MercureExtension |
25 | 27 | {
|
26 |
| - public function getFunctions(): array |
| 28 | + private $hubRegistry; |
| 29 | + private $authorization; |
| 30 | + private $requestStack; |
| 31 | + |
| 32 | + public function __construct(HubRegistry $hubRegistry, ?Authorization $authorization = null, ?RequestStack $requestStack = null) |
| 33 | + { |
| 34 | + $this->hubRegistry = $hubRegistry; |
| 35 | + $this->authorization = $authorization; |
| 36 | + $this->requestStack = $requestStack; |
| 37 | + } |
| 38 | + |
| 39 | + /** |
| 40 | + * @param string|string[]|null $topics A topic or an array of topics to subscribe for. If this parameter is omitted or `null` is passed, the URL of the hub will be returned (useful for publishing in JavaScript). |
| 41 | + * @param array{subscribe?: string[]|string, publish?: string[]|string, additionalClaims?: array<string, mixed>, lastEventId?: string, hub?: string} $options The options to pass to the JWT factory |
| 42 | + * |
| 43 | + * @return string The URL of the hub with the appropriate "topic" query parameters (if any) |
| 44 | + */ |
| 45 | + #[AsTwigFunction('mercure')] |
| 46 | + public function mercure($topics = null, array $options = []): string |
27 | 47 | {
|
28 |
| - return [new TwigFunction('mercure', [MercureRuntime::class, 'mercure'])]; |
| 48 | + $hub = $options['hub'] ?? null; |
| 49 | + $url = $this->hubRegistry->getHub($hub)->getPublicUrl(); |
| 50 | + if (null !== $topics) { |
| 51 | + // We cannot use http_build_query() because this method doesn't support generating multiple query parameters with the same name without the [] suffix |
| 52 | + $separator = '?'; |
| 53 | + foreach ((array) $topics as $topic) { |
| 54 | + $url .= $separator.'topic='.rawurlencode($topic); |
| 55 | + if ('?' === $separator) { |
| 56 | + $separator = '&'; |
| 57 | + } |
| 58 | + } |
| 59 | + } |
| 60 | + |
| 61 | + if ('' !== ($options['lastEventId'] ?? '')) { |
| 62 | + $encodedLastEventId = rawurlencode($options['lastEventId']); |
| 63 | + // Last-Event-ID is kept for compatibility with older versions of the protocol: https://mercure.rocks/docs/UPGRADE#0-14 |
| 64 | + $url .= "&lastEventID=$encodedLastEventId&Last-Event-ID=$encodedLastEventId"; |
| 65 | + } |
| 66 | + |
| 67 | + if ( |
| 68 | + null === $this->authorization |
| 69 | + || null === $this->requestStack |
| 70 | + || (!isset($options['subscribe']) && !isset($options['publish']) && !isset($options['additionalClaims'])) |
| 71 | + /* @phpstan-ignore-next-line */ |
| 72 | + || null === $request = method_exists($this->requestStack, 'getMainRequest') ? $this->requestStack->getMainRequest() : $this->requestStack->getMasterRequest() |
| 73 | + ) { |
| 74 | + return $url; |
| 75 | + } |
| 76 | + |
| 77 | + $this->authorization->setCookie($request, $options['subscribe'] ?? [], $options['publish'] ?? [], $options['additionalClaims'] ?? [], $hub); |
| 78 | + |
| 79 | + return $url; |
29 | 80 | }
|
30 | 81 | }
|
0 commit comments