vendor/api-platform/core/src/Doctrine/Common/State/LinksHandlerTrait.php line 105

  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\Doctrine\Common\State;
  12. use ApiPlatform\Exception\OperationNotFoundException;
  13. use ApiPlatform\Metadata\Exception\RuntimeException;
  14. use ApiPlatform\Metadata\GraphQl\Operation as GraphQlOperation;
  15. use ApiPlatform\Metadata\GraphQl\Query;
  16. use ApiPlatform\Metadata\HttpOperation;
  17. use ApiPlatform\Metadata\Link;
  18. use ApiPlatform\Metadata\Operation;
  19. use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
  20. use Psr\Container\ContainerInterface;
  21. trait LinksHandlerTrait
  22. {
  23.     private ?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory;
  24.     private ?ContainerInterface $handleLinksLocator;
  25.     /**
  26.      * @return Link[]
  27.      */
  28.     private function getLinks(string $resourceClassOperation $operation, array $context): array
  29.     {
  30.         $links $this->getOperationLinks($operation);
  31.         if (!($linkClass $context['linkClass'] ?? false)) {
  32.             return $links;
  33.         }
  34.         $newLink null;
  35.         $linkProperty $context['linkProperty'] ?? null;
  36.         foreach ($links as $link) {
  37.             if ($linkClass === $link->getFromClass() && $linkProperty === $link->getFromProperty()) {
  38.                 $newLink $link;
  39.                 break;
  40.             }
  41.         }
  42.         if ($newLink) {
  43.             return [$newLink];
  44.         }
  45.         if (!$this->resourceMetadataCollectionFactory) {
  46.             return [];
  47.         }
  48.         // Using GraphQL, it's possible that we won't find a GraphQL Operation of the same type (e.g. it is disabled).
  49.         try {
  50.             $resourceMetadataCollection $this->resourceMetadataCollectionFactory->create($linkClass);
  51.             $linkedOperation $resourceMetadataCollection->getOperation($operation->getName());
  52.         } catch (OperationNotFoundException $e) {
  53.             if (!$operation instanceof GraphQlOperation) {
  54.                 throw $e;
  55.             }
  56.             // Instead, we'll look for the first Query available.
  57.             foreach ($resourceMetadataCollection as $resourceMetadata) {
  58.                 foreach ($resourceMetadata->getGraphQlOperations() as $op) {
  59.                     if ($op instanceof Query) {
  60.                         $linkedOperation $op;
  61.                     }
  62.                 }
  63.             }
  64.         }
  65.         foreach ($this->getOperationLinks($linkedOperation ?? null) as $link) {
  66.             if ($resourceClass === $link->getToClass() && $linkProperty === $link->getFromProperty()) {
  67.                 $newLink $link;
  68.                 break;
  69.             }
  70.         }
  71.         if (!$newLink) {
  72.             throw new RuntimeException(sprintf('The class "%s" cannot be retrieved from "%s".'$resourceClass$linkClass));
  73.         }
  74.         return [$newLink];
  75.     }
  76.     private function getIdentifierValue(array &$identifiersstring $name null): mixed
  77.     {
  78.         if (isset($identifiers[$name])) {
  79.             $value $identifiers[$name];
  80.             unset($identifiers[$name]);
  81.             return $value;
  82.         }
  83.         return array_shift($identifiers);
  84.     }
  85.     private function getOperationLinks(Operation $operation null): array
  86.     {
  87.         if ($operation instanceof GraphQlOperation) {
  88.             return $operation->getLinks() ?? [];
  89.         }
  90.         if ($operation instanceof HttpOperation) {
  91.             return $operation->getUriVariables() ?? [];
  92.         }
  93.         return [];
  94.     }
  95.     private function getLinksHandler(Operation $operation): ?callable
  96.     {
  97.         if (!($options $operation->getStateOptions()) || !method_exists($options'getHandleLinks') || null === $options->getHandleLinks()) {
  98.             return null;
  99.         }
  100.         $handleLinks $options->getHandleLinks(); // @phpstan-ignore-line method_exists called above
  101.         if (\is_callable($handleLinks)) {
  102.             return $handleLinks;
  103.         }
  104.         if ($this->handleLinksLocator && \is_string($handleLinks) && $this->handleLinksLocator->has($handleLinks)) {
  105.             return [$this->handleLinksLocator->get($handleLinks), 'handleLinks'];
  106.         }
  107.         throw new RuntimeException(sprintf('Could not find handleLinks service "%s"'$handleLinks));
  108.     }
  109. }