Skip to content

Commit 17c321f

Browse files
author
abluchet
committed
Add SubresourceOperations to metadata
1 parent 1e5b1ca commit 17c321f

16 files changed

+105
-63
lines changed

src/Annotation/ApiResource.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ final class ApiResource
4848
*/
4949
public $collectionOperations;
5050

51+
/**
52+
* @var array
53+
*/
54+
public $subresourceOperations;
55+
5156
/**
5257
* @var array
5358
*/

src/Bridge/Symfony/Routing/ApiLoader.php

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,6 @@ public function load($data, $type = null): RouteCollection
8787

8888
if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) {
8989
foreach ($collectionOperations as $operationName => $operation) {
90-
if ('subresource' === substr($operationName, -11)) {
91-
continue;
92-
}
9390
$this->addRoute($routeCollection, $resourceClass, $operationName, $operation, $resourceShortName, OperationType::COLLECTION);
9491
}
9592
}
@@ -118,13 +115,13 @@ public function load($data, $type = null): RouteCollection
118115
'collection' => $operation['collection'],
119116
'operationId' => $operationId,
120117
],
121-
] + $operations['defaults'],
122-
$operation['requirements'],
123-
$operation['options'],
124-
$operation['host'],
125-
$operation['schemes'],
118+
] + $operation['defaults'] ?? [],
119+
$operation['requirements'] ?? [],
120+
$operation['options'] ?? [],
121+
$operation['host'] ?? '',
122+
$operation['schemes'] ?? [],
126123
['GET'],
127-
$operation['condition']
124+
$operation['condition'] ?? ''
128125
));
129126
}
130127
}

src/Metadata/Extractor/XmlExtractor.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ protected function extractPath(string $path)
4747
'iri' => $this->phpize($resource, 'iri', 'string'),
4848
'itemOperations' => $this->getOperations($resource, 'itemOperation'),
4949
'collectionOperations' => $this->getOperations($resource, 'collectionOperation'),
50+
'subresourceOperations' => $this->getOperations($resource, 'subresourceOperation'),
5051
'attributes' => $this->getAttributes($resource, 'attribute') ?: null,
5152
'properties' => $this->getProperties($resource) ?: null,
5253
];

src/Metadata/Extractor/YamlExtractor.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ private function extractResources(array $resourcesYaml, string $path)
6767
'iri' => $this->phpize($resourceYaml, 'iri', 'string'),
6868
'itemOperations' => $resourceYaml['itemOperations'] ?? null,
6969
'collectionOperations' => $resourceYaml['collectionOperations'] ?? null,
70+
'subresourceOperations' => $resourceYaml['subresourceOperations'] ?? null,
7071
'attributes' => $resourceYaml['attributes'] ?? null,
7172
];
7273

src/Metadata/Resource/Factory/AnnotationResourceMetadataFactory.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,13 @@ private function createMetadata(ApiResource $annotation, ResourceMetadata $paren
9090
$annotation->iri,
9191
$annotation->itemOperations,
9292
$annotation->collectionOperations,
93-
$annotation->attributes
93+
$annotation->attributes,
94+
$annotation->subresourceOperations
9495
);
9596
}
9697

