-
-
Notifications
You must be signed in to change notification settings - Fork 968
Expand file tree
/
Copy pathResourceMetadataCollection.php
More file actions
113 lines (92 loc) · 4.11 KB
/
Copy pathResourceMetadataCollection.php
File metadata and controls
113 lines (92 loc) · 4.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
<?php
/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace ApiPlatform\Metadata\Resource;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\CollectionOperationInterface;
use ApiPlatform\Metadata\Exception\OperationNotFoundException;
use ApiPlatform\Metadata\Operation;
/**
* @extends \ArrayObject<int, ApiResource>
*/
final class ResourceMetadataCollection extends \ArrayObject
{
private const GRAPHQL_PREFIX = 'g_';
private const HTTP_PREFIX = 'h_';
private const FORCE_COLLECTION = 'co_';
private const HTTP_OPERATION = 'ht_';
private array $operationCache = [];
public function __construct(private readonly string $resourceClass, array $input = [])
{
parent::__construct($input);
}
public function getOperation(?string $operationName = null, bool $forceCollection = false, bool $httpOperation = false, bool $forceGraphQl = false): Operation
{
$operationName ??= '';
$cachePrefix = ($forceCollection ? self::FORCE_COLLECTION : '').($httpOperation ? self::HTTP_OPERATION : '');
$httpCacheKey = self::HTTP_PREFIX.$cachePrefix.$operationName;
if (isset($this->operationCache[$httpCacheKey])) {
return $this->operationCache[$httpCacheKey];
}
$gqlCacheKey = self::GRAPHQL_PREFIX.$cachePrefix.$operationName;
if (isset($this->operationCache[$gqlCacheKey])) {
return $this->operationCache[$gqlCacheKey];
}
$it = $this->getIterator();
$metadata = null;
while ($it->valid()) {
/** @var ApiResource $metadata */
$metadata = $it->current();
if (!$forceGraphQl) {
foreach ($metadata->getOperations() ?? [] as $name => $operation) {
$isCollection = $operation instanceof CollectionOperationInterface;
$method = $operation->getMethod();
$isGetOperation = 'GET' === $method || 'OPTIONS' === $method || 'HEAD' === $method;
if ('' === $operationName && $isGetOperation && ($forceCollection ? $isCollection : !$isCollection)) {
return $this->operationCache[$httpCacheKey] = $operation;
}
if ($name === $operationName) {
return $this->operationCache[$httpCacheKey] = $operation;
}
if ($operation->getUriTemplate() === $operationName) {
return $this->operationCache[$httpCacheKey] = $operation;
}
}
}
foreach ($metadata->getGraphQlOperations() ?? [] as $name => $operation) {
$isCollection = $operation instanceof CollectionOperationInterface;
if ('' === $operationName && ($forceCollection ? $isCollection : !$isCollection) && false === $httpOperation) {
return $this->operationCache[$gqlCacheKey] = $operation;
}
if ($name === $operationName) {
return $this->operationCache[$httpCacheKey] = $operation;
}
}
$it->next();
}
// Idea:
// if ($metadata) {
// return (new class extends HttpOperation {})->withResource($metadata);
// }
$this->handleNotFound($operationName, $metadata);
}
/**
* @throws OperationNotFoundException
*/
private function handleNotFound(string $operationName, ?ApiResource $metadata): void
{
// Hide the FQDN in the exception message if possible
$shortName = $metadata?->getShortName() ? $metadata->getShortName() : $this->resourceClass;
if (!$metadata && false !== $pos = strrpos($shortName, '\\')) {
$shortName = substr($shortName, $pos + 1);
}
throw new OperationNotFoundException(\sprintf('Operation "%s" not found for resource "%s".', $operationName, $shortName));
}
}