Example #1
0
 /**
  * Adds a hint to a query object
  *
  * @param Query  $query
  * @param string $name
  * @param mixed  $value
  *
  * @return bool TRUE if the hint is added; otherwise, FALSE
  */
 public function addHint(Query $query, $name, $value)
 {
     $result = false;
     if ($name === Query::HINT_CUSTOM_TREE_WALKERS) {
         $walkers = $query->getHint(Query::HINT_CUSTOM_TREE_WALKERS);
         if (false === $walkers) {
             $walkers = [$value];
             $query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, $walkers);
             $result = true;
         } elseif (!in_array($value, $walkers, true)) {
             $walkers[] = $value;
             $query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, $walkers);
             $result = true;
         }
     } elseif ($name === Query::HINT_CUSTOM_OUTPUT_WALKER) {
         if ($query->getHint($name) !== $value) {
             $query->setHint($name, $value);
             $result = true;
         }
     } else {
         $query->setHint($name, $value);
         $result = true;
     }
     return $result;
 }
Example #2
0
 /**
  * Parses a query string.
  *
  * @return ParserResult
  */
 public function parse()
 {
     $AST = $this->getAST();
     if (($customWalkers = $this->_query->getHint(Query::HINT_CUSTOM_TREE_WALKERS)) !== false) {
         $this->_customTreeWalkers = $customWalkers;
     }
     if (($customOutputWalker = $this->_query->getHint(Query::HINT_CUSTOM_OUTPUT_WALKER)) !== false) {
         $this->_customOutputWalker = $customOutputWalker;
     }
     // Run any custom tree walkers over the AST
     if ($this->_customTreeWalkers) {
         $treeWalkerChain = new TreeWalkerChain($this->_query, $this->_parserResult, $this->_queryComponents);
         foreach ($this->_customTreeWalkers as $walker) {
             $treeWalkerChain->addTreeWalker($walker);
         }
         if ($AST instanceof AST\SelectStatement) {
             $treeWalkerChain->walkSelectStatement($AST);
         } else {
             if ($AST instanceof AST\UpdateStatement) {
                 $treeWalkerChain->walkUpdateStatement($AST);
             } else {
                 $treeWalkerChain->walkDeleteStatement($AST);
             }
         }
     }
     if ($this->_customOutputWalker) {
         $outputWalker = new $this->_customOutputWalker($this->_query, $this->_parserResult, $this->_queryComponents);
     } else {
         $outputWalker = new SqlWalker($this->_query, $this->_parserResult, $this->_queryComponents);
     }
     // Assign an SQL executor to the parser result
     $this->_parserResult->setSqlExecutor($outputWalker->getExecutor($AST));
     return $this->_parserResult;
 }
 /**
  * Appends a custom tree walker to the tree walkers hint.
  *
  * @param Query $query
  * @param string $walkerClass
  */
 private function appendTreeWalker(Query $query, $walkerClass)
 {
     $hints = $query->getHint(Query::HINT_CUSTOM_TREE_WALKERS);
     if ($hints === false) {
         $hints = array();
     }
     $hints[] = $walkerClass;
     $query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, $hints);
 }
Example #4
0
 /**
  * Add a custom TreeWalker $walker class name to
  * be included in the CustomTreeWalker hint list
  * of the given $query
  *
  * @param Query $query
  * @param string $walker
  * @return void
  */
 public static function addCustomTreeWalker(Query $query, $walker)
 {
     $customTreeWalkers = $query->getHint(Query::HINT_CUSTOM_TREE_WALKERS);
     if ($customTreeWalkers !== false && is_array($customTreeWalkers)) {
         $customTreeWalkers = array_merge($customTreeWalkers, array($walker));
     } else {
         $customTreeWalkers = array($walker);
     }
     $query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, $customTreeWalkers);
 }
