PluginProbe ʕ •ᴥ•ʔ
MailPoet – Newsletters, Email Marketing, and Automation / 5.36.0
MailPoet – Newsletters, Email Marketing, and Automation v5.36.0
5.36.0 5.35.1 5.35.0 5.34.3 5.34.2 5.34.1 5.34.0 5.33.1 5.33.0 5.32.0 5.31.0 5.30.0 5.29.0 5.28.1 5.28.0 5.27.0 5.26.0 5.26.1 5.25.0 5.24.0 4.43.0 4.43.1 4.44.0 4.44.1 4.45.0 4.46.0 4.47.0 4.48.0 4.48.1 4.48.2 4.49.0 4.49.1 4.5.0 4.5.1 4.5.2 4.50.0 4.50.1 4.51.0 4.51.1 4.51.2 4.52.0 4.53.0 4.54.0 4.55.0 4.56.0 4.57.0 4.58.0 4.58.1 4.58.2 4.6.0 4.6.1 4.6.2 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 5.0.0 5.0.1 5.0.2 5.1.0 5.1.1 5.10.0 5.10.1 5.11.0 5.12.0 5.12.1 5.12.10 5.12.11 5.12.12 5.12.13 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.12.7 5.12.8 5.12.9 5.13.0 5.13.1 5.13.2 5.14.0 5.14.1 5.14.2 5.14.3 5.15.0 5.15.1 5.16.0 5.16.1 5.16.2 5.16.3 5.16.4 5.17.0 5.17.1 5.17.2 5.17.3 5.17.4 5.17.5 5.17.6 5.18.0 5.19.0 5.2.0 5.2.1 5.2.2 5.2.3 5.20.0 5.21.0 5.21.1 5.21.2 5.21.3 5.22.0 5.22.1 5.22.2 5.22.3 5.22.4 5.23.0 5.23.1 5.23.2 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.4.0 5.4.1 5.4.2 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.6.3 5.6.4 5.7.0 5.7.1 5.8.0 5.8.1 5.9.0 3.0.0-beta.15 3.7.1 3.0.0-beta.16 3.7.2 3.0.0-beta.17 3.7.3 3.0.0-beta.18 3.7.4 3.0.0-beta.19 3.7.5 3.0.0-beta.2 3.7.6 3.0.0-beta.20 3.7.8 3.0.0-beta.21 3.70.0 3.0.0-beta.22 3.71.0 3.0.0-beta.23 3.71.1 3.0.0-beta.23.1 3.71.2 3.0.0-beta.23.2 3.71.3 3.0.0-beta.24 3.72.0 3.0.0-beta.25 3.73.0 3.0.0-beta.26 3.73.1 3.0.0-beta.27 3.73.2 3.0.0-beta.28 3.74.0 3.0.0-beta.29 3.74.1 3.0.0-beta.3 3.74.2 3.0.0-beta.30 3.74.3 3.0.0-beta.31 3.75.0 3.0.0-beta.32 3.75.1 3.0.0-beta.33 3.76.0 3.0.0-beta.33.1 3.77.0 3.0.0-beta.34.0.0 3.77.1 3.0.0-beta.36.0.0 3.78.0 3.0.0-beta.36.0.1 3.79.0 3.0.0-beta.36.2.0 3.8 3.0.0-beta.36.3.0 3.8.1 3.0.0-beta.36.3.1 3.8.2 3.0.0-beta.37.0.0 3.8.3 3.0.0-beta.4 3.8.4 3.0.0-beta.5 3.8.5 3.0.0-beta.6 3.8.6 3.0.0-beta.7 3.80.0 3.0.0-beta.7.1 3.81.0 3.0.0-beta.8 3.82.0 3.0.0-beta.9 3.83.0 3.0.0-rc.1.0.0 3.84.0 3.0.0-rc.1.0.1 3.84.1 3.0.0-rc.1.0.2 3.85.0 3.0.0-rc.1.0.3 3.85.1 3.0.0-rc.1.0.4 3.86.0 3.0.0-rc.2.0.0 3.87.0 3.0.0-rc.2.0.1 3.87.1 3.0.0-rc.2.0.2 3.87.2 3.0.0-rc.2.0.3 3.88.0 3.0.1 3.88.1 3.0.2 3.88.2 3.0.3 3.89.0 3.0.4 3.89.1 3.0.5 3.89.2 3.0.6 3.89.3 3.0.7 3.89.4 3.0.8 3.9.0 3.0.9 3.9.1 3.1.0 3.90.0 3.10 3.90.1 3.10.1 3.90.2 3.100.0 3.91.0 3.100.1 3.91.1 3.100.2 3.92.0 3.101.0 3.92.1 3.101.1 3.93.0 3.102.0 3.93.1 3.102.1 3.94.0 3.103.0 3.95.0 3.103.1 3.95.1 3.11.0 3.96.0 3.11.1 3.96.1 3.11.2 3.97.0 3.11.3 3.98.0 3.11.4 3.98.1 3.11.5 3.99.0 3.12.0 3.99.1 3.12.1 4.0.0 3.13.0 4.0.1 3.14.0 4.1.0 3.14.1 4.1.1 3.15.0 4.10.0 3.16.0 4.11.0 3.16.1 4.11.1 3.16.2 4.12.0 3.16.3 4.12.1 3.17.0 4.12.2 3.17.1 4.13.0 3.17.2 4.14.0 3.18.0 4.15.0 3.18.1 4.16.0 3.18.2 4.17.0 3.19.0 4.17.1 3.19.1 4.18.0 3.19.2 4.18.1 3.19.3 4.19.0 3.2.0 4.2.0 3.2.1 4.20.0 3.2.2 4.20.1 3.2.3 4.20.2 3.2.4 4.21.0 3.2.5 4.22.0 3.20.0 4.22.1 3.21.0 4.22.2 3.21.1 4.23.0 3.22.0 4.24.0 3.23.0 4.25.0 3.23.1 4.26.0 3.23.2 4.26.1 3.24.0 4.27.0 3.25.0 4.28.0 3.25.1 4.29.0 3.26.0 4.3.0 3.26.1 4.3.1 3.27.0 4.30.0 3.28.0 4.31.0 3.29.0 4.31.1 3.3.0 4.32.0 3.3.1 4.33.0 3.3.2 4.34.0 3.3.3 4.35.0 3.3.4 4.35.1 3.3.5 4.36.0 3.3.6 4.37.0 3.30.0 4.38.0 3.31.0 4.39.0 3.31.1 4.4.0 3.32.0 4.40.0 3.32.1 4.41.0 3.32.2 4.41.1 3.33.0 4.41.2 3.34.0 4.41.3 3.34.1 4.42.0 3.34.2 4.42.1 3.34.3 3.34.4 3.35.0 3.35.1 3.35.3 3.35.4 3.36.0 3.37.0 3.37.1 3.37.2 3.37.3 3.38.0 3.38.1 3.39.0 3.39.1 3.39.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.40.0 3.40.1 3.41.0 3.41.1 3.41.2 3.42.0 3.42.1 3.42.2 3.42.3 3.43.0 3.43.1 3.44.0 3.45.0 3.45.1 3.46.0 3.46.1 3.46.10 3.46.11 3.46.12 3.46.13 3.46.14 3.46.2 3.46.3 3.46.4 3.46.5 3.46.6 3.46.7 3.46.8 3.46.9 3.47.0 3.47.1 3.47.10 3.47.11 3.47.2 3.47.3 3.47.5 3.47.6 3.47.7 3.47.9 3.48.0 3.48.1 3.49.0 3.49.1 3.5.0 3.5.1 3.50.0 3.51.0 3.51.1 3.51.2 3.52.0 3.53.0 3.54.0 3.54.1 3.54.2 3.54.3 3.55.0 3.55.1 3.56.0 3.56.1 3.56.2 3.57.0 3.57.1 3.58.0 3.59.0 3.59.1 3.59.2 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.60.0 3.60.1 3.60.10 3.60.11 3.60.12 3.60.2 3.60.3 3.60.4 3.60.6 3.60.7 3.60.8 3.60.9 3.61.0 3.62.0 3.62.1 3.63.0 3.64.0 3.64.1 3.64.2 3.64.3 3.65.0 trunk 3.65.1 3.0.0 3.66.0 3.0.0-beta.1 3.67.0 3.0.0-beta.10 3.67.1 3.0.0-beta.11 3.68.0 3.0.0-beta.12 3.69.0 3.0.0-beta.13 3.69.1 3.0.0-beta.14 3.7.0
mailpoet / vendor-prefixed / doctrine / orm / src / QueryBuilder.php
mailpoet / vendor-prefixed / doctrine / orm / src Last commit date
Cache 9 months ago Decorator 9 months ago Event 9 months ago Exception 9 months ago Id 9 months ago Internal 9 months ago Mapping 9 months ago Persisters 8 months ago Proxy 9 months ago Query 9 months ago Repository 9 months ago Tools 9 months ago Utility 9 months ago AbstractQuery.php 9 months ago Cache.php 9 months ago Configuration.php 9 months ago EntityManager.php 9 months ago EntityManagerInterface.php 9 months ago EntityNotFoundException.php 9 months ago EntityRepository.php 9 months ago Events.php 9 months ago LazyCriteriaCollection.php 9 months ago NativeQuery.php 9 months ago NoResultException.php 9 months ago NonUniqueResultException.php 9 months ago ORMException.php 9 months ago ORMInvalidArgumentException.php 9 months ago ORMSetup.php 9 months ago OptimisticLockException.php 9 months ago PersistentCollection.php 9 months ago PessimisticLockException.php 9 months ago Query.php 9 months ago QueryBuilder.php 9 months ago TransactionRequiredException.php 9 months ago UnexpectedResultException.php 9 months ago UnitOfWork.php 9 months ago Version.php 9 months ago index.php 9 months ago
QueryBuilder.php
605 lines
1 <?php
2 declare (strict_types=1);
3 namespace MailPoetVendor\Doctrine\ORM;
4 if (!defined('ABSPATH')) exit;
5 use MailPoetVendor\Doctrine\Common\Collections\ArrayCollection;
6 use MailPoetVendor\Doctrine\Common\Collections\Criteria;
7 use MailPoetVendor\Doctrine\Deprecations\Deprecation;
8 use MailPoetVendor\Doctrine\ORM\Internal\CriteriaOrderings;
9 use MailPoetVendor\Doctrine\ORM\Query\Expr;
10 use MailPoetVendor\Doctrine\ORM\Query\Parameter;
11 use MailPoetVendor\Doctrine\ORM\Query\QueryExpressionVisitor;
12 use InvalidArgumentException;
13 use RuntimeException;
14 use function array_keys;
15 use function array_merge;
16 use function array_unshift;
17 use function assert;
18 use function func_get_args;
19 use function func_num_args;
20 use function implode;
21 use function in_array;
22 use function is_array;
23 use function is_numeric;
24 use function is_object;
25 use function is_string;
26 use function key;
27 use function reset;
28 use function sprintf;
29 use function str_starts_with;
30 use function strpos;
31 use function strrpos;
32 use function substr;
33 class QueryBuilder
34 {
35 use CriteriaOrderings;
36 public const SELECT = 0;
37 public const DELETE = 1;
38 public const UPDATE = 2;
39 public const STATE_DIRTY = 0;
40 public const STATE_CLEAN = 1;
41 private $em;
42 private $dqlParts = ['distinct' => \false, 'select' => [], 'from' => [], 'join' => [], 'set' => [], 'where' => null, 'groupBy' => [], 'having' => null, 'orderBy' => []];
43 private $type = self::SELECT;
44 private $state = self::STATE_CLEAN;
45 private $dql;
46 private $parameters;
47 private $firstResult = 0;
48 private $maxResults = null;
49 private $joinRootAliases = [];
50 protected $cacheable = \false;
51 protected $cacheRegion;
52 protected $cacheMode;
53 protected $lifetime = 0;
54 public function __construct(EntityManagerInterface $em)
55 {
56 $this->em = $em;
57 $this->parameters = new ArrayCollection();
58 }
59 public function expr()
60 {
61 return $this->em->getExpressionBuilder();
62 }
63 public function setCacheable($cacheable)
64 {
65 $this->cacheable = (bool) $cacheable;
66 return $this;
67 }
68 public function isCacheable()
69 {
70 return $this->cacheable;
71 }
72 public function setCacheRegion($cacheRegion)
73 {
74 $this->cacheRegion = (string) $cacheRegion;
75 return $this;
76 }
77 public function getCacheRegion()
78 {
79 return $this->cacheRegion;
80 }
81 public function getLifetime()
82 {
83 return $this->lifetime;
84 }
85 public function setLifetime($lifetime)
86 {
87 $this->lifetime = (int) $lifetime;
88 return $this;
89 }
90 public function getCacheMode()
91 {
92 return $this->cacheMode;
93 }
94 public function setCacheMode($cacheMode)
95 {
96 $this->cacheMode = (int) $cacheMode;
97 return $this;
98 }
99 public function getType()
100 {
101 Deprecation::trigger('doctrine/dbal', 'https://github.com/doctrine/orm/pull/9945', 'Relying on the type of the query being built is deprecated.' . ' If necessary, track the type of the query being built outside of the builder.');
102 return $this->type;
103 }
104 public function getEntityManager()
105 {
106 return $this->em;
107 }
108 public function getState()
109 {
110 Deprecation::trigger('doctrine/dbal', 'https://github.com/doctrine/orm/pull/9945', 'Relying on the query builder state is deprecated as it is an internal concern.');
111 return $this->state;
112 }
113 public function getDQL()
114 {
115 // @phpstan-ignore classConstant.deprecated
116 if ($this->dql !== null && $this->state === self::STATE_CLEAN) {
117 return $this->dql;
118 }
119 switch ($this->type) {
120 // @phpstan-ignore classConstant.deprecated
121 case self::DELETE:
122 $dql = $this->getDQLForDelete();
123 break;
124 // @phpstan-ignore classConstant.deprecated
125 case self::UPDATE:
126 $dql = $this->getDQLForUpdate();
127 break;
128 // @phpstan-ignore classConstant.deprecated
129 case self::SELECT:
130 default:
131 $dql = $this->getDQLForSelect();
132 break;
133 }
134 // @phpstan-ignore classConstant.deprecated
135 $this->state = self::STATE_CLEAN;
136 $this->dql = $dql;
137 return $dql;
138 }
139 public function getQuery()
140 {
141 $parameters = clone $this->parameters;
142 $query = $this->em->createQuery($this->getDQL())->setParameters($parameters)->setFirstResult($this->firstResult)->setMaxResults($this->maxResults);
143 if ($this->lifetime) {
144 $query->setLifetime($this->lifetime);
145 }
146 if ($this->cacheMode) {
147 $query->setCacheMode($this->cacheMode);
148 }
149 if ($this->cacheable) {
150 $query->setCacheable($this->cacheable);
151 }
152 if ($this->cacheRegion) {
153 $query->setCacheRegion($this->cacheRegion);
154 }
155 return $query;
156 }
157 private function findRootAlias(string $alias, string $parentAlias) : string
158 {
159 if (in_array($parentAlias, $this->getRootAliases(), \true)) {
160 $rootAlias = $parentAlias;
161 } elseif (isset($this->joinRootAliases[$parentAlias])) {
162 $rootAlias = $this->joinRootAliases[$parentAlias];
163 } else {
164 // Should never happen with correct joining order. Might be
165 // thoughtful to throw exception instead.
166 // @phpstan-ignore method.deprecated
167 $rootAlias = $this->getRootAlias();
168 }
169 $this->joinRootAliases[$alias] = $rootAlias;
170 return $rootAlias;
171 }
172 public function getRootAlias()
173 {
174 $aliases = $this->getRootAliases();
175 if (!isset($aliases[0])) {
176 throw new RuntimeException('No alias was set before invoking getRootAlias().');
177 }
178 return $aliases[0];
179 }
180 public function getRootAliases()
181 {
182 $aliases = [];
183 foreach ($this->dqlParts['from'] as &$fromClause) {
184 if (is_string($fromClause)) {
185 $spacePos = strrpos($fromClause, ' ');
186 $from = substr($fromClause, 0, $spacePos);
187 $alias = substr($fromClause, $spacePos + 1);
188 $fromClause = new Query\Expr\From($from, $alias);
189 }
190 $aliases[] = $fromClause->getAlias();
191 }
192 return $aliases;
193 }
194 public function getAllAliases()
195 {
196 return array_merge($this->getRootAliases(), array_keys($this->joinRootAliases));
197 }
198 public function getRootEntities()
199 {
200 $entities = [];
201 foreach ($this->dqlParts['from'] as &$fromClause) {
202 if (is_string($fromClause)) {
203 $spacePos = strrpos($fromClause, ' ');
204 $from = substr($fromClause, 0, $spacePos);
205 $alias = substr($fromClause, $spacePos + 1);
206 $fromClause = new Query\Expr\From($from, $alias);
207 }
208 $entities[] = $fromClause->getFrom();
209 }
210 return $entities;
211 }
212 public function setParameter($key, $value, $type = null)
213 {
214 $existingParameter = $this->getParameter($key);
215 if ($existingParameter !== null) {
216 $existingParameter->setValue($value, $type);
217 return $this;
218 }
219 $this->parameters->add(new Parameter($key, $value, $type));
220 return $this;
221 }
222 public function setParameters($parameters)
223 {
224 // BC compatibility with 2.3-
225 if (is_array($parameters)) {
226 $parameterCollection = new ArrayCollection();
227 foreach ($parameters as $key => $value) {
228 $parameter = new Parameter($key, $value);
229 $parameterCollection->add($parameter);
230 }
231 $parameters = $parameterCollection;
232 }
233 $this->parameters = $parameters;
234 return $this;
235 }
236 public function getParameters()
237 {
238 return $this->parameters;
239 }
240 public function getParameter($key)
241 {
242 $key = Parameter::normalizeName($key);
243 $filteredParameters = $this->parameters->filter(static function (Parameter $parameter) use($key) : bool {
244 $parameterName = $parameter->getName();
245 return $key === $parameterName;
246 });
247 return !$filteredParameters->isEmpty() ? $filteredParameters->first() : null;
248 }
249 public function setFirstResult($firstResult)
250 {
251 $this->firstResult = (int) $firstResult;
252 return $this;
253 }
254 public function getFirstResult()
255 {
256 return $this->firstResult;
257 }
258 public function setMaxResults($maxResults)
259 {
260 if ($maxResults !== null) {
261 $maxResults = (int) $maxResults;
262 }
263 $this->maxResults = $maxResults;
264 return $this;
265 }
266 public function getMaxResults()
267 {
268 return $this->maxResults;
269 }
270 public function add($dqlPartName, $dqlPart, $append = \false)
271 {
272 if ($append && ($dqlPartName === 'where' || $dqlPartName === 'having')) {
273 throw new InvalidArgumentException("Using \$append = true does not have an effect with 'where' or 'having' " . 'parts. See QueryBuilder#andWhere() for an example for correct usage.');
274 }
275 $isMultiple = is_array($this->dqlParts[$dqlPartName]) && !($dqlPartName === 'join' && !$append);
276 // Allow adding any part retrieved from self::getDQLParts().
277 if (is_array($dqlPart) && $dqlPartName !== 'join') {
278 $dqlPart = reset($dqlPart);
279 }
280 // This is introduced for backwards compatibility reasons.
281 // TODO: Remove for 3.0
282 if ($dqlPartName === 'join') {
283 $newDqlPart = [];
284 foreach ($dqlPart as $k => $v) {
285 // @phpstan-ignore method.deprecated
286 $k = is_numeric($k) ? $this->getRootAlias() : $k;
287 $newDqlPart[$k] = $v;
288 }
289 $dqlPart = $newDqlPart;
290 }
291 if ($append && $isMultiple) {
292 if (is_array($dqlPart)) {
293 $key = key($dqlPart);
294 $this->dqlParts[$dqlPartName][$key][] = $dqlPart[$key];
295 } else {
296 $this->dqlParts[$dqlPartName][] = $dqlPart;
297 }
298 } else {
299 $this->dqlParts[$dqlPartName] = $isMultiple ? [$dqlPart] : $dqlPart;
300 }
301 // @phpstan-ignore classConstant.deprecated
302 $this->state = self::STATE_DIRTY;
303 return $this;
304 }
305 public function select($select = null)
306 {
307 // @phpstan-ignore classConstant.deprecated
308 $this->type = self::SELECT;
309 if (empty($select)) {
310 return $this;
311 }
312 $selects = is_array($select) ? $select : func_get_args();
313 return $this->add('select', new Expr\Select($selects), \false);
314 }
315 public function distinct($flag = \true)
316 {
317 $flag = (bool) $flag;
318 if ($this->dqlParts['distinct'] !== $flag) {
319 $this->dqlParts['distinct'] = $flag;
320 // @phpstan-ignore classConstant.deprecated
321 $this->state = self::STATE_DIRTY;
322 }
323 return $this;
324 }
325 public function addSelect($select = null)
326 {
327 // @phpstan-ignore classConstant.deprecated
328 $this->type = self::SELECT;
329 if (empty($select)) {
330 return $this;
331 }
332 $selects = is_array($select) ? $select : func_get_args();
333 return $this->add('select', new Expr\Select($selects), \true);
334 }
335 public function delete($delete = null, $alias = null)
336 {
337 // @phpstan-ignore classConstant.deprecated
338 $this->type = self::DELETE;
339 if (!$delete) {
340 return $this;
341 }
342 if (!$alias) {
343 Deprecation::trigger('doctrine/orm', 'https://github.com/doctrine/orm/issues/9733', 'Omitting the alias is deprecated and will throw an exception in Doctrine 3.0.');
344 }
345 return $this->add('from', new Expr\From($delete, $alias));
346 }
347 public function update($update = null, $alias = null)
348 {
349 // @phpstan-ignore classConstant.deprecated
350 $this->type = self::UPDATE;
351 if (!$update) {
352 return $this;
353 }
354 if (!$alias) {
355 Deprecation::trigger('doctrine/orm', 'https://github.com/doctrine/orm/issues/9733', 'Omitting the alias is deprecated and will throw an exception in Doctrine 3.0.');
356 }
357 return $this->add('from', new Expr\From($update, $alias));
358 }
359 public function from($from, $alias, $indexBy = null)
360 {
361 return $this->add('from', new Expr\From($from, $alias, $indexBy), \true);
362 }
363 public function indexBy($alias, $indexBy)
364 {
365 $rootAliases = $this->getRootAliases();
366 if (!in_array($alias, $rootAliases, \true)) {
367 throw new Query\QueryException(sprintf('Specified root alias %s must be set before invoking indexBy().', $alias));
368 }
369 foreach ($this->dqlParts['from'] as &$fromClause) {
370 assert($fromClause instanceof Expr\From);
371 if ($fromClause->getAlias() !== $alias) {
372 continue;
373 }
374 $fromClause = new Expr\From($fromClause->getFrom(), $fromClause->getAlias(), $indexBy);
375 }
376 return $this;
377 }
378 public function join($join, $alias, $conditionType = null, $condition = null, $indexBy = null)
379 {
380 return $this->innerJoin($join, $alias, $conditionType, $condition, $indexBy);
381 }
382 public function innerJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null)
383 {
384 $parentAlias = substr($join, 0, (int) strpos($join, '.'));
385 $rootAlias = $this->findRootAlias($alias, $parentAlias);
386 $join = new Expr\Join(Expr\Join::INNER_JOIN, $join, $alias, $conditionType, $condition, $indexBy);
387 return $this->add('join', [$rootAlias => $join], \true);
388 }
389 public function leftJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null)
390 {
391 $parentAlias = substr($join, 0, (int) strpos($join, '.'));
392 $rootAlias = $this->findRootAlias($alias, $parentAlias);
393 $join = new Expr\Join(Expr\Join::LEFT_JOIN, $join, $alias, $conditionType, $condition, $indexBy);
394 return $this->add('join', [$rootAlias => $join], \true);
395 }
396 public function set($key, $value)
397 {
398 return $this->add('set', new Expr\Comparison($key, Expr\Comparison::EQ, $value), \true);
399 }
400 public function where($predicates)
401 {
402 if (!(func_num_args() === 1 && $predicates instanceof Expr\Composite)) {
403 $predicates = new Expr\Andx(func_get_args());
404 }
405 return $this->add('where', $predicates);
406 }
407 public function andWhere()
408 {
409 $args = func_get_args();
410 $where = $this->getDQLPart('where');
411 if ($where instanceof Expr\Andx) {
412 $where->addMultiple($args);
413 } else {
414 array_unshift($args, $where);
415 $where = new Expr\Andx($args);
416 }
417 return $this->add('where', $where);
418 }
419 public function orWhere()
420 {
421 $args = func_get_args();
422 $where = $this->getDQLPart('where');
423 if ($where instanceof Expr\Orx) {
424 $where->addMultiple($args);
425 } else {
426 array_unshift($args, $where);
427 $where = new Expr\Orx($args);
428 }
429 return $this->add('where', $where);
430 }
431 public function groupBy($groupBy)
432 {
433 return $this->add('groupBy', new Expr\GroupBy(func_get_args()));
434 }
435 public function addGroupBy($groupBy)
436 {
437 return $this->add('groupBy', new Expr\GroupBy(func_get_args()), \true);
438 }
439 public function having($having)
440 {
441 if (!(func_num_args() === 1 && ($having instanceof Expr\Andx || $having instanceof Expr\Orx))) {
442 $having = new Expr\Andx(func_get_args());
443 }
444 return $this->add('having', $having);
445 }
446 public function andHaving($having)
447 {
448 $args = func_get_args();
449 $having = $this->getDQLPart('having');
450 if ($having instanceof Expr\Andx) {
451 $having->addMultiple($args);
452 } else {
453 array_unshift($args, $having);
454 $having = new Expr\Andx($args);
455 }
456 return $this->add('having', $having);
457 }
458 public function orHaving($having)
459 {
460 $args = func_get_args();
461 $having = $this->getDQLPart('having');
462 if ($having instanceof Expr\Orx) {
463 $having->addMultiple($args);
464 } else {
465 array_unshift($args, $having);
466 $having = new Expr\Orx($args);
467 }
468 return $this->add('having', $having);
469 }
470 public function orderBy($sort, $order = null)
471 {
472 $orderBy = $sort instanceof Expr\OrderBy ? $sort : new Expr\OrderBy($sort, $order);
473 return $this->add('orderBy', $orderBy);
474 }
475 public function addOrderBy($sort, $order = null)
476 {
477 $orderBy = $sort instanceof Expr\OrderBy ? $sort : new Expr\OrderBy($sort, $order);
478 return $this->add('orderBy', $orderBy, \true);
479 }
480 public function addCriteria(Criteria $criteria)
481 {
482 $allAliases = $this->getAllAliases();
483 if (!isset($allAliases[0])) {
484 throw new Query\QueryException('No aliases are set before invoking addCriteria().');
485 }
486 $visitor = new QueryExpressionVisitor($this->getAllAliases());
487 $whereExpression = $criteria->getWhereExpression();
488 if ($whereExpression) {
489 $this->andWhere($visitor->dispatch($whereExpression));
490 foreach ($visitor->getParameters() as $parameter) {
491 $this->parameters->add($parameter);
492 }
493 }
494 foreach (self::getCriteriaOrderings($criteria) as $sort => $order) {
495 $hasValidAlias = \false;
496 foreach ($allAliases as $alias) {
497 if (str_starts_with($sort . '.', $alias . '.')) {
498 $hasValidAlias = \true;
499 break;
500 }
501 }
502 if (!$hasValidAlias) {
503 $sort = $allAliases[0] . '.' . $sort;
504 }
505 $this->addOrderBy($sort, $order);
506 }
507 // Overwrite limits only if they was set in criteria
508 $firstResult = $criteria->getFirstResult();
509 if ($firstResult > 0) {
510 $this->setFirstResult($firstResult);
511 }
512 $maxResults = $criteria->getMaxResults();
513 if ($maxResults !== null) {
514 $this->setMaxResults($maxResults);
515 }
516 return $this;
517 }
518 public function getDQLPart($queryPartName)
519 {
520 return $this->dqlParts[$queryPartName];
521 }
522 public function getDQLParts()
523 {
524 return $this->dqlParts;
525 }
526 private function getDQLForDelete() : string
527 {
528 return 'DELETE' . $this->getReducedDQLQueryPart('from', ['pre' => ' ', 'separator' => ', ']) . $this->getReducedDQLQueryPart('where', ['pre' => ' WHERE ']) . $this->getReducedDQLQueryPart('orderBy', ['pre' => ' ORDER BY ', 'separator' => ', ']);
529 }
530 private function getDQLForUpdate() : string
531 {
532 return 'UPDATE' . $this->getReducedDQLQueryPart('from', ['pre' => ' ', 'separator' => ', ']) . $this->getReducedDQLQueryPart('set', ['pre' => ' SET ', 'separator' => ', ']) . $this->getReducedDQLQueryPart('where', ['pre' => ' WHERE ']) . $this->getReducedDQLQueryPart('orderBy', ['pre' => ' ORDER BY ', 'separator' => ', ']);
533 }
534 private function getDQLForSelect() : string
535 {
536 $dql = 'SELECT' . ($this->dqlParts['distinct'] === \true ? ' DISTINCT' : '') . $this->getReducedDQLQueryPart('select', ['pre' => ' ', 'separator' => ', ']);
537 $fromParts = $this->getDQLPart('from');
538 $joinParts = $this->getDQLPart('join');
539 $fromClauses = [];
540 // Loop through all FROM clauses
541 if (!empty($fromParts)) {
542 $dql .= ' FROM ';
543 foreach ($fromParts as $from) {
544 $fromClause = (string) $from;
545 if ($from instanceof Expr\From && isset($joinParts[$from->getAlias()])) {
546 foreach ($joinParts[$from->getAlias()] as $join) {
547 $fromClause .= ' ' . (string) $join;
548 }
549 }
550 $fromClauses[] = $fromClause;
551 }
552 }
553 $dql .= implode(', ', $fromClauses) . $this->getReducedDQLQueryPart('where', ['pre' => ' WHERE ']) . $this->getReducedDQLQueryPart('groupBy', ['pre' => ' GROUP BY ', 'separator' => ', ']) . $this->getReducedDQLQueryPart('having', ['pre' => ' HAVING ']) . $this->getReducedDQLQueryPart('orderBy', ['pre' => ' ORDER BY ', 'separator' => ', ']);
554 return $dql;
555 }
556 private function getReducedDQLQueryPart(string $queryPartName, array $options = []) : string
557 {
558 $queryPart = $this->getDQLPart($queryPartName);
559 if (empty($queryPart)) {
560 return $options['empty'] ?? '';
561 }
562 return ($options['pre'] ?? '') . (is_array($queryPart) ? implode($options['separator'], $queryPart) : $queryPart) . ($options['post'] ?? '');
563 }
564 public function resetDQLParts($parts = null)
565 {
566 if ($parts === null) {
567 $parts = array_keys($this->dqlParts);
568 }
569 foreach ($parts as $part) {
570 $this->resetDQLPart($part);
571 }
572 return $this;
573 }
574 public function resetDQLPart($part)
575 {
576 $this->dqlParts[$part] = is_array($this->dqlParts[$part]) ? [] : null;
577 // @phpstan-ignore classConstant.deprecated
578 $this->state = self::STATE_DIRTY;
579 return $this;
580 }
581 public function __toString()
582 {
583 return $this->getDQL();
584 }
585 public function __clone()
586 {
587 foreach ($this->dqlParts as $part => $elements) {
588 if (is_array($this->dqlParts[$part])) {
589 foreach ($this->dqlParts[$part] as $idx => $element) {
590 if (is_object($element)) {
591 $this->dqlParts[$part][$idx] = clone $element;
592 }
593 }
594 } elseif (is_object($elements)) {
595 $this->dqlParts[$part] = clone $elements;
596 }
597 }
598 $parameters = [];
599 foreach ($this->parameters as $parameter) {
600 $parameters[] = clone $parameter;
601 }
602 $this->parameters = new ArrayCollection($parameters);
603 }
604 }
605