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

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