Skip to content

Commit c26e612

Browse files
committed
Update ChainSubresourceDataProvider to take into account RestrictedDataProviderInterface
1 parent 7bdead7 commit c26e612

File tree

2 files changed

+71
-3
lines changed

2 files changed

+71
-3
lines changed

src/DataProvider/ChainSubresourceDataProvider.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,19 @@ public function __construct(array $dataProviders)
3737
*/
3838
public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null)
3939
{
40-
foreach ($this->dataProviders as $dataProviders) {
40+
foreach ($this->dataProviders as $dataProvider) {
4141
try {
42-
return $dataProviders->getSubresource($resourceClass, $identifiers, $context, $operationName);
42+
if ($dataProvider instanceof RestrictedDataProviderInterface && !$dataProvider->supports($resourceClass, $operationName, $context)) {
43+
continue;
44+
}
45+
46+
return $dataProvider->getSubresource($resourceClass, $identifiers, $context, $operationName);
4347
} catch (ResourceClassNotSupportedException $e) {
48+
@trigger_error(sprintf('Throwing a "%s" in a data provider is deprecated in favor of implementing "%s"', ResourceClassNotSupportedException::class, RestrictedDataProviderInterface::class), E_USER_DEPRECATED);
4449
continue;
4550
}
4651
}
52+
53+
return ($context['collection'] ?? false) ? [] : null;
4754
}
4855
}

tests/DataProvider/ChainSubresourcedataProviderTest.php

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
namespace ApiPlatform\Core\Tests\DataProvider;
1515

1616
use ApiPlatform\Core\DataProvider\ChainSubresourceDataProvider;
17+
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
1718
use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface;
1819
use ApiPlatform\Core\Exception\ResourceClassNotSupportedException;
1920
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy;
@@ -33,20 +34,80 @@ public function testGetSubresource()
3334

3435
$context = ['identifiers' => ['id' => Dummy::class], 'property' => 'relatedDummies'];
3536
$firstDataProvider = $this->prophesize(SubresourceDataProviderInterface::class);
37+
$firstDataProvider->willImplement(RestrictedDataProviderInterface::class);
38+
$firstDataProvider->supports(Dummy::class, 'get', $context)->willReturn(false);
3639
$firstDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy, $dummy2])->willThrow(ResourceClassNotSupportedException::class);
3740

3841
$secondDataProvider = $this->prophesize(SubresourceDataProviderInterface::class);
42+
$secondDataProvider->willImplement(RestrictedDataProviderInterface::class);
43+
$secondDataProvider->supports(Dummy::class, 'get', $context)->willReturn(true);
3944
$secondDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy, $dummy2]);
4045

4146
$thirdDataProvider = $this->prophesize(SubresourceDataProviderInterface::class);
47+
$thirdDataProvider->willImplement(RestrictedDataProviderInterface::class);
48+
$thirdDataProvider->supports(Dummy::class, 'get', $context)->willReturn(true);
4249
$thirdDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy]);
4350

4451
$chainSubresourceDataProvider = new ChainSubresourceDataProvider([$firstDataProvider->reveal(), $secondDataProvider->reveal(), $thirdDataProvider->reveal()]);
4552

4653
$this->assertEquals([$dummy, $dummy2], $chainSubresourceDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get'));
4754
}
4855

49-
public function testGetCollectionExeptions()
56+
public function testGetSubresourceExceptionsItem()
57+
{
58+
$context = ['collection' => false];
59+
$firstDataProvider = $this->prophesize(SubresourceDataProviderInterface::class);
60+
$firstDataProvider->willImplement(RestrictedDataProviderInterface::class);
61+
$firstDataProvider->supports(Dummy::class, 'get', $context)->willReturn(false);
62+
63+
$chainSubresourceDataProvider = new ChainSubresourceDataProvider([$firstDataProvider->reveal()]);
64+
65+
$this->assertNull($chainSubresourceDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get'));
66+
}
67+
68+
public function testGetSubresourceExceptionsCollection()
69+
{
70+
$context = ['collection' => true];
71+
$firstDataProvider = $this->prophesize(SubresourceDataProviderInterface::class);
72+
$firstDataProvider->willImplement(RestrictedDataProviderInterface::class);
73+
$firstDataProvider->supports(Dummy::class, 'get', $context)->willReturn(false);
74+
75+
$chainSubresourceDataProvider = new ChainSubresourceDataProvider([$firstDataProvider->reveal()]);
76+
77+
$this->assertEquals([], $chainSubresourceDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get'));
78+
}
79+
80+
/**
81+
* @group legacy
82+
* @expectedDeprecation Throwing a "ApiPlatform\Core\Exception\ResourceClassNotSupportedException" in a data provider is deprecated in favor of implementing "ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface"
83+
*/
84+
public function testLegacyGetSubresource()
85+
{
86+
$dummy = new Dummy();
87+
$dummy->setName('Rosa');
88+
$dummy2 = new Dummy();
89+
$dummy2->setName('Parks');
90+
91+
$context = ['identifiers' => ['id' => Dummy::class], 'property' => 'relatedDummies'];
92+
$firstDataProvider = $this->prophesize(SubresourceDataProviderInterface::class);
93+
$firstDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy, $dummy2])->willThrow(ResourceClassNotSupportedException::class);
94+
95+
$secondDataProvider = $this->prophesize(SubresourceDataProviderInterface::class);
96+
$secondDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy, $dummy2]);
97+
98+
$thirdDataProvider = $this->prophesize(SubresourceDataProviderInterface::class);
99+
$thirdDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get')->willReturn([$dummy]);
100+
101+
$chainSubresourceDataProvider = new ChainSubresourceDataProvider([$firstDataProvider->reveal(), $secondDataProvider->reveal(), $thirdDataProvider->reveal()]);
102+
103+
$this->assertEquals([$dummy, $dummy2], $chainSubresourceDataProvider->getSubresource(Dummy::class, ['id' => 1], $context, 'get'));
104+
}
105+
106+
/**
107+
* @group legacy
108+
* @expectedDeprecation Throwing a "ApiPlatform\Core\Exception\ResourceClassNotSupportedException" in a data provider is deprecated in favor of implementing "ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface"
109+
*/
110+
public function testLegacyGetCollectionExeptions()
50111
{
51112
$firstDataProvider = $this->prophesize(SubresourceDataProviderInterface::class);
52113
$firstDataProvider->getSubresource('notfound', ['id' => 1], [], 'get')->willThrow(ResourceClassNotSupportedException::class);

0 commit comments

Comments
 (0)