Completed
Push — develop ( 5414b4...71e1c1 )
by Nate
02:38
created

QueryHelper::prepareParamValue()   B

Complexity

Conditions 8
Paths 7

Size

Total Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
dl 0
loc 36
ccs 0
cts 28
cp 0
rs 8.0995
c 0
b 0
f 0
cc 8
nc 7
nop 3
crap 72
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://github.com/flipboxfactory/craft-ember/blob/master/LICENSE
6
 * @link       https://github.com/flipboxfactory/craft-ember/
7
 */
8
9
namespace flipbox\craft\ember\helpers;
10
11
use craft\helpers\StringHelper;
12
use yii\db\Query;
13
use yii\db\QueryInterface;
14
15
/**
16
 * @author Flipbox Factory <[email protected]>
17
 * @since 2.0.0
18
 */
19
class QueryHelper
20
{
21
    /**
22
     * @var array
23
     */
24
    protected static $operators = ['not ', '!=', '<=', '>=', '<', '>', '='];
25
26
    /**
27
     * @param $condition
28
     * @return array
29
     */
30
    public static function conditionToCriteria($condition)
31
    {
32
        if (empty($condition)) {
33
            return $condition;
34
        }
35
36
        // Assume it's an id
37
        if (!is_array($condition)) {
38
            $condition = [
39
                'id' => $condition
40
            ];
41
        }
42
43
        return ['where' => ['and', $condition]];
44
    }
45
46
    /**
47
     * @param QueryInterface|Query $query
48
     * @param array $config
49
     * @return QueryInterface
50
     */
51
    public static function configure(QueryInterface $query, $config = []): QueryInterface
52
    {
53
        // Halt
54
        if (empty($config)) {
55
            return $query;
56
        }
57
58
        // Force array
59
        if (!is_array($config)) {
60
            $config = ArrayHelper::toArray($config, [], false);
61
        }
62
63
        // Populate query attributes
64
        foreach ($config as $name => $value) {
65
            if ($query->canSetProperty($name)) {
66
                $query->$name = $value;
67
            }
68
        }
69
70
        return $query;
71
    }
72
73
    /**
74
     * Prepares a query params input value to be used as a condition.  This will attempt to resolve an object
75
     * or look one up based on a 'handle' or other unique string identifier (via the lookup callable).
76
     *
77
     * ```php
78
     *
79
     * [
80
     *      'and',
81
     *      'not' => [
82
     *          4, elementFiveHandle, $someElementWithIdOfSix
83
     *      ]
84
     * ]
85
     * ```
86
     * Would result in a query condition as `NOT IN (4, 5, 6)`.
87
     *
88
     * @param $value
89
     * @param callable|null $lookup
90
     * @return array|string
91
     */
92
    public static function prepareParam($value, callable $lookup = null)
93
    {
94
        if (!is_array($value)) {
95
96
            // An object (model, element, record)
97
            if (is_object($value)) {
98
                // Try to grab the Id from it
99
                try {
100
                    return $value->id;
101
                } catch (\Exception $e) {
0 ignored issues
show
Unused Code introduced by
catch (\Exception $e) { } does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
102
                    // Carry on
103
                }
104
            }
105
106
            // alpha identifier (handle, etc)
107
            if (is_string($value) &&
108
                !in_array($value, ['and', 'or'], true) &&
109
                StringHelper::isAlpha($value)
110
            ) {
111
112
                if (null !== $lookup) {
113
                    if (null !== ($val = call_user_func($lookup, $value))) {
114
                        return static::prepareParam($val, $lookup);
115
                    }
116
                }
117
            }
118
119
            return $value;
120
        }
121
122
        // Traverse
123
        $return = [];
124
        foreach ($value as $key => $val) {
125
            $return = ArrayHelper::merge(
126
                $return,
127
                static::prepareParamValue($key, $val, $lookup)
128
            );
129
        }
130
131
        return $return;
132
    }
133
134
    /**
135
     * @param $key
136
     * @param $value
137
     * @param callable|null $lookup
138
     * @return array
139
     */
140
    protected static function prepareParamValue($key, $value, callable $lookup = null): array
141
    {
142
        $value = static::prepareParam($value, $lookup);
143
144
        // Move arrays up one level
145
        if (is_array($value)) {
146
            $values = [];
147
148
            $firstVal = strtolower(reset($value));
149
150
            foreach ($value as $k => $val) {
151
                $values = ArrayHelper::merge(
152
                    $values,
153
                    static::prepareParamValue(
154
                        is_numeric($k) ? $key : $k,
155
                        $val,
156
                        $lookup
157
                    )
158
                );
159
            }
160
161
            if (in_array($firstVal, ['and', 'or'], true)) {
162
                return [$values];
163
            }
164
165
            return $values;
166
        }
167
168
        if (!is_numeric($key)) {
169
            if (is_string($value) || is_numeric($value)) {
170
                $value = $key . ' ' . $value;
171
            }
172
        }
173
174
        return [$value];
175
    }
176
177
178
    /**
179
     * Standard param parsing.
180
     *
181
     * @param $value
182
     * @param $join
183
     * @return bool
184
     *
185
     * @deprecated
186
     */
187
    public static function parseBaseParam(&$value, &$join): bool
188
    {
189
        // Force array
190
        if (!is_array($value)) {
191
            $value = [$value];
192
        }
193
194
        // Get join type ('and' , 'or')
195
        $join = self::getJoinType($value, $join);
0 ignored issues
show
Deprecated Code introduced by
The method flipbox\craft\ember\help...ryHelper::getJoinType() has been deprecated.

This method has been deprecated.

Loading history...
196
197
        // Check for object array (via 'id' key)
198
        if ($id = self::findIdFromObjectArray($value)) {
0 ignored issues
show
Deprecated Code introduced by
The method flipbox\craft\ember\help...findIdFromObjectArray() has been deprecated.

This method has been deprecated.

Loading history...
199
            $value = [$id];
200
            return true;
201
        }
202
203
        return false;
204
    }
205
206
    /**
207
     * Attempt to resolve a param value by the value.
208
     * Return false if a 'handle' or other string identifier is detected.
209
     *
210
     * @param $value
211
     * @param $operator
212
     * @return bool
213
     *
214
     * @deprecated
215
     */
216
    public static function findParamValue(&$value, &$operator): bool
217
    {
218
        if (is_array($value) || is_object($value)) {
219
            $value = static::assembleParamValue($value, $operator);
0 ignored issues
show
Deprecated Code introduced by
The method flipbox\craft\ember\help...r::assembleParamValue() has been deprecated.

This method has been deprecated.

Loading history...
220
        } else {
221
            self::normalizeEmptyValue($value);
0 ignored issues
show
Deprecated Code introduced by
The method flipbox\craft\ember\help...::normalizeEmptyValue() has been deprecated.

This method has been deprecated.

Loading history...
222
223
            $operator = self::parseParamOperator($value);
0 ignored issues
show
Deprecated Code introduced by
The method flipbox\craft\ember\help...r::parseParamOperator() has been deprecated.

This method has been deprecated.

Loading history...
224
225
            if (is_numeric($value)) {
226
                $value = self::prependOperator($value, $operator);
0 ignored issues
show
Deprecated Code introduced by
The method flipbox\craft\ember\help...lper::prependOperator() has been deprecated.

This method has been deprecated.

Loading history...
227
            } else {
228
                $value = StringHelper::toLowerCase($value);
229
230
                if ($value !== ':empty:' || $value !== 'not :empty:') {
231
                    // Trim any whitespace from the value
232
                    $value = StringHelper::trim($value);
233
234
                    return false;
235
                }
236
            }
237
        }
238
239
        return true;
240
    }
241
242
    /**
243
     * Format the param value so that we return a string w/ a prepended operator.
244
     *
245
     * @param $value
246
     * @param $operator
247
     * @param string|int|mixed $defaultValue
248
     * @return array|string
249
     *
250
     * @deprecated
251
     */
252
    public static function assembleParamValue($value, $operator, $defaultValue = ':default:')
253
    {
254
        if (is_array($value) || is_object($value)) {
255
            $id = self::findIdFromObjectArray($value, $operator);
0 ignored issues
show
Deprecated Code introduced by
The method flipbox\craft\ember\help...findIdFromObjectArray() has been deprecated.

This method has been deprecated.

Loading history...
256
257
            if ($id !== null) {
258
                return self::prependOperator($id, $operator);
0 ignored issues
show
Deprecated Code introduced by
The method flipbox\craft\ember\help...lper::prependOperator() has been deprecated.

This method has been deprecated.

Loading history...
259
            }
260
261
            if (is_object($value)) {
262
                return $defaultValue;
263
            }
264
        }
265
266
        return self::prependOperator($value, $operator);
0 ignored issues
show
Deprecated Code introduced by
The method flipbox\craft\ember\help...lper::prependOperator() has been deprecated.

This method has been deprecated.

Loading history...
267
    }
268
269
    /**
270
     * Attempt to resolve a param value by the value.
271
     * Return false if a 'handle' or other string identifier is detected.
272
     *
273
     * @param $value
274
     * @param $operator
275
     * @return bool
276
     *
277
     * @deprecated
278
     */
279
    public static function prepParamValue(&$value, &$operator): bool
280
    {
281
282
        if (is_array($value)) {
283
            return true;
284
        } else {
285
            self::normalizeEmptyValue($value);
0 ignored issues
show
Deprecated Code introduced by
The method flipbox\craft\ember\help...::normalizeEmptyValue() has been deprecated.

This method has been deprecated.

Loading history...
286
            $operator = self::parseParamOperator($value);
0 ignored issues
show
Deprecated Code introduced by
The method flipbox\craft\ember\help...r::parseParamOperator() has been deprecated.

This method has been deprecated.

Loading history...
287
288
            if (is_numeric($value)) {
289
                return true;
290
            } else {
291
                $value = StringHelper::toLowerCase($value);
292
293
                if ($value !== ':empty:' || $value !== 'not :empty:') {
294
                    // Trim any whitespace from the value
295
                    $value = StringHelper::trim($value);
296
297
                    return false;
298
                }
299
            }
300
        }
301
302
        return true;
303
    }
304
305
    /**
306
     * @param $value
307
     * @param string $default
308
     * @return mixed|string
309
     *
310
     * @deprecated
311
     */
312
    private static function getJoinType(&$value, $default = 'or')
313
    {
314
315
        // Get first value in array
316
        $joinType = ArrayHelper::firstValue($value);
317
318
        // Make sure first value is a string
319
        $firstVal = is_string($joinType) ? StringHelper::toLowerCase($joinType) : '';
320
321
        if ($firstVal == 'and' || $firstVal == 'or') {
322
            $join = array_shift($value);
323
        } else {
324
            $join = $default;
325
        }
326
327
        return $join;
328
    }
329
330
    /**
331
     * Attempt to get a numeric value from an object array.
332
     * @param $value
333
     * @param null $operator
334
     * @return mixed|string
335
     *
336
     * @deprecated
337
     */
338
    private static function findIdFromObjectArray($value, $operator = null)
339
    {
340
        if ($id = ArrayHelper::getValue($value, 'id')) {
341
            return self::prependOperator($id, $operator);
0 ignored issues
show
Deprecated Code introduced by
The method flipbox\craft\ember\help...lper::prependOperator() has been deprecated.

This method has been deprecated.

Loading history...
342
        }
343
344
        return $id;
345
    }
346
347
    /**
348
     * Prepend the operator to a value
349
     *
350
     * @param $value
351
     * @param null $operator
352
     * @return string|array
353
     *
354
     * @deprecated
355
     */
356
    private static function prependOperator($value, $operator = null)
357
    {
358
359
        if ($operator) {
360
            $operator = StringHelper::toLowerCase($operator);
361
362
            if (in_array($operator, static::$operators) || $operator === 'not') {
363
                if (is_array($value)) {
364
                    $values = [];
365
366
                    foreach ($value as $v) {
367
                        $values[] = $operator . ($operator === 'not' ? ' ' : '') . $v;
368
                    }
369
370
                    return $values;
371
                }
372
373
                return $operator . ($operator === 'not' ? ' ' : '') . $value;
374
            }
375
        }
376
377
        return $value;
378
    }
379
380
    /**
381
     * Normalizes “empty” values.
382
     *
383
     * @param string &$value The param value.
384
     *
385
     * @deprecated
386
     */
387
    private static function normalizeEmptyValue(&$value)
388
    {
389
        if ($value === null) {
390
            $value = ':empty:';
391
        } else {
392
            if (StringHelper::toLowerCase($value) == ':notempty:') {
393
                $value = 'not :empty:';
394
            }
395
        }
396
    }
397
398
    /**
399
     * Extracts the operator from a DB param and returns it.
400
     *
401
     * @param string &$value Te param value.
402
     *
403
     * @return string The operator.
404
     *
405
     * @deprecated
406
     */
407
    private static function parseParamOperator(&$value)
408
    {
409
        foreach (static::$operators as $testOperator) {
410
            // Does the value start with this operator?
411
            $operatorLength = strlen($testOperator);
412
413
            if (strncmp(
414
                    StringHelper::toLowerCase($value),
415
                    $testOperator,
416
                    $operatorLength
417
                ) == 0
418
            ) {
419
                $value = mb_substr($value, $operatorLength);
420
421
                if ($testOperator == 'not ') {
422
                    return 'not';
423
                } else {
424
                    return $testOperator;
425
                }
426
            }
427
        }
428
429
        return '';
430
    }
431
}
432