‪TYPO3CMS  ‪main
Typo3DbQueryParser.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\ArrayParameterType;
21 use Doctrine\DBAL\ParameterType;
22 use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
23 use Doctrine\DBAL\Types\Type;
24 use Psr\Http\Message\ServerRequestInterface;
25 use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
26 use TYPO3\CMS\Backend\Utility\BackendUtility;
33 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
65 
70 #[Autoconfigure(public: true, shared: false)]
72 {
74 
80  protected ‪$pageRepository;
81 
87  protected ‪$queryBuilder;
88 
97  protected ‪$tablePropertyMap = [];
98 
105  protected $tableAliasMap = [];
106 
112  protected $unionTableAliasCache = [];
113 
117  protected $tableName = '';
118 
122  protected $suggestDistinctQuery = false;
123 
124  public function __construct(‪DataMapper ‪$dataMapper)
125  {
126  $this->‪dataMapper = ‪$dataMapper;
127  }
128 
134  public function ‪isDistinctQuerySuggested(): bool
135  {
136  return $this->suggestDistinctQuery;
137  }
138 
145  {
146  // Reset all properties
147  $this->tablePropertyMap = [];
148  $this->tableAliasMap = [];
149  $this->unionTableAliasCache = [];
150  $this->tableName = '';
151 
152  if ($query->‪getStatement() && $query->‪getStatement()->getStatement() instanceof QueryBuilder) {
153  $this->queryBuilder = clone $query->‪getStatement()->getStatement();
154  return ‪$this->queryBuilder;
155  }
156  // Find the right table name
157  $source = $query->‪getSource();
158  $this->‪initializeQueryBuilder($source);
159 
160  $constraint = $query->‪getConstraint();
161  if ($constraint instanceof ‪ConstraintInterface) {
162  $wherePredicates = $this->‪parseConstraint($constraint, $source);
163  if (!empty($wherePredicates)) {
164  $this->queryBuilder->andWhere($wherePredicates);
165  }
166  }
167 
168  $this->‪parseOrderings($query->‪getOrderings(), $source);
169  $this->‪addTypo3Constraints($query);
170 
171  return ‪$this->queryBuilder;
172  }
173 
179  protected function ‪initializeQueryBuilder(‪SourceInterface $source)
180  {
181  if ($source instanceof ‪SelectorInterface) {
182  $className = $source->getNodeTypeName();
183  $tableName = $this->‪dataMapper->getDataMap($className)->getTableName();
184  $this->tableName = $tableName;
185 
186  $this->queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
187  ->getQueryBuilderForTable($tableName);
188 
189  $this->queryBuilder
190  ->getRestrictions()
191  ->removeAll();
192 
193  $tableAlias = $this->‪getUniqueAlias($tableName);
194 
195  $this->queryBuilder
196  ->select($tableAlias . '.*')
197  ->from($tableName, $tableAlias);
198 
199  $this->‪addRecordTypeConstraint($className);
200  } elseif ($source instanceof JoinInterface) {
201  $leftSource = $source->getLeft();
202  $leftTableName = $leftSource->getSelectorName();
203 
204  $this->queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
205  ->getQueryBuilderForTable($leftTableName);
206  $leftTableAlias = $this->‪getUniqueAlias($leftTableName);
207  $this->queryBuilder
208  ->select($leftTableAlias . '.*')
209  ->from($leftTableName, $leftTableAlias);
210  $this->‪parseJoin($source, $leftTableAlias);
211  }
212  }
213 
222  protected function ‪parseConstraint(ConstraintInterface $constraint, SourceInterface $source)
223  {
224  if ($constraint instanceof AndInterface) {
225  return $this->queryBuilder->expr()->‪and(
226  $this->‪parseConstraint($constraint->getConstraint1(), $source),
227  $this->parseConstraint($constraint->getConstraint2(), $source)
228  );
229  }
230  if ($constraint instanceof OrInterface) {
231  return $this->queryBuilder->expr()->or(
232  $this->‪parseConstraint($constraint->getConstraint1(), $source),
233  $this->parseConstraint($constraint->getConstraint2(), $source)
234  );
235  }
236  if ($constraint instanceof NotInterface) {
237  return ' NOT(' . $this->‪parseConstraint($constraint->getConstraint(), $source) . ')';
238  }
239  if ($constraint instanceof ComparisonInterface) {
240  return $this->‪parseComparison($constraint, $source);
241  }
242  throw new \RuntimeException('not implemented', 1476199898);
243  }
244 
252  protected function ‪parseOrderings(array $orderings, SourceInterface $source)
253  {
254  foreach ($orderings as $propertyName => $order) {
256  throw new UnsupportedOrderException('Unsupported order encountered.', 1242816074);
257  }
258  $className = null;
259  $tableName = '';
260  if ($source instanceof SelectorInterface) {
261  $className = $source->getNodeTypeName();
262  $tableName = $this->‪dataMapper->convertClassNameToTableName($className);
263  $fullPropertyPath = '';
264  while (str_contains($propertyName, '.')) {
265  $this->‪addUnionStatement($className, $tableName, $propertyName, $fullPropertyPath);
266  }
267  } elseif ($source instanceof JoinInterface) {
268  $tableName = $source->getLeft()->getSelectorName();
269  }
270  $columnName = $this->‪dataMapper->convertPropertyNameToColumnName($propertyName, $className);
271  if ($tableName !== '') {
272  $this->queryBuilder->addOrderBy($tableName . '.' . $columnName, $order);
273  } else {
274  $this->queryBuilder->addOrderBy($columnName, $order);
275  }
276  }
277  }
278 
282  protected function ‪addTypo3Constraints(‪QueryInterface $query)
283  {
284  $index = 0;
285  foreach ($this->tableAliasMap as $tableAlias => $tableName) {
286  if ($index === 0) {
287  // We only add the pid and language check for the first table (aggregate root).
288  // We know the first table is always the main table for the current query run.
289  $additionalWhereClauses = $this->‪getAdditionalWhereClause($query->‪getQuerySettings(), $tableName, $tableAlias);
290  } else {
291  $additionalWhereClauses = [];
292  }
293  $index++;
294  $statement = $this->‪getVisibilityConstraintStatement($query->‪getQuerySettings(), $tableName, $tableAlias);
295  if ($statement !== '') {
296  $additionalWhereClauses[] = $statement;
297  }
298  if (!empty($additionalWhereClauses)) {
299  if (in_array($tableAlias, $this->unionTableAliasCache, true)) {
300  $this->queryBuilder->andWhere(
301  $this->queryBuilder->expr()->or(
302  $this->queryBuilder->expr()->and(...$additionalWhereClauses),
303  $this->queryBuilder->expr()->isNull($tableAlias . '.uid')
304  )
305  );
306  } else {
307  $this->queryBuilder->andWhere(...$additionalWhereClauses);
308  }
309  }
310  }
311  }
312 
323  protected function ‪parseComparison(ComparisonInterface $comparison, SourceInterface $source)
324  {
325  if ($comparison->getOperator() === ‪QueryInterface::OPERATOR_CONTAINS) {
326  if ($comparison->getOperand2() === null) {
327  throw new BadConstraintException('The value for the CONTAINS operator must not be null.', 1484828468);
328  }
329  $value = $this->‪dataMapper->getPlainValue($comparison->getOperand2());
330  if (!$source instanceof SelectorInterface) {
331  throw new \RuntimeException('Source is not of type "SelectorInterface"', 1395362539);
332  }
333  $className = $source->getNodeTypeName();
334  $tableName = $this->‪dataMapper->convertClassNameToTableName($className);
335  $operand1 = $comparison->getOperand1();
336  $propertyName = $operand1->getPropertyName();
337  $fullPropertyPath = '';
338  while (str_contains($propertyName, '.')) {
339  $this->‪addUnionStatement($className, $tableName, $propertyName, $fullPropertyPath);
340  }
341  $columnName = $this->‪dataMapper->convertPropertyNameToColumnName($propertyName, $className);
342  $dataMap = $this->‪dataMapper->getDataMap($className);
343  $columnMap = $dataMap->getColumnMap($propertyName);
344  $typeOfRelation = $columnMap instanceof ColumnMap ? $columnMap->getTypeOfRelation() : null;
345  if ($typeOfRelation === Relation::HAS_AND_BELONGS_TO_MANY) {
347  $relationTableName = (string)$columnMap->getRelationTableName();
348  $queryBuilderForSubselect = $this->queryBuilder->getConnection()->createQueryBuilder();
349  $queryBuilderForSubselect
350  ->select($columnMap->getParentKeyFieldName())
351  ->from($relationTableName)
352  ->where(
353  $queryBuilderForSubselect->expr()->eq(
354  $columnMap->getChildKeyFieldName(),
355  $this->queryBuilder->createNamedParameter($value)
356  )
357  );
358  $additionalWhereForMatchFields = $this->‪getAdditionalMatchFieldsStatement($queryBuilderForSubselect->expr(), $columnMap, $relationTableName, $relationTableName);
359  if ($additionalWhereForMatchFields) {
360  $queryBuilderForSubselect->andWhere($additionalWhereForMatchFields);
361  }
362 
363  return $this->queryBuilder->expr()->comparison(
364  $this->queryBuilder->quoteIdentifier($tableName . '.uid'),
365  'IN',
366  '(' . $queryBuilderForSubselect->getSQL() . ')'
367  );
368  }
369  if ($typeOfRelation === Relation::HAS_MANY) {
370  $parentKeyFieldName = $columnMap->getParentKeyFieldName();
371  if (isset($parentKeyFieldName)) {
372  $childTableName = $columnMap->getChildTableName();
373 
374  // Build the SQL statement of the subselect
375  $queryBuilderForSubselect = $this->queryBuilder->getConnection()->createQueryBuilder();
376  $queryBuilderForSubselect
377  ->select($parentKeyFieldName)
378  ->from($childTableName)
379  ->where(
380  $queryBuilderForSubselect->expr()->eq(
381  'uid',
382  (int)$value
383  )
384  );
385 
386  // Add it to the main query
387  return $this->queryBuilder->expr()->eq(
388  $tableName . '.uid',
389  '(' . $queryBuilderForSubselect->getSQL() . ')'
390  );
391  }
392  return $this->queryBuilder->expr()->inSet(
393  $tableName . '.' . $columnName,
394  $this->queryBuilder->quote((string)$value)
395  );
396  }
397  throw new RepositoryException('Unsupported or non-existing property name "' . $propertyName . '" used in relation matching.', 1327065745);
398  }
399  return $this->‪parseDynamicOperand($comparison, $source);
400  }
401 
410  protected function ‪parseDynamicOperand(ComparisonInterface $comparison, SourceInterface $source)
411  {
412  $value = $comparison->getOperand2();
413  $fieldName = $this->‪parseOperand($comparison->getOperand1(), $source);
414  $exprBuilder = $this->queryBuilder->expr();
415  switch ($comparison->getOperator()) {
417  $hasValue = false;
418  $plainValues = [];
419  foreach ($value as $singleValue) {
420  $plainValue = $this->‪dataMapper->getPlainValue($singleValue);
421  if ($plainValue !== null) {
422  $hasValue = true;
423  $plainValues[] = $this->‪createTypedNamedParameter($singleValue);
424  }
425  }
426  if (!$hasValue) {
427  throw new BadConstraintException(
428  'The IN operator needs a non-empty value list to compare against. ' .
429  'The given value list is empty.',
430  1484828466
431  );
432  }
433  $expr = $exprBuilder->comparison($fieldName, 'IN', '(' . implode(', ', $plainValues) . ')');
434  break;
436  if ($value === null) {
437  $expr = $fieldName . ' IS NULL';
438  } else {
439  $placeHolder = $this->‪createTypedNamedParameter($value);
440  $expr = $exprBuilder->comparison($fieldName, $exprBuilder::EQ, $placeHolder);
441  }
442  break;
444  $expr = $fieldName . ' IS NULL';
445  break;
447  if ($value === null) {
448  $expr = $fieldName . ' IS NOT NULL';
449  } else {
450  $placeHolder = $this->‪createTypedNamedParameter($value);
451  $expr = $exprBuilder->comparison($fieldName, $exprBuilder::NEQ, $placeHolder);
452  }
453  break;
455  $expr = $fieldName . ' IS NOT NULL';
456  break;
458  $placeHolder = $this->‪createTypedNamedParameter($value);
459  $expr = $exprBuilder->comparison($fieldName, $exprBuilder::LT, $placeHolder);
460  break;
462  $placeHolder = $this->‪createTypedNamedParameter($value);
463  $expr = $exprBuilder->comparison($fieldName, $exprBuilder::LTE, $placeHolder);
464  break;
466  $placeHolder = $this->‪createTypedNamedParameter($value);
467  $expr = $exprBuilder->comparison($fieldName, $exprBuilder::GT, $placeHolder);
468  break;
470  $placeHolder = $this->‪createTypedNamedParameter($value);
471  $expr = $exprBuilder->comparison($fieldName, $exprBuilder::GTE, $placeHolder);
472  break;
474  $placeHolder = $this->‪createTypedNamedParameter($value, ‪Connection::PARAM_STR);
475  if ($this->queryBuilder->getConnection()->getDatabasePlatform() instanceof PostgreSQLPlatform) {
476  $expr = $exprBuilder->comparison($fieldName, 'ILIKE', $placeHolder);
477  } else {
478  $expr = $exprBuilder->comparison($fieldName, 'LIKE', $placeHolder);
479  }
480  break;
481  default:
482  throw new Exception(
483  'Unsupported operator encountered.',
484  1242816073
485  );
486  }
487  return $expr;
488  }
489 
494  protected function ‪getParameterType(mixed $value): ParameterType
495  {
496  $parameterType = gettype($value);
497  switch ($parameterType) {
498  case 'integer':
500  case 'string':
502  default:
503  throw new \InvalidArgumentException(
504  'Unsupported parameter type encountered. Expected integer or string, ' . $parameterType . ' given.',
505  1494878863
506  );
507  }
508  }
509 
520  protected function ‪createTypedNamedParameter(mixed $value, ParameterType|Type|ArrayParameterType|null $forceType = null): string
521  {
522  if ($value instanceof ‪DomainObjectInterface
524  && $value->_getProperty(‪AbstractDomainObject::PROPERTY_LOCALIZED_UID) > 0
525  ) {
526  $plainValue = (int)$value->_getProperty(‪AbstractDomainObject::PROPERTY_LOCALIZED_UID);
527  } else {
528  $plainValue = $this->‪dataMapper->getPlainValue($value);
529  }
530  $parameterType = $forceType ?? $this->‪getParameterType($plainValue);
531  $placeholder = $this->queryBuilder->createNamedParameter($plainValue, $parameterType);
532 
533  return $placeholder;
534  }
535 
541  protected function ‪parseOperand(‪DynamicOperandInterface $operand, ‪SourceInterface $source)
542  {
543  $tableName = null;
544  if ($operand instanceof ‪LowerCaseInterface) {
545  $constraintSQL = 'LOWER(' . $this->‪parseOperand($operand->getOperand(), $source) . ')';
546  } elseif ($operand instanceof UpperCaseInterface) {
547  $constraintSQL = 'UPPER(' . $this->‪parseOperand($operand->getOperand(), $source) . ')';
548  } elseif ($operand instanceof PropertyValueInterface) {
549  $propertyName = $operand->getPropertyName();
550  $className = '';
551  if ($source instanceof SelectorInterface) {
552  $className = $source->getNodeTypeName();
553  $tableName = $this->‪dataMapper->convertClassNameToTableName($className);
554  $fullPropertyPath = '';
555  while (str_contains($propertyName, '.')) {
556  $this->‪addUnionStatement($className, $tableName, $propertyName, $fullPropertyPath);
557  }
558  } elseif ($source instanceof JoinInterface) {
559  $tableName = $source->getJoinCondition()->getSelector1Name();
560  }
561  $columnName = $this->‪dataMapper->convertPropertyNameToColumnName($propertyName, $className);
562  $constraintSQL = (!empty($tableName) ? $tableName . '.' : '') . $columnName;
563  $constraintSQL = $this->queryBuilder->getConnection()->quoteIdentifier($constraintSQL);
564  } else {
565  throw new \InvalidArgumentException('Given operand has invalid type "' . get_class($operand) . '".', 1395710211);
566  }
567  return $constraintSQL;
568  }
569 
575  protected function ‪addRecordTypeConstraint($className)
576  {
577  if ($className !== null) {
578  $dataMap = $this->‪dataMapper->getDataMap($className);
579  if ($dataMap->getRecordTypeColumnName() !== null) {
580  $recordTypes = [];
581  if ($dataMap->getRecordType() !== null) {
582  $recordTypes[] = $dataMap->getRecordType();
583  }
584  foreach ($dataMap->getSubclasses() as $subclassName) {
585  $subclassDataMap = $this->‪dataMapper->getDataMap($subclassName);
586  if ($subclassDataMap->getRecordType() !== null) {
587  $recordTypes[] = $subclassDataMap->getRecordType();
588  }
589  }
590  if (!empty($recordTypes)) {
591  $recordTypeStatements = [];
592  foreach ($recordTypes as $recordType) {
593  $tableName = $dataMap->getTableName();
594  $recordTypeStatements[] = $this->queryBuilder->expr()->eq(
595  $tableName . '.' . $dataMap->getRecordTypeColumnName(),
596  $this->queryBuilder->createNamedParameter($recordType)
597  );
598  }
599  $this->queryBuilder->andWhere(
600  $this->queryBuilder->expr()->or(...$recordTypeStatements)
601  );
602  }
603  }
604  }
605  }
606 
617  protected function ‪getAdditionalMatchFieldsStatement($exprBuilder, $columnMap, $childTableAlias, $parentTable = null)
618  {
619  $additionalWhereForMatchFields = [];
620  $relationTableMatchFields = $columnMap->getRelationTableMatchFields();
621  if (is_array($relationTableMatchFields) && !empty($relationTableMatchFields)) {
622  foreach ($relationTableMatchFields as $fieldName => $value) {
623  $additionalWhereForMatchFields[] = $exprBuilder->eq($childTableAlias . '.' . $fieldName, $this->queryBuilder->createNamedParameter($value));
624  }
625  }
626 
627  if (isset($parentTable)) {
628  $parentTableFieldName = $columnMap->getParentTableFieldName();
629  if (!empty($parentTableFieldName)) {
630  $additionalWhereForMatchFields[] = $exprBuilder->eq($childTableAlias . '.' . $parentTableFieldName, $this->queryBuilder->createNamedParameter($parentTable));
631  }
632  }
633 
634  if (!empty($additionalWhereForMatchFields)) {
635  return $exprBuilder->‪and(...$additionalWhereForMatchFields);
636  }
637  return '';
638  }
639 
648  protected function ‪getAdditionalWhereClause(QuerySettingsInterface $querySettings, $tableName, $tableAlias = null)
649  {
650  $tableAlias = (string)$tableAlias;
651  // todo: $tableAlias must not be null
652 
653  $whereClause = [];
654  if ($querySettings->getRespectSysLanguage()) {
655  $systemLanguageStatement = $this->‪getLanguageStatement($tableName, $tableAlias, $querySettings);
656  if (!empty($systemLanguageStatement)) {
657  $whereClause[] = $systemLanguageStatement;
658  }
659  }
660 
661  if ($querySettings->getRespectStoragePage()) {
662  $pageIdStatement = $this->‪getPageIdStatement($tableName, $tableAlias, $querySettings->getStoragePageIds());
663  if (!empty($pageIdStatement)) {
664  $whereClause[] = $pageIdStatement;
665  }
666  }
667  if (!empty(‪$GLOBALS['TCA'][$tableName]['ctrl']['versioningWS'])) {
668  // Always prevent workspace records from being returned (except for newly created records)
669  $whereClause[] = $this->queryBuilder->expr()->eq($tableAlias . '.t3ver_oid', 0);
670  }
671 
672  return $whereClause;
673  }
674 
682  protected function ‪getVisibilityConstraintStatement(QuerySettingsInterface $querySettings, $tableName, $tableAlias)
683  {
684  if (!is_array(‪$GLOBALS['TCA'][$tableName]['ctrl'] ?? null)) {
685  return '';
686  }
687 
688  $ignoreEnableFields = $querySettings->getIgnoreEnableFields();
689  $enableFieldsToBeIgnored = $querySettings->getEnableFieldsToBeIgnored();
690  $includeDeleted = $querySettings->getIncludeDeleted();
691  if ((‪$GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface
692  && ‪ApplicationType::fromRequest(‪$GLOBALS['TYPO3_REQUEST'])->isFrontend()
693  ) {
694  $statement = $this->‪getFrontendConstraintStatement($tableName, $tableAlias, $ignoreEnableFields, $enableFieldsToBeIgnored, $includeDeleted);
695  } else {
696  // applicationType backend
697  $statement = $this->‪getBackendConstraintStatement($tableName, $ignoreEnableFields, $includeDeleted);
698  if (!empty($statement)) {
699  $statement = $this->‪replaceTableNameWithAlias($statement, $tableName, $tableAlias);
700  $statement = strtolower(substr($statement, 1, 3)) === 'and' ? substr($statement, 5) : $statement;
701  }
702  }
703  return $statement;
704  }
705 
714  protected function ‪getFrontendConstraintStatement(string $tableName, string $tableAlias, bool $ignoreEnableFields, array $enableFieldsToBeIgnored, bool $includeDeleted): string
715  {
716  $statement = '';
717  if ($ignoreEnableFields && !$includeDeleted) {
718  if (!empty($enableFieldsToBeIgnored)) {
719  $constraints = $this->‪getPageRepository()->‪getDefaultConstraints($tableName, $enableFieldsToBeIgnored, $tableAlias);
720  if ($constraints !== []) {
721  $statement = implode(' AND ', $constraints);
722  }
723  } elseif (!empty(‪$GLOBALS['TCA'][$tableName]['ctrl']['delete'])) {
724  $statement = $tableAlias . '.' . ‪$GLOBALS['TCA'][$tableName]['ctrl']['delete'] . '=0';
725  }
726  } elseif (!$ignoreEnableFields && !$includeDeleted) {
727  $constraints = $this->‪getPageRepository()->‪getDefaultConstraints($tableName, [], $tableAlias);
728  if ($constraints !== []) {
729  $statement = implode(' AND ', $constraints);
730  }
731  } elseif (!$ignoreEnableFields) {
732  throw new InconsistentQuerySettingsException('Query setting "ignoreEnableFields=FALSE" can not be used together with "includeDeleted=TRUE" in frontend context.', 1460975922);
733  }
734  return $statement;
735  }
736 
745  protected function ‪getBackendConstraintStatement($tableName, $ignoreEnableFields, $includeDeleted)
746  {
747  $statement = '';
748  // In case of versioning-preview, enableFields are ignored (checked in Typo3DbBackend::doLanguageAndWorkspaceOverlay)
749  $isUserInWorkspace = GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('workspace', 'isOffline');
750  if (!$ignoreEnableFields && !$isUserInWorkspace) {
751  $statement .= BackendUtility::BEenableFields($tableName);
752  }
753  if (!$includeDeleted && !empty(‪$GLOBALS['TCA'][$tableName]['ctrl']['delete'])) {
754  $statement .= ' AND ' . $tableName . '.' . ‪$GLOBALS['TCA'][$tableName]['ctrl']['delete'] . '=0';
755  }
756  return $statement;
757  }
758 
767  protected function ‪getLanguageStatement($tableName, $tableAlias, QuerySettingsInterface $querySettings)
768  {
769  if (empty(‪$GLOBALS['TCA'][$tableName]['ctrl']['languageField'])) {
770  return '';
771  }
772 
773  // Select all entries for the current language
774  // If any language is set -> get those entries which are not translated yet
775  // They will be removed by \TYPO3\CMS\Core\Domain\Repository\PageRepository::getRecordOverlay if not matching overlay mode
776  $languageField = ‪$GLOBALS['TCA'][$tableName]['ctrl']['languageField'];
777 
778  $languageAspect = $querySettings->getLanguageAspect();
779 
780  $transOrigPointerField = ‪$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] ?? '';
781  if (!$transOrigPointerField || !$languageAspect->getContentId()) {
782  return $this->queryBuilder->expr()->in(
783  $tableAlias . '.' . $languageField,
784  [$languageAspect->getContentId(), -1]
785  );
786  }
787 
788  if (!$languageAspect->doOverlays()) {
789  return $this->queryBuilder->expr()->in(
790  $tableAlias . '.' . $languageField,
791  [$languageAspect->getContentId(), -1]
792  );
793  }
794 
795  $defLangTableAlias = $tableAlias . '_dl';
796  $defaultLanguageRecordsSubSelect = $this->queryBuilder->getConnection()->createQueryBuilder();
797  $defaultLanguageRecordsSubSelect
798  ->select($defLangTableAlias . '.uid')
799  ->from($tableName, $defLangTableAlias)
800  ->where(
801  $defaultLanguageRecordsSubSelect->expr()->and(
802  $defaultLanguageRecordsSubSelect->expr()->eq($defLangTableAlias . '.' . $transOrigPointerField, 0),
803  $defaultLanguageRecordsSubSelect->expr()->eq($defLangTableAlias . '.' . $languageField, 0)
804  )
805  );
806 
807  $andConditions = [];
808  // records in language 'all'
809  $andConditions[] = $this->queryBuilder->expr()->eq($tableAlias . '.' . $languageField, -1);
810  // translated records where a default language exists
811  $andConditions[] = $this->queryBuilder->expr()->and(
812  $this->queryBuilder->expr()->eq($tableAlias . '.' . $languageField, $languageAspect->getContentId()),
813  $this->queryBuilder->expr()->in(
814  $tableAlias . '.' . $transOrigPointerField,
815  $defaultLanguageRecordsSubSelect->getSQL()
816  )
817  );
818  // Records in translation with no default language
819  if ($languageAspect->getOverlayType() === ‪LanguageAspect::OVERLAYS_ON_WITH_FLOATING) {
820  $andConditions[] = $this->queryBuilder->expr()->and(
821  $this->queryBuilder->expr()->eq($tableAlias . '.' . $languageField, $languageAspect->getContentId()),
822  $this->queryBuilder->expr()->eq($tableAlias . '.' . $transOrigPointerField, 0),
823  $this->queryBuilder->expr()->notIn(
824  $tableAlias . '.' . $transOrigPointerField,
825  $defaultLanguageRecordsSubSelect->getSQL()
826  )
827  );
828  }
829  if ($languageAspect->getOverlayType() === ‪LanguageAspect::OVERLAYS_MIXED) {
830  // returns records from current language which have a default language
831  // together with not translated default language records
832  $translatedOnlyTableAlias = $tableAlias . '_to';
833  $queryBuilderForSubselect = $this->queryBuilder->getConnection()->createQueryBuilder();
834  $queryBuilderForSubselect
835  ->select($translatedOnlyTableAlias . '.' . $transOrigPointerField)
836  ->from($tableName, $translatedOnlyTableAlias)
837  ->where(
838  $queryBuilderForSubselect->expr()->and(
839  $queryBuilderForSubselect->expr()->gt($translatedOnlyTableAlias . '.' . $transOrigPointerField, 0),
840  $queryBuilderForSubselect->expr()->eq($translatedOnlyTableAlias . '.' . $languageField, $languageAspect->getContentId())
841  )
842  );
843  // records in default language, which do not have a translation
844  $andConditions[] = $this->queryBuilder->expr()->and(
845  $this->queryBuilder->expr()->eq($tableAlias . '.' . $languageField, 0),
846  $this->queryBuilder->expr()->notIn(
847  $tableAlias . '.uid',
848  $queryBuilderForSubselect->getSQL()
849  )
850  );
851  }
852 
853  return $this->queryBuilder->expr()->or(...$andConditions);
854  }
855 
865  protected function ‪getPageIdStatement($tableName, $tableAlias, array $storagePageIds)
866  {
867  if (!is_array(‪$GLOBALS['TCA'][$tableName]['ctrl'] ?? null)) {
868  return '';
869  }
870 
871  $rootLevel = (int)(‪$GLOBALS['TCA'][$tableName]['ctrl']['rootLevel'] ?? 0);
872  switch ($rootLevel) {
873  // Only in pid 0
874  case 1:
875  $storagePageIds = [0];
876  break;
877  // Pid 0 and pagetree
878  case -1:
879  if (empty($storagePageIds)) {
880  $storagePageIds = [0];
881  } else {
882  $storagePageIds[] = 0;
883  }
884  break;
885  // Only pagetree or not set
886  case 0:
887  if (empty($storagePageIds)) {
888  throw new InconsistentQuerySettingsException('Missing storage page ids.', 1365779762);
889  }
890  break;
891  // Invalid configuration
892  default:
893  return '';
894  }
895  $storagePageIds = array_map(intval(...), $storagePageIds);
896  if (count($storagePageIds) === 1) {
897  return $this->queryBuilder->expr()->eq($tableAlias . '.pid', reset($storagePageIds));
898  }
899  return $this->queryBuilder->expr()->in($tableAlias . '.pid', $storagePageIds);
900  }
901 
908  protected function ‪parseJoin(‪JoinInterface $join, $leftTableAlias)
909  {
910  $leftSource = $join->‪getLeft();
911  $leftClassName = $leftSource->‪getNodeTypeName();
912  $this->‪addRecordTypeConstraint($leftClassName);
913  $rightSource = $join->‪getRight();
914  if ($rightSource instanceof ‪JoinInterface) {
915  $left = $rightSource->getLeft();
916  $rightClassName = $left->‪getNodeTypeName();
917  $rightTableName = $left->getSelectorName();
918  } else {
919  $rightClassName = $rightSource->getNodeTypeName();
920  $rightTableName = $rightSource->getSelectorName();
921  $this->queryBuilder->addSelect($rightTableName . '.*');
922  }
923  $this->‪addRecordTypeConstraint($rightClassName);
924  $rightTableAlias = $this->‪getUniqueAlias($rightTableName);
925  $joinCondition = $join->‪getJoinCondition();
926  $joinConditionExpression = null;
927  if ($joinCondition instanceof ‪EquiJoinCondition) {
928  $column1Name = $this->‪dataMapper->convertPropertyNameToColumnName($joinCondition->getProperty1Name(), $leftClassName);
929  $column2Name = $this->‪dataMapper->convertPropertyNameToColumnName($joinCondition->getProperty2Name(), $rightClassName);
930 
931  $joinConditionExpression = $this->queryBuilder->expr()->eq(
932  $leftTableAlias . '.' . $column1Name,
933  $this->queryBuilder->quoteIdentifier($rightTableAlias . '.' . $column2Name)
934  );
935  }
936  $this->queryBuilder->leftJoin($leftTableAlias, $rightTableName, $rightTableAlias, $joinConditionExpression);
937  if ($rightSource instanceof ‪JoinInterface) {
938  $this->‪parseJoin($rightSource, $rightTableAlias);
939  }
940  }
941 
950  protected function ‪getUniqueAlias($tableName, $fullPropertyPath = null)
951  {
952  if (isset($fullPropertyPath) && isset($this->tablePropertyMap[$fullPropertyPath])) {
953  return $this->tablePropertyMap[$fullPropertyPath];
954  }
955 
956  $alias = $tableName;
957  $i = 0;
958  while (isset($this->tableAliasMap[$alias])) {
959  $alias = $tableName . $i;
960  $i++;
961  }
962 
963  $this->tableAliasMap[$alias] = $tableName;
964 
965  if (isset($fullPropertyPath)) {
966  $this->tablePropertyMap[$fullPropertyPath] = $alias;
967  }
968 
969  return $alias;
970  }
971 
984  protected function ‪addUnionStatement(&$className, &$tableName, &$propertyPath, &$fullPropertyPath)
985  {
986  $explodedPropertyPath = explode('.', $propertyPath, 2);
987  $propertyName = $explodedPropertyPath[0];
988  $columnName = $this->‪dataMapper->convertPropertyNameToColumnName($propertyName, $className);
989  $realTableName = $this->‪dataMapper->convertClassNameToTableName($className);
990  $tableName = $this->tablePropertyMap[$fullPropertyPath] ?? $realTableName;
991  $columnMap = $this->‪dataMapper->getDataMap($className)->getColumnMap($propertyName);
992 
993  if ($columnMap === null) {
994  throw new MissingColumnMapException('The ColumnMap for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1355142232);
995  }
996 
997  $parentKeyFieldName = $columnMap->getParentKeyFieldName();
998  $childTableName = $columnMap->getChildTableName();
999 
1000  if ($childTableName === null) {
1001  throw new InvalidRelationConfigurationException('The relation information for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1353170925);
1002  }
1003 
1004  $fullPropertyPath .= ($fullPropertyPath === '') ? $propertyName : '.' . $propertyName;
1005  $childTableAlias = $this->‪getUniqueAlias($childTableName, $fullPropertyPath);
1006 
1007  // If there is already a union with the current identifier we do not need to build it again and exit early.
1008  if (in_array($childTableAlias, $this->unionTableAliasCache, true)) {
1009  $propertyPath = $explodedPropertyPath[1];
1010  $tableName = $childTableAlias;
1011  $className = $this->‪dataMapper->getType($className, $propertyName);
1012  return;
1013  }
1014 
1015  if ($columnMap->getTypeOfRelation() === Relation::HAS_ONE) {
1016  if (isset($parentKeyFieldName)) {
1017  // @todo: no test for this part yet
1018  $basicJoinCondition = $this->queryBuilder->expr()->eq(
1019  $tableName . '.uid',
1020  $this->queryBuilder->quoteIdentifier($childTableAlias . '.' . $parentKeyFieldName)
1021  );
1022  } else {
1023  $basicJoinCondition = $this->queryBuilder->expr()->eq(
1024  $tableName . '.' . $columnName,
1025  $this->queryBuilder->quoteIdentifier($childTableAlias . '.uid')
1026  );
1027  }
1028  $joinConditionExpression = $this->queryBuilder->expr()->and(
1029  $basicJoinCondition,
1030  $this->‪getAdditionalMatchFieldsStatement($this->queryBuilder->expr(), $columnMap, $childTableAlias, $realTableName)
1031  );
1032  $this->queryBuilder->leftJoin($tableName, $childTableName, $childTableAlias, (string)$joinConditionExpression);
1033  $this->unionTableAliasCache[] = $childTableAlias;
1034  } elseif ($columnMap->getTypeOfRelation() === Relation::HAS_MANY) {
1035  if (isset($parentKeyFieldName)) {
1036  $basicJoinCondition = $this->queryBuilder->expr()->eq(
1037  $tableName . '.uid',
1038  $this->queryBuilder->quoteIdentifier($childTableAlias . '.' . $parentKeyFieldName)
1039  );
1040  } else {
1041  $basicJoinCondition = $this->queryBuilder->expr()->inSet(
1042  $tableName . '.' . $columnName,
1043  $this->queryBuilder->quoteIdentifier($childTableAlias . '.uid'),
1044  true
1045  );
1046  }
1047  $joinConditionExpression = $this->queryBuilder->expr()->and(
1048  $basicJoinCondition,
1049  $this->‪getAdditionalMatchFieldsStatement($this->queryBuilder->expr(), $columnMap, $childTableAlias, $realTableName)
1050  );
1051  $this->queryBuilder->leftJoin($tableName, $childTableName, $childTableAlias, (string)$joinConditionExpression);
1052  $this->unionTableAliasCache[] = $childTableAlias;
1053  $this->suggestDistinctQuery = true;
1054  } elseif ($columnMap->getTypeOfRelation() === Relation::HAS_AND_BELONGS_TO_MANY) {
1055  $relationTableName = (string)$columnMap->getRelationTableName();
1056  $relationTableAlias = $this->‪getUniqueAlias($relationTableName, $fullPropertyPath . '_mm');
1057 
1058  $joinConditionExpression = $this->queryBuilder->expr()->and(
1059  $this->queryBuilder->expr()->eq(
1060  $tableName . '.uid',
1061  $this->queryBuilder->quoteIdentifier(
1062  $relationTableAlias . '.' . $columnMap->getParentKeyFieldName()
1063  )
1064  ),
1065  $this->getAdditionalMatchFieldsStatement($this->queryBuilder->expr(), $columnMap, $relationTableAlias, $realTableName)
1066  );
1067  $this->queryBuilder->leftJoin($tableName, $relationTableName, $relationTableAlias, (string)$joinConditionExpression);
1068  $joinConditionExpression = $this->queryBuilder->expr()->eq(
1069  $relationTableAlias . '.' . $columnMap->getChildKeyFieldName(),
1070  $this->queryBuilder->quoteIdentifier($childTableAlias . '.uid')
1071  );
1072  $this->queryBuilder->leftJoin($relationTableAlias, $childTableName, $childTableAlias, $joinConditionExpression);
1073  $this->unionTableAliasCache[] = $childTableAlias;
1074  $this->suggestDistinctQuery = true;
1075  } else {
1076  throw new Exception('Could not determine type of relation.', 1252502725);
1077  }
1078  $propertyPath = $explodedPropertyPath[1];
1079  $tableName = $childTableAlias;
1080  $className = $this->‪dataMapper->getType($className, $propertyName);
1081  }
1082 
1092  protected function ‪replaceTableNameWithAlias($statement, $tableName, $tableAlias)
1093  {
1094  if ($tableAlias !== $tableName) {
1095  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($tableName);
1096  $quotedTableName = $connection->quoteIdentifier($tableName);
1097  $quotedTableAlias = $connection->quoteIdentifier($tableAlias);
1098  $statement = str_replace(
1099  [$tableName . '.', $quotedTableName . '.'],
1100  [$tableAlias . '.', $quotedTableAlias . '.'],
1101  $statement
1102  );
1103  }
1105  return $statement;
1106  }
1107 
1111  protected function ‪getPageRepository()
1112  {
1113  if (!$this->pageRepository instanceof ‪PageRepository) {
1114  $this->pageRepository = GeneralUtility::makeInstance(PageRepository::class);
1115  }
1116  return ‪$this->pageRepository;
1117  }
1118 }
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\getConstraint
‪ConstraintInterface null getConstraint()
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\JoinInterface\getLeft
‪SelectorInterface getLeft()
‪TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidRelationConfigurationException
Definition: InvalidRelationConfigurationException.php:25
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\initializeQueryBuilder
‪initializeQueryBuilder(SourceInterface $source)
Definition: Typo3DbQueryParser.php:172
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\getLanguageStatement
‪CompositeExpression string getLanguageStatement($tableName, $tableAlias, QuerySettingsInterface $querySettings)
Definition: Typo3DbQueryParser.php:760
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\OPERATOR_LIKE
‪const OPERATOR_LIKE
Definition: QueryInterface.php:74
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\SelectorInterface\getNodeTypeName
‪string getNodeTypeName()
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface\getLanguageAspect
‪getLanguageAspect()
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\OPERATOR_GREATER_THAN_OR_EQUAL_TO
‪const OPERATOR_GREATER_THAN_OR_EQUAL_TO
Definition: QueryInterface.php:69
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface\getStoragePageIds
‪int[] getStoragePageIds()
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:52
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
Definition: ExpressionBuilder.php:40
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\replaceTableNameWithAlias
‪string replaceTableNameWithAlias($statement, $tableName, $tableAlias)
Definition: Typo3DbQueryParser.php:1085
‪TYPO3\CMS\Core\Context\LanguageAspect\OVERLAYS_MIXED
‪const OVERLAYS_MIXED
Definition: LanguageAspect.php:75
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface\getRespectStoragePage
‪bool getRespectStoragePage()
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\OPERATOR_NOT_EQUAL_TO_NULL
‪const OPERATOR_NOT_EQUAL_TO_NULL
Definition: QueryInterface.php:49
‪TYPO3\CMS\Extbase\Persistence\QueryInterface
Definition: QueryInterface.php:30
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\getBackendConstraintStatement
‪string getBackendConstraintStatement($tableName, $ignoreEnableFields, $includeDeleted)
Definition: Typo3DbQueryParser.php:738
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\addRecordTypeConstraint
‪addRecordTypeConstraint($className)
Definition: Typo3DbQueryParser.php:568
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\OPERATOR_GREATER_THAN
‪const OPERATOR_GREATER_THAN
Definition: QueryInterface.php:64
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface\getIncludeDeleted
‪getIncludeDeleted()
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap
Definition: ColumnMap.php:27
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\ORDER_DESCENDING
‪const ORDER_DESCENDING
Definition: QueryInterface.php:100
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\parseOrderings
‪parseOrderings(array $orderings, SourceInterface $source)
Definition: Typo3DbQueryParser.php:245
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\OPERATOR_IN
‪const OPERATOR_IN
Definition: QueryInterface.php:84
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface
Definition: SourceInterface.php:23
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\getParameterType
‪getParameterType(mixed $value)
Definition: Typo3DbQueryParser.php:487
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\$pageRepository
‪PageRepository $pageRepository
Definition: Typo3DbQueryParser.php:79
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\convertQueryToDoctrineQueryBuilder
‪QueryBuilder convertQueryToDoctrineQueryBuilder(QueryInterface $query)
Definition: Typo3DbQueryParser.php:137
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\getQuerySettings
‪QuerySettingsInterface getQuerySettings()
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface\getRespectSysLanguage
‪bool getRespectSysLanguage()
‪TYPO3\CMS\Extbase\Persistence\Generic\Exception\RepositoryException
Definition: RepositoryException.php:24
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper
Definition: DataMapper.php:60
‪TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject\PROPERTY_LOCALIZED_UID
‪const PROPERTY_LOCALIZED_UID
Definition: AbstractDomainObject.php:34
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface\getEnableFieldsToBeIgnored
‪string[] getEnableFieldsToBeIgnored()
‪TYPO3\CMS\Core\Database\Connection\PARAM_STR
‪const PARAM_STR
Definition: Connection.php:57
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\OrInterface
Definition: OrInterface.php:29
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:54
‪TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression\and
‪static and($part=null,... $parts)
Definition: CompositeExpression.php:85
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\OPERATOR_LESS_THAN_OR_EQUAL_TO
‪const OPERATOR_LESS_THAN_OR_EQUAL_TO
Definition: QueryInterface.php:59
‪TYPO3\CMS\Extbase\Exception
Definition: Exception.php:25
‪TYPO3\CMS\Extbase\Persistence\Generic\Exception\InconsistentQuerySettingsException
Definition: InconsistentQuerySettingsException.php:25
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\getUniqueAlias
‪string getUniqueAlias($tableName, $fullPropertyPath=null)
Definition: Typo3DbQueryParser.php:943
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\PropertyValueInterface
Definition: PropertyValueInterface.php:32
‪TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression
Definition: CompositeExpression.php:27
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\getPageIdStatement
‪string getPageIdStatement($tableName, $tableAlias, array $storagePageIds)
Definition: Typo3DbQueryParser.php:858
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\getSource
‪TYPO3 CMS Extbase Persistence Generic Qom SourceInterface getSource()
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\SelectorInterface
Definition: SelectorInterface.php:32
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\ORDER_ASCENDING
‪const ORDER_ASCENDING
Definition: QueryInterface.php:99
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap\getTypeOfRelation
‪getTypeOfRelation()
Definition: ColumnMap.php:127
‪TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface
Definition: DomainObjectInterface.php:33
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\getFrontendConstraintStatement
‪getFrontendConstraintStatement(string $tableName, string $tableAlias, bool $ignoreEnableFields, array $enableFieldsToBeIgnored, bool $includeDeleted)
Definition: Typo3DbQueryParser.php:707
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\getPageRepository
‪PageRepository getPageRepository()
Definition: Typo3DbQueryParser.php:1104
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\parseComparison
‪string parseComparison(ComparisonInterface $comparison, SourceInterface $source)
Definition: Typo3DbQueryParser.php:316
‪TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject
Definition: AbstractDomainObject.php:31
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\OPERATOR_CONTAINS
‪const OPERATOR_CONTAINS
Definition: QueryInterface.php:79
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\getVisibilityConstraintStatement
‪string getVisibilityConstraintStatement(QuerySettingsInterface $querySettings, $tableName, $tableAlias)
Definition: Typo3DbQueryParser.php:675
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\createTypedNamedParameter
‪string createTypedNamedParameter(mixed $value, ParameterType|Type|ArrayParameterType|null $forceType=null)
Definition: Typo3DbQueryParser.php:513
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\getStatement
‪TYPO3 CMS Extbase Persistence Generic Qom Statement getStatement()
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\ComparisonInterface
Definition: ComparisonInterface.php:66
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\$dataMapper
‪DataMapper $dataMapper
Definition: Typo3DbQueryParser.php:73
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\parseConstraint
‪CompositeExpression string parseConstraint(ConstraintInterface $constraint, SourceInterface $source)
Definition: Typo3DbQueryParser.php:215
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\dataMapper
‪array< string, $tableAliasMap=array();protected array $unionTableAliasCache=array();protected string $tableName='';protected bool $suggestDistinctQuery=false;public function __construct(DataMapper $dataMapper) { $this-> dataMapper
Definition: Typo3DbQueryParser.php:119
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage
Definition: BackendInterface.php:18
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\getAdditionalMatchFieldsStatement
‪CompositeExpression string getAdditionalMatchFieldsStatement($exprBuilder, $columnMap, $childTableAlias, $parentTable=null)
Definition: Typo3DbQueryParser.php:610
‪TYPO3\CMS\Extbase\Persistence\Generic\Exception
Definition: InconsistentQuerySettingsException.php:18
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\getOrderings
‪array< string, string > getOrderings()
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\JoinInterface
Definition: JoinInterface.php:24
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\NotInterface
Definition: NotInterface.php:26
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Exception\BadConstraintException
Definition: BadConstraintException.php:25
‪TYPO3\CMS\Core\Context\LanguageAspect
Definition: LanguageAspect.php:57
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface
Definition: QuerySettingsInterface.php:26
‪TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnsupportedOrderException
Definition: UnsupportedOrderException.php:25
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\getAdditionalWhereClause
‪array getAdditionalWhereClause(QuerySettingsInterface $querySettings, $tableName, $tableAlias=null)
Definition: Typo3DbQueryParser.php:641
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\OPERATOR_LESS_THAN
‪const OPERATOR_LESS_THAN
Definition: QueryInterface.php:54
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\$tablePropertyMap
‪array $tablePropertyMap
Definition: Typo3DbQueryParser.php:94
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom
Definition: AndInterface.php:16
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\OPERATOR_EQUAL_TO
‪const OPERATOR_EQUAL_TO
Definition: QueryInterface.php:34
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\isDistinctQuerySuggested
‪isDistinctQuerySuggested()
Definition: Typo3DbQueryParser.php:127
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\getDefaultConstraints
‪CompositeExpression[] getDefaultConstraints(string $table, array $enableFieldsToIgnore=[], ?string $tableAlias=null)
Definition: PageRepository.php:1482
‪TYPO3\CMS\Extbase\Persistence\Generic\Exception\MissingColumnMapException
Definition: MissingColumnMapException.php:25
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\parseDynamicOperand
‪string parseDynamicOperand(ComparisonInterface $comparison, SourceInterface $source)
Definition: Typo3DbQueryParser.php:403
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\UpperCaseInterface
Definition: UpperCaseInterface.php:30
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\ComparisonInterface\getOperand1
‪getOperand1()
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\JoinInterface\getRight
‪SelectorInterface getRight()
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\OPERATOR_NOT_EQUAL_TO
‪const OPERATOR_NOT_EQUAL_TO
Definition: QueryInterface.php:44
‪TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface\getIgnoreEnableFields
‪getIgnoreEnableFields()
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\ConstraintInterface
Definition: ConstraintInterface.php:27
‪TYPO3\CMS\Core\Http\fromRequest
‪@ fromRequest
Definition: ApplicationType.php:66
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\ComparisonInterface\getOperand2
‪mixed getOperand2()
‪TYPO3\CMS\Core\Domain\Repository\PageRepository
Definition: PageRepository.php:69
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\DynamicOperandInterface
Definition: DynamicOperandInterface.php:23
‪TYPO3\CMS\Extbase\Persistence\QueryInterface\OPERATOR_EQUAL_TO_NULL
‪const OPERATOR_EQUAL_TO_NULL
Definition: QueryInterface.php:39
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Context\LanguageAspect\OVERLAYS_ON_WITH_FLOATING
‪const OVERLAYS_ON_WITH_FLOATING
Definition: LanguageAspect.php:77
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\parseOperand
‪string parseOperand(DynamicOperandInterface $operand, SourceInterface $source)
Definition: Typo3DbQueryParser.php:534
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\ComparisonInterface\getOperator
‪QueryInterface::OPERATOR_ * getOperator()
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\addTypo3Constraints
‪addTypo3Constraints(QueryInterface $query)
Definition: Typo3DbQueryParser.php:275
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\EquiJoinCondition
Definition: EquiJoinCondition.php:30
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\parseJoin
‪parseJoin(JoinInterface $join, $leftTableAlias)
Definition: Typo3DbQueryParser.php:901
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\LowerCaseInterface
Definition: LowerCaseInterface.php:30
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\AndInterface
Definition: AndInterface.php:27
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\addUnionStatement
‪addUnionStatement(&$className, &$tableName, &$propertyPath, &$fullPropertyPath)
Definition: Typo3DbQueryParser.php:977
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\$queryBuilder
‪QueryBuilder $queryBuilder
Definition: Typo3DbQueryParser.php:85
‪TYPO3\CMS\Extbase\Persistence\Generic\Qom\JoinInterface\getJoinCondition
‪JoinConditionInterface getJoinCondition()
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap
Definition: Relation.php:18
‪TYPO3\CMS\Core\Http\ApplicationType
‪ApplicationType
Definition: ApplicationType.php:55
‪TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap\Relation
‪Relation
Definition: Relation.php:24
‪TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface\_hasProperty
‪_hasProperty(string $propertyName)
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser
Definition: Typo3DbQueryParser.php:72