Skip to content

Commit 3bbc18c

Browse files
feat(symfony): add getOperation Expression Language function on Mercure topics
1 parent d85ed0c commit 3bbc18c

File tree

5 files changed

+119
-3
lines changed

5 files changed

+119
-3
lines changed

features/mercure/publish.feature

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,30 @@ Feature: Mercure publish support
3131
"name": "Hello World!"
3232
}
3333
"""
34+
35+
Scenario: Checks that Mercure Updates are dispatched following topics configured with expression language
36+
Given I add "Accept" header equal to "application/ld+json"
37+
And I add "Content-Type" header equal to "application/ld+json"
38+
When I send a "POST" request to "/mercure_with_topics" with body:
39+
"""
40+
{
41+
"name": "Hello World!"
42+
}
43+
"""
44+
Then the response status code should be 201
45+
And the response should be in JSON
46+
And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
47+
Then 1 Mercure update should have been sent
48+
And the Mercure update should have topics:
49+
| http://example.com/mercure_with_topics/1 |
50+
| http://example.com/custom_resource/mercure_with_topics/1 |
51+
And the Mercure update should have data:
52+
"""
53+
{
54+
"@context": "/contexts/MercureWithTopics",
55+
"@id": "/mercure_with_topics/1",
56+
"@type": "MercureWithTopics",
57+
"id": 1,
58+
"name": "Hello World!"
59+
}
60+
"""

src/Doctrine/EventListener/PublishMercureUpdatesListener.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use ApiPlatform\GraphQl\Subscription\SubscriptionManagerInterface as GraphQlSubscriptionManagerInterface;
2323
use ApiPlatform\Metadata\HttpOperation;
2424
use ApiPlatform\Metadata\IriConverterInterface;
25+
use ApiPlatform\Metadata\Operation;
2526
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
2627
use ApiPlatform\Metadata\ResourceClassResolverInterface;
2728
use ApiPlatform\Metadata\UrlGeneratorInterface;
@@ -84,7 +85,10 @@ public function __construct(LegacyResourceClassResolverInterface|ResourceClassRe
8485
$this->expressionLanguage->addFunction($rawurlencode);
8586

8687
$this->expressionLanguage->addFunction(
87-
new ExpressionFunction('iri', static fn (string $apiResource, int $referenceType = UrlGeneratorInterface::ABS_URL): string => sprintf('iri(%s, %d)', $apiResource, $referenceType), static fn (array $arguments, $apiResource, int $referenceType = UrlGeneratorInterface::ABS_URL): string => $iriConverter->getIriFromResource($apiResource, $referenceType))
88+
new ExpressionFunction('getOperation', static fn (string $apiResource, string $name): string => sprintf('getOperation(%s, %s)', $apiResource, $name), static fn (array $arguments, $apiResource, string $name): Operation => $resourceMetadataFactory->create($resourceClassResolver->getResourceClass($apiResource))->getOperation($name))
89+
);
90+
$this->expressionLanguage->addFunction(
91+
new ExpressionFunction('iri', static fn (string $apiResource, int $referenceType = UrlGeneratorInterface::ABS_URL, string $operation = null): string => sprintf('iri(%s, %d, %s)', $apiResource, $referenceType, $operation), static fn (array $arguments, $apiResource, int $referenceType = UrlGeneratorInterface::ABS_URL, $operation = null): string => $iriConverter->getIriFromResource($apiResource, $referenceType, $operation))
8892
);
8993
}
9094

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Fixtures\TestBundle\Document;
15+
16+
use ApiPlatform\Metadata\ApiResource;
17+
use ApiPlatform\Metadata\Get;
18+
use ApiPlatform\Metadata\Post;
19+
use ApiPlatform\Metadata\UrlGeneratorInterface;
20+
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
21+
22+
#[ApiResource(
23+
operations: [
24+
new Get(uriTemplate: '/mercure_with_topics/{id}{._format}'),
25+
new Post(uriTemplate: '/mercure_with_topics{._format}'),
26+
new Get(uriTemplate: '/custom_resource/mercure_with_topics/{id}{._format}'),
27+
],
28+
mercure: [
29+
'topics' => [
30+
'@=iri(object)',
31+
'@=iri(object, '.UrlGeneratorInterface::ABS_URL.', getOperation(object, "/custom_resource/mercure_with_topics/{id}{._format}"))',
32+
],
33+
]
34+
)]
35+
#[ODM\Document]
36+
class MercureWithTopics
37+
{
38+
#[ODM\Id(strategy: 'INCREMENT', type: 'int')]
39+
public $id;
40+
#[ODM\Field(type: 'string')]
41+
public $name;
42+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity;
15+
16+
use ApiPlatform\Metadata\ApiResource;
17+
use ApiPlatform\Metadata\Get;
18+
use ApiPlatform\Metadata\Post;
19+
use ApiPlatform\Metadata\UrlGeneratorInterface;
20+
use Doctrine\ORM\Mapping as ORM;
21+
22+
#[ApiResource(
23+
operations: [
24+
new Get(uriTemplate: '/mercure_with_topics/{id}{._format}'),
25+
new Post(uriTemplate: '/mercure_with_topics{._format}'),
26+
new Get(uriTemplate: '/custom_resource/mercure_with_topics/{id}{._format}'),
27+
],
28+
mercure: [
29+
'topics' => [
30+
'@=iri(object)',
31+
'@=iri(object, '.UrlGeneratorInterface::ABS_URL.', getOperation(object, "/custom_resource/mercure_with_topics/{id}{._format}"))',
32+
],
33+
]
34+
)]
35+
#[ORM\Entity]
36+
class MercureWithTopics
37+
{
38+
#[ORM\Id]
39+
#[ORM\Column(type: 'integer')]
40+
#[ORM\GeneratedValue(strategy: 'AUTO')]
41+
public $id;
42+
#[ORM\Column]
43+
public $name;
44+
}

tests/Symfony/Bundle/Test/ApiTestCaseTest.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,7 @@ public function testFindIriBy(): void
217217
*/
218218
public function testGetMercureMessages(): void
219219
{
220-
// debug mode is required to get Mercure TraceableHub
221-
$this->recreateSchema(['debug' => true, 'environment' => 'mercure']);
220+
$this->recreateSchema(['environment' => 'mercure']);
222221

223222
self::createClient()->request('POST', '/direct_mercures', [
224223
'headers' => [

0 commit comments

Comments
 (0)