Completed
Push — master ( 1d488b...70a73d )
by Julián
01:52
created

getQueryBuilderFromCriteria()   C

Complexity

Conditions 7
Paths 12

Size

Total Lines 33
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 33
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 20
nc 12
nop 2
1
<?php
2
3
/*
4
 * doctrine-orm-repositories (https://github.com/juliangut/doctrine-orm-repositories).
5
 * Doctrine2 ORM utility entity repositories.
6
 *
7
 * @license MIT
8
 * @link https://github.com/juliangut/doctrine-orm-repositories
9
 * @author Julián Gutiérrez <[email protected]>
10
 */
11
12
declare(strict_types=1);
13
14
namespace Jgut\Doctrine\Repository\ORM;
15
16
use Doctrine\Common\Util\ClassUtils;
17
use Doctrine\ORM\EntityManager;
18
use Doctrine\ORM\EntityRepository;
19
use Doctrine\ORM\Query;
20
use Doctrine\ORM\QueryBuilder;
21
use Doctrine\ORM\Tools\Pagination\Paginator as RelationalPaginator;
22
use Jgut\Doctrine\Repository\EventsTrait;
23
use Jgut\Doctrine\Repository\PaginatorTrait;
24
use Jgut\Doctrine\Repository\Repository;
25
use Jgut\Doctrine\Repository\RepositoryTrait;
26
use Rb\Specification\Doctrine\SpecificationAwareInterface;
27
use Rb\Specification\Doctrine\SpecificationRepositoryTrait;
28
use Zend\Paginator\Paginator;
29
30
/**
31
 * Relational entity repository.
32
 */
33
class RelationalRepository extends EntityRepository implements Repository, SpecificationAwareInterface
34
{
35
    use SpecificationRepositoryTrait;
36
    use RepositoryTrait;
37
    use EventsTrait;
38
    use PaginatorTrait;
39
40
    /**
41
     * Class name.
42
     *
43
     * @var string
44
     */
45
    protected $className;
46
47
    /**
48
     * Class alias.
49
     *
50
     * @var string
51
     */
52
    protected $classAlias;
53
54
    /**
55
     * Get class alias.
56
     *
57
     * @return string
58
     */
59
    protected function getClassAlias(): string
60
    {
61
        if ($this->classAlias === null) {
62
            $this->classAlias = strtoupper($this->getEntityName()[0]);
63
        }
64
65
        return $this->classAlias;
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function getClassName(): string
72
    {
73
        if ($this->className === null) {
74
            $this->className = ClassUtils::getRealClass($this->getEntityName());
75
        }
76
77
        return $this->className;
78
    }
79
80
    /**
81
     * {@inheritdoc}
82
     */
83
    protected function getManager(): EntityManager
84
    {
85
        return $this->getEntityManager();
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     *
91
     * @param array      $criteria
92
     * @param array|null $orderBy
93
     * @param int        $itemsPerPage
94
     *
95
     * @return \Zend\Paginator\Paginator
96
     */
97
    public function findPaginatedBy($criteria, array $orderBy = [], int $itemsPerPage = 10): Paginator
98
    {
99
        $queryBuilder = $this->getQueryBuilderFromCriteria($criteria, $orderBy);
100
101
        return $this->paginate($queryBuilder->getQuery(), $itemsPerPage);
102
    }
103
104
    /**
105
     * Get query builder from criteria array.
106
     *
107
     * @param array $criteria
108
     * @param array $orderBy
109
     *
110
     * @return QueryBuilder
111
     */
112
    protected function getQueryBuilderFromCriteria(array $criteria, array $orderBy = []): QueryBuilder
113
    {
114
        $entityAlias = $this->getClassAlias();
115
        $queryBuilder = $this->createQueryBuilder($entityAlias);
116
117
        foreach ($criteria as $field => $value) {
118
            if (is_null($value)) {
119
                $queryBuilder->andWhere(sprintf('%s.%s IS NULL', $entityAlias, $field));
120
            } else {
121
                $parameter = sprintf('%s_%s', $field, substr(sha1($field), 0, 5));
122
123
                if (is_array($value)) {
124
                    $queryBuilder->andWhere(sprintf('%s.%s IN (:%s)', $entityAlias, $field, $parameter));
125
                } else {
126
                    $queryBuilder->andWhere(sprintf('%s.%s = :%s', $entityAlias, $field, $parameter));
127
                }
128
129
                $queryBuilder->setParameter($parameter, $value);
130
            }
131
        }
132
133
        if (is_array($orderBy)) {
134
            $entityAlias = count($queryBuilder->getRootAliases())
135
                ? $queryBuilder->getRootAliases()[0]
136
                : $this->getClassAlias();
137
138
            foreach ($orderBy as $field => $order) {
139
                $queryBuilder->addOrderBy($entityAlias . '.' . $field, $order);
140
            }
141
        }
142
143
        return $queryBuilder;
144
    }
145
146
    /**
147
     * Paginate query.
148
     *
149
     * @param Query $query
150
     * @param int   $itemsPerPage
151
     *
152
     * @return Paginator
153
     */
154
    protected function paginate(Query $query, int $itemsPerPage = 10): Paginator
155
    {
156
        return $this->getPaginator(new RelationalPaginatorAdapter(new RelationalPaginator($query)), $itemsPerPage);
157
    }
158
159
    /**
160
     * {@inheritdoc}
161
     *
162
     * @param array|QueryBuilder $criteria
163
     *
164
     * @return int
165
     */
166
    public function countBy($criteria): int
167
    {
168
        return $this->getEntityManager()->getUnitOfWork()->getEntityPersister($this->getEntityName())->count($criteria);
169
    }
170
}
171