Example #5
0
 /**
  * Parses a query string.
  *
  * @return ParserResult
  */
 public function parse()
 {
     $AST = $this->getAST();
     // Fix order of identification variables.
     // They have to appear in the select clause in the same order as the
     // declarations (from ... x join ... y join ... z ...) appear in the query
     // as the hydration process relies on that order for proper operation.
     if (count($this->_identVariableExpressions) > 1) {
         foreach ($this->_queryComponents as $dqlAlias => $qComp) {
             if (isset($this->_identVariableExpressions[$dqlAlias])) {
                 $expr = $this->_identVariableExpressions[$dqlAlias];
                 $key = array_search($expr, $AST->selectClause->selectExpressions);
                 unset($AST->selectClause->selectExpressions[$key]);
                 $AST->selectClause->selectExpressions[] = $expr;
             }
         }
     }
     if (($customWalkers = $this->_query->getHint(Query::HINT_CUSTOM_TREE_WALKERS)) !== false) {
         $this->_customTreeWalkers = $customWalkers;
     }
     if (($customOutputWalker = $this->_query->getHint(Query::HINT_CUSTOM_OUTPUT_WALKER)) !== false) {
         $this->_customOutputWalker = $customOutputWalker;
     }
     // Run any custom tree walkers over the AST
     if ($this->_customTreeWalkers) {
         $treeWalkerChain = new TreeWalkerChain($this->_query, $this->_parserResult, $this->_queryComponents);
         foreach ($this->_customTreeWalkers as $walker) {
             $treeWalkerChain->addTreeWalker($walker);
         }
         if ($AST instanceof AST\SelectStatement) {
             $treeWalkerChain->walkSelectStatement($AST);
         } else {
             if ($AST instanceof AST\UpdateStatement) {
                 $treeWalkerChain->walkUpdateStatement($AST);
             } else {
                 $treeWalkerChain->walkDeleteStatement($AST);
             }
         }
     }
     if ($this->_customOutputWalker) {
         $outputWalker = new $this->_customOutputWalker($this->_query, $this->_parserResult, $this->_queryComponents);
     } else {
         $outputWalker = new SqlWalker($this->_query, $this->_parserResult, $this->_queryComponents);
     }
     // Assign an SQL executor to the parser result
     $this->_parserResult->setSqlExecutor($outputWalker->getExecutor($AST));
     return $this->_parserResult;
 }
