Completed
Pull Request — master (#5713)
by Ondřej
14:07
created

QueryExpressionVisitor::walkComparison()   C

Complexity

Conditions 15
Paths 100

Size

Total Lines 72
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 40
CRAP Score 15.0242

Importance

Changes 1
Bugs 1 Features 0
Metric Value
dl 0
loc 72
ccs 40
cts 42
cp 0.9524
rs 5.4849
c 1
b 1
f 0
cc 15
eloc 46
nc 100
nop 1
crap 15.0242

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
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\ORM\Query;
21
22
use Doctrine\Common\Collections\ArrayCollection;
23
24
use Doctrine\Common\Collections\Expr\ExpressionVisitor;
25
use Doctrine\Common\Collections\Expr\Comparison;
26
use Doctrine\Common\Collections\Expr\CompositeExpression;
27
use Doctrine\Common\Collections\Expr\Value;
28
29
/**
30
 * Converts Collection expressions to Query expressions.
31
 *
32
 * @author Kirill chEbba Chebunin <[email protected]>
33
 * @since 2.4
34
 */
35
class QueryExpressionVisitor extends ExpressionVisitor
36
{
37
    /**
38
     * @var array
39
     */
40
    private static $operatorMap = array(
41
        Comparison::GT => Expr\Comparison::GT,
42
        Comparison::GTE => Expr\Comparison::GTE,
43
        Comparison::LT  => Expr\Comparison::LT,
44
        Comparison::LTE => Expr\Comparison::LTE
45
    );
46
47
    /**
48
     * @var array
49
     */
50
    private $queryAliases;
51
52
    /**
53
     * @var Expr
54
     */
55
    private $expr;
56
57
    /**
58
     * @var array
59
     */
60
    private $parameters = array();
61
62
    /**
63
     * Constructor
64
     *
65
     * @param array $queryAliases
66
     */
67 32
    public function __construct($queryAliases)
68
    {
69 32
        $this->queryAliases = $queryAliases;
70 32
        $this->expr = new Expr();
71 32
    }
72
73
    /**
74
     * Gets bound parameters.
75
     * Filled after {@link dispach()}.
76
     *
77
     * @return \Doctrine\Common\Collections\Collection
78
     */
79 22
    public function getParameters()
80
    {
81 22
        return new ArrayCollection($this->parameters);
82
    }
83
84
    /**
85
     * Clears parameters.
86
     *
87
     * @return void
88
     */
89 1
    public function clearParameters()
90
    {
91 1
        $this->parameters = array();
92 1
    }
93
94
    /**
95
     * Converts Criteria expression to Query one based on static map.
96
     *
97
     * @param string $criteriaOperator
98
     *
99
     * @return string|null
100
     */
101 11
    private static function convertComparisonOperator($criteriaOperator)
102
    {
103 11
        return isset(self::$operatorMap[$criteriaOperator]) ? self::$operatorMap[$criteriaOperator] : null;
104
    }
105
106
    /**
107
     * {@inheritDoc}
108
     */
109 10
    public function walkCompositeExpression(CompositeExpression $expr)
110
    {
111 10
        $expressionList = array();
112
113 10
        foreach ($expr->getExpressionList() as $child) {
114 10
            $expressionList[] = $this->dispatch($child);
115
        }
116
117 10
        switch($expr->getType()) {
118 10
            case CompositeExpression::TYPE_AND:
119 9
                return new Expr\Andx($expressionList);
120
121 1
            case CompositeExpression::TYPE_OR:
122 1
                return new Expr\Orx($expressionList);
123
124
            default:
125
                throw new \RuntimeException("Unknown composite " . $expr->getType());
126
        }
127
    }
128
129
    /**
130
     * {@inheritDoc}
131
     */
132 26
    public function walkComparison(Comparison $comparison)
133
    {
134
135 26
        if ( ! isset($this->queryAliases[0])) {
136
            throw new QueryException('No aliases are set before invoking walkComparison().');
137
        }
138
139 26
        $field = $this->queryAliases[0] . '.' . $comparison->getField();
140
141 26
        foreach($this->queryAliases as $alias) {
142 26
            if(strpos($comparison->getField() . '.', $alias . '.') === 0) {
143 5
                $field = $comparison->getField();
144 26
                break;
145
            }
146
        }
147
148 26
        $parameterName = str_replace('.', '_', $comparison->getField());
149
150 26
        foreach ($this->parameters as $parameter) {
151 10
            if ($parameter->getName() === $parameterName) {
152 4
                $parameterName .= '_' . count($this->parameters);
153 10
                break;
154
            }
155
        }
156
157 26
        $parameter = new Parameter($parameterName, $this->walkValue($comparison->getValue()));
158 26
        $placeholder = ':' . $parameterName;
159
160 26
        switch ($comparison->getOperator()) {
161 26
            case Comparison::IN:
162 1
                $this->parameters[] = $parameter;
163
                
164 1
                return $this->expr->in($field, $placeholder);
165 25
            case Comparison::NIN:
166 1
                $this->parameters[] = $parameter;
167
                
168 1
                return $this->expr->notIn($field, $placeholder);
169 24
            case Comparison::EQ:
170 14
            case Comparison::IS:
171 17
                if ($this->walkValue($comparison->getValue()) === null) {
172 2
                    return $this->expr->isNull($field);
173
                }
174 15
                $this->parameters[] = $parameter;
175
                
176 15
                return $this->expr->eq($field, $placeholder);
177 14
            case Comparison::NEQ:
178 2
                if ($this->walkValue($comparison->getValue()) === null) {
179 1
                    return $this->expr->isNotNull($field);
180
                }
181 1
                $this->parameters[] = $parameter;
182
                
183 1
                return $this->expr->neq($field, $placeholder);
184 12
            case Comparison::CONTAINS:
185 1
                $parameter->setValue('%' . $parameter->getValue() . '%', $parameter->getType());
186 1
                $this->parameters[] = $parameter;
187
                
188 1
                return $this->expr->like($field, $placeholder);
189
            default:
190 11
                $operator = self::convertComparisonOperator($comparison->getOperator());
191 11
                if ($operator) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $operator of type string|null 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...
192 11
                    $this->parameters[] = $parameter;
193
194 11
                    return new Expr\Comparison(
195
                        $field,
196
                        $operator,
197
                        $placeholder
198
                    );
199
                }
200
201
                throw new \RuntimeException("Unknown comparison operator: " . $comparison->getOperator());
202
        }
203
    }
204
205
    /**
206
     * {@inheritDoc}
207
     */
208 27
    public function walkValue(Value $value)
209
    {
210 27
        return $value->getValue();
211
    }
212
}
213