vendor/api-platform/core/src/Core/Api/IdentifiersExtractor.php line 49
- <?php
- /*
- * This file is part of the API Platform project.
- *
- * (c) Kévin Dunglas <dunglas@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- declare(strict_types=1);
- namespace ApiPlatform\Core\Api;
- use ApiPlatform\Api\IdentifiersExtractor as NewIdentifiersExtractor;
- use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
- use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
- use ApiPlatform\Exception\RuntimeException;
- use ApiPlatform\Util\ResourceClassInfoTrait;
- use Symfony\Component\PropertyAccess\PropertyAccess;
- use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
- /**
- * {@inheritdoc}
- *
- * @author Antoine Bluchet <soyuka@gmail.com>
- */
- final class IdentifiersExtractor implements IdentifiersExtractorInterface
- {
- use ResourceClassInfoTrait;
- private $propertyNameCollectionFactory;
- private $propertyMetadataFactory;
- private $propertyAccessor;
- public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, PropertyAccessorInterface $propertyAccessor = null, ResourceClassResolverInterface $resourceClassResolver = null, bool $metadataBackwardCompatibilityLayer = null)
- {
- $this->propertyNameCollectionFactory = $propertyNameCollectionFactory;
- $this->propertyMetadataFactory = $propertyMetadataFactory;
- $this->propertyAccessor = $propertyAccessor ?? PropertyAccess::createPropertyAccessor();
- $this->resourceClassResolver = $resourceClassResolver;
- if (null === $this->resourceClassResolver) {
- @trigger_error(sprintf('Not injecting %s in the IdentifiersExtractor might introduce cache issues with object identifiers.', ResourceClassResolverInterface::class), \E_USER_DEPRECATED);
- }
- if ($metadataBackwardCompatibilityLayer) {
- trigger_deprecation('api-platform/core', '2.7', sprintf('The service "%s" is deprecated, use %s instead.', self::class, NewIdentifiersExtractor::class));
- }
- }
- /**
- * {@inheritdoc}
- */
- public function getIdentifiersFromResourceClass(string $resourceClass): array
- {
- $identifiers = [];
- foreach ($properties = $this->propertyNameCollectionFactory->create($resourceClass) as $property) {
- if ($this->propertyMetadataFactory->create($resourceClass, $property)->isIdentifier() ?? false) {
- $identifiers[] = $property;
- }
- }
- if (!$identifiers) {
- if (\in_array('id', iterator_to_array($properties), true)) {
- return ['id'];
- }
- 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));
- }
- return $identifiers;
- }
- /**
- * {@inheritdoc}
- */
- public function getIdentifiersFromItem($item): array
- {
- $identifiers = [];
- $resourceClass = $this->getResourceClass($item, true);
- $identifierProperties = $this->getIdentifiersFromResourceClass($resourceClass);
- foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) {
- if (!\in_array($propertyName, $identifierProperties, true)) {
- continue;
- }
- $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName);
- $identifier = $identifiers[$propertyName] = $this->propertyAccessor->getValue($item, $propertyName);
- if (!\is_object($identifier)) {
- continue;
- }
- if (null === $relatedResourceClass = $this->getResourceClass($identifier)) {
- continue;
- }
- $relatedItem = $identifier;
- unset($identifiers[$propertyName]);
- foreach ($this->propertyNameCollectionFactory->create($relatedResourceClass) as $relatedPropertyName) {
- $propertyMetadata = $this->propertyMetadataFactory->create($relatedResourceClass, $relatedPropertyName);
- if ($propertyMetadata->isIdentifier()) {
- if (isset($identifiers[$propertyName])) {
- throw new RuntimeException(sprintf('Composite identifiers not supported in "%s" through relation "%s" of "%s" used as identifier', $relatedResourceClass, $propertyName, $resourceClass));
- }
- $identifiers[$propertyName] = $this->propertyAccessor->getValue($relatedItem, $relatedPropertyName);
- }
- }
- if (!isset($identifiers[$propertyName])) {
- throw new RuntimeException(sprintf('No identifier found in "%s" through relation "%s" of "%s" used as identifier', $relatedResourceClass, $propertyName, $resourceClass));
- }
- }
- return $identifiers;
- }
- }