Example #6
0
 /**
  * SelectExpression ::=
  *      IdentificationVariable | StateFieldPathExpression |
  *      (AggregateExpression | "(" Subselect ")" | FunctionDeclaration) [["AS"] AliasResultVariable]
  *
  * @return \Doctrine\ORM\Query\AST\SelectExpression
  */
 public function SelectExpression()
 {
     $expression = null;
     $fieldAliasIdentificationVariable = null;
     $peek = $this->_lexer->glimpse();
     // First we recognize for an IdentificationVariable (DQL class alias)
     if ($peek['value'] != '.' && $peek['value'] != '(' && $this->_lexer->lookahead['type'] === Lexer::T_IDENTIFIER) {
         $expression = $this->IdentificationVariable();
     } else {
         if (($isFunction = $this->_isFunction()) !== false || $this->_isSubselect()) {
             if ($isFunction) {
                 if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
                     $expression = $this->AggregateExpression();
                 } else {
                     $expression = $this->FunctionDeclaration();
                 }
             } else {
                 $this->match(Lexer::T_OPEN_PARENTHESIS);
                 $expression = $this->Subselect();
                 $this->match(Lexer::T_CLOSE_PARENTHESIS);
             }
             if ($this->_lexer->isNextToken(Lexer::T_AS)) {
                 $this->match(Lexer::T_AS);
             }
             if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
                 $token = $this->_lexer->lookahead;
                 $fieldAliasIdentificationVariable = $this->AliasResultVariable();
                 // Include AliasResultVariable in query components.
                 $this->_queryComponents[$fieldAliasIdentificationVariable] = array('resultVariable' => $expression, 'nestingLevel' => $this->_nestingLevel, 'token' => $token);
             }
         } else {
             // Deny hydration of partial objects if doctrine.forcePartialLoad query hint not defined
             if ($this->_query->getHydrationMode() == Query::HYDRATE_OBJECT && !$this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) {
                 throw DoctrineException::partialObjectsAreDangerous();
             }
             $expression = $this->StateFieldPathExpression();
         }
     }
     return new AST\SelectExpression($expression, $fieldAliasIdentificationVariable);
 }
 /**
  * Parses a query string.
  *
  * @return ParserResult
  */
 public function parse()
 {
     $AST = $this->getAST();
     if (($customWalkers = $this->query->getHint(Query::HINT_CUSTOM_TREE_WALKERS)) !== false) {
         $this->customTreeWalkers = $customWalkers;
     }
     if (($customOutputWalker = $this->query->getHint(Query::HINT_CUSTOM_OUTPUT_WALKER)) !== false) {
         $this->customOutputWalker = $customOutputWalker;
     }
     // Run any custom tree walkers over the AST
     if ($this->customTreeWalkers) {
         $treeWalkerChain = new TreeWalkerChain($this->query, $this->parserResult, $this->queryComponents);
         foreach ($this->customTreeWalkers as $walker) {
             $treeWalkerChain->addTreeWalker($walker);
         }
         switch (true) {
             case $AST instanceof AST\UpdateStatement:
                 $treeWalkerChain->walkUpdateStatement($AST);
                 break;
             case $AST instanceof AST\DeleteStatement:
                 $treeWalkerChain->walkDeleteStatement($AST);
                 break;
             case $AST instanceof AST\SelectStatement:
             default:
                 $treeWalkerChain->walkSelectStatement($AST);
         }
         $this->queryComponents = $treeWalkerChain->getQueryComponents();
     }
     $outputWalkerClass = $this->customOutputWalker ?: __NAMESPACE__ . '\\SqlWalker';
     $outputWalker = new $outputWalkerClass($this->query, $this->parserResult, $this->queryComponents);
     // Assign an SQL executor to the parser result
     $this->parserResult->setSqlExecutor($outputWalker->getExecutor($AST));
     return $this->parserResult;
 }
    /**
     * This query works well with small offset, but if want to use it with large offsets please refer to the link on how to implement
     * http://www.scribd.com/doc/14683263/Efficient-Pagination-Using-MySQL
     * This will only check permissions on the first entity added in the from clause, it will not check permissions
     * By default the number of rows returned are 10 starting from 0
     *
     * @param Query $query
     *
     * @return string
     */
    private function getPermittedAclIdsSQLForUser(Query $query)
    {
        $aclConnection = $this->em->getConnection();
        $databasePrefix = is_file($aclConnection->getDatabase()) ? '' : $aclConnection->getDatabase() . '.';
        $mask = $query->getHint('acl.mask');
        $rootEntity = '"' . str_replace('\\', '\\\\', $query->getHint('acl.root.entity')) . '"';
        /* @var $token TokenInterface */
        $token = $this->securityContext->getToken();
        $userRoles = array();
        $user = null;
        if (!is_null($token)) {
            $user = $token->getUser();
            $userRoles = $this->roleHierarchy->getReachableRoles($token->getRoles());
        }
        // Security context does not provide anonymous role automatically.
        $uR = array('"IS_AUTHENTICATED_ANONYMOUSLY"');
        /* @var $role RoleInterface */
        foreach ($userRoles as $role) {
            // The reason we ignore this is because by default FOSUserBundle adds ROLE_USER for every user
            if ($role->getRole() !== 'ROLE_USER') {
                $uR[] = '"' . $role->getRole() . '"';
            }
        }
        $uR = array_unique($uR);
        $inString = implode(' OR s.identifier = ', $uR);
        if (is_object($user)) {
            $inString .= ' OR s.identifier = "' . str_replace('\\', '\\\\', get_class($user)) . '-' . $user->getUserName() . '"';
        }
        $selectQuery = <<<SELECTQUERY
SELECT DISTINCT o.object_identifier as id FROM {$databasePrefix}acl_object_identities as o
INNER JOIN {$databasePrefix}acl_classes c ON c.id = o.class_id
LEFT JOIN {$databasePrefix}acl_entries e ON (
    e.class_id = o.class_id AND (e.object_identity_id = o.id
    OR {$aclConnection->getDatabasePlatform()->getIsNullExpression('e.object_identity_id')})
)
LEFT JOIN {$databasePrefix}acl_security_identities s ON (
s.id = e.security_identity_id
)
WHERE c.class_type = {$rootEntity}
AND (s.identifier = {$inString})
AND e.mask & {$mask} > 0
SELECTQUERY;
        return $selectQuery;
    }
