1
|
|
|
<?php |
2
|
|
|
if (!function_exists('for_all')) { |
3
|
|
|
/** |
4
|
|
|
* Применение callback функции к каждому элементу массива, который является строкой или просто строке |
5
|
|
|
* Всем переменным не являющимися массивом или строкой, будет присвоено значение null |
6
|
|
|
* |
7
|
|
|
* @param mixed $data Строка или массив с данными |
8
|
|
|
* @param Closure $callback callback функция |
9
|
|
|
* @return mixed |
10
|
|
|
*/ |
11
|
|
|
function for_all($data, Closure $callback) |
12
|
|
|
{ |
13
|
|
|
switch (true) { |
14
|
|
|
case is_array($data): |
15
|
|
|
foreach ($data as &$val) { |
16
|
|
|
$val = for_all($val, $callback); |
17
|
|
|
} |
18
|
|
|
break; |
19
|
|
|
case is_scalar($data): |
20
|
|
|
$data = $callback($data); |
21
|
|
|
break; |
22
|
|
|
default: |
23
|
|
|
$data = null; |
24
|
|
|
} |
25
|
|
|
return $data; |
26
|
|
|
} |
27
|
|
|
} |
28
|
|
|
|
29
|
|
|
if (!function_exists('get_key')) { |
30
|
|
|
/** |
31
|
|
|
* Получение значения по ключу из массива, либо возврат значения по умолчанию |
32
|
|
|
* |
33
|
|
|
* @param mixed $data массив |
34
|
|
|
* @param string $key ключ массива |
35
|
|
|
* @param mixed $default null значение по умолчанию |
36
|
|
|
* @param Closure $validate null функция дополнительной валидации значения (должна возвращать true или false) |
37
|
|
|
* @return mixed |
38
|
|
|
*/ |
39
|
|
|
function get_key($data, $key, $default = null, $validate = null) |
40
|
|
|
{ |
41
|
|
|
$out = $default; |
42
|
|
|
if (is_array($data) && (is_int($key) || is_string($key)) && $key !== '' && array_key_exists($key, $data)) { |
43
|
|
|
$out = $data[$key]; |
44
|
|
|
} |
45
|
|
|
if (!empty($validate) && is_callable($validate)) { |
46
|
|
|
$out = (($validate($out) === true) ? $out : $default); |
47
|
|
|
} |
48
|
|
|
return $out; |
49
|
|
|
} |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
if (!function_exists('rename_key_array')) { |
53
|
|
|
/** |
54
|
|
|
* Переменовывание элементов массива |
55
|
|
|
* |
56
|
|
|
* @param array $data массив с данными |
57
|
|
|
* @param string $prefix префикс ключей |
58
|
|
|
* @param string $suffix суффикс ключей |
59
|
|
|
* @param string $addPS разделитель суффиксов, префиксов и ключей массива |
60
|
|
|
* @param string $sep разделитель ключей при склейке многомерных массивов |
61
|
|
|
* @return array массив с переименованными ключами |
62
|
|
|
*/ |
63
|
|
|
function rename_key_array($data, $prefix = '', $suffix = '', $addPS = '.', $sep = '.') |
64
|
|
|
{ |
65
|
|
|
$out = array(); |
66
|
|
|
if (is_array($data)) { |
67
|
|
|
if (!is_scalar($addPS)) { |
68
|
|
|
$addPS = ''; |
69
|
|
|
} |
70
|
|
|
$InsertPrefix = (is_scalar($prefix) && $prefix !== '') ? ($prefix . $addPS) : ''; |
71
|
|
|
$InsertSuffix = (is_scalar($suffix) && $suffix !== '') ? ($addPS . $suffix) : ''; |
72
|
|
|
foreach ($data as $key => $item) { |
73
|
|
|
$key = $InsertPrefix . $key; |
74
|
|
|
$val = null; |
75
|
|
|
switch (true) { |
76
|
|
|
case is_scalar($item): |
77
|
|
|
$val = $item; |
78
|
|
|
break; |
79
|
|
|
case is_array($item): |
80
|
|
|
$val = (is_scalar($sep) && $sep !== '') ? rename_key_array($item, $key . $sep, $InsertSuffix, '', $sep) : array(); |
81
|
|
|
$out = array_merge($out, $val); |
82
|
|
|
$val = ''; |
83
|
|
|
break; |
84
|
|
|
} |
85
|
|
|
$out[$key . $InsertSuffix] = $val; |
86
|
|
|
} |
87
|
|
|
} |
88
|
|
|
return $out; |
89
|
|
|
} |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
if (!function_exists('make_array')) { |
93
|
|
|
/** |
94
|
|
|
* Создание многомерного массива из двухмерного, в имени которого содержится разделитель |
95
|
|
|
* |
96
|
|
|
* @param array $data массив с данными |
97
|
|
|
* @param string $sep разделитель ключей при склейке многомерных массивов |
98
|
|
|
* @return array массив с переименованными ключами |
99
|
|
|
*/ |
100
|
|
|
function make_array($data, $sep = '.') |
101
|
|
|
{ |
102
|
|
|
$out = array(); |
103
|
|
|
if (is_array($data)) { |
104
|
|
|
if (is_scalar($sep) && $sep !== '') { |
105
|
|
|
foreach ($data as $key => $val) { |
106
|
|
|
$keys = explode($sep, $key); |
107
|
|
|
$workArray = &$out; |
108
|
|
|
foreach ($keys as $i => $subKey) { |
109
|
|
|
if (!array_key_exists($subKey, $workArray)) { |
110
|
|
|
$workArray[$subKey] = ($i + 1 == count($keys)) ? $val : array(); |
111
|
|
|
} |
112
|
|
|
$workArray = &$workArray[$subKey]; |
113
|
|
|
} |
114
|
|
|
} |
115
|
|
|
} else { |
116
|
|
|
$out = $data; |
117
|
|
|
} |
118
|
|
|
} |
119
|
|
|
return $out; |
120
|
|
|
} |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
if (!function_exists('array_sort')) { |
124
|
|
|
/** |
125
|
|
|
* Сортировка массива |
126
|
|
|
* |
127
|
|
|
* @param array $arr массив с данными |
128
|
|
|
* @param string $sort_field по какому ключу сортировать массив |
129
|
|
|
* @param bool $desc направление сортировки |
130
|
|
|
* @return array |
131
|
|
|
*/ |
132
|
|
|
function array_sort(array $arr, $sort_field, $desc = false) |
133
|
|
|
{ |
134
|
|
|
$first = reset($arr); |
135
|
|
|
if (!isset($first[$sort_field])) { |
136
|
|
|
return $arr; |
137
|
|
|
} |
138
|
|
|
$sort = array(); |
139
|
|
|
foreach ($arr as $key => $item) { |
140
|
|
|
$sort[$key] = $item[$sort_field]; |
141
|
|
|
} |
142
|
|
|
array_multisort($sort, $desc ? SORT_DESC : SORT_ASC, $arr); |
143
|
|
|
return $arr; |
144
|
|
|
} |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
if (!function_exists('array_unset')) { |
148
|
|
|
/** |
149
|
|
|
* Удаление списка ключей из массива |
150
|
|
|
* |
151
|
|
|
* @param array $arr массив с данными |
152
|
|
|
* @param string|array $keys ключ или массив ключей, которые необходимо удалить |
153
|
|
|
* @return array |
154
|
|
|
*/ |
155
|
|
|
function array_unset($arr, $keys) |
156
|
|
|
{ |
157
|
|
|
if (is_scalar($keys)) { |
158
|
|
|
$keys = array($keys); |
159
|
|
|
} |
160
|
|
|
if (is_array($keys) && is_array($arr)) { |
161
|
|
|
foreach ($keys as $key) { |
162
|
|
|
if (is_scalar($key)) { |
163
|
|
|
unset($arr[$key]); |
164
|
|
|
} |
165
|
|
|
} |
166
|
|
|
} |
167
|
|
|
return $arr; |
168
|
|
|
} |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
if (!function_exists('array_filter')) { |
172
|
|
|
/** |
173
|
|
|
* Фильтрация массива |
174
|
|
|
* |
175
|
|
|
* @param array $data массив с данными |
176
|
|
|
* @param string|Closure $filter функция для фильтрации массива |
177
|
|
|
* @return array |
178
|
|
|
*/ |
179
|
|
|
function array_filter($data, $filter) |
180
|
|
|
{ |
181
|
|
|
$out = array(); |
182
|
|
|
foreach ($data as $k => $v) { |
183
|
|
|
if (is_callable($filter) && $filter($v, $k)){ |
184
|
|
|
$out[$k] = $v; |
185
|
|
|
} |
186
|
|
|
} |
187
|
|
|
return $out; |
188
|
|
|
} |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
if (!function_exists('array_path')) { |
192
|
|
|
/** |
193
|
|
|
* Получение значения многомерного массива |
194
|
|
|
* |
195
|
|
|
* @param array $array многомерный массив |
196
|
|
|
* @param string $path путь к ключу многомерного массива (каждый уровень разделяется символом $separator) |
197
|
|
|
* @param mixed $default значение по умолчанию, если ключа в массиве нет |
198
|
|
|
* @param string $separator разделитель уровней массива |
199
|
|
|
* @return mixed |
200
|
|
|
*/ |
201
|
|
|
function array_path($array, $path, $default = null, $separator = '.') |
202
|
|
|
{ |
203
|
|
|
$path = explode($separator, $path); |
204
|
|
|
while ($key = array_shift($path)) { |
205
|
|
|
if (!isset($array[$key])){ |
206
|
|
|
return $default; |
207
|
|
|
} |
208
|
|
|
$array = $array[$key]; |
209
|
|
|
} |
210
|
|
|
return $array; |
211
|
|
|
} |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
if (!function_exists('array_path_unset')) { |
215
|
|
|
/** |
216
|
|
|
* Удаление ключа многомерного массива |
217
|
|
|
* |
218
|
|
|
* @param array $array многомерный массив |
219
|
|
|
* @param string $path путь к ключу многомерного массива (каждый уровень разделяется символом $separator) |
220
|
|
|
* @param string $separator разделитель уровней массива |
221
|
|
|
* @return void |
222
|
|
|
*/ |
223
|
|
|
function array_path_unset(&$array, $path, $separator = '.') |
224
|
|
|
{ |
225
|
|
|
$tmp = &$array; |
226
|
|
|
$path = explode($separator, $path); |
227
|
|
View Code Duplication |
while (count($path) > 1) { |
|
|
|
|
228
|
|
|
$key = array_shift($path); |
229
|
|
|
if (!isset($tmp[$key])) return; |
230
|
|
|
$tmp = &$tmp[$key]; |
231
|
|
|
} |
232
|
|
|
unset($tmp[array_shift($path)]); |
233
|
|
|
} |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
if (!function_exists('array_path_replace')) { |
237
|
|
|
/** |
238
|
|
|
* Заменить значение многомерного массива |
239
|
|
|
* |
240
|
|
|
* @param array $array многомерный массив |
241
|
|
|
* @param string $path путь к ключу многомерного массива (каждый уровень разделяется символом $separator) |
242
|
|
|
* @param mixed $value новое значение |
243
|
|
|
* @param string $separator разделитель уровней массива |
244
|
|
|
* @return void |
245
|
|
|
*/ |
246
|
|
|
function array_path_replace(&$array, $path, $value, $separator = '.') |
247
|
|
|
{ |
248
|
|
|
$tmp = &$array; |
249
|
|
|
$path = explode($separator, $path); |
250
|
|
View Code Duplication |
while (count($path) > 1) { |
|
|
|
|
251
|
|
|
$key = array_shift($path); |
252
|
|
|
if (!isset($tmp[$key])) $tmp[$key] = array(); |
253
|
|
|
$tmp = &$tmp[$key]; |
254
|
|
|
} |
255
|
|
|
$tmp[array_shift($path)] = $value; |
256
|
|
|
} |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
if (!function_exists('array_clean')) { |
260
|
|
|
/** |
261
|
|
|
* Удалить пустые элементы из массива |
262
|
|
|
* |
263
|
|
|
* @param array $array |
264
|
|
|
* @param array $symbols удаляемые значения |
265
|
|
|
* @return array |
266
|
|
|
*/ |
267
|
|
|
function array_clean($array, array $symbols = array('', null)) |
268
|
|
|
{ |
269
|
|
|
return is_array($array) ? array_diff($array, $symbols) : array(); |
270
|
|
|
} |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
if( !function_exists('array_shuffle')){ |
274
|
|
|
/** |
275
|
|
|
* Перемешать массив в случайном порядке с сохранением ключей |
276
|
|
|
* |
277
|
|
|
* @param array $data массив с данными |
278
|
|
|
* @return bool результат сортировки массива |
279
|
|
|
*/ |
280
|
|
|
function array_shuffle(array &$data = array()){ |
281
|
|
|
return uksort($data, function() { return rand() > rand(); }); |
282
|
|
|
} |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
if (!function_exists('array_random')) { |
286
|
|
|
/** |
287
|
|
|
* Получить несколько случайных записей из массива с сохранением ключей |
288
|
|
|
* |
289
|
|
|
* @param array $data массив с данными |
290
|
|
|
* @param int $count требуемое число записей из массива |
291
|
|
|
* @return array|mixed |
292
|
|
|
*/ |
293
|
|
|
function array_random(array $data = array(), $count = 1) |
294
|
|
|
{ |
295
|
|
|
$flag = array_shuffle($data); |
296
|
|
|
if ($flag) { |
297
|
|
|
if ((int)$count > 0) { |
298
|
|
|
$data = current(array_chunk($data, (int)$count, true)); |
299
|
|
|
} |
300
|
|
|
} else { |
301
|
|
|
$data = array(); |
302
|
|
|
} |
303
|
|
|
return $data; |
304
|
|
|
} |
305
|
|
|
} |
306
|
|
|
|
307
|
|
|
if(!function_exists('is_assoc')){ |
308
|
|
|
/** |
309
|
|
|
* Является ли массив ассоциативным |
310
|
|
|
* |
311
|
|
|
* @param array $array проверяемый массив |
312
|
|
|
* @return bool результат проверки |
313
|
|
|
*/ |
314
|
|
|
function is_assoc($array) { |
315
|
|
|
return is_array($array) ? (bool)count(array_filter(array_keys($array), 'is_string')) : false; |
316
|
|
|
} |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
if(!function_exists('array_copy_key')){ |
320
|
|
|
/** |
321
|
|
|
* Определить ключи массива равыне значениям |
322
|
|
|
* |
323
|
|
|
* @param array $data исходный массив со значениями |
324
|
|
|
* @return array |
325
|
|
|
*/ |
326
|
|
|
function array_copy_key(array $data = array()){ |
327
|
|
|
$data = array_filter($data, function($val){ |
328
|
|
|
return is_scalar($val); |
329
|
|
|
}); |
330
|
|
|
return array_combine($data, $data); |
331
|
|
|
} |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
if(!function_exists('make_tree')){ |
335
|
|
|
/** |
336
|
|
|
* Helper function |
337
|
|
|
* @see http://gostash.it/ru/users/3191 |
338
|
|
|
* |
339
|
|
|
* @param array $tree flat data, implementing a id/parent id (adjacency list) structure |
340
|
|
|
* @param mixed $pid root id, node to return |
341
|
|
|
* @param string $parent parent id index |
342
|
|
|
* @param string $key id index |
343
|
|
|
* @param string $children children index |
344
|
|
|
* @return array |
345
|
|
|
*/ |
346
|
|
|
function make_tree($tree = array(), $pid = 0, $parent = 'pid', $key = 'id', $children = 'tree') |
347
|
|
|
{ |
348
|
|
|
$result = array(); |
349
|
|
|
|
350
|
|
|
if (!empty($tree)) |
351
|
|
|
{ |
352
|
|
|
$m = array(); |
353
|
|
|
|
354
|
|
|
foreach ($tree as $e) |
355
|
|
|
{ |
356
|
|
|
isset($m[$e[$parent]]) ?: $m[$e[$parent]] = array(); |
357
|
|
|
isset($m[$e[$key]]) ?: $m[$e[$key]] = array(); |
358
|
|
|
|
359
|
|
|
$m[$e[$parent]][] = array_merge($e, array($children => &$m[$e[$key]])); |
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
$result = $m[$pid]; |
363
|
|
|
} |
364
|
|
|
|
365
|
|
|
return $result; |
366
|
|
|
} |
367
|
|
|
} |
368
|
|
|
|
369
|
|
|
if(!function_exists('array_chunk_vcolumn')){ |
370
|
|
|
/** |
371
|
|
|
* Разбиение массива на несколько частей с сохранением ключей, чтобы в каждой из этих частей было равное кол-во элементов |
372
|
|
|
* Массив наполняется последовательно. Т.е. сначала наполняется данными первая часть, потом вторая и так, пока не закончатся данные. |
373
|
|
|
* |
374
|
|
|
* @see: http://gostash.it/ru/stashes/117 |
375
|
|
|
* @param array $input исходный массив |
376
|
|
|
* @param int $size кол-во частей |
377
|
|
|
*/ |
378
|
|
|
function array_chunk_vcolumn(array $input, $size){ |
379
|
|
|
$data = array_fill(0, $size, array()); |
380
|
|
|
$size = ceil(count($input) / $size); |
381
|
|
|
$i = 0; |
382
|
|
|
$j = 0; |
383
|
|
View Code Duplication |
foreach ($input as $k => $v) |
|
|
|
|
384
|
|
|
{ |
385
|
|
|
if (++$j > $size) |
386
|
|
|
{ |
387
|
|
|
$i++; |
388
|
|
|
$j = 1; |
389
|
|
|
} |
390
|
|
|
$data[$i][$k] = $v; |
391
|
|
|
} |
392
|
|
|
return $data; |
393
|
|
|
} |
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
if(!function_exists('array_chunk_hcolumn')){ |
397
|
|
|
/** |
398
|
|
|
* Разбиение массива на несколько частей с сохранением ключей, чтобы в каждой из этих частей было равное кол-во элементов |
399
|
|
|
* Массив наполняется равномерно. Т.е. в первую строку каждой части складывается по одному элементу из массива. Затем аналогичным образом во вторую и так, пока не закончатся данные. |
400
|
|
|
* |
401
|
|
|
* @param array $input исходный массив |
402
|
|
|
* @param int $size кол-во частей |
403
|
|
|
*/ |
404
|
|
|
function array_chunk_hcolumn(array $input, $size){ |
405
|
|
|
$data = array_fill(0, $size, array()); |
406
|
|
|
$j = -1; |
407
|
|
View Code Duplication |
foreach ($input as $k => $v) |
|
|
|
|
408
|
|
|
{ |
409
|
|
|
if (++$j >= $size){ |
410
|
|
|
$j = 0; |
411
|
|
|
} |
412
|
|
|
$data[$j][$k] = $v; |
413
|
|
|
} |
414
|
|
|
return $data; |
415
|
|
|
} |
416
|
|
|
} |
417
|
|
|
|
418
|
|
|
if(!function_exists('array_filter_keys')){ |
419
|
|
|
/** |
420
|
|
|
* Фильтрация массива по ключу |
421
|
|
|
* |
422
|
|
|
* @param array $array исходный массив |
423
|
|
|
* @param string $needle регулярное выражение для фильтрации ключей |
424
|
|
|
*/ |
425
|
|
|
function array_filter_keys($array, $needle){ |
426
|
|
|
$matchedKeys = array_filter(array_keys($array), function($key) use ($needle){ |
427
|
|
|
return preg_match($needle, $key); |
428
|
|
|
}); |
429
|
|
|
return array_intersect_key($array, array_flip($matchedKeys)); |
430
|
|
|
} |
431
|
|
|
} |
432
|
|
|
if(!function_exists('choose_chance')){ |
433
|
|
|
/*** |
|
|
|
|
434
|
|
|
* Выбор ключа массива со определенной вероятность |
435
|
|
|
* choose_chance(array("a" => 10, "b" => 25, "c" => 25, "d" => 40)); |
436
|
|
|
* |
437
|
|
|
* @see: http://gostash.it/ru/stashes/381 |
438
|
|
|
* @param array $arr исходный массив |
439
|
|
|
*/ |
440
|
|
|
function choose_chance(array $arr){ |
441
|
|
|
$rnd = mt_rand(1, array_sum($arr)); |
442
|
|
|
$i = 0; |
443
|
|
|
foreach ($arr as $value => $chance) { |
444
|
|
|
$i += $chance; |
445
|
|
|
//$i = 51; |
|
|
|
|
446
|
|
|
if ($rnd <= $i) { |
447
|
|
|
return $value; |
448
|
|
|
} |
449
|
|
|
} |
450
|
|
|
} |
451
|
|
|
} |
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.