Skip to content

Commit 6332272

Browse files
committed
Add support for ignore property exist test for interface
1. it makes no sens to check if an interface exists in case it's an interface 2. If the property is not recognized as one and there is no identifier, then api platform will not be able to call the DataProvider for a given item and interface as a resource is an incomplete feature.
1 parent e0c6134 commit 6332272

File tree

8 files changed

+85
-4
lines changed

8 files changed

+85
-4
lines changed

features/main/table_inheritance.feature

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,10 @@ Feature: Table inheritance
314314
"foo": {
315315
"type": "string",
316316
"required": "true"
317+
},
318+
"bar": {
319+
"type": "string",
320+
"required": "true"
317321
}
318322
}
319323
},
@@ -323,3 +327,38 @@ Feature: Table inheritance
323327
"required": ["hydra:member"]
324328
}
325329
"""
330+
331+
Scenario: Get an interface resource item
332+
When I send a "GET" request to "/resource_interfaces/some-id"
333+
Then the response status code should be 200
334+
And the response should be in JSON
335+
And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
336+
And the JSON should be valid according to this schema:
337+
"""
338+
{
339+
"type": "object",
340+
"properties": {
341+
"context": {
342+
"type": "string",
343+
"pattern": "ResourceInterface$"
344+
},
345+
"@id": {
346+
"type": "string",
347+
"pattern": "ResourceInterface$"
348+
},
349+
"@type": {
350+
"type": "string",
351+
"pattern": "^ResourceInterface$"
352+
},
353+
"foo": {
354+
"type": "string",
355+
"required": "true"
356+
},
357+
"bar": {
358+
"type": "string",
359+
"required": "true",
360+
"pattern": "^bar$"
361+
}
362+
}
363+
}
364+
"""

src/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,15 @@ public function create(string $resourceClass, string $property, array $options =
4848
}
4949
}
5050

51+
try {
52+
$isInterface = (new \ReflectionClass($resourceClass))->isInterface();
53+
} catch (\ReflectionException $e) {
54+
$isInterface = false;
55+
}
56+
5157
if (
52-
!property_exists($resourceClass, $property) ||
53-
!$propertyMetadata = $this->extractor->getResources()[$resourceClass]['properties'][$property] ?? false
58+
!property_exists($resourceClass, $property) && !$isInterface ||
59+
empty($propertyMetadata = $this->extractor->getResources()[$resourceClass]['properties'][$property] ?? [])
5460
) {
5561
return $this->handleNotFound($parentPropertyMetadata, $resourceClass, $property);
5662
}
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
resources:
2-
'ApiPlatform\Core\Tests\Fixtures\DummyResourceInterface': ~
2+
'ApiPlatform\Core\Tests\Fixtures\DummyResourceInterface':
3+
properties:
4+
something:
5+
identifier: true
6+
somethingElse:
7+
writable: false
8+
readable: true

tests/Fixtures/TestBundle/DataProvider/ResourceInterfaceImplementationDataProvider.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ public function supports(string $resourceClass, string $operationName = null, ar
2828

2929
public function getItem(string $resourceClass, $id, string $operationName = null, array $context = [])
3030
{
31-
return (new ResourceInterfaceImplementation())->setFoo('single item');
31+
if ('some-id' === $id) {
32+
return (new ResourceInterfaceImplementation())->setFoo('single item');
33+
}
34+
35+
return null;
3236
}
3337

3438
public function getCollection(string $resourceClass, string $operationName = null)

tests/Fixtures/TestBundle/OtherResources/ResourceInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@
1616
interface ResourceInterface
1717
{
1818
public function getFoo(): string;
19+
20+
public function getBar(): string;
1921
}

tests/Fixtures/TestBundle/OtherResources/ResourceInterfaceImplementation.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,9 @@ public function getFoo(): string
3434
{
3535
return $this->foo;
3636
}
37+
38+
public function getBar(): string
39+
{
40+
return 'bar';
41+
}
3742
}

tests/Fixtures/app/config/api_platform/flex.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ ApiPlatform\Core\Tests\Fixtures\TestBundle\OtherResources\ResourceInterface:
77
collectionOperations:
88
get:
99
method: 'GET'
10+
11+
properties:
12+
foo:
13+
identifier: true

tests/Metadata/Property/Factory/ExtractorPropertyMetadataFactoryTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
2222
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
2323
use ApiPlatform\Core\Metadata\Property\SubresourceMetadata;
24+
use ApiPlatform\Core\Tests\Fixtures\DummyResourceInterface;
2425
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\FileConfigDummy;
2526
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy;
2627
use Doctrine\Common\Collections\ArrayCollection;
@@ -243,4 +244,18 @@ public function testCreateWithMalformedYaml()
243244

244245
(new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class, 'foo');
245246
}
247+
248+
public function testItExtractPropertiesFromInterfaceResources()
249+
{
250+
$configPath = __DIR__.'/../../../Fixtures/FileConfigurations/interface_resource.yml';
251+
252+
$propertyMetadataFactory = new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath]));
253+
$metadataSomething = $propertyMetadataFactory->create(DummyResourceInterface::class, 'something');
254+
$metadataSomethingElse = $propertyMetadataFactory->create(DummyResourceInterface::class, 'somethingElse');
255+
256+
$this->assertInstanceOf(PropertyMetadata::class, $metadataSomething);
257+
$this->assertInstanceOf(PropertyMetadata::class, $metadataSomethingElse);
258+
$this->assertTrue($metadataSomething->isIdentifier());
259+
$this->assertFalse($metadataSomethingElse->isWritable());
260+
}
246261
}

0 commit comments

Comments
 (0)