‪TYPO3CMS  ‪main
ConcreteQueryBuilder.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Doctrine\DBAL\Query\Expression\CompositeExpression;
21 use Doctrine\DBAL\Query\From;
22 use Doctrine\DBAL\Query\Join;
23 use Doctrine\DBAL\Query\QueryBuilder as DoctrineQueryBuilder;
24 use Doctrine\DBAL\Query\QueryType;
26 
40 class ‪ConcreteQueryBuilder extends DoctrineQueryBuilder
41 {
45  protected QueryType ‪$type = QueryType::SELECT;
46 
52  protected array ‪$select = [];
53 
57  protected bool ‪$distinct = false;
58 
64  protected array ‪$from = [];
65 
71  protected array ‪$join = [];
72 
76  protected string|CompositeExpression|null ‪$where = null;
77 
83  protected array ‪$groupBy = [];
84 
88  protected string|CompositeExpression|null ‪$having = null;
89 
95  protected array ‪$orderBy = [];
96 
102  public function ‪__construct(protected readonly ‪Connection $connection)
103  {
104  parent::__construct($this->connection);
105  }
106 
110  public function ‪__clone()
111  {
112  parent::__clone();
113  foreach ($this->‪from as $key => ‪$from) {
114  $this->‪from[$key] = clone ‪$from;
115  }
116  foreach ($this->join as $fromAlias => $joins) {
117  foreach ($joins as $key => ‪$join) {
118  $this->join[$fromAlias][$key] = clone ‪$join;
119  }
120  }
121  if (is_object($this->‪where)) {
122  $this->‪where = clone ‪$this->where;
123  }
124  if (is_object($this->‪having)) {
125  $this->‪having = clone ‪$this->having;
126  }
127  }
128 
144  public function ‪select(string ...$expressions): self
145  {
146  parent::select(...$expressions);
147  $this->type = QueryType::SELECT;
148  if (count($expressions) < 1) {
149  return $this;
150  }
151  $this->‪select = $expressions;
152  return $this;
153  }
154 
167  public function ‪distinct(bool ‪$distinct = true): self
168  {
169  parent::distinct(‪$distinct);
170  $this->‪distinct = ‪$distinct;
171  return $this;
172  }
173 
190  public function ‪addSelect(string $expression, string ...$expressions): self
191  {
192  parent::addSelect($expression, ...$expressions);
193  $this->type = QueryType::SELECT;
194  $this->‪select = array_merge($this->‪select, [$expression], $expressions);
195  return $this;
196  }
197 
213  public function delete(string $table): self
214  {
215  parent::delete($table);
216  $this->type = QueryType::DELETE;
217  return $this;
218  }
219 
235  public function ‪update(string $table): self
236  {
237  parent::update($table);
238  $this->type = QueryType::UPDATE;
239  return $this;
240  }
241 
261  public function ‪insert(string $table): self
262  {
263  parent::insert($table);
264  $this->type = QueryType::INSERT;
265  return $this;
266  }
267 
283  public function ‪from(string $table, ?string $alias = null): self
284  {
285  parent::from($table, $alias);
286  $this->‪from[] = new From($table, $alias);
287  return $this;
288  }
289 
307  public function ‪innerJoin(string $fromAlias, string ‪$join, string $alias, ?string $condition = null): self
308  {
309  parent::innerJoin($fromAlias, ‪$join, $alias, $condition);
310  $this->join[$fromAlias][] = Join::inner(‪$join, $alias, $condition);
311  return $this;
312  }
313 
331  public function ‪leftJoin(string $fromAlias, string ‪$join, string $alias, ?string $condition = null): self
332  {
333  parent::leftJoin($fromAlias, ‪$join, $alias, $condition);
334  $this->join[$fromAlias][] = Join::left(‪$join, $alias, $condition);
335  return $this;
336  }
337 
355  public function ‪rightJoin(string $fromAlias, string ‪$join, string $alias, ?string $condition = null): self
356  {
357  parent::rightJoin($fromAlias, ‪$join, $alias, $condition);
358  $this->join[$fromAlias][] = Join::right(‪$join, $alias, $condition);
359  return $this;
360  }
361 
389  public function ‪where(string|CompositeExpression $predicate, string|CompositeExpression ...$predicates): self
390  {
391  ‪$where = $this->‪where = $this->‪createPredicate($predicate, ...$predicates);
392  parent::where(‪$where);
393  return $this;
394  }
395 
415  public function ‪andWhere(string|CompositeExpression $predicate, string|CompositeExpression ...$predicates): self
416  {
417  ‪$where = $this->‪where = $this->‪appendToPredicate(
418  $this->‪where,
419  CompositeExpression::TYPE_AND,
420  $predicate,
421  ...$predicates,
422  );
423  $this->‪where(‪$where);
424  return $this;
425  }
426 
446  public function ‪orWhere(string|CompositeExpression $predicate, string|CompositeExpression ...$predicates): self
447  {
448  ‪$where = $this->‪where = $this->‪appendToPredicate($this->‪where, CompositeExpression::TYPE_OR, $predicate, ...$predicates);
449  $this->‪where(‪$where);
450  return $this;
451  }
452 
469  public function ‪groupBy(string $expression, string ...$expressions): self
470  {
471  ‪$groupBy = $this->‪groupBy = array_merge([$expression], $expressions);
472  parent::groupBy(...‪$groupBy);
473  return $this;
474  }
475 
492  public function ‪addGroupBy(string $expression, string ...$expressions): self
493  {
494  ‪$groupBy = $this->‪groupBy = array_merge($this->‪groupBy, [$expression], $expressions);
495  $this->‪groupBy(...$groupBy);
496  return $this;
497  }
498 
508  public function ‪having(string|CompositeExpression $predicate, string|CompositeExpression ...$predicates): self
509  {
510  ‪$having = $this->‪having = $this->‪createPredicate($predicate, ...$predicates);
511  parent::having(‪$having);
512  return $this;
513  }
514 
524  public function ‪andHaving(string|CompositeExpression $predicate, string|CompositeExpression ...$predicates): self
525  {
526  ‪$having = $this->‪having = $this->‪appendToPredicate(
527  $this->‪having,
528  CompositeExpression::TYPE_AND,
529  $predicate,
530  ...$predicates,
531  );
532  $this->‪having(‪$having);
533  return $this;
534  }
535 
545  public function ‪orHaving(string|CompositeExpression $predicate, string|CompositeExpression ...$predicates): self
546  {
547  ‪$having = $this->‪having = $this->‪appendToPredicate(
548  $this->‪having,
549  CompositeExpression::TYPE_OR,
550  $predicate,
551  ...$predicates,
552  );
553  $this->‪having(‪$having);
554  return $this;
555  }
556 
560  private function ‪createPredicate(
561  string|CompositeExpression $predicate,
562  string|CompositeExpression ...$predicates,
563  ): string|CompositeExpression {
564  if (count($predicates) === 0) {
565  return $predicate;
566  }
567  $predicates = array_filter($predicates, static fn(CompositeExpression|string|null $value): bool => !self::isEmptyPart($value));
568  return new CompositeExpression(CompositeExpression::TYPE_AND, $predicate, ...$predicates);
569  }
570 
574  private function ‪appendToPredicate(
575  string|CompositeExpression|null $currentPredicate,
576  string ‪$type,
577  string|CompositeExpression ...$predicates,
578  ): string|CompositeExpression {
579  $predicates = array_filter($predicates, static fn(CompositeExpression|string|null $value): bool => !self::isEmptyPart($value));
580  if ($currentPredicate instanceof CompositeExpression && $currentPredicate->getType() === ‪$type) {
581  return $currentPredicate->with(...$predicates);
582  }
583  if ($currentPredicate !== null) {
584  array_unshift($predicates, $currentPredicate);
585  } elseif (count($predicates) === 1) {
586  return $predicates[0];
587  }
588  return new CompositeExpression(‪$type, ...$predicates);
589  }
590 
600  public function ‪orderBy(string $sort, ?string $order = null): self
601  {
602  parent::orderBy($sort, $order);
603  ‪$orderBy = $sort;
604  if ($order !== null) {
605  ‪$orderBy .= ' ' . $order;
606  }
607  $this->‪orderBy = [‪$orderBy];
608  return $this;
609  }
610 
619  public function ‪addOrderBy(string $sort, ?string $order = null): self
620  {
621  parent::addOrderBy($sort, $order);
622  ‪$orderBy = $sort;
623  if ($order !== null) {
624  ‪$orderBy .= ' ' . $order;
625  }
626  $this->‪orderBy[] = ‪$orderBy;
627  return $this;
628  }
629 
635  public function ‪resetWhere(): self
636  {
637  parent::resetWhere();
638  $this->‪where = null;
639  return $this;
640  }
641 
647  public function ‪resetGroupBy(): self
648  {
649  parent::resetGroupBy();
650  $this->‪groupBy = [];
651  return $this;
652  }
653 
659  public function ‪resetHaving(): self
660  {
661  $this->‪resetHaving();
662  $this->‪having = null;
663  return $this;
664  }
665 
671  public function ‪resetOrderBy(): self
672  {
673  parent::resetOrderBy();
674  $this->‪orderBy = [];
675  return $this;
676  }
677 
678  //##################################################################################################################
679  // Below are added methods not originated from Doctrine DBAL QueryBuilder
680  //##################################################################################################################
681 
696  protected static function ‪isEmptyPart(CompositeExpression|string|null $value): bool
697  {
698  return $value === null
699  || ($value instanceof CompositeExpression && $value->count() === 0)
700  || trim((string)$value, '() ') === ''
701  ;
702  }
703 }
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\andHaving
‪$this andHaving(string|CompositeExpression $predicate, string|CompositeExpression ... $predicates)
Definition: ConcreteQueryBuilder.php:524
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\leftJoin
‪$this leftJoin(string $fromAlias, string $join, string $alias, ?string $condition=null)
Definition: ConcreteQueryBuilder.php:331
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder
Definition: ConcreteQueryBuilder.php:41
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\where
‪$this where(string|CompositeExpression $predicate, string|CompositeExpression ... $predicates)
Definition: ConcreteQueryBuilder.php:389
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\orWhere
‪$this orWhere(string|CompositeExpression $predicate, string|CompositeExpression ... $predicates)
Definition: ConcreteQueryBuilder.php:446
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\createPredicate
‪createPredicate(string|CompositeExpression $predicate, string|CompositeExpression ... $predicates,)
Definition: ConcreteQueryBuilder.php:560
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\resetGroupBy
‪$this resetGroupBy()
Definition: ConcreteQueryBuilder.php:647
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\rightJoin
‪$this rightJoin(string $fromAlias, string $join, string $alias, ?string $condition=null)
Definition: ConcreteQueryBuilder.php:355
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\innerJoin
‪$this innerJoin(string $fromAlias, string $join, string $alias, ?string $condition=null)
Definition: ConcreteQueryBuilder.php:307
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\__clone
‪__clone()
Definition: ConcreteQueryBuilder.php:110
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\$distinct
‪bool $distinct
Definition: ConcreteQueryBuilder.php:57
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\$having
‪string CompositeExpression null $having
Definition: ConcreteQueryBuilder.php:88
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\appendToPredicate
‪appendToPredicate(string|CompositeExpression|null $currentPredicate, string $type, string|CompositeExpression ... $predicates,)
Definition: ConcreteQueryBuilder.php:574
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\addSelect
‪$this addSelect(string $expression, string ... $expressions)
Definition: ConcreteQueryBuilder.php:190
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\$where
‪string CompositeExpression null $where
Definition: ConcreteQueryBuilder.php:76
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\$groupBy
‪array $groupBy
Definition: ConcreteQueryBuilder.php:83
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\update
‪$this update(string $table)
Definition: ConcreteQueryBuilder.php:235
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\__construct
‪__construct(protected readonly Connection $connection)
Definition: ConcreteQueryBuilder.php:102
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\insert
‪$this insert(string $table)
Definition: ConcreteQueryBuilder.php:261
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\groupBy
‪$this groupBy(string $expression, string ... $expressions)
Definition: ConcreteQueryBuilder.php:469
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\distinct
‪$this distinct(bool $distinct=true)
Definition: ConcreteQueryBuilder.php:167
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\andWhere
‪$this andWhere(string|CompositeExpression $predicate, string|CompositeExpression ... $predicates)
Definition: ConcreteQueryBuilder.php:415
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\$select
‪array $select
Definition: ConcreteQueryBuilder.php:52
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\resetHaving
‪$this resetHaving()
Definition: ConcreteQueryBuilder.php:659
‪TYPO3\CMS\Core\Database\Query
Definition: BulkInsertQuery.php:18
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\$type
‪QueryType $type
Definition: ConcreteQueryBuilder.php:45
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\from
‪$this from(string $table, ?string $alias=null)
Definition: ConcreteQueryBuilder.php:283
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\addOrderBy
‪$this addOrderBy(string $sort, ?string $order=null)
Definition: ConcreteQueryBuilder.php:619
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\resetWhere
‪$this resetWhere()
Definition: ConcreteQueryBuilder.php:635
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\$orderBy
‪array $orderBy
Definition: ConcreteQueryBuilder.php:95
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\select
‪$this select(string ... $expressions)
Definition: ConcreteQueryBuilder.php:144
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\having
‪$this having(string|CompositeExpression $predicate, string|CompositeExpression ... $predicates)
Definition: ConcreteQueryBuilder.php:508
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\resetOrderBy
‪$this resetOrderBy()
Definition: ConcreteQueryBuilder.php:671
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\$from
‪array $from
Definition: ConcreteQueryBuilder.php:64
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\addGroupBy
‪$this addGroupBy(string $expression, string ... $expressions)
Definition: ConcreteQueryBuilder.php:492
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\isEmptyPart
‪static bool isEmptyPart(CompositeExpression|string|null $value)
Definition: ConcreteQueryBuilder.php:696
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\orHaving
‪$this orHaving(string|CompositeExpression $predicate, string|CompositeExpression ... $predicates)
Definition: ConcreteQueryBuilder.php:545
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\$join
‪array $join
Definition: ConcreteQueryBuilder.php:71
‪TYPO3\CMS\Core\Database\Query\ConcreteQueryBuilder\orderBy
‪$this orderBy(string $sort, ?string $order=null)
Definition: ConcreteQueryBuilder.php:600