2012-01-22 16:35:06 +04:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Doctrine ORM
|
|
|
|
*
|
|
|
|
* LICENSE
|
|
|
|
*
|
|
|
|
* This source file is subject to the new BSD license that is bundled
|
|
|
|
* with this package in the file LICENSE. This license can also be viewed
|
|
|
|
* at http://hobodave.com/license.txt
|
|
|
|
*
|
|
|
|
* @category DoctrineExtensions
|
|
|
|
* @package DoctrineExtensions\Paginate
|
|
|
|
* @author David Abdemoulaie <dave@hobodave.com>
|
|
|
|
* @copyright Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/)
|
|
|
|
* @license http://hobodave.com/license.txt New BSD License
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace Doctrine\ORM\Tools\Pagination;
|
|
|
|
|
|
|
|
use Doctrine\ORM\Query\AST\ArithmeticExpression,
|
|
|
|
Doctrine\ORM\Query\AST\SimpleArithmeticExpression,
|
|
|
|
Doctrine\ORM\Query\TreeWalkerAdapter,
|
|
|
|
Doctrine\ORM\Query\AST\SelectStatement,
|
|
|
|
Doctrine\ORM\Query\AST\PathExpression,
|
|
|
|
Doctrine\ORM\Query\AST\InExpression,
|
|
|
|
Doctrine\ORM\Query\AST\NullComparisonExpression,
|
|
|
|
Doctrine\ORM\Query\AST\InputParameter,
|
|
|
|
Doctrine\ORM\Query\AST\ConditionalPrimary,
|
|
|
|
Doctrine\ORM\Query\AST\ConditionalTerm,
|
|
|
|
Doctrine\ORM\Query\AST\ConditionalExpression,
|
|
|
|
Doctrine\ORM\Query\AST\ConditionalFactor,
|
|
|
|
Doctrine\ORM\Query\AST\WhereClause;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replaces the whereClause of the AST with a WHERE id IN (:foo_1, :foo_2) equivalent
|
|
|
|
*
|
|
|
|
* @category DoctrineExtensions
|
|
|
|
* @package DoctrineExtensions\Paginate
|
|
|
|
* @author David Abdemoulaie <dave@hobodave.com>
|
|
|
|
* @copyright Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/)
|
|
|
|
* @license http://hobodave.com/license.txt New BSD License
|
|
|
|
*/
|
|
|
|
class WhereInWalker extends TreeWalkerAdapter
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* ID Count hint name
|
|
|
|
*/
|
|
|
|
const HINT_PAGINATOR_ID_COUNT = 'doctrine.id.count';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Primary key alias for query
|
|
|
|
*/
|
|
|
|
const PAGINATOR_ID_ALIAS = 'dpid';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replaces the whereClause in the AST
|
|
|
|
*
|
|
|
|
* Generates a clause equivalent to WHERE IN (:dpid_1, :dpid_2, ...)
|
|
|
|
*
|
|
|
|
* The parameter namespace (dpid) is defined by
|
|
|
|
* the PAGINATOR_ID_ALIAS
|
|
|
|
*
|
|
|
|
* The total number of parameters is retrieved from
|
|
|
|
* the HINT_PAGINATOR_ID_COUNT query hint
|
|
|
|
*
|
|
|
|
* @param SelectStatement $AST
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function walkSelectStatement(SelectStatement $AST)
|
|
|
|
{
|
|
|
|
$rootComponents = array();
|
2012-03-24 14:16:32 +04:00
|
|
|
foreach ($this->_getQueryComponents() as $dqlAlias => $qComp) {
|
2012-01-22 16:35:06 +04:00
|
|
|
$isParent = array_key_exists('parent', $qComp)
|
|
|
|
&& $qComp['parent'] === null
|
|
|
|
&& $qComp['nestingLevel'] == 0
|
|
|
|
;
|
|
|
|
if ($isParent) {
|
|
|
|
$rootComponents[] = array($dqlAlias => $qComp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (count($rootComponents) > 1) {
|
|
|
|
throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction");
|
|
|
|
}
|
|
|
|
$root = reset($rootComponents);
|
|
|
|
$parentName = key($root);
|
|
|
|
$parent = current($root);
|
|
|
|
|
|
|
|
$pathExpression = new PathExpression(
|
|
|
|
PathExpression::TYPE_STATE_FIELD, $parentName, $parent['metadata']->getSingleIdentifierFieldName()
|
|
|
|
);
|
|
|
|
$pathExpression->type = PathExpression::TYPE_STATE_FIELD;
|
|
|
|
|
|
|
|
$count = $this->_getQuery()->getHint(self::HINT_PAGINATOR_ID_COUNT);
|
|
|
|
|
|
|
|
if ($count > 0) {
|
|
|
|
$arithmeticExpression = new ArithmeticExpression();
|
|
|
|
$arithmeticExpression->simpleArithmeticExpression = new SimpleArithmeticExpression(
|
|
|
|
array($pathExpression)
|
|
|
|
);
|
|
|
|
$expression = new InExpression($arithmeticExpression);
|
|
|
|
$ns = self::PAGINATOR_ID_ALIAS;
|
|
|
|
|
|
|
|
for ($i = 1; $i <= $count; $i++) {
|
|
|
|
$expression->literals[] = new InputParameter(":{$ns}_$i");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$expression = new NullComparisonExpression($pathExpression);
|
|
|
|
$expression->not = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$conditionalPrimary = new ConditionalPrimary;
|
|
|
|
$conditionalPrimary->simpleConditionalExpression = $expression;
|
|
|
|
if ($AST->whereClause) {
|
|
|
|
if ($AST->whereClause->conditionalExpression instanceof ConditionalTerm) {
|
|
|
|
$AST->whereClause->conditionalExpression->conditionalFactors[] = $conditionalPrimary;
|
|
|
|
} elseif ($AST->whereClause->conditionalExpression instanceof ConditionalPrimary) {
|
|
|
|
$AST->whereClause->conditionalExpression = new ConditionalExpression(array(
|
|
|
|
new ConditionalTerm(array(
|
|
|
|
$AST->whereClause->conditionalExpression,
|
|
|
|
$conditionalPrimary
|
|
|
|
))
|
|
|
|
));
|
2012-01-23 18:42:41 +04:00
|
|
|
} elseif ($AST->whereClause->conditionalExpression instanceof ConditionalExpression
|
|
|
|
|| $AST->whereClause->conditionalExpression instanceof ConditionalFactor
|
|
|
|
) {
|
2012-01-22 16:35:06 +04:00
|
|
|
$tmpPrimary = new ConditionalPrimary;
|
|
|
|
$tmpPrimary->conditionalExpression = $AST->whereClause->conditionalExpression;
|
|
|
|
$AST->whereClause->conditionalExpression = new ConditionalTerm(array(
|
|
|
|
$tmpPrimary,
|
|
|
|
$conditionalPrimary
|
|
|
|
));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$AST->whereClause = new WhereClause(
|
|
|
|
new ConditionalExpression(array(
|
|
|
|
new ConditionalTerm(array(
|
|
|
|
$conditionalPrimary
|
|
|
|
))
|
|
|
|
))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|