ConditionDbParser::parseConditions()   C
last analyzed

Complexity

Conditions 12
Paths 12

Size

Total Lines 37
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 33
nc 12
nop 2
dl 0
loc 37
rs 5.1612
c 0
b 0
f 0

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
namespace WebComplete\core\condition;
4
5
use Doctrine\DBAL\Query\QueryBuilder;
6
7
class ConditionDbParser
8
{
9
10
    /** @var array */
11
    protected $map = [];
12
13
    /**
14
     * @param QueryBuilder $queryBuilder
15
     * @param Condition|null $condition
16
     * @param array|null $map
17
     */
18
    public function parse(QueryBuilder $queryBuilder, Condition $condition = null, array $map = null)
19
    {
20
        if ($condition === null) {
21
            return;
22
        }
23
        if ($map) {
24
            $this->map = \array_flip($map);
25
        }
26
        $this->parseConditions($queryBuilder, $condition);
27
28
        foreach ($condition->getSort() as $field => $direction) {
29
            $queryBuilder->orderBy($this->mapField($field), $direction === \SORT_DESC ? 'desc' : 'asc');
30
        }
31
32
        if ($offset = (int)$condition->getOffset()) {
33
            $queryBuilder->setFirstResult($offset);
34
        }
35
36
        if ($limit = (int)$condition->getLimit()) {
37
            $queryBuilder->setMaxResults($limit);
38
        }
39
    }
40
41
    /**
42
     * @param QueryBuilder $queryBuilder
43
     * @param Condition $condition
44
     */
45
    protected function parseConditions(QueryBuilder $queryBuilder, Condition $condition)
46
    {
47
        foreach ($condition->getConditions() as $cond) {
48
            if (!\is_array($cond)) {
49
                continue;
50
            }
51
52
            $cond = \array_values($cond);
53
            $type = \array_shift($cond);
54
            switch ($type) {
55
                case Condition::EQUALS:
56
                    $this->parseSimpleCondition('=', $queryBuilder, $cond);
57
                    break;
58
                case Condition::NOT_EQUALS:
59
                    $this->parseSimpleCondition('<>', $queryBuilder, $cond);
60
                    break;
61
                case Condition::LESS_THAN:
62
                    $this->parseSimpleCondition('<', $queryBuilder, $cond);
63
                    break;
64
                case Condition::GREATER_THAN:
65
                    $this->parseSimpleCondition('>', $queryBuilder, $cond);
66
                    break;
67
                case Condition::LESS_OR_EQUALS:
68
                    $this->parseSimpleCondition('<=', $queryBuilder, $cond);
69
                    break;
70
                case Condition::GREATER_OR_EQUALS:
71
                    $this->parseSimpleCondition('>=', $queryBuilder, $cond);
72
                    break;
73
                case Condition::BETWEEN:
74
                    $this->parseBetweenCondition($queryBuilder, $cond);
75
                    break;
76
                case Condition::LIKE:
77
                    $this->parseLikeCondition($queryBuilder, $cond);
78
                    break;
79
                case Condition::IN:
80
                    $this->parseInCondition($queryBuilder, $cond);
81
                    break;
82
            }
83
        }
84
    }
85
86
    /**
87
     * @param QueryBuilder $queryBuilder
88
     * @param $cond
89
     */
90
    protected function parseLikeCondition(QueryBuilder $queryBuilder, $cond)
91
    {
92
        $value = $cond[2] ? '%' : '';
93
        $value .= $cond[1];
94
        $value .= $cond[3] ? '%' : '';
95
        $field = $this->mapField($cond[0]);
96
        $queryBuilder->andWhere("{$field} LIKE " . $queryBuilder->createNamedParameter($value));
97
    }
98
99
    /**
100
     * @param QueryBuilder $queryBuilder
101
     * @param $cond
102
     */
103
    protected function parseInCondition(QueryBuilder $queryBuilder, $cond)
104
    {
105
        if ($cond[1]) {
106
            $isNumeric = $cond[2];
107
            $sql = '';
108
            /** @var array $values */
109
            $values = $cond[1];
110
            foreach ($values as $v) {
111
                $sql .= ($isNumeric ? (float)$v : $queryBuilder->createNamedParameter($v)) . ',';
112
            }
113
            $field = $this->mapField($cond[0]);
114
            $queryBuilder->andWhere("{$field} IN (" . \rtrim($sql, ',') . ')');
115
        } else {
116
            $queryBuilder->andWhere('1 = 2'); // IN empty array is always false
117
        }
118
    }
119
120
    /**
121
     * @param QueryBuilder $queryBuilder
122
     * @param $cond
123
     */
124
    protected function parseBetweenCondition(QueryBuilder $queryBuilder, $cond)
125
    {
126
        $field = $this->mapField($cond[0]);
127
        $queryBuilder->andWhere("{$field} BETWEEN " . $queryBuilder->createNamedParameter($cond[1])
128
            . ' AND ' . $queryBuilder->createNamedParameter($cond[2]));
129
    }
130
131
    /**
132
     * @param string $exp
133
     * @param QueryBuilder $queryBuilder
134
     * @param $cond
135
     */
136
    protected function parseSimpleCondition(string $exp, QueryBuilder $queryBuilder, $cond)
137
    {
138
        $field = $this->mapField($cond[0]);
139
        $queryBuilder->andWhere("{$field} $exp " . $queryBuilder->createNamedParameter($cond[1]));
140
    }
141
142
    /**
143
     * @param $field
144
     *
145
     * @return mixed
146
     */
147
    protected function mapField($field)
148
    {
149
        return $this->map[$field] ?? $field;
150
    }
151
}
152