vendor/api-platform/core/src/Metadata/Resource/ResourceMetadataCollection.php line 38

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