‪TYPO3CMS  10.4
ExpressionBuilder.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\Platforms\AbstractPlatform;
22 
35 {
36  const ‪EQ = '=';
37  const ‪NEQ = '<>';
38  const ‪LT = '<';
39  const ‪LTE = '<=';
40  const ‪GT = '>';
41  const ‪GTE = '>=';
42 
43  const ‪QUOTE_NOTHING = 0;
45  const ‪QUOTE_PARAMETER = 2;
46 
52  protected ‪$connection;
53 
60  {
61  $this->connection = ‪$connection;
62  }
63 
71  public function ‪andX(...$expressions): ‪CompositeExpression
72  {
73  return new ‪CompositeExpression(CompositeExpression::TYPE_AND, $expressions);
74  }
75 
83  public function ‪orX(...$expressions): CompositeExpression
84  {
85  return new CompositeExpression(CompositeExpression::TYPE_OR, $expressions);
86  }
87 
97  public function ‪comparison($leftExpression, string $operator, $rightExpression): string
98  {
99  return $leftExpression . ' ' . $operator . ' ' . $rightExpression;
100  }
101 
110  public function ‪eq(string $fieldName, $value): string
111  {
112  return $this->‪comparison($this->connection->quoteIdentifier($fieldName), static::EQ, $value);
113  }
114 
129  public function ‪neq(string $fieldName, $value): string
130  {
131  return $this->‪comparison($this->connection->quoteIdentifier($fieldName), static::NEQ, $value);
132  }
133 
142  public function ‪lt($fieldName, $value): string
143  {
144  return $this->‪comparison($this->connection->quoteIdentifier($fieldName), static::LT, $value);
145  }
146 
155  public function ‪lte(string $fieldName, $value): string
156  {
157  return $this->‪comparison($this->connection->quoteIdentifier($fieldName), static::LTE, $value);
158  }
159 
168  public function ‪gt(string $fieldName, $value): string
169  {
170  return $this->‪comparison($this->connection->quoteIdentifier($fieldName), static::GT, $value);
171  }
172 
181  public function ‪gte(string $fieldName, $value): string
182  {
183  return $this->‪comparison($this->connection->quoteIdentifier($fieldName), static::GTE, $value);
184  }
185 
193  public function ‪isNull(string $fieldName): string
194  {
195  return $this->connection->quoteIdentifier($fieldName) . ' IS NULL';
196  }
197 
205  public function ‪isNotNull(string $fieldName): string
206  {
207  return $this->connection->quoteIdentifier($fieldName) . ' IS NOT NULL';
208  }
209 
218  public function ‪like(string $fieldName, $value): string
219  {
220  return $this->‪comparison($this->connection->quoteIdentifier($fieldName), 'LIKE', $value);
221  }
222 
231  public function ‪notLike(string $fieldName, $value): string
232  {
233  return $this->‪comparison($this->connection->quoteIdentifier($fieldName), 'NOT LIKE', $value);
234  }
235 
245  public function ‪in(string $fieldName, $value): string
246  {
247  return $this->‪comparison(
248  $this->connection->quoteIdentifier($fieldName),
249  'IN',
250  '(' . implode(', ', (array)$value) . ')'
251  );
252  }
253 
263  public function ‪notIn(string $fieldName, $value): string
264  {
265  return $this->‪comparison(
266  $this->connection->quoteIdentifier($fieldName),
267  'NOT IN',
268  '(' . implode(', ', (array)$value) . ')'
269  );
270  }
271 
282  public function ‪inSet(string $fieldName, string $value, bool $isColumn = false): string
283  {
284  if ($value === '') {
285  throw new \InvalidArgumentException(
286  'ExpressionBuilder::inSet() can not be used with an empty string value.',
287  1459696089
288  );
289  }
290 
291  if (strpos($value, ',') !== false) {
292  throw new \InvalidArgumentException(
293  'ExpressionBuilder::inSet() can not be used with values that contain a comma (",").',
294  1459696090
295  );
296  }
297 
298  switch ($this->connection->getDatabasePlatform()->getName()) {
299  case 'postgresql':
300  case 'pdo_postgresql':
301  return $this->‪comparison(
302  $isColumn ? $value . '::text' : $this->‪literal($this->‪unquoteLiteral((string)$value)),
303  self::EQ,
304  sprintf(
305  'ANY(string_to_array(%s, %s))',
306  $this->connection->quoteIdentifier($fieldName) . '::text',
307  $this->literal(',')
308  )
309  );
310  case 'oci8':
311  case 'pdo_oracle':
312  throw new \RuntimeException(
313  'FIND_IN_SET support for database platform "Oracle" not yet implemented.',
314  1459696680
315  );
316  case 'sqlsrv':
317  case 'pdo_sqlsrv':
318  case 'mssql':
319  // See unit and functional tests for details
320  if ($isColumn) {
321  $expression = $this->‪orX(
322  $this->‪eq($fieldName, $value),
323  $this->‪like($fieldName, $value . ' + \',%\''),
324  $this->‪like($fieldName, '\'%,\' + ' . $value),
325  $this->‪like($fieldName, '\'%,\' + ' . $value . ' + \',%\'')
326  );
327  } else {
328  $likeEscapedValue = str_replace(
329  ['[', '%'],
330  ['[[]', '[%]'],
331  $this->‪unquoteLiteral($value)
332  );
333  $expression = $this->‪orX(
334  $this->‪eq($fieldName, $this->‪literal($this->‪unquoteLiteral((string)$value))),
335  $this->‪like($fieldName, $this->‪literal($likeEscapedValue . ',%')),
336  $this->‪like($fieldName, $this->‪literal('%,' . $likeEscapedValue)),
337  $this->‪like($fieldName, $this->‪literal('%,' . $likeEscapedValue . ',%'))
338  );
339  }
340  return (string)$expression;
341  case 'sqlite':
342  case 'sqlite3':
343  case 'pdo_sqlite':
344  if (strpos($value, ':') === 0 || $value === '?') {
345  throw new \InvalidArgumentException(
346  'ExpressionBuilder::inSet() for SQLite can not be used with placeholder arguments.',
347  1476029421
348  );
349  }
350  $comparison = sprintf(
351  'instr(%s, %s)',
352  implode(
353  '||',
354  [
355  $this->‪literal(','),
356  $this->connection->quoteIdentifier($fieldName),
357  $this->literal(','),
358  ]
359  ),
360  $isColumn ?
361  implode(
362  '||',
363  [
364  $this->‪literal(','),
365  // do not explicitly quote value as it is expected to be
366  // quoted by the caller
367  'cast(' . $value . ' as text)',
368  $this->‪literal(','),
369  ]
370  )
371  : $this->‪literal(
372  ',' . $this->‪unquoteLiteral($value) . ','
373  )
374  );
375  return $comparison;
376  default:
377  return sprintf(
378  'FIND_IN_SET(%s, %s)',
379  $value,
380  $this->connection->quoteIdentifier($fieldName)
381  );
382  }
383  }
384 
392  public function ‪bitAnd(string $fieldName, int $value): string
393  {
394  switch ($this->connection->getDatabasePlatform()->getName()) {
395  case 'oci8':
396  case 'pdo_oracle':
397  return sprintf(
398  'BITAND(%s, %s)',
399  $this->connection->quoteIdentifier($fieldName),
400  $value
401  );
402  default:
403  return $this->‪comparison(
404  $this->connection->quoteIdentifier($fieldName),
405  '&',
406  $value
407  );
408  }
409  }
410 
418  public function ‪min(string $fieldName, string $alias = null): string
419  {
420  return $this->‪calculation('MIN', $fieldName, $alias);
421  }
422 
430  public function ‪max(string $fieldName, string $alias = null): string
431  {
432  return $this->‪calculation('MAX', $fieldName, $alias);
433  }
434 
442  public function ‪avg(string $fieldName, string $alias = null): string
443  {
444  return $this->‪calculation('AVG', $fieldName, $alias);
445  }
446 
454  public function ‪sum(string $fieldName, string $alias = null): string
455  {
456  return $this->‪calculation('SUM', $fieldName, $alias);
457  }
458 
466  public function ‪count(string $fieldName, string $alias = null): string
467  {
468  return $this->‪calculation('COUNT', $fieldName, $alias);
469  }
470 
478  public function ‪length(string $fieldName, string $alias = null): string
479  {
480  return $this->‪calculation('LENGTH', $fieldName, $alias);
481  }
482 
491  protected function ‪calculation(string $aggregateName, string $fieldName, string $alias = null): string
492  {
493  $aggregateSQL = sprintf(
494  '%s(%s)',
495  $aggregateName,
496  $this->connection->quoteIdentifier($fieldName)
497  );
498 
499  if (!empty($alias)) {
500  $aggregateSQL .= ' AS ' . $this->connection->quoteIdentifier($alias);
501  }
502 
503  return $aggregateSQL;
504  }
505 
514  public function ‪trim(string $fieldName, int $position = AbstractPlatform::TRIM_UNSPECIFIED, string $char = null)
515  {
516  return $this->connection->getDatabasePlatform()->getTrimExpression(
517  $this->connection->quoteIdentifier($fieldName),
518  $position,
519  ($char === null ? false : $this->literal($char))
520  );
521  }
522 
531  public function ‪literal($input, string $type = null)
532  {
533  return $this->connection->quote($input, $type);
534  }
535 
542  protected function ‪unquoteLiteral(string $value): string
543  {
544  $quoteChar = $this->connection
545  ->getDatabasePlatform()
546  ->getStringLiteralQuoteCharacter();
547 
548  $isQuoted = strpos($value, $quoteChar) === 0 && strpos(strrev($value), $quoteChar) === 0;
549 
550  if ($isQuoted) {
551  return str_replace($quoteChar . $quoteChar, $quoteChar, substr($value, 1, -1));
552  }
553 
554  return $value;
555  }
556 }
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\max
‪string max(string $fieldName, string $alias=null)
Definition: ExpressionBuilder.php:429
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\sum
‪string sum(string $fieldName, string $alias=null)
Definition: ExpressionBuilder.php:453
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\gt
‪string gt(string $fieldName, $value)
Definition: ExpressionBuilder.php:167
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\QUOTE_NOTHING
‪const QUOTE_NOTHING
Definition: ExpressionBuilder.php:43
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\unquoteLiteral
‪string unquoteLiteral(string $value)
Definition: ExpressionBuilder.php:541
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\like
‪string like(string $fieldName, $value)
Definition: ExpressionBuilder.php:217
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
Definition: ExpressionBuilder.php:35
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\EQ
‪const EQ
Definition: ExpressionBuilder.php:36
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\literal
‪mixed literal($input, string $type=null)
Definition: ExpressionBuilder.php:530
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\bitAnd
‪string bitAnd(string $fieldName, int $value)
Definition: ExpressionBuilder.php:391
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\eq
‪string eq(string $fieldName, $value)
Definition: ExpressionBuilder.php:109
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\count
‪string count(string $fieldName, string $alias=null)
Definition: ExpressionBuilder.php:465
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\LTE
‪const LTE
Definition: ExpressionBuilder.php:39
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\lt
‪string lt($fieldName, $value)
Definition: ExpressionBuilder.php:141
‪TYPO3\CMS\Core\Database\Query\Expression
Definition: CompositeExpression.php:18
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\notIn
‪string notIn(string $fieldName, $value)
Definition: ExpressionBuilder.php:262
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\neq
‪string neq(string $fieldName, $value)
Definition: ExpressionBuilder.php:128
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\calculation
‪string calculation(string $aggregateName, string $fieldName, string $alias=null)
Definition: ExpressionBuilder.php:490
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\QUOTE_IDENTIFIER
‪const QUOTE_IDENTIFIER
Definition: ExpressionBuilder.php:44
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\GTE
‪const GTE
Definition: ExpressionBuilder.php:41
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\__construct
‪__construct(Connection $connection)
Definition: ExpressionBuilder.php:58
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\lte
‪string lte(string $fieldName, $value)
Definition: ExpressionBuilder.php:154
‪TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression
Definition: CompositeExpression.php:25
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\in
‪string in(string $fieldName, $value)
Definition: ExpressionBuilder.php:244
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\andX
‪CompositeExpression andX(... $expressions)
Definition: ExpressionBuilder.php:70
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\GT
‪const GT
Definition: ExpressionBuilder.php:40
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\orX
‪CompositeExpression orX(... $expressions)
Definition: ExpressionBuilder.php:82
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\NEQ
‪const NEQ
Definition: ExpressionBuilder.php:37
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\min
‪string min(string $fieldName, string $alias=null)
Definition: ExpressionBuilder.php:417
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\length
‪string length(string $fieldName, string $alias=null)
Definition: ExpressionBuilder.php:477
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\LT
‪const LT
Definition: ExpressionBuilder.php:38
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:36
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\gte
‪string gte(string $fieldName, $value)
Definition: ExpressionBuilder.php:180
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\$connection
‪Connection $connection
Definition: ExpressionBuilder.php:51
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\avg
‪string avg(string $fieldName, string $alias=null)
Definition: ExpressionBuilder.php:441
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\notLike
‪string notLike(string $fieldName, $value)
Definition: ExpressionBuilder.php:230
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\isNull
‪string isNull(string $fieldName)
Definition: ExpressionBuilder.php:192
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\QUOTE_PARAMETER
‪const QUOTE_PARAMETER
Definition: ExpressionBuilder.php:45
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\isNotNull
‪string isNotNull(string $fieldName)
Definition: ExpressionBuilder.php:204
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\inSet
‪string inSet(string $fieldName, string $value, bool $isColumn=false)
Definition: ExpressionBuilder.php:281
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\trim
‪string trim(string $fieldName, int $position=AbstractPlatform::TRIM_UNSPECIFIED, string $char=null)
Definition: ExpressionBuilder.php:513
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\comparison
‪string comparison($leftExpression, string $operator, $rightExpression)
Definition: ExpressionBuilder.php:96