Skip to content

Commit f2539dd

Browse files
authored
Merge pull request #2065 from Nek-/feature/add-support-for-interface-as-resource
Add support for interface as a resource
2 parents e5539ee + c15bbaf commit f2539dd

File tree

13 files changed

+216
-3
lines changed

13 files changed

+216
-3
lines changed

features/main/table_inheritance.feature

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,3 +291,35 @@ Feature: Table inheritance
291291
"required": ["hydra:member"]
292292
}
293293
"""
294+
295+
Scenario: Get the parent interface collection
296+
When I send a "GET" request to "/resource_interfaces"
297+
Then the response status code should be 200
298+
And the response should be in JSON
299+
And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
300+
And the JSON should be valid according to this schema:
301+
"""
302+
{
303+
"type": "object",
304+
"properties": {
305+
"hydra:member": {
306+
"type": "array",
307+
"items": {
308+
"type": "object",
309+
"properties": {
310+
"@type": {
311+
"type": "string",
312+
"pattern": "^ResourceInterface$"
313+
},
314+
"foo": {
315+
"type": "string",
316+
"required": "true"
317+
}
318+
}
319+
},
320+
"minItems": 1
321+
}
322+
},
323+
"required": ["hydra:member"]
324+
}
325+
"""

src/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public function create(string $resourceClass): ResourceMetadata
4848
}
4949
}
5050

51-
if (!class_exists($resourceClass) || !$resource = $this->extractor->getResources()[$resourceClass] ?? false) {
51+
if (!(class_exists($resourceClass) || interface_exists($resourceClass)) || !$resource = $this->extractor->getResources()[$resourceClass] ?? false) {
5252
return $this->handleNotFound($parentResourceMetadata, $resourceClass);
5353
}
5454

tests/Api/ResourceClassResolverTest.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
use ApiPlatform\Core\Exception\InvalidArgumentException;
1919
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface;
2020
use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection;
21+
use ApiPlatform\Core\Tests\Fixtures\DummyResourceImplementation;
22+
use ApiPlatform\Core\Tests\Fixtures\DummyResourceInterface;
2123
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy;
2224
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyCar;
2325
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance;
@@ -168,6 +170,17 @@ public function testGetResourceClassWithChildResource()
168170

169171
$resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal());
170172

171-
$this->assertEquals($resourceClassResolver->getResourceClass($t, DummyTableInheritance::class), DummyTableInheritanceChild::class);
173+
$this->assertEquals(DummyTableInheritanceChild::class, $resourceClassResolver->getResourceClass($t, DummyTableInheritance::class));
174+
}
175+
176+
public function testGetResourceClassWithInterfaceResource()
177+
{
178+
$dummy = new DummyResourceImplementation();
179+
$resourceNameCollectionFactoryProphecy = $this->prophesize(ResourceNameCollectionFactoryInterface::class);
180+
$resourceNameCollectionFactoryProphecy->create()->willReturn(new ResourceNameCollection([DummyResourceInterface::class]))->shouldBeCalled();
181+
182+
$resourceClassResolver = new ResourceClassResolver($resourceNameCollectionFactoryProphecy->reveal());
183+
$resourceClass = $resourceClassResolver->getResourceClass($dummy, DummyResourceInterface::class, true);
184+
$this->assertEquals(DummyResourceImplementation::class, $resourceClass);
172185
}
173186
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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\Tests\Fixtures;
15+
16+
class DummyResourceImplementation implements DummyResourceInterface
17+
{
18+
public function getSomething(): string
19+
{
20+
return 'What is the answer to the universe?';
21+
}
22+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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\Tests\Fixtures;
15+
16+
interface DummyResourceInterface
17+
{
18+
public function getSomething(): string;
19+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
resources:
2+
'ApiPlatform\Core\Tests\Fixtures\DummyResourceInterface': ~
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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\Tests\Fixtures\TestBundle\DataProvider;
15+
16+
use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
17+
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
18+
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
19+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\OtherResources\ResourceInterface;
20+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\OtherResources\ResourceInterfaceImplementation;
21+
22+
class ResourceInterfaceImplementationDataProvider implements ItemDataProviderInterface, CollectionDataProviderInterface, RestrictedDataProviderInterface
23+
{
24+
public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
25+
{
26+
return ResourceInterface::class === $resourceClass;
27+
}
28+
29+
public function getItem(string $resourceClass, $id, string $operationName = null, array $context = [])
30+
{
31+
return (new ResourceInterfaceImplementation())->setFoo('single item');
32+
}
33+
34+
public function getCollection(string $resourceClass, string $operationName = null)
35+
{
36+
yield (new ResourceInterfaceImplementation())->setFoo('item1');
37+
yield (new ResourceInterfaceImplementation())->setFoo('item2');
38+
}
39+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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\Tests\Fixtures\TestBundle\OtherResources;
15+
16+
interface ResourceInterface
17+
{
18+
public function getFoo(): string;
19+
}
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\Tests\Fixtures\TestBundle\OtherResources;
15+
16+
/**
17+
* @author Maxime Veber <[email protected]>
18+
*/
19+
class ResourceInterfaceImplementation implements ResourceInterface
20+
{
21+
/**
22+
* @var string
23+
*/
24+
private $foo;
25+
26+
public function setFoo(string $foo)
27+
{
28+
$this->foo = $foo;
29+
30+
return $this;
31+
}
32+
33+
public function getFoo(): string
34+
{
35+
return $this->foo;
36+
}
37+
}

tests/Fixtures/TestBundle/Resources/config/api_resources.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ resources:
33
shortName: 'fileconfigdummy'
44
description: 'Dummy resource'
55
itemOperations:
6-
custom_operation:
6+
custom_operation:
77
method: 'GET'
88
controller: 'app.config_dummy_resource.action'
99
properties:

0 commit comments

Comments
 (0)