vendor/api-platform/core/src/Core/Metadata/Resource/Factory/OperationResourceMetadataFactory.php line 104

Open in your IDE?
  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\Core\Metadata\Resource\Factory;
  12. use ApiPlatform\Core\Metadata\Resource\ResourceMetadata;
  13. /**
  14.  * Creates or completes operations.
  15.  *
  16.  * @author Kévin Dunglas <dunglas@gmail.com>
  17.  */
  18. final class OperationResourceMetadataFactory implements ResourceMetadataFactoryInterface
  19. {
  20.     /**
  21.      * @internal
  22.      */
  23.     public const SUPPORTED_COLLECTION_OPERATION_METHODS = [
  24.         'GET' => true,
  25.         'POST' => true,
  26.     ];
  27.     /**
  28.      * @internal
  29.      */
  30.     public const SUPPORTED_ITEM_OPERATION_METHODS = [
  31.         'GET' => true,
  32.         'PUT' => true,
  33.         // PATCH is automatically supported if at least one patch format has been configured
  34.         'DELETE' => true,
  35.     ];
  36.     private $decorated;
  37.     private $patchFormats;
  38.     public function __construct(ResourceMetadataFactoryInterface $decorated, array $patchFormats = [])
  39.     {
  40.         $this->decorated $decorated;
  41.         $this->patchFormats $patchFormats;
  42.     }
  43.     /**
  44.      * {@inheritdoc}
  45.      */
  46.     public function create(string $resourceClass): ResourceMetadata
  47.     {
  48.         $resourceMetadata $this->decorated->create($resourceClass);
  49.         $isAbstract = (new \ReflectionClass($resourceClass))->isAbstract();
  50.         $collectionOperations $resourceMetadata->getCollectionOperations();
  51.         if (null === $collectionOperations) {
  52.             $resourceMetadata $resourceMetadata->withCollectionOperations($this->createOperations($isAbstract ? ['GET'] : ['GET''POST'], $resourceMetadata));
  53.         } else {
  54.             $resourceMetadata $this->normalize(true$resourceClass$resourceMetadata$collectionOperations);
  55.         }
  56.         $itemOperations $resourceMetadata->getItemOperations();
  57.         if (null === $itemOperations) {
  58.             $methods = ['GET''DELETE'];
  59.             if (!$isAbstract) {
  60.                 $methods[] = 'PUT';
  61.                 if ($this->patchFormats) {
  62.                     $methods[] = 'PATCH';
  63.                 }
  64.             }
  65.             $resourceMetadata $resourceMetadata->withItemOperations($this->createOperations($methods$resourceMetadata));
  66.         } else {
  67.             $resourceMetadata $this->normalize(false$resourceClass$resourceMetadata$itemOperations);
  68.         }
  69.         $graphql $resourceMetadata->getGraphql();
  70.         if (null === $graphql) {
  71.             $resourceMetadata $resourceMetadata->withGraphql(['item_query' => [], 'collection_query' => [], 'delete' => [], 'update' => [], 'create' => []]);
  72.         } else {
  73.             $resourceMetadata $this->normalizeGraphQl($resourceMetadata$graphql);
  74.         }
  75.         return $resourceMetadata;
  76.     }
  77.     private function createOperations(array $methodsResourceMetadata $resourceMetadata): array
  78.     {
  79.         $operations = [];
  80.         foreach ($methods as $method) {
  81.             $operations[strtolower($method)] = ['method' => $method'stateless' => $resourceMetadata->getAttribute('stateless')];
  82.         }
  83.         return $operations;
  84.     }
  85.     private function normalize(bool $collectionstring $resourceClassResourceMetadata $resourceMetadata, array $operations): ResourceMetadata
  86.     {
  87.         $newOperations = [];
  88.         foreach ($operations as $operationName => $operation) {
  89.             // e.g.: @ApiResource(itemOperations={"get"})
  90.             if (\is_int($operationName) && \is_string($operation)) {
  91.                 $operationName $operation;
  92.                 $operation = [];
  93.             }
  94.             $upperOperationName strtoupper((string) $operationName);
  95.             if ($collection) {
  96.                 $supported = isset(self::SUPPORTED_COLLECTION_OPERATION_METHODS[$upperOperationName]);
  97.             } else {
  98.                 $supported = isset(self::SUPPORTED_ITEM_OPERATION_METHODS[$upperOperationName]) || ($this->patchFormats && 'PATCH' === $upperOperationName);
  99.             }
  100.             if (!isset($operation['method']) && !isset($operation['route_name'])) {
  101.                 if ($supported) {
  102.                     $operation['method'] = $upperOperationName;
  103.                 } else {
  104.                     @trigger_error(sprintf('The "route_name" attribute will not be set automatically again in API Platform 3.0, set it for the %s operation "%s" of the class "%s".'$collection 'collection' 'item'$operationName$resourceClass), \E_USER_DEPRECATED);
  105.                     $operation['route_name'] = $operationName;
  106.                 }
  107.             }
  108.             if (isset($operation['method'])) {
  109.                 $operation['method'] = strtoupper($operation['method']);
  110.             }
  111.             $operation['stateless'] = $operation['stateless'] ?? $resourceMetadata->getAttribute('stateless');
  112.             $newOperations[$operationName] = $operation;
  113.         }
  114.         return $collection $resourceMetadata->withCollectionOperations($newOperations) : $resourceMetadata->withItemOperations($newOperations);
  115.     }
  116.     private function normalizeGraphQl(ResourceMetadata $resourceMetadata, array $operations): ResourceMetadata
  117.     {
  118.         foreach ($operations as $operationName => $operation) {
  119.             if (\is_int($operationName) && \is_string($operation)) {
  120.                 unset($operations[$operationName]);
  121.                 $operations[$operation] = [];
  122.             }
  123.         }
  124.         return $resourceMetadata->withGraphql($operations);
  125.     }
  126. }