Passed
Push — master ( 1079b7...e5d772 )
by Aleksandar
02:22
created

ConditionTrait::buildWrapValue()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 7
c 0
b 0
f 0
nc 3
nop 3
dl 0
loc 13
ccs 8
cts 8
cp 1
crap 3
rs 10
1
<?php
2
/**
3
 * Copyright 2021 Aleksandar Panic
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 *   http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
namespace ArekX\PQL\Drivers\MySql\Builder\Builders\Traits;
19
20
use ArekX\PQL\Contracts\StructuredQuery;
21
use ArekX\PQL\Drivers\MySql\Builder\MySqlQueryBuilderState;
22
23
trait ConditionTrait
24
{
25
    use SubQueryTrait;
26
    use QuoteNameTrait;
27
28 16
    protected function buildCondition($condition, MySqlQueryBuilderState $state)
29
    {
30 16
        static $map = null;
31
32 16
        if ($map === null) {
33
            $map = [
34 4
                'all' => fn($condition, $state) => $this->buildAssociativeCondition(' AND ', $condition, $state),
35 3
                'any' => fn($condition, $state) => $this->buildAssociativeCondition(' OR ', $condition, $state),
36 3
                'and' => fn($condition, $state) => $this->buildConjuctionCondition(' AND ', $condition, $state),
37 3
                'or' => fn($condition, $state) => $this->buildConjuctionCondition(' OR ', $condition, $state),
38 3
                'not' => fn($condition, $state) => $this->buildNotCondition($condition, $state),
39 3
                'in' => fn($condition, $state) => $this->buildInCondition($condition, $state),
40 3
                'between' => fn($condition, $state) => $this->buildBetweenCondition($condition, $state),
41 3
                'like' => fn($condition, $state) => $this->buildLikeCondition($condition, $state),
42 8
                'column' => fn($condition) => $this->buildColumnCondition($condition),
43 8
                'value' => fn($condition, $state) => $this->buildValueCondition($condition, $state),
44
            ];
45
        }
46
47 16
        if ($condition instanceof StructuredQuery) {
48 3
            return $this->buildSubQuery($condition, $state);
49
        }
50
51 16
        if (is_array($condition)) {
52 15
            if (empty($map[$condition[0]])) {
53 1
                throw new \Exception('Unknown condition: ' . var_export($condition[0], true));
54
            }
55
56 14
            return $map[$condition[0]]($condition, $state);
57
        }
58
59 1
        throw new \Exception('Condition must be an array.');
60
    }
61
62 4
    protected function buildAssociativeCondition($glue, $condition, MySqlQueryBuilderState $state)
63
    {
64 4
        $result = [];
65 4
        foreach ($condition[1] as $key => $value) {
66 4
            $leftSide = $this->quoteName($key);
67
68 4
            if ($value instanceof StructuredQuery) {
69 2
                $result[] = $leftSide . ' IN ' . $this->buildSubQuery($value, $state);
70 2
                continue;
71
            }
72
73 4
            if (is_array($value)) {
74 2
                $result[] = $leftSide . ' IN (' . $this->buildWrapValue($value, $state) . ')';
75 2
                continue;
76
            }
77
78 4
            $result[] = $leftSide . ' = ' . $this->buildWrapValue($value, $state);
79
        }
80
81 4
        return implode($glue, $result);
82
    }
83
84 11
    protected function buildWrapValue($value, MySqlQueryBuilderState $state, $type = null)
85
    {
86 11
        $builder = $state->getParamsBuilder();
87
88 11
        if (is_array($value)) {
89 3
            $results = [];
90 3
            foreach ($value as $item) {
91 3
                $results[] = $builder->wrapValue($item, $type);
92
            }
93 3
            return implode(', ', $results);
94
        }
95
96 10
        return $builder->wrapValue($value, $type);
97
    }
98
99 2
    protected function buildConjuctionCondition(string $glue, $condition, MySqlQueryBuilderState $state)
100
    {
101 2
        $result = [];
102
103 2
        $max = count($condition);
104 2
        for ($i = 1; $i < $max; $i++) {
105 2
            $result[] = '(' . $this->buildCondition($condition[$i], $state) . ')';
106
        }
107
108 2
        return implode($glue, $result);
109
    }
110
111 6
    protected function buildColumnCondition($condition)
112
    {
113 6
        $column = $condition[1] ?? null;
114
115 6
        if (empty($column)) {
116 1
            throw new \Exception('Column name must be set.');
117 5
        } else if (!is_string($column)) {
118 1
            throw new \Exception('Column name must be a string.');
119
        }
120
121 4
        return $this->quoteName($column);
122
    }
123
124 7
    protected function buildValueCondition($condition, MySqlQueryBuilderState $state)
125
    {
126 7
        return $this->buildWrapValue(
127 7
            $condition[1] ?? null,
128
            $state,
129 7
            $condition[2] ?? null
130
        );
131
    }
132
133 1
    protected function buildNotCondition($condition, MySqlQueryBuilderState $state)
134
    {
135 1
        if ($condition[1] instanceof StructuredQuery) {
136 1
            return 'NOT ' . $this->buildSubQuery($condition[1], $state);
137
        }
138
139 1
        return 'NOT (' . $this->buildCondition($condition[1], $state) . ')';
140
    }
141
142 1
    protected function buildBetweenCondition($condition, MySqlQueryBuilderState $state)
143
    {
144 1
        $of = $this->buildCondition($condition[1] ?? null, $state);
145 1
        $from = $this->buildCondition($condition[2] ?? null, $state);
146 1
        $to = $this->buildCondition($condition[3] ?? null, $state);
147
148 1
        return $of . ' BETWEEN ' . $from . ' AND ' . $to;
149
    }
150
151 1
    protected function buildInCondition($condition, MySqlQueryBuilderState $state)
152
    {
153 1
        $left = $this->buildCondition($condition[1] ?? null, $state);
154
155 1
        $right = $condition[2] ?? null;
156 1
        if ($right instanceof StructuredQuery) {
157 1
            return $left . ' IN ' . $this->buildSubQuery($right, $state);
158
        }
159
160 1
        return $left . ' IN (' . $this->buildCondition($right, $state) . ')';
161
    }
162
163 1
    protected function buildLikeCondition($condition, MySqlQueryBuilderState $state)
164
    {
165 1
        $left = $this->buildCondition($condition[1] ?? null, $state);
166 1
        $right = $this->buildCondition($condition[2] ?? null, $state);
167
168 1
        return $left . ' LIKE ' . $right;
169
    }
170
}