Skip to content

Commit ab77784

Browse files
authored
Merge pull request #573 from soyuka/individual-resources
"resources" on single resource declarations is optional
2 parents cf27cb3 + 53b3ce7 commit ab77784

File tree

8 files changed

+164
-21
lines changed

8 files changed

+164
-21
lines changed

src/Metadata/Resource/Factory/XmlResourceMetadataFactory.php

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,22 +61,18 @@ public function create(string $resourceClass) : ResourceMetadata
6161
$metadata = null;
6262

6363
foreach ($this->paths as $path) {
64-
$this->xmlParser->loadXML(file_get_contents($path));
64+
$resources = $this->getResourcesDom($path);
6565

6666
$internalErrors = libxml_use_internal_errors(true);
6767

68-
if (false === @$this->xmlParser->schemaValidate(self::RESOURCE_SCHEMA)) {
68+
if (false === @$resources->schemaValidate(self::RESOURCE_SCHEMA)) {
6969
throw new \InvalidArgumentException(sprintf('XML Schema loaded from path %s is not valid! Errors: %s', realpath($path), implode("\n", $this->getXmlErrors($internalErrors))));
7070
}
7171

7272
libxml_clear_errors();
7373
libxml_use_internal_errors($internalErrors);
7474

75-
$xpath = new \DOMXpath($this->xmlParser);
76-
77-
$resources = $xpath->query('/resources/resource');
78-
79-
foreach ($resources as $resource) {
75+
foreach ($resources->getElementsByTagName('resource') as $resource) {
8076
$class = $resource->getAttribute('class');
8177

8278
if ($resourceClass !== $class) {
@@ -93,6 +89,8 @@ public function create(string $resourceClass) : ResourceMetadata
9389
return $this->handleNotFound($parentResourceMetadata, $resourceClass);
9490
}
9591

92+
$xpath = new \DOMXpath($resources);
93+
9694
$metadata = [
9795
'shortName' => $metadata->getAttribute('shortName') ?: null,
9896
'description' => $metadata->getAttribute('description') ?: null,
@@ -126,6 +124,31 @@ public function create(string $resourceClass) : ResourceMetadata
126124
return $resourceMetadata;
127125
}
128126

127+
/**
128+
* Creates a DOMDocument based on `resource` tags of a file-loaded xml document.
129+
*
130+
* @param string $path the xml file path
131+
*
132+
* @return \DOMDocument
133+
*/
134+
private function getResourcesDom(string $path) : \DOMDocument
135+
{
136+
$doc = new \DOMDocument('1.0', 'utf-8');
137+
$root = $doc->createElement('resources');
138+
$doc->appendChild($root);
139+
140+
$this->xmlParser->loadXML(file_get_contents($path));
141+
142+
$xpath = new \DOMXpath($this->xmlParser);
143+
$resources = $xpath->query('//resource');
144+
145+
foreach ($resources as $resource) {
146+
$root->appendChild($doc->importNode($resource, true));
147+
}
148+
149+
return $doc;
150+
}
151+
129152
/**
130153
* Get operations from xml.
131154
*

src/Metadata/Resource/Factory/XmlResourceNameCollectionFactory.php

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,29 +51,50 @@ public function create() : ResourceNameCollection
5151
}
5252

5353
foreach ($this->paths as $path) {
54-
$this->xmlParser->loadXML(file_get_contents($path));
54+
$resources = $this->getResourcesDom($path);
5555

5656
$internalErrors = libxml_use_internal_errors(true);
5757

58-
if (false === @$this->xmlParser->schemaValidate(self::RESOURCE_SCHEMA)) {
58+
if (false === @$resources->schemaValidate(self::RESOURCE_SCHEMA)) {
5959
throw new \InvalidArgumentException(sprintf('XML Schema loaded from path %s is not valid! Errors: %s', realpath($path), implode("\n", $this->getXmlErrors($internalErrors))));
6060
}
6161

6262
libxml_clear_errors();
6363
libxml_use_internal_errors($internalErrors);
6464

65-
$xpath = new \DOMXpath($this->xmlParser);
66-
67-
$resources = $xpath->query('/resources/resource');
68-
69-
foreach ($resources as $resource) {
65+
foreach ($resources->getElementsByTagName('resource') as $resource) {
7066
$classes[$resource->getAttribute('class')] = true;
7167
}
7268
}
7369

7470
return new ResourceNameCollection(array_keys($classes));
7571
}
7672

73+
/**
74+
* Creates a DOMDocument based on `resource` tags of a file-loaded xml document.
75+
*
76+
* @param string $path the xml file path
77+
*
78+
* @return \DOMDocument
79+
*/
80+
private function getResourcesDom(string $path) : \DOMDocument
81+
{
82+
$doc = new \DOMDocument('1.0', 'utf-8');
83+
$root = $doc->createElement('resources');
84+
$doc->appendChild($root);
85+
86+
$this->xmlParser->loadXML(file_get_contents($path));
87+
88+
$xpath = new \DOMXpath($this->xmlParser);
89+
$resources = $xpath->query('//resource');
90+
91+
foreach ($resources as $resource) {
92+
$root->appendChild($doc->importNode($resource, true));
93+
}
94+
95+
return $doc;
96+
}
97+
7798
/**
7899
* Returns the XML errors of the internal XML parser.
79100
*

src/Metadata/Resource/Factory/YamlResourceMetadataFactory.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ public function create(string $resourceClass) : ResourceMetadata
6060
$metadata = null;
6161

6262
foreach ($this->paths as $path) {
63-
$resources = $this->yamlParser->parse(file_get_contents($path))['resources'];
63+
$resources = $this->yamlParser->parse(file_get_contents($path));
64+
65+
$resources = $resources['resources'] ?? $resources;
6466

6567
foreach ($resources as $resource) {
6668
if (!isset($resource['class'])) {

src/Metadata/Resource/Factory/YamlResourceNameCollectionFactory.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ public function create() : ResourceNameCollection
5050
}
5151

5252
foreach ($this->paths as $path) {
53-
$resources = $this->yamlParser->parse(file_get_contents($path))['resources'];
53+
$resources = $this->yamlParser->parse(file_get_contents($path));
54+
55+
$resources = $resources['resources'] ?? $resources;
5456

5557
foreach ($resources as $resource) {
5658
if (!isset($resource['class'])) {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<resource class="ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\FileConfigDummy" shortName="thedummyshortname" description="Dummy resource" iri="someirischema">
3+
<itemOperations>
4+
<operation key="my_op_name" method="GET" />
5+
<operation key="my_other_op_name" method="POST" />
6+
</itemOperations>
7+
<collectionOperations>
8+
<operation key="my_collection_op" method="POST" path="the/collection/path"/>
9+
</collectionOperations>
10+
<attributes>
11+
<attribute key="normalization_context">
12+
<attribute key="groups">
13+
<attribute>default</attribute>
14+
</attribute>
15+
</attribute>
16+
<attribute key="denormalization_context">
17+
<attribute key="groups">
18+
<attribute>default</attribute>
19+
</attribute>
20+
</attribute>
21+
<attribute key="hydra_context">
22+
<attribute key="@type">hydra:Operation</attribute>
23+
<attribute key="@hydra:title">File config Dummy</attribute>
24+
</attribute>
25+
</attributes>
26+
</resource>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
configdummy:
2+
shortName: 'thedummyshortname'
3+
description: 'Dummy resource'
4+
class: 'ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\FileConfigDummy'
5+
itemOperations:
6+
my_op_name:
7+
method: 'GET'
8+
my_other_op_name:
9+
method: 'POST'
10+
collectionOperations:
11+
my_collection_op:
12+
method: 'POST'
13+
path: 'the/collection/path'
14+
attributes:
15+
normalization_context:
16+
groups: ['default']
17+
denormalization_context:
18+
groups: ['default']
19+
hydra_context:
20+
'@type': 'hydra:Operation'
21+
'@hydra:title': 'File config Dummy'
22+
iri: 'someirischema'
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
resources:
2-
single_file_config:
3-
shortName: 'single_file_config'
4-
description: 'File configured resource'
5-
class: 'ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\SingleFileConfigDummy'
1+
single_file_config:
2+
shortName: 'single_file_config'
3+
description: 'File configured resource'
4+
class: 'ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\SingleFileConfigDummy'

tests/Metadata/Resource/Factory/FileConfigurationMetadataTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,52 @@ public function testYamlOptionalResourceMetadata($expectedResourceMetadata)
192192
$this->assertInstanceOf(ResourceMetadata::class, $resourceMetadata);
193193
$this->assertEquals($expectedResourceMetadata, $resourceMetadata);
194194
}
195+
196+
public function testXmlSingleResourceName()
197+
{
198+
$configPath = __DIR__.'/../../../Fixtures/FileConfigurations/single_resource.xml';
199+
$xmlResourceNameCollectionFactory = new XmlResourceNameCollectionFactory([$configPath]);
200+
201+
$this->assertEquals($xmlResourceNameCollectionFactory->create(), new ResourceNameCollection([
202+
FileConfigDummy::class,
203+
]));
204+
}
205+
206+
/**
207+
* @dataProvider resourceMetadataProvider
208+
*/
209+
public function testXmlSingleResourceMetadata($expectedResourceMetadata)
210+
{
211+
$configPath = __DIR__.'/../../../Fixtures/FileConfigurations/single_resource.xml';
212+
213+
$resourceMetadataFactory = new XmlResourceMetadataFactory([$configPath]);
214+
$resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class);
215+
216+
$this->assertInstanceOf(ResourceMetadata::class, $resourceMetadata);
217+
$this->assertEquals($expectedResourceMetadata, $resourceMetadata);
218+
}
219+
220+
public function testYamlSingleResourceName()
221+
{
222+
$configPath = __DIR__.'/../../../Fixtures/FileConfigurations/single_resource.yml';
223+
$yamlResourceNameCollectionFactory = new YamlResourceNameCollectionFactory([$configPath]);
224+
225+
$this->assertEquals($yamlResourceNameCollectionFactory->create(), new ResourceNameCollection([
226+
FileConfigDummy::class,
227+
]));
228+
}
229+
230+
/**
231+
* @dataProvider resourceMetadataProvider
232+
*/
233+
public function testYamlSingleResourceMetadata(ResourceMetadata $expectedResourceMetadata)
234+
{
235+
$configPath = __DIR__.'/../../../Fixtures/FileConfigurations/single_resource.yml';
236+
237+
$resourceMetadataFactory = new YamlResourceMetadataFactory([$configPath]);
238+
$resourceMetadata = $resourceMetadataFactory->create(FileConfigDummy::class);
239+
240+
$this->assertInstanceOf(ResourceMetadata::class, $resourceMetadata);
241+
$this->assertEquals($expectedResourceMetadata, $resourceMetadata);
242+
}
195243
}

0 commit comments

Comments
 (0)