70 $this->databaseHandle =
$GLOBALS[
'TYPO3_DB'];
79 $this->tableColumnCache = $this->cacheManager->getCache(
'extbase_typo3dbbackend_tablecolumns');
90 $hashPartials = array(
97 $hash = md5(serialize($hashPartials));
117 $operators = array();
118 $objectsToParse = array();
123 $objectsToParse = array($comparison->getConstraint1(), $comparison->getConstraint2());
124 } elseif ($comparison instanceof Qom\
OrInterface) {
126 $objectsToParse = array($comparison->getConstraint1(), $comparison->getConstraint2());
129 $objectsToParse = array($comparison->getConstraint());
131 $operand1 = $comparison->getOperand1();
133 $comparison->setParameterIdentifier($parameterIdentifier);
134 $operator = $comparison->getOperator();
135 $operand2 = $comparison->getOperand2();
138 foreach ($operand2 as $value) {
140 if ($value !== NULL) {
148 $operators[] = $operator;
149 } elseif (!is_object($comparison)) {
153 throw new \Exception(
'Can not hash Query Component "' . get_class($comparison) .
'".', 1392840462);
156 $childObjectIterator = 0;
157 foreach ($objectsToParse as $objectToParse) {
158 list($preparsedParameters, $preparsedOperators) = $this->
preparseComparison($objectToParse, $qomPath . $delimiter . $childObjectIterator++);
159 if (!empty($preparsedParameters)) {
162 if (!empty($preparsedOperators)) {
163 $operators = array_merge($operators, $preparsedOperators);
178 return ':' . preg_replace(
'/[^A-Za-z0-9]/',
'', $identifier);
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();
203 $tableNames = array_unique(array_keys(
$sql[
'tables'] +
$sql[
'unions']));
204 foreach ($tableNames as $tableName) {
205 if (is_string($tableName) && !empty($tableName)) {
223 if (!isset($sql[
'additionalWhereClause'])) {
224 throw new \InvalidArgumentException(
'Invalid statement given.', 1399512421);
226 $tableNames = array_unique(array_keys($sql[
'tables'] + $sql[
'unions']));
227 foreach ($tableNames as $tableName) {
228 if (is_string($tableName) && !empty($tableName)) {
243 $className = $source->getNodeTypeName();
244 $tableName = $this->dataMapper->getDataMap($className)->getTableName();
246 $sql[
'fields'][$tableName] = $tableName .
'.*';
247 $sql[
'tables'][$tableName] = $tableName;
263 $sql[
'where'][] =
'(';
265 $sql[
'where'][] =
' AND ';
267 $sql[
'where'][] =
')';
268 } elseif ($constraint instanceof Qom\
OrInterface) {
269 $sql[
'where'][] =
'(';
271 $sql[
'where'][] =
' OR ';
273 $sql[
'where'][] =
')';
275 $sql[
'where'][] =
'NOT (';
277 $sql[
'where'][] =
')';
293 foreach ($orderings as $propertyName => $order) {
306 throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnsupportedOrderException(
'Unsupported order encountered.', 1242816074);
311 $className = $source->getNodeTypeName();
312 $tableName = $this->dataMapper->convertClassNameToTableName($className);
313 while (strpos($propertyName,
'.') !== FALSE) {
317 $tableName = $source->getLeft()->getSelectorName();
319 $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className);
320 if ($tableName !==
'') {
321 $sql[
'orderings'][] = $tableName .
'.' . $columnName .
' ' . $order;
323 $sql[
'orderings'][] = $columnName .
' ' . $order;
341 $operator = $comparison->getOperator();
342 $operand2 = $comparison->getOperand2();
345 foreach ($operand2 as $value) {
347 if ($value !== NULL) {
352 if ($hasValue === FALSE) {
353 $sql[
'where'][] =
'1<>1';
358 if ($operand2 === NULL) {
359 $sql[
'where'][] =
'1<>1';
362 throw new \RuntimeException(
'Source is not of type "SelectorInterface"', 1395362539);
364 $className = $source->getNodeTypeName();
365 $tableName = $this->dataMapper->convertClassNameToTableName($className);
366 $operand1 = $comparison->getOperand1();
367 $propertyName = $operand1->getPropertyName();
368 while (strpos($propertyName,
'.') !== FALSE) {
371 $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className);
372 $dataMap = $this->dataMapper->getDataMap($className);
373 $columnMap = $dataMap->getColumnMap($propertyName);
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);
383 $additionalWhereForMatchFields =
' AND ' . implode(
' AND ', $additionalWhere);
385 $additionalWhereForMatchFields =
'';
387 $sql[
'where'][] = $tableName .
'.uid IN (SELECT ' . $columnMap->getParentKeyFieldName() .
' FROM ' . $relationTableName .
' WHERE ' . $columnMap->getChildKeyFieldName() .
'=' . $parameterIdentifier . $additionalWhereForMatchFields .
')';
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 .
')';
394 $sql[
'where'][] =
'FIND_IN_SET(' . $parameterIdentifier .
', ' . $tableName .
'.' . $columnName .
')';
397 throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\RepositoryException(
'Unsupported or non-existing property name "' . $propertyName .
'" used in relation matching.', 1327065745);
415 $operand = $comparison->getOperand1();
417 $constraintSQL = $this->
parseOperand($operand, $source, $sql) .
' ' . $operator .
' ';
420 if ($operator ===
'IN') {
421 $parameterIdentifier =
'(' . $parameterIdentifier .
')';
423 $constraintSQL .= $parameterIdentifier;
425 $sql[
'where'][] = $constraintSQL;
437 $constraintSQL =
'LOWER(' . $this->
parseOperand($operand->getOperand(), $source,
$sql) .
')';
439 $constraintSQL =
'UPPER(' . $this->
parseOperand($operand->getOperand(), $source,
$sql) .
')';
441 $propertyName = $operand->getPropertyName();
445 $className = $source->getNodeTypeName();
446 $tableName = $this->dataMapper->convertClassNameToTableName($className);
447 while (strpos($propertyName,
'.') !== FALSE) {
451 $tableName = $source->getJoinCondition()->getSelector1Name();
453 $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className);
454 $constraintSQL = (!empty($tableName) ? $tableName .
'.' :
'') . $columnName;
456 throw new \InvalidArgumentException(
'Given operand has invalid type "' . get_class($operand) .
'".', 1395710211);
458 return $constraintSQL;
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();
476 foreach ($dataMap->getSubclasses() as $subclassName) {
477 $subclassDataMap = $this->dataMapper->getDataMap($subclassName);
478 if ($subclassDataMap->getRecordType() !== NULL) {
479 $recordTypes[] = $subclassDataMap->getRecordType();
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);
488 $sql[
'additionalWhereClause'][] =
'(' . implode(
' OR ', $recordTypeStatements) .
')';
521 if (is_array(
$GLOBALS[
'TCA'][$tableName][
'ctrl'])) {
525 if ($this->environmentService->isEnvironmentInFrontendMode()) {
531 if (!empty($statement)) {
532 $statement = strtolower(substr($statement, 1, 3)) ===
'and' ? substr($statement, 5) : $statement;
533 $sql[
'additionalWhereClause'][] = $statement;
550 if ($ignoreEnableFields && !$includeDeleted) {
551 if (count($enableFieldsToBeIgnored)) {
553 $statement .= $this->
getPageRepository()->enableFields($tableName, -1, array_combine($enableFieldsToBeIgnored, $enableFieldsToBeIgnored));
557 } elseif (!$ignoreEnableFields && !$includeDeleted) {
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);
575 if (!$ignoreEnableFields) {
578 if (!$includeDeleted) {
593 if (is_array(
$GLOBALS[
'TCA'][$tableName][
'ctrl'])) {
594 if (!empty(
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'languageField'])) {
596 $additionalWhereClause = $tableName .
'.' .
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'languageField'] .
' IN (' . (int)$querySettings->getLanguageUid() .
',-1)';
599 if (isset(
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'transOrigPointerField'])
600 && $querySettings->getLanguageUid() > 0
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();
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();
622 if (isset(
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'delete'])) {
623 $additionalWhereClause .=
' AND ' . $tableName .
'.' .
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'delete'] .
'=0';
625 $additionalWhereClause .=
'))';
627 $sql[
'additionalWhereClause'][] =
'(' . $additionalWhereClause .
')';
642 $tableColumns = $this->tableColumnCache->get($tableName);
643 if ($tableColumns === FALSE) {
644 $tableColumns = $this->databaseHandle->admin_get_fields($tableName);
645 $this->tableColumnCache->set($tableName, $tableColumns);
647 if (is_array(
$GLOBALS[
'TCA'][$tableName][
'ctrl']) && array_key_exists(
'pid', $tableColumns)) {
648 $rootLevel = (int)
$GLOBALS[
'TCA'][$tableName][
'ctrl'][
'rootLevel'];
650 if ($rootLevel === 1) {
651 $sql[
'additionalWhereClause'][] = $tableName .
'.pid = 0';
654 if (empty($storagePageIds)) {
655 throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InconsistentQuerySettingsException(
'Missing storage page ids.', 1365779762);
657 $sql[
'additionalWhereClause'][] = $tableName .
'.pid IN (' . implode(
',', $this->databaseHandle->cleanIntArray($storagePageIds)) .
')';
670 $leftSource = $join->getLeft();
671 $leftClassName = $leftSource->getNodeTypeName();
672 $leftTableName = $leftSource->getSelectorName();
674 $rightSource = $join->getRight();
676 $left = $rightSource->getLeft();
677 $rightClassName = $left->getNodeTypeName();
678 $rightTableName = $left->getSelectorName();
680 $rightClassName = $rightSource->getNodeTypeName();
681 $rightTableName = $rightSource->getSelectorName();
682 $sql[
'fields'][$leftTableName] = $rightTableName .
'.*';
685 $sql[
'tables'][$leftTableName] = $leftTableName;
686 $sql[
'unions'][$rightTableName] =
'LEFT JOIN ' . $rightTableName;
687 $joinCondition = $join->getJoinCondition();
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;
693 if ($rightSource instanceof Qom\JoinInterface) {
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);
709 if ($input instanceof \DateTime) {
710 return $input->format(
'U');
712 return (
string) $input;
713 } elseif (is_object($input)) {
715 $realInput = $input->_loadRealInstance();
720 return $realInput->getUid();
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);
724 } elseif (is_bool($input)) {
725 return $input === TRUE ? 1 : 0;
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);
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);
754 $parentKeyFieldName = $columnMap->getParentKeyFieldName();
755 $childTableName = $columnMap->getChildTableName();
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);
762 if (isset($parentKeyFieldName)) {
763 $sql[
'unions'][$childTableName] =
'LEFT JOIN ' . $childTableName .
' ON ' . $tableName .
'.uid=' . $childTableName .
'.' . $parentKeyFieldName;
765 $sql[
'unions'][$childTableName] =
'LEFT JOIN ' . $childTableName .
' ON ' . $tableName .
'.' . $columnName .
'=' . $childTableName .
'.uid';
767 $className = $this->dataMapper->getType($className, $propertyName);
769 if (isset($parentKeyFieldName)) {
770 $sql[
'unions'][$childTableName] =
'LEFT JOIN ' . $childTableName .
' ON ' . $tableName .
'.uid=' . $childTableName .
'.' . $parentKeyFieldName;
772 $onStatement =
'(FIND_IN_SET(' . $childTableName .
'.uid, ' . $tableName .
'.' . $columnName .
'))';
773 $sql[
'unions'][$childTableName] =
'LEFT JOIN ' . $childTableName .
' ON ' . $onStatement;
775 $className = $this->dataMapper->getType($className, $propertyName);
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);
782 throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception(
'Could not determine type of relation.', 1252502725);
785 $sql[
'keywords'][
'distinct'] =
'DISTINCT';
786 $propertyPath = $explodedPropertyPath[1];
787 $tableName = $childTableName;
812 $operator =
'IS NOT';
830 throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception(
'Unsupported operator encountered.', 1242816073);
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;
const OPERATOR_GREATER_THAN
const RELATION_HAS_AND_BELONGS_TO_MANY
addDynamicQueryParts(QuerySettingsInterface $querySettings, array &$sql)
addUnionStatement(&$className, &$tableName, &$propertyPath, array &$sql)
resolveOperator($operator)
addSysLanguageStatement($tableName, array &$sql, $querySettings)
getBackendConstraintStatement($tableName, $ignoreEnableFields, $includeDeleted)
parseOrderings(array $orderings, Qom\SourceInterface $source, array &$sql)
parseQuery(QueryInterface $query)
addRecordTypeConstraint($className, &$sql)
parseComparison(Qom\ComparisonInterface $comparison, Qom\SourceInterface $source, array &$sql)
addPageIdStatement($tableName, array &$sql, array $storagePageIds)
getFrontendConstraintStatement($tableName, $ignoreEnableFields, array $enableFieldsToBeIgnored=array(), $includeDeleted)
const OPERATOR_NOT_EQUAL_TO_NULL
static makeInstance($className)
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)
preparseComparison($comparison, $qomPath='')
parseJoin(Qom\JoinInterface $join, array &$sql)
const OPERATOR_LESS_THAN_OR_EQUAL_TO
const OPERATOR_EQUAL_TO_NULL
getEnableFieldsToBeIgnored()
parseSource(Qom\SourceInterface $source, array &$sql)
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
const OPERATOR_GREATER_THAN_OR_EQUAL_TO
normalizeParameterIdentifier($identifier)
const JCR_ORDER_ASCENDING
addVisibilityConstraintStatement(QuerySettingsInterface $querySettings, $tableName, array &$sql)
addAdditionalWhereClause(QuerySettingsInterface $querySettings, $tableName, &$sql)
preparseQuery(QueryInterface $query)
const JCR_ORDER_DESCENDING
static BEenableFields($table, $inv=0)
static deleteClause($table, $tableAlias='')
const OPERATOR_NOT_EQUAL_TO