vendor/happyr/doctrine-specification/src/Repository/EntitySpecificationRepositoryTrait.php line 163

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4.  * This file is part of the Happyr Doctrine Specification package.
  5.  *
  6.  * (c) Tobias Nyholm <tobias@happyr.com>
  7.  *     Kacper Gunia <kacper@gunia.me>
  8.  *     Peter Gribanov <info@peter-gribanov.ru>
  9.  *
  10.  * For the full copyright and license information, please view the LICENSE
  11.  * file that was distributed with this source code.
  12.  */
  13. namespace Happyr\DoctrineSpecification\Repository;
  14. use Doctrine\ORM\AbstractQuery;
  15. use Doctrine\ORM\NonUniqueResultException as DoctrineNonUniqueResultException;
  16. use Doctrine\ORM\NoResultException as DoctrineNoResultException;
  17. use Doctrine\ORM\Query;
  18. use Doctrine\ORM\QueryBuilder;
  19. use Happyr\DoctrineSpecification\Exception\NonUniqueResultException;
  20. use Happyr\DoctrineSpecification\Exception\NoResultException;
  21. use Happyr\DoctrineSpecification\Filter\Filter;
  22. use Happyr\DoctrineSpecification\Query\QueryModifier;
  23. use Happyr\DoctrineSpecification\Result\ResultModifier;
  24. /**
  25.  * This trait should be used by a class extending \Doctrine\ORM\EntityRepository.
  26.  */
  27. trait EntitySpecificationRepositoryTrait
  28. {
  29.     /**
  30.      * @var string
  31.      */
  32.     private $alias 'root';
  33.     /**
  34.      * Get results when you match with a Specification.
  35.      *
  36.      * @param Filter|QueryModifier $specification
  37.      * @param ResultModifier|null  $modifier
  38.      *
  39.      * @return mixed
  40.      */
  41.     public function match($specification, ?ResultModifier $modifier null)
  42.     {
  43.         $query $this->getQuery($specification$modifier);
  44.         return $query->execute();
  45.     }
  46.     /**
  47.      * Get single result when you match with a Specification.
  48.      *
  49.      * @param Filter|QueryModifier $specification
  50.      * @param ResultModifier|null  $modifier
  51.      *
  52.      * @throw Exception\NonUniqueException  If more than one result is found
  53.      * @throw Exception\NoResultException   If no results found
  54.      *
  55.      * @return mixed
  56.      */
  57.     public function matchSingleResult($specification, ?ResultModifier $modifier null)
  58.     {
  59.         $query $this->getQuery($specification$modifier);
  60.         try {
  61.             return $query->getSingleResult();
  62.         } catch (DoctrineNonUniqueResultException $e) {
  63.             throw new NonUniqueResultException($e->getMessage(), $e->getCode(), $e);
  64.         } catch (DoctrineNoResultException $e) {
  65.             throw new NoResultException($e->getMessage(), $e->getCode(), $e);
  66.         }
  67.     }
  68.     /**
  69.      * Get single result or null when you match with a Specification.
  70.      *
  71.      * @param Filter|QueryModifier $specification
  72.      * @param ResultModifier|null  $modifier
  73.      *
  74.      * @throw Exception\NonUniqueException  If more than one result is found
  75.      *
  76.      * @return mixed|null
  77.      */
  78.     public function matchOneOrNullResult($specification, ?ResultModifier $modifier null)
  79.     {
  80.         try {
  81.             return $this->matchSingleResult($specification$modifier);
  82.         } catch (NoResultException $e) {
  83.             return null;
  84.         }
  85.     }
  86.     /**
  87.      * Get single scalar result when you match with a Specification.
  88.      *
  89.      * @param Filter|QueryModifier $specification
  90.      * @param ResultModifier|null  $modifier
  91.      *
  92.      * @throw Exception\NonUniqueException  If more than one result is found
  93.      * @throw Exception\NoResultException   If no results found
  94.      *
  95.      * @return mixed
  96.      */
  97.     public function matchSingleScalarResult($specification, ?ResultModifier $modifier null)
  98.     {
  99.         $query $this->getQuery($specification$modifier);
  100.         try {
  101.             return $query->getSingleScalarResult();
  102.         } catch (DoctrineNonUniqueResultException $e) {
  103.             throw new NonUniqueResultException($e->getMessage(), $e->getCode(), $e);
  104.         }
  105.     }
  106.     /**
  107.      * Get scalar result when you match with a Specification.
  108.      *
  109.      * @param Filter|QueryModifier $specification
  110.      * @param ResultModifier|null  $modifier
  111.      *
  112.      * @throw Exception\NonUniqueException  If more than one result is found
  113.      * @throw Exception\NoResultException   If no results found
  114.      *
  115.      * @return mixed
  116.      */
  117.     public function matchScalarResult($specification, ?ResultModifier $modifier null)
  118.     {
  119.         $query $this->getQuery($specification$modifier);
  120.         return $query->getScalarResult();
  121.     }
  122.     /**
  123.      * Prepare a Query with a Specification.
  124.      *
  125.      * @param Filter|QueryModifier $specification
  126.      * @param ResultModifier|null  $modifier
  127.      *
  128.      * @return Query
  129.      */
  130.     public function getQuery($specification, ?ResultModifier $modifier null): AbstractQuery
  131.     {
  132.         $query $this->getQueryBuilder($specification)->getQuery();
  133.         if (null !== $modifier) {
  134.             $modifier->modify($query);
  135.         }
  136.         return $query;
  137.     }
  138.     /**
  139.      * @param Filter|QueryModifier $specification
  140.      * @param string|null          $alias
  141.      *
  142.      * @return QueryBuilder
  143.      */
  144.     public function getQueryBuilder($specification, ?string $alias null): QueryBuilder
  145.     {
  146.         $qb $this->createQueryBuilder($alias ?: $this->getAlias());
  147.         $this->applySpecification($qb$specification$alias);
  148.         return $qb;
  149.     }
  150.     /**
  151.      * Iterate results when you match with a Specification.
  152.      *
  153.      * @param Filter|QueryModifier $specification
  154.      * @param ResultModifier|null  $modifier
  155.      *
  156.      * @return \Traversable<mixed>
  157.      */
  158.     public function iterate($specification, ?ResultModifier $modifier null): \Traversable
  159.     {
  160.         $query $this->getQuery($specification$modifier);
  161.         if (method_exists($query'toIterable')) {
  162.             yield from $query->toIterable();
  163.         } else {
  164.             foreach ($query->iterate() as $key => $row) {
  165.                 yield $key => current($row);
  166.             }
  167.         }
  168.     }
  169.     /**
  170.      * @param string $alias
  171.      */
  172.     public function setAlias(string $alias): void
  173.     {
  174.         $this->alias $alias;
  175.     }
  176.     /**
  177.      * @return string
  178.      */
  179.     public function getAlias(): string
  180.     {
  181.         return $this->alias;
  182.     }
  183.     /**
  184.      * @param QueryBuilder         $queryBuilder
  185.      * @param Filter|QueryModifier $specification
  186.      * @param string|null          $alias
  187.      *
  188.      * @throws \InvalidArgumentException
  189.      */
  190.     protected function applySpecification(
  191.         QueryBuilder $queryBuilder,
  192.         $specification null,
  193.         ?string $alias null
  194.     ): void {
  195.         if ($specification instanceof QueryModifier) {
  196.             $specification->modify($queryBuilder$alias ?: $this->getAlias());
  197.         }
  198.         if ($specification instanceof Filter) {
  199.             $filter $specification->getFilter($queryBuilder$alias ?: $this->getAlias());
  200.             $filter trim($filter);
  201.             if ('' !== $filter) {
  202.                 $queryBuilder->andWhere($filter);
  203.             }
  204.         }
  205.     }
  206. }