vendor/api-platform/core/src/Metadata/Property/Factory/AnnotationSubresourceMetadataFactory.php line 44

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\Metadata\Property\Factory;
  12. use ApiPlatform\Core\Annotation\ApiSubresource;
  13. use ApiPlatform\Core\Exception\InvalidResourceException;
  14. use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
  15. use ApiPlatform\Core\Metadata\Property\SubresourceMetadata;
  16. use ApiPlatform\Core\Util\Reflection;
  17. use Doctrine\Common\Annotations\Reader;
  18. /**
  19.  * Adds subresources to the properties metadata from {@see ApiResource} annotations.
  20.  *
  21.  * @author Antoine Bluchet <soyuka@gmail.com>
  22.  */
  23. final class AnnotationSubresourceMetadataFactory implements PropertyMetadataFactoryInterface
  24. {
  25.     private $reader;
  26.     private $decorated;
  27.     public function __construct(Reader $readerPropertyMetadataFactoryInterface $decorated)
  28.     {
  29.         $this->reader $reader;
  30.         $this->decorated $decorated;
  31.     }
  32.     /**
  33.      * {@inheritdoc}
  34.      */
  35.     public function create(string $resourceClassstring $property, array $options = []): PropertyMetadata
  36.     {
  37.         $propertyMetadata $this->decorated->create($resourceClass$property$options);
  38.         try {
  39.             $reflectionClass = new \ReflectionClass($resourceClass);
  40.         } catch (\ReflectionException $reflectionException) {
  41.             return $propertyMetadata;
  42.         }
  43.         if ($reflectionClass->hasProperty($property)) {
  44.             $annotation $this->reader->getPropertyAnnotation($reflectionClass->getProperty($property), ApiSubresource::class);
  45.             if ($annotation instanceof ApiSubresource) {
  46.                 return $this->updateMetadata($annotation$propertyMetadata$resourceClass$property);
  47.             }
  48.         }
  49.         foreach (array_merge(Reflection::ACCESSOR_PREFIXESReflection::MUTATOR_PREFIXES) as $prefix) {
  50.             $methodName $prefix.ucfirst($property);
  51.             if (!$reflectionClass->hasMethod($methodName)) {
  52.                 continue;
  53.             }
  54.             $reflectionMethod $reflectionClass->getMethod($methodName);
  55.             if (!$reflectionMethod->isPublic()) {
  56.                 continue;
  57.             }
  58.             $annotation $this->reader->getMethodAnnotation($reflectionMethodApiSubresource::class);
  59.             if ($annotation instanceof ApiSubresource) {
  60.                 return $this->updateMetadata($annotation$propertyMetadata$resourceClass$property);
  61.             }
  62.         }
  63.         return $propertyMetadata;
  64.     }
  65.     private function updateMetadata(ApiSubresource $annotationPropertyMetadata $propertyMetadatastring $originResourceClassstring $propertyName): PropertyMetadata
  66.     {
  67.         $type $propertyMetadata->getType();
  68.         if (null === $type) {
  69.             throw new InvalidResourceException(sprintf('Property "%s" on resource "%s" is declared as a subresource, but its type could not be determined.'$propertyName$originResourceClass));
  70.         }
  71.         $isCollection $type->isCollection();
  72.         $resourceClass $isCollection && ($collectionValueType $type->getCollectionValueType()) ? $collectionValueType->getClassName() : $type->getClassName();
  73.         $maxDepth $annotation->maxDepth;
  74.         // @ApiSubresource is on the class identifier (/collection/{id}/subcollection/{subcollectionId})
  75.         if (null === $resourceClass) {
  76.             $resourceClass $originResourceClass;
  77.             $isCollection false;
  78.         }
  79.         return $propertyMetadata->withSubresource(new SubresourceMetadata($resourceClass$isCollection$maxDepth));
  80.     }
  81. }