Skip to content

Instantly share code, notes, and snippets.

@maryo
Last active December 24, 2015 07:19
Show Gist options
  • Save maryo/6762610 to your computer and use it in GitHub Desktop.
Save maryo/6762610 to your computer and use it in GitHub Desktop.
Doctrine2 Sandboxing Safe Condition DQL AST Walker
<?php
use Doctrine\ORM\Query\AST;
use Doctrine\ORM\Query\TreeWalkerAdapter;
class SafeConditionWalker extends TreeWalkerAdapter
{
/** @var bool */
private $inCondition = false;
/**
* {@inheritDoc}
*/
public function walkSelectStatement(AST\SelectStatement $selectStatement)
{
$this->notAllowedIfInCondition('select statements are not allowed.');
if ($selectStatement->whereClause) {
$this->walkWhereClause($selectStatement->whereClause);
}
if ($selectStatement->havingClause) {
$this->walkHavingClause($selectStatement->havingClause);
}
if ($selectStatement->orderByClause) {
$this->walkOrderByClause($selectStatement->orderByClause);
}
}
/**
* {@inheritDoc}
*/
public function walkUpdateStatement(AST\UpdateStatement $updateStatement)
{
$this->notAllowedIfInCondition('update statements are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkDeleteStatement(AST\DeleteStatement $deleteStatement)
{
$this->notAllowedIfInCondition('delete statements are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkSelectClause($selectClause)
{
$this->notAllowedIfInCondition('select clauses are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkFromClause($fromClause)
{
$this->notAllowedIfInCondition('from clauses are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkHavingClause($havingClause)
{
$this->walkConditionalExpression($havingClause->conditionalExpression);
}
/**
* {@inheritDoc}
*/
public function walkJoin($join)
{
$this->notAllowedIfInCondition('joins are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkSelectExpression($selectExpression)
{
$this->notAllowedIfInCondition('select expression are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkQuantifiedExpression($quantifiedExpression)
{
$this->notAllowedIfInCondition('quantified expressions are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkSubselect($subselect)
{
$this->notAllowedIfInCondition('subselects are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkSubselectFromClause($subselectFromClause)
{
$this->notAllowedIfInCondition('subselect from clauses are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkSimpleSelectClause($simpleSelectClause)
{
$this->notAllowedIfInCondition('simple select clauses are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkSimpleSelectExpression($simpleSelectExpression)
{
$this->notAllowedIfInCondition('simple select expressions are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkAggregateExpression($aggregateExpression)
{
$this->walkSimpleArithmeticExpression($aggregateExpression->pathExpression);
}
/**
* {@inheritDoc}
*/
public function walkDeleteClause(AST\DeleteClause $deleteClause)
{
$this->notAllowedIfInCondition('delete clauses are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkUpdateClause($updateClause)
{
$this->notAllowedIfInCondition('update clauses are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkUpdateItem($updateItem)
{
$this->notAllowedIfInCondition('update items are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkWhereClause($whereClause)
{
$this->walkConditionalExpression($whereClause->conditionalExpression);
}
/**
* {@inheritDoc}
*/
public function walkConditionalExpression($conditionalExpression)
{
$this->inCondition = true;
if (!$conditionalExpression instanceof AST\ConditionalExpression) {
return $this->walkConditionalTerm($conditionalExpression);
}
array_walk($conditionalExpression->conditionalTerms, array($this, 'walkConditionalTerm'));
}
/**
* {@inheritDoc}
*/
public function walkConditionalTerm($conditionalTerm)
{
if (!$conditionalTerm instanceof AST\ConditionalTerm) {
return $this->walkConditionalFactor($conditionalTerm);
}
array_walk($conditionalTerm->conditionalFactors, array($this, 'walkConditionalFactor'));
}
/**
* {@inheritDoc}
*/
public function walkConditionalFactor($factor)
{
$this->walkConditionalPrimary($factor instanceof AST\ConditionalFactor ? $factor->conditionalPrimary : $factor);
}
/**
* {@inheritDoc}
*/
public function walkConditionalPrimary($primary)
{
if ($primary->isSimpleConditionalExpression()) {
return $primary->simpleConditionalExpression->dispatch($this);
}
if ($primary->isConditionalExpression()) {
$this->walkConditionalExpression($primary->conditionalExpression);
}
}
/**
* {@inheritDoc}
*/
public function walkExistsExpression($existsExpression)
{
$this->notAllowedIfInCondition('exists expressions are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkCollectionMemberExpression($collectionMemberExpression)
{
if ($collectionMemberExpression->entityExpression instanceof AST\InputParameter) {
$this->walkInputParameter($collectionMemberExpression->entityExpression);
}
}
/**
* {@inheritDoc}
*/
public function walkNullComparisonExpression($nullComparisonExpression)
{
if ($nullComparisonExpression->expression instanceof AST\InputParameter) {
$this->walkInputParameter($nullComparisonExpression->expression);
}
$nullComparisonExpression->expression->dispatch($this);
}
/**
* {@inheritDoc}
*/
public function walkInExpression($inExpression)
{
$this->walkArithmeticExpression($inExpression->expression);
if ($inExpression->subselect) {
$this->walkSubselect($inExpression->subselect);
}
array_walk($inExpression->literals, array($this, 'walkInParameter'));
}
/**
* {@inheritDoc}
*/
public function walkInstanceOfExpression($instanceOfExpression)
{
$this->notAllowedIfInCondition('instanceOf expressions are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkInParameter($inParameter)
{
if ($inParameter instanceof AST\InputParameter) {
$this->walkInputParameter($inParameter);
}
}
/**
* {@inheritDoc}
*/
public function walkBetweenExpression($betweenExpression)
{
$this->walkArithmeticExpression($betweenExpression->expression);
$this->walkArithmeticExpression($betweenExpression->leftBetweenExpression);
$this->walkArithmeticExpression($betweenExpression->rightBetweenExpression);
}
/**
* {@inheritDoc}
*/
public function walkLikeExpression($likeExpression)
{
$likeExpression->stringExpression->dispatch($this);
if ($likeExpression->stringPattern instanceof AST\InputParameter) {
$this->walkInputParameter($likeExpression->stringPattern);
}
}
/**
* {@inheritDoc}
*/
public function walkComparisonExpression($comparisonExpression)
{
if ($comparisonExpression->leftExpression instanceof AST\Node) {
$comparisonExpression->leftExpression->dispatch($this);
}
if ($comparisonExpression->rightExpression instanceof AST\Node) {
$comparisonExpression->rightExpression->dispatch($this);
}
}
/**
* {@inheritDoc}
*/
public function walkInputParameter($inputParameter)
{
$this->notAllowedIfInCondition('input parameters are not allowed.');
}
/**
* {@inheritDoc}
*/
public function walkArithmeticExpression($arithmeticExpression)
{
if ($arithmeticExpression->isSubselect()) {
$this->walkSubselect($arithmeticExpression->subselect);
}
$this->walkSimpleArithmeticExpression($arithmeticExpression->simpleArithmeticExpression);
}
/**
* {@inheritDoc}
*/
public function walkSimpleArithmeticExpression($simpleArithmeticExpression)
{
if (!$simpleArithmeticExpression instanceof AST\SimpleArithmeticExpression) {
return $this->walkArithmeticTerm($simpleArithmeticExpression);
}
array_walk($simpleArithmeticExpression->arithmeticTerms, array($this, 'walkArithmeticTerm'));
}
/**
* {@inheritDoc}
*/
public function walkArithmeticTerm($arithmeticTerm)
{
if (is_string($arithmeticTerm)) {
return;
}
if (!$arithmeticTerm instanceof AST\ArithmeticTerm) {
return $this->walkArithmeticFactor($arithmeticTerm);
}
array_walk($arithmeticTerm->arithmeticFactors, array($this, 'walkArithmeticFactor'));
}
/**
* {@inheritDoc}
*/
public function walkArithmeticFactor($arithmeticFactor)
{
if (is_string($arithmeticFactor)) {
return;
} elseif (!$arithmeticFactor instanceof AST\ArithmeticFactor) {
return $this->walkArithmeticPrimary($arithmeticFactor);
}
$this->walkArithmeticPrimary($arithmeticFactor->arithmeticPrimary);
}
/**
* {@inheritDoc}
*/
public function walkArithmeticPrimary($arithmeticPrimary)
{
if ($arithmeticPrimary instanceof AST\SimpleArithmeticExpression) {
$this->walkSimpleArithmeticExpression($arithmeticPrimary);
} elseif ($arithmeticPrimary instanceof AST\Node) {
$arithmeticPrimary->dispatch($this);
}
}
/**
* {@inheritDoc}
*/
public function walkStringPrimary($stringPrimary)
{
if (!is_string($stringPrimary)) {
$stringPrimary->dispatch($this);
}
}
/**
* @param string $message
* @throws \Exception
*/
private function notAllowedIfInCondition($message)
{
if ($this->inCondition) {
throw InvalidQueryException::notAllowed($message);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment