|
22 | 22 | use ApiPlatform\Metadata\ApiResource;
|
23 | 23 | use ApiPlatform\Metadata\Get;
|
24 | 24 | use ApiPlatform\Metadata\Operations;
|
| 25 | +use ApiPlatform\Metadata\Post; |
25 | 26 | use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
|
26 | 27 | use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
|
27 | 28 | use ApiPlatform\Tests\Fixtures\NotAResource;
|
|
30 | 31 | use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyFriend;
|
31 | 32 | use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyMercure;
|
32 | 33 | use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyOffer;
|
| 34 | +use ApiPlatform\Tests\Fixtures\TestBundle\Entity\MercureWithTopics; |
33 | 35 | use Doctrine\ORM\EntityManagerInterface;
|
34 | 36 | use Doctrine\ORM\Event\OnFlushEventArgs;
|
35 | 37 | use Doctrine\ORM\UnitOfWork;
|
@@ -169,6 +171,123 @@ public function testPublishUpdate(): void
|
169 | 171 | $this->assertEquals([null, null, null, null, null, 10, null], $retry);
|
170 | 172 | }
|
171 | 173 |
|
| 174 | + public function testPublishUpdateMultipleTopicsUsingExpressionLanguage(): void |
| 175 | + { |
| 176 | + $mercure = [ |
| 177 | + 'topics' => [ |
| 178 | + '@=iri(object)', |
| 179 | + '@=iri(object, '.UrlGeneratorInterface::ABS_PATH.')', |
| 180 | + '@=iri(object, '.UrlGeneratorInterface::ABS_URL.', getOperation(object, "/custom_resource/mercure_with_topics/{id}{._format}"))', |
| 181 | + ], |
| 182 | + ]; |
| 183 | + |
| 184 | + $toInsert = new MercureWithTopics(); |
| 185 | + $toInsert->id = 1; |
| 186 | + $toInsert->name = 'Hello World!'; |
| 187 | + |
| 188 | + $toUpdate = new MercureWithTopics(); |
| 189 | + $toUpdate->id = 2; |
| 190 | + $toUpdate->name = 'Hello World!'; |
| 191 | + |
| 192 | + $toDelete = new MercureWithTopics(); |
| 193 | + $toDelete->id = 3; |
| 194 | + $toDelete->name = 'Hello World!'; |
| 195 | + |
| 196 | + // Even if it's the Post operation which sends Updates to Mercure, |
| 197 | + // the `mercure` configuration is retrieved from the first operation |
| 198 | + // of the resource because the Doctrine Listener doesn't have a |
| 199 | + // reference to the operation. |
| 200 | + $getOperation = (new Get())->withMercure($mercure)->withShortName('MercureWithTopics'); |
| 201 | + $customGetOperation = (new Get(uriTemplate: '/custom_resource/mercure_with_topics/{id}{._format}')); |
| 202 | + $postOperation = (new Post()); |
| 203 | + |
| 204 | + $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); |
| 205 | + $resourceClassResolverProphecy->getResourceClass(Argument::type(MercureWithTopics::class))->willReturn(MercureWithTopics::class); |
| 206 | + $resourceClassResolverProphecy->isResourceClass(MercureWithTopics::class)->willReturn(true); |
| 207 | + |
| 208 | + $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); |
| 209 | + |
| 210 | + $iriConverterProphecy->getIriFromResource($toInsert, UrlGeneratorInterface::ABS_URL, null)->willReturn('http://example.com/mercure_with_topics/1')->shouldBeCalled(); |
| 211 | + $iriConverterProphecy->getIriFromResource($toInsert, UrlGeneratorInterface::ABS_PATH, null)->willReturn('/mercure_with_topics/1')->shouldBeCalled(); |
| 212 | + $iriConverterProphecy->getIriFromResource($toInsert, UrlGeneratorInterface::ABS_URL, Argument::exact($customGetOperation))->willReturn('http://example.com/custom_resource/mercure_with_topics/1')->shouldBeCalled(); |
| 213 | + |
| 214 | + $iriConverterProphecy->getIriFromResource($toUpdate, UrlGeneratorInterface::ABS_URL, null)->willReturn('http://example.com/mercure_with_topics/2')->shouldBeCalled(); |
| 215 | + $iriConverterProphecy->getIriFromResource($toUpdate, UrlGeneratorInterface::ABS_PATH, null)->willReturn('/mercure_with_topics/2')->shouldBeCalled(); |
| 216 | + $iriConverterProphecy->getIriFromResource($toUpdate, UrlGeneratorInterface::ABS_URL, Argument::exact($customGetOperation))->willReturn('http://example.com/custom_resource/mercure_with_topics/2')->shouldBeCalled(); |
| 217 | + |
| 218 | + $iriConverterProphecy->getIriFromResource($toDelete)->willReturn('/mercure_with_topics/3')->shouldBeCalled(); |
| 219 | + $iriConverterProphecy->getIriFromResource($toDelete, UrlGeneratorInterface::ABS_URL, null)->willReturn('http://example.com/mercure_with_topics/3')->shouldBeCalled(); |
| 220 | + $iriConverterProphecy->getIriFromResource($toDelete, UrlGeneratorInterface::ABS_PATH, null)->willReturn('/mercure_with_topics/3')->shouldBeCalled(); |
| 221 | + $iriConverterProphecy->getIriFromResource($toDelete, UrlGeneratorInterface::ABS_URL, Argument::exact($customGetOperation))->willReturn('http://example.com/custom_resource/mercure_with_topics/3')->shouldBeCalled(); |
| 222 | + |
| 223 | + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); |
| 224 | + |
| 225 | + $resourceMetadataFactoryProphecy->create(MercureWithTopics::class)->willReturn(new ResourceMetadataCollection(MercureWithTopics::class, [ |
| 226 | + (new ApiResource())->withOperations(new Operations([ |
| 227 | + 'get' => $getOperation, |
| 228 | + 'custom_get' => $customGetOperation, |
| 229 | + 'post' => $postOperation, |
| 230 | + ])), |
| 231 | + ]))->shouldBeCalled(); |
| 232 | + |
| 233 | + $serializerProphecy = $this->prophesize(SerializerInterface::class); |
| 234 | + $serializerProphecy->serialize($toInsert, 'jsonld', [])->willReturn('{"@type":"MercureWithTopics","@id":"/mercure_with_topics/1","id":1,"name":"Hello World!"}')->shouldBeCalled(); |
| 235 | + $serializerProphecy->serialize($toUpdate, 'jsonld', [])->willReturn('{"@type":"MercureWithTopics","@id":"/mercure_with_topics/2","id":2,"name":"Hello World!"}')->shouldBeCalled(); |
| 236 | + |
| 237 | + $formats = ['jsonld' => ['application/ld+json'], 'jsonhal' => ['application/hal+json']]; |
| 238 | + |
| 239 | + $topics = []; |
| 240 | + $private = []; |
| 241 | + $retry = []; |
| 242 | + $data = []; |
| 243 | + |
| 244 | + $defaultHub = $this->createMockHub(function (Update $update) use (&$topics, &$private, &$retry, &$data): string { |
| 245 | + $topics = array_merge($topics, $update->getTopics()); |
| 246 | + $private[] = $update->isPrivate(); |
| 247 | + $retry[] = $update->getRetry(); |
| 248 | + $data[] = $update->getData(); |
| 249 | + |
| 250 | + return 'id'; |
| 251 | + }); |
| 252 | + |
| 253 | + $listener = new PublishMercureUpdatesListener( |
| 254 | + $resourceClassResolverProphecy->reveal(), |
| 255 | + $iriConverterProphecy->reveal(), |
| 256 | + $resourceMetadataFactoryProphecy->reveal(), |
| 257 | + $serializerProphecy->reveal(), |
| 258 | + $formats, |
| 259 | + null, |
| 260 | + new HubRegistry($defaultHub, ['default' => $defaultHub]), |
| 261 | + null, |
| 262 | + null, |
| 263 | + null, |
| 264 | + true, |
| 265 | + ); |
| 266 | + |
| 267 | + $uowProphecy = $this->prophesize(UnitOfWork::class); |
| 268 | + $uowProphecy->getScheduledEntityInsertions()->willReturn([$toInsert])->shouldBeCalled(); |
| 269 | + $uowProphecy->getScheduledEntityUpdates()->willReturn([$toUpdate])->shouldBeCalled(); |
| 270 | + $uowProphecy->getScheduledEntityDeletions()->willReturn([$toDelete])->shouldBeCalled(); |
| 271 | + |
| 272 | + $emProphecy = $this->prophesize(EntityManagerInterface::class); |
| 273 | + $emProphecy->getUnitOfWork()->willReturn($uowProphecy->reveal())->shouldBeCalled(); |
| 274 | + $eventArgs = new OnFlushEventArgs($emProphecy->reveal()); |
| 275 | + |
| 276 | + $listener->onFlush($eventArgs); |
| 277 | + $listener->postFlush(); |
| 278 | + |
| 279 | + $this->assertEquals([ |
| 280 | + '{"@type":"MercureWithTopics","@id":"/mercure_with_topics/1","id":1,"name":"Hello World!"}', |
| 281 | + '{"@type":"MercureWithTopics","@id":"/mercure_with_topics/2","id":2,"name":"Hello World!"}', |
| 282 | + '{"@id":"\/mercure_with_topics\/3","@type":"MercureWithTopics"}', |
| 283 | + ], $data); |
| 284 | + $this->assertEquals([ |
| 285 | + 'http://example.com/mercure_with_topics/1', '/mercure_with_topics/1', 'http://example.com/custom_resource/mercure_with_topics/1', |
| 286 | + 'http://example.com/mercure_with_topics/2', '/mercure_with_topics/2', 'http://example.com/custom_resource/mercure_with_topics/2', |
| 287 | + 'http://example.com/mercure_with_topics/3', '/mercure_with_topics/3', 'http://example.com/custom_resource/mercure_with_topics/3', |
| 288 | + ], $topics); |
| 289 | + } |
| 290 | + |
172 | 291 | public function testPublishGraphQlUpdates(): void
|
173 | 292 | {
|
174 | 293 | $toUpdate = new Dummy();
|
|
0 commit comments