Failed Conditions
Pull Request — master (#6392)
by Alessandro
11:37
created

QueryExpressionVisitor::clearParameters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
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 = [
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 = [];
61
62
    /**
63
     * Constructor
64
     *
65
     * @param array $queryAliases
66
     */
67 34
    public function __construct($queryAliases)
68
    {
69 34
        $this->queryAliases = $queryAliases;
70 34
        $this->expr = new Expr();
71 34
    }
72
73
    /**
74
     * Gets bound parameters.
75
     * Filled after {@link dispach()}.
76
     *
77
     * @return \Doctrine\Common\Collections\Collection
78
     */
79 24
    public function getParameters()
80
    {
81 24
        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 = [];
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 = [];
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 28
    public function walkComparison(Comparison $comparison)
133
    {
134
135 28
        if ( ! isset($this->queryAliases[0])) {
136
            throw new QueryException('No aliases are set before invoking walkComparison().');
137
        }
138
139 28
        $field = $this->queryAliases[0] . '.' . $comparison->getField();
140
141 28
        foreach($this->queryAliases as $alias) {
142 28
            if(strpos($comparison->getField() . '.', $alias . '.') === 0) {
143 5
                $field = $comparison->getField();
144 5
                break;
145
            }
146
        }
147
148 28
        $parameterName = str_replace('.', '_', $comparison->getField());
149
150 28
        foreach ($this->parameters as $parameter) {
151 10
            if ($parameter->getName() === $parameterName) {
152 4
                $parameterName .= '_' . count($this->parameters);
153 4
                break;
154
            }
155
        }
156
157 28
        $parameter = new Parameter($parameterName, $this->walkValue($comparison->getValue()));
158 28
        $placeholder = ':' . $parameterName;
159
160 28
        switch ($comparison->getOperator()) {
161 28
            case Comparison::IN:
162 1
                $this->parameters[] = $parameter;
163
164 1
                return $this->expr->in($field, $placeholder);
165 27
            case Comparison::NIN:
166 1
                $this->parameters[] = $parameter;
167
168 1
                return $this->expr->notIn($field, $placeholder);
169 26
            case Comparison::EQ:
170 16 View Code Duplication
            case Comparison::IS:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 16 View Code Duplication
            case Comparison::NEQ:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 14 View Code Duplication
            case Comparison::CONTAINS:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
185 1
                $parameter->setValue('%' . $parameter->getValue() . '%', $parameter->getType());
186 1
                $this->parameters[] = $parameter;
187
188 1
                return $this->expr->like($field, $placeholder);
189 13 View Code Duplication
            case Comparison::STARTS_WITH:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
190 1
                $parameter->setValue($parameter->getValue() . '%', $parameter->getType());
191 1
                $this->parameters[] = $parameter;
192
193 1
                return $this->expr->like($field, $placeholder);
194 12 View Code Duplication
            case Comparison::ENDS_WITH:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
195 1
                $parameter->setValue('%' . $parameter->getValue(), $parameter->getType());
196 1
                $this->parameters[] = $parameter;
197
198 1
                return $this->expr->like($field, $placeholder);
199
            default:
200 11
                $operator = self::convertComparisonOperator($comparison->getOperator());
201 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...
202 11
                    $this->parameters[] = $parameter;
203
204 11
                    return new Expr\Comparison(
205 11
                        $field,
206 11
                        $operator,
207 11
                        $placeholder
208
                    );
209
                }
210
211
                throw new \RuntimeException("Unknown comparison operator: " . $comparison->getOperator());
212
        }
213
    }
214
215
    /**
216
     * {@inheritDoc}
217
     */
218 29
    public function walkValue(Value $value)
219
    {
220 29
        return $value->getValue();
221
    }
222
}
223