Completed
Pull Request — master (#2007)
by Kentaro
38:32
created

WhereInWalker   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 100
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 14

Test Coverage

Coverage 90.91%

Importance

Changes 0
Metric Value
dl 0
loc 100
ccs 40
cts 44
cp 0.9091
rs 10
c 0
b 0
f 0
wmc 9
lcom 0
cbo 14

1 Method

Rating   Name   Duplication   Size   Complexity  
C walkSelectStatement() 0 70 9
1
<?php
2
/**
3
 * Doctrine ORM
4
 *
5
 * LICENSE
6
 *
7
 * This source file is subject to the new BSD license that is bundled
8
 * with this package in the file LICENSE. This license can also be viewed
9
 * at http://hobodave.com/license.txt
10
 *
11
 * @category    DoctrineExtensions
12
 * @package     DoctrineExtensions\Paginate
13
 * @author      David Abdemoulaie <[email protected]>
14
 * @copyright   Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/)
15
 * @license     http://hobodave.com/license.txt New BSD License
16
 */
17
18
namespace Eccube\Doctrine\ORM\Tools\Pagination;
19
20
use Doctrine\ORM\Query\AST\ArithmeticExpression;
21
use Doctrine\ORM\Query\AST\SimpleArithmeticExpression;
22
use Doctrine\ORM\Query\TreeWalkerAdapter;
23
use Doctrine\ORM\Query\AST\SelectStatement;
24
use Doctrine\ORM\Query\AST\PathExpression;
25
use Doctrine\ORM\Query\AST\InExpression;
26
use Doctrine\ORM\Query\AST\NullComparisonExpression;
27
use Doctrine\ORM\Query\AST\InputParameter;
28
use Doctrine\ORM\Query\AST\ConditionalPrimary;
29
use Doctrine\ORM\Query\AST\ConditionalTerm;
30
use Doctrine\ORM\Query\AST\ConditionalExpression;
31
use Doctrine\ORM\Query\AST\ConditionalFactor;
32
use Doctrine\ORM\Query\AST\WhereClause;
33
34
/**
35
 * Replaces the whereClause of the AST with a WHERE id IN (:foo_1, :foo_2) equivalent.
36
 *
37
 * @category    DoctrineExtensions
38
 * @package     DoctrineExtensions\Paginate
39
 * @author      David Abdemoulaie <[email protected]>
40
 * @copyright   Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/)
41
 * @license     http://hobodave.com/license.txt New BSD License
42
 */
43
class WhereInWalker extends TreeWalkerAdapter
44
{
45
    /**
46
     * ID Count hint name.
47
     */
48
    const HINT_PAGINATOR_ID_COUNT = 'doctrine.id.count';
49
50
    /**
51
     * Primary key alias for query.
52
     */
53
    const PAGINATOR_ID_ALIAS = 'dpid';
54
55
    /**
56
     * Replaces the whereClause in the AST.
57
     *
58
     * Generates a clause equivalent to WHERE IN (:dpid_1, :dpid_2, ...)
59
     *
60
     * The parameter namespace (dpid) is defined by
61
     * the PAGINATOR_ID_ALIAS
62
     *
63
     * The total number of parameters is retrieved from
64
     * the HINT_PAGINATOR_ID_COUNT query hint.
65
     *
66
     * @param SelectStatement $AST
67
     *
68
     * @return void
69
     *
70
     * @throws \RuntimeException
71
     */
72 18
    public function walkSelectStatement(SelectStatement $AST)
73
    {
74 18
        $queryComponents = $this->_getQueryComponents();
75
        // Get the root entity and alias from the AST fromClause
76 18
        $from = $AST->fromClause->identificationVariableDeclarations;
77
        
0 ignored issues
show
introduced by
Please trim any trailing whitespace
Loading history...
78 18
        if (count($from) > 1) {
79
            throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction");
80
        }
81
       
0 ignored issues
show
introduced by
Please trim any trailing whitespace
Loading history...
82 18
        $fromRoot            = reset($from);
83 18
        $rootAlias           = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable;
84 18
        $rootClass           = $queryComponents[$rootAlias]['metadata'];
85 18
        $identifierFieldName = $rootClass->getSingleIdentifierFieldName();
86
87 18
        $pathType = PathExpression::TYPE_STATE_FIELD;
88 18
        if (isset($rootClass->associationMappings[$identifierFieldName])) {
89
            $pathType = PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION;
90
        }
91
92 18
        $pathExpression       = new PathExpression(PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, $rootAlias, $identifierFieldName);
93 18
        $pathExpression->type = $pathType;
94
95 18
        $count = $this->_getQuery()->getHint(self::HINT_PAGINATOR_ID_COUNT);
96
97 18
        if ($count > 0) {
98 18
            $arithmeticExpression = new ArithmeticExpression();
99 18
            $arithmeticExpression->simpleArithmeticExpression = new SimpleArithmeticExpression(
100 18
                array($pathExpression)
101
            );
102 18
            $expression = new InExpression($arithmeticExpression);
103 18
            $expression->literals[] = new InputParameter(":" . self::PAGINATOR_ID_ALIAS);
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
104
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
105
        } else {
106
            $expression = new NullComparisonExpression($pathExpression);
107
            $expression->not = false;
108
        }
109
110 18
        $conditionalPrimary = new ConditionalPrimary;
0 ignored issues
show
introduced by
Use parentheses when instantiating classes
Loading history...
111 18
        $conditionalPrimary->simpleConditionalExpression = $expression;
112 18
        if ($AST->whereClause) {
113 17
            if ($AST->whereClause->conditionalExpression instanceof ConditionalTerm) {
114 7
                $AST->whereClause->conditionalExpression->conditionalFactors[] = $conditionalPrimary;
115 10
            } elseif ($AST->whereClause->conditionalExpression instanceof ConditionalPrimary) {
116 7
                $AST->whereClause->conditionalExpression = new ConditionalExpression(array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
117 7
                    new ConditionalTerm(array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
118 7
                        $AST->whereClause->conditionalExpression,
119 7
                        $conditionalPrimary
120
                    ))
121
                ));
122 3
            } elseif ($AST->whereClause->conditionalExpression instanceof ConditionalExpression
123 3
                || $AST->whereClause->conditionalExpression instanceof ConditionalFactor
124
            ) {
125 3
                $tmpPrimary = new ConditionalPrimary;
0 ignored issues
show
introduced by
Use parentheses when instantiating classes
Loading history...
126 3
                $tmpPrimary->conditionalExpression = $AST->whereClause->conditionalExpression;
0 ignored issues
show
Documentation Bug introduced by
It seems like $AST->whereClause->conditionalExpression can also be of type object<Doctrine\ORM\Query\AST\ConditionalFactor>. However, the property $conditionalExpression is declared as type object<Doctrine\ORM\Quer...itionalExpression>|null. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
127 3
                $AST->whereClause->conditionalExpression = new ConditionalTerm(array(
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Doctrine\ORM\Query\..., $conditionalPrimary)) of type object<Doctrine\ORM\Query\AST\ConditionalTerm> is incompatible with the declared type object<Doctrine\ORM\Quer...\ConditionalExpression> of property $conditionalExpression.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
introduced by
Add a comma after each item in a multi-line array
Loading history...
128 3
                    $tmpPrimary,
129 17
                    $conditionalPrimary
130
                ));
131
            }
132
        } else {
133 1
            $AST->whereClause = new WhereClause(
134 1
                new ConditionalExpression(array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
135 1
                    new ConditionalTerm(array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
136 1
                        $conditionalPrimary
137
                    ))
138
                ))
139
            );
140
        }
141
    }
142
}
143