9798
$resourceMetadata = $parentResourceMetadata;
98-
foreach (['shortName', 'description', 'iri', 'itemOperations', 'collectionOperations', 'attributes'] as $property) {
99+
foreach (['shortName', 'description', 'iri', 'itemOperations', 'collectionOperations', 'subresourceOperations', 'attributes'] as $property) {
99100
$resourceMetadata = $this->createWith($resourceMetadata, $property, $annotation->$property);
100101
}
101102

src/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ private function handleNotFound(ResourceMetadata $parentPropertyMetadata = null,
8484
*/
8585
private function update(ResourceMetadata $resourceMetadata, array $metadata): ResourceMetadata
8686
{
87-
foreach (['shortName', 'description', 'iri', 'itemOperations', 'collectionOperations', 'attributes'] as $property) {
87+
foreach (['shortName', 'description', 'iri', 'itemOperations', 'collectionOperations', 'subresourceOperations', 'attributes'] as $property) {
8888
if (null === $metadata[$property] || null !== $resourceMetadata->{'get'.ucfirst($property)}()) {
8989
continue;
9090
}

src/Metadata/Resource/ResourceMetadata.php

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,17 @@ final class ResourceMetadata
2525
private $iri;
2626
private $itemOperations;
2727
private $collectionOperations;
28+
private $subresourceOperations;
2829
private $attributes;
2930

30-
public function __construct(string $shortName = null, string $description = null, string $iri = null, array $itemOperations = null, array $collectionOperations = null, array $attributes = null)
31+
public function __construct(string $shortName = null, string $description = null, string $iri = null, array $itemOperations = null, array $collectionOperations = null, array $attributes = null, array $subresourceOperations = null)
3132
{
3233
$this->shortName = $shortName;
3334
$this->description = $description;
3435
$this->iri = $iri;
3536
$this->itemOperations = $itemOperations;
3637
$this->collectionOperations = $collectionOperations;
38+
$this->subresourceOperations = $subresourceOperations;
3739
$this->attributes = $attributes;
3840
}
3941

@@ -49,10 +51,6 @@ public function getShortName()
4951

5052
/**
5153
* Returns a new instance with the given short name.
52-
*
53-
* @param string $shortName
54-
*
55-
* @return self
5654
*/
5755
public function withShortName(string $shortName): self
5856
{
@@ -74,10 +72,6 @@ public function getDescription()
7472

7573
/**
7674
* Returns a new instance with the given description.
77-
*
78-
* @param string $description
79-
*
80-
* @return self
8175
*/
8276
public function withDescription(string $description): self
8377
{
@@ -99,10 +93,6 @@ public function getIri()
9993

10094
/**
10195
* Returns a new instance with the given IRI.
102-
*
103-
* @param string $iri
104-
*
105-
* @return self
10696
*/
10797
public function withIri(string $iri): self
10898
{
@@ -124,10 +114,6 @@ public function getItemOperations()
124114

125115
/**
126116
* Returns a new instance with the given item operations.
127-
*
128-
* @param array $itemOperations
129-
*
130-
* @return self
131117
*/
132118
public function withItemOperations(array $itemOperations): self
133119
{
@@ -149,10 +135,6 @@ public function getCollectionOperations()
149135

150136
/**
151137
* Returns a new instance with the given collection operations.
152-
*
153-
* @param array $collectionOperations
154-
*
155-
* @return self
156138
*/
157139
public function withCollectionOperations(array $collectionOperations): self
158140
{
@@ -162,13 +144,31 @@ public function withCollectionOperations(array $collectionOperations): self
162144
return $metadata;
163145
}
164146

147+
/**
148+
* Gets subresource operations.
149+
*
150+
* @return array|null
151+
*/
152+
public function getSubresourceOperations()
153+
{
154+
return $this->subresourceOperations;
155+
}
156+
157+
/**
158+
* Returns a new instance with the given subresource operations.
159+
*/
160+
public function withSubresourceOperations(array $subresourceOperations): self
161+
{
162+
$metadata = clone $this;
163+
$metadata->subresourceOperations = $subresourceOperations;
164+
165+
return $metadata;
166+
}
167+
165168
/**
166169
* Gets a collection operation attribute, optionally fallback to a resource attribute.
167170
*
168-
* @param string|null $operationName
169-
* @param string $key
170-
* @param mixed $defaultValue
171-
* @param bool $resourceFallback
171+
* @param mixed $defaultValue
172172
*
173173
* @return mixed
174174
*/
@@ -180,10 +180,7 @@ public function getCollectionOperationAttribute(string $operationName = null, st
180180
/**
181181
* Gets an item operation attribute, optionally fallback to a resource attribute.
182182
*
183-
* @param string|null $operationName
184-
* @param string $key
185-
* @param mixed $defaultValue
186-
* @param bool $resourceFallback
183+
* @param mixed $defaultValue
187184
*
188185
* @return mixed
189186
*/
@@ -192,14 +189,22 @@ public function getItemOperationAttribute(string $operationName = null, string $
192189
return $this->getOperationAttribute($this->itemOperations, $operationName, $key, $defaultValue, $resourceFallback);
193190
}
194191

192+
/**
193+
* Gets a subresource operation attribute, optionally fallback to a resource attribute.
194+
*
195+
* @param mixed $defaultValue
196+
*
197+
* @return mixed
198+
*/
199+
public function getSubresourceOperationAttribute(string $operationName = null, string $key, $defaultValue = null, bool $resourceFallback = false)
200+
{
201+
return $this->getOperationAttribute($this->subresourceOperations, $operationName, $key, $defaultValue, $resourceFallback);
202+
}
203+
195204
/**
196205
* Gets an operation attribute, optionally fallback to a resource attribute.
197206
*
198-
* @param array|null $operations
199-
* @param string|null $operationName
200-
* @param string $key
201-
* @param mixed $defaultValue
202-
* @param bool $resourceFallback
207+
* @param mixed $defaultValue
203208
*
204209
* @return mixed
205210
*/
@@ -229,8 +234,7 @@ public function getAttributes()
229234
/**
230235
* Gets an attribute.
231236
*
232-
* @param string $key
233-
* @param mixed $defaultValue
237+
* @param mixed $defaultValue
234238
*
235239
* @return mixed
236240
*/
@@ -245,10 +249,6 @@ public function getAttribute(string $key, $defaultValue = null)
245249

246250
/**
247251
* Returns a new instance with the given attribute.
248-
*
249-
* @param array $attributes
250-
*
251-
* @return self
252252
*/
253253
public function withAttributes(array $attributes): self
254254
{

src/Metadata/schema/metadata.xsd

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<xsd:element name="property" minOccurs="0" maxOccurs="unbounded" type="property"/>
2323
<xsd:element name="itemOperations" minOccurs="0" maxOccurs="unbounded" type="itemOperations"/>
2424
<xsd:element name="collectionOperations" minOccurs="0" maxOccurs="unbounded" type="collectionOperations"/>
25+
<xsd:element name="subresourceOperations" minOccurs="0" maxOccurs="unbounded" type="subresourceOperations"/>
2526
</xsd:sequence>
2627

2728
<xsd:attribute type="xsd:string" name="class" use="required"/>
@@ -56,6 +57,19 @@
5657
<xsd:attribute type="xsd:string" name="name"/>
5758
</xsd:complexType>
5859

60+
<xsd:complexType name="subresourceOperations">
61+
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
62+
<xsd:element name="subresourceOperation" minOccurs="0" maxOccurs="unbounded" type="subresourceOperation"/>
63+
</xsd:sequence>
64+
</xsd:complexType>
65+
66+
<xsd:complexType name="subresourceOperation">
67+
<xsd:sequence minOccurs="1" maxOccurs="unbounded">
68+
<xsd:element name="attribute" minOccurs="1" maxOccurs="unbounded" type="attribute"/>
69+
</xsd:sequence>
70+
<xsd:attribute type="xsd:string" name="name"/>
71+
</xsd:complexType>
72+
5973
<xsd:complexType name="attribute" mixed="true">
6074
<xsd:choice maxOccurs="unbounded">
6175
<xsd:element name="attribute" type="attribute" minOccurs="0" maxOccurs="unbounded" />

src/Operation/Factory/SubresourceOperationFactory.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ private function computeSubresourceOperations(string $resourceClass, array &$tre
102102
self::SUBRESOURCE_SUFFIX
103103
);
104104

105-
$collectionOperation = $rootResourceMetadata->getCollectionOperations()[$operation['operation_name']] ?? [];
105+
$subresourceOperation = $rootResourceMetadata->getSubresourceOperations()[$operation['operation_name']] ?? [];
106106

107107
$operation['route_name'] = sprintf(
108108
'%s%s_%s',
@@ -111,7 +111,7 @@ private function computeSubresourceOperations(string $resourceClass, array &$tre
111111
$operation['operation_name']
112112
);
113113

114-
$operation['path'] = $collectionOperation['path'] ?? sprintf(
114+
$operation['path'] = $subresourceOperation['path'] ?? sprintf(
115115
'/%s/{id}/%s%s',
116116
$this->pathSegmentNameGenerator->getSegmentName($rootShortname, true),
117117
$this->pathSegmentNameGenerator->getSegmentName($operation['property'], $operation['collection']),
@@ -134,10 +134,10 @@ private function computeSubresourceOperations(string $resourceClass, array &$tre
134134
$operation['shortNames'][] = $resourceMetadata->getShortName();
135135
}
136136

137-
$collectionOperation = $rootResourceMetadata->getCollectionOperations()[$operation['operation_name']] ?? [];
137+
$subresourceOperation = $rootResourceMetadata->getSubresourceOperations()[$operation['operation_name']] ?? [];
138138

139-
if (isset($collectionOperation['path'])) {
140-
$operation['path'] = $collectionOperation['path'];
139+
if (isset($subresourceOperation['path'])) {
140+
$operation['path'] = $subresourceOperation['path'];
141141
} else {
142142
$operation['path'] = str_replace(self::FORMAT_SUFFIX, '', $parentOperation['path']);
143143
if ($parentOperation['collection']) {
@@ -149,7 +149,7 @@ private function computeSubresourceOperations(string $resourceClass, array &$tre
149149
}
150150

151151
foreach (self::ROUTE_OPTIONS as $routeOption => $defaultValue) {
152-
$operation[$routeOption] = $collectionOperation[$routeOption] ?? $defaultValue;
152+
$operation[$routeOption] = $subresourceOperation[$routeOption] ?? $defaultValue;
153153
}
154154

155155
$tree[$operation['route_name']] = $operation;

tests/Fixtures/FileConfigurations/resources.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@
2525
<attribute name="path">the/collection/path</attribute>
2626
</collectionOperation>
2727
</collectionOperations>
28+
<subresourceOperations>
29+
<subresourceOperation name="my_collection_subresource">
30+
<attribute name="path">the/subresource/path</attribute>
31+
</subresourceOperation>
32+
</subresourceOperations>
2833
<attribute name="normalization_context">
2934
<attribute name="groups">
3035
<attribute>default</attribute>

tests/Fixtures/FileConfigurations/resources.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ resources:
1212
my_collection_op:
1313
method: 'POST'
1414
path: 'the/collection/path'
15+
subresourceOperations:
16+
my_collection_subresource:
17+
path: 'the/subresource/path'
1518
attributes:
1619
normalization_context:
1720
groups: ['default']

tests/Fixtures/FileConfigurations/single_resource.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
my_collection_op:
1111
method: 'POST'
1212
path: 'the/collection/path'
13+
subresourceOperations:
14+
my_collection_subresource:
15+
path: 'the/subresource/path'
1316
attributes:
1417
normalization_context:
1518
groups: ['default']

tests/Metadata/Resource/Factory/AnnotationResourceMetadataFactoryTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public function testCreate(ProphecyInterface $reader, ProphecyInterface $decorat
4242
$this->assertEquals('http://example.com', $metadata->getIri());
4343
$this->assertEquals(['foo' => ['bar' => true]], $metadata->getItemOperations());
4444
$this->assertEquals(['baz' => ['tab' => false]], $metadata->getCollectionOperations());
45+
$this->assertEquals(['sub' => ['bus' => false]], $metadata->getSubresourceOperations());
4546
$this->assertEquals(['a' => 1], $metadata->getAttributes());
4647
}
4748

@@ -53,6 +54,7 @@ public function getCreateDependencies()
5354
$annotation->iri = 'http://example.com';
5455
$annotation->itemOperations = ['foo' => ['bar' => true]];
5556
$annotation->collectionOperations = ['baz' => ['tab' => false]];
57+
$annotation->subresourceOperations = ['sub' => ['bus' => false]];
5658
$annotation->attributes = ['a' => 1];
5759

5860
$reader = $this->prophesize(Reader::class);

tests/Metadata/Resource/Factory/FileConfigurationMetadataFactoryProvider.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ public function resourceMetadataProvider()
3838
'collectionOperations' => [
3939
'my_collection_op' => ['method' => 'POST', 'path' => 'the/collection/path'],
4040
],
41+
'subresourceOperations' => [
42+
'my_collection_subresource' => ['path' => 'the/subresource/path'],
43+
],
4144
'iri' => 'someirischema',
4245
'attributes' => [
4346
'normalization_context' => [
@@ -53,7 +56,7 @@ public function resourceMetadataProvider()
5356
],
5457
];
5558

56-
foreach (['shortName', 'description', 'itemOperations', 'collectionOperations', 'iri', 'attributes'] as $property) {
59+
foreach (['shortName', 'description', 'itemOperations', 'collectionOperations', 'subresourceOperations', 'iri', 'attributes'] as $property) {
5760
$wither = 'with'.ucfirst($property);
5861
$resourceMetadata = $resourceMetadata->$wither($metadata[$property]);
5962
}

0 commit comments

Comments
 (0)