5dc0081f56
The Pagination tool throws an exception on a DQL query like: SELECT u FROM User u WHERE NOT (u INSTANCE OF Person) This is because Paginate does not know about the Doctrine\ORM\Query\AST\ConditionalFactor which implements the NOT operator. This patch adds support for that.
145 lines
5.3 KiB
PHP
145 lines
5.3 KiB
PHP
<?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();
|
|
foreach ($this->_getQueryComponents() AS $dqlAlias => $qComp) {
|
|
$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
|
|
))
|
|
));
|
|
} elseif ($AST->whereClause->conditionalExpression instanceof ConditionalExpression
|
|
|| $AST->whereClause->conditionalExpression instanceof ConditionalFactor
|
|
) {
|
|
$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
|
|
))
|
|
))
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|