Completed
Push — master ( c1951e...846a6f )
by Filip
07:02
created

EntityRepository::__call()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 4
nc 2
nop 2
1
<?php
2
3
/**
4
 * This file is part of the Kdyby (http://www.kdyby.org)
5
 *
6
 * Copyright (c) 2008 Filip Procházka ([email protected])
7
 *
8
 * For the full copyright and license information, please view the file license.txt that was distributed with this source code.
9
 */
10
11
namespace Kdyby\Doctrine;
12
13
use Doctrine;
14
use Doctrine\ORM\AbstractQuery;
15
use Doctrine\ORM\NoResultException;
16
use Doctrine\ORM\NonUniqueResultException;
17
use Kdyby;
18
use Kdyby\Persistence;
19
use Nette;
20
21
22
23
/**
24
 * This class is an extension to EntityRepository and should help you with prototyping.
25
 * The first and only rule with EntityRepository is not to ever inherit them, ever.
26
 *
27
 * The only valid reason to inherit EntityRepository is to add more common methods to all EntityRepositories in application,
28
 * when you're creating your own framework (but do we really need to go any deeper than this?).
29
 *
30
 * @author Filip Procházka <[email protected]>
31
 */
32
class EntityRepository extends Doctrine\ORM\EntityRepository implements Persistence\QueryExecutor, Persistence\Queryable //, Persistence\ObjectFactory
33
{
34
35
	use \Kdyby\StrictObjects\Scream;
36
37
	public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
38
	{
39
		if ($this->criteriaRequiresDql($criteria) === FALSE && $this->criteriaRequiresDql((array) $orderBy) === FALSE) {
40
			return parent::findBy($criteria, $orderBy, $limit, $offset);
41
		}
42
43
		$qb = $this->createQueryBuilder('e')
44
			->whereCriteria($criteria)
45
			->autoJoinOrderBy((array) $orderBy);
46
47
		return $qb->getQuery()
48
			->setMaxResults($limit)
49
			->setFirstResult($offset)
50
			->getResult();
51
	}
52
53
54
55
	public function findOneBy(array $criteria, array $orderBy = null)
56
	{
57
		if ($this->criteriaRequiresDql($criteria) === FALSE && $this->criteriaRequiresDql((array) $orderBy) === FALSE) {
58
			return parent::findOneBy($criteria, $orderBy);
59
		}
60
61
		$qb = $this->createQueryBuilder('e')
62
			->whereCriteria($criteria)
63
			->autoJoinOrderBy((array) $orderBy);
64
65
		try {
66
			return $qb->setMaxResults(1)
67
				->getQuery()->getSingleResult();
68
69
		} catch (NoResultException $e) {
70
			return NULL;
71
		}
72
	}
73
74
75
76
	/**
77
	 * @param array $criteria
78
	 * @return int
79
	 */
80
	public function countBy(array $criteria = [])
81
	{
82
		return (int) $this->createQueryBuilder('e')
83
			->whereCriteria($criteria)
84
			->select('COUNT(e)')
85
			->getQuery()->getSingleScalarResult();
86
	}
87
88
89
90
	/**
91
	 * @param array $criteria
92
	 * @return bool
93
	 */
94
	private function criteriaRequiresDql(array $criteria)
95
	{
96
		foreach ($criteria as $key => $val) {
97
			if (preg_match('~[\\?\\s\\.]~', $key)) {
98
				return TRUE;
99
			}
100
		}
101
102
		return FALSE;
103
	}
104
105
106
107
	/**
108
	 * Fetches all records like $key => $value pairs
109
	 *
110
	 * @param array $criteria parameter can be skipped
111
	 * @param string $value mandatory
112
	 * @param array|string $orderBy parameter can be skipped
113
	 * @param string $key optional
114
	 *
115
	 * @throws QueryException
116
	 * @return array
117
	 */
118
	public function findPairs($criteria, $value = NULL, $orderBy = [], $key = NULL)
119
	{
120
		if (!is_array($criteria)) {
121
			$key = $orderBy;
122
			$orderBy = $value;
123
			$value = $criteria;
124
			$criteria = [];
125
		}
126
127
		if (!is_array($orderBy)) {
128
			$key = $orderBy;
129
			$orderBy = [];
130
		}
131
132
		if (empty($key)) {
133
			$key = $this->getClassMetadata()->getSingleIdentifierFieldName();
134
		}
135
136
		/** @var \Kdyby\Doctrine\QueryBuilder $qb */
137
		$qb = $this->createQueryBuilder('e')
138
			->whereCriteria($criteria)
139
			->select(["e.$value", "e.$key"])
140
			->resetDQLPart('from')->from($this->getEntityName(), 'e', 'e.' . $key);
141
		$query = $qb->autoJoinOrderBy($orderBy)->getQuery();
142
143
		try {
144
			return array_map(function ($row) {
145
				return reset($row);
146
			}, $query->getResult(AbstractQuery::HYDRATE_ARRAY));
147
148
		} catch (\Exception $e) {
149
			throw $this->handleException($e, $query);
150
		}
151
	}
152
153
154
155
	/**
156
	 * Fetches all records and returns an associative array indexed by key
157
	 *
158
	 * @param array $criteria
159
	 * @param string $key
160
	 *
161
	 * @throws \Exception|QueryException
162
	 * @return array
163
	 */
164
	public function findAssoc($criteria, $key = NULL)
165
	{
166
		if (!is_array($criteria)) {
167
			$key = $criteria;
168
			$criteria = [];
169
		}
170
171
		$query = $this->createQueryBuilder('e')
172
			->whereCriteria($criteria)
173
			->resetDQLPart('from')->from($this->getEntityName(), 'e', 'e.' . $key)
174
			->getQuery();
175
176
		try {
177
			return $query->getResult();
178
179
		} catch (\Exception $e) {
180
			throw $this->handleException($e, $query);
181
		}
182
	}
183
184
185
186
	/**
187
	 * @param string $sql
188
	 * @param Doctrine\ORM\Query\ResultSetMapping $rsm
189
	 * @return Doctrine\ORM\NativeQuery
190
	 */
191
	public function createNativeQuery($sql, Doctrine\ORM\Query\ResultSetMapping $rsm)
192
	{
193
		return $this->getEntityManager()->createNativeQuery($sql, $rsm);
194
	}
195
196
197
198
	/**
199
	 * @param string $alias
200
	 * @param string $indexBy The index for the from.
201
	 * @return \Kdyby\Doctrine\QueryBuilder
202
	 */
203
	public function createQueryBuilder($alias = NULL, $indexBy = NULL)
204
	{
205
		$qb = $this->getEntityManager()->createQueryBuilder();
206
207
		if ($alias !== NULL) {
208
			$qb->select($alias)->from($this->getEntityName(), $alias, $indexBy);
209
		}
210
211
		return $qb;
212
	}
213
214
215
216
	/**
217
	 * @param string $dql
218
	 *
219
	 * @return \Doctrine\ORM\Query
220
	 */
221
	public function createQuery($dql = NULL)
222
	{
223
		$dql = implode(' ', func_get_args());
224
225
		return $this->getEntityManager()->createQuery($dql);
226
	}
227
228
229
230
	/**
231
	 * @param \Kdyby\Persistence\Query|\Kdyby\Doctrine\QueryObject $queryObject
232
	 * @param int $hydrationMode
233
	 * @throws QueryException
234
	 * @return array|\Kdyby\Doctrine\ResultSet
235
	 */
236
	public function fetch(Persistence\Query $queryObject, $hydrationMode = AbstractQuery::HYDRATE_OBJECT)
237
	{
238
		try {
239
			return $queryObject->fetch($this, $hydrationMode);
0 ignored issues
show
Unused Code introduced by
The call to Query::fetch() has too many arguments starting with $hydrationMode.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
240
241
		} catch (\Exception $e) {
242
			throw $this->handleQueryException($e, $queryObject);
243
		}
244
	}
245
246
247
248
	/**
249
	 * @param \Kdyby\Persistence\Query|\Kdyby\Doctrine\QueryObject $queryObject
250
	 *
251
	 * @throws InvalidStateException
252
	 * @throws QueryException
253
	 * @return object
254
	 */
255
	public function fetchOne(Persistence\Query $queryObject)
256
	{
257
		try {
258
			return $queryObject->fetchOne($this);
259
260
		} catch (NoResultException $e) {
261
			return NULL;
262
263
		} catch (NonUniqueResultException $e) { // this should never happen!
264
			throw new InvalidStateException("You have to setup your query calling ->setMaxResult(1).", 0, $e);
265
266
		} catch (\Exception $e) {
267
			throw $this->handleQueryException($e, $queryObject);
268
		}
269
	}
270
271
272
273
	/**
274
	 * @param integer|array $id
275
	 * @return \Doctrine\ORM\Proxy\Proxy
276
	 */
277
	public function getReference($id)
278
	{
279
		return $this->getEntityManager()->getReference($this->_entityName, $id);
280
	}
281
282
283
284
	/**
285
	 * @param \Exception $e
286
	 * @param \Kdyby\Persistence\Query $queryObject
287
	 * @return \Kdyby\Doctrine\QueryException
288
	 */
289
	private function handleQueryException(\Exception $e, Persistence\Query $queryObject)
290
	{
291
		$lastQuery = $queryObject instanceof QueryObject ? $queryObject->getLastQuery() : NULL;
292
293
		return new QueryException($e, $lastQuery, '[' . get_class($queryObject) . '] ' . $e->getMessage());
294
	}
295
296
297
298
	/**
299
	 * @param \Exception $e
300
	 * @param \Doctrine\ORM\Query $query
301
	 * @param string $message
302
	 * @return \Exception|\Kdyby\Doctrine\QueryException
303
	 */
304
	private function handleException(\Exception $e, Doctrine\ORM\Query $query = NULL, $message = NULL)
305
	{
306
		if ($e instanceof Doctrine\ORM\Query\QueryException) {
307
			return new QueryException($e, $query, $message);
308
		}
309
310
		return $e;
311
	}
312
313
314
315
	/**
316
	 * @return \Kdyby\Doctrine\Mapping\ClassMetadata
317
	 */
318
	public function getClassMetadata()
319
	{
320
		/** @var \Kdyby\Doctrine\Mapping\ClassMetadata $classMetadata */
321
		$classMetadata = parent::getClassMetadata();
322
		return $classMetadata;
323
	}
324
325
326
327
	/**
328
	 * @return \Kdyby\Doctrine\EntityManager
329
	 */
330
	public function getEntityManager()
331
	{
332
		/** @var \Kdyby\Doctrine\EntityManager $entityManager */
333
		$entityManager = parent::getEntityManager();
334
		return $entityManager;
335
	}
336
337
338
339
	/**
340
	 * @param string $relation
341
	 * @return \Kdyby\Doctrine\EntityRepository
342
	 */
343
	public function related($relation)
344
	{
345
		$meta = $this->getClassMetadata();
346
		$targetClass = $meta->getAssociationTargetClass($relation);
347
348
		/** @var \Kdyby\Doctrine\EntityRepository $entityRepository */
349
		$entityRepository = $this->getEntityManager()->getRepository($targetClass);
350
		return $entityRepository;
351
	}
352
353
}
354