QueryBuilder   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 152
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 23
lcom 1
cbo 3
dl 0
loc 152
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
B whereCriteria() 0 41 9
B autoJoinOrderBy() 0 35 6
A getIterator() 0 4 1
B autoJoin() 0 37 7
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\Query\Expr;
15
use Kdyby;
16
use Nette;
17
18
19
20
/**
21
 * @author Filip Procházka <[email protected]>
22
 *
23
 * @method \Kdyby\Doctrine\QueryBuilder select(array|string $select = null)
24
 * @method \Kdyby\Doctrine\QueryBuilder addSelect(array|string $select = null)
25
 * @method \Kdyby\Doctrine\QueryBuilder from($from, $alias, $indexBy = null)
26
 * @method \Kdyby\Doctrine\QueryBuilder setMaxResults(int|NULL $maxResults)
27
 * @method \Kdyby\Doctrine\QueryBuilder setFirstResult(int|NULL $maxResults)
28
 * @method \Kdyby\Doctrine\QueryBuilder resetDQLPart(string $part)
29
 */
30
class QueryBuilder extends Doctrine\ORM\QueryBuilder implements \IteratorAggregate
31
{
32
33
	use \Kdyby\StrictObjects\Scream;
34
35
	/**
36
	 * @var array
37
	 */
38
	private $criteriaJoins = [];
39
40
41
42
	/**
43
	 * @param array $criteria
44
	 * @return QueryBuilder
45
	 */
46
	public function whereCriteria(array $criteria)
47
	{
48
		foreach ($criteria as $key => $val) {
49
			$alias = $this->autoJoin($key);
50
51
			$operator = '=';
52
			if (preg_match('~(?P<key>[^\\s]+)\\s+(?P<operator>.+)\\s*~', $key, $m)) {
53
				$key = $m['key'];
54
				$operator = strtr(strtolower($m['operator']), [
55
					'neq' => '!=',
56
					'eq' => '=',
57
					'lt' => '<',
58
					'lte' => '<=',
59
					'gt' => '>',
60
					'gte' => '>=',
61
				]);
62
			}
63
64
			$not = substr($operator, 0, 1) === '!';
65
			if (substr($operator, 0, 3) === 'not') {
66
				$operator = substr($operator, 4);
67
				$not = TRUE;
68
			}
69
70
			$paramName = 'param_' . (count($this->getParameters()) + 1);
71
72
			if (is_array($val)) {
73
				$this->andWhere("$alias.$key " . ($not ? 'NOT ' : '') . "IN (:$paramName)");
74
				$this->setParameter($paramName, $val, is_integer(reset($val)) ? Connection::PARAM_INT_ARRAY : Connection::PARAM_STR_ARRAY);
75
76
			} elseif ($val === NULL) {
77
				$this->andWhere("$alias.$key IS " . ($not ? 'NOT ' : '') . 'NULL');
78
79
			} else {
80
				$this->andWhere(sprintf('%s.%s %s :%s', $alias, $key, strtoupper($operator), $paramName));
81
				$this->setParameter($paramName, $val);
82
			}
83
		}
84
85
		return $this;
86
	}
87
88
89
90
	/**
91
	 * @internal
92
	 * @param string|array $sort
93
	 * @param string $order
94
	 * @return Doctrine\ORM\QueryBuilder
95
	 */
96
	public function autoJoinOrderBy($sort, $order = NULL)
97
	{
98
		if (is_array($sort)) {
99
			foreach (func_get_arg(0) as $sort => $order) {
100
				if (!is_string($sort)) {
101
					$sort = $order;
102
					$order = NULL;
103
				}
104
				$this->autoJoinOrderBy($sort, $order);
105
			}
106
107
			return $this;
108
		}
109
110
		if (is_string($sort)) {
111
			$reg = '~[^()]+(?=\))~';
112
			if (preg_match($reg, $sort, $matches)) {
113
				$sortMix = $sort;
114
				$sort = $matches[0];
115
				$alias = $this->autoJoin($sort, 'leftJoin');
116
				$hiddenAlias = $alias . $sort . count($this->getDQLPart('orderBy'));
117
118
				$this->addSelect(preg_replace($reg, $alias . '.' . $sort, $sortMix) . ' as HIDDEN ' . $hiddenAlias);
119
				$rootAliases = $this->getRootAliases();
120
				$this->addGroupBy(reset($rootAliases) . '.id');
121
				$sort = $hiddenAlias;
122
123
			} else {
124
				$alias = $this->autoJoin($sort);
125
				$sort = $alias . '.' . $sort;
126
			}
127
		}
128
129
		return $this->addOrderBy($sort, $order);
130
	}
131
132
133
	/**
134
	 * @return \Doctrine\ORM\Internal\Hydration\IterableResult|\Traversable
135
	 */
136
	public function getIterator()
137
	{
138
		return $this->getQuery()->iterate();
139
	}
140
141
142
143
	private function autoJoin(&$key, $methodJoin = "innerJoin")
144
	{
145
		$rootAliases = $this->getRootAliases();
146
		$alias = reset($rootAliases);
147
148
		if (($i = strpos($key, '.')) === FALSE || !in_array(substr($key, 0, $i), $rootAliases)) {
149
			// there is no root alias to join from, assume first root alias
150
			$key = $alias . '.' . $key;
151
		}
152
153
		while (preg_match('~([^\\.]+)\\.(.+)~', $key, $m)) {
154
			$key = $m[2];
155
			$property = $m[1];
156
157
			if (in_array($property, $rootAliases)) {
158
				$alias = $property;
159
				continue;
160
			}
161
162
			if (isset($this->criteriaJoins[$alias][$property])) {
163
				$alias = $this->criteriaJoins[$alias][$property];
164
				continue;
165
			}
166
167
			$j = 0;
168
			do {
169
				$joinAs = substr($property, 0, 1) . (string) $j++;
170
			} while (isset($this->criteriaJoins[$joinAs]));
171
			$this->criteriaJoins[$joinAs] = [];
172
173
			$this->{$methodJoin}("$alias.$property", $joinAs);
174
			$this->criteriaJoins[$alias][$property] = $joinAs;
175
			$alias = $joinAs;
176
		}
177
178
		return $alias;
179
	}
180
181
}
182