‪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\Types\Type;
23 use Psr\Http\Message\ServerRequestInterface;
24 use TYPO3\CMS\Backend\Utility\BackendUtility;
31 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
63 
69 {
71 
77  protected ‪$pageRepository;
78 
84  protected ‪$queryBuilder;
85 
94  protected ‪$tablePropertyMap = [];
95 
102  protected $tableAliasMap = [];
103 
109  protected $unionTableAliasCache = [];
110 
114  protected $tableName = '';
115 
119  protected $suggestDistinctQuery = false;
120 
121  public function __construct(‪DataMapper ‪$dataMapper)
122  {
123  $this->‪dataMapper = ‪$dataMapper;
124  }
125 
131  public function ‪isDistinctQuerySuggested(): bool
132  {
133  return $this->suggestDistinctQuery;
134  }
135 
142  {
143  // Reset all properties
144  $this->tablePropertyMap = [];
145  $this->tableAliasMap = [];
146  $this->unionTableAliasCache = [];
147  $this->tableName = '';
148 
149  if ($query->‪getStatement() && $query->‪getStatement()->getStatement() instanceof QueryBuilder) {
150  $this->queryBuilder = clone $query->‪getStatement()->getStatement();
151  return ‪$this->queryBuilder;
152  }
153  // Find the right table name
154  $source = $query->‪getSource();
155  $this->‪initializeQueryBuilder($source);
156 
157  $constraint = $query->‪getConstraint();
158  if ($constraint instanceof ‪ConstraintInterface) {
159  $wherePredicates = $this->‪parseConstraint($constraint, $source);
160  if (!empty($wherePredicates)) {
161  $this->queryBuilder->andWhere($wherePredicates);
162  }
163  }
164 
165  $this->‪parseOrderings($query->‪getOrderings(), $source);
166  $this->‪addTypo3Constraints($query);
167 
168  return ‪$this->queryBuilder;
169  }
170 
176  protected function ‪initializeQueryBuilder(‪SourceInterface $source)
177  {
178  if ($source instanceof ‪SelectorInterface) {
179  $className = $source->getNodeTypeName();
180  $tableName = $this->‪dataMapper->getDataMap($className)->getTableName();
181  $this->tableName = $tableName;
182 
183  $this->queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
184  ->getQueryBuilderForTable($tableName);
185 
186  $this->queryBuilder
187  ->getRestrictions()
188  ->removeAll();
189 
190  $tableAlias = $this->‪getUniqueAlias($tableName);
191 
192  $this->queryBuilder
193  ->select($tableAlias . '.*')
194  ->from($tableName, $tableAlias);
195 
196  $this->‪addRecordTypeConstraint($className);
197  } elseif ($source instanceof JoinInterface) {
198  $leftSource = $source->getLeft();
199  $leftTableName = $leftSource->getSelectorName();
200 
201  $this->queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
202  ->getQueryBuilderForTable($leftTableName);
203  $leftTableAlias = $this->‪getUniqueAlias($leftTableName);
204  $this->queryBuilder
205  ->select($leftTableAlias . '.*')
206  ->from($leftTableName, $leftTableAlias);
207  $this->‪parseJoin($source, $leftTableAlias);
208  }
209  }
210 
219  protected function ‪parseConstraint(ConstraintInterface $constraint, SourceInterface $source)
220  {
221  if ($constraint instanceof AndInterface) {
222  return $this->queryBuilder->expr()->‪and(
223  $this->‪parseConstraint($constraint->getConstraint1(), $source),
224  $this->parseConstraint($constraint->getConstraint2(), $source)
225  );
226  }
227  if ($constraint instanceof OrInterface) {
228  return $this->queryBuilder->expr()->or(
229  $this->‪parseConstraint($constraint->getConstraint1(), $source),
230  $this->parseConstraint($constraint->getConstraint2(), $source)
231  );
232  }
233  if ($constraint instanceof NotInterface) {
234  return ' NOT(' . $this->‪parseConstraint($constraint->getConstraint(), $source) . ')';
235  }
236  if ($constraint instanceof ComparisonInterface) {
237  return $this->‪parseComparison($constraint, $source);
238  }
239  throw new \RuntimeException('not implemented', 1476199898);
240  }
241 
249  protected function ‪parseOrderings(array $orderings, SourceInterface $source)
250  {
251  foreach ($orderings as $propertyName => $order) {
253  throw new UnsupportedOrderException('Unsupported order encountered.', 1242816074);
254  }
255  $className = null;
256  $tableName = '';
257  if ($source instanceof SelectorInterface) {
258  $className = $source->getNodeTypeName();
259  $tableName = $this->‪dataMapper->convertClassNameToTableName($className);
260  $fullPropertyPath = '';
261  while (str_contains($propertyName, '.')) {
262  $this->‪addUnionStatement($className, $tableName, $propertyName, $fullPropertyPath);
263  }
264  } elseif ($source instanceof JoinInterface) {
265  $tableName = $source->getLeft()->getSelectorName();
266  }
267  $columnName = $this->‪dataMapper->convertPropertyNameToColumnName($propertyName, $className);
268  if ($tableName !== '') {
269  $this->queryBuilder->addOrderBy($tableName . '.' . $columnName, $order);
270  } else {
271  $this->queryBuilder->addOrderBy($columnName, $order);
272  }
273  }
274  }
275 
279  protected function ‪addTypo3Constraints(‪QueryInterface $query)
280  {
281  $index = 0;
282  foreach ($this->tableAliasMap as $tableAlias => $tableName) {
283  if ($index === 0) {
284  // We only add the pid and language check for the first table (aggregate root).
285  // We know the first table is always the main table for the current query run.
286  $additionalWhereClauses = $this->‪getAdditionalWhereClause($query->‪getQuerySettings(), $tableName, $tableAlias);
287  } else {
288  $additionalWhereClauses = [];
289  }
290  $index++;
291  $statement = $this->‪getVisibilityConstraintStatement($query->‪getQuerySettings(), $tableName, $tableAlias);
292  if ($statement !== '') {
293  $additionalWhereClauses[] = $statement;
294  }
295  if (!empty($additionalWhereClauses)) {
296  if (in_array($tableAlias, $this->unionTableAliasCache, true)) {
297  $this->queryBuilder->andWhere(
298  $this->queryBuilder->expr()->or(
299  $this->queryBuilder->expr()->and(...$additionalWhereClauses),
300  $this->queryBuilder->expr()->isNull($tableAlias . '.uid')
301  )
302  );
303  } else {
304  $this->queryBuilder->andWhere(...$additionalWhereClauses);
305  }
306  }
307  }
308  }
309 
320  protected function ‪parseComparison(ComparisonInterface $comparison, SourceInterface $source)
321  {
322  if ($comparison->getOperator() === ‪QueryInterface::OPERATOR_CONTAINS) {
323  if ($comparison->getOperand2() === null) {
324  throw new BadConstraintException('The value for the CONTAINS operator must not be null.', 1484828468);
325  }
326  $value = $this->‪dataMapper->getPlainValue($comparison->getOperand2());
327  if (!$source instanceof SelectorInterface) {
328  throw new \RuntimeException('Source is not of type "SelectorInterface"', 1395362539);
329  }
330  $className = $source->getNodeTypeName();
331  $tableName = $this->‪dataMapper->convertClassNameToTableName($className);
332  $operand1 = $comparison->getOperand1();
333  $propertyName = $operand1->getPropertyName();
334  $fullPropertyPath = '';
335  while (str_contains($propertyName, '.')) {
336  $this->‪addUnionStatement($className, $tableName, $propertyName, $fullPropertyPath);
337  }
338  $columnName = $this->‪dataMapper->convertPropertyNameToColumnName($propertyName, $className);
339  $dataMap = $this->‪dataMapper->getDataMap($className);
340  $columnMap = $dataMap->getColumnMap($propertyName);
341  $typeOfRelation = $columnMap instanceof ColumnMap ? $columnMap->getTypeOfRelation() : null;
342  if ($typeOfRelation === Relation::HAS_AND_BELONGS_TO_MANY) {
344  $relationTableName = (string)$columnMap->getRelationTableName();
345  $queryBuilderForSubselect = $this->queryBuilder->getConnection()->createQueryBuilder();
346  $queryBuilderForSubselect
347  ->select($columnMap->getParentKeyFieldName())
348  ->from($relationTableName)
349  ->where(
350  $queryBuilderForSubselect->expr()->eq(
351  $columnMap->getChildKeyFieldName(),
352  $this->queryBuilder->createNamedParameter($value)
353  )
354  );
355  $additionalWhereForMatchFields = $this->‪getAdditionalMatchFieldsStatement($queryBuilderForSubselect->expr(), $columnMap, $relationTableName, $relationTableName);
356  if ($additionalWhereForMatchFields) {
357  $queryBuilderForSubselect->andWhere($additionalWhereForMatchFields);
358  }
359 
360  return $this->queryBuilder->expr()->comparison(
361  $this->queryBuilder->quoteIdentifier($tableName . '.uid'),
362  'IN',
363  '(' . $queryBuilderForSubselect->getSQL() . ')'
364  );
365  }
366  if ($typeOfRelation === Relation::HAS_MANY) {
367  $parentKeyFieldName = $columnMap->getParentKeyFieldName();
368  if (isset($parentKeyFieldName)) {
369  $childTableName = $columnMap->getChildTableName();
370 
371  // Build the SQL statement of the subselect
372  $queryBuilderForSubselect = $this->queryBuilder->getConnection()->createQueryBuilder();
373  $queryBuilderForSubselect
374  ->select($parentKeyFieldName)
375  ->from($childTableName)
376  ->where(
377  $queryBuilderForSubselect->expr()->eq(
378  'uid',
379  (int)$value
380  )
381  );
382 
383  // Add it to the main query
384  return $this->queryBuilder->expr()->eq(
385  $tableName . '.uid',
386  '(' . $queryBuilderForSubselect->getSQL() . ')'
387  );
388  }
389  return $this->queryBuilder->expr()->inSet(
390  $tableName . '.' . $columnName,
391  $this->queryBuilder->quote((string)$value)
392  );
393  }
394  throw new RepositoryException('Unsupported or non-existing property name "' . $propertyName . '" used in relation matching.', 1327065745);
395  }
396  return $this->‪parseDynamicOperand($comparison, $source);
397  }
398 
407  protected function ‪parseDynamicOperand(ComparisonInterface $comparison, SourceInterface $source)
408  {
409  $value = $comparison->getOperand2();
410  $fieldName = $this->‪parseOperand($comparison->getOperand1(), $source);
411  $exprBuilder = $this->queryBuilder->expr();
412  switch ($comparison->getOperator()) {
414  $hasValue = false;
415  $plainValues = [];
416  foreach ($value as $singleValue) {
417  $plainValue = $this->‪dataMapper->getPlainValue($singleValue);
418  if ($plainValue !== null) {
419  $hasValue = true;
420  $plainValues[] = $this->‪createTypedNamedParameter($singleValue);
421  }
422  }
423  if (!$hasValue) {
424  throw new BadConstraintException(
425  'The IN operator needs a non-empty value list to compare against. ' .
426  'The given value list is empty.',
427  1484828466
428  );
429  }
430  $expr = $exprBuilder->comparison($fieldName, 'IN', '(' . implode(', ', $plainValues) . ')');
431  break;
433  if ($value === null) {
434  $expr = $fieldName . ' IS NULL';
435  } else {
436  $placeHolder = $this->‪createTypedNamedParameter($value);
437  $expr = $exprBuilder->comparison($fieldName, $exprBuilder::EQ, $placeHolder);
438  }
439  break;
441  $expr = $fieldName . ' IS NULL';
442  break;
444  if ($value === null) {
445  $expr = $fieldName . ' IS NOT NULL';
446  } else {
447  $placeHolder = $this->‪createTypedNamedParameter($value);
448  $expr = $exprBuilder->comparison($fieldName, $exprBuilder::NEQ, $placeHolder);
449  }
450  break;
452  $expr = $fieldName . ' IS NOT NULL';
453  break;
455  $placeHolder = $this->‪createTypedNamedParameter($value);
456  $expr = $exprBuilder->comparison($fieldName, $exprBuilder::LT, $placeHolder);
457  break;
459  $placeHolder = $this->‪createTypedNamedParameter($value);
460  $expr = $exprBuilder->comparison($fieldName, $exprBuilder::LTE, $placeHolder);
461  break;
463  $placeHolder = $this->‪createTypedNamedParameter($value);
464  $expr = $exprBuilder->comparison($fieldName, $exprBuilder::GT, $placeHolder);
465  break;
467  $placeHolder = $this->‪createTypedNamedParameter($value);
468  $expr = $exprBuilder->comparison($fieldName, $exprBuilder::GTE, $placeHolder);
469  break;
471  $placeHolder = $this->‪createTypedNamedParameter($value, ‪Connection::PARAM_STR);
472  $expr = $exprBuilder->comparison($fieldName, 'LIKE', $placeHolder);
473  break;
474  default:
475  throw new Exception(
476  'Unsupported operator encountered.',
477  1242816073
478  );
479  }
480  return $expr;
481  }
482 
487  protected function ‪getParameterType(mixed $value): ParameterType
488  {
489  $parameterType = gettype($value);
490  switch ($parameterType) {
491  case 'integer':
493  case 'string':
495  default:
496  throw new \InvalidArgumentException(
497  'Unsupported parameter type encountered. Expected integer or string, ' . $parameterType . ' given.',
498  1494878863
499  );
500  }
501  }
502 
513  protected function ‪createTypedNamedParameter(mixed $value, ParameterType|Type|ArrayParameterType|null $forceType = null): string
514  {
515  if ($value instanceof ‪DomainObjectInterface
517  && $value->_getProperty(‪AbstractDomainObject::PROPERTY_LOCALIZED_UID) > 0
518  ) {
519  $plainValue = (int)$value->_getProperty(‪AbstractDomainObject::PROPERTY_LOCALIZED_UID);
520  } else {
521  $plainValue = $this->‪dataMapper->getPlainValue($value);
522  }
523  $parameterType = $forceType ?? $this->‪getParameterType($plainValue);
524  $placeholder = $this->queryBuilder->createNamedParameter($plainValue, $parameterType);
525 
526  return $placeholder;
527  }
528 
534  protected function ‪parseOperand(‪DynamicOperandInterface $operand, ‪SourceInterface $source)
535  {
536  $tableName = null;
537  if ($operand instanceof ‪LowerCaseInterface) {
538  $constraintSQL = 'LOWER(' . $this->‪parseOperand($operand->getOperand(), $source) . ')';
539  } elseif ($operand instanceof UpperCaseInterface) {
540  $constraintSQL = 'UPPER(' . $this->‪parseOperand($operand->getOperand(), $source) . ')';
541  } elseif ($operand instanceof PropertyValueInterface) {
542  $propertyName = $operand->getPropertyName();
543  $className = '';
544  if ($source instanceof SelectorInterface) {
545  $className = $source->getNodeTypeName();
546  $tableName = $this->‪dataMapper->convertClassNameToTableName($className);
547  $fullPropertyPath = '';
548  while (str_contains($propertyName, '.')) {
549  $this->‪addUnionStatement($className, $tableName, $propertyName, $fullPropertyPath);
550  }
551  } elseif ($source instanceof JoinInterface) {
552  $tableName = $source->getJoinCondition()->getSelector1Name();
553  }
554  $columnName = $this->‪dataMapper->convertPropertyNameToColumnName($propertyName, $className);
555  $constraintSQL = (!empty($tableName) ? $tableName . '.' : '') . $columnName;
556  $constraintSQL = $this->queryBuilder->getConnection()->quoteIdentifier($constraintSQL);
557  } else {
558  throw new \InvalidArgumentException('Given operand has invalid type "' . get_class($operand) . '".', 1395710211);
559  }
560  return $constraintSQL;
561  }
562 
568  protected function ‪addRecordTypeConstraint($className)
569  {
570  if ($className !== null) {
571  $dataMap = $this->‪dataMapper->getDataMap($className);
572  if ($dataMap->getRecordTypeColumnName() !== null) {
573  $recordTypes = [];
574  if ($dataMap->getRecordType() !== null) {
575  $recordTypes[] = $dataMap->getRecordType();
576  }
577  foreach ($dataMap->getSubclasses() as $subclassName) {
578  $subclassDataMap = $this->‪dataMapper->getDataMap($subclassName);
579  if ($subclassDataMap->getRecordType() !== null) {
580  $recordTypes[] = $subclassDataMap->getRecordType();
581  }
582  }
583  if (!empty($recordTypes)) {
584  $recordTypeStatements = [];
585  foreach ($recordTypes as $recordType) {
586  $tableName = $dataMap->getTableName();
587  $recordTypeStatements[] = $this->queryBuilder->expr()->eq(
588  $tableName . '.' . $dataMap->getRecordTypeColumnName(),
589  $this->queryBuilder->createNamedParameter($recordType)
590  );
591  }
592  $this->queryBuilder->andWhere(
593  $this->queryBuilder->expr()->or(...$recordTypeStatements)
594  );
595  }
596  }
597  }
598  }
599 
610  protected function ‪getAdditionalMatchFieldsStatement($exprBuilder, $columnMap, $childTableAlias, $parentTable = null)
611  {
612  $additionalWhereForMatchFields = [];
613  $relationTableMatchFields = $columnMap->getRelationTableMatchFields();
614  if (is_array($relationTableMatchFields) && !empty($relationTableMatchFields)) {
615  foreach ($relationTableMatchFields as $fieldName => $value) {
616  $additionalWhereForMatchFields[] = $exprBuilder->eq($childTableAlias . '.' . $fieldName, $this->queryBuilder->createNamedParameter($value));
617  }
618  }
619 
620  if (isset($parentTable)) {
621  $parentTableFieldName = $columnMap->getParentTableFieldName();
622  if (!empty($parentTableFieldName)) {
623  $additionalWhereForMatchFields[] = $exprBuilder->eq($childTableAlias . '.' . $parentTableFieldName, $this->queryBuilder->createNamedParameter($parentTable));
624  }
625  }
626 
627  if (!empty($additionalWhereForMatchFields)) {
628  return $exprBuilder->‪and(...$additionalWhereForMatchFields);
629  }
630  return '';
631  }
632 
641  protected function ‪getAdditionalWhereClause(QuerySettingsInterface $querySettings, $tableName, $tableAlias = null)
642  {
643  $tableAlias = (string)$tableAlias;
644  // todo: $tableAlias must not be null
645 
646  $whereClause = [];
647  if ($querySettings->getRespectSysLanguage()) {
648  $systemLanguageStatement = $this->‪getLanguageStatement($tableName, $tableAlias, $querySettings);
649  if (!empty($systemLanguageStatement)) {
650  $whereClause[] = $systemLanguageStatement;
651  }
652  }
653 
654  if ($querySettings->getRespectStoragePage()) {
655  $pageIdStatement = $this->‪getPageIdStatement($tableName, $tableAlias, $querySettings->getStoragePageIds());
656  if (!empty($pageIdStatement)) {
657  $whereClause[] = $pageIdStatement;
658  }
659  }
660  if (!empty(‪$GLOBALS['TCA'][$tableName]['ctrl']['versioningWS'])) {
661  // Always prevent workspace records from being returned (except for newly created records)
662  $whereClause[] = $this->queryBuilder->expr()->eq($tableAlias . '.t3ver_oid', 0);
663  }
664 
665  return $whereClause;
666  }
667 
675  protected function ‪getVisibilityConstraintStatement(QuerySettingsInterface $querySettings, $tableName, $tableAlias)
676  {
677  if (!is_array(‪$GLOBALS['TCA'][$tableName]['ctrl'] ?? null)) {
678  return '';
679  }
680 
681  $ignoreEnableFields = $querySettings->getIgnoreEnableFields();
682  $enableFieldsToBeIgnored = $querySettings->getEnableFieldsToBeIgnored();
683  $includeDeleted = $querySettings->getIncludeDeleted();
684  if ((‪$GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface
685  && ‪ApplicationType::fromRequest(‪$GLOBALS['TYPO3_REQUEST'])->isFrontend()
686  ) {
687  $statement = $this->‪getFrontendConstraintStatement($tableName, $tableAlias, $ignoreEnableFields, $enableFieldsToBeIgnored, $includeDeleted);
688  } else {
689  // applicationType backend
690  $statement = $this->‪getBackendConstraintStatement($tableName, $ignoreEnableFields, $includeDeleted);
691  if (!empty($statement)) {
692  $statement = $this->‪replaceTableNameWithAlias($statement, $tableName, $tableAlias);
693  $statement = strtolower(substr($statement, 1, 3)) === 'and' ? substr($statement, 5) : $statement;
694  }
695  }
696  return $statement;
697  }
698 
707  protected function ‪getFrontendConstraintStatement(string $tableName, string $tableAlias, bool $ignoreEnableFields, array $enableFieldsToBeIgnored, bool $includeDeleted): string
708  {
709  $statement = '';
710  if ($ignoreEnableFields && !$includeDeleted) {
711  if (!empty($enableFieldsToBeIgnored)) {
712  $constraints = $this->‪getPageRepository()->‪getDefaultConstraints($tableName, $enableFieldsToBeIgnored, $tableAlias);
713  if ($constraints !== []) {
714  $statement = implode(' AND ', $constraints);
715  }
716  } elseif (!empty(‪$GLOBALS['TCA'][$tableName]['ctrl']['delete'])) {
717  $statement = $tableAlias . '.' . ‪$GLOBALS['TCA'][$tableName]['ctrl']['delete'] . '=0';
718  }
719  } elseif (!$ignoreEnableFields && !$includeDeleted) {
720  $constraints = $this->‪getPageRepository()->‪getDefaultConstraints($tableName, [], $tableAlias);
721  if ($constraints !== []) {
722  $statement = implode(' AND ', $constraints);
723  }
724  } elseif (!$ignoreEnableFields) {
725  throw new InconsistentQuerySettingsException('Query setting "ignoreEnableFields=FALSE" can not be used together with "includeDeleted=TRUE" in frontend context.', 1460975922);
726  }
727  return $statement;
728  }
729 
738  protected function ‪getBackendConstraintStatement($tableName, $ignoreEnableFields, $includeDeleted)
739  {
740  $statement = '';
741  // In case of versioning-preview, enableFields are ignored (checked in Typo3DbBackend::doLanguageAndWorkspaceOverlay)
742  $isUserInWorkspace = GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('workspace', 'isOffline');
743  if (!$ignoreEnableFields && !$isUserInWorkspace) {
744  $statement .= BackendUtility::BEenableFields($tableName);
745  }
746  if (!$includeDeleted && !empty(‪$GLOBALS['TCA'][$tableName]['ctrl']['delete'])) {
747  $statement .= ' AND ' . $tableName . '.' . ‪$GLOBALS['TCA'][$tableName]['ctrl']['delete'] . '=0';
748  }
749  return $statement;
750  }
751 
760  protected function ‪getLanguageStatement($tableName, $tableAlias, QuerySettingsInterface $querySettings)
761  {
762  if (empty(‪$GLOBALS['TCA'][$tableName]['ctrl']['languageField'])) {
763  return '';
764  }
765 
766  // Select all entries for the current language
767  // If any language is set -> get those entries which are not translated yet
768  // They will be removed by \TYPO3\CMS\Core\Domain\Repository\PageRepository::getRecordOverlay if not matching overlay mode
769  $languageField = ‪$GLOBALS['TCA'][$tableName]['ctrl']['languageField'];
770 
771  $languageAspect = $querySettings->getLanguageAspect();
772 
773  $transOrigPointerField = ‪$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] ?? '';
774  if (!$transOrigPointerField || !$languageAspect->getContentId()) {
775  return $this->queryBuilder->expr()->in(
776  $tableAlias . '.' . $languageField,
777  [$languageAspect->getContentId(), -1]
778  );
779  }
780 
781  if (!$languageAspect->doOverlays()) {
782  return $this->queryBuilder->expr()->in(
783  $tableAlias . '.' . $languageField,
784  [$languageAspect->getContentId(), -1]
785  );
786  }
787 
788  $defLangTableAlias = $tableAlias . '_dl';
789  $defaultLanguageRecordsSubSelect = $this->queryBuilder->getConnection()->createQueryBuilder();
790  $defaultLanguageRecordsSubSelect
791  ->select($defLangTableAlias . '.uid')
792  ->from($tableName, $defLangTableAlias)
793  ->where(
794  $defaultLanguageRecordsSubSelect->expr()->and(
795  $defaultLanguageRecordsSubSelect->expr()->eq($defLangTableAlias . '.' . $transOrigPointerField, 0),
796  $defaultLanguageRecordsSubSelect->expr()->eq($defLangTableAlias . '.' . $languageField, 0)
797  )
798  );
799 
800  $andConditions = [];
801  // records in language 'all'
802  $andConditions[] = $this->queryBuilder->expr()->eq($tableAlias . '.' . $languageField, -1);
803  // translated records where a default language exists
804  $andConditions[] = $this->queryBuilder->expr()->and(
805  $this->queryBuilder->expr()->eq($tableAlias . '.' . $languageField, $languageAspect->getContentId()),
806  $this->queryBuilder->expr()->in(
807  $tableAlias . '.' . $transOrigPointerField,
808  $defaultLanguageRecordsSubSelect->getSQL()
809  )
810  );
811  // Records in translation with no default language
812  if ($languageAspect->getOverlayType() === ‪LanguageAspect::OVERLAYS_ON_WITH_FLOATING) {
813  $andConditions[] = $this->queryBuilder->expr()->and(
814  $this->queryBuilder->expr()->eq($tableAlias . '.' . $languageField, $languageAspect->getContentId()),
815  $this->queryBuilder->expr()->eq($tableAlias . '.' . $transOrigPointerField, 0),
816  $this->queryBuilder->expr()->notIn(
817  $tableAlias . '.' . $transOrigPointerField,
818  $defaultLanguageRecordsSubSelect->getSQL()
819  )
820  );
821  }
822  if ($languageAspect->getOverlayType() === ‪LanguageAspect::OVERLAYS_MIXED) {
823  // returns records from current language which have a default language
824  // together with not translated default language records
825  $translatedOnlyTableAlias = $tableAlias . '_to';
826  $queryBuilderForSubselect = $this->queryBuilder->getConnection()->createQueryBuilder();
827  $queryBuilderForSubselect
828  ->select($translatedOnlyTableAlias . '.' . $transOrigPointerField)
829  ->from($tableName, $translatedOnlyTableAlias)
830  ->where(
831  $queryBuilderForSubselect->expr()->and(
832  $queryBuilderForSubselect->expr()->gt($translatedOnlyTableAlias . '.' . $transOrigPointerField, 0),
833  $queryBuilderForSubselect->expr()->eq($translatedOnlyTableAlias . '.' . $languageField, $languageAspect->getContentId())
834  )
835  );
836  // records in default language, which do not have a translation
837  $andConditions[] = $this->queryBuilder->expr()->and(
838  $this->queryBuilder->expr()->eq($tableAlias . '.' . $languageField, 0),
839  $this->queryBuilder->expr()->notIn(
840  $tableAlias . '.uid',
841  $queryBuilderForSubselect->getSQL()
842  )
843  );
844  }
845 
846  return $this->queryBuilder->expr()->or(...$andConditions);
847  }
848 
858  protected function ‪getPageIdStatement($tableName, $tableAlias, array $storagePageIds)
859  {
860  if (!is_array(‪$GLOBALS['TCA'][$tableName]['ctrl'] ?? null)) {
861  return '';
862  }
863 
864  $rootLevel = (int)(‪$GLOBALS['TCA'][$tableName]['ctrl']['rootLevel'] ?? 0);
865  switch ($rootLevel) {
866  // Only in pid 0
867  case 1:
868  $storagePageIds = [0];
869  break;
870  // Pid 0 and pagetree
871  case -1:
872  if (empty($storagePageIds)) {
873  $storagePageIds = [0];
874  } else {
875  $storagePageIds[] = 0;
876  }
877  break;
878  // Only pagetree or not set
879  case 0:
880  if (empty($storagePageIds)) {
881  throw new InconsistentQuerySettingsException('Missing storage page ids.', 1365779762);
882  }
883  break;
884  // Invalid configuration
885  default:
886  return '';
887  }
888  $storagePageIds = array_map(intval(...), $storagePageIds);
889  if (count($storagePageIds) === 1) {
890  return $this->queryBuilder->expr()->eq($tableAlias . '.pid', reset($storagePageIds));
891  }
892  return $this->queryBuilder->expr()->in($tableAlias . '.pid', $storagePageIds);
893  }
894 
901  protected function ‪parseJoin(‪JoinInterface $join, $leftTableAlias)
902  {
903  $leftSource = $join->‪getLeft();
904  $leftClassName = $leftSource->‪getNodeTypeName();
905  $this->‪addRecordTypeConstraint($leftClassName);
906  $rightSource = $join->‪getRight();
907  if ($rightSource instanceof ‪JoinInterface) {
908  $left = $rightSource->getLeft();
909  $rightClassName = $left->‪getNodeTypeName();
910  $rightTableName = $left->getSelectorName();
911  } else {
912  $rightClassName = $rightSource->getNodeTypeName();
913  $rightTableName = $rightSource->getSelectorName();
914  $this->queryBuilder->addSelect($rightTableName . '.*');
915  }
916  $this->‪addRecordTypeConstraint($rightClassName);
917  $rightTableAlias = $this->‪getUniqueAlias($rightTableName);
918  $joinCondition = $join->‪getJoinCondition();
919  $joinConditionExpression = null;
920  if ($joinCondition instanceof ‪EquiJoinCondition) {
921  $column1Name = $this->‪dataMapper->convertPropertyNameToColumnName($joinCondition->getProperty1Name(), $leftClassName);
922  $column2Name = $this->‪dataMapper->convertPropertyNameToColumnName($joinCondition->getProperty2Name(), $rightClassName);
923 
924  $joinConditionExpression = $this->queryBuilder->expr()->eq(
925  $leftTableAlias . '.' . $column1Name,
926  $this->queryBuilder->quoteIdentifier($rightTableAlias . '.' . $column2Name)
927  );
928  }
929  $this->queryBuilder->leftJoin($leftTableAlias, $rightTableName, $rightTableAlias, $joinConditionExpression);
930  if ($rightSource instanceof ‪JoinInterface) {
931  $this->‪parseJoin($rightSource, $rightTableAlias);
932  }
933  }
934 
943  protected function ‪getUniqueAlias($tableName, $fullPropertyPath = null)
944  {
945  if (isset($fullPropertyPath) && isset($this->tablePropertyMap[$fullPropertyPath])) {
946  return $this->tablePropertyMap[$fullPropertyPath];
947  }
948 
949  $alias = $tableName;
950  $i = 0;
951  while (isset($this->tableAliasMap[$alias])) {
952  $alias = $tableName . $i;
953  $i++;
954  }
955 
956  $this->tableAliasMap[$alias] = $tableName;
957 
958  if (isset($fullPropertyPath)) {
959  $this->tablePropertyMap[$fullPropertyPath] = $alias;
960  }
961 
962  return $alias;
963  }
964 
977  protected function ‪addUnionStatement(&$className, &$tableName, &$propertyPath, &$fullPropertyPath)
978  {
979  $explodedPropertyPath = explode('.', $propertyPath, 2);
980  $propertyName = $explodedPropertyPath[0];
981  $columnName = $this->‪dataMapper->convertPropertyNameToColumnName($propertyName, $className);
982  $realTableName = $this->‪dataMapper->convertClassNameToTableName($className);
983  $tableName = $this->tablePropertyMap[$fullPropertyPath] ?? $realTableName;
984  $columnMap = $this->‪dataMapper->getDataMap($className)->getColumnMap($propertyName);
985 
986  if ($columnMap === null) {
987  throw new MissingColumnMapException('The ColumnMap for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1355142232);
988  }
989 
990  $parentKeyFieldName = $columnMap->getParentKeyFieldName();
991  $childTableName = $columnMap->getChildTableName();
992 
993  if ($childTableName === null) {
994  throw new InvalidRelationConfigurationException('The relation information for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1353170925);
995  }
996 
997  $fullPropertyPath .= ($fullPropertyPath === '') ? $propertyName : '.' . $propertyName;
998  $childTableAlias = $this->‪getUniqueAlias($childTableName, $fullPropertyPath);
999 
1000  // If there is already a union with the current identifier we do not need to build it again and exit early.
1001  if (in_array($childTableAlias, $this->unionTableAliasCache, true)) {
1002  $propertyPath = $explodedPropertyPath[1];
1003  $tableName = $childTableAlias;
1004  $className = $this->‪dataMapper->getType($className, $propertyName);
1005  return;
1006  }
1007 
1008  if ($columnMap->getTypeOfRelation() === Relation::HAS_ONE) {
1009  if (isset($parentKeyFieldName)) {
1010  // @todo: no test for this part yet
1011  $basicJoinCondition = $this->queryBuilder->expr()->eq(
1012  $tableName . '.uid',
1013  $this->queryBuilder->quoteIdentifier($childTableAlias . '.' . $parentKeyFieldName)
1014  );
1015  } else {
1016  $basicJoinCondition = $this->queryBuilder->expr()->eq(
1017  $tableName . '.' . $columnName,
1018  $this->queryBuilder->quoteIdentifier($childTableAlias . '.uid')
1019  );
1020  }
1021  $joinConditionExpression = $this->queryBuilder->expr()->and(
1022  $basicJoinCondition,
1023  $this->‪getAdditionalMatchFieldsStatement($this->queryBuilder->expr(), $columnMap, $childTableAlias, $realTableName)
1024  );
1025  $this->queryBuilder->leftJoin($tableName, $childTableName, $childTableAlias, (string)$joinConditionExpression);
1026  $this->unionTableAliasCache[] = $childTableAlias;
1027  } elseif ($columnMap->getTypeOfRelation() === Relation::HAS_MANY) {
1028  if (isset($parentKeyFieldName)) {
1029  $basicJoinCondition = $this->queryBuilder->expr()->eq(
1030  $tableName . '.uid',
1031  $this->queryBuilder->quoteIdentifier($childTableAlias . '.' . $parentKeyFieldName)
1032  );
1033  } else {
1034  $basicJoinCondition = $this->queryBuilder->expr()->inSet(
1035  $tableName . '.' . $columnName,
1036  $this->queryBuilder->quoteIdentifier($childTableAlias . '.uid'),
1037  true
1038  );
1039  }
1040  $joinConditionExpression = $this->queryBuilder->expr()->and(
1041  $basicJoinCondition,
1042  $this->‪getAdditionalMatchFieldsStatement($this->queryBuilder->expr(), $columnMap, $childTableAlias, $realTableName)
1043  );
1044  $this->queryBuilder->leftJoin($tableName, $childTableName, $childTableAlias, (string)$joinConditionExpression);
1045  $this->unionTableAliasCache[] = $childTableAlias;
1046  $this->suggestDistinctQuery = true;
1047  } elseif ($columnMap->getTypeOfRelation() === Relation::HAS_AND_BELONGS_TO_MANY) {
1048  $relationTableName = (string)$columnMap->getRelationTableName();
1049  $relationTableAlias = $this->‪getUniqueAlias($relationTableName, $fullPropertyPath . '_mm');
1050 
1051  $joinConditionExpression = $this->queryBuilder->expr()->and(
1052  $this->queryBuilder->expr()->eq(
1053  $tableName . '.uid',
1054  $this->queryBuilder->quoteIdentifier(
1055  $relationTableAlias . '.' . $columnMap->getParentKeyFieldName()
1056  )
1057  ),
1058  $this->getAdditionalMatchFieldsStatement($this->queryBuilder->expr(), $columnMap, $relationTableAlias, $realTableName)
1059  );
1060  $this->queryBuilder->leftJoin($tableName, $relationTableName, $relationTableAlias, (string)$joinConditionExpression);
1061  $joinConditionExpression = $this->queryBuilder->expr()->eq(
1062  $relationTableAlias . '.' . $columnMap->getChildKeyFieldName(),
1063  $this->queryBuilder->quoteIdentifier($childTableAlias . '.uid')
1064  );
1065  $this->queryBuilder->leftJoin($relationTableAlias, $childTableName, $childTableAlias, $joinConditionExpression);
1066  $this->unionTableAliasCache[] = $childTableAlias;
1067  $this->suggestDistinctQuery = true;
1068  } else {
1069  throw new Exception('Could not determine type of relation.', 1252502725);
1070  }
1071  $propertyPath = $explodedPropertyPath[1];
1072  $tableName = $childTableAlias;
1073  $className = $this->‪dataMapper->getType($className, $propertyName);
1074  }
1075 
1085  protected function ‪replaceTableNameWithAlias($statement, $tableName, $tableAlias)
1086  {
1087  if ($tableAlias !== $tableName) {
1088  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($tableName);
1089  $quotedTableName = $connection->quoteIdentifier($tableName);
1090  $quotedTableAlias = $connection->quoteIdentifier($tableAlias);
1091  $statement = str_replace(
1092  [$tableName . '.', $quotedTableName . '.'],
1093  [$tableAlias . '.', $quotedTableAlias . '.'],
1094  $statement
1095  );
1096  }
1098  return $statement;
1099  }
1100 
1104  protected function ‪getPageRepository()
1105  {
1106  if (!$this->pageRepository instanceof ‪PageRepository) {
1107  $this->pageRepository = GeneralUtility::makeInstance(PageRepository::class);
1108  }
1109  return ‪$this->pageRepository;
1110  }
1111 }
‪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:169
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\getLanguageStatement
‪CompositeExpression string getLanguageStatement($tableName, $tableAlias, QuerySettingsInterface $querySettings)
Definition: Typo3DbQueryParser.php:753
‪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:1078
‪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:731
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\addRecordTypeConstraint
‪addRecordTypeConstraint($className)
Definition: Typo3DbQueryParser.php:561
‪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:242
‪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:480
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\$pageRepository
‪PageRepository $pageRepository
Definition: Typo3DbQueryParser.php:76
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\convertQueryToDoctrineQueryBuilder
‪QueryBuilder convertQueryToDoctrineQueryBuilder(QueryInterface $query)
Definition: Typo3DbQueryParser.php:134
‪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:58
‪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:936
‪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:851
‪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:700
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\getPageRepository
‪PageRepository getPageRepository()
Definition: Typo3DbQueryParser.php:1097
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\parseComparison
‪string parseComparison(ComparisonInterface $comparison, SourceInterface $source)
Definition: Typo3DbQueryParser.php:313
‪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:668
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\createTypedNamedParameter
‪string createTypedNamedParameter(mixed $value, ParameterType|Type|ArrayParameterType|null $forceType=null)
Definition: Typo3DbQueryParser.php:506
‪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:70
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\parseConstraint
‪CompositeExpression string parseConstraint(ConstraintInterface $constraint, SourceInterface $source)
Definition: Typo3DbQueryParser.php:212
‪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:116
‪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:603
‪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:634
‪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:91
‪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:124
‪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:400
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\getDefaultConstraints
‪CompositeExpression[] getDefaultConstraints(string $table, array $enableFieldsToIgnore=[], string $tableAlias=null)
Definition: PageRepository.php:1467
‪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:527
‪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:272
‪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:894
‪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:970
‪TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser\$queryBuilder
‪QueryBuilder $queryBuilder
Definition: Typo3DbQueryParser.php:82
‪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:69