TYPO3 CMS  TYPO3_6-2
Typo3DbQueryParser.php
Go to the documentation of this file.
1 <?php
3 
23 
28 
34  protected $databaseHandle;
35 
40  protected $dataMapper;
41 
47  protected $pageRepository;
48 
53  protected $cacheManager;
54 
58  protected $tableColumnCache;
59 
65 
69  public function __construct() {
70  $this->databaseHandle = $GLOBALS['TYPO3_DB'];
71  }
72 
78  public function initializeObject() {
79  $this->tableColumnCache = $this->cacheManager->getCache('extbase_typo3dbbackend_tablecolumns');
80  }
81 
88  public function preparseQuery(QueryInterface $query) {
89  list($parameters, $operators) = $this->preparseComparison($query->getConstraint());
90  $hashPartials = array(
91  $query->getQuerySettings(),
92  $query->getSource(),
93  array_keys($parameters),
94  $operators,
95  $query->getOrderings(),
96  );
97  $hash = md5(serialize($hashPartials));
98 
99  return array($hash, $parameters);
100  }
101 
115  protected function preparseComparison($comparison, $qomPath = '') {
116  $parameters = array();
117  $operators = array();
118  $objectsToParse = array();
119 
120  $delimiter = '';
121  if ($comparison instanceof Qom\AndInterface) {
122  $delimiter = 'AND';
123  $objectsToParse = array($comparison->getConstraint1(), $comparison->getConstraint2());
124  } elseif ($comparison instanceof Qom\OrInterface) {
125  $delimiter = 'OR';
126  $objectsToParse = array($comparison->getConstraint1(), $comparison->getConstraint2());
127  } elseif ($comparison instanceof Qom\NotInterface) {
128  $delimiter = 'NOT';
129  $objectsToParse = array($comparison->getConstraint());
130  } elseif ($comparison instanceof Qom\ComparisonInterface) {
131  $operand1 = $comparison->getOperand1();
132  $parameterIdentifier = $this->normalizeParameterIdentifier($qomPath . $operand1->getPropertyName());
133  $comparison->setParameterIdentifier($parameterIdentifier);
134  $operator = $comparison->getOperator();
135  $operand2 = $comparison->getOperand2();
136  if ($operator === QueryInterface::OPERATOR_IN) {
137  $items = array();
138  foreach ($operand2 as $value) {
139  $value = $this->getPlainValue($value);
140  if ($value !== NULL) {
141  $items[] = $value;
142  }
143  }
144  $parameters[$parameterIdentifier] = $items;
145  } else {
146  $parameters[$parameterIdentifier] = $operand2;
147  }
148  $operators[] = $operator;
149  } elseif (!is_object($comparison)) {
150  $parameters = array(array(), $comparison);
151  return array($parameters, $operators);
152  } else {
153  throw new \Exception('Can not hash Query Component "' . get_class($comparison) . '".', 1392840462);
154  }
155 
156  $childObjectIterator = 0;
157  foreach ($objectsToParse as $objectToParse) {
158  list($preparsedParameters, $preparsedOperators) = $this->preparseComparison($objectToParse, $qomPath . $delimiter . $childObjectIterator++);
159  if (!empty($preparsedParameters)) {
160  $parameters = array_merge($parameters, $preparsedParameters);
161  }
162  if (!empty($preparsedOperators)) {
163  $operators = array_merge($operators, $preparsedOperators);
164  }
165  }
166 
167  return array($parameters, $operators);
168  }
169 
177  public function normalizeParameterIdentifier($identifier) {
178  return ':' . preg_replace('/[^A-Za-z0-9]/', '', $identifier);
179  }
180 
187  public function parseQuery(QueryInterface $query) {
188  $sql = array();
189  $sql['keywords'] = array();
190  $sql['tables'] = array();
191  $sql['unions'] = array();
192  $sql['fields'] = array();
193  $sql['where'] = array();
194  $sql['additionalWhereClause'] = array();
195  $sql['orderings'] = array();
196  $sql['limit'] = ((int)$query->getLimit() ?: NULL);
197  $sql['offset'] = ((int)$query->getOffset() ?: NULL);
198  $source = $query->getSource();
199  $this->parseSource($source, $sql);
200  $this->parseConstraint($query->getConstraint(), $source, $sql);
201  $this->parseOrderings($query->getOrderings(), $source, $sql);
202 
203  $tableNames = array_unique(array_keys($sql['tables'] + $sql['unions']));
204  foreach ($tableNames as $tableName) {
205  if (is_string($tableName) && !empty($tableName)) {
206  $this->addAdditionalWhereClause($query->getQuerySettings(), $tableName, $sql);
207  }
208  }
209 
210  return $sql;
211  }
212 
222  public function addDynamicQueryParts(QuerySettingsInterface $querySettings, array &$sql) {
223  if (!isset($sql['additionalWhereClause'])) {
224  throw new \InvalidArgumentException('Invalid statement given.', 1399512421);
225  }
226  $tableNames = array_unique(array_keys($sql['tables'] + $sql['unions']));
227  foreach ($tableNames as $tableName) {
228  if (is_string($tableName) && !empty($tableName)) {
229  $this->addVisibilityConstraintStatement($querySettings, $tableName, $sql);
230  }
231  }
232  }
233 
241  protected function parseSource(Qom\SourceInterface $source, array &$sql) {
242  if ($source instanceof Qom\SelectorInterface) {
243  $className = $source->getNodeTypeName();
244  $tableName = $this->dataMapper->getDataMap($className)->getTableName();
245  $this->addRecordTypeConstraint($className, $sql);
246  $sql['fields'][$tableName] = $tableName . '.*';
247  $sql['tables'][$tableName] = $tableName;
248  } elseif ($source instanceof Qom\JoinInterface) {
249  $this->parseJoin($source, $sql);
250  }
251  }
252 
261  protected function parseConstraint(Qom\ConstraintInterface $constraint = NULL, Qom\SourceInterface $source, array &$sql) {
262  if ($constraint instanceof Qom\AndInterface) {
263  $sql['where'][] = '(';
264  $this->parseConstraint($constraint->getConstraint1(), $source, $sql);
265  $sql['where'][] = ' AND ';
266  $this->parseConstraint($constraint->getConstraint2(), $source, $sql);
267  $sql['where'][] = ')';
268  } elseif ($constraint instanceof Qom\OrInterface) {
269  $sql['where'][] = '(';
270  $this->parseConstraint($constraint->getConstraint1(), $source, $sql);
271  $sql['where'][] = ' OR ';
272  $this->parseConstraint($constraint->getConstraint2(), $source, $sql);
273  $sql['where'][] = ')';
274  } elseif ($constraint instanceof Qom\NotInterface) {
275  $sql['where'][] = 'NOT (';
276  $this->parseConstraint($constraint->getConstraint(), $source, $sql);
277  $sql['where'][] = ')';
278  } elseif ($constraint instanceof Qom\ComparisonInterface) {
279  $this->parseComparison($constraint, $source, $sql);
280  }
281  }
282 
292  protected function parseOrderings(array $orderings, Qom\SourceInterface $source, array &$sql) {
293  foreach ($orderings as $propertyName => $order) {
294  switch ($order) {
296 
298  $order = 'ASC';
299  break;
301 
303  $order = 'DESC';
304  break;
305  default:
306  throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnsupportedOrderException('Unsupported order encountered.', 1242816074);
307  }
308  $className = '';
309  $tableName = '';
310  if ($source instanceof Qom\SelectorInterface) {
311  $className = $source->getNodeTypeName();
312  $tableName = $this->dataMapper->convertClassNameToTableName($className);
313  while (strpos($propertyName, '.') !== FALSE) {
314  $this->addUnionStatement($className, $tableName, $propertyName, $sql);
315  }
316  } elseif ($source instanceof Qom\JoinInterface) {
317  $tableName = $source->getLeft()->getSelectorName();
318  }
319  $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className);
320  if ($tableName !== '') {
321  $sql['orderings'][] = $tableName . '.' . $columnName . ' ' . $order;
322  } else {
323  $sql['orderings'][] = $columnName . ' ' . $order;
324  }
325  }
326  }
327 
338  protected function parseComparison(Qom\ComparisonInterface $comparison, Qom\SourceInterface $source, array &$sql) {
339  $parameterIdentifier = $this->normalizeParameterIdentifier($comparison->getParameterIdentifier());
340 
341  $operator = $comparison->getOperator();
342  $operand2 = $comparison->getOperand2();
343  if ($operator === QueryInterface::OPERATOR_IN) {
344  $hasValue = FALSE;
345  foreach ($operand2 as $value) {
346  $value = $this->getPlainValue($value);
347  if ($value !== NULL) {
348  $parameters[] = $value;
349  $hasValue = TRUE;
350  }
351  }
352  if ($hasValue === FALSE) {
353  $sql['where'][] = '1<>1';
354  } else {
355  $this->parseDynamicOperand($comparison, $source, $sql);
356  }
357  } elseif ($operator === QueryInterface::OPERATOR_CONTAINS) {
358  if ($operand2 === NULL) {
359  $sql['where'][] = '1<>1';
360  } else {
361  if (!$source instanceof Qom\SelectorInterface) {
362  throw new \RuntimeException('Source is not of type "SelectorInterface"', 1395362539);
363  }
364  $className = $source->getNodeTypeName();
365  $tableName = $this->dataMapper->convertClassNameToTableName($className);
366  $operand1 = $comparison->getOperand1();
367  $propertyName = $operand1->getPropertyName();
368  while (strpos($propertyName, '.') !== FALSE) {
369  $this->addUnionStatement($className, $tableName, $propertyName, $sql);
370  }
371  $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className);
372  $dataMap = $this->dataMapper->getDataMap($className);
373  $columnMap = $dataMap->getColumnMap($propertyName);
374  $typeOfRelation = $columnMap instanceof ColumnMap ? $columnMap->getTypeOfRelation() : NULL;
375  if ($typeOfRelation === ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
376  $relationTableName = $columnMap->getRelationTableName();
377  $relationTableMatchFields = $columnMap->getRelationTableMatchFields();
378  if (is_array($relationTableMatchFields)) {
379  $additionalWhere = array();
380  foreach ($relationTableMatchFields as $fieldName => $value) {
381  $additionalWhere[] = $fieldName . ' = ' . $this->databaseHandle->fullQuoteStr($value, $relationTableName);
382  }
383  $additionalWhereForMatchFields = ' AND ' . implode(' AND ', $additionalWhere);
384  } else {
385  $additionalWhereForMatchFields = '';
386  }
387  $sql['where'][] = $tableName . '.uid IN (SELECT ' . $columnMap->getParentKeyFieldName() . ' FROM ' . $relationTableName . ' WHERE ' . $columnMap->getChildKeyFieldName() . '=' . $parameterIdentifier . $additionalWhereForMatchFields . ')';
388  } elseif ($typeOfRelation === ColumnMap::RELATION_HAS_MANY) {
389  $parentKeyFieldName = $columnMap->getParentKeyFieldName();
390  if (isset($parentKeyFieldName)) {
391  $childTableName = $columnMap->getChildTableName();
392  $sql['where'][] = $tableName . '.uid=(SELECT ' . $childTableName . '.' . $parentKeyFieldName . ' FROM ' . $childTableName . ' WHERE ' . $childTableName . '.uid=' . $parameterIdentifier . ')';
393  } else {
394  $sql['where'][] = 'FIND_IN_SET(' . $parameterIdentifier . ', ' . $tableName . '.' . $columnName . ')';
395  }
396  } else {
397  throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\RepositoryException('Unsupported or non-existing property name "' . $propertyName . '" used in relation matching.', 1327065745);
398  }
399  }
400  } else {
401  $this->parseDynamicOperand($comparison, $source, $sql);
402  }
403  }
404 
413  protected function parseDynamicOperand(Qom\ComparisonInterface $comparison, Qom\SourceInterface $source, array &$sql) {
414  $operator = $this->resolveOperator($comparison->getOperator());
415  $operand = $comparison->getOperand1();
416 
417  $constraintSQL = $this->parseOperand($operand, $source, $sql) . ' ' . $operator . ' ';
418 
419  $parameterIdentifier = $this->normalizeParameterIdentifier($comparison->getParameterIdentifier());
420  if ($operator === 'IN') {
421  $parameterIdentifier = '(' . $parameterIdentifier . ')';
422  }
423  $constraintSQL .= $parameterIdentifier;
424 
425  $sql['where'][] = $constraintSQL;
426  }
427 
435  protected function parseOperand(Qom\DynamicOperandInterface $operand, Qom\SourceInterface $source, array &$sql) {
436  if ($operand instanceof Qom\LowerCaseInterface) {
437  $constraintSQL = 'LOWER(' . $this->parseOperand($operand->getOperand(), $source, $sql) . ')';
438  } elseif ($operand instanceof Qom\UpperCaseInterface) {
439  $constraintSQL = 'UPPER(' . $this->parseOperand($operand->getOperand(), $source, $sql) . ')';
440  } elseif ($operand instanceof Qom\PropertyValueInterface) {
441  $propertyName = $operand->getPropertyName();
442  $className = '';
443  if ($source instanceof Qom\SelectorInterface) {
444  // FIXME Only necessary to differ from Join
445  $className = $source->getNodeTypeName();
446  $tableName = $this->dataMapper->convertClassNameToTableName($className);
447  while (strpos($propertyName, '.') !== FALSE) {
448  $this->addUnionStatement($className, $tableName, $propertyName, $sql);
449  }
450  } elseif ($source instanceof Qom\JoinInterface) {
451  $tableName = $source->getJoinCondition()->getSelector1Name();
452  }
453  $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className);
454  $constraintSQL = (!empty($tableName) ? $tableName . '.' : '') . $columnName;
455  } else {
456  throw new \InvalidArgumentException('Given operand has invalid type "' . get_class($operand) . '".', 1395710211);
457  }
458  return $constraintSQL;
459  }
460 
468  protected function addRecordTypeConstraint($className, &$sql) {
469  if ($className !== NULL) {
470  $dataMap = $this->dataMapper->getDataMap($className);
471  if ($dataMap->getRecordTypeColumnName() !== NULL) {
472  $recordTypes = array();
473  if ($dataMap->getRecordType() !== NULL) {
474  $recordTypes[] = $dataMap->getRecordType();
475  }
476  foreach ($dataMap->getSubclasses() as $subclassName) {
477  $subclassDataMap = $this->dataMapper->getDataMap($subclassName);
478  if ($subclassDataMap->getRecordType() !== NULL) {
479  $recordTypes[] = $subclassDataMap->getRecordType();
480  }
481  }
482  if (!empty($recordTypes)) {
483  $recordTypeStatements = array();
484  foreach ($recordTypes as $recordType) {
485  $tableName = $dataMap->getTableName();
486  $recordTypeStatements[] = $tableName . '.' . $dataMap->getRecordTypeColumnName() . '=' . $this->databaseHandle->fullQuoteStr($recordType, $tableName);
487  }
488  $sql['additionalWhereClause'][] = '(' . implode(' OR ', $recordTypeStatements) . ')';
489  }
490  }
491  }
492  }
493 
502  protected function addAdditionalWhereClause(QuerySettingsInterface $querySettings, $tableName, &$sql) {
503  if ($querySettings->getRespectSysLanguage()) {
504  $this->addSysLanguageStatement($tableName, $sql, $querySettings);
505  }
506  if ($querySettings->getRespectStoragePage()) {
507  $this->addPageIdStatement($tableName, $sql, $querySettings->getStoragePageIds());
508  }
509  }
510 
519  protected function addVisibilityConstraintStatement(QuerySettingsInterface $querySettings, $tableName, array &$sql) {
520  $statement = '';
521  if (is_array($GLOBALS['TCA'][$tableName]['ctrl'])) {
522  $ignoreEnableFields = $querySettings->getIgnoreEnableFields();
523  $enableFieldsToBeIgnored = $querySettings->getEnableFieldsToBeIgnored();
524  $includeDeleted = $querySettings->getIncludeDeleted();
525  if ($this->environmentService->isEnvironmentInFrontendMode()) {
526  $statement .= $this->getFrontendConstraintStatement($tableName, $ignoreEnableFields, $enableFieldsToBeIgnored, $includeDeleted);
527  } else {
528  // TYPO3_MODE === 'BE'
529  $statement .= $this->getBackendConstraintStatement($tableName, $ignoreEnableFields, $includeDeleted);
530  }
531  if (!empty($statement)) {
532  $statement = strtolower(substr($statement, 1, 3)) === 'and' ? substr($statement, 5) : $statement;
533  $sql['additionalWhereClause'][] = $statement;
534  }
535  }
536  }
537 
548  protected function getFrontendConstraintStatement($tableName, $ignoreEnableFields, array $enableFieldsToBeIgnored = array(), $includeDeleted) {
549  $statement = '';
550  if ($ignoreEnableFields && !$includeDeleted) {
551  if (count($enableFieldsToBeIgnored)) {
552  // array_combine() is necessary because of the way \TYPO3\CMS\Frontend\Page\PageRepository::enableFields() is implemented
553  $statement .= $this->getPageRepository()->enableFields($tableName, -1, array_combine($enableFieldsToBeIgnored, $enableFieldsToBeIgnored));
554  } else {
555  $statement .= $this->getPageRepository()->deleteClause($tableName);
556  }
557  } elseif (!$ignoreEnableFields && !$includeDeleted) {
558  $statement .= $this->getPageRepository()->enableFields($tableName);
559  } elseif (!$ignoreEnableFields && $includeDeleted) {
560  throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InconsistentQuerySettingsException('Query setting "ignoreEnableFields=FALSE" can not be used together with "includeDeleted=TRUE" in frontend context.', 1327678173);
561  }
562  return $statement;
563  }
564 
573  protected function getBackendConstraintStatement($tableName, $ignoreEnableFields, $includeDeleted) {
574  $statement = '';
575  if (!$ignoreEnableFields) {
576  $statement .= BackendUtility::BEenableFields($tableName);
577  }
578  if (!$includeDeleted) {
579  $statement .= BackendUtility::deleteClause($tableName);
580  }
581  return $statement;
582  }
583 
592  protected function addSysLanguageStatement($tableName, array &$sql, $querySettings) {
593  if (is_array($GLOBALS['TCA'][$tableName]['ctrl'])) {
594  if (!empty($GLOBALS['TCA'][$tableName]['ctrl']['languageField'])) {
595  // Select all entries for the current language
596  $additionalWhereClause = $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' IN (' . (int)$querySettings->getLanguageUid() . ',-1)';
597  // If any language is set -> get those entries which are not translated yet
598  // They will be removed by t3lib_page::getRecordOverlay if not matching overlay mode
599  if (isset($GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'])
600  && $querySettings->getLanguageUid() > 0
601  ) {
602 
603  $mode = $querySettings->getLanguageMode();
604  if ($mode === 'strict') {
605  $additionalWhereClause = $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=-1' .
606  ' OR (' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' = ' . (int)$querySettings->getLanguageUid() .
607  ' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '=0' .
608  ') OR (' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=0' .
609  ' AND ' . $tableName . '.uid IN (SELECT ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] .
610  ' FROM ' . $tableName .
611  ' WHERE ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '>0' .
612  ' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=' . (int)$querySettings->getLanguageUid();
613  } else {
614  $additionalWhereClause .= ' OR (' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=0' .
615  ' AND ' . $tableName . '.uid NOT IN (SELECT ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] .
616  ' FROM ' . $tableName .
617  ' WHERE ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '>0' .
618  ' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=' . (int)$querySettings->getLanguageUid();
619  }
620 
621  // Add delete clause to ensure all entries are loaded
622  if (isset($GLOBALS['TCA'][$tableName]['ctrl']['delete'])) {
623  $additionalWhereClause .= ' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['delete'] . '=0';
624  }
625  $additionalWhereClause .= '))';
626  }
627  $sql['additionalWhereClause'][] = '(' . $additionalWhereClause . ')';
628  }
629  }
630  }
631 
641  protected function addPageIdStatement($tableName, array &$sql, array $storagePageIds) {
642  $tableColumns = $this->tableColumnCache->get($tableName);
643  if ($tableColumns === FALSE) {
644  $tableColumns = $this->databaseHandle->admin_get_fields($tableName);
645  $this->tableColumnCache->set($tableName, $tableColumns);
646  }
647  if (is_array($GLOBALS['TCA'][$tableName]['ctrl']) && array_key_exists('pid', $tableColumns)) {
648  $rootLevel = (int)$GLOBALS['TCA'][$tableName]['ctrl']['rootLevel'];
649  if ($rootLevel) {
650  if ($rootLevel === 1) {
651  $sql['additionalWhereClause'][] = $tableName . '.pid = 0';
652  }
653  } else {
654  if (empty($storagePageIds)) {
655  throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InconsistentQuerySettingsException('Missing storage page ids.', 1365779762);
656  }
657  $sql['additionalWhereClause'][] = $tableName . '.pid IN (' . implode(',', $this->databaseHandle->cleanIntArray($storagePageIds)) . ')';
658  }
659  }
660  }
661 
669  protected function parseJoin(Qom\JoinInterface $join, array &$sql) {
670  $leftSource = $join->getLeft();
671  $leftClassName = $leftSource->getNodeTypeName();
672  $leftTableName = $leftSource->getSelectorName();
673  $this->addRecordTypeConstraint($leftClassName, $sql);
674  $rightSource = $join->getRight();
675  if ($rightSource instanceof Qom\JoinInterface) {
676  $left = $rightSource->getLeft();
677  $rightClassName = $left->getNodeTypeName();
678  $rightTableName = $left->getSelectorName();
679  } else {
680  $rightClassName = $rightSource->getNodeTypeName();
681  $rightTableName = $rightSource->getSelectorName();
682  $sql['fields'][$leftTableName] = $rightTableName . '.*';
683  }
684  $this->addRecordTypeConstraint($rightClassName, $sql);
685  $sql['tables'][$leftTableName] = $leftTableName;
686  $sql['unions'][$rightTableName] = 'LEFT JOIN ' . $rightTableName;
687  $joinCondition = $join->getJoinCondition();
688  if ($joinCondition instanceof Qom\EquiJoinCondition) {
689  $column1Name = $this->dataMapper->convertPropertyNameToColumnName($joinCondition->getProperty1Name(), $leftClassName);
690  $column2Name = $this->dataMapper->convertPropertyNameToColumnName($joinCondition->getProperty2Name(), $rightClassName);
691  $sql['unions'][$rightTableName] .= ' ON ' . $joinCondition->getSelector1Name() . '.' . $column1Name . ' = ' . $joinCondition->getSelector2Name() . '.' . $column2Name;
692  }
693  if ($rightSource instanceof Qom\JoinInterface) {
694  $this->parseJoin($rightSource, $sql);
695  }
696  }
697 
705  protected function getPlainValue($input) {
706  if (is_array($input)) {
707  throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException('An array could not be converted to a plain value.', 1274799932);
708  }
709  if ($input instanceof \DateTime) {
710  return $input->format('U');
711  } elseif (TypeHandlingUtility::isCoreType($input)) {
712  return (string) $input;
713  } elseif (is_object($input)) {
714  if ($input instanceof \TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy) {
715  $realInput = $input->_loadRealInstance();
716  } else {
717  $realInput = $input;
718  }
719  if ($realInput instanceof \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface) {
720  return $realInput->getUid();
721  } else {
722  throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException('An object of class "' . get_class($realInput) . '" could not be converted to a plain value.', 1274799934);
723  }
724  } elseif (is_bool($input)) {
725  return $input === TRUE ? 1 : 0;
726  } else {
727  return $input;
728  }
729  }
730 
731 
743  protected function addUnionStatement(&$className, &$tableName, &$propertyPath, array &$sql) {
744  $explodedPropertyPath = explode('.', $propertyPath, 2);
745  $propertyName = $explodedPropertyPath[0];
746  $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className);
747  $tableName = $this->dataMapper->convertClassNameToTableName($className);
748  $columnMap = $this->dataMapper->getDataMap($className)->getColumnMap($propertyName);
749 
750  if ($columnMap === NULL) {
751  throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\MissingColumnMapException('The ColumnMap for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1355142232);
752  }
753 
754  $parentKeyFieldName = $columnMap->getParentKeyFieldName();
755  $childTableName = $columnMap->getChildTableName();
756 
757  if ($childTableName === NULL) {
758  throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidRelationConfigurationException('The relation information for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1353170925);
759  }
760 
761  if ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_ONE) {
762  if (isset($parentKeyFieldName)) {
763  $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.uid=' . $childTableName . '.' . $parentKeyFieldName;
764  } else {
765  $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.' . $columnName . '=' . $childTableName . '.uid';
766  }
767  $className = $this->dataMapper->getType($className, $propertyName);
768  } elseif ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_MANY) {
769  if (isset($parentKeyFieldName)) {
770  $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.uid=' . $childTableName . '.' . $parentKeyFieldName;
771  } else {
772  $onStatement = '(FIND_IN_SET(' . $childTableName . '.uid, ' . $tableName . '.' . $columnName . '))';
773  $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $onStatement;
774  }
775  $className = $this->dataMapper->getType($className, $propertyName);
776  } elseif ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
777  $relationTableName = $columnMap->getRelationTableName();
778  $sql['unions'][$relationTableName] = 'LEFT JOIN ' . $relationTableName . ' ON ' . $tableName . '.uid=' . $relationTableName . '.' . $columnMap->getParentKeyFieldName();
779  $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $relationTableName . '.' . $columnMap->getChildKeyFieldName() . '=' . $childTableName . '.uid';
780  $className = $this->dataMapper->getType($className, $propertyName);
781  } else {
782  throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception('Could not determine type of relation.', 1252502725);
783  }
784  // TODO check if there is another solution for this
785  $sql['keywords']['distinct'] = 'DISTINCT';
786  $propertyPath = $explodedPropertyPath[1];
787  $tableName = $childTableName;
788  }
789 
797  protected function resolveOperator($operator) {
798  switch ($operator) {
800  $operator = 'IN';
801  break;
803  $operator = '=';
804  break;
806  $operator = 'IS';
807  break;
809  $operator = '!=';
810  break;
812  $operator = 'IS NOT';
813  break;
815  $operator = '<';
816  break;
818  $operator = '<=';
819  break;
821  $operator = '>';
822  break;
824  $operator = '>=';
825  break;
827  $operator = 'LIKE';
828  break;
829  default:
830  throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception('Unsupported operator encountered.', 1242816073);
831  }
832  return $operator;
833  }
834 
838  protected function getPageRepository() {
839  if (!$this->pageRepository instanceof \TYPO3\CMS\Frontend\Page\PageRepository) {
840  if ($this->environmentService->isEnvironmentInFrontendMode() && is_object($GLOBALS['TSFE'])) {
841  $this->pageRepository = $GLOBALS['TSFE']->sys_page;
842  } else {
843  $this->pageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
844  }
845  }
846 
847  return $this->pageRepository;
848  }
849 }
addDynamicQueryParts(QuerySettingsInterface $querySettings, array &$sql)
addUnionStatement(&$className, &$tableName, &$propertyPath, array &$sql)
$sql
Definition: server.php:82
$parameters
Definition: FileDumpEID.php:15
addSysLanguageStatement($tableName, array &$sql, $querySettings)
getBackendConstraintStatement($tableName, $ignoreEnableFields, $includeDeleted)
parseOrderings(array $orderings, Qom\SourceInterface $source, array &$sql)
parseComparison(Qom\ComparisonInterface $comparison, Qom\SourceInterface $source, array &$sql)
addPageIdStatement($tableName, array &$sql, array $storagePageIds)
getFrontendConstraintStatement($tableName, $ignoreEnableFields, array $enableFieldsToBeIgnored=array(), $includeDeleted)
parseDynamicOperand(Qom\ComparisonInterface $comparison, Qom\SourceInterface $source, array &$sql)
parseConstraint(Qom\ConstraintInterface $constraint=NULL, Qom\SourceInterface $source, array &$sql)
parseOperand(Qom\DynamicOperandInterface $operand, Qom\SourceInterface $source, array &$sql)
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
addVisibilityConstraintStatement(QuerySettingsInterface $querySettings, $tableName, array &$sql)
addAdditionalWhereClause(QuerySettingsInterface $querySettings, $tableName, &$sql)
static deleteClause($table, $tableAlias='')