Failed Conditions
Pull Request — develop (#6947)
by Filippo
10:01
created

QueryExpressionVisitor::walkComparison()   D

Complexity

Conditions 17
Paths 118

Size

Total Lines 80
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 44
CRAP Score 17.0237

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 17
eloc 54
nc 118
nop 1
dl 0
loc 80
ccs 44
cts 46
cp 0.9565
crap 17.0237
rs 4.7308
c 1
b 0
f 0

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\Query;
6
7
use Doctrine\Common\Collections\ArrayCollection;
8
9
use Doctrine\Common\Collections\Expr\ExpressionVisitor;
10
use Doctrine\Common\Collections\Expr\Comparison;
11
use Doctrine\Common\Collections\Expr\CompositeExpression;
12
use Doctrine\Common\Collections\Expr\Value;
13
14
/**
15
 * Converts Collection expressions to Query expressions.
16
 *
17
 * @author Kirill chEbba Chebunin <[email protected]>
18
 * @since 2.4
19
 */
20
class QueryExpressionVisitor extends ExpressionVisitor
21
{
22
    /**
23
     * @var array
24
     */
25
    private static $operatorMap = [
26
        Comparison::GT => Expr\Comparison::GT,
27
        Comparison::GTE => Expr\Comparison::GTE,
28
        Comparison::LT  => Expr\Comparison::LT,
29
        Comparison::LTE => Expr\Comparison::LTE
30
    ];
31
32
    /**
33
     * @var array
34
     */
35
    private $queryAliases;
36
37
    /**
38
     * @var Expr
39
     */
40
    private $expr;
41
42
    /**
43
     * @var array
44
     */
45
    private $parameters = [];
46
47
    /**
48
     * Constructor
49
     *
50
     * @param array $queryAliases
51
     */
52 34
    public function __construct($queryAliases)
53
    {
54 34
        $this->queryAliases = $queryAliases;
55 34
        $this->expr = new Expr();
56 34
    }
57
58
    /**
59
     * Gets bound parameters.
60
     * Filled after {@link dispach()}.
61
     *
62
     * @return \Doctrine\Common\Collections\Collection
63
     */
64 24
    public function getParameters()
65
    {
66 24
        return new ArrayCollection($this->parameters);
67
    }
68
69
    /**
70
     * Clears parameters.
71
     *
72
     * @return void
73
     */
74 1
    public function clearParameters()
75
    {
76 1
        $this->parameters = [];
77 1
    }
78
79
    /**
80
     * Converts Criteria expression to Query one based on static map.
81
     *
82
     * @param string $criteriaOperator
83
     *
84
     * @return string|null
85
     */
86 11
    private static function convertComparisonOperator($criteriaOperator)
87
    {
88 11
        return self::$operatorMap[$criteriaOperator] ?? null;
89
    }
90
91
    /**
92
     * {@inheritDoc}
93
     */
94 10
    public function walkCompositeExpression(CompositeExpression $expr)
95
    {
96 10
        $expressionList = [];
97
98 10
        foreach ($expr->getExpressionList() as $child) {
99 10
            $expressionList[] = $this->dispatch($child);
100
        }
101
102 10
        switch ($expr->getType()) {
103
            case CompositeExpression::TYPE_AND:
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
104 9
                return new Expr\Andx($expressionList);
105
106
            case CompositeExpression::TYPE_OR:
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
107 1
                return new Expr\Orx($expressionList);
108
109
            default:
110
                throw new \RuntimeException("Unknown composite " . $expr->getType());
111
        }
112
    }
113
114
    /**
115
     * {@inheritDoc}
116
     */
117 28
    public function walkComparison(Comparison $comparison)
118
    {
119 28
        if ( ! isset($this->queryAliases[0])) {
120
            throw new QueryException('No aliases are set before invoking walkComparison().');
121
        }
122
123 28
        $field = $this->queryAliases[0] . '.' . $comparison->getField();
124
125 28
        foreach ($this->queryAliases as $alias) {
126 28
            if (strpos($comparison->getField() . '.', $alias . '.') === 0) {
127 5
                $field = $comparison->getField();
128 28
                break;
129
            }
130
        }
131
132 28
        $parameterName = str_replace('.', '_', $comparison->getField());
133 28
        $parameterCount = \count($this->parameters);
134
135 28
        foreach ($this->parameters as $parameter) {
136 10
            if ($parameter->getName() === $parameterName) {
137 4
                $parameterName .= '_' . $parameterCount;
138 10
                break;
139
            }
140
        }
141
142 28
        $parameter = new Parameter($parameterName, $this->walkValue($comparison->getValue()));
143 28
        $placeholder = ':' . $parameterName;
144
145 28
        switch ($comparison->getOperator()) {
146
            case Comparison::IN:
147 1
                $this->parameters[] = $parameter;
148
149 1
                return $this->expr->in($field, $placeholder);
150
            case Comparison::NIN:
151 1
                $this->parameters[] = $parameter;
152
153 1
                return $this->expr->notIn($field, $placeholder);
154
            case Comparison::EQ:
155
            case Comparison::IS:
156 17
                if ($this->walkValue($comparison->getValue()) === null) {
157 2
                    return $this->expr->isNull($field);
158
                }
159 15
                $this->parameters[] = $parameter;
160
161 15
                return $this->expr->eq($field, $placeholder);
162
            case Comparison::NEQ:
163 2
                if ($this->walkValue($comparison->getValue()) === null) {
164 1
                    return $this->expr->isNotNull($field);
165
                }
166 1
                $this->parameters[] = $parameter;
167
168 1
                return $this->expr->neq($field, $placeholder);
169
            case Comparison::CONTAINS:
170 1
                $parameter->setValue('%' . $parameter->getValue() . '%', $parameter->getType());
171 1
                $this->parameters[] = $parameter;
172
173 1
                return $this->expr->like($field, $placeholder);
174
            case Comparison::STARTS_WITH:
175 1
                $parameter->setValue($parameter->getValue() . '%', $parameter->getType());
176 1
                $this->parameters[] = $parameter;
177
178 1
                return $this->expr->like($field, $placeholder);
179
            case Comparison::ENDS_WITH:
180 1
                $parameter->setValue('%' . $parameter->getValue(), $parameter->getType());
181 1
                $this->parameters[] = $parameter;
182
183 1
                return $this->expr->like($field, $placeholder);
184
            default:
185 11
                $operator = self::convertComparisonOperator($comparison->getOperator());
186 11
                if ($operator) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $operator of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
187 11
                    $this->parameters[] = $parameter;
188
189 11
                    return new Expr\Comparison(
190 11
                        $field,
191 11
                        $operator,
192 11
                        $placeholder
193
                    );
194
                }
195
196
                throw new \RuntimeException("Unknown comparison operator: " . $comparison->getOperator());
197
        }
198
    }
199
200
    /**
201
     * {@inheritDoc}
202
     */
203 29
    public function walkValue(Value $value)
204
    {
205 29
        return $value->getValue();
206
    }
207
}
208