Skip to content

Instantly share code, notes, and snippets.

@temp
Created May 15, 2015 06:24
Show Gist options
  • Save temp/26148b1fc700cc969e07 to your computer and use it in GitHub Desktop.
Save temp/26148b1fc700cc969e07 to your computer and use it in GitHub Desktop.
<?php
/**
* phlexible
*
* @copyright 2007 brainbits GmbH (http://www.brainbits.net)
* @license http://www.makeweb.de/LICENCE Dummy Licence
*/
namespace Phlexible\Component\Expression;
use Doctrine\ORM\QueryBuilder;
use Webmozart\Expression\Comparison\Contains;
use Webmozart\Expression\Comparison\EndsWith;
use Webmozart\Expression\Comparison\Equals;
use Webmozart\Expression\Comparison\GreaterThan;
use Webmozart\Expression\Comparison\GreaterThanEqual;
use Webmozart\Expression\Comparison\In;
use Webmozart\Expression\Comparison\IsEmpty;
use Webmozart\Expression\Comparison\KeyExists;
use Webmozart\Expression\Comparison\KeyNotExists;
use Webmozart\Expression\Comparison\LessThan;
use Webmozart\Expression\Comparison\LessThanEqual;
use Webmozart\Expression\Comparison\Matches;
use Webmozart\Expression\Comparison\NotEmpty;
use Webmozart\Expression\Comparison\NotEquals;
use Webmozart\Expression\Comparison\NotSame;
use Webmozart\Expression\Comparison\Same;
use Webmozart\Expression\Comparison\StartsWith;
use Webmozart\Expression\Expression;
use Webmozart\Expression\Logic\AlwaysFalse;
use Webmozart\Expression\Logic\AlwaysTrue;
use Webmozart\Expression\Logic\Conjunction;
use Webmozart\Expression\Logic\Disjunction;
use Webmozart\Expression\Logic\Literal;
use Webmozart\Expression\Logic\Not;
use Webmozart\Expression\Selector\All;
use Webmozart\Expression\Selector\AtLeast;
use Webmozart\Expression\Selector\AtMost;
use Webmozart\Expression\Selector\Exactly;
use Webmozart\Expression\Selector\Key;
/**
* Expression visitor
*
* @author Stephan Wentz <sw@brainbits.net>
*/
class QueryBuilderExpressionVisitor
{
/**
* @var QueryBuilder
*/
private $qb;
/**
* @var string
*/
private $currentField;
/**
* @param QueryBuilder $qb
*/
public function __construct(QueryBuilder $qb)
{
$this->qb = $qb;
}
/**
* Dispatches walking an expression to the appropriate handler.
*
* @param Expression $expr
*
* @return mixed
*
* @throws \RuntimeException
*/
public function dispatch(Expression $expr)
{
switch (true) {
case ($expr instanceof Conjunction):
$and = $this->qb->expr()->andX();
foreach ($expr->getConjuncts() as $conjunct) {
$and->add($this->dispatch($conjunct));
}
return $and;
case ($expr instanceof Disjunction):
$or = $this->qb->expr()->orX();
foreach ($expr->getDisjuncts() as $disjunct) {
$or->add($this->dispatch($disjunct));
}
return $or;
case ($expr instanceof Key):
$this->currentField = $expr->getKey();
$result = $this->dispatch($expr->getExpression());
$this->currentField = null;
return $result;
case ($expr instanceof AlwaysTrue):
return $this->qb->expr()->eq(1, 1);
case ($expr instanceof AlwaysFalse):
return $this->qb->expr()->eq(1, 0);
case ($expr instanceof Not):
return $this->qb->expr()->not($this->dispatch($expr->getNegatedExpression()));
case ($expr instanceof All):
case ($expr instanceof AtLeast):
case ($expr instanceof AtMost):
case ($expr instanceof Exactly):
throw new \RuntimeException("Unsupported selector " . get_class($expr));
case ($expr instanceof Literal):
return $this->walkComparison($expr);
default:
throw new \RuntimeException("Unknown Expression " . get_class($expr));
}
}
/**
* {@inheritDoc}
*/
public function walkComparison(Literal $comparison)
{
if (!$this->currentField) {
throw new \RuntimeException("Comparison without field");
}
$field = 'm.' . $this->currentField;
if ($comparison instanceof Contains) {
$value = $comparison->getComparedValue();
return $this->qb->expr()->like($field, $this->literal("%$value%"));
} elseif ($comparison instanceof EndsWith) {
$value = $comparison->getAcceptedSuffix();
return $this->qb->expr()->eq($field, $this->literal("%$value"));
} elseif ($comparison instanceof Equals) {
$value = $comparison->getComparedValue();
return $this->qb->expr()->eq($field, $this->literal($value));
} elseif ($comparison instanceof GreaterThan) {
$value = $comparison->getComparedValue();
return $this->qb->expr()->gt($field, $this->literal($value));
} elseif ($comparison instanceof GreaterThanEqual) {
$value = $comparison->getComparedValue();
return $this->qb->expr()->gte($field, $this->literal($value));
} elseif ($comparison instanceof In) {
$values = $comparison->getAcceptedValues();
return $this->qb->expr()->in($field, $this->literal($values));
} elseif ($comparison instanceof IsEmpty) {
throw new \RuntimeException("Unsupported comparison " . get_class($comparison));
} elseif ($comparison instanceof KeyExists) {
throw new \RuntimeException("Unsupported comparison " . get_class($comparison));
} elseif ($comparison instanceof KeyNotExists) {
throw new \RuntimeException("Unsupported comparison " . get_class($comparison));
} elseif ($comparison instanceof LessThan) {
$value = $comparison->getComparedValue();
return $this->qb->expr()->lt($field, $this->literal($value));
} elseif ($comparison instanceof LessThanEqual) {
$value = $comparison->getComparedValue();
return $this->qb->expr()->lte($field, $this->literal($value));
} elseif ($comparison instanceof Matches) {
throw new \RuntimeException("Unsupported comparison " . get_class($comparison));
} elseif ($comparison instanceof NotEmpty) {
throw new \RuntimeException("Unsupported comparison " . get_class($comparison));
} elseif ($comparison instanceof NotEquals) {
$value = $comparison->getComparedValue();
return $this->qb->expr()->neq($field, $this->literal($value));
} elseif ($comparison instanceof NotSame) {
$value = $comparison->getComparedValue();
return $this->qb->expr()->neq($field, $this->literal($value));
} elseif ($comparison instanceof Same) {
$value = $comparison->getComparedValue();
return $this->qb->expr()->eq($field, $this->literal($value));
} elseif ($comparison instanceof StartsWith) {
$value = $comparison->getAcceptedPrefix();
return $this->qb->expr()->like($field, $this->literal("$value%"));
} else {
throw new \RuntimeException("Unknown comparison " . get_class($comparison));
}
}
private function literal($value)
{
if (is_array($value)) {
foreach ($value as $index => $v) {
$value[$index] = $this->qb->expr()->literal($v);
}
} else {
$value = $this->qb->expr()->literal($value);
}
return $value;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment