/** * 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; }
/** * 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; }
/** * JoinAssociationDeclaration ::= JoinAssociationPathExpression ["AS"] AliasIdentificationVariable [IndexBy] * * @return \Doctrine\ORM\Query\AST\JoinAssociationPathExpression */ public function JoinAssociationDeclaration() { $joinAssociationPathExpression = $this->JoinAssociationPathExpression(); if ($this->_lexer->isNextToken(Lexer::T_AS)) { $this->match(Lexer::T_AS); } $aliasIdentificationVariable = $this->AliasIdentificationVariable(); $indexBy = $this->_lexer->isNextToken(Lexer::T_INDEX) ? $this->IndexBy() : null; $identificationVariable = $joinAssociationPathExpression->identificationVariable; $field = $joinAssociationPathExpression->associationField; $class = $this->_queryComponents[$identificationVariable]['metadata']; $targetClass = $this->_em->getClassMetadata($class->associationMappings[$field]['targetEntity']); // Building queryComponent $joinQueryComponent = array('metadata' => $targetClass, 'parent' => $joinAssociationPathExpression->identificationVariable, 'relation' => $class->getAssociationMapping($field), 'map' => null, 'nestingLevel' => $this->_nestingLevel, 'token' => $this->_lexer->lookahead); $this->_queryComponents[$aliasIdentificationVariable] = $joinQueryComponent; return new AST\JoinAssociationDeclaration($joinAssociationPathExpression, $aliasIdentificationVariable, $indexBy); }