Failed Conditions
Push — master ( ee4e26...e98654 )
by Marco
13:06
created

EntityRepository::getEntityName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ORM;
6
7
use Doctrine\Common\Collections\Criteria;
8
use Doctrine\Common\Collections\Selectable;
9
use Doctrine\Common\Persistence\ObjectRepository;
10
use Doctrine\Common\Util\Inflector;
11
use Doctrine\ORM\Query\ResultSetMappingBuilder;
12
13
/**
14
 * An EntityRepository serves as a repository for entities with generic as well as
15
 * business specific methods for retrieving entities.
16
 *
17
 * This class is designed for inheritance and users can subclass this class to
18
 * write their own repositories with business-specific methods to locate entities.
19
 */
20
class EntityRepository implements ObjectRepository, Selectable
21
{
22
    /**
23
     * @var string
24
     */
25
    protected $entityName;
26
27
    /**
28
     * @var EntityManagerInterface
29
     */
30
    protected $em;
31
32
    /**
33
     * @var \Doctrine\ORM\Mapping\ClassMetadata
34
     */
35
    protected $class;
36
37
    /**
38
     * Initializes a new <tt>EntityRepository</tt>.
39
     *
40
     * @param EntityManagerInterface $em    The EntityManager to use.
41
     * @param Mapping\ClassMetadata  $class The class descriptor.
42
     */
43 146
    public function __construct(EntityManagerInterface $em, Mapping\ClassMetadata $class)
44
    {
45 146
        $this->entityName = $class->getClassName();
46 146
        $this->em         = $em;
47 146
        $this->class      = $class;
48 146
    }
49
50
    /**
51
     * Creates a new QueryBuilder instance that is prepopulated for this entity name.
52
     *
53
     * @param string $alias
54
     * @param string $indexBy The index for the from.
55
     *
56
     * @return QueryBuilder
57
     */
58 8
    public function createQueryBuilder($alias, $indexBy = null)
59
    {
60 8
        return $this->em->createQueryBuilder()
61 8
            ->select($alias)
62 8
            ->from($this->entityName, $alias, $indexBy);
63
    }
64
65
    /**
66
     * Creates a new result set mapping builder for this entity.
67
     *
68
     * The column naming strategy is "INCREMENT".
69
     *
70
     * @param string $alias
71
     *
72
     * @return ResultSetMappingBuilder
73
     */
74 1
    public function createResultSetMappingBuilder($alias)
75
    {
76 1
        $rsm = new ResultSetMappingBuilder($this->em, ResultSetMappingBuilder::COLUMN_RENAMING_INCREMENT);
77 1
        $rsm->addRootEntityFromClassMetadata($this->entityName, $alias);
78
79 1
        return $rsm;
80
    }
81
82
    /**
83
     * Creates a native SQL query.
84
     *
85
     * @param string $queryName
86
     *
87
     * @return NativeQuery
88
     */
89 9
    public function createNativeNamedQuery($queryName)
90
    {
91 9
        $queryMapping = $this->class->getNamedNativeQuery($queryName);
92 9
        $rsm          = new Query\ResultSetMappingBuilder($this->em);
93
94 9
        $rsm->addNamedNativeQueryMapping($this->class, $queryMapping);
95
96 9
        return $this->em->createNativeQuery($queryMapping['query'], $rsm);
97
    }
98
99
    /**
100
     * Clears the repository, causing all managed entities to become detached.
101
     */
102
    public function clear()
103
    {
104
        $this->em->clear($this->class->getRootClassName());
105
    }
106
107
    /**
108
     * Finds an entity by its primary key / identifier.
109
     *
110
     * @param mixed    $id          The identifier.
111
     * @param int|null $lockMode    One of the \Doctrine\DBAL\LockMode::* constants
112
     *                              or NULL if no specific lock mode should be used
113
     *                              during the search.
114
     * @param int|null $lockVersion The lock version.
115
     *
116
     * @return object|null The entity instance or NULL if the entity can not be found.
117
     */
118 15
    public function find($id, $lockMode = null, $lockVersion = null)
119
    {
120 15
        return $this->em->find($this->entityName, $id, $lockMode, $lockVersion);
121
    }
122
123
    /**
124
     * Finds all entities in the repository.
125
     *
126
     * @return object[] The entities.
127
     */
128 33
    public function findAll()
129
    {
130 33
        return $this->findBy([]);
131
    }
132
133
    /**
134
     * Finds entities by a set of criteria.
135
     *
136
     * @param mixed[]  $criteria
137
     * @param mixed[]  $orderBy
138
     * @param int|null $limit
139
     * @param int|null $offset
140
     *
141
     * @return object[] The objects.
142
     *
143
     * @todo guilhermeblanco Change orderBy to use a blank array by default (requires Common\Persistence change).
144
     */
145 64
    public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null)
