Completed
Push — master ( 59b3e2...6dd6b9 )
by Andrii
15:38
created

AbstractQueryBuilder::buildInCondition()   D

Complexity

Conditions 9
Paths 30

Size

Total Lines 30
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 30
rs 4.909
c 0
b 0
f 0
cc 9
eloc 18
nc 30
nop 3
1
<?php
2
/**
3
 * Tools to use API as ActiveRecord for Yii2
4
 *
5
 * @link      https://github.com/hiqdev/yii2-hiart
6
 * @package   yii2-hiart
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2015-2017, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hiqdev\hiart;
12
13
use yii\base\InvalidParamException;
14
use yii\base\NotSupportedException;
15
use yii\helpers\ArrayHelper;
16
17
/**
18
 * Abstract QueryBuilder.
19
 *
20
 * QueryBuilder builds a request from the specification given as a [[Query]] object.
21
 */
22
abstract class AbstractQueryBuilder extends \yii\base\Object implements QueryBuilderInterface
23
{
24
    public $db;
25
26
    public function __construct($connection, $config = [])
27
    {
28
        $this->db = $connection;
29
        parent::__construct($config);
30
    }
31
32
    /**
33
     * Builds config array to create Command.
34
     * @param Query $query
35
     * @throws NotSupportedException
36
     * @return array
37
     */
38
    public function build(Query $query)
39
    {
40
        return ['request' => $this->createRequest($query)];
41
    }
42
43
    public function createRequest($query)
44
    {
45
        return new $this->db->requestClass($this, $query);
46
    }
47
48
    /**
49
     * Prepares query before actual building.
50
     * This function for you to redefine.
51
     * It will be called before other build functions.
52
     * @param Query $query
53
     */
54
    public function prepare(Query $query)
55
    {
56
        return $query->prepare($this);
0 ignored issues
show
Documentation introduced by
$this is of type this<hiqdev\hiart\AbstractQueryBuilder>, but the function expects a object<yii\db\QueryBuilder>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
57
    }
58
59
    /**
60
     * This function is for you to provide your authentication.
61
     * @param Query $query
62
     */
63
    abstract public function buildAuth(Query $query);
64
65
    abstract public function buildMethod(Query $query);
66
67
    abstract public function buildUri(Query $query);
68
69
    abstract public function buildHeaders(Query $query);
70
71
    abstract public function buildProtocolVersion(Query $query);
72
73
    abstract public function buildQueryParams(Query $query);
74
75
    abstract public function buildFormParams(Query $query);
76
77
    abstract public function buildBody(Query $query);
78
79
    /**
80
     * Creates insert request.
81
     * @param string $table
82
     * @param array $columns
83
     * @param array $options
84
     * @return Request
85
     */
86
    public function insert($table, $columns, array $options = [])
87
    {
88
        return $this->perform('insert', $table, $columns, $options);
89
    }
90
91
    /**
92
     * Creates update request.
93
     * @param string $table
94
     * @param array $columns
95
     * @param array $options
96
     * @return Request
97
     */
98
    public function update($table, $columns, $condition = [], array $options = [])
99
    {
100
        $query = $this->createQuery('update', $table, $options)->body($columns)->where($condition);
101
102
        return $this->createRequest($query);
103
    }
104
105
    public function delete($table, $condition = [], array $options = [])
106
    {
107
        $query = $this->createQuery('delete', $table, $options)->where($condition);
108
109
        return $this->createRequest($query);
110
    }
111
112
    public function perform($action, $table, $body, $options = [])
113
    {
114
        $query = $this->createQuery($action, $table, $options)->body($body);
115
116
        return $this->createRequest($query);
117
    }
118
119
    public function createQuery($action, $table, array $options = [])
120
    {
121
        $class = $this->db->queryClass;
122
123
        return $class::instantiate($action, $table, $options);
124
    }
125
126
    public function buildCondition($condition)
127
    {
128
        static $builders = [
129
            'and'     => 'buildAndCondition',
130
            'between' => 'buildBetweenCondition',
131
            'eq'      => 'buildEqCondition',
132
            'ne'      => 'buildNotEqCondition',
133
            'in'      => 'buildInCondition',
134
            'ni'      => 'buildNotInCondition',
135
            'like'    => 'buildLikeCondition',
136
            'ilike'   => 'buildIlikeCondition',
137
            'gt'      => 'buildCompareCondition',
138
            'ge'      => 'buildCompareCondition',
139
            'lt'      => 'buildCompareCondition',
140
            'le'      => 'buildCompareCondition',
141
        ];
142
        if (empty($condition)) {
143
            return [];
144
        }
145
        if (!is_array($condition)) {
146
            throw new NotSupportedException('String conditions in where() are not supported by HiArt.');
147
        }
148
149
        if (isset($condition[0])) { // operator format: operator, operand 1, operand 2, ...
150
            $operator = strtolower($condition[0]);
151
            if (isset($builders[$operator])) {
152
                $method = $builders[$operator];
153
                array_shift($condition); // Shift build condition
154
155
                return $this->$method($operator, $condition);
156
            } else {
157
                throw new InvalidParamException('Found unknown operator in query: ' . $operator);
158
            }
159
        } else {
160
            return $this->buildHashCondition($condition);
161
        }
162
    }
163
164
    protected function buildHashCondition($condition)
165
    {
166
        $parts = [];
167
        foreach ($condition as $attribute => $value) {
168
            if (is_array($value)) { // IN condition
169
                // $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...
170
                $parts[$attribute . 's'] = implode(',', $value);
171
            } else {
172
                $parts[$attribute] = $value;
173
            }
174
        }
175
176
        return $parts;
177
    }
178
179
    protected 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...
180
    {
181
        return [$operands[0] . '_like' => $operands[1]];
182
    }
183
184
    protected function buildIlikeCondition($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...
185
    {
186
        return [$operands[0] . '_ilike' => $operands[1]];
187
    }
188
189
    protected function buildCompareCondition($operator, $operands)
190
    {
191
        if (!isset($operands[0], $operands[1])) {
192
            throw new InvalidParamException("Operator '$operator' requires three operands.");
193
        }
194
195
        return [$operands[0] . '_' . $operator => $operands[1]];
196
    }
197
198
    protected 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...
199
    {
200
        $parts = [];
201
        foreach ($operands as $operand) {
202
            if (is_array($operand)) {
203
                $parts = ArrayHelper::merge($this->buildCondition($operand), $parts);
204
            }
205
        }
206
        if (!empty($parts)) {
207
            return $parts;
208
        } else {
209
            return [];
210
        }
211
    }
212
213
    protected function buildBetweenCondition($operator, $operands)
0 ignored issues
show
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...
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...
214
    {
215
        throw new NotSupportedException('Between condition is not supported by HiArt.');
216
    }
217
218
    protected function buildInCondition($operator, $operands, $not = false)
219
    {
220
        if (!isset($operands[0], $operands[1])) {
221
            throw new InvalidParamException("Operator '$operator' requires two operands.");
222
        }
223
224
        list($column, $values) = $operands;
225
226
        if (count($column) > 1) {
227
            return $this->buildCompositeInCondition($operator, $column, $values);
228
        } elseif (is_array($column)) {
229
            $column = reset($column);
230
        }
231
232
        foreach ((array) $values as $i => $value) {
233
            if (is_array($value)) {
234
                $values[$i] = $value = isset($value[$column]) ? $value[$column] : null;
235
            }
236
            if ($value === null) {
237
                unset($values[$i]);
238
            }
239
        }
240
241
        if ($not) {
242
            $key = $column . '_ni'; // not in
243
        } else {
244
            $key = $column . '_in';
245
        }
246
        return [$key => $values];
247
    }
248
249
    protected function buildNotInCondition($operator, $operands)
250
    {
251
        return $this->buildInCondition($operator, $operands, true);
252
    }
253
254
    protected 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...
255
    {
256
        $key = array_shift($operands);
257
258
        return [$key => reset($operands)];
259
    }
260
261
    protected function buildNotEqCondition($operator, $operands)
262
    {
263
        $key = array_shift($operands);
264
265
        return [$key . '_' . $operator => reset($operands)];
266
    }
267
268
    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...
269
    {
270
        throw new NotSupportedException('composite in is not supported by HiArt.');
271
    }
272
}
273