Completed
Push — master ( 5d896f...588e78 )
by Peter
10:12 queued 13s
created

EntitySpecificationRepositoryTrait   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 207
Duplicated Lines 100 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
dl 207
loc 207
c 0
b 0
f 0
wmc 28
lcom 1
cbo 7
rs 10

11 Methods

Rating   Name   Duplication   Size   Complexity  
A match() 6 6 1
A matchSingleResult() 12 12 3
A matchOneOrNullResult() 8 8 2
A matchSingleScalarResult() 10 10 2
A matchScalarResult() 6 6 1
A getQuery() 10 10 2
A getQueryBuilder() 7 7 2
A iterate() 6 6 2
A setAlias() 6 6 1
A getAlias() 4 4 1
B applySpecification() 26 26 11

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/**
4
 * This file is part of the Happyr Doctrine Specification package.
5
 *
6
 * (c) Tobias Nyholm <[email protected]>
7
 *     Kacper Gunia <[email protected]>
8
 *     Peter Gribanov <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Happyr\DoctrineSpecification\Repository;
15
16
use Doctrine\ORM\NonUniqueResultException as DoctrineNonUniqueResultException;
17
use Doctrine\ORM\NoResultException as DoctrineNoResultException;
18
use Doctrine\ORM\Query;
19
use Doctrine\ORM\QueryBuilder;
20
use Happyr\DoctrineSpecification\Exception\NonUniqueResultException;
21
use Happyr\DoctrineSpecification\Exception\NoResultException;
22
use Happyr\DoctrineSpecification\Filter\Filter;
23
use Happyr\DoctrineSpecification\Query\QueryModifier;
24
use Happyr\DoctrineSpecification\Result\ResultModifier;
25
26
/**
27
 * This trait should be used by a class extending \Doctrine\ORM\EntityRepository.
28
 */
