vendor/api-platform/core/src/Core/Identifier/IdentifierConverter.php line 40

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\Identifier;
  12. use ApiPlatform\Core\Api\IdentifiersExtractorInterface;
  13. use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
  14. use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
  15. use ApiPlatform\Exception\InvalidIdentifierException;
  16. use Symfony\Component\PropertyInfo\Type;
  17. use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
  18. /**
  19. * Identifier converter that chains identifier denormalizers.
  20. *
  21. * @author Antoine Bluchet <soyuka@gmail.com>
  22. */
  23. final class IdentifierConverter implements ContextAwareIdentifierConverterInterface
  24. {
  25. private $propertyMetadataFactory;
  26. private $identifiersExtractor;
  27. private $identifierDenormalizers;
  28. private $resourceMetadataFactory;
  29. /**
  30. * TODO: rename identifierDenormalizers to identifierTransformers in 3.0 and change their interfaces to a IdentifierTransformerInterface.
  31. *
  32. * @param iterable<DenormalizerInterface> $identifierDenormalizers
  33. */
  34. public function __construct(IdentifiersExtractorInterface $identifiersExtractor, PropertyMetadataFactoryInterface $propertyMetadataFactory, iterable $identifierDenormalizers, ResourceMetadataFactoryInterface $resourceMetadataFactory = null)
  35. {
  36. $this->propertyMetadataFactory = $propertyMetadataFactory;
  37. $this->identifiersExtractor = $identifiersExtractor;
  38. $this->identifierDenormalizers = $identifierDenormalizers;
  39. $this->resourceMetadataFactory = $resourceMetadataFactory;
  40. }
  41. /**
  42. * {@inheritdoc}
  43. */
  44. public function convert($data, string $class, array $context = []): array
  45. {
  46. if (!\is_array($data)) {
  47. @trigger_error(sprintf('Not using an array as the first argument of "%s->convert" is deprecated since API Platform 2.6 and will not be possible anymore in API Platform 3', self::class), \E_USER_DEPRECATED);
  48. $data = ['id' => $data];
  49. }
  50. $identifiers = $data;
  51. foreach ($data as $parameter => $value) {
  52. if (null === $type = $this->getIdentifierType($context['identifiers'][$parameter][0] ?? $class, $context['identifiers'][$parameter][1] ?? $parameter)) {
  53. continue;
  54. }
  55. /* @var DenormalizerInterface[] */
  56. foreach ($this->identifierDenormalizers as $identifierTransformer) {
  57. if (!$identifierTransformer->supportsDenormalization($value, $type)) {
  58. continue;
  59. }
  60. try {
  61. $identifiers[$parameter] = $identifierTransformer->denormalize($value, $type);
  62. break;
  63. } catch (InvalidIdentifierException $e) { // @phpstan-ignore-line wrong choice of interface, was fixed in 3.0
  64. throw new InvalidIdentifierException(sprintf('Identifier "%s" could not be denormalized.', $parameter), $e->getCode(), $e);
  65. }
  66. }
  67. }
  68. return $identifiers;
  69. }
  70. private function getIdentifierType(string $resourceClass, string $property): ?string
  71. {
  72. if (!$type = $this->propertyMetadataFactory->create($resourceClass, $property)->getType()) {
  73. return null;
  74. }
  75. return Type::BUILTIN_TYPE_OBJECT === ($builtinType = $type->getBuiltinType()) ? $type->getClassName() : $builtinType;
  76. }
  77. }