/** * Parse a Comparison into SQL and parameter arrays. * * @param Qom\ComparisonInterface $comparison The comparison to parse * @param Qom\SourceInterface $source The source * @throws \RuntimeException * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\RepositoryException * @return string */ protected function parseComparison(Qom\ComparisonInterface $comparison, Qom\SourceInterface $source) { if ($comparison->getOperator() === QueryInterface::OPERATOR_CONTAINS) { if ($comparison->getOperand2() === null) { return '1<>1'; } else { $value = $this->dataMapper->getPlainValue($comparison->getOperand2()); if (!$source instanceof Qom\SelectorInterface) { throw new \RuntimeException('Source is not of type "SelectorInterface"', 1395362539); } $className = $source->getNodeTypeName(); $tableName = $this->dataMapper->convertClassNameToTableName($className); $operand1 = $comparison->getOperand1(); $propertyName = $operand1->getPropertyName(); $fullPropertyPath = ''; while (strpos($propertyName, '.') !== false) { $this->addUnionStatement($className, $tableName, $propertyName, $fullPropertyPath); } $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className); $dataMap = $this->dataMapper->getDataMap($className); $columnMap = $dataMap->getColumnMap($propertyName); $typeOfRelation = $columnMap instanceof ColumnMap ? $columnMap->getTypeOfRelation() : null; if ($typeOfRelation === ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) { $relationTableName = $columnMap->getRelationTableName(); $queryBuilderForSubselect = $this->queryBuilder->getConnection()->createQueryBuilder(); $queryBuilderForSubselect->select($columnMap->getParentKeyFieldName())->from($relationTableName)->where($queryBuilderForSubselect->expr()->eq($columnMap->getChildKeyFieldName(), $this->queryBuilder->createNamedParameter($value))); $additionalWhereForMatchFields = $this->getAdditionalMatchFieldsStatement($queryBuilderForSubselect->expr(), $columnMap, $relationTableName, $relationTableName); if ($additionalWhereForMatchFields) { $queryBuilderForSubselect->andWhere($additionalWhereForMatchFields); } return $this->queryBuilder->expr()->comparison($this->queryBuilder->quoteIdentifier($tableName . '.uid'), 'IN', '(' . $queryBuilderForSubselect->getSQL() . ')'); } elseif ($typeOfRelation === ColumnMap::RELATION_HAS_MANY) { $parentKeyFieldName = $columnMap->getParentKeyFieldName(); if (isset($parentKeyFieldName)) { $childTableName = $columnMap->getChildTableName(); // Build the SQL statement of the subselect $queryBuilderForSubselect = $this->queryBuilder->getConnection()->createQueryBuilder(); $queryBuilderForSubselect->select($parentKeyFieldName)->from($childTableName)->where($queryBuilderForSubselect->expr()->eq('uid', (int) $value)); // Add it to the main query return $this->queryBuilder->expr()->eq($tableName . '.uid', $queryBuilderForSubselect->getSQL()); } else { return $this->queryBuilder->expr()->inSet($tableName . '.' . $columnName, $this->queryBuilder->createNamedParameter($value)); } } else { throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\RepositoryException('Unsupported or non-existing property name "' . $propertyName . '" used in relation matching.', 1327065745); } } } else { return $this->parseDynamicOperand($comparison, $source); } }
/** * Build the MySql where clause by table. * * @param QueryBuilder $queryBuilder * @param string $tableName Record table name * @param array $fieldsToSearchWithin User right based visible fields where we can search within. * @return CompositeExpression */ protected function makeQuerySearchByTable(QueryBuilder &$queryBuilder, $tableName, array $fieldsToSearchWithin) { $constraints = []; // If the search string is a simple integer, assemble an equality comparison if (MathUtility::canBeInterpretedAsInteger($this->queryString)) { foreach ($fieldsToSearchWithin as $fieldName) { if ($fieldName !== 'uid' && $fieldName !== 'pid' && !isset($GLOBALS['TCA'][$tableName]['columns'][$fieldName])) { continue; } $fieldConfig = $GLOBALS['TCA'][$tableName]['columns'][$fieldName]['config']; $fieldType = $fieldConfig['type']; $evalRules = $fieldConfig['eval'] ?: ''; // Assemble the search condition only if the field is an integer, or is uid or pid if ($fieldName === 'uid' || $fieldName === 'pid' || $fieldType === 'input' && $evalRules && GeneralUtility::inList($evalRules, 'int')) { $constraints[] = $queryBuilder->expr()->eq($fieldName, $queryBuilder->createNamedParameter($this->queryString, \PDO::PARAM_INT)); } elseif ($fieldType === 'text' || $fieldType === 'flex' || $fieldType === 'input' && (!$evalRules || !preg_match('/date|time|int/', $evalRules))) { // Otherwise and if the field makes sense to be searched, assemble a like condition $constraints[] = $constraints[] = $queryBuilder->expr()->like($fieldName, $queryBuilder->createNamedParameter('%' . $queryBuilder->escapeLikeWildcards((int) $this->queryString) . '%', \PDO::PARAM_STR)); } } } else { $like = '%' . $queryBuilder->escapeLikeWildcards($this->queryString) . '%'; foreach ($fieldsToSearchWithin as $fieldName) { if (!isset($GLOBALS['TCA'][$tableName]['columns'][$fieldName])) { continue; } $fieldConfig =& $GLOBALS['TCA'][$tableName]['columns'][$fieldName]['config']; $fieldType = $fieldConfig['type']; $evalRules = $fieldConfig['eval'] ?: ''; // Check whether search should be case-sensitive or not $searchConstraint = $queryBuilder->expr()->andX($queryBuilder->expr()->comparison('LOWER(' . $queryBuilder->quoteIdentifier($fieldName) . ')', 'LIKE', $queryBuilder->createNamedParameter(strtolower($like), \PDO::PARAM_STR))); if (is_array($fieldConfig['search'])) { if (in_array('case', $fieldConfig['search'], true)) { // Replace case insensitive default constraint $searchConstraint = $queryBuilder->expr()->andX($queryBuilder->expr()->like($fieldName, $queryBuilder->createNamedParameter($like, \PDO::PARAM_STR))); } // Apply additional condition, if any if ($fieldConfig['search']['andWhere']) { $searchConstraint->add(QueryHelper::stripLogicalOperatorPrefix($fieldConfig['search']['andWhere'])); } } // Assemble the search condition only if the field makes sense to be searched if ($fieldType === 'text' || $fieldType === 'flex' || $fieldType === 'input' && (!$evalRules || !preg_match('/date|time|int/', $evalRules))) { if ($searchConstraint->count() !== 0) { $constraints[] = $searchConstraint; } } } } // If no search field conditions have been build ensure no results are returned if (empty($constraints)) { return '0=1'; } return $queryBuilder->expr()->orX(...$constraints); }