146
    {
147 64
        $persister = $this->em->getUnitOfWork()->getEntityPersister($this->entityName);
148
149 64
        return $persister->loadAll($criteria, $orderBy !== null ? $orderBy : [], $limit, $offset);
150
    }
151
152
    /**
153
     * Finds a single entity by a set of criteria.
154
     *
155
     * @param mixed[] $criteria
156
     * @param mixed[] $orderBy
157
     *
158
     * @return object|null The entity instance or NULL if the entity can not be found.
159
     */
160 20
    public function findOneBy(array $criteria, array $orderBy = [])
161
    {
162 20
        $persister = $this->em->getUnitOfWork()->getEntityPersister($this->entityName);
163
164 20
        return $persister->load($criteria, null, null, [], null, 1, $orderBy);
165
    }
166
167
    /**
168
     * Counts entities by a set of criteria.
169
     *
170
     * @todo Add this method to `ObjectRepository` interface in the next major release
171
     *
172
     * @param Criteria[] $criteria
173
     *
174
     * @return int The cardinality of the objects that match the given criteria.
175
     */
176 2
    public function count(array $criteria)
177
    {
178 2
        return $this->em->getUnitOfWork()->getEntityPersister($this->entityName)->count($criteria);
179
    }
180
181
    /**
182
     * Adds support for magic method calls.
183
     *
184
     * @param string  $method
185
     * @param mixed[] $arguments
186
     *
187
     * @return mixed The returned value from the resolved method.
188
     *
189
     * @throws ORMException
190
     * @throws \BadMethodCallException If the method called is invalid.
191
     */
192 13
    public function __call($method, $arguments)
193
    {
194 13
        if (strpos($method, 'findBy') === 0) {
195 8
            return $this->resolveMagicCall('findBy', substr($method, 6), $arguments);
196
        }
197
198 5
        if (strpos($method, 'findOneBy') === 0) {
199 3
            return $this->resolveMagicCall('findOneBy', substr($method, 9), $arguments);
200
        }
201
202 2
        if (strpos($method, 'countBy') === 0) {
203 1
            return $this->resolveMagicCall('count', substr($method, 7), $arguments);
204
        }
205
206 1
        throw new \BadMethodCallException(
207 1
            sprintf(
208 1
                "Undefined method '%s'. The method name must start with either findBy, findOneBy or countBy!",
209 1
                $method
210
            )
211
        );
212
    }
213
214
    /**
215
     * @return string
216
     */
217
    protected function getEntityName()
218
    {
219
        return $this->entityName;
220
    }
221
222
    /**
223
     * @return string
224
     */
225
    public function getClassName()
226
    {
227
        return $this->getEntityName();
228
    }
229
230
    /**
231
     * @return EntityManagerInterface
232
     */
233
    protected function getEntityManager()
234
    {
235
        return $this->em;
236
    }
237
238
    /**
239
     * @return Mapping\ClassMetadata
240
     */
241
    protected function getClassMetadata()
242
    {
243
        return $this->class;
244
    }
245
246
    /**
247
     * Select all elements from a selectable that match the expression and
248
     * return a new collection containing these elements.
249
     *
250
     * @return \Doctrine\Common\Collections\Collection|object[]
251
     */
252 26
    public function matching(Criteria $criteria)
253
    {
254 26
        $persister = $this->em->getUnitOfWork()->getEntityPersister($this->entityName);
255
256 26
        return new LazyCriteriaCollection($persister, $criteria);
257
    }
258
259
    /**
260
     * Resolves a magic method call to the proper existent method at `EntityRepository`.
261
     *
262
     * @param string  $method    The method to call
263
     * @param string  $by        The property name used as condition
264
     * @param mixed[] $arguments The arguments to pass at method call
265
     *
266
     * @throws ORMException If the method called is invalid or the requested field/association does not exist.
267
     *
268
     * @return mixed
269
     */
270 12
    private function resolveMagicCall($method, $by, array $arguments)
271
    {
272 12
        if (! $arguments) {
273 1
            throw ORMException::findByRequiresParameter($method . $by);
274
        }
275
276 11
        $fieldName = lcfirst(Inflector::classify($by));
277
278 11
        if ($this->class->getProperty($fieldName) === null) {
279 1
            throw ORMException::invalidMagicCall($this->entityName, $fieldName, $method . $by);
280
        }
281
282 10
        return $this->{$method}([$fieldName => $arguments[0]], ...array_slice($arguments, 1));
283
    }
284
}
285