Completed
Push — master ( f9a038...cc9983 )
by Kamil
22:34
created

ExpressionVisitor::walkComparison()   C

Complexity

Conditions 13
Paths 13

Size

Total Lines 50
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 50
rs 5.3808
cc 13
eloc 33
nc 13
nop 2

How to fix   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
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sylius\Bundle\GridBundle\Doctrine\PHPCRODM;
13
14
use Sylius\Component\Grid\Data\ExpressionBuilderInterface;
15
use Doctrine\ODM\PHPCR\Query\Builder\QueryBuilder;
16
use Doctrine\Common\Collections\Expr\CompositeExpression;
17
use Doctrine\Common\Collections\Expr\Comparison;
18
use Doctrine\Common\Collections\Expr\Value;
19
use Doctrine\ODM\PHPCR\Query\Builder\AbstractNode;
20
use Doctrine\ODM\PHPCR\Query\Builder\OperandFactory;
21
use Doctrine\Common\Collections\Expr\Expression;
22
use Sylius\Bundle\GridBundle\Doctrine\PHPCRODM\ExtraComparison;
23
24
/**
25
 * Walks a Doctrine\Commons\Expr object graph and builds up a PHPCR-ODM
26
 * query using the (fluent) PHPCR-ODM query builder.
27
 */
28
class ExpressionVisitor
29
{
30
    private $queryBuilder;
31
32
    /**
33
     * @param QueryBuilder $queryBuilder
34
     */
35
    public function __construct(QueryBuilder $queryBuilder)
36
    {
37
        $this->queryBuilder = $queryBuilder;
38
    }
39
40
    /**
41
     * {@inheritDoc}
42
     */
43
    public function walkComparison(Comparison $comparison, AbstractNode $parentNode)
44
    {
45
        $field = $comparison->getField();
46
        $value = $comparison->getValue()->getValue(); // shortcut for walkValue()
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
47
48
        switch ($comparison->getOperator()) {
49
            case Comparison::EQ:
50
                return $parentNode->eq()->field($this->getField($field))->literal($value)->end();
51
52
            case Comparison::NEQ:
53
                return $parentNode->neq()->field($this->getField($field))->literal($value)->end();
54
55
            case Comparison::LT:
56
                return $parentNode->lt()->field($this->getField($field))->literal($value)->end();
57
58
            case Comparison::LTE:
59
                return $parentNode->lte()->field($this->getField($field))->literal($value)->end();
60
61
            case Comparison::GT:
62
                return $parentNode->gt()->field($this->getField($field))->literal($value)->end();
63
64
            case Comparison::GTE:
65
                return $parentNode->gte()->field($this->getField($field))->literal($value)->end();
66
67
            case Comparison::IN:
68
                return $this->getInConstraint($parentNode, $field, $value);
69
70
            case Comparison::NIN:
71
                $node = $parentNode->not();
72
                $this->getInConstraint($node, $field, $value);
73
                return $node->end();
74
75
            case Comparison::CONTAINS:
76
                return $parentNode->like()->field($this->getField($field))->literal($value)->end();
77
78
            case ExtraComparison::NOT_CONTAINS:
79
                return $parentNode->not()->like()->field($this->getField($field))->literal($value)->end()->end();
80
81
            case ExtraComparison::IS_NULL:
82
                return $parentNode->not()->fieldIsset($this->getField($field))->end();
83
84
            case ExtraComparison::IS_NOT_NULL:
85
                return $parentNode->fieldIsset($this->getField($field));
86
87
            default:
88
                throw new \RuntimeException("Unknown comparison operator: " . $comparison->getOperator());
89
        }
90
91
        return $parentNode;
0 ignored issues
show
Unused Code introduced by
return $parentNode; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
92
    }
93
94
    /**
95
     * {@inheritDoc}
96
     */
97
    public function walkValue(Value $value, OperandFactory $parentNode)
98
    {
99
        throw new \BadMethodCallException('What is this even used for?');
100
        return $parentNode->literal($value->getValue());
0 ignored issues
show
Unused Code introduced by
return $parentNode->literal($value->getValue()); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
101
    }
102
103
    /**
104
     * {@inheritDoc}
105
     */
106
    public function walkCompositeExpression(CompositeExpression $expr, AbstractNode $parentNode)
107
    {
108
        switch($expr->getType()) {
109
            case CompositeExpression::TYPE_AND:
110
                $node = $parentNode->andX();
111
                break;
112
            case CompositeExpression::TYPE_OR:
113
                $node = $parentNode->orX();
114
                break;
115
            default:
116
                throw new \RuntimeException('Unknown composite: ' . $expr->getType());
117
        }
118
119
        $expressions = $expr->getExpressionList();
120
121
        $leftExpression = array_shift($expressions);
122
        $this->dispatch($leftExpression, $node);
123
124
        $parentNode = $node;
125
        foreach ($expressions as $index => $expression) {
126
            if (count($expressions) === $index + 1) {
127
                $this->dispatch($expression, $parentNode);
128
                break;
129
            }
130
131
            switch($expr->getType()) {
132
                case CompositeExpression::TYPE_AND:
133
                    $parentNode = $parentNode->andX();
134
                    break;
135
                case CompositeExpression::TYPE_OR:
136
                    $parentNode = $parentNode->orX();
137
                    break;
138
            }
139
140
            $this->dispatch($expression, $parentNode);
141
        }
142
143
        return $node;
144
    }
145
146
    /**
147
     * Walk the given expression to build up the PHPCR-ODM query builder.
148
     *
149
     * @param Expression $expr
150
     * @param AbstractNode $parentNode
151
     */
152
    public function dispatch(Expression $expr, AbstractNode $parentNode = null)
153
    {
154
        if ($parentNode === null) {
155
            $parentNode = $this->queryBuilder->where();
156
        }
157
158
        switch (true) {
159
            case ($expr instanceof Comparison):
160
                return $this->walkComparison($expr, $parentNode);
161
162
            case ($expr instanceof Value):
163
                return $this->walkValue($expr, $parentNode);
164
165
            case ($expr instanceof CompositeExpression):
166
                return $this->walkCompositeExpression($expr, $parentNode);
167
168
            default:
169
                throw new \RuntimeException("Unknown Expression " . get_class($expr));
170
        }
171
    }
172
173
    private function getField($field)
174
    {
175
        return Driver::QB_SOURCE_ALIAS . '.' . $field;
176
    }
177
178
    private function getInConstraint(AbstractNode $parentNode, $field, array $values)
179
    {
180
        $orNode = $parentNode->orx();
181
182
        foreach ($values as $value) {
183
            $orNode->eq()->field($this->getField($field))->literal($value);
184
        }
185
186
        $orNode->end();
187
    }
188
}
189