vendor/api-platform/core/src/Core/Bridge/Symfony/Routing/IriConverter.php line 67

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\Bridge\Symfony\Routing;
  12. use ApiPlatform\Core\Api\IdentifiersExtractor;
  13. use ApiPlatform\Core\Api\IdentifiersExtractorInterface;
  14. use ApiPlatform\Core\Api\IriConverterInterface;
  15. use ApiPlatform\Core\Api\OperationType;
  16. use ApiPlatform\Core\Api\ResourceClassResolverInterface;
  17. use ApiPlatform\Core\Api\UrlGeneratorInterface;
  18. use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
  19. use ApiPlatform\Core\DataProvider\OperationDataProviderTrait;
  20. use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface;
  21. use ApiPlatform\Core\Identifier\CompositeIdentifierParser;
  22. use ApiPlatform\Core\Identifier\IdentifierConverterInterface;
  23. use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
  24. use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
  25. use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
  26. use ApiPlatform\Exception\InvalidArgumentException;
  27. use ApiPlatform\Exception\InvalidIdentifierException;
  28. use ApiPlatform\Exception\ItemNotFoundException;
  29. use ApiPlatform\Exception\RuntimeException;
  30. use ApiPlatform\Symfony\Routing\IriConverter as NewIriConverter;
  31. use ApiPlatform\Util\AttributesExtractor;
  32. use ApiPlatform\Util\ResourceClassInfoTrait;
  33. use Symfony\Component\PropertyAccess\PropertyAccess;
  34. use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
  35. use Symfony\Component\Routing\Exception\ExceptionInterface as RoutingExceptionInterface;
  36. use Symfony\Component\Routing\RouterInterface;
  37. /**
  38.  * {@inheritdoc}
  39.  *
  40.  * @author Kévin Dunglas <dunglas@gmail.com>
  41.  */
  42. final class IriConverter implements IriConverterInterface
  43. {
  44.     use OperationDataProviderTrait;
  45.     use ResourceClassInfoTrait;
  46.     private $routeNameResolver;
  47.     private $router;
  48.     private $identifiersExtractor;
  49.     public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactoryPropertyMetadataFactoryInterface $propertyMetadataFactoryItemDataProviderInterface $itemDataProviderRouteNameResolverInterface $routeNameResolverRouterInterface $routerPropertyAccessorInterface $propertyAccessor nullIdentifiersExtractorInterface $identifiersExtractor nullSubresourceDataProviderInterface $subresourceDataProvider nullIdentifierConverterInterface $identifierConverter nullResourceClassResolverInterface $resourceClassResolver nullResourceMetadataFactoryInterface $resourceMetadataFactory null)
  50.     {
  51.         $this->itemDataProvider $itemDataProvider;
  52.         $this->routeNameResolver $routeNameResolver;
  53.         $this->router $router;
  54.         $this->subresourceDataProvider $subresourceDataProvider;
  55.         $this->identifierConverter $identifierConverter;
  56.         $this->resourceClassResolver $resourceClassResolver;
  57.         $this->identifiersExtractor $identifiersExtractor ?: new IdentifiersExtractor($propertyNameCollectionFactory$propertyMetadataFactory$propertyAccessor ?? PropertyAccess::createPropertyAccessor());
  58.         $this->resourceMetadataFactory $resourceMetadataFactory;
  59.         trigger_deprecation('api-platform/core''2.7'sprintf('The service "%s" is deprecated, use %s instead.'self::class, NewIriConverter::class));
  60.     }
  61.     /**
  62.      * {@inheritdoc}
  63.      *
  64.      * @return object
  65.      */
  66.     public function getItemFromIri(string $iri, array $context = [])
  67.     {
  68.         try {
  69.             $parameters $this->router->match($iri);
  70.         } catch (RoutingExceptionInterface $e) {
  71.             throw new InvalidArgumentException(sprintf('No route matches "%s".'$iri), $e->getCode(), $e);
  72.         }
  73.         if (!isset($parameters['_api_resource_class'])) {
  74.             throw new InvalidArgumentException(sprintf('No resource associated to "%s".'$iri));
  75.         }
  76.         if (isset($parameters['_api_collection_operation_name'])) {
  77.             throw new InvalidArgumentException(sprintf('The iri "%s" references a collection not an item.'$iri));
  78.         }
  79.         $attributes AttributesExtractor::extractAttributes($parameters);
  80.         try {
  81.             $identifiers $this->extractIdentifiers($parameters$attributes);
  82.         } catch (InvalidIdentifierException $e) {
  83.             throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
  84.         }
  85.         if ($this->identifierConverter) {
  86.             $context[IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER] = true;
  87.         }
  88.         if (isset($attributes['subresource_operation_name'])) {
  89.             if (($item $this->getSubresourceData($identifiers$attributes$context)) && !\is_array($item)) {
  90.                 return $item;
  91.             }
  92.             throw new ItemNotFoundException(sprintf('Item not found for "%s".'$iri));
  93.         }
  94.         if ($item $this->getItemData($identifiers$attributes$context)) {
  95.             return $item;
  96.         }
  97.         throw new ItemNotFoundException(sprintf('Item not found for "%s".'$iri));
  98.     }
  99.     /**
  100.      * {@inheritdoc}
  101.      */
  102.     public function getIriFromItem($itemint $referenceType null): string
  103.     {
  104.         $resourceClass $this->getResourceClass($itemtrue);
  105.         try {
  106.             $identifiers $this->identifiersExtractor->getIdentifiersFromItem($item);
  107.         } catch (RuntimeException $e) {
  108.             throw new InvalidArgumentException(sprintf('Unable to generate an IRI for the item of type "%s"'$resourceClass), $e->getCode(), $e);
  109.         }
  110.         return $this->getItemIriFromResourceClass($resourceClass$identifiers$this->getReferenceType($resourceClass$referenceType));
  111.     }
  112.     /**
  113.      * {@inheritdoc}
  114.      */
  115.     public function getIriFromResourceClass(string $resourceClassint $referenceType null): string
  116.     {
  117.         try {
  118.             return $this->router->generate($this->routeNameResolver->getRouteName($resourceClassOperationType::COLLECTION), [], $this->getReferenceType($resourceClass$referenceType));
  119.         } catch (RoutingExceptionInterface $e) {
  120.             throw new InvalidArgumentException(sprintf('Unable to generate an IRI for "%s".'$resourceClass), $e->getCode(), $e);
  121.         }
  122.     }
  123.     /**
  124.      * {@inheritdoc}
  125.      */
  126.     public function getItemIriFromResourceClass(string $resourceClass, array $identifiersint $referenceType null): string
  127.     {
  128.         $routeName $this->routeNameResolver->getRouteName($resourceClassOperationType::ITEM);
  129.         $metadata $this->resourceMetadataFactory->create($resourceClass);
  130.         if (\count($identifiers) > && true === $metadata->getAttribute('composite_identifier'true)) {
  131.             $identifiers = ['id' => CompositeIdentifierParser::stringify($identifiers)];
  132.         }
  133.         try {
  134.             return $this->router->generate($routeName$identifiers$this->getReferenceType($resourceClass$referenceType));
  135.         } catch (RoutingExceptionInterface $e) {
  136.             throw new InvalidArgumentException(sprintf('Unable to generate an IRI for "%s".'$resourceClass), $e->getCode(), $e);
  137.         }
  138.     }
  139.     /**
  140.      * {@inheritdoc}
  141.      */
  142.     public function getSubresourceIriFromResourceClass(string $resourceClass, array $contextint $referenceType null): string
  143.     {
  144.         try {
  145.             return $this->router->generate($this->routeNameResolver->getRouteName($resourceClassOperationType::SUBRESOURCE$context), $context['subresource_identifiers'], $this->getReferenceType($resourceClass$referenceType));
  146.         } catch (RoutingExceptionInterface $e) {
  147.             throw new InvalidArgumentException(sprintf('Unable to generate an IRI for "%s".'$resourceClass), $e->getCode(), $e);
  148.         }
  149.     }
  150.     private function getReferenceType(string $resourceClass, ?int $referenceType): ?int
  151.     {
  152.         if (null === $referenceType && null !== $this->resourceMetadataFactory) {
  153.             $metadata $this->resourceMetadataFactory->create($resourceClass);
  154.             $referenceType $metadata->getAttribute('url_generation_strategy');
  155.         }
  156.         return $referenceType ?? UrlGeneratorInterface::ABS_PATH;
  157.     }
  158. }