Completed
Push — master ( 193c3c...281dde )
by Nate
07:20
created

QueryHelper::findParamValue()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 26
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
dl 0
loc 26
ccs 0
cts 19
cp 0
rs 8.439
c 0
b 0
f 0
nc 4
cc 6
eloc 14
nop 2
crap 42
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\ember\helpers;
10
11
use craft\helpers\ArrayHelper;
12
use craft\helpers\StringHelper;
13
use yii\db\Query;
14
use yii\db\QueryInterface;
15
16
/**
17
 * @author Flipbox Factory <[email protected]>
18
 * @since 1.0.0
19
 */
20
class QueryHelper
21
{
22
    /**
23
     * @var array
24
     */
25
    protected static $operators = ['not ', '!=', '<=', '>=', '<', '>', '='];
26
27
    /**
28
     * @param QueryInterface|Query $query
29
     * @param array $config
30
     * @return QueryInterface
31
     */
32
    public static function configure(QueryInterface $query, $config = []): QueryInterface
33
    {
34
        // Halt
35
        if (empty($config)) {
36
            return $query;
37
        }
38
39
        // Force array
40
        if (!is_array($config)) {
41
            $config = ArrayHelper::toArray($config, [], false);
42
        }
43
44
        // Populate query attributes
45
        foreach ($config as $name => $value) {
46
            if ($query->canSetProperty($name)) {
47
                $query->$name = $value;
48
            }
49
        }
50
51
        return $query;
52
    }
53
54
    /**
55
     * Standard param parsing.
56
     *
57
     * @param $value
58
     * @param $join
59
     * @return bool
60
     */
61
    public static function parseBaseParam(&$value, &$join): bool
62
    {
63
        // Force array
64
        if (!is_array($value)) {
65
            $value = [$value];
66
        }
67
68
        // Get join type ('and' , 'or')
69
        $join = static::getJoinType($value, $join);
0 ignored issues
show
Bug introduced by
Since getJoinType() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of getJoinType() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
70
71
        // Check for object array (via 'id' key)
72
        if ($id = static::findIdFromObjectArray($value)) {
0 ignored issues
show
Bug introduced by
Since findIdFromObjectArray() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of findIdFromObjectArray() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
73
            $value = [$id];
74
            return true;
75
        }
76
77
        return false;
78
    }
79
80
    /**
81
     * Attempt to resolve a param value by the value.
82
     * Return false if a 'handle' or other string identifier is detected.
83
     *
84
     * @param $value
85
     * @param $operator
86
     * @return bool
87
     */
88
    public static function findParamValue(&$value, &$operator): bool
89
    {
90
91
        if (is_array($value) || is_object($value)) {
92
            $value = static::assembleParamValue($value, $operator);
93
        } else {
94
            static::normalizeEmptyValue($value);
0 ignored issues
show
Bug introduced by
Since normalizeEmptyValue() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of normalizeEmptyValue() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
95
96
            $operator = static::parseParamOperator($value);
0 ignored issues
show
Bug introduced by
Since parseParamOperator() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of parseParamOperator() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
97
98
            if (is_numeric($value)) {
99
                $value = static::assembleParamValue($value, $operator);
100
            } else {
101
                $value = StringHelper::toLowerCase($value);
102
103
                if ($value !== ':empty:' || $value !== 'not :empty:') {
104
                    // Trim any whitespace from the value
105
                    $value = StringHelper::trim($value);
106
107
                    return false;
108
                }
109
            }
110
        }
111
112
        return true;
113
    }
114
115
    /**
116
     * Format the param value so that we return a string w/ a prepended operator.
117
     *
118
     * @param $value
119
     * @param $operator
120
     * @return string
121
     */
122
    public static function assembleParamValue($value, $operator)
123
    {
124
125
        // Handle arrays as values
126
        if (is_array($value) || is_object($value)) {
127
            // Look for an 'id' key in an array
128
            if ($id = static::findIdFromObjectArray($value, $operator)) {
0 ignored issues
show
Bug introduced by
Since findIdFromObjectArray() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of findIdFromObjectArray() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
129
                // Prepend the operator
130
                return static::prependOperator($id, $operator);
0 ignored issues
show
Bug introduced by
Since prependOperator() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of prependOperator() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
131
            }
132
        }
133
134
        return static::prependOperator($value, $operator);
0 ignored issues
show
Bug introduced by
Since prependOperator() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of prependOperator() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
135
    }
136
137
    /**
138
     * Attempt to resolve a param value by the value.
139
     * Return false if a 'handle' or other string identifier is detected.
140
     *
141
     * @param $value
142
     * @param $operator
143
     * @return bool
144
     */
145
    public static function prepParamValue(&$value, &$operator): bool
146
    {
147
148
        if (is_array($value)) {
149
            return true;
150
        } else {
151
            static::normalizeEmptyValue($value);
0 ignored issues
show
Bug introduced by
Since normalizeEmptyValue() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of normalizeEmptyValue() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
152
            $operator = static::parseParamOperator($value);
0 ignored issues
show
Bug introduced by
Since parseParamOperator() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of parseParamOperator() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
153
154
            if (is_numeric($value)) {
155
                return true;
156
            } else {
157
                $value = StringHelper::toLowerCase($value);
158
159
                if ($value !== ':empty:' || $value !== 'not :empty:') {
160
                    // Trim any whitespace from the value
161
                    $value = StringHelper::trim($value);
162
163
                    return false;
164
                }
165
            }
166
        }
167
168
        return true;
169
    }
170
171
    /**
172
     * @param $value
173
     * @param string $default
174
     * @return mixed|string
175
     */
176
    private static function getJoinType(&$value, $default = 'or')
177
    {
178
179
        // Get first value in array
180
        $joinType = ArrayHelper::firstValue($value);
181
182
        // Make sure first value is a string
183
        $firstVal = is_string($joinType) ? StringHelper::toLowerCase($joinType) : '';
184
185
        if ($firstVal == 'and' || $firstVal == 'or') {
186
            $join = array_shift($value);
187
        } else {
188
            $join = $default;
189
        }
190
191
        return $join;
192
    }
193
194
    /**
195
     * Attempt to get a numeric value from an object array.
196
     * @param $value
197
     * @param null $operator
198
     * @return mixed|string
199
     */
200
    private static function findIdFromObjectArray($value, $operator = null)
201
    {
202
        if ($id = ArrayHelper::getValue($value, 'id')) {
203
            return static::prependOperator($id, $operator);
0 ignored issues
show
Bug introduced by
Since prependOperator() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of prependOperator() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
204
        }
205
206
        return $id;
207
    }
208
209
    /**
210
     * Prepend the operator to a value
211
     *
212
     * @param $value
213
     * @param null $operator
214
     * @return string|array
215
     */
216
    private static function prependOperator($value, $operator = null)
217
    {
218
219
        if ($operator) {
220
            $operator = StringHelper::toLowerCase($operator);
221
222
            if (in_array($operator, static::$operators) || $operator === 'not') {
223
                if (is_array($value)) {
224
                    $values = [];
225
226
                    foreach ($value as $v) {
227
                        $values[] = $operator . ($operator === 'not' ? ' ' : '') . $v;
228
                    }
229
230
                    return $values;
231
                }
232
233
                return $operator . ($operator === 'not' ? ' ' : '') . $value;
234
            }
235
        }
236
237
        return $value;
238
    }
239
240
    /**
241
     * Normalizes “empty” values.
242
     *
243
     * @param string &$value The param value.
244
     */
245
    private static function normalizeEmptyValue(&$value)
246
    {
247
        if ($value === null) {
248
            $value = ':empty:';
249
        } else {
250
            if (StringHelper::toLowerCase($value) == ':notempty:') {
251
                $value = 'not :empty:';
252
            }
253
        }
254
    }
255
256
    /**
257
     * Extracts the operator from a DB param and returns it.
258
     *
259
     * @param string &$value Te param value.
260
     *
261
     * @return string The operator.
262
     */
263
    private static function parseParamOperator(&$value)
264
    {
265
        foreach (static::$operators as $testOperator) {
266
            // Does the value start with this operator?
267
            $operatorLength = strlen($testOperator);
268
269
            if (strncmp(
270
                StringHelper::toLowerCase($value),
271
                $testOperator,
272
                $operatorLength
273
            ) == 0
274
            ) {
275
                $value = mb_substr($value, $operatorLength);
276
277
                if ($testOperator == 'not ') {
278
                    return 'not';
279
                } else {
280
                    return $testOperator;
281
                }
282
            }
283
        }
284
285
        return '';
286
    }
287
}
288