29 View Code Duplication
trait EntitySpecificationRepositoryTrait
0 ignored issues
show
Duplication introduced by
This class seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
30
{
31
    /**
32
     * @var string alias
33
     */
34
    private $alias = 'e';
35
36
    /**
37
     * Get results when you match with a Specification.
38
     *
39
     * @param Filter|QueryModifier $specification
40
     * @param ResultModifier|null  $modifier
41
     *
42
     * @return mixed[]
43
     */
44
    public function match($specification, ResultModifier $modifier = null)
45
    {
46
        $query = $this->getQuery($specification, $modifier);
47
48
        return $query->execute();
49
    }
50
51
    /**
52
     * Get single result when you match with a Specification.
53
     *
54
     * @param Filter|QueryModifier $specification
55
     * @param ResultModifier|null  $modifier
56
     *
57
     * @throw Exception\NonUniqueException  If more than one result is found
58
     * @throw Exception\NoResultException   If no results found
59
     *
60
     * @return mixed
61
     */
62
    public function matchSingleResult($specification, ResultModifier $modifier = null)
63
    {
64
        $query = $this->getQuery($specification, $modifier);
65
66
        try {
67
            return $query->getSingleResult();
68
        } catch (DoctrineNonUniqueResultException $e) {
69
            throw new NonUniqueResultException($e->getMessage(), $e->getCode(), $e);
70
        } catch (DoctrineNoResultException $e) {
71
            throw new NoResultException($e->getMessage(), $e->getCode(), $e);
72
        }
73
    }
74
75
    /**
76
     * Get single result or null when you match with a Specification.
77
     *
78
     * @param Filter|QueryModifier $specification
79
     * @param ResultModifier|null  $modifier
80
     *
81
     * @throw Exception\NonUniqueException  If more than one result is found
82
     *
83
     * @return mixed|null
84
     */
85
    public function matchOneOrNullResult($specification, ResultModifier $modifier = null)
86
    {
87
        try {
88
            return $this->matchSingleResult($specification, $modifier);
89
        } catch (NoResultException $e) {
90
            return null;
91
        }
92
    }
93
94
    /**
95
     * Get single scalar result when you match with a Specification.
96
     *
97
     * @param Filter|QueryModifier $specification
98
     * @param ResultModifier|null  $modifier
99
     *
100
     * @throw Exception\NonUniqueException  If more than one result is found
101
     * @throw Exception\NoResultException   If no results found
102
     *
103
     * @return mixed
104
     */
105
    public function matchSingleScalarResult($specification, ResultModifier $modifier = null)
106
    {
107
        $query = $this->getQuery($specification, $modifier);
108
109
        try {
110
            return $query->getSingleScalarResult();
111
        } catch (DoctrineNonUniqueResultException $e) {
112
            throw new NonUniqueResultException($e->getMessage(), $e->getCode(), $e);
113
        }
114
    }
115
116
    /**
117
     * Get scalar result when you match with a Specification.
118
     *
119
     * @param Filter|QueryModifier $specification
120
     * @param ResultModifier|null  $modifier
121
     *
122
     * @throw Exception\NonUniqueException  If more than one result is found
123
     * @throw Exception\NoResultException   If no results found
124
     *
125
     * @return mixed
126
     */
127
    public function matchScalarResult($specification, ResultModifier $modifier = null)
128
    {
129
        $query = $this->getQuery($specification, $modifier);
130
131
        return $query->getScalarResult();
132
    }
133
134
    /**
135
     * Prepare a Query with a Specification.
136
     *
137
     * @param Filter|QueryModifier $specification
138
     * @param ResultModifier|null  $modifier
139
     *
140
     * @return Query
141
     */
142
    public function getQuery($specification, ResultModifier $modifier = null)
143
    {
144
        $query = $this->getQueryBuilder($specification)->getQuery();
145
146
        if (null !== $modifier) {
147
            $modifier->modify($query);
148
        }
149
150
        return $query;
151
    }
152
153
    /**
154
     * @param Filter|QueryModifier $specification
155
     * @param string|null          $alias
156
     *
157
     * @return QueryBuilder
158
     */
159
    public function getQueryBuilder($specification, $alias = null)
160
    {
161
        $qb = $this->createQueryBuilder($alias ?: $this->getAlias());
0 ignored issues
show
Bug introduced by
It seems like createQueryBuilder() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
162
        $this->applySpecification($qb, $specification, $alias);
163
164
        return $qb;
165
    }
166
167
    /**
168
     * Iterate results when you match with a Specification.
169
     *
170
     * @param Filter|QueryModifier $specification
171
     * @param ResultModifier|null  $modifier
172
     *
173
     * @return \Traversable
174
     */
175
    public function iterate($specification, ResultModifier $modifier = null)
176
    {
177
        foreach ($this->getQuery($specification, $modifier)->iterate() as $row) {
178
            yield current($row);
179
        }
180
    }
181
182
    /**
183
     * @param string $alias
184
     *
185
     * @return $this
186
     */
187
    public function setAlias($alias)
188
    {
189
        $this->alias = $alias;
190
191
        return $this;
192
    }
193
194
    /**
195
     * @return string
196
     */
197
    public function getAlias()
198
    {
199
        return $this->alias;
200
    }
201
202
    /**
203
     * @param QueryBuilder                    $queryBuilder
204
     * @param Filter|QueryModifier|mixed|null $specification
205
     * @param string                          $alias
206
     *
207
     * @throws \InvalidArgumentException
208
     */
209
    protected function applySpecification(QueryBuilder $queryBuilder, $specification = null, $alias = null)
210
    {
211
        if (null === $specification) {
212
            return;
213
        }
214
215
        if (!$specification instanceof QueryModifier && !$specification instanceof Filter) {
216
            throw new \InvalidArgumentException(sprintf(
217
                'Expected argument of type "%s" or "%s", "%s" given.',
218
                QueryModifier::class,
219
                Filter::class,
220
                is_object($specification) ? get_class($specification) : gettype($specification)
221
            ));
222
        }
223
224
        if ($specification instanceof QueryModifier) {
225
            $specification->modify($queryBuilder, $alias ?: $this->getAlias());
226
        }
227
228
        if ($specification instanceof Filter &&
229
            ($filter = $specification->getFilter($queryBuilder, $alias ?: $this->getAlias())) &&
230
            ($filter = trim($filter))
231
        ) {
232
            $queryBuilder->andWhere($filter);
233
        }
234
    }
235
}
236

 

OSZAR »