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
|
|
|
// An object (model, element, record) |
96
|
|
|
if (is_object($value)) { |
97
|
|
|
// Try to grab the Id from it |
98
|
|
|
try { |
99
|
|
|
return $value->id ?: false; |
100
|
|
|
} catch (\Exception $e) { |
|
|
|
|
101
|
|
|
// Carry on |
102
|
|
|
} |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
// alpha identifier (handle, etc) |
106
|
|
|
if (is_string($value) && |
107
|
|
|
!in_array($value, ['and', 'or'], true) && |
108
|
|
|
StringHelper::isAlpha($value) |
109
|
|
|
) { |
110
|
|
|
if (null !== $lookup) { |
111
|
|
|
if (null !== ($val = call_user_func($lookup, $value))) { |
112
|
|
|
return static::prepareParam($val, $lookup); |
113
|
|
|
} |
114
|
|
|
} |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
return $value; |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
// Traverse |
121
|
|
|
$return = []; |
122
|
|
|
foreach ($value as $key => $val) { |
123
|
|
|
$return = ArrayHelper::merge( |
124
|
|
|
$return, |
125
|
|
|
static::prepareParamValue($key, $val, $lookup) |
126
|
|
|
); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
return $return; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* @param $key |
134
|
|
|
* @param $value |
135
|
|
|
* @param callable|null $lookup |
136
|
|
|
* @return array |
137
|
|
|
*/ |
138
|
|
|
protected static function prepareParamValue($key, $value, callable $lookup = null): array |
139
|
|
|
{ |
140
|
|
|
$value = static::prepareParam($value, $lookup); |
141
|
|
|
|
142
|
|
|
// Move arrays up one level |
143
|
|
|
if (is_array($value)) { |
144
|
|
|
$values = []; |
145
|
|
|
|
146
|
|
|
$firstVal = strtolower(reset($value)); |
147
|
|
|
|
148
|
|
|
foreach ($value as $k => $val) { |
149
|
|
|
$values = ArrayHelper::merge( |
150
|
|
|
$values, |
151
|
|
|
static::prepareParamValue( |
152
|
|
|
is_numeric($k) ? $key : $k, |
153
|
|
|
$val, |
154
|
|
|
$lookup |
155
|
|
|
) |
156
|
|
|
); |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
if (in_array($firstVal, ['and', 'or'], true)) { |
160
|
|
|
return [$values]; |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
return $values; |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
if (!is_numeric($key)) { |
167
|
|
|
if (is_string($value) || is_numeric($value)) { |
168
|
|
|
$value = $key . ' ' . $value; |
169
|
|
|
} |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
return [$value]; |
173
|
|
|
} |
174
|
|
|
} |
175
|
|
|
|
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
orexit
statements that have been added for debug purposes.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.