Skip to content

Commit 526de3e

Browse files
authored
Merge pull request #2583 from soyuka/fix-messenger-per-operation
Use ContextAware on data persister chains
2 parents 1ee9be8 + c6f8359 commit 526de3e

File tree

8 files changed

+122
-70
lines changed

8 files changed

+122
-70
lines changed

src/Bridge/Doctrine/Common/DataPersister.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
namespace ApiPlatform\Core\Bridge\Doctrine\Common;
1515

16-
use ApiPlatform\Core\DataPersister\DataPersisterInterface;
16+
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
1717
use ApiPlatform\Core\Util\ClassInfoTrait;
1818
use Doctrine\Common\Persistence\ManagerRegistry;
1919
use Doctrine\Common\Persistence\ObjectManager as DoctrineObjectManager;
@@ -24,7 +24,7 @@
2424
*
2525
* @author Baptiste Meyer <[email protected]>
2626
*/
27-
final class DataPersister implements DataPersisterInterface
27+
final class DataPersister implements ContextAwareDataPersisterInterface
2828
{
2929
use ClassInfoTrait;
3030

@@ -38,15 +38,15 @@ public function __construct(ManagerRegistry $managerRegistry)
3838
/**
3939
* {@inheritdoc}
4040
*/
41-
public function supports($data): bool
41+
public function supports($data, array $context = []): bool
4242
{
4343
return null !== $this->getManager($data);
4444
}
4545

4646
/**
4747
* {@inheritdoc}
4848
*/
49-
public function persist($data)
49+
public function persist($data, array $context = [])
5050
{
5151
if (!$manager = $this->getManager($data)) {
5252
return $data;
@@ -65,7 +65,7 @@ public function persist($data)
6565
/**
6666
* {@inheritdoc}
6767
*/
68-
public function remove($data)
68+
public function remove($data, array $context = [])
6969
{
7070
if (!$manager = $this->getManager($data)) {
7171
return;

src/Bridge/Symfony/Bundle/DataPersister/TraceableChainDataPersister.php

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@
1414
namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DataPersister;
1515

1616
use ApiPlatform\Core\DataPersister\ChainDataPersister;
17+
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
1718
use ApiPlatform\Core\DataPersister\DataPersisterInterface;
1819

1920
/**
2021
* @author Anthony GRASSIOT <[email protected]>
2122
*/
22-
final class TraceableChainDataPersister implements DataPersisterInterface
23+
final class TraceableChainDataPersister implements ContextAwareDataPersisterInterface
2324
{
2425
private $persisters = [];
2526
private $persistersResponse = [];
@@ -41,37 +42,37 @@ public function getPersistersResponse(): array
4142
/**
4243
* {@inheritdoc}
4344
*/
44-
public function supports($data): bool
45+
public function supports($data, array $context = []): bool
4546
{
46-
return $this->decorated->supports($data);
47+
return $this->decorated->supports($data, $context);
4748
}
4849

4950
/**
5051
* {@inheritdoc}
5152
*/
52-
public function persist($data)
53+
public function persist($data, array $context = [])
5354
{
54-
if ($match = $this->tracePersisters($data)) {
55-
return $match->persist($data) ?? $data;
55+
if ($match = $this->tracePersisters($data, $context)) {
56+
return $match->persist($data, $context) ?? $data;
5657
}
5758
}
5859

5960
/**
6061
* {@inheritdoc}
6162
*/
62-
public function remove($data)
63+
public function remove($data, array $context = [])
6364
{
64-
if ($match = $this->tracePersisters($data)) {
65-
return $match->remove($data);
65+
if ($match = $this->tracePersisters($data, $context)) {
66+
return $match->remove($data, $context);
6667
}
6768
}
6869

69-
private function tracePersisters($data)
70+
private function tracePersisters($data, array $context = [])
7071
{
7172
$match = null;
7273
foreach ($this->persisters as $persister) {
7374
$this->persistersResponse[\get_class($persister)] = $match ? null : false;
74-
if (!$match && $persister->supports($data)) {
75+
if (!$match && $persister->supports($data, $context)) {
7576
$match = $persister;
7677
$this->persistersResponse[\get_class($persister)] = true;
7778
}

src/Bridge/Symfony/Messenger/DataPersister.php

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313

1414
namespace ApiPlatform\Core\Bridge\Symfony\Messenger;
1515

16-
use ApiPlatform\Core\DataPersister\DataPersisterInterface;
16+
use ApiPlatform\Core\Api\OperationType;
17+
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
1718
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
1819
use ApiPlatform\Core\Util\ClassInfoTrait;
1920
use Symfony\Component\Messenger\Envelope;
@@ -27,7 +28,7 @@
2728
*
2829
* @author Kévin Dunglas <[email protected]>
2930
*/
30-
final class DataPersister implements DataPersisterInterface
31+
final class DataPersister implements ContextAwareDataPersisterInterface
3132
{
3233
use ClassInfoTrait;
3334

@@ -43,15 +44,26 @@ public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFa
4344
/**
4445
* {@inheritdoc}
4546
*/
46-
public function supports($data): bool
47+
public function supports($data, array $context = []): bool
4748
{
48-
return true === $this->resourceMetadataFactory->create($this->getObjectClass($data))->getAttribute('messenger');
49+
$resourceMetadata = $this->resourceMetadataFactory->create($this->getObjectClass($data));
50+
if (null !== $operationName = $context['collection_operation_name'] ?? $context['item_operation_name'] ?? null) {
51+
return true === $resourceMetadata->getTypedOperationAttribute(
52+
$context['collection_operation_name'] ?? false ? OperationType::COLLECTION : OperationType::ITEM,
53+
$operationName,
54+
'messenger',
55+
false,
56+
true
57+
);
58+
}
59+
60+
return true === $resourceMetadata->getAttribute('messenger');
4961
}
5062

5163
/**
5264
* {@inheritdoc}
5365
*/
54-
public function persist($data)
66+
public function persist($data, array $context = [])
5567
{
5668
$envelope = $this->messageBus->dispatch($data);
5769
if (null === $stamp = $envelope->last(HandledStamp::class)) {
@@ -64,7 +76,7 @@ public function persist($data)
6476
/**
6577
* {@inheritdoc}
6678
*/
67-
public function remove($data)
79+
public function remove($data, array $context = [])
6880
{
6981
$this->messageBus->dispatch(new Envelope($data, new RemoveStamp()));
7082
}

src/DataPersister/ChainDataPersister.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*
1919
* @author Baptiste Meyer <[email protected]>
2020
*/
21-
final class ChainDataPersister implements DataPersisterInterface
21+
final class ChainDataPersister implements ContextAwareDataPersisterInterface
2222
{
2323
/** @internal */
2424
public $persisters;
@@ -34,10 +34,10 @@ public function __construct(/* iterable */ $persisters)
3434
/**
3535
* {@inheritdoc}
3636
*/
37-
public function supports($data): bool
37+
public function supports($data, array $context = []): bool
3838
{
3939
foreach ($this->persisters as $persister) {
40-
if ($persister->supports($data)) {
40+
if ($persister->supports($data, $context)) {
4141
return true;
4242
}
4343
}
@@ -48,23 +48,23 @@ public function supports($data): bool
4848
/**
4949
* {@inheritdoc}
5050
*/
51-
public function persist($data)
51+
public function persist($data, array $context = [])
5252
{
5353
foreach ($this->persisters as $persister) {
54-
if ($persister->supports($data)) {
55-
return $persister->persist($data) ?? $data;
54+
if ($persister->supports($data, $context)) {
55+
return $persister->persist($data, $context) ?? $data;
5656
}
5757
}
5858
}
5959

6060
/**
6161
* {@inheritdoc}
6262
*/
63-
public function remove($data)
63+
public function remove($data, array $context = [])
6464
{
6565
foreach ($this->persisters as $persister) {
66-
if ($persister->supports($data)) {
67-
$persister->remove($data);
66+
if ($persister->supports($data, $context)) {
67+
$persister->remove($data, $context);
6868

6969
return;
7070
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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\Core\DataPersister;
15+
16+
/**
17+
* Manages data persistence.
18+
*
19+
* @author Antoine Bluchet <[email protected]>
20+
*/
21+
interface ContextAwareDataPersisterInterface extends DataPersisterInterface
22+
{
23+
/**
24+
* {@inheritdoc}
25+
*/
26+
public function supports($data, array $context = []): bool;
27+
28+
/**
29+
* {@inheritdoc}
30+
*/
31+
public function persist($data, array $context = []);
32+
33+
/**
34+
* {@inheritdoc}
35+
*/
36+
public function remove($data, array $context = []);
37+
}

src/EventListener/WriteListener.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@ public function onKernelView(GetResponseForControllerResultEvent $event)
4949
}
5050

5151
$controllerResult = $event->getControllerResult();
52-
if (!$this->dataPersister->supports($controllerResult)) {
52+
if (!$this->dataPersister->supports($controllerResult, $attributes)) {
5353
return;
5454
}
5555

5656
switch ($request->getMethod()) {
5757
case 'PUT':
5858
case 'PATCH':
5959
case 'POST':
60-
$persistResult = $this->dataPersister->persist($controllerResult);
60+
$persistResult = $this->dataPersister->persist($controllerResult, $attributes);
6161

6262
if (null === $persistResult) {
6363
@trigger_error(sprintf('Returning void from %s::persist() is deprecated since API Platform 2.3 and will not be supported in API Platform 3, an object should always be returned.', DataPersisterInterface::class), E_USER_DEPRECATED);

tests/DataPersister/ChainDataPersisterTest.php

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use ApiPlatform\Core\DataPersister\DataPersisterInterface;
1818
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy;
1919
use PHPUnit\Framework\TestCase;
20+
use Prophecy\Argument;
2021

2122
/**
2223
* @author Baptiste Meyer <[email protected]>
@@ -33,7 +34,7 @@ public function testSupports()
3334
$dummy = new Dummy();
3435

3536
$persisterProphecy = $this->prophesize(DataPersisterInterface::class);
36-
$persisterProphecy->supports($dummy)->willReturn(true)->shouldBeCalled();
37+
$persisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled();
3738

3839
$this->assertTrue((new ChainDataPersister([$persisterProphecy->reveal()]))->supports($dummy));
3940
}
@@ -43,7 +44,7 @@ public function testDoesNotSupport()
4344
$dummy = new Dummy();
4445

4546
$persisterProphecy = $this->prophesize(DataPersisterInterface::class);
46-
$persisterProphecy->supports($dummy)->willReturn(false)->shouldBeCalled();
47+
$persisterProphecy->supports($dummy, Argument::type('array'))->willReturn(false)->shouldBeCalled();
4748

4849
$this->assertFalse((new ChainDataPersister([$persisterProphecy->reveal()]))->supports($dummy));
4950
}
@@ -53,16 +54,16 @@ public function testPersist()
5354
$dummy = new Dummy();
5455

5556
$fooPersisterProphecy = $this->prophesize(DataPersisterInterface::class);
56-
$fooPersisterProphecy->supports($dummy)->willReturn(false)->shouldBeCalled();
57-
$fooPersisterProphecy->persist($dummy)->shouldNotBeCalled();
57+
$fooPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(false)->shouldBeCalled();
58+
$fooPersisterProphecy->persist($dummy, Argument::type('array'))->shouldNotBeCalled();
5859

5960
$barPersisterProphecy = $this->prophesize(DataPersisterInterface::class);
60-
$barPersisterProphecy->supports($dummy)->willReturn(true)->shouldBeCalled();
61-
$barPersisterProphecy->persist($dummy)->shouldBeCalled();
61+
$barPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled();
62+
$barPersisterProphecy->persist($dummy, Argument::type('array'))->shouldBeCalled();
6263

6364
$foobarPersisterProphecy = $this->prophesize(DataPersisterInterface::class);
64-
$foobarPersisterProphecy->supports($dummy)->shouldNotBeCalled();
65-
$foobarPersisterProphecy->persist($dummy)->shouldNotBeCalled();
65+
$foobarPersisterProphecy->supports($dummy, Argument::type('array'))->shouldNotBeCalled();
66+
$foobarPersisterProphecy->persist($dummy, Argument::type('array'))->shouldNotBeCalled();
6667

6768
(new ChainDataPersister([$fooPersisterProphecy->reveal(), $barPersisterProphecy->reveal(), $foobarPersisterProphecy->reveal()]))->persist($dummy);
6869
}
@@ -72,16 +73,16 @@ public function testRemove()
7273
$dummy = new Dummy();
7374

7475
$fooPersisterProphecy = $this->prophesize(DataPersisterInterface::class);
75-
$fooPersisterProphecy->supports($dummy)->willReturn(false)->shouldBeCalled();
76-
$fooPersisterProphecy->remove($dummy)->shouldNotBeCalled();
76+
$fooPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(false)->shouldBeCalled();
77+
$fooPersisterProphecy->remove($dummy, Argument::type('array'))->shouldNotBeCalled();
7778

7879
$barPersisterProphecy = $this->prophesize(DataPersisterInterface::class);
79-
$barPersisterProphecy->supports($dummy)->willReturn(true)->shouldBeCalled();
80-
$barPersisterProphecy->remove($dummy)->shouldBeCalled();
80+
$barPersisterProphecy->supports($dummy, Argument::type('array'))->willReturn(true)->shouldBeCalled();
81+
$barPersisterProphecy->remove($dummy, Argument::type('array'))->shouldBeCalled();
8182

8283
$foobarPersisterProphecy = $this->prophesize(DataPersisterInterface::class);
83-
$foobarPersisterProphecy->supports($dummy)->shouldNotBeCalled();
84-
$foobarPersisterProphecy->remove($dummy)->shouldNotBeCalled();
84+
$foobarPersisterProphecy->supports($dummy, Argument::type('array'))->shouldNotBeCalled();
85+
$foobarPersisterProphecy->remove($dummy, Argument::type('array'))->shouldNotBeCalled();
8586

8687
(new ChainDataPersister([$fooPersisterProphecy->reveal(), $barPersisterProphecy->reveal(), $foobarPersisterProphecy->reveal()]))->remove($dummy);
8788
}

0 commit comments

Comments
 (0)