/** * StateFieldPathExpression ::= SimpleStateFieldPathExpression | SimpleStateFieldAssociationPathExpression */ public function _StateFieldPathExpression() { if (!empty($this->_deferredPathExpressionStacks)) { $exprStack = array_pop($this->_deferredPathExpressionStacks); $this->match(Lexer::T_IDENTIFIER); $parts = array($this->_lexer->token['value']); while ($this->_lexer->isNextToken('.')) { $this->match('.'); $this->match(Lexer::T_IDENTIFIER); $parts[] = $this->_lexer->token['value']; } $expr = new AST\StateFieldPathExpression($parts); $exprStack[] = $expr; array_push($this->_deferredPathExpressionStacks, $exprStack); return $expr; // EARLY EXIT! } $parts = array(); $stateFieldSeen = false; $assocSeen = false; $identificationVariable = $this->_IdentificationVariable(); if (!isset($this->_queryComponents[$identificationVariable])) { $this->syntaxError("IdentificationVariable '{$identificationVariable}' was not declared."); } $qComp = $this->_queryComponents[$identificationVariable]; $parts[] = $identificationVariable; $class = $qComp['metadata']; if (!$this->_lexer->isNextToken('.')) { if ($class->isIdentifierComposite) { $this->syntaxError(); } $parts[] = $class->identifier[0]; } while ($this->_lexer->isNextToken('.')) { if ($stateFieldSeen) { $this->syntaxError(); } $this->match('.'); $part = $this->_IdentificationVariable(); if ($class->hasField($part)) { $stateFieldSeen = true; } else { if ($class->hasAssociation($part)) { $assoc = $class->getAssociationMapping($part); $class = $this->_em->getClassMetadata($assoc->getTargetEntityName()); $assocSeen = true; } else { $this->semanticalError('The class ' . $class->name . ' has no field or association named ' . $part); } } $parts[] = $part; } $pathExpr = new AST\StateFieldPathExpression($parts); if ($assocSeen) { $pathExpr->setIsSimpleStateFieldAssociationPathExpression(true); } else { $pathExpr->setIsSimpleStateFieldPathExpression(true); } return $pathExpr; }
/** * FunctionDeclaration ::= FunctionsReturningStrings | FunctionsReturningNumerics | FunctionsReturningDatetime */ public function FunctionDeclaration() { $token = $this->_lexer->lookahead; $funcName = strtolower($token['value']); // Check for built-in functions first! if (isset(self::$_STRING_FUNCTIONS[$funcName])) { return $this->FunctionsReturningStrings(); } else { if (isset(self::$_NUMERIC_FUNCTIONS[$funcName])) { return $this->FunctionsReturningNumerics(); } else { if (isset(self::$_DATETIME_FUNCTIONS[$funcName])) { return $this->FunctionsReturningDatetime(); } } } // Check for custom functions afterwards $config = $this->_em->getConfiguration(); if (($func = $config->getCustomStringFunction($funcName)) !== null) { self::$_STRING_FUNCTIONS[$funcName] = $func; return $this->FunctionsReturningStrings(); } else { if (($func = $config->getCustomNumericFunction($funcName)) !== null) { self::$_NUMERIC_FUNCTIONS[$funcName] = $func; return $this->FunctionsReturningNumerics(); } else { if (($func = $config->getCustomDatetimeFunction($funcName)) !== null) { self::$_DATETIME_FUNCTIONS[$funcName] = $func; return $this->FunctionsReturningDatetime(); } } } $this->syntaxError('known function', $token); }
public function CustomFunctionsReturningStrings() { $funcName = $this->_lexer->lookahead['value']; // getCustomStringFunction is case-insensitive $funcClass = $this->_em->getConfiguration()->getCustomStringFunction($funcName); $function = new $funcClass($funcName); $function->parse($this); return $function; }
/** * Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" JoinAssociationPathExpression * ["AS"] AliasIdentificationVariable [("ON" | "WITH") ConditionalExpression] * * @return \Doctrine\ORM\Query\AST\Join */ public function Join() { // Check Join type $joinType = AST\Join::JOIN_TYPE_INNER; if ($this->_lexer->isNextToken(Lexer::T_LEFT)) { $this->match(Lexer::T_LEFT); // Possible LEFT OUTER join if ($this->_lexer->isNextToken(Lexer::T_OUTER)) { $this->match(Lexer::T_OUTER); $joinType = AST\Join::JOIN_TYPE_LEFTOUTER; } else { $joinType = AST\Join::JOIN_TYPE_LEFT; } } else { if ($this->_lexer->isNextToken(Lexer::T_INNER)) { $this->match(Lexer::T_INNER); } } $this->match(Lexer::T_JOIN); $joinPathExpression = $this->JoinAssociationPathExpression(); if ($this->_lexer->isNextToken(Lexer::T_AS)) { $this->match(Lexer::T_AS); } $token = $this->_lexer->lookahead; $aliasIdentificationVariable = $this->AliasIdentificationVariable(); // Verify that the association exists. $parentClass = $this->_queryComponents[$joinPathExpression->identificationVariable]['metadata']; $assocField = $joinPathExpression->associationField; if (!$parentClass->hasAssociation($assocField)) { $this->semanticalError("Class " . $parentClass->name . " has no association named '{$assocField}'."); } $targetClassName = $parentClass->getAssociationMapping($assocField)->targetEntityName; // Building queryComponent $joinQueryComponent = array('metadata' => $this->_em->getClassMetadata($targetClassName), 'parent' => $joinPathExpression->identificationVariable, 'relation' => $parentClass->getAssociationMapping($assocField), 'map' => null, 'nestingLevel' => $this->_nestingLevel, 'token' => $token); $this->_queryComponents[$aliasIdentificationVariable] = $joinQueryComponent; // Create AST node $join = new AST\Join($joinType, $joinPathExpression, $aliasIdentificationVariable); // Check for ad-hoc Join conditions if ($this->_lexer->isNextToken(Lexer::T_ON) || $this->_lexer->isNextToken(Lexer::T_WITH)) { if ($this->_lexer->isNextToken(Lexer::T_ON)) { $this->match(Lexer::T_ON); $join->whereType = AST\Join::JOIN_WHERE_ON; } else { $this->match(Lexer::T_WITH); } $join->conditionalExpression = $this->ConditionalExpression(); } return $join; }