vendor/api-platform/core/src/Doctrine/Common/PropertyHelperTrait.php line 132

  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\Doctrine\Common;
  12. use Doctrine\Persistence\ManagerRegistry;
  13. use Doctrine\Persistence\Mapping\ClassMetadata;
  14. /**
  15.  * Helper trait for getting information regarding a property using the resource metadata.
  16.  *
  17.  * @author Kévin Dunglas <dunglas@gmail.com>
  18.  * @author Théo FIDRY <theo.fidry@gmail.com>
  19.  * @author Alan Poulain <contact@alanpoulain.eu>
  20.  */
  21. trait PropertyHelperTrait
  22. {
  23.     abstract protected function getManagerRegistry(): ManagerRegistry;
  24.     /**
  25.      * Determines whether the given property is mapped.
  26.      */
  27.     protected function isPropertyMapped(string $propertystring $resourceClassbool $allowAssociation false): bool
  28.     {
  29.         if ($this->isPropertyNested($property$resourceClass)) {
  30.             $propertyParts $this->splitPropertyParts($property$resourceClass);
  31.             $metadata $this->getNestedMetadata($resourceClass$propertyParts['associations']);
  32.             $property $propertyParts['field'];
  33.         } else {
  34.             $metadata $this->getClassMetadata($resourceClass);
  35.         }
  36.         return $metadata->hasField($property) || ($allowAssociation && $metadata->hasAssociation($property));
  37.     }
  38.     /**
  39.      * Determines whether the given property is nested.
  40.      */
  41.     protected function isPropertyNested(string $propertystring $resourceClass): bool
  42.     {
  43.         $pos strpos($property'.');
  44.         if (false === $pos) {
  45.             return false;
  46.         }
  47.         return $this->getClassMetadata($resourceClass)->hasAssociation(substr($property0$pos));
  48.     }
  49.     /**
  50.      * Determines whether the given property is embedded.
  51.      */
  52.     protected function isPropertyEmbedded(string $propertystring $resourceClass): bool
  53.     {
  54.         return str_contains($property'.') && $this->getClassMetadata($resourceClass)->hasField($property);
  55.     }
  56.     /**
  57.      * Splits the given property into parts.
  58.      *
  59.      * Returns an array with the following keys:
  60.      *   - associations: array of associations according to nesting order
  61.      *   - field: string holding the actual field (leaf node)
  62.      */
  63.     protected function splitPropertyParts(string $propertystring $resourceClass): array
  64.     {
  65.         $parts explode('.'$property);
  66.         $metadata $this->getClassMetadata($resourceClass);
  67.         $slice 0;
  68.         foreach ($parts as $part) {
  69.             if ($metadata->hasAssociation($part)) {
  70.                 $metadata $this->getClassMetadata($metadata->getAssociationTargetClass($part));
  71.                 ++$slice;
  72.             }
  73.         }
  74.         if (\count($parts) === $slice) {
  75.             --$slice;
  76.         }
  77.         return [
  78.             'associations' => \array_slice($parts0$slice),
  79.             'field' => implode('.'\array_slice($parts$slice)),
  80.         ];
  81.     }
  82.     /**
  83.      * Gets the Doctrine Type of a given property/resourceClass.
  84.      */
  85.     protected function getDoctrineFieldType(string $propertystring $resourceClass): ?string
  86.     {
  87.         $propertyParts $this->splitPropertyParts($property$resourceClass);
  88.         $metadata $this->getNestedMetadata($resourceClass$propertyParts['associations']);
  89.         return $metadata->getTypeOfField($propertyParts['field']);
  90.     }
  91.     /**
  92.      * Gets nested class metadata for the given resource.
  93.      *
  94.      * @param string[] $associations
  95.      */
  96.     protected function getNestedMetadata(string $resourceClass, array $associations): ClassMetadata
  97.     {
  98.         $metadata $this->getClassMetadata($resourceClass);
  99.         foreach ($associations as $association) {
  100.             if ($metadata->hasAssociation($association)) {
  101.                 $associationClass $metadata->getAssociationTargetClass($association);
  102.                 $metadata $this->getClassMetadata($associationClass);
  103.             }
  104.         }
  105.         return $metadata;
  106.     }
  107.     /**
  108.      * Gets class metadata for the given resource.
  109.      */
  110.     protected function getClassMetadata(string $resourceClass): ClassMetadata
  111.     {
  112.         return $this
  113.             ->getManagerRegistry()
  114.             ->getManagerForClass($resourceClass)
  115.             ->getClassMetadata($resourceClass);
  116.     }
  117. }