Skip to content

Ignore property that does not exist for interfaces (identifiers for interfaces) #2086

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 30 additions & 7 deletions features/main/table_inheritance.feature
Original file line number Diff line number Diff line change
Expand Up @@ -307,15 +307,11 @@ Feature: Table inheritance
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"pattern": "^ResourceInterface$"
},
"@id": {
"foo": {
"type": "string",
"pattern": "^_:"
"required": "true"
},
"foo": {
"fooz": {
"type": "string",
"required": "true"
}
Expand All @@ -327,3 +323,30 @@ Feature: Table inheritance
"required": ["hydra:member"]
}
"""

Scenario: Get an interface resource item
When I send a "GET" request to "/resource_interfaces/some-id"
Then the response status code should be 200
And the response should be in JSON
And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
And the JSON should be valid according to this schema:
"""
{
"type": "object",
"properties": {
"context": {
"type": "string",
"pattern": "ResourceInterface$"
},
"foo": {
"type": "string",
"required": "true"
},
"fooz": {
"type": "string",
"required": "true",
"pattern": "fooz"
}
}
}
"""
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ public function create(string $resourceClass, string $property, array $options =
}
}

$isInterface = interface_exists($resourceClass);

if (
!property_exists($resourceClass, $property) ||
!$propertyMetadata = $this->extractor->getResources()[$resourceClass]['properties'][$property] ?? false
!property_exists($resourceClass, $property) && !$isInterface ||
null === ($propertyMetadata = $this->extractor->getResources()[$resourceClass]['properties'][$property] ?? null)
) {
return $this->handleNotFound($parentPropertyMetadata, $resourceClass, $property);
}
Expand Down
8 changes: 7 additions & 1 deletion tests/Fixtures/FileConfigurations/interface_resource.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
resources:
'ApiPlatform\Core\Tests\Fixtures\DummyResourceInterface': ~
'ApiPlatform\Core\Tests\Fixtures\DummyResourceInterface':
properties:
something:
identifier: true
somethingElse:
writable: false
readable: true
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ public function supports(string $resourceClass, string $operationName = null, ar

public function getItem(string $resourceClass, $id, string $operationName = null, array $context = [])
{
return (new ResourceInterfaceImplementation())->setFoo('single item');
if ('some-id' === $id) {
return (new ResourceInterfaceImplementation())->setFoo('single item');
}

return null;
}

public function getCollection(string $resourceClass, string $operationName = null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@
interface ResourceInterface
{
public function getFoo(): string;

public function getFooz(): string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,9 @@ public function getBar(): ?string
{
return $this->bar;
}

public function getFooz(): string
{
return 'fooz';
}
}
4 changes: 4 additions & 0 deletions tests/Fixtures/TestBundle/Resources/config/api_resources.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ resources:
collectionOperations:
get:
method: 'GET'

properties:
foo:
identifier: true
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
use ApiPlatform\Core\Metadata\Property\SubresourceMetadata;
use ApiPlatform\Core\Tests\Fixtures\DummyResourceInterface;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\FileConfigDummy;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy;
use Doctrine\Common\Collections\ArrayCollection;
Expand Down Expand Up @@ -237,4 +238,18 @@ public function testCreateWithMalformedYaml()

(new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath])))->create(FileConfigDummy::class, 'foo');
}

public function testItExtractPropertiesFromInterfaceResources()
{
$configPath = __DIR__.'/../../../Fixtures/FileConfigurations/interface_resource.yml';

$propertyMetadataFactory = new ExtractorPropertyMetadataFactory(new YamlExtractor([$configPath]));
$metadataSomething = $propertyMetadataFactory->create(DummyResourceInterface::class, 'something');
$metadataSomethingElse = $propertyMetadataFactory->create(DummyResourceInterface::class, 'somethingElse');

$this->assertInstanceOf(PropertyMetadata::class, $metadataSomething);
$this->assertInstanceOf(PropertyMetadata::class, $metadataSomethingElse);
$this->assertTrue($metadataSomething->isIdentifier());
$this->assertFalse($metadataSomethingElse->isWritable());
}
}