Example #9
0
 /**
  * Determine whether to use an output walker for the query
  *
  * @param Query $query The query.
  *
  * @return bool
  */
 private function useOutputWalker(Query $query)
 {
     if ($this->useOutputWalkers === null) {
         return (bool) $query->getHint(Query::HINT_CUSTOM_OUTPUT_WALKER) == false;
     }
     return $this->useOutputWalkers;
 }
    /**
     * This query works well with small offset, but if want to use it with large offsets please refer to the link on how to implement
     * http://www.scribd.com/doc/14683263/Efficient-Pagination-Using-MySQL
     * This will only check permissions on first enity added in the from clause, it will not check permissions
     * By default the number of rows returned are 10 starting from 0
     *
     * @param Query         $query        Query
     * @param QueryBuilder  $queryBuilder QueryBuilder
     * @param UserInterface $user         User
     *
     * @return string
     */
    private function getPermittedIdsACLSQLForUser(Query $query, QueryBuilder $queryBuilder, UserInterface $user = null)
    {
        $database = $this->aclConnection->getDatabase();
        $mask = $query->getHint('acl.mask');
        $rootEntities = $query->getHint('acl.root.entities');
        foreach ($rootEntities as $rootEntity) {
            $rE[] = '"' . str_replace('\\', '\\\\', $rootEntity) . '"';
            // For now ACL will be checked for first root entity, it will not check for all other entities in join etc..,
            break;
        }
        $rootEntities = implode(',', $rE);
        if (!is_object($user)) {
            $token = $this->securityContext->getToken();
            // for now lets imagine we will have token i.e user is logged in
            $user = $token->getUser();
        }
        $identifier = "''";
        if (is_object($user)) {
            $identifiers = array();
            $userRoles = $user->getRoles();
            foreach ($userRoles as $role) {
                // The reason we ignore this is because by default FOSUserBundle adds ROLE_USER for every user
                if ($role !== 'ROLE_USER') {
                    $identifiers[] = $role;
                }
            }
            $identifiers[] = str_replace('\\', '\\\\', get_class($user)) . '-' . $user->getUserName();
            $identifier = '"' . implode('","', $identifiers) . '"';
        }
        $isNullExpression = $this->aclConnection->getDatabasePlatform()->getIsNullExpression('e.object_identity_id');
        $selectQuery = <<<SELECTQUERY
            SELECT DISTINCT o.object_identifier as id FROM {$database}.acl_object_identities as o
            INNER JOIN {$database}.acl_classes c ON c.id = o.class_id
            LEFT JOIN {$database}.acl_entries e ON (
                e.class_id = o.class_id AND (e.object_identity_id = o.id OR {$isNullExpression})
            )
            LEFT JOIN {$database}.acl_security_identities s ON (
                s.id = e.security_identity_id
            )
            WHERE c.class_type = {$rootEntities}
            AND s.identifier IN ({$identifier})
            AND e.mask >= {$mask}

SELECTQUERY;
        return $selectQuery;
    }