vendor/api-platform/core/src/Core/Bridge/Doctrine/Common/PropertyHelperTrait.php line 41

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\Bridge\Doctrine\Common;
  12. use Doctrine\DBAL\Types\Type;
  13. use Doctrine\Persistence\ManagerRegistry;
  14. use Doctrine\Persistence\Mapping\ClassMetadata;
  15. /**
  16.  * Helper trait for getting information regarding a property using the resource metadata.
  17.  *
  18.  * @author Kévin Dunglas <dunglas@gmail.com>
  19.  * @author Théo FIDRY <theo.fidry@gmail.com>
  20.  * @author Alan Poulain <contact@alanpoulain.eu>
  21.  */
  22. trait PropertyHelperTrait
  23. {
  24.     abstract protected function getManagerRegistry(): ManagerRegistry;
  25.     /**
  26.      * Determines whether the given property is mapped.
  27.      */
  28.     protected function isPropertyMapped(string $propertystring $resourceClassbool $allowAssociation false): bool
  29.     {
  30.         if ($this->isPropertyNested($property$resourceClass)) {
  31.             $propertyParts $this->splitPropertyParts($property$resourceClass);
  32.             $metadata $this->getNestedMetadata($resourceClass$propertyParts['associations']);
  33.             $property $propertyParts['field'];
  34.         } else {
  35.             $metadata $this->getClassMetadata($resourceClass);
  36.         }
  37.         return $metadata->hasField($property) || ($allowAssociation && $metadata->hasAssociation($property));
  38.     }
  39.     /**
  40.      * Determines whether the given property is nested.
  41.      */
  42.     protected function isPropertyNested(string $property/* , string $resourceClass */): bool
  43.     {
  44.         if (\func_num_args() > 1) {
  45.             $resourceClass = (string) func_get_arg(1);
  46.         } else {
  47.             if (__CLASS__ !== static::class) { // @phpstan-ignore-line
  48.                 $r = new \ReflectionMethod($this__FUNCTION__);
  49.                 if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
  50.                     @trigger_error(sprintf('Method %s() will have a second `$resourceClass` argument in version API Platform 3.0. Not defining it is deprecated since API Platform 2.1.'__FUNCTION__), \E_USER_DEPRECATED);
  51.                 }
  52.             }
  53.             $resourceClass null;
  54.         }
  55.         $pos strpos($property'.');
  56.         if (false === $pos) {
  57.             return false;
  58.         }
  59.         return null !== $resourceClass && $this->getClassMetadata($resourceClass)->hasAssociation(substr($property0$pos));
  60.     }
  61.     /**
  62.      * Determines whether the given property is embedded.
  63.      */
  64.     protected function isPropertyEmbedded(string $propertystring $resourceClass): bool
  65.     {
  66.         return false !== strpos($property'.') && $this->getClassMetadata($resourceClass)->hasField($property);
  67.     }
  68.     /**
  69.      * Splits the given property into parts.
  70.      *
  71.      * Returns an array with the following keys:
  72.      *   - associations: array of associations according to nesting order
  73.      *   - field: string holding the actual field (leaf node)
  74.      */
  75.     protected function splitPropertyParts(string $property/* , string $resourceClass */): array
  76.     {
  77.         $resourceClass null;
  78.         $parts explode('.'$property);
  79.         if (\func_num_args() > 1) {
  80.             $resourceClass func_get_arg(1);
  81.         } elseif (__CLASS__ !== static::class) { // @phpstan-ignore-line
  82.             $r = new \ReflectionMethod($this__FUNCTION__);
  83.             if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
  84.                 @trigger_error(sprintf('Method %s() will have a second `$resourceClass` argument in version API Platform 3.0. Not defining it is deprecated since API Platform 2.1.'__FUNCTION__), \E_USER_DEPRECATED);
  85.             }
  86.         }
  87.         if (null === $resourceClass) {
  88.             return [
  89.                 'associations' => \array_slice($parts0, -1),
  90.                 'field' => end($parts),
  91.             ];
  92.         }
  93.         $metadata $this->getClassMetadata($resourceClass);
  94.         $slice 0;
  95.         foreach ($parts as $part) {
  96.             if ($metadata->hasAssociation($part)) {
  97.                 $metadata $this->getClassMetadata($metadata->getAssociationTargetClass($part));
  98.                 ++$slice;
  99.             }
  100.         }
  101.         if (\count($parts) === $slice) {
  102.             --$slice;
  103.         }
  104.         return [
  105.             'associations' => \array_slice($parts0$slice),
  106.             'field' => implode('.'\array_slice($parts$slice)),
  107.         ];
  108.     }
  109.     /**
  110.      * Gets the Doctrine Type of a given property/resourceClass.
  111.      *
  112.      * @return string|null
  113.      */
  114.     protected function getDoctrineFieldType(string $propertystring $resourceClass)
  115.     {
  116.         $propertyParts $this->splitPropertyParts($property$resourceClass);
  117.         $metadata $this->getNestedMetadata($resourceClass$propertyParts['associations']);
  118.         return $metadata->getTypeOfField($propertyParts['field']);
  119.     }
  120.     /**
  121.      * Gets nested class metadata for the given resource.
  122.      *
  123.      * @param string[] $associations
  124.      */
  125.     protected function getNestedMetadata(string $resourceClass, array $associations): ClassMetadata
  126.     {
  127.         $metadata $this->getClassMetadata($resourceClass);
  128.         foreach ($associations as $association) {
  129.             if ($metadata->hasAssociation($association)) {
  130.                 $associationClass $metadata->getAssociationTargetClass($association);
  131.                 $metadata $this->getClassMetadata($associationClass);
  132.             }
  133.         }
  134.         return $metadata;
  135.     }
  136.     /**
  137.      * Gets class metadata for the given resource.
  138.      */
  139.     protected function getClassMetadata(string $resourceClass): ClassMetadata
  140.     {
  141.         return $this
  142.             ->getManagerRegistry()
  143.             ->getManagerForClass($resourceClass)
  144.             ->getClassMetadata($resourceClass);
  145.     }
  146. }