vendor/symfony/validator/Mapping/Loader/AnnotationLoader.php line 32

  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.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. namespace Symfony\Component\Validator\Mapping\Loader;
  11. use Doctrine\Common\Annotations\Reader;
  12. use Symfony\Component\Validator\Constraint;
  13. use Symfony\Component\Validator\Constraints\Callback;
  14. use Symfony\Component\Validator\Constraints\GroupSequence;
  15. use Symfony\Component\Validator\Constraints\GroupSequenceProvider;
  16. use Symfony\Component\Validator\Exception\MappingException;
  17. use Symfony\Component\Validator\Mapping\ClassMetadata;
  18. /**
  19.  * Loads validation metadata using a Doctrine annotation {@link Reader} or using PHP 8 attributes.
  20.  *
  21.  * @author Bernhard Schussek <bschussek@gmail.com>
  22.  * @author Alexander M. Turek <me@derrabus.de>
  23.  */
  24. class AnnotationLoader implements LoaderInterface
  25. {
  26.     protected $reader;
  27.     public function __construct(Reader $reader null)
  28.     {
  29.         $this->reader $reader;
  30.     }
  31.     public function loadClassMetadata(ClassMetadata $metadata): bool
  32.     {
  33.         $reflClass $metadata->getReflectionClass();
  34.         $className $reflClass->name;
  35.         $success false;
  36.         foreach ($this->getAnnotations($reflClass) as $constraint) {
  37.             if ($constraint instanceof GroupSequence) {
  38.                 $metadata->setGroupSequence($constraint->groups);
  39.             } elseif ($constraint instanceof GroupSequenceProvider) {
  40.                 $metadata->setGroupSequenceProvider(true);
  41.             } elseif ($constraint instanceof Constraint) {
  42.                 $metadata->addConstraint($constraint);
  43.             }
  44.             $success true;
  45.         }
  46.         foreach ($reflClass->getProperties() as $property) {
  47.             if ($property->getDeclaringClass()->name === $className) {
  48.                 foreach ($this->getAnnotations($property) as $constraint) {
  49.                     if ($constraint instanceof Constraint) {
  50.                         $metadata->addPropertyConstraint($property->name$constraint);
  51.                     }
  52.                     $success true;
  53.                 }
  54.             }
  55.         }
  56.         foreach ($reflClass->getMethods() as $method) {
  57.             if ($method->getDeclaringClass()->name === $className) {
  58.                 foreach ($this->getAnnotations($method) as $constraint) {
  59.                     if ($constraint instanceof Callback) {
  60.                         $constraint->callback $method->getName();
  61.                         $metadata->addConstraint($constraint);
  62.                     } elseif ($constraint instanceof Constraint) {
  63.                         if (preg_match('/^(get|is|has)(.+)$/i'$method->name$matches)) {
  64.                             $metadata->addGetterMethodConstraint(lcfirst($matches[2]), $matches[0], $constraint);
  65.                         } else {
  66.                             throw new MappingException(sprintf('The constraint on "%s::%s()" cannot be added. Constraints can only be added on methods beginning with "get", "is" or "has".'$className$method->name));
  67.                         }
  68.                     }
  69.                     $success true;
  70.                 }
  71.             }
  72.         }
  73.         return $success;
  74.     }
  75.     /**
  76.      * @param \ReflectionClass|\ReflectionMethod|\ReflectionProperty $reflection
  77.      */
  78.     private function getAnnotations(object $reflection): iterable
  79.     {
  80.         foreach ($reflection->getAttributes(GroupSequence::class) as $attribute) {
  81.             yield $attribute->newInstance();
  82.         }
  83.         foreach ($reflection->getAttributes(GroupSequenceProvider::class) as $attribute) {
  84.             yield $attribute->newInstance();
  85.         }
  86.         foreach ($reflection->getAttributes(Constraint::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
  87.             yield $attribute->newInstance();
  88.         }
  89.         if (!$this->reader) {
  90.             return;
  91.         }
  92.         if ($reflection instanceof \ReflectionClass) {
  93.             yield from $this->reader->getClassAnnotations($reflection);
  94.         }
  95.         if ($reflection instanceof \ReflectionMethod) {
  96.             yield from $this->reader->getMethodAnnotations($reflection);
  97.         }
  98.         if ($reflection instanceof \ReflectionProperty) {
  99.             yield from $this->reader->getPropertyAnnotations($reflection);
  100.         }
  101.     }
  102. }