vendor/symfony/doctrine-bridge/Form/ChoiceList/ORMQueryBuilderLoader.php line 47

Open in your IDE?
  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\Bridge\Doctrine\Form\ChoiceList;
  11. use Doctrine\DBAL\ArrayParameterType;
  12. use Doctrine\DBAL\Connection;
  13. use Doctrine\DBAL\Types\ConversionException;
  14. use Doctrine\DBAL\Types\Type;
  15. use Doctrine\ORM\QueryBuilder;
  16. use Symfony\Component\Form\Exception\TransformationFailedException;
  17. /**
  18.  * Loads entities using a {@link QueryBuilder} instance.
  19.  *
  20.  * @author Benjamin Eberlei <kontakt@beberlei.de>
  21.  * @author Bernhard Schussek <bschussek@gmail.com>
  22.  */
  23. class ORMQueryBuilderLoader implements EntityLoaderInterface
  24. {
  25.     /**
  26.      * Contains the query builder that builds the query for fetching the
  27.      * entities.
  28.      *
  29.      * This property should only be accessed through queryBuilder.
  30.      *
  31.      * @var QueryBuilder
  32.      */
  33.     private $queryBuilder;
  34.     public function __construct(QueryBuilder $queryBuilder)
  35.     {
  36.         $this->queryBuilder $queryBuilder;
  37.     }
  38.     /**
  39.      * {@inheritdoc}
  40.      */
  41.     public function getEntities()
  42.     {
  43.         return $this->queryBuilder->getQuery()->execute();
  44.     }
  45.     /**
  46.      * {@inheritdoc}
  47.      */
  48.     public function getEntitiesByIds(string $identifier, array $values)
  49.     {
  50.         if (null !== $this->queryBuilder->getMaxResults() || < (int) $this->queryBuilder->getFirstResult()) {
  51.             // an offset or a limit would apply on results including the where clause with submitted id values
  52.             // that could make invalid choices valid
  53.             $choices = [];
  54.             $metadata $this->queryBuilder->getEntityManager()->getClassMetadata(current($this->queryBuilder->getRootEntities()));
  55.             foreach ($this->getEntities() as $entity) {
  56.                 if (\in_array((string) current($metadata->getIdentifierValues($entity)), $valuestrue)) {
  57.                     $choices[] = $entity;
  58.                 }
  59.             }
  60.             return $choices;
  61.         }
  62.         $qb = clone $this->queryBuilder;
  63.         $alias current($qb->getRootAliases());
  64.         $parameter 'ORMQueryBuilderLoader_getEntitiesByIds_'.$identifier;
  65.         $parameter str_replace('.''_'$parameter);
  66.         $where $qb->expr()->in($alias.'.'.$identifier':'.$parameter);
  67.         // Guess type
  68.         $entity current($qb->getRootEntities());
  69.         $metadata $qb->getEntityManager()->getClassMetadata($entity);
  70.         if (\in_array($type $metadata->getTypeOfField($identifier), ['integer''bigint''smallint'])) {
  71.             $parameterType class_exists(ArrayParameterType::class) ? ArrayParameterType::INTEGER Connection::PARAM_INT_ARRAY;
  72.             // Filter out non-integer values (e.g. ""). If we don't, some
  73.             // databases such as PostgreSQL fail.
  74.             $values array_values(array_filter($values, function ($v) {
  75.                 return (string) $v === (string) (int) $v || ctype_digit($v);
  76.             }));
  77.         } elseif (\in_array($type, ['ulid''uuid''guid'])) {
  78.             $parameterType class_exists(ArrayParameterType::class) ? ArrayParameterType::STRING Connection::PARAM_STR_ARRAY;
  79.             // Like above, but we just filter out empty strings.
  80.             $values array_values(array_filter($values, function ($v) {
  81.                 return '' !== (string) $v;
  82.             }));
  83.             // Convert values into right type
  84.             if (Type::hasType($type)) {
  85.                 $doctrineType Type::getType($type);
  86.                 $platform $qb->getEntityManager()->getConnection()->getDatabasePlatform();
  87.                 foreach ($values as &$value) {
  88.                     try {
  89.                         $value $doctrineType->convertToDatabaseValue($value$platform);
  90.                     } catch (ConversionException $e) {
  91.                         throw new TransformationFailedException(sprintf('Failed to transform "%s" into "%s".'$value$type), 0$e);
  92.                     }
  93.                 }
  94.                 unset($value);
  95.             }
  96.         } else {
  97.             $parameterType class_exists(ArrayParameterType::class) ? ArrayParameterType::STRING Connection::PARAM_STR_ARRAY;
  98.         }
  99.         if (!$values) {
  100.             return [];
  101.         }
  102.         return $qb->andWhere($where)
  103.                   ->getQuery()
  104.                   ->setParameter($parameter$values$parameterType)
  105.                   ->getResult();
  106.     }
  107. }