Passed
Push — master ( e5d772...d49019 )
by Aleksandar
03:31
created

ConditionTrait::buildUnaryCondition()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 3
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 2
rs 10
c 0
b 0
f 0
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 23
    protected function buildCondition($condition, MySqlQueryBuilderState $state)
29
    {
30 23
        static $map = null;
31
32 23
        if ($map === null) {
33
            $map = [
34 5
                '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->buildUnaryCondition('NOT', $condition, $state),
39 2
                'exists' => fn($condition, $state) => $this->buildUnaryCondition('EXISTS', $condition, $state),
40 3
                'in' => fn($condition, $state) => $this->buildInCondition($condition, $state),
41 3
                'between' => fn($condition, $state) => $this->buildBetweenCondition($condition, $state),
42 3
                'like' => fn($condition, $state) => $this->buildBinaryCondition(' LIKE ', $condition, $state),
43 3
                '=' => fn($condition, $state) => $this->buildBinaryCondition(' = ', $condition, $state),
44 3
                '>' => fn($condition, $state) => $this->buildBinaryCondition(' > ', $condition, $state),
45 3
                '>=' => fn($condition, $state) => $this->buildBinaryCondition(' >= ', $condition, $state),
46 3
                '<' => fn($condition, $state) => $this->buildBinaryCondition(' < ', $condition, $state),
47 3
                '<=' => fn($condition, $state) => $this->buildBinaryCondition(' <= ', $condition, $state),
48 3
                '<>' => fn($condition, $state) => $this->buildBinaryCondition(' <> ', $condition, $state),
49 3
                '!=' => fn($condition, $state) => $this->buildBinaryCondition(' <> ', $condition, $state),
50 14
                'column' => fn($condition) => $this->buildColumnCondition($condition),
51 15
                'value' => fn($condition, $state) => $this->buildValueCondition($condition, $state),
52
            ];
53
        }
54
55 23
        if ($condition instanceof StructuredQuery) {
56 9
            return $this->buildSubQuery($condition, $state);
57
        }
58
59 23
        if (is_array($condition)) {
60 22
            if (empty($map[$condition[0]])) {
61 1
                throw new \Exception('Unknown condition: ' . var_export($condition[0], true));
62
            }
63
64 21
            return $map[$condition[0]]($condition, $state);
65
        }
66
67 1
        throw new \Exception('Condition must be an array.');
68
    }
69
70 5
    protected function buildAssociativeCondition($glue, $condition, MySqlQueryBuilderState $state)
71
    {
72 5
        $result = [];
73 5
        foreach ($condition[1] as $key => $value) {
74 5
            $leftSide = $this->quoteName($key);
75
76 5
            if ($value instanceof StructuredQuery) {
77 2
                $result[] = $leftSide . ' IN ' . $this->buildSubQuery($value, $state);
78 2
                continue;
79
            }
80
81 5
            if (is_array($value)) {
82 2
                $result[] = $leftSide . ' IN (' . $this->buildWrapValue($value, $state) . ')';
83 2
                continue;
84
            }
85
86 5
            $result[] = $leftSide . ' = ' . $this->buildWrapValue($value, $state);
87
        }
88
89 5
        return implode($glue, $result);
90
    }
91
92 18
    protected function buildWrapValue($value, MySqlQueryBuilderState $state, $type = null)
93
    {
94 18
        $builder = $state->getParamsBuilder();
95
96 18
        if (is_array($value)) {
97 3
            $results = [];
98 3
            foreach ($value as $item) {
99 3
                $results[] = $builder->wrapValue($item, $type);
100
            }
101 3
            return implode(', ', $results);
102
        }
103
104 17
        return $builder->wrapValue($value, $type);
105
    }
106
107 2
    protected function buildConjuctionCondition(string $glue, $condition, MySqlQueryBuilderState $state)
108
    {
109 2
        $result = [];
110
111 2
        $max = count($condition);
112 2
        for ($i = 1; $i < $max; $i++) {
113 2
            $result[] = '(' . $this->buildCondition($condition[$i], $state) . ')';
114
        }
115
116 2
        return implode($glue, $result);
117
    }
118
119 12
    protected function buildColumnCondition($condition)
120
    {
121 12
        $column = $condition[1] ?? null;
122
123 12
        if (empty($column)) {
124 1
            throw new \Exception('Column name must be set.');
125 11
        } else if (!is_string($column)) {
126 1
            throw new \Exception('Column name must be a string.');
127
        }
128
129 10
        return $this->quoteName($column);
130
    }
131
132 13
    protected function buildValueCondition($condition, MySqlQueryBuilderState $state)
133
    {
134 13
        return $this->buildWrapValue(
135 13
            $condition[1] ?? null,
136
            $state,
137 13
            $condition[2] ?? null
138
        );
139
    }
140
141 2
    protected function buildUnaryCondition(string $op, $condition, MySqlQueryBuilderState $state)
142
    {
143 2
        if ($condition[1] instanceof StructuredQuery) {
144 2
            return $op . ' ' . $this->buildSubQuery($condition[1], $state);
145
        }
146
147 2
        return $op . ' (' . $this->buildCondition($condition[1], $state) . ')';
148
    }
149
150 1
    protected function buildBetweenCondition($condition, MySqlQueryBuilderState $state)
151
    {
152 1
        $of = $this->buildCondition($condition[1] ?? null, $state);
153 1
        $from = $this->buildCondition($condition[2] ?? null, $state);
154 1
        $to = $this->buildCondition($condition[3] ?? null, $state);
155
156 1
        return $of . ' BETWEEN ' . $from . ' AND ' . $to;
157
    }
158
159
160 7
    protected function buildBinaryCondition(string $operation, $condition, MySqlQueryBuilderState $state)
161
    {
162 7
        $left = $this->buildCondition($condition[1] ?? null, $state);
163 7
        $right = $this->buildCondition($condition[2] ?? null, $state);
164
165 7
        return $left . $operation . $right;
166
    }
167
168 1
    protected function buildInCondition($condition, MySqlQueryBuilderState $state)
169
    {
170 1
        $left = $this->buildCondition($condition[1] ?? null, $state);
171
172 1
        $right = $condition[2] ?? null;
173 1
        if ($right instanceof StructuredQuery) {
174 1
            return $left . ' IN ' . $this->buildSubQuery($right, $state);
175
        }
176
177 1
        return $left . ' IN (' . $this->buildCondition($right, $state) . ')';
178
    }
179
}