Skip to content

Commit 8d9f3a4

Browse files
Refacto ResourceMetadata in favor of OperationCollectionMetadata
1 parent ff701dd commit 8d9f3a4

File tree

101 files changed

+1585
-994
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+1585
-994
lines changed

src/Annotation/ApiResource.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
* @Attribute("securityMessage", type="string"),
6464
* @Attribute("securityPostDenormalize", type="string"),
6565
* @Attribute("securityPostDenormalizeMessage", type="string"),
66+
* @Attribute("path", type="string"),
6667
* @Attribute("shortName", type="string"),
6768
* @Attribute("stateless", type="bool"),
6869
* @Attribute("subresourceOperations", type="array"),
@@ -159,6 +160,11 @@ final class ApiResource
159160
*/
160161
public $itemOperations;
161162

163+
/**
164+
* @var string
165+
*/
166+
public $path;
167+
162168
/**
163169
* @var string
164170
*/

src/Bridge/Elasticsearch/Metadata/Resource/Factory/ElasticsearchOperationResourceMetadataFactory.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,14 @@ public function create(string $resourceClass): ResourceMetadata
3939
{
4040
$resourceMetadata = $this->decorated->create($resourceClass);
4141

42-
if (null === $resourceMetadata->getCollectionOperations()) {
43-
$resourceMetadata = $resourceMetadata->withCollectionOperations(['get' => ['method' => 'GET']]);
44-
}
45-
46-
if (null === $resourceMetadata->getItemOperations()) {
47-
$resourceMetadata = $resourceMetadata->withItemOperations(['get' => ['method' => 'GET']]);
42+
foreach ($resourceMetadata as $path => $operationCollectionMetadata) {
43+
if (null === $operationCollectionMetadata->getCollectionOperations()) {
44+
$resourceMetadata[$path] = $operationCollectionMetadata->withCollectionOperations(['get' => ['method' => 'GET']]);
45+
}
46+
47+
if (null === $operationCollectionMetadata->getItemOperations()) {
48+
$resourceMetadata[$path] = $operationCollectionMetadata->withItemOperations(['get' => ['method' => 'GET']]);
49+
}
4850
}
4951

5052
return $resourceMetadata;

src/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProvider.php

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
use ApiPlatform\Core\Documentation\Documentation;
2121
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
2222
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface;
23-
use ApiPlatform\Core\Metadata\Resource\ResourceMetadata;
23+
use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata;
2424
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
2525
use Nelmio\ApiDocBundle\Extractor\AnnotationsProviderInterface;
2626
use Psr\Container\ContainerInterface;
@@ -81,23 +81,23 @@ public function getAnnotations(): array
8181

8282
$annotations = [];
8383
foreach ($resourceNameCollection as $resourceClass) {
84-
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
85-
86-
$prefixedShortName = ($iri = $resourceMetadata->getIri()) ? $iri : '#'.$resourceMetadata->getShortName();
87-
$resourceHydraDoc = $this->getResourceHydraDoc($hydraDoc, $prefixedShortName);
88-
if (null === $resourceHydraDoc) {
89-
continue;
90-
}
84+
foreach ($this->resourceMetadataFactory->create($resourceClass) as $resourceMetadata) {
85+
$prefixedShortName = ($iri = $resourceMetadata->getIri()) ? $iri : '#'.$resourceMetadata->getShortName();
86+
$resourceHydraDoc = $this->getResourceHydraDoc($hydraDoc, $prefixedShortName);
87+
if (null === $resourceHydraDoc) {
88+
continue;
89+
}
9190

92-
if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) {
93-
foreach ($collectionOperations as $operationName => $operation) {
94-
$annotations[] = $this->getApiDoc(true, $resourceClass, $resourceMetadata, $operationName, $resourceHydraDoc, $entrypointHydraDoc);
91+
if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) {
92+
foreach ($collectionOperations as $operationName => $operation) {
93+
$annotations[] = $this->getApiDoc(true, $resourceClass, $resourceMetadata, $operationName, $resourceHydraDoc, $entrypointHydraDoc);
94+
}
9595
}
96-
}
9796

98-
if (null !== $itemOperations = $resourceMetadata->getItemOperations()) {
99-
foreach ($itemOperations as $operationName => $operation) {
100-
$annotations[] = $this->getApiDoc(false, $resourceClass, $resourceMetadata, $operationName, $resourceHydraDoc);
97+
if (null !== $itemOperations = $resourceMetadata->getItemOperations()) {
98+
foreach ($itemOperations as $operationName => $operation) {
99+
$annotations[] = $this->getApiDoc(false, $resourceClass, $resourceMetadata, $operationName, $resourceHydraDoc);
100+
}
101101
}
102102
}
103103
}
@@ -108,7 +108,7 @@ public function getAnnotations(): array
108108
/**
109109
* Builds ApiDoc annotation from ApiPlatform data.
110110
*/
111-
private function getApiDoc(bool $collection, string $resourceClass, ResourceMetadata $resourceMetadata, string $operationName, array $resourceHydraDoc, array $entrypointHydraDoc = []): ApiDoc
111+
private function getApiDoc(bool $collection, string $resourceClass, OperationCollectionMetadata $resourceMetadata, string $operationName, array $resourceHydraDoc, array $entrypointHydraDoc = []): ApiDoc
112112
{
113113
if ($collection) {
114114
$method = $this->operationMethodResolver->getCollectionOperationMethod($resourceClass, $operationName);

src/Bridge/Symfony/Routing/ApiLoader.php

Lines changed: 54 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
use ApiPlatform\Core\Exception\RuntimeException;
2020
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
2121
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface;
22-
use ApiPlatform\Core\Metadata\Resource\ResourceMetadata;
22+
use ApiPlatform\Core\Metadata\Resource\OperationCollectionMetadata;
2323
use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface;
2424
use ApiPlatform\Core\PathResolver\OperationPathResolverInterface;
2525
use Symfony\Component\Config\FileLocator;
@@ -92,63 +92,64 @@ public function load($data, $type = null): RouteCollection
9292
$this->loadExternalFiles($routeCollection);
9393

9494
foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) {
95-
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
96-
$resourceMetadata = $resourceMetadata->withAttributes(($resourceMetadata->getAttributes() ?: []) + ['identified_by' => $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass)]);
97-
$resourceShortName = $resourceMetadata->getShortName();
95+
foreach ($this->resourceMetadataFactory->create($resourceClass) as $operationCollectionMetadata) {
96+
$operationCollectionMetadata = $operationCollectionMetadata->withAttributes(($operationCollectionMetadata->getAttributes() ?: []) + ['identified_by' => $this->identifiersExtractor->getIdentifiersFromResourceClass($resourceClass)]);
97+
$resourceShortName = $operationCollectionMetadata->getShortName();
9898

99-
if (null === $resourceShortName) {
100-
throw new InvalidResourceException(sprintf('Resource %s has no short name defined.', $resourceClass));
101-
}
99+
if (null === $resourceShortName) {
100+
throw new InvalidResourceException(sprintf('Resource %s has no short name defined.', $resourceClass));
101+
}
102102

103-
if (null !== $collectionOperations = $resourceMetadata->getCollectionOperations()) {
104-
foreach ($collectionOperations as $operationName => $operation) {
105-
$this->addRoute($routeCollection, $resourceClass, $operationName, $operation, $resourceMetadata, OperationType::COLLECTION);
103+
if (null !== $collectionOperations = $operationCollectionMetadata->getCollectionOperations()) {
104+
foreach ($collectionOperations as $operationName => $operation) {
105+
$this->addRoute($routeCollection, $resourceClass, $operationName, $operation, $operationCollectionMetadata, OperationType::COLLECTION);
106+
}
106107
}
107-
}
108108

109-
if (null !== $itemOperations = $resourceMetadata->getItemOperations()) {
110-
foreach ($itemOperations as $operationName => $operation) {
111-
$this->addRoute($routeCollection, $resourceClass, $operationName, $operation, $resourceMetadata, OperationType::ITEM);
109+
if (null !== $itemOperations = $operationCollectionMetadata->getItemOperations()) {
110+
foreach ($itemOperations as $operationName => $operation) {
111+
$this->addRoute($routeCollection, $resourceClass, $operationName, $operation, $operationCollectionMetadata, OperationType::ITEM);
112+
}
112113
}
113-
}
114114

115-
if (null === $this->subresourceOperationFactory) {
116-
continue;
117-
}
115+
if (null === $this->subresourceOperationFactory) {
116+
continue;
117+
}
118118

119-
foreach ($this->subresourceOperationFactory->create($resourceClass) as $operationId => $operation) {
120-
if (null === $controller = $operation['controller'] ?? null) {
121-
$controller = self::DEFAULT_ACTION_PATTERN.'get_subresource';
119+
foreach ($this->subresourceOperationFactory->create($resourceClass) as $operationId => $operation) {
120+
if (null === $controller = $operation['controller'] ?? null) {
121+
$controller = self::DEFAULT_ACTION_PATTERN.'get_subresource';
122122

123-
if (!$this->container->has($controller)) {
124-
throw new RuntimeException(sprintf('There is no builtin action for the %s %s operation. You need to define the controller yourself.', OperationType::SUBRESOURCE, 'GET'));
123+
if (!$this->container->has($controller)) {
124+
throw new RuntimeException(sprintf('There is no builtin action for the %s %s operation. You need to define the controller yourself.', OperationType::SUBRESOURCE, 'GET'));
125+
}
125126
}
126-
}
127127

128-
$routeCollection->add($operation['route_name'], new Route(
129-
$operation['path'],
130-
[
131-
'_controller' => $controller,
132-
'_format' => null,
133-
'_stateless' => $operation['stateless'] ?? $resourceMetadata->getAttribute('stateless'),
134-
'_api_resource_class' => $operation['resource_class'],
135-
'_api_identified_by' => $operation['identified_by'],
136-
'_api_has_composite_identifier' => false,
137-
'_api_subresource_operation_name' => $operation['route_name'],
138-
'_api_subresource_context' => [
139-
'property' => $operation['property'],
140-
'identifiers' => $operation['identifiers'],
141-
'collection' => $operation['collection'],
142-
'operationId' => $operationId,
143-
],
144-
] + ($operation['defaults'] ?? []),
145-
$operation['requirements'] ?? [],
146-
$operation['options'] ?? [],
147-
$operation['host'] ?? '',
148-
$operation['schemes'] ?? [],
149-
['GET'],
150-
$operation['condition'] ?? ''
151-
));
128+
$routeCollection->add($operation['route_name'], new Route(
129+
$operation['path'],
130+
[
131+
'_controller' => $controller,
132+
'_format' => null,
133+
'_stateless' => $operation['stateless'] ?? $operationCollectionMetadata->getAttribute('stateless'),
134+
'_api_resource_class' => $operation['resource_class'],
135+
'_api_identified_by' => $operation['identified_by'],
136+
'_api_has_composite_identifier' => false,
137+
'_api_subresource_operation_name' => $operation['route_name'],
138+
'_api_subresource_context' => [
139+
'property' => $operation['property'],
140+
'identifiers' => $operation['identifiers'],
141+
'collection' => $operation['collection'],
142+
'operationId' => $operationId,
143+
],
144+
] + ($operation['defaults'] ?? []),
145+
$operation['requirements'] ?? [],
146+
$operation['options'] ?? [],
147+
$operation['host'] ?? '',
148+
$operation['schemes'] ?? [],
149+
['GET'],
150+
$operation['condition'] ?? ''
151+
));
152+
}
152153
}
153154
}
154155

@@ -204,9 +205,9 @@ private function loadExternalFiles(RouteCollection $routeCollection): void
204205
*
205206
* @throws RuntimeException
206207
*/
207-
private function addRoute(RouteCollection $routeCollection, string $resourceClass, string $operationName, array $operation, ResourceMetadata $resourceMetadata, string $operationType): void
208+
private function addRoute(RouteCollection $routeCollection, string $resourceClass, string $operationName, array $operation, OperationCollectionMetadata $operationCollectionMetadata, string $operationType): void
208209
{
209-
$resourceShortName = $resourceMetadata->getShortName();
210+
$resourceShortName = $operationCollectionMetadata->getShortName();
210211

211212
if (isset($operation['route_name'])) {
212213
if (!isset($operation['method'])) {
@@ -228,10 +229,10 @@ private function addRoute(RouteCollection $routeCollection, string $resourceClas
228229
}
229230
}
230231

231-
$operation['identified_by'] = (array) ($operation['identified_by'] ?? $resourceMetadata->getAttribute('identified_by'));
232-
$operation['has_composite_identifier'] = \count($operation['identified_by']) > 1 ? $resourceMetadata->getAttribute('composite_identifier', true) : false;
232+
$operation['identified_by'] = (array) ($operation['identified_by'] ?? $operationCollectionMetadata->getAttribute('identified_by'));
233+
$operation['has_composite_identifier'] = \count($operation['identified_by']) > 1 ? $operationCollectionMetadata->getAttribute('composite_identifier', true) : false;
233234

234-
$path = trim(trim($resourceMetadata->getAttribute('route_prefix', '')), '/');
235+
$path = trim(trim($operationCollectionMetadata->getAttribute('route_prefix', '')), '/');
235236
$path .= $this->operationPathResolver->resolveOperationPath($resourceShortName, $operation, $operationType, $operationName);
236237

237238
$route = new Route(

src/Metadata/Extractor/XmlExtractor.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ protected function extractPath(string $path)
4242
foreach ($xml->resource as $resource) {
4343
$resourceClass = $this->resolve((string) $resource['class']);
4444

45-
$this->resources[$resourceClass] = [
45+
$this->resources[$resourceClass][] = [
46+
'path' => $this->phpize($resource, 'path', 'string'),
4647
'shortName' => $this->phpize($resource, 'shortName', 'string'),
4748
'description' => $this->phpize($resource, 'description', 'string'),
4849
'iri' => $this->phpize($resource, 'iri', 'string'),

src/Metadata/Extractor/YamlExtractor.php

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ protected function extractPath(string $path)
5353
private function extractResources(array $resourcesYaml, string $path): void
5454
{
5555
foreach ($resourcesYaml as $resourceName => $resourceYaml) {
56+
if (is_numeric($resourceName)) {
57+
// Multi ApiResource declared
58+
$resourceName = array_key_first($resourceYaml);
59+
$resourceYaml = $resourceYaml[$resourceName];
60+
}
61+
5662
$resourceName = $this->resolve($resourceName);
5763

5864
if (null === $resourceYaml) {
@@ -63,7 +69,8 @@ private function extractResources(array $resourcesYaml, string $path): void
6369
throw new InvalidArgumentException(sprintf('"%s" setting is expected to be null or an array, %s given in "%s".', $resourceName, \gettype($resourceYaml), $path));
6470
}
6571

66-
$this->resources[$resourceName] = [
72+
$resource = [
73+
'path' => $this->phpize($resourceYaml, 'path', 'string'),
6774
'shortName' => $this->phpize($resourceYaml, 'shortName', 'string'),
6875
'description' => $this->phpize($resourceYaml, 'description', 'string'),
6976
'iri' => $this->phpize($resourceYaml, 'iri', 'string'),
@@ -75,7 +82,8 @@ private function extractResources(array $resourcesYaml, string $path): void
7582
];
7683

7784
if (!isset($resourceYaml['properties'])) {
78-
$this->resources[$resourceName]['properties'] = null;
85+
$resource['properties'] = null;
86+
$this->resources[$resourceName][] = $resource;
7987

8088
continue;
8189
}
@@ -84,15 +92,17 @@ private function extractResources(array $resourcesYaml, string $path): void
8492
throw new InvalidArgumentException(sprintf('"properties" setting is expected to be null or an array, %s given in "%s".', \gettype($resourceYaml['properties']), $path));
8593
}
8694

87-
$this->extractProperties($resourceYaml, $resourceName, $path);
95+
$this->extractProperties($resourceYaml, $resource, $path);
96+
97+
$this->resources[$resourceName][] = $resource;
8898
}
8999
}
90100

91-
private function extractProperties(array $resourceYaml, string $resourceName, string $path): void
101+
private function extractProperties(array $resourceYaml, array $resource, string $path): void
92102
{
93103
foreach ($resourceYaml['properties'] as $propertyName => $propertyValues) {
94104
if (null === $propertyValues) {
95-
$this->resources[$resourceName]['properties'][$propertyName] = null;
105+
$resource['properties'][$propertyName] = null;
96106

97107
continue;
98108
}
@@ -104,7 +114,7 @@ private function extractProperties(array $resourceYaml, string $resourceName, st
104114
$propertyValues['subresource']['resourceClass'] = $this->resolve($propertyValues['subresource']['resourceClass']);
105115
}
106116

107-
$this->resources[$resourceName]['properties'][$propertyName] = [
117+
$resource['properties'][$propertyName] = [
108118
'description' => $this->phpize($propertyValues, 'description', 'string'),
109119
'readable' => $this->phpize($propertyValues, 'readable', 'bool'),
110120
'writable' => $this->phpize($propertyValues, 'writable', 'bool'),

0 commit comments

Comments
 (0)