Skip to content

Commit 8389b4e

Browse files
vincentchalamonsoyuka
authored andcommitted
Allow setting ApiResource several times
1 parent f18a8f8 commit 8389b4e

29 files changed

+217
-109
lines changed

src/Annotation/ApiResource.php

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ final class ApiResource
122122
'paginationMaximumItemsPerPage',
123123
'paginationPartial',
124124
'paginationViaCursor',
125+
'parent',
126+
'property',
125127
'routePrefix',
126128
'stateless',
127129
'sunset',
@@ -142,6 +144,16 @@ final class ApiResource
142144
*/
143145
public $description;
144146

147+
/**
148+
* @var string
149+
*/
150+
public $parent;
151+
152+
/**
153+
* @var string
154+
*/
155+
public $property;
156+
145157
/**
146158
* @see https://api-platform.com/docs/core/graphql
147159
*
@@ -380,20 +392,6 @@ final class ApiResource
380392
*/
381393
private $paginationPartial;
382394

383-
/**
384-
* @see https://github.com/Haehnchen/idea-php-annotation-plugin/issues/112
385-
*
386-
* @var string
387-
*/
388-
private $parent;
389-
390-
/**
391-
* @see https://github.com/Haehnchen/idea-php-annotation-plugin/issues/112
392-
*
393-
* @var string
394-
*/
395-
private $property;
396-
397395
/**
398396
* @see https://api-platform.com/docs/core/operations/#prefixing-all-routes-of-all-operations
399397
* @see https://github.com/Haehnchen/idea-php-annotation-plugin/issues/112

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ public function __construct(ResourceMetadataFactoryInterface $decorated)
3535
/**
3636
* {@inheritdoc}
3737
*/
38-
public function create(string $resourceClass): ResourceMetadata
38+
public function create(string $resourceClass, string $parent = null, string $property = null): ResourceMetadata
3939
{
40-
$resourceMetadata = $this->decorated->create($resourceClass);
40+
$resourceMetadata = $this->decorated->create($resourceClass, $parent, $property);
4141

4242
if (null === $resourceMetadata->getCollectionOperations()) {
4343
$resourceMetadata = $resourceMetadata->withCollectionOperations(['get' => ['method' => 'GET']]);

src/Metadata/Extractor/XmlExtractor.php

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,32 @@ protected function extractPath(string $path)
3939
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
4040
}
4141

42-
foreach ($xml->resource as $resource) {
43-
$resourceClass = $this->resolve((string) $resource['class']);
44-
45-
$this->resources[$resourceClass] = [
46-
'shortName' => $this->phpize($resource, 'shortName', 'string'),
47-
'description' => $this->phpize($resource, 'description', 'string'),
48-
'iri' => $this->phpize($resource, 'iri', 'string'),
49-
'itemOperations' => $this->getOperations($resource, 'itemOperation'),
50-
'collectionOperations' => $this->getOperations($resource, 'collectionOperation'),
51-
'subresourceOperations' => $this->getOperations($resource, 'subresourceOperation'),
52-
'graphql' => $this->getOperations($resource, 'operation'),
53-
'attributes' => $this->getAttributes($resource, 'attribute') ?: null,
54-
'properties' => $this->getProperties($resource) ?: null,
42+
foreach ($xml->resource as $resourceXml) {
43+
$resourceClass = $this->resolve((string) $resourceXml['class']);
44+
$parent = $this->phpize($resourceXml, 'parent', 'string');
45+
$property = $this->phpize($resourceXml, 'property', 'string');
46+
47+
$resource = [
48+
'parent' => $parent,
49+
'property' => $property,
50+
'shortName' => $this->phpize($resourceXml, 'shortName', 'string'),
51+
'description' => $this->phpize($resourceXml, 'description', 'string'),
52+
'iri' => $this->phpize($resourceXml, 'iri', 'string'),
53+
'itemOperations' => $this->getOperations($resourceXml, 'itemOperation'),
54+
'collectionOperations' => $this->getOperations($resourceXml, 'collectionOperation'),
55+
'subresourceOperations' => $this->getOperations($resourceXml, 'subresourceOperation'),
56+
'graphql' => $this->getOperations($resourceXml, 'operation'),
57+
'attributes' => $this->getAttributes($resourceXml, 'attribute') ?: null,
58+
'properties' => $this->getProperties($resourceXml) ?: null,
5559
];
60+
61+
if (!empty($parent)) {
62+
$this->resources[$resourceClass][$parent][$property] = $resource;
63+
64+
return;
65+
}
66+
67+
$this->resources[$resourceClass]['_self'] = $resource;
5668
}
5769
}
5870

src/Metadata/Extractor/YamlExtractor.php

Lines changed: 27 additions & 10 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,12 @@ 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+
$parent = $this->phpize($resourceYaml, 'parent', 'string');
73+
$property = $this->phpize($resourceYaml, 'property', 'string');
74+
75+
$resource = [
76+
'parent' => $parent,
77+
'property' => $property,
6778
'shortName' => $this->phpize($resourceYaml, 'shortName', 'string'),
6879
'description' => $this->phpize($resourceYaml, 'description', 'string'),
6980
'iri' => $this->phpize($resourceYaml, 'iri', 'string'),
@@ -74,25 +85,31 @@ private function extractResources(array $resourcesYaml, string $path): void
7485
'attributes' => $resourceYaml['attributes'] ?? null,
7586
];
7687

77-
if (!isset($resourceYaml['properties'])) {
78-
$this->resources[$resourceName]['properties'] = null;
88+
if (isset($resourceYaml['properties'])) {
89+
if (!\is_array($resourceYaml['properties'])) {
90+
throw new InvalidArgumentException(sprintf('"properties" setting is expected to be null or an array, %s given in "%s".', \gettype($resourceYaml['properties']), $path));
91+
}
7992

80-
continue;
93+
$this->extractProperties($resourceYaml, $resource, $path);
8194
}
8295

83-
if (!\is_array($resourceYaml['properties'])) {
84-
throw new InvalidArgumentException(sprintf('"properties" setting is expected to be null or an array, %s given in "%s".', \gettype($resourceYaml['properties']), $path));
96+
$resource['properties'] = null;
97+
98+
if (!empty($parent)) {
99+
$this->resources[$resourceName][$parent][$property] = $resource;
100+
101+
return;
85102
}
86103

87-
$this->extractProperties($resourceYaml, $resourceName, $path);
104+
$this->resources[$resourceName]['_self'] = $resource;
88105
}
89106
}
90107

91-
private function extractProperties(array $resourceYaml, string $resourceName, string $path): void
108+
private function extractProperties(array $resourceYaml, array $resource, string $path): void
92109
{
93110
foreach ($resourceYaml['properties'] as $propertyName => $propertyValues) {
94111
if (null === $propertyValues) {
95-
$this->resources[$resourceName]['properties'][$propertyName] = null;
112+
$resource['properties'][$propertyName] = null;
96113

97114
continue;
98115
}
@@ -104,7 +121,7 @@ private function extractProperties(array $resourceYaml, string $resourceName, st
104121
$propertyValues['subresource']['resourceClass'] = $this->resolve($propertyValues['subresource']['resourceClass']);
105122
}
106123

107-
$this->resources[$resourceName]['properties'][$propertyName] = [
124+
$resource['properties'][$propertyName] = [
108125
'description' => $this->phpize($propertyValues, 'description', 'string'),
109126
'readable' => $this->phpize($propertyValues, 'readable', 'bool'),
110127
'writable' => $this->phpize($propertyValues, 'writable', 'bool'),

src/Metadata/Resource/Factory/AnnotationResourceFilterMetadataFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ public function __construct(Reader $reader, ResourceMetadataFactoryInterface $de
4040
/**
4141
* {@inheritdoc}
4242
*/
43-
public function create(string $resourceClass): ResourceMetadata
43+
public function create(string $resourceClass, string $parent = null, string $property = null): ResourceMetadata
4444
{
4545
$parentResourceMetadata = null;
4646
if ($this->decorated) {
4747
try {
48-
$parentResourceMetadata = $this->decorated->create($resourceClass);
48+
$parentResourceMetadata = $this->decorated->create($resourceClass, $parent, $property);
4949
} catch (ResourceClassNotFoundException $resourceNotFoundException) {
5050
// Ignore not found exception from decorated factories
5151
}

src/Metadata/Resource/Factory/AnnotationResourceMetadataFactory.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ public function __construct(Reader $reader, ResourceMetadataFactoryInterface $de
3939
/**
4040
* {@inheritdoc}
4141
*/
42-
public function create(string $resourceClass): ResourceMetadata
42+
public function create(string $resourceClass, string $parent = null, string $property = null): ResourceMetadata
4343
{
4444
$parentResourceMetadata = null;
4545
if ($this->decorated) {
4646
try {
47-
$parentResourceMetadata = $this->decorated->create($resourceClass);
47+
$parentResourceMetadata = $this->decorated->create($resourceClass, $parent, $property);
4848
} catch (ResourceClassNotFoundException $resourceNotFoundException) {
4949
// Ignore not found exception from decorated factories
5050
}
@@ -56,12 +56,13 @@ public function create(string $resourceClass): ResourceMetadata
5656
return $this->handleNotFound($parentResourceMetadata, $resourceClass);
5757
}
5858

59-
$resourceAnnotation = $this->reader->getClassAnnotation($reflectionClass, ApiResource::class);
60-
if (!$resourceAnnotation instanceof ApiResource) {
61-
return $this->handleNotFound($parentResourceMetadata, $resourceClass);
59+
foreach ($this->reader->getClassAnnotations($reflectionClass) as $resourceAnnotation) {
60+
if (ApiResource::class === \get_class($resourceAnnotation) && (!$parent || ($parent === $resourceAnnotation->parent && $property === $resourceAnnotation->property))) {
61+
return $this->createMetadata($resourceAnnotation, $parentResourceMetadata);
62+
}
6263
}
6364

64-
return $this->createMetadata($resourceAnnotation, $parentResourceMetadata);
65+
return $this->handleNotFound($parentResourceMetadata, $resourceClass);
6566
}
6667

6768
/**
@@ -91,7 +92,9 @@ private function createMetadata(ApiResource $annotation, ResourceMetadata $paren
9192
$annotation->collectionOperations ?? $this->defaults['collection_operations'] ?? null,
9293
$attributes,
9394
$annotation->subresourceOperations,
94-
$annotation->graphql ?? $this->defaults['graphql'] ?? null
95+
$annotation->graphql ?? $this->defaults['graphql'] ?? null,
96+
$annotation->parent ?? null,
97+
$annotation->property ?? null
9598
);
9699
}
97100

src/Metadata/Resource/Factory/CachedResourceMetadataFactory.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ public function __construct(CacheItemPoolInterface $cacheItemPool, ResourceMetad
3939
/**
4040
* {@inheritdoc}
4141
*/
42-
public function create(string $resourceClass): ResourceMetadata
42+
public function create(string $resourceClass, string $parent = null, string $property = null): ResourceMetadata
4343
{
4444
$cacheKey = self::CACHE_KEY_PREFIX.md5($resourceClass);
4545

46-
return $this->getCached($cacheKey, function () use ($resourceClass) {
47-
return $this->decorated->create($resourceClass);
46+
return $this->getCached($cacheKey, function () use ($resourceClass, $parent, $property) {
47+
return $this->decorated->create($resourceClass, $parent, $property);
4848
});
4949
}
5050
}

src/Metadata/Resource/Factory/ExtractorResourceMetadataFactory.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,12 @@ public function __construct(ExtractorInterface $extractor, ResourceMetadataFacto
3939
/**
4040
* {@inheritdoc}
4141
*/
42-
public function create(string $resourceClass): ResourceMetadata
42+
public function create(string $resourceClass, string $parent = null, string $property = null): ResourceMetadata
4343
{
44+
if (!empty($parent) && empty($property)) {
45+
throw new \LogicException('You must set a property when setting a parent.');
46+
}
47+
4448
$parentResourceMetadata = null;
4549
if ($this->decorated) {
4650
try {
@@ -50,7 +54,10 @@ public function create(string $resourceClass): ResourceMetadata
5054
}
5155
}
5256

53-
if (!(class_exists($resourceClass) || interface_exists($resourceClass)) || !$resource = $this->extractor->getResources()[$resourceClass] ?? false) {
57+
if (!(class_exists($resourceClass) || interface_exists($resourceClass))
58+
|| !($resource = $this->extractor->getResources()[$resourceClass] ?? false)
59+
|| !(($resource = $resource['_self'] ?? false) || ($resource = $resource[$parent][$property] ?? false))
60+
) {
5461
return $this->handleNotFound($parentResourceMetadata, $resourceClass);
5562
}
5663

src/Metadata/Resource/Factory/FormatsResourceMetadataFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ public function __construct(ResourceMetadataFactoryInterface $decorated, array $
4848
*
4949
* @throws ResourceClassNotFoundException
5050
*/
51-
public function create(string $resourceClass): ResourceMetadata
51+
public function create(string $resourceClass, string $parent = null, string $property = null): ResourceMetadata
5252
{
53-
$resourceMetadata = $this->decorated->create($resourceClass);
53+
$resourceMetadata = $this->decorated->create($resourceClass, $parent, $property);
5454
$rawResourceFormats = $resourceMetadata->getAttribute('formats');
5555
$resourceFormats = null === $rawResourceFormats ? $this->formats : $this->normalizeFormats($rawResourceFormats);
5656

src/Metadata/Resource/Factory/InputOutputResourceMetadataFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ public function __construct(ResourceMetadataFactoryInterface $decorated)
3232
/**
3333
* {@inheritdoc}
3434
*/
35-
public function create(string $resourceClass): ResourceMetadata
35+
public function create(string $resourceClass, string $parent = null, string $property = null): ResourceMetadata
3636
{
37-
$resourceMetadata = $this->decorated->create($resourceClass);
37+
$resourceMetadata = $this->decorated->create($resourceClass, $parent, $property);
3838

3939
$attributes = $resourceMetadata->getAttributes() ?: [];
4040
$attributes['input'] = isset($attributes['input']) ? $this->transformInputOutput($attributes['input']) : null;

src/Metadata/Resource/Factory/OperationResourceMetadataFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ public function __construct(ResourceMetadataFactoryInterface $decorated, array $
5252
/**
5353
* {@inheritdoc}
5454
*/
55-
public function create(string $resourceClass): ResourceMetadata
55+
public function create(string $resourceClass, string $parent = null, string $property = null): ResourceMetadata
5656
{
57-
$resourceMetadata = $this->decorated->create($resourceClass);
57+
$resourceMetadata = $this->decorated->create($resourceClass, $parent, $property);
5858
$isAbstract = (new \ReflectionClass($resourceClass))->isAbstract();
5959

6060
$collectionOperations = $resourceMetadata->getCollectionOperations();

src/Metadata/Resource/Factory/PhpDocResourceMetadataFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ public function __construct(ResourceMetadataFactoryInterface $decorated, DocBloc
3939
/**
4040
* {@inheritdoc}
4141
*/
42-
public function create(string $resourceClass): ResourceMetadata
42+
public function create(string $resourceClass, string $parent = null, string $property = null): ResourceMetadata
4343
{
44-
$resourceMetadata = $this->decorated->create($resourceClass);
44+
$resourceMetadata = $this->decorated->create($resourceClass, $parent, $property);
4545

4646
if (null !== $resourceMetadata->getDescription()) {
4747
return $resourceMetadata;

src/Metadata/Resource/Factory/ResourceMetadataFactoryInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ interface ResourceMetadataFactoryInterface
2828
*
2929
* @throws ResourceClassNotFoundException
3030
*/
31-
public function create(string $resourceClass): ResourceMetadata;
31+
public function create(string $resourceClass, string $parent = null, string $property = null): ResourceMetadata;
3232
}

src/Metadata/Resource/Factory/ShortNameResourceMetadataFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ public function __construct(ResourceMetadataFactoryInterface $decorated)
3232
/**
3333
* {@inheritdoc}
3434
*/
35-
public function create(string $resourceClass): ResourceMetadata
35+
public function create(string $resourceClass, string $parent = null, string $property = null): ResourceMetadata
3636
{
37-
$resourceMetadata = $this->decorated->create($resourceClass);
37+
$resourceMetadata = $this->decorated->create($resourceClass, $parent, $property);
3838

3939
if (null !== $resourceMetadata->getShortName()) {
4040
return $resourceMetadata;

0 commit comments

Comments
 (0)