vendor/api-platform/core/src/Core/Api/IdentifiersExtractor.php line 47

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\Api;
  12. use ApiPlatform\Api\IdentifiersExtractor as NewIdentifiersExtractor;
  13. use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
  14. use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
  15. use ApiPlatform\Exception\RuntimeException;
  16. use ApiPlatform\Util\ResourceClassInfoTrait;
  17. use Symfony\Component\PropertyAccess\PropertyAccess;
  18. use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
  19. /**
  20.  * @author Antoine Bluchet <soyuka@gmail.com>
  21.  */
  22. final class IdentifiersExtractor implements IdentifiersExtractorInterface
  23. {
  24.     use ResourceClassInfoTrait;
  25.     private $propertyNameCollectionFactory;
  26.     private $propertyMetadataFactory;
  27.     private $propertyAccessor;
  28.     public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactoryPropertyMetadataFactoryInterface $propertyMetadataFactoryPropertyAccessorInterface $propertyAccessor nullResourceClassResolverInterface $resourceClassResolver nullbool $metadataBackwardCompatibilityLayer null)
  29.     {
  30.         $this->propertyNameCollectionFactory $propertyNameCollectionFactory;
  31.         $this->propertyMetadataFactory $propertyMetadataFactory;
  32.         $this->propertyAccessor $propertyAccessor ?? PropertyAccess::createPropertyAccessor();
  33.         $this->resourceClassResolver $resourceClassResolver;
  34.         if (null === $this->resourceClassResolver) {
  35.             @trigger_error(sprintf('Not injecting %s in the IdentifiersExtractor might introduce cache issues with object identifiers.'ResourceClassResolverInterface::class), \E_USER_DEPRECATED);
  36.         }
  37.         if ($metadataBackwardCompatibilityLayer) {
  38.             trigger_deprecation('api-platform/core''2.7'sprintf('The service "%s" is deprecated, use %s instead.'self::class, NewIdentifiersExtractor::class));
  39.         }
  40.     }
  41.     public function getIdentifiersFromResourceClass(string $resourceClass): array
  42.     {
  43.         $identifiers = [];
  44.         foreach ($properties $this->propertyNameCollectionFactory->create($resourceClass) as $property) {
  45.             if ($this->propertyMetadataFactory->create($resourceClass$property)->isIdentifier() ?? false) {
  46.                 $identifiers[] = $property;
  47.             }
  48.         }
  49.         if (!$identifiers) {
  50.             if (\in_array('id'iterator_to_array($properties), true)) {
  51.                 return ['id'];
  52.             }
  53.             throw new RuntimeException(sprintf('No identifier defined in "%s". You should add #[\ApiPlatform\Core\Annotation\ApiProperty(identifier: true)]" on the property identifying the resource."'$resourceClass));
  54.         }
  55.         return $identifiers;
  56.     }
  57.     public function getIdentifiersFromItem($item): array
  58.     {
  59.         $identifiers = [];
  60.         $resourceClass $this->getResourceClass($itemtrue);
  61.         $identifierProperties $this->getIdentifiersFromResourceClass($resourceClass);
  62.         foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) {
  63.             if (!\in_array($propertyName$identifierPropertiestrue)) {
  64.                 continue;
  65.             }
  66.             $propertyMetadata $this->propertyMetadataFactory->create($resourceClass$propertyName);
  67.             $identifier $identifiers[$propertyName] = $this->propertyAccessor->getValue($item$propertyName);
  68.             if (!\is_object($identifier)) {
  69.                 continue;
  70.             }
  71.             if (null === $relatedResourceClass $this->getResourceClass($identifier)) {
  72.                 continue;
  73.             }
  74.             $relatedItem $identifier;
  75.             unset($identifiers[$propertyName]);
  76.             foreach ($this->propertyNameCollectionFactory->create($relatedResourceClass) as $relatedPropertyName) {
  77.                 $propertyMetadata $this->propertyMetadataFactory->create($relatedResourceClass$relatedPropertyName);
  78.                 if ($propertyMetadata->isIdentifier()) {
  79.                     if (isset($identifiers[$propertyName])) {
  80.                         throw new RuntimeException(sprintf('Composite identifiers not supported in "%s" through relation "%s" of "%s" used as identifier'$relatedResourceClass$propertyName$resourceClass));
  81.                     }
  82.                     $identifiers[$propertyName] = $this->propertyAccessor->getValue($relatedItem$relatedPropertyName);
  83.                 }
  84.             }
  85.             if (!isset($identifiers[$propertyName])) {
  86.                 throw new RuntimeException(sprintf('No identifier found in "%s" through relation "%s" of "%s" used as identifier'$relatedResourceClass$propertyName$resourceClass));
  87.             }
  88.         }
  89.         return $identifiers;
  90.     }
  91. }