Completed
Push — master ( aceef1...ea50c0 )
by Dmitry
04:16
created

QueryBuilder::buildNotEqCondition()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 5
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
crap 2
1
<?php
2
3
/*
4
 * Tools to use API as ActiveRecord for Yii2
5
 *
6
 * @link      https://github.com/hiqdev/yii2-hiart
7
 * @package   yii2-hiart
8
 * @license   BSD-3-Clause
9
 * @copyright Copyright (c) 2015-2016, HiQDev (http://hiqdev.com/)
10
 */
11
12
namespace hiqdev\hiart;
13
14
use yii\base\InvalidParamException;
15
use yii\base\NotSupportedException;
16
use yii\helpers\ArrayHelper;
17
18
/**
19
 * QueryBuilder builds an HiArt query based on the specification given as a [[Query]] object.
20
 */
21
class QueryBuilder extends \yii\base\Object
22
{
23
    private $_sort = [
24
        SORT_ASC  => '_asc',
25
        SORT_DESC => '_desc',
26
    ];
27
28
    public $db;
29
30
    public function __construct($connection, $config = [])
31
    {
32
        $this->db = $connection;
33
        parent::__construct($config);
34
    }
35
36
    /**
37
     * @param ActiveQuery $query
38
     *
39
     * @throws NotSupportedException
40
     *
41
     * @return array
42
     */
43
    public function build($query)
44
    {
45
        $parts = [];
46
        $query->prepare();
47
48
        $this->buildSelect($query->select, $parts);
49
        $this->buildLimit($query->limit, $parts);
50
        $this->buildPage($query->offset, $query->limit, $parts);
51
        $this->buildOrderBy($query->orderBy, $parts);
52
53
        $parts = ArrayHelper::merge($parts, $this->buildCondition($query->where));
54
55
        return [
56
            'queryParts' => $parts,
57
            'index'      => $query->index,
58
            'type'       => $query->type,
59
        ];
60
    }
61
62
    public function buildLimit($limit, &$parts)
63
    {
64
        if (!empty($limit)) {
65
            if ($limit === -1) {
66
                $limit = 'ALL';
67
            }
68
            $parts['limit'] = $limit;
69
        }
70
    }
71
72
    public function buildPage($offset, $limit, &$parts)
73
    {
74
        if ($offset > 0) {
75
            $parts['page'] = ceil($offset / $limit) + 1;
76
        }
77
    }
78
79
    public function buildOrderBy($orderBy, &$parts)
80
    {
81
        if (!empty($orderBy)) {
82
            $parts['orderby'] = key($orderBy) . $this->_sort[reset($orderBy)];
83
        }
84
    }
85
86
    public function buildSelect($select, &$parts)
87
    {
88
        if (!empty($select)) {
89
            foreach ($select as $attribute) {
90
                $parts['select'][$attribute] = $attribute;
91
            }
92
        }
93
    }
94
95
    public function buildCondition($condition)
96
    {
97
        static $builders = [
98
            'and'     => 'buildAndCondition',
99
            'between' => 'buildBetweenCondition',
100
            'eq'      => 'buildEqCondition',
101
            'ne'      => 'buildNotEqCondition',
102
            'in'      => 'buildInCondition',
103
            'like'    => 'buildLikeCondition',
104
            'gt'      => 'buildCompareCondition',
105
            'ge'      => 'buildCompareCondition',
106
            'lt'      => 'buildCompareCondition',
107
            'le'      => 'buildCompareCondition',
108
        ];
109
        if (empty($condition)) {
110
            return [];
111
        }
112
        if (!is_array($condition)) {
113
            throw new NotSupportedException('String conditions in where() are not supported by HiArt.');
114
        }
115
116
        if (isset($condition[0])) { // operator format: operator, operand 1, operand 2, ...
117
            $operator = strtolower($condition[0]);
118
            if (isset($builders[$operator])) {
119
                $method = $builders[$operator];
120
                array_shift($condition); // Shift build condition
121
122
                return $this->$method($operator, $condition);
123
            } else {
124
                throw new InvalidParamException('Found unknown operator in query: ' . $operator);
125
            }
126
        } else {
127
            return $this->buildHashCondition($condition);
128
        }
129
    }
130
131
    private function buildHashCondition($condition)
132
    {
133
        $parts = [];
134
        foreach ($condition as $attribute => $value) {
135
            if (is_array($value)) { // IN condition
136
                // $parts[] = [$attribute.'s' => join(',',$value)];
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% 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...
137
                $parts[$attribute . 's'] = implode(',', $value);
138
            } else {
139
                $parts[$attribute] = $value;
140
            }
141
        }
142
143
        return $parts;
144
    }
145
146
    private function buildLikeCondition($operator, $operands)
0 ignored issues
show
Unused Code introduced by
The parameter $operator is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
147
    {
148
        return [$operands[0] . '_like' => $operands[1]];
149
    }
150
151
    private function buildCompareCondition($operator, $operands)
152
    {
153
        if (!isset($operands[0], $operands[1])) {
154
            throw new InvalidParamException("Operator '$operator' requires three operands.");
155
        }
156
157
        return [$operands[0] . '_' . $operator => $operands[1]];
158
    }
159
160
    private function buildAndCondition($operator, $operands)
0 ignored issues
show
Unused Code introduced by
The parameter $operator is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
161
    {
162
        $parts = [];
163
        foreach ($operands as $operand) {
164
            if (is_array($operand)) {
165
                $parts = \yii\helpers\ArrayHelper::merge($this->buildCondition($operand), $parts);
166
            }
167
        }
168
        if (!empty($parts)) {
169
            return $parts;
170
        } else {
171
            return [];
172
        }
173
    }
174
175
    private function buildBetweenCondition($operator, $operands)
0 ignored issues
show
Unused Code introduced by
The parameter $operator is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $operands is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
176
    {
177
        throw new NotSupportedException('Between condition is not supported by HiArt.');
178
    }
179
180
    private function buildInCondition($operator, $operands)
181
    {
182
        if (!isset($operands[0], $operands[1])) {
183
            throw new InvalidParamException("Operator '$operator' requires two operands.");
184
        }
185
186
        list($column, $values) = $operands;
187
188
        if (count($column) > 1) {
189
            return $this->buildCompositeInCondition($operator, $column, $values);
190
        } elseif (is_array($column)) {
191
            $column = reset($column);
192
        }
193
194
        foreach ((array) $values as $i => $value) {
195
            if (is_array($value)) {
196
                $values[$i] = $value = isset($value[$column]) ? $value[$column] : null;
197
            }
198
            if ($value === null) {
199
                unset($values[$i]);
200
            }
201
        }
202
203
        return [$column . '_in' => $values];
204
    }
205
206
    private function buildEqCondition($operator, $operands)
0 ignored issues
show
Unused Code introduced by
The parameter $operator is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
207
    {
208
        $key = array_shift($operands);
209
210
        return [$key => reset($operands)];
211
    }
212
213
    private function buildNotEqCondition($operator, $operands)
214
    {
215
        $key = array_shift($operands);
216
217
        return [$key . '_' . $operator => reset($operands)];
218
    }
219
220
    protected function buildCompositeInCondition($operator, $columns, $values)
0 ignored issues
show
Unused Code introduced by
The parameter $operator is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $columns is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $values is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
221
    {
222
        throw new NotSupportedException('composite in is not supported by HiArt.');
223
    }
224
}
225