diff --git a/src/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php b/src/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php index 456fb9e5cc7..aa267b8d7e0 100644 --- a/src/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php +++ b/src/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php @@ -87,16 +87,23 @@ private function handleNotFound(?ResourceMetadata $parentPropertyMetadata, strin } /** - * Creates a new instance of metadata if the property is not already set. + * Update resource metadata if new config is given. */ private function update(ResourceMetadata $resourceMetadata, array $metadata): ResourceMetadata { foreach (['shortName', 'description', 'iri', 'itemOperations', 'collectionOperations', 'subresourceOperations', 'graphql', 'attributes'] as $property) { - if (null === $metadata[$property] || null !== $resourceMetadata->{'get'.ucfirst($property)}()) { + $propertyMetadata = $metadata[$property]; + $parentPropertyMetadata = $resourceMetadata->{'get'.ucfirst($property)}(); + + if (null === $propertyMetadata) { continue; } - $resourceMetadata = $resourceMetadata->{'with'.ucfirst($property)}($metadata[$property]); + if (\is_array($parentPropertyMetadata) && \is_array($propertyMetadata)) { + $propertyMetadata = array_merge($parentPropertyMetadata, $propertyMetadata); + } + + $resourceMetadata = $resourceMetadata->{'with'.ucfirst($property)}($propertyMetadata); } return $resourceMetadata; diff --git a/tests/Fixtures/FileConfigurations/resources.xml b/tests/Fixtures/FileConfigurations/resources.xml index f12ed385eaa..872e6d4aae7 100644 --- a/tests/Fixtures/FileConfigurations/resources.xml +++ b/tests/Fixtures/FileConfigurations/resources.xml @@ -23,6 +23,7 @@ POST the/collection/path + 201 diff --git a/tests/Fixtures/FileConfigurations/resources.yml b/tests/Fixtures/FileConfigurations/resources.yml index b20ab46e982..514c760b6e0 100644 --- a/tests/Fixtures/FileConfigurations/resources.yml +++ b/tests/Fixtures/FileConfigurations/resources.yml @@ -12,6 +12,7 @@ resources: my_collection_op: method: 'POST' path: 'the/collection/path' + status: '201' subresourceOperations: my_collection_subresource: path: 'the/subresource/path' diff --git a/tests/Fixtures/FileConfigurations/resourcesoverride.xml b/tests/Fixtures/FileConfigurations/resourcesoverride.xml new file mode 100644 index 00000000000..63554a2e64e --- /dev/null +++ b/tests/Fixtures/FileConfigurations/resourcesoverride.xml @@ -0,0 +1,21 @@ + + + + + + + GET + the/path + + + + + POST + 200 + + + + diff --git a/tests/Fixtures/FileConfigurations/resourcesoverride.yml b/tests/Fixtures/FileConfigurations/resourcesoverride.yml new file mode 100644 index 00000000000..36d021ab1d3 --- /dev/null +++ b/tests/Fixtures/FileConfigurations/resourcesoverride.yml @@ -0,0 +1,11 @@ +resources: + 'ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\FileConfigDummy': + description: New description + itemOperations: + my_op_name: + method: 'GET' + path: 'the/path' + collectionOperations: + my_collection_op: + method: 'POST' + status: '200' diff --git a/tests/Fixtures/FileConfigurations/single_resource.yml b/tests/Fixtures/FileConfigurations/single_resource.yml index c7c22563313..46bd3b184fc 100644 --- a/tests/Fixtures/FileConfigurations/single_resource.yml +++ b/tests/Fixtures/FileConfigurations/single_resource.yml @@ -10,6 +10,7 @@ my_collection_op: method: 'POST' path: 'the/collection/path' + status: '201' subresourceOperations: my_collection_subresource: path: 'the/subresource/path' diff --git a/tests/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php b/tests/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php index 07f700a8d68..d2f20aeb9b4 100644 --- a/tests/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php +++ b/tests/Metadata/Resource/Factory/ExtractorResourceMetadataFactoryTest.php @@ -163,6 +163,23 @@ public function testXmlExistingParentResourceMetadataFactory(ResourceMetadata $e $this->assertEquals($expectedResourceMetadata, $resourceMetadata); } + /** + * @dataProvider overrideOperationsResourceMetadataProvider + */ + public function testXmlOverrideExistingParentResourceMetadataFactory(ResourceMetadata $expectedResourceMetadata) + { + $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/resourcesoverride.xml'; + + $decorated = $this->prophesize(ResourceMetadataFactoryInterface::class); + $decorated->create(FileConfigDummy::class)->willReturn($this->resourceMetadataProvider()[0][0])->shouldBeCalled(); + + $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new XmlExtractor([$configPath]), $decorated->reveal()); + + $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); + + $this->assertEquals($expectedResourceMetadata, $resourceMetadata); + } + /** * @dataProvider resourceMetadataProvider */ @@ -251,6 +268,23 @@ public function testYamlExistingParentResourceMetadataFactory(ResourceMetadata $ $this->assertEquals($expectedResourceMetadata, $resourceMetadata); } + /** + * @dataProvider overrideOperationsResourceMetadataProvider + */ + public function testYamlOverrideExistingParentResourceMetadataFactory(ResourceMetadata $expectedResourceMetadata) + { + $configPath = __DIR__.'/../../../Fixtures/FileConfigurations/resourcesoverride.yml'; + + $decorated = $this->prophesize(ResourceMetadataFactoryInterface::class); + $decorated->create(FileConfigDummy::class)->willReturn($this->resourceMetadataProvider()[0][0])->shouldBeCalled(); + + $resourceMetadataFactory = new ExtractorResourceMetadataFactory(new YamlExtractor([$configPath]), $decorated->reveal()); + + $resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class); + + $this->assertEquals($expectedResourceMetadata, $resourceMetadata); + } + public function testCreateWithMalformedYaml() { $this->expectException(InvalidArgumentException::class); diff --git a/tests/Metadata/Resource/Factory/FileConfigurationMetadataFactoryProvider.php b/tests/Metadata/Resource/Factory/FileConfigurationMetadataFactoryProvider.php index 39c81511c39..e96f93f1024 100644 --- a/tests/Metadata/Resource/Factory/FileConfigurationMetadataFactoryProvider.php +++ b/tests/Metadata/Resource/Factory/FileConfigurationMetadataFactoryProvider.php @@ -36,7 +36,7 @@ public function resourceMetadataProvider() 'my_other_op_name' => ['method' => 'POST'], ], 'collectionOperations' => [ - 'my_collection_op' => ['method' => 'POST', 'path' => 'the/collection/path'], + 'my_collection_op' => ['method' => 'POST', 'path' => 'the/collection/path', 'status' => '201'], ], 'subresourceOperations' => [ 'my_collection_subresource' => ['path' => 'the/subresource/path'], @@ -111,4 +111,22 @@ public function legacyOperationsResourceMetadataProvider() return [[$resourceMetadata]]; } + + public function overrideOperationsResourceMetadataProvider() + { + $resourceMetadata = $this->resourceMetadataProvider()[0][0]; + + $resourceMetadata = $resourceMetadata->withDescription('New description'); + + $resourceMetadata = $resourceMetadata->withItemOperations([ + 'my_op_name' => ['method' => 'GET', 'path' => 'the/path'], + 'my_other_op_name' => ['method' => 'POST'], + ]); + + $resourceMetadata = $resourceMetadata->withCollectionOperations([ + 'my_collection_op' => ['method' => 'POST', 'status' => '200'], + ]); + + return [[$resourceMetadata]]; + } }