1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace EntWeChat\Support; |
4
|
|
|
|
5
|
|
|
use Closure; |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* Array helper from Illuminate\Support\Arr. |
9
|
|
|
*/ |
10
|
|
|
class Arr |
11
|
|
|
{ |
12
|
|
|
/** |
13
|
|
|
* Add an element to an array using "dot" notation if it doesn't exist. |
14
|
|
|
* |
15
|
|
|
* @param array $array |
16
|
|
|
* @param string $key |
17
|
|
|
* @param mixed $value |
18
|
|
|
* |
19
|
|
|
* @return array |
20
|
|
|
*/ |
21
|
|
|
public static function add($array, $key, $value) |
22
|
|
|
{ |
23
|
|
|
if (is_null(static::get($array, $key))) { |
24
|
|
|
static::set($array, $key, $value); |
25
|
|
|
} |
26
|
|
|
|
27
|
|
|
return $array; |
28
|
|
|
} |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Build a new array using a callback. |
32
|
|
|
* |
33
|
|
|
* @param array $array |
34
|
|
|
* @param \Closure $callback |
35
|
|
|
* |
36
|
|
|
* @return array |
37
|
|
|
*/ |
38
|
|
View Code Duplication |
public static function build($array, Closure $callback) |
|
|
|
|
39
|
|
|
{ |
40
|
|
|
$results = []; |
41
|
|
|
|
42
|
|
|
foreach ($array as $key => $value) { |
43
|
|
|
list($innerKey, $innerValue) = call_user_func($callback, $key, $value); |
44
|
|
|
$results[$innerKey] = $innerValue; |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
return $results; |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Divide an array into two arrays. One with keys and the other with values. |
52
|
|
|
* |
53
|
|
|
* @param array $array |
54
|
|
|
* |
55
|
|
|
* @return array |
56
|
|
|
*/ |
57
|
|
|
public static function divide($array) |
58
|
|
|
{ |
59
|
|
|
return [ |
60
|
|
|
array_keys($array), |
61
|
|
|
array_values($array), |
62
|
|
|
]; |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Flatten a multi-dimensional associative array with dots. |
67
|
|
|
* |
68
|
|
|
* @param array $array |
69
|
|
|
* @param string $prepend |
70
|
|
|
* |
71
|
|
|
* @return array |
72
|
|
|
*/ |
73
|
|
|
public static function dot($array, $prepend = '') |
74
|
|
|
{ |
75
|
|
|
$results = []; |
76
|
|
|
|
77
|
|
|
foreach ($array as $key => $value) { |
78
|
|
|
if (is_array($value)) { |
79
|
|
|
$results = array_merge($results, static::dot($value, $prepend.$key.'.')); |
80
|
|
|
} else { |
81
|
|
|
$results[$prepend.$key] = $value; |
82
|
|
|
} |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
return $results; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Get all of the given array except for a specified array of items. |
90
|
|
|
* |
91
|
|
|
* @param array $array |
92
|
|
|
* @param array|string $keys |
93
|
|
|
* |
94
|
|
|
* @return array |
95
|
|
|
*/ |
96
|
|
|
public static function except($array, $keys) |
97
|
|
|
{ |
98
|
|
|
return array_diff_key($array, array_flip((array) $keys)); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* Fetch a flattened array of a nested array element. |
103
|
|
|
* |
104
|
|
|
* @param array $array |
105
|
|
|
* @param string $key |
106
|
|
|
* |
107
|
|
|
* @return array |
108
|
|
|
*/ |
109
|
|
|
public static function fetch($array, $key) |
110
|
|
|
{ |
111
|
|
|
$results = []; |
112
|
|
|
|
113
|
|
|
foreach (explode('.', $key) as $segment) { |
114
|
|
|
$results = []; |
115
|
|
|
foreach ($array as $value) { |
116
|
|
|
$value = (array) $value; |
117
|
|
|
$results[] = $value[$segment]; |
118
|
|
|
} |
119
|
|
|
$array = array_values($results); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
return array_values($results); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* Return the first element in an array passing a given truth test. |
127
|
|
|
* |
128
|
|
|
* @param array $array |
129
|
|
|
* @param \Closure $callback |
130
|
|
|
* @param mixed $default |
131
|
|
|
* |
132
|
|
|
* @return mixed |
133
|
|
|
*/ |
134
|
|
|
public static function first($array, $callback, $default = null) |
135
|
|
|
{ |
136
|
|
|
foreach ($array as $key => $value) { |
137
|
|
|
if (call_user_func($callback, $key, $value)) { |
138
|
|
|
return $value; |
139
|
|
|
} |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
return $default; |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Return the last element in an array passing a given truth test. |
147
|
|
|
* |
148
|
|
|
* @param array $array |
149
|
|
|
* @param \Closure $callback |
150
|
|
|
* @param mixed $default |
151
|
|
|
* |
152
|
|
|
* @return mixed |
153
|
|
|
*/ |
154
|
|
|
public static function last($array, $callback, $default = null) |
155
|
|
|
{ |
156
|
|
|
return static::first(array_reverse($array), $callback, $default); |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* Flatten a multi-dimensional array into a single level. |
161
|
|
|
* |
162
|
|
|
* @param array $array |
163
|
|
|
* |
164
|
|
|
* @return array |
165
|
|
|
*/ |
166
|
|
|
public static function flatten($array) |
167
|
|
|
{ |
168
|
|
|
$return = []; |
169
|
|
|
array_walk_recursive( |
170
|
|
|
$array, |
171
|
|
|
function ($x) use (&$return) { |
172
|
|
|
$return[] = $x; |
173
|
|
|
} |
174
|
|
|
); |
175
|
|
|
|
176
|
|
|
return $return; |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* Remove one or many array items from a given array using "dot" notation. |
181
|
|
|
* |
182
|
|
|
* @param array $array |
183
|
|
|
* @param array|string $keys |
184
|
|
|
*/ |
185
|
|
|
public static function forget(&$array, $keys) |
186
|
|
|
{ |
187
|
|
|
$original = &$array; |
188
|
|
|
|
189
|
|
|
foreach ((array) $keys as $key) { |
190
|
|
|
$parts = explode('.', $key); |
191
|
|
|
while (count($parts) > 1) { |
192
|
|
|
$part = array_shift($parts); |
193
|
|
|
if (isset($array[$part]) && is_array($array[$part])) { |
194
|
|
|
$array = &$array[$part]; |
195
|
|
|
} |
196
|
|
|
} |
197
|
|
|
unset($array[array_shift($parts)]); |
198
|
|
|
// clean up after each pass |
199
|
|
|
$array = &$original; |
200
|
|
|
} |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
/** |
204
|
|
|
* Get an item from an array using "dot" notation. |
205
|
|
|
* |
206
|
|
|
* @param array $array |
207
|
|
|
* @param string $key |
208
|
|
|
* @param mixed $default |
209
|
|
|
* |
210
|
|
|
* @return mixed |
211
|
|
|
*/ |
212
|
|
View Code Duplication |
public static function get($array, $key, $default = null) |
|
|
|
|
213
|
|
|
{ |
214
|
|
|
if (is_null($key)) { |
215
|
|
|
return $array; |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
if (isset($array[$key])) { |
219
|
|
|
return $array[$key]; |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
foreach (explode('.', $key) as $segment) { |
223
|
|
|
if (!is_array($array) || !array_key_exists($segment, $array)) { |
224
|
|
|
return $default; |
225
|
|
|
} |
226
|
|
|
$array = $array[$segment]; |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
return $array; |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* Get a subset of the items from the given array. |
234
|
|
|
* |
235
|
|
|
* @param array $array |
236
|
|
|
* @param array|string $keys |
237
|
|
|
* |
238
|
|
|
* @return array |
239
|
|
|
*/ |
240
|
|
|
public static function only($array, $keys) |
241
|
|
|
{ |
242
|
|
|
return array_intersect_key($array, array_flip((array) $keys)); |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* Pluck an array of values from an array. |
247
|
|
|
* |
248
|
|
|
* @param array $array |
249
|
|
|
* @param string $value |
250
|
|
|
* @param string $key |
251
|
|
|
* |
252
|
|
|
* @return array |
253
|
|
|
*/ |
254
|
|
|
public static function pluck($array, $value, $key = null) |
255
|
|
|
{ |
256
|
|
|
$results = []; |
257
|
|
|
|
258
|
|
|
foreach ($array as $item) { |
259
|
|
|
$itemValue = is_object($item) ? $item->{$value} : $item[$value]; |
260
|
|
|
// If the key is "null", we will just append the value to the array and keep |
261
|
|
|
// looping. Otherwise we will key the array using the value of the key we |
262
|
|
|
// received from the developer. Then we'll return the final array form. |
263
|
|
|
if (is_null($key)) { |
264
|
|
|
$results[] = $itemValue; |
265
|
|
|
} else { |
266
|
|
|
$itemKey = is_object($item) ? $item->{$key} : $item[$key]; |
267
|
|
|
$results[$itemKey] = $itemValue; |
268
|
|
|
} |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
return $results; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* Get a value from the array, and remove it. |
276
|
|
|
* |
277
|
|
|
* @param array $array |
278
|
|
|
* @param string $key |
279
|
|
|
* @param mixed $default |
280
|
|
|
* |
281
|
|
|
* @return mixed |
282
|
|
|
*/ |
283
|
|
|
public static function pull(&$array, $key, $default = null) |
284
|
|
|
{ |
285
|
|
|
$value = static::get($array, $key, $default); |
286
|
|
|
static::forget($array, $key); |
287
|
|
|
|
288
|
|
|
return $value; |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
/** |
292
|
|
|
* Set an array item to a given value using "dot" notation. |
293
|
|
|
* |
294
|
|
|
* If no key is given to the method, the entire array will be replaced. |
295
|
|
|
* |
296
|
|
|
* @param array $array |
297
|
|
|
* @param string $key |
298
|
|
|
* @param mixed $value |
299
|
|
|
* |
300
|
|
|
* @return array |
301
|
|
|
*/ |
302
|
|
|
public static function set(&$array, $key, $value) |
303
|
|
|
{ |
304
|
|
|
if (is_null($key)) { |
305
|
|
|
return $array = $value; |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
$keys = explode('.', $key); |
309
|
|
|
|
310
|
|
|
while (count($keys) > 1) { |
311
|
|
|
$key = array_shift($keys); |
312
|
|
|
// If the key doesn't exist at this depth, we will just create an empty array |
313
|
|
|
// to hold the next value, allowing us to create the arrays to hold final |
314
|
|
|
// values at the correct depth. Then we'll keep digging into the array. |
315
|
|
|
if (!isset($array[$key]) || !is_array($array[$key])) { |
316
|
|
|
$array[$key] = []; |
317
|
|
|
} |
318
|
|
|
$array = &$array[$key]; |
319
|
|
|
} |
320
|
|
|
$array[array_shift($keys)] = $value; |
321
|
|
|
|
322
|
|
|
return $array; |
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
/** |
326
|
|
|
* Sort the array using the given Closure. |
327
|
|
|
* |
328
|
|
|
* @param array $array |
329
|
|
|
* @param \Closure $callback |
330
|
|
|
* |
331
|
|
|
* @return array |
332
|
|
|
*/ |
333
|
|
|
public static function sort($array, Closure $callback) |
334
|
|
|
{ |
335
|
|
|
$results = []; |
336
|
|
|
|
337
|
|
|
foreach ($array as $key => $value) { |
338
|
|
|
$results[$key] = $callback($value); |
339
|
|
|
} |
340
|
|
|
|
341
|
|
|
return $results; |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
/** |
345
|
|
|
* Filter the array using the given Closure. |
346
|
|
|
* |
347
|
|
|
* @param array $array |
348
|
|
|
* @param \Closure $callback |
349
|
|
|
* |
350
|
|
|
* @return array |
351
|
|
|
*/ |
352
|
|
View Code Duplication |
public static function where($array, Closure $callback) |
|
|
|
|
353
|
|
|
{ |
354
|
|
|
$filtered = []; |
355
|
|
|
|
356
|
|
|
foreach ($array as $key => $value) { |
357
|
|
|
if (call_user_func($callback, $key, $value)) { |
358
|
|
|
$filtered[$key] = $value; |
359
|
|
|
} |
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
return $filtered; |
363
|
|
|
} |
364
|
|
|
} |
365
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.