/** * Applies ACL conditions to the search query * * @param Query $query * @param string $permission * * @return Query */ public function apply(Query $query, $permission = 'VIEW') { $queryFromEntities = $query->getFrom(); // in query, from record !== '*' if ($queryFromEntities[0] === '*') { $queryFromEntities = $this->mappingProvider->getEntitiesListAliases(); } $allowedAliases = []; $ownerExpressions = []; $expr = $query->getCriteria()->expr(); if (!empty($queryFromEntities)) { foreach ($queryFromEntities as $entityAlias) { $className = $this->mappingProvider->getEntityClass($entityAlias); if ($className) { $ownerField = sprintf('%s_owner', $entityAlias); $condition = $this->ownershipDataBuilder->getAclConditionData($className, $permission); if (count($condition) === 0 || !($condition[0] === null && $condition[3] === null)) { $allowedAliases[] = $entityAlias; // in case if we should not limit data for entity if (count($condition) === 0 || $condition[1] === null) { $ownerExpressions[] = $expr->gte('integer.' . $ownerField, SearchListener::EMPTY_OWNER_ID); continue; } $owners = [SearchListener::EMPTY_OWNER_ID]; if (!empty($condition[1])) { $owners = $condition[1]; if (is_array($owners) && count($owners) === 1) { $owners = $owners[0]; } } if (is_array($owners)) { $ownerExpressions[] = $expr->in('integer.' . $ownerField, $owners); } else { $ownerExpressions[] = $expr->eq('integer.' . $ownerField, $owners); } } } } } if (!empty($ownerExpressions)) { $query->getCriteria()->andWhere(new CompositeExpression(CompositeExpression::TYPE_OR, $ownerExpressions)); } $query->from($allowedAliases); $this->addOrganizationLimits($query, $expr); return $query; }
/** * Parse order_by statement of expression and fills Criteria orderings. */ protected function parseOrderByExpression() { /** @var Criteria $criteria */ $criteria = $this->query->getCriteria(); /** @var Token $orderByToken */ $orderByToken = $this->stream->expect(Token::KEYWORD_TYPE, Query::KEYWORD_ORDER_BY); $from = $this->query->getFrom(); if (count($from) > 1 || $from[0] === '*') { throw new ExpressionSyntaxError(sprintf('Order By expression is allowed only for searching by single entity. Token "%s", value "%s"', $orderByToken->type, $orderByToken->value), $orderByToken->cursor); } $orderFieldType = $this->stream->expect(Token::STRING_TYPE, $this->types, null, false); $orderFieldName = $criteria->implodeFieldTypeName($orderFieldType ? $orderFieldType->value : Query::TYPE_TEXT, $this->stream->expect(Token::STRING_TYPE, null, 'Ordering field name is expected')->value); $orderDirection = Criteria::ASC; if (!$this->stream->isEOF() && $this->stream->current->test(Token::STRING_TYPE)) { $orderDirectionToken = $this->stream->expect(Token::STRING_TYPE, $this->orderDirections, null, false); if ($orderDirectionToken) { $orderDirection = $orderDirectionToken->value; } } $criteria->orderBy([$orderFieldName => $orderDirection]); }
/** * Set from parameters from search query * * @param \Oro\Bundle\SearchBundle\Query\Query $query * @param \Doctrine\ORM\QueryBuilder $qb */ protected function setFrom(Query $query, QueryBuilder $qb) { $useFrom = true; foreach ($query->getFrom() as $from) { if ($from == '*') { $useFrom = false; } } if ($useFrom) { $qb->andWhere($qb->expr()->in('search.alias', $query->getFrom())); } }
/** * Apply special behavior of class inheritance processing * * @param Query $query */ protected function applyModesBehavior(Query $query) { // process abstract indexes // make hashes increasing performance $fromParts = (array) $query->getFrom(); $fromHash = array_combine($fromParts, $fromParts); $aliases = $this->mapper->getEntitiesListAliases(); $aliasesHash = array_flip($aliases); if (!isset($fromHash['*'])) { foreach ($fromParts as $part) { $entityName = $part; $isAlias = false; if (isset($aliasesHash[$part])) { // find real name by alias $entityName = $aliasesHash[$part]; $isAlias = true; } $mode = $this->mapper->getEntityModeConfig($entityName); $descendants = $this->mapper->getRegisteredDescendants($entityName); if (false !== $descendants) { // add descendants to from clause foreach ($descendants as $fromPart) { if ($isAlias) { $fromPart = $aliases[$fromPart]; } if (!isset($fromHash[$fromPart])) { $fromHash[$fromPart] = $fromPart; } } } if ($mode === Mode::ONLY_DESCENDANTS) { unset($fromHash[$part]); } } } $collectedParts = array_values($fromHash); if ($collectedParts !== $fromParts) { $query->from($collectedParts); } }
/** * Apply ACL to search Query. * Removes all entities of the request to which the user has no access * * @param Query $query */ protected function applyAclToQuery(Query $query) { $allowedEntities = $this->getAllowedEntitiesListAliases(); $queryFromEntities = $query->getFrom(); $entitiesList = array_values($allowedEntities); // in query, from record !== '*' if (!empty($queryFromEntities) && $queryFromEntities[0] !== '*') { foreach ($queryFromEntities as $key => $fromEntityAlias) { if (!in_array($fromEntityAlias, $entitiesList)) { unset($queryFromEntities[$key]); } } $query->from($queryFromEntities); } else { $query->from($allowedEntities); } }
/** * @param Query $query * @return string * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function combineQueryString(Query $query) { $selectString = $query->getQuery(); $fromString = ''; if ($query->getFrom()) { $fromString .= ' from ' . implode(', ', $query->getFrom()); } $whereParts = array(); foreach ($query->getOptions() as $whereOptions) { if (is_array($whereOptions['fieldValue'])) { $whereOptions['fieldValue'] = '(' . implode(', ', $whereOptions['fieldValue']) . ')'; } $whereParts[] = sprintf('%s((%s)%s %s %s)', $whereOptions['type'], $whereOptions['fieldType'], $whereOptions['fieldName'], $whereOptions['condition'], $whereOptions['fieldValue']); } $whereString = ''; if ($whereParts) { $whereString .= ' where ' . implode(' ', $whereParts); } $orderByString = ''; if ($query->getOrderBy()) { $orderByString .= ' ' . $query->getOrderBy(); } if ($query->getOrderDirection()) { $orderByString .= ' ' . $query->getOrderDirection(); } if ($orderByString) { $orderByString = ' order by' . $orderByString; } $limitString = ''; if ($query->getMaxResults() && $query->getMaxResults() != Query::INFINITY) { $limitString = ' limit ' . $query->getMaxResults(); } $offsetString = ''; if ($query->getFirstResult()) { $offsetString .= ' offset ' . $query->getFirstResult(); } return $selectString . $fromString . $whereString . $orderByString . $limitString . $offsetString; }
/** * Get search query 'from' aliases * * @param Query $query * * @return array Return search aliases from Query. In case if from part = *, return all search aliases */ protected function getSearchAliases(Query $query) { $queryAliases = $query->getFrom(); if ($queryAliases[0] === '*') { $queryAliases = $this->mappingProvider->getEntitiesListAliases(); } return $queryAliases; }