Completed
Push — master ( 8c259e...a3e53b )
by Guilherme
27:10 queued 12:02
created

WhereInWalker::walkSelectStatement()   B

Complexity

Conditions 10
Paths 31

Size

Total Lines 73
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 44
CRAP Score 10.0259

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 49
c 1
b 0
f 0
nc 31
nop 1
dl 0
loc 73
ccs 44
cts 47
cp 0.9362
crap 10.0259
rs 7.246

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ORM\Tools\Pagination;
6
7
use Doctrine\ORM\Mapping\AssociationMetadata;
8
use Doctrine\ORM\Mapping\ToOneAssociationMetadata;
9
use Doctrine\ORM\Query\AST\ArithmeticExpression;
10
use Doctrine\ORM\Query\AST\ConditionalExpression;
11
use Doctrine\ORM\Query\AST\ConditionalFactor;
12
use Doctrine\ORM\Query\AST\ConditionalPrimary;
13
use Doctrine\ORM\Query\AST\ConditionalTerm;
14
use Doctrine\ORM\Query\AST\InExpression;
15
use Doctrine\ORM\Query\AST\InputParameter;
16
use Doctrine\ORM\Query\AST\NullComparisonExpression;
17
use Doctrine\ORM\Query\AST\PathExpression;
18
use Doctrine\ORM\Query\AST\SelectStatement;
19
use Doctrine\ORM\Query\AST\SimpleArithmeticExpression;
20
use Doctrine\ORM\Query\AST\WhereClause;
21
use Doctrine\ORM\Query\TreeWalkerAdapter;
22
use RuntimeException;
23
use function count;
24
use function reset;
25
26
/**
27
 * Replaces the whereClause of the AST with a WHERE id IN (:foo_1, :foo_2) equivalent.
28
 */
29
class WhereInWalker extends TreeWalkerAdapter
30
{
31
    /**
32
     * ID Count hint name.
33
     */
34
    public const HINT_PAGINATOR_ID_COUNT = 'doctrine.id.count';
35
36
    /**
37
     * Primary key alias for query.
38
     */
39
    public const PAGINATOR_ID_ALIAS = 'dpid';
40
41
    /**
42
     * Replaces the whereClause in the AST.
43
     *
44
     * Generates a clause equivalent to WHERE IN (:dpid_1, :dpid_2, ...)
45
     *
46
     * The parameter namespace (dpid) is defined by
47
     * the PAGINATOR_ID_ALIAS
48
     *
49
     * The total number of parameters is retrieved from
50
     * the HINT_PAGINATOR_ID_COUNT query hint.
51
     *
52
     * @throws RuntimeException
53
     */
54 60
    public function walkSelectStatement(SelectStatement $AST)
55
    {
56 60
        $queryComponents = $this->getQueryComponents();
57
        // Get the root entity and alias from the AST fromClause
58 60
        $from = $AST->fromClause->identificationVariableDeclarations;
59
60 60
        if (count($from) > 1) {
61
            throw new RuntimeException('Cannot count query which selects two FROM components, cannot make distinction');
62
        }
63
64 60
        $fromRoot  = reset($from);
65 60
        $rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable;
66 60
        $rootClass = $queryComponents[$rootAlias]['metadata'];
67 60
        $property  = $rootClass->getProperty($rootClass->getSingleIdentifierFieldName());
68 60
        $pathType  = PathExpression::TYPE_STATE_FIELD;
69
70 60
        if ($property instanceof AssociationMetadata) {
71 1
            $pathType = $property instanceof ToOneAssociationMetadata
72 1
                ? PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION
73 1
                : PathExpression::TYPE_COLLECTION_VALUED_ASSOCIATION;
74
        }
75
76 60
        $pathExpression = new PathExpression(
77 60
            PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION,
78
            $rootAlias,
79 60
            $property->getName()
80
        );
81
82 60
        $pathExpression->type = $pathType;
83
84 60
        $count = $this->getQuery()->getHint(self::HINT_PAGINATOR_ID_COUNT);
85
86 60
        if ($count > 0) {
87 60
            $arithmeticExpression                             = new ArithmeticExpression();
88 60
            $arithmeticExpression->simpleArithmeticExpression = new SimpleArithmeticExpression(
89 60
                [$pathExpression]
90
            );
91 60
            $expression                                       = new InExpression($arithmeticExpression);
92 60
            $expression->literals[]                           = new InputParameter(':' . self::PAGINATOR_ID_ALIAS);
93
        } else {
94
            $expression      = new NullComparisonExpression($pathExpression);
95
            $expression->not = false;
96
        }
97
98 60
        $conditionalPrimary                              = new ConditionalPrimary();
99 60
        $conditionalPrimary->simpleConditionalExpression = $expression;
100
101 60
        if ($AST->whereClause) {
102 10
            if ($AST->whereClause->conditionalExpression instanceof ConditionalTerm) {
0 ignored issues
show
introduced by
$AST->whereClause->conditionalExpression is never a sub-type of Doctrine\ORM\Query\AST\ConditionalTerm.
Loading history...
103 2
                $AST->whereClause->conditionalExpression->conditionalFactors[] = $conditionalPrimary;
104 8
            } elseif ($AST->whereClause->conditionalExpression instanceof ConditionalPrimary) {
0 ignored issues
show
introduced by
$AST->whereClause->conditionalExpression is never a sub-type of Doctrine\ORM\Query\AST\ConditionalPrimary.
Loading history...
105 5
                $AST->whereClause->conditionalExpression = new ConditionalExpression([
106 5
                    new ConditionalTerm([
107 5
                        $AST->whereClause->conditionalExpression,
108 5
                        $conditionalPrimary,
109
                    ]),
110
                ]);
111 3
            } elseif ($AST->whereClause->conditionalExpression instanceof ConditionalExpression
0 ignored issues
show
introduced by
$AST->whereClause->conditionalExpression is always a sub-type of Doctrine\ORM\Query\AST\ConditionalExpression.
Loading history...
112 3
                || $AST->whereClause->conditionalExpression instanceof ConditionalFactor
113
            ) {
114 3
                $tmpPrimary                              = new ConditionalPrimary();
115 3
                $tmpPrimary->conditionalExpression       = $AST->whereClause->conditionalExpression;
116 3
                $AST->whereClause->conditionalExpression = new ConditionalTerm(
0 ignored issues
show
Documentation Bug introduced by
It seems like new Doctrine\ORM\Query\A..., $conditionalPrimary)) of type Doctrine\ORM\Query\AST\ConditionalTerm is incompatible with the declared type Doctrine\ORM\Query\AST\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...
117
                    [
118 3
                        $tmpPrimary,
119 10
                        $conditionalPrimary,
120
                    ]
121
                );
122
            }
123
        } else {
124 50
            $AST->whereClause = new WhereClause(
125 50
                new ConditionalExpression(
126 50
                    [new ConditionalTerm([$conditionalPrimary])]
127
                )
128
            );
129
        }
130 60
    }
131
}
132