Arr   D
last analyzed

Complexity

Total Complexity 211

Size/Duplication

Total Lines 1335
Duplicated Lines 9.74 %

Coupling/Cohesion

Components 2
Dependencies 0

Importance

Changes 8
Bugs 0 Features 1
Metric Value
wmc 211
c 8
b 0
f 1
lcom 2
cbo 0
dl 130
loc 1335
rs 4.4102

41 Methods

Rating   Name   Duplication   Size   Complexity  
C get() 9 47 13
C set() 4 34 7
C pluck() 0 25 13
A has() 0 14 4
C delete() 9 38 7
B assocToKeyval() 0 18 6
A toAssoc() 0 15 3
B isAssoc() 0 17 5
B flatten() 0 26 6
A flattenAssoc() 0 4 1
D reverseFlatten() 4 34 9
A filterPrefixed() 16 16 4
B filterRecursive() 0 15 5
A removePrefixed() 0 11 3
A filterSuffixed() 16 16 4
A removeSuffixed() 0 11 3
B filterKeys() 0 16 6
A insert() 0 11 2
A insertAssoc() 0 11 2
A insertBeforeKey() 11 11 3
A insertAfterKey() 15 15 3
A insertAfterValue() 11 11 2
A insertBeforeValue() 11 11 2
C sort() 0 41 7
B multisort() 0 26 6
A average() 0 10 2
B replaceKey() 0 28 6
D merge() 0 37 10
C mergeAssoc() 0 32 8
A prepend() 0 4 2
B inArrayRecursive() 0 20 7
A isMulti() 0 5 2
C search() 0 39 14
B unique() 0 26 2
A sum() 0 9 3
A reIndex() 0 12 3
B previousByKey() 12 27 6
B nextByKey() 12 27 6
B previousByValue() 0 27 6
B nextByValue() 0 27 6
A subset() 0 11 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Arr often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Arr, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @package    Fuel\Common
4
 * @version    2.0
5
 * @author     Fuel Development Team
6
 * @license    MIT License
7
 * @copyright  2010 - 2015 Fuel Development Team
8
 * @link       http://fuelphp.com
9
 */
10
11
namespace Fuel\Common;
12
13
/**
14
 * The Arr class provides a few nice functions for making
15
 * dealing with arrays easier
16
 *
17
 * @package Fuel\Common
18
 *
19
 * @since 2.0
20
 */
21
class Arr
22
{
23
	/**
24
	 * Gets a dot-notated key from an array, with a default value if it does
25
	 * not exist.
26
	 *
27
	 * @param   array  $array   The search array
28
	 * @param   mixed  $key     The dot-notated key or array of keys
29
	 * @param   string $default The default value
30
	 *
31
	 * @return  mixed
32
	 *
33
	 * @throws \InvalidArgumentException
34
	 * @since 2.0
35
	 */
36
	public static function get($array, $key, $default = null)
37
	{
38
		if (! is_array($array) and ! $array instanceof \ArrayAccess)
39
		{
40
			throw new \InvalidArgumentException('First parameter must be an array or ArrayAccess object.');
41
		}
42
43
		if (is_null($key))
44
		{
45
			return $array;
46
		}
47
48 View Code Duplication
		if (is_array($key))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
49
		{
50
			$return = array();
51
			foreach ($key as $k)
52
			{
53
				$return[$k] = static::get($array, $k, $default);
54
			}
55
			return $return;
56
		}
57
58
		if (is_object($key))
59
		{
60
			$key = (string) $key;
61
		}
62
63
		if (array_key_exists($key, $array))
64
		{
65
			return $array[$key];
66
		}
67
68
		foreach (explode('.', $key) as $key_part)
69
		{
70
			if (($array instanceof \ArrayAccess and isset($array[$key_part])) === false)
71
			{
72
				if (! is_array($array) or ! array_key_exists($key_part, $array))
73
				{
74
					return result($default);
75
				}
76
			}
77
78
			$array = $array[$key_part];
79
		}
80
81
		return $array;
82
	}
83
84
	/**
85
	 * Set an array item (dot-notated) to the value.
86
	 *
87
	 * @param   array $array The array to insert it into
88
	 * @param   mixed $key   The dot-notated key to set or array of keys
89
	 * @param   mixed $value The value
90
	 *
91
	 * @return  void
92
	 * @since 2.0
93
	 */
94
	public static function set(&$array, $key, $value = null)
95
	{
96
		if (is_null($key))
97
		{
98
			$array = $value;
99
			return;
100
		}
101
102
		if (is_array($key))
103
		{
104
			foreach ($key as $k => $v)
105
			{
106
				static::set($array, $k, $v);
107
			}
108
		}
109
		else
110
		{
111
			$keys = explode('.', $key);
112
113
			while (count($keys) > 1)
114
			{
115
				$key = array_shift($keys);
116
117 View Code Duplication
				if (! isset($array[$key]) or ! is_array($array[$key]))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
118
				{
119
					$array[$key] = array();
120
				}
121
122
				$array =& $array[$key];
123
			}
124
125
			$array[array_shift($keys)] = $value;
126
		}
127
	}
128
129
	/**
130
	 * Pluck an array of values from an array.
131
	 *
132
	 * @param  array  $array collection of arrays to pluck from
133
	 * @param  string $key   key of the value to pluck
134
	 * @param  string $index optional return array index key, true for original index
135
	 *
136
	 * @return array   array of plucked values
137
	 * @since 2.0
138
	 */
139
	public static function pluck($array, $key, $index = null)
140
	{
141
		$return = array();
142
		$get_deep = strpos($key, '.') !== false;
143
144
		if (! $index)
0 ignored issues
show
Bug Best Practice introduced by
The expression $index of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
145
		{
146
			foreach ($array as $i => $a)
147
			{
148
				$return[] = (is_object($a) and ! ($a instanceof \ArrayAccess)) ? $a->{$key} :
149
					($get_deep ? static::get($a, $key) : $a[$key]);
150
			}
151
		}
152
		else
153
		{
154
			foreach ($array as $i => $a)
155
			{
156
				$index !== true and $i = (is_object($a) and ! ($a instanceof \ArrayAccess)) ? $a->{$index} : $a[$index];
157
				$return[$i] = (is_object($a) and ! ($a instanceof \ArrayAccess)) ? $a->{$key} :
158
					($get_deep ? static::get($a, $key) : $a[$key]);
159
			}
160
		}
161
162
		return $return;
163
	}
164
165
	/**
166
	 * Array_key_exists with a dot-notated key from an array.
167
	 *
168
	 * @param   array $array The search array
169
	 * @param   mixed $key   The dot-notated key or array of keys
170
	 *
171
	 * @return  mixed
172
	 * @since 2.0
173
	 */
174
	public static function has($array, $key)
175
	{
176
		foreach (explode('.', $key) as $key_part)
177
		{
178
			if (! is_array($array) or ! array_key_exists($key_part, $array))
179
			{
180
				return false;
181
			}
182
183
			$array = $array[$key_part];
184
		}
185
186
		return true;
187
	}
188
189
	/**
190
	 * Unsets dot-notated key from an array
191
	 *
192
	 * @param   array $array The search array
193
	 * @param   mixed $key   The dot-notated key or array of keys
194
	 *
195
	 * @return  mixed
196
	 * @since 2.0
197
	 */
198
	public static function delete(&$array, $key)
199
	{
200
		if (is_null($key))
201
		{
202
			return false;
203
		}
204
205 View Code Duplication
		if (is_array($key))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
206
		{
207
			$return = array();
208
			foreach ($key as $k)
209
			{
210
				$return[$k] = static::delete($array, $k);
211
			}
212
			return $return;
213
		}
214
215
		$key_parts = explode('.', $key);
216
217
		if (! is_array($array) or ! array_key_exists($key_parts[0], $array))
218
		{
219
			return false;
220
		}
221
222
		$this_key = array_shift($key_parts);
223
224
		if (! empty($key_parts))
225
		{
226
			$key = implode('.', $key_parts);
227
			return static::delete($array[$this_key], $key);
228
		}
229
		else
230
		{
231
			unset($array[$this_key]);
232
		}
233
234
		return true;
235
	}
236
237
	/**
238
	 * Converts a multi-dimensional associative array into an array of key => values with the provided field names
239
	 *
240
	 * @param   array  $assoc     the array to convert
241
	 * @param   string $key_field the field name of the key field
242
	 * @param   string $val_field the field name of the value field
243
	 *
244
	 * @return  array
245
	 * @throws  \InvalidArgumentException
246
	 * @since 2.0
247
	 */
248
	public static function assocToKeyval($assoc, $key_field, $val_field)
249
	{
250
		if (! is_array($assoc) and ! $assoc instanceof \Iterator)
251
		{
252
			throw new \InvalidArgumentException('The first parameter must be an array.');
253
		}
254
255
		$output = array();
256
		foreach ($assoc as $row)
257
		{
258
			if (isset($row[$key_field]) and isset($row[$val_field]))
259
			{
260
				$output[$row[$key_field]] = $row[$val_field];
261
			}
262
		}
263
264
		return $output;
265
	}
266
267
	/**
268
	 * Converts the given 1 dimensional non-associative array to an associative
269
	 * array.
270
	 *
271
	 * The array given must have an even number of elements or null will be returned.
272
	 *
273
	 *     Arr::to_assoc(array('foo','bar'));
274
	 *
275
	 * @param   string $arr the array to change
276
	 *
277
	 * @return  array|null  the new array or null
278
	 * @throws  \BadMethodCallException
279
	 * @since 2.0
280
	 */
281
	public static function toAssoc($arr)
282
	{
283
		if (($count = count($arr)) % 2 > 0)
284
		{
285
			throw new \BadMethodCallException('Number of values in to_assoc must be even.');
286
		}
287
		$keys = $vals = array();
288
289
		for ($i = 0; $i < $count - 1; $i += 2)
290
		{
291
			$keys[] = array_shift($arr);
292
			$vals[] = array_shift($arr);
293
		}
294
		return array_combine($keys, $vals);
295
	}
296
297
	/**
298
	 * Checks if the given array is an assoc array.
299
	 *
300
	 * @param   array $arr the array to check
301
	 *
302
	 * @return  bool   true if its an assoc array, false if not
303
	 *
304
	 * @throws \InvalidArgumentException
305
	 * @since 2.0
306
	 */
307
	public static function isAssoc($arr)
308
	{
309
		if (! is_array($arr))
310
		{
311
			throw new \InvalidArgumentException('The parameter must be an array.');
312
		}
313
314
		$counter = 0;
315
		foreach ($arr as $key => $unused)
316
		{
317
			if (! is_int($key) or $key !== $counter ++)
318
			{
319
				return true;
320
			}
321
		}
322
		return false;
323
	}
324
325
	/**
326
	 * Flattens a multi-dimensional associative array down into a 1 dimensional
327
	 * associative array.
328
	 *
329
	 * @param   array  $array   the array to flatten
330
	 * @param   string $glue    what to glue the keys together with
331
	 * @param   bool   $reset   whether to reset and start over on a new array
332
	 * @param   bool   $indexed whether to flatten only associative array's, or also indexed ones
333
	 *
334
	 * @return  array
335
	 * @since 2.0
336
	 */
337
	public static function flatten($array, $glue = ':', $reset = true, $indexed = true)
338
	{
339
		static $return = array();
340
		static $curr_key = array();
341
342
		if ($reset)
343
		{
344
			$return = array();
345
			$curr_key = array();
346
		}
347
348
		foreach ($array as $key => $val)
349
		{
350
			$curr_key[] = $key;
351
			if (is_array($val) and ($indexed or array_values($val) !== $val))
352
			{
353
				static::flattenAssoc($val, $glue, false);
354
			}
355
			else
356
			{
357
				$return[implode($glue, $curr_key)] = $val;
358
			}
359
			array_pop($curr_key);
360
		}
361
		return $return;
362
	}
363
364
	/**
365
	 * Flattens a multi-dimensional associative array down into a 1 dimensional
366
	 * associative array.
367
	 *
368
	 * @param   array  $array the array to flatten
369
	 * @param   string $glue  what to glue the keys together with
370
	 * @param   bool   $reset whether to reset and start over on a new array
371
	 *
372
	 * @return  array
373
	 * @since 2.0
374
	 */
375
	public static function flattenAssoc($array, $glue = ':', $reset = true)
376
	{
377
		return static::flatten($array, $glue, $reset, false);
378
	}
379
380
	/**
381
	 * Reverse a flattened array in its original form.
382
	 *
383
	 * @param   array  $array flattened array
384
	 * @param   string $glue  glue used in flattening
385
	 *
386
	 * @return  array   the unflattened array
387
	 * @since 2.0
388
	 */
389
	public static function reverseFlatten($array, $glue = ':')
390
	{
391
		$return = array();
392
393
		foreach ($array as $key => $value)
394
		{
395
			if (stripos($key, $glue) !== false)
396
			{
397
				$keys = explode($glue, $key);
398
				$temp =& $return;
399
				while (count($keys) > 1)
400
				{
401
					$key = array_shift($keys);
402
					$key = is_numeric($key) ? (int) $key : $key;
403 View Code Duplication
					if (! isset($temp[$key]) or ! is_array($temp[$key]))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
404
					{
405
						$temp[$key] = array();
406
					}
407
					$temp =& $temp[$key];
408
				}
409
410
				$key = array_shift($keys);
411
				$key = is_numeric($key) ? (int) $key : $key;
412
				$temp[$key] = $value;
413
			}
414
			else
415
			{
416
				$key = is_numeric($key) ? (int) $key : $key;
417
				$return[$key] = $value;
418
			}
419
		}
420
421
		return $return;
422
	}
423
424
	/**
425
	 * Filters an array on prefixed associative keys.
426
	 *
427
	 * @param   array  $array        the array to filter.
428
	 * @param   string $prefix       prefix to filter on.
429
	 * @param   bool   $removePrefix whether to remove the prefix.
430
	 *
431
	 * @return  array
432
	 * @since 2.0
433
	 */
434 View Code Duplication
	public static function filterPrefixed($array, $prefix, $removePrefix = true)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
435
	{
436
		$return = array();
437
		foreach ($array as $key => $val)
438
		{
439
			if (preg_match('/^' . $prefix . '/', $key))
440
			{
441
				if ($removePrefix === true)
442
				{
443
					$key = preg_replace('/^' . $prefix . '/', '', $key);
444
				}
445
				$return[$key] = $val;
446
			}
447
		}
448
		return $return;
449
	}
450
451
	/**
452
	 * Recursive version of PHP's array_filter()
453
	 *
454
	 * @param   array     $array    the array to filter.
455
	 * @param   \Callback $callback the callback that determines whether or not a value is filtered
456
	 *
457
	 * @return  array
458
	 * @since 2.0
459
	 */
460
	public static function filterRecursive($array, $callback = null)
461
	{
462
		foreach ($array as &$value)
463
		{
464
			if (is_array($value))
465
			{
466
				$value = $callback === null ? static::filterRecursive($value) : static::filterRecursive(
467
																					  $value,
468
																						  $callback
469
				);
470
			}
471
		}
472
473
		return $callback === null ? array_filter($array) : array_filter($array, $callback);
474
	}
475
476
	/**
477
	 * Removes items from an array that match a key prefix.
478
	 *
479
	 * @param   array  $array  the array to remove from
480
	 * @param   string $prefix prefix to filter on
481
	 *
482
	 * @return  array
483
	 * @since 2.0
484
	 */
485
	public static function removePrefixed($array, $prefix)
486
	{
487
		foreach ($array as $key => $val)
488
		{
489
			if (preg_match('/^' . $prefix . '/', $key))
490
			{
491
				unset($array[$key]);
492
			}
493
		}
494
		return $array;
495
	}
496
497
	/**
498
	 * Filters an array on suffixed associative keys.
499
	 *
500
	 * @param   array  $array        the array to filter.
501
	 * @param   string $suffix       suffix to filter on.
502
	 * @param   bool   $removeSuffix whether to remove the suffix.
503
	 *
504
	 * @return  array
505
	 * @since 2.0
506
	 */
507 View Code Duplication
	public static function filterSuffixed($array, $suffix, $removeSuffix = true)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
508
	{
509
		$return = array();
510
		foreach ($array as $key => $val)
511
		{
512
			if (preg_match('/' . $suffix . '$/', $key))
513
			{
514
				if ($removeSuffix === true)
515
				{
516
					$key = preg_replace('/' . $suffix . '$/', '', $key);
517
				}
518
				$return[$key] = $val;
519
			}
520
		}
521
		return $return;
522
	}
523
524
	/**
525
	 * Removes items from an array that match a key suffix.
526
	 *
527
	 * @param   array  $array  the array to remove from
528
	 * @param   string $suffix suffix to filter on
529
	 *
530
	 * @return  array
531
	 * @since 2.0
532
	 */
533
	public static function removeSuffixed($array, $suffix)
534
	{
535
		foreach ($array as $key => $val)
536
		{
537
			if (preg_match('/' . $suffix . '$/', $key))
538
			{
539
				unset($array[$key]);
540
			}
541
		}
542
		return $array;
543
	}
544
545
	/**
546
	 * Filters an array by an array of keys
547
	 *
548
	 * @param   array $array  the array to filter.
549
	 * @param   array $keys   the keys to filter
550
	 * @param   bool  $remove if true, removes the matched elements.
551
	 *
552
	 * @return  array
553
	 * @since 2.0
554
	 */
555
	public static function filterKeys($array, $keys, $remove = false)
556
	{
557
		$return = array();
558
		foreach ($keys as $key)
559
		{
560
			if (array_key_exists($key, $array))
561
			{
562
				$remove or $return[$key] = $array[$key];
563
				if ($remove)
564
				{
565
					unset($array[$key]);
566
				}
567
			}
568
		}
569
		return $remove ? $array : $return;
570
	}
571
572
	/**
573
	 * Insert value(s) into an array, mostly an array_splice alias
574
	 * WARNING: original array is edited by reference, only boolean success is returned
575
	 *
576
	 * @param   array       &$original the original array (by reference)
577
	 * @param   array|mixed $value     the value(s) to insert, if you want to insert an array it needs to be in an array itself
578
	 * @param   int         $pos       the numeric position at which to insert, negative to count from the end backwards
579
	 *
580
	 * @return  bool         false when array shorter then $pos, otherwise true
581
	 * @throws  \InvalidArgumentException
582
	 * @since 2.0
583
	 */
584
	public static function insert(array &$original, $value, $pos)
585
	{
586
		if (count($original) < abs($pos))
587
		{
588
			throw new \InvalidArgumentException('Position larger than number of elements in array in which to insert.');
589
		}
590
591
		array_splice($original, $pos, 0, $value);
592
593
		return true;
594
	}
595
596
	/**
597
	 * Insert value(s) into an array, mostly an array_splice alias
598
	 * WARNING: original array is edited by reference, only boolean success is returned
599
	 *
600
	 * @param   array       &$original the original array (by reference)
601
	 * @param   array|mixed $values    the value(s) to insert, if you want to insert an array it needs to be in an array itself
602
	 * @param   int         $pos       the numeric position at which to insert, negative to count from the end backwards
603
	 *
604
	 * @return  bool         false when array shorter then $pos, otherwise true
605
	 * @since 2.0
606
	 */
607
	public static function insertAssoc(array &$original, array $values, $pos)
608
	{
609
		if (count($original) < abs($pos))
610
		{
611
			return false;
612
		}
613
614
		$original = array_slice($original, 0, $pos, true) + $values + array_slice($original, $pos, null, true);
615
616
		return true;
617
	}
618
619
	/**
620
	 * Insert value(s) into an array before a specific key
621
	 * WARNING: original array is edited by reference, only boolean success is returned
622
	 *
623
	 * @param   array       &$original the original array (by reference)
624
	 * @param   array|mixed $value     the value(s) to insert, if you want to insert an array it needs to be in an array itself
625
	 * @param   string|int  $key       the key before which to insert
626
	 * @param   bool        $isAssoc   wether the input is an associative array
627
	 *
628
	 * @return  bool         false when key isn't found in the array, otherwise true
629
	 *
630
	 * @throws \InvalidArgumentException
631
	 * @since 2.0
632
	 */
633 View Code Duplication
	public static function insertBeforeKey(array &$original, $value, $key, $isAssoc = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
634
	{
635
		$pos = array_search($key, array_keys($original));
636
637
		if ($pos === false)
638
		{
639
			throw new \InvalidArgumentException('Unknown key before which to insert the new value into the array.');
640
		}
641
642
		return $isAssoc ? static::insertAssoc($original, $value, $pos) : static::insert($original, $value, $pos);
643
	}
644
645
	/**
646
	 * Insert value(s) into an array after a specific key
647
	 * WARNING: original array is edited by reference, only boolean success is returned
648
	 *
649
	 * @param   array       &$original the original array (by reference)
650
	 * @param   array|mixed $value     the value(s) to insert, if you want to insert an array it needs to be in an array itself
651
	 * @param   string|int  $key       the key after which to insert
652
	 * @param   bool        $isAssoc   wether the input is an associative array
653
	 *
654
	 * @return  bool         false when key isn't found in the array, otherwise true
655
	 *
656
	 * @throws \InvalidArgumentException
657
	 * @since 2.0
658
	 */
659 View Code Duplication
	public static function insertAfterKey(array &$original, $value, $key, $isAssoc = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
660
	{
661
		$pos = array_search($key, array_keys($original));
662
663
		if ($pos === false)
664
		{
665
			throw new \InvalidArgumentException('Unknown key after which to insert the new value into the array.');
666
		}
667
668
		return $isAssoc ? static::insertAssoc($original, $value, $pos + 1) : static::insert(
669
																				   $original,
670
																					   $value,
671
																					   $pos + 1
672
		);
673
	}
674
675
	/**
676
	 * Insert value(s) into an array after a specific value (first found in array)
677
	 *
678
	 * @param   array       &$original the original array (by reference)
679
	 * @param   array|mixed $value     the value(s) to insert, if you want to insert an array it needs to be in an array itself
680
	 * @param   string|int  $search    the value after which to insert
681
	 * @param   bool        $isAssoc   wether the input is an associative array
682
	 *
683
	 * @return  bool         false when value isn't found in the array, otherwise true
684
	 *
685
	 * @throws \InvalidArgumentException
686
	 * @since 2.0
687
	 */
688 View Code Duplication
	public static function insertAfterValue(array &$original, $value, $search, $isAssoc = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
689
	{
690
		$key = array_search($search, $original);
691
692
		if ($key === false)
693
		{
694
			throw new \InvalidArgumentException('Unknown value after which to insert the new value into the array.');
695
		}
696
697
		return static::insertAfterKey($original, $value, $key, $isAssoc);
698
	}
699
700
	/**
701
	 * Insert value(s) into an array before a specific value (first found in array)
702
	 *
703
	 * @param   array       &$original the original array (by reference)
704
	 * @param   array|mixed $value     the value(s) to insert, if you want to insert an array it needs to be in an array itself
705
	 * @param   string|int  $search    the value after which to insert
706
	 * @param   bool        $isAssoc   wether the input is an associative array
707
	 *
708
	 * @return  bool         false when value isn't found in the array, otherwise true
709
	 *
710
	 * @throws \InvalidArgumentException
711
	 * @since 2.0
712
	 */
713 View Code Duplication
	public static function insertBeforeValue(array &$original, $value, $search, $isAssoc = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
714
	{
715
		$key = array_search($search, $original);
716
717
		if ($key === false)
718
		{
719
			throw new \InvalidArgumentException('Unknown value before which to insert the new value into the array.');
720
		}
721
722
		return static::insertBeforeKey($original, $value, $key, $isAssoc);
723
	}
724
725
	/**
726
	 * Sorts a multi-dimensional array by it's values.
727
	 *
728
	 * @param    array  $array     The array to fetch from
729
	 * @param    string $key       The key to sort by
730
	 * @param    string $order     The order (asc or desc)
731
	 * @param    int    $sortFlags The php sort type flag
732
	 *
733
	 * @return    array
734
	 *
735
	 * @throws \InvalidArgumentException
736
	 * @since 2.0
737
	 */
738
	public static function sort($array, $key, $order = 'asc', $sortFlags = SORT_REGULAR)
739
	{
740
		if (! is_array($array))
741
		{
742
			throw new \InvalidArgumentException('Arr::sort() - $array must be an array.');
743
		}
744
745
		if (empty($array))
746
		{
747
			return $array;
748
		}
749
750
		foreach ($array as $k => $v)
751
		{
752
			$b[$k] = static::get($v, $key);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$b was never initialized. Although not strictly required by PHP, it is generally a good practice to add $b = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
753
		}
754
755
		switch ($order)
756
		{
757
			case 'asc':
758
				asort($b, $sortFlags);
759
				break;
760
761
			case 'desc':
762
				arsort($b, $sortFlags);
763
				break;
764
765
			default:
766
				throw new \InvalidArgumentException('Arr::sort() - $order must be asc or desc.');
767
				break;
0 ignored issues
show
Unused Code introduced by
break; 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...
768
		}
769
770
		$c = array();
771
772
		foreach ($b as $key => $val)
773
		{
774
			$c[] = $array[$key];
775
		}
776
777
		return $c;
778
	}
779
780
	/**
781
	 * Sorts an array on multitiple values, with deep sorting support.
782
	 *
783
	 * @param   array $array       collection of arrays/objects to sort
784
	 * @param   array $conditions  sorting conditions
785
	 * @param   bool  $ignore_case wether to sort case insensitive
786
	 *
787
	 * @return array
788
	 * @since 2.0
789
	 */
790
	public static function multisort($array, $conditions, $ignore_case = false)
791
	{
792
		$temp = array();
793
		$keys = array_keys($conditions);
794
795
		foreach ($keys as $key)
796
		{
797
			$temp[$key] = static::pluck($array, $key, true);
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
798
			is_array($conditions[$key]) or $conditions[$key] = array($conditions[$key]);
799
		}
800
801
		$args = array();
802
		foreach ($keys as $key)
803
		{
804
			$args[] = $ignore_case ? array_map('strtolower', $temp[$key]) : $temp[$key];
805
			foreach ($conditions[$key] as $flag)
806
			{
807
				$args[] = $flag;
808
			}
809
		}
810
811
		$args[] = & $array;
812
813
		call_user_func_array('array_multisort', $args);
814
		return $array;
815
	}
816
817
	/**
818
	 * Find the average of an array
819
	 *
820
	 * @param   array    $array the array containing the values
821
	 *
822
	 * @return  int  the average value
823
	 * @since 2.0
824
	 */
825
	public static function average($array)
826
	{
827
		// No arguments passed, lets not divide by 0
828
		if (! ($count = count($array)) > 0)
829
		{
830
			return 0;
831
		}
832
833
		return (array_sum($array) / $count);
834
	}
835
836
	/**
837
	 * Replaces key names in an array by names in $replace
838
	 *
839
	 * @param  array        $source the array containing the key/value combinations
840
	 * @param  array|string $replace to replace or array containing the replacement keys
841
	 * @param  string       $new_key the replacement key
842
	 *
843
	 * @return  array the array with the new keys
844
	 *
845
	 * @throws \InvalidArgumentException
846
	 * @since 2.0
847
	 */
848
	public static function replaceKey($source, $replace, $new_key = null)
849
	{
850
		if (is_string($replace))
851
		{
852
			$replace = array($replace => $new_key);
853
		}
854
855
		if (! is_array($source) or ! is_array($replace))
856
		{
857
			throw new \InvalidArgumentException('Arr::replaceKey() - $source must an array. $replace must be an array or string.');
858
		}
859
860
		$result = array();
861
862
		foreach ($source as $key => $value)
863
		{
864
			if (array_key_exists($key, $replace))
865
			{
866
				$result[$replace[$key]] = $value;
867
			}
868
			else
869
			{
870
				$result[$key] = $value;
871
			}
872
		}
873
874
		return $result;
875
	}
876
877
	/**
878
	 * Merge 2 arrays recursively, differs in 2 important ways from array_merge_recursive()
879
	 * - When there's 2 different values and not both arrays, the latter value overwrites the earlier
880
	 *   instead of merging both into an array
881
	 * - Numeric keys that don't conflict aren't changed, only when a numeric key already exists is the
882
	 *   value added using array_push()
883
	 *
884
	 * Expects multiple variables all of which must be arrays
885
	 *
886
	 * @return  array
887
	 * @throws  \InvalidArgumentException
888
	 * @since 2.0
889
	 */
890
	public static function merge()
891
	{
892
		$array = func_get_arg(0);
893
		$arrays = array_slice(func_get_args(), 1);
894
895
		if (! is_array($array))
896
		{
897
			throw new \InvalidArgumentException('Arr::merge() - all arguments must be arrays.');
898
		}
899
900
		foreach ($arrays as $arr)
901
		{
902
			if (! is_array($arr))
903
			{
904
				throw new \InvalidArgumentException('Arr::merge() - all arguments must be arrays.');
905
			}
906
907
			foreach ($arr as $k => $v)
908
			{
909
				// numeric keys are appended
910
				if (is_int($k))
911
				{
912
					array_key_exists($k, $array) ? $array[] = $v : $array[$k] = $v;
913
				}
914
				elseif (is_array($v) and array_key_exists($k, $array) and is_array($array[$k]))
915
				{
916
					$array[$k] = static::merge($array[$k], $v);
917
				}
918
				else
919
				{
920
					$array[$k] = $v;
921
				}
922
			}
923
		}
924
925
		return $array;
926
	}
927
928
	/**
929
	 * Merge 2 arrays recursively, differs in 2 important ways from array_merge_recursive()
930
	 * - When there's 2 different values and not both arrays, the latter value overwrites the earlier
931
	 *   instead of merging both into an array
932
	 * - Numeric keys are never changed
933
	 *
934
	 * Expects multiple variables all of which must be arrays
935
	 *
936
	 * @return  array
937
	 * @throws  \InvalidArgumentException
938
	 * @since 2.0
939
	 */
940
	public static function mergeAssoc()
941
	{
942
		$array = func_get_arg(0);
943
		$arrays = array_slice(func_get_args(), 1);
944
945
		if (! is_array($array))
946
		{
947
			throw new \InvalidArgumentException('Arr::mergeAssoc() - all arguments must be arrays.');
948
		}
949
950
		foreach ($arrays as $arr)
951
		{
952
			if (! is_array($arr))
953
			{
954
				throw new \InvalidArgumentException('Arr::mergeAssoc() - all arguments must be arrays.');
955
			}
956
957
			foreach ($arr as $k => $v)
958
			{
959
				if (is_array($v) and array_key_exists($k, $array) and is_array($array[$k]))
960
				{
961
					$array[$k] = static::mergeAssoc($array[$k], $v);
962
				}
963
				else
964
				{
965
					$array[$k] = $v;
966
				}
967
			}
968
		}
969
970
		return $array;
971
	}
972
973
	/**
974
	 * Prepends a value with an asociative key to an array.
975
	 * Will overwrite if the value exists.
976
	 *
977
	 * @param   array        &$arr  the array to prepend to
978
	 * @param   string|array $key   the key or array of keys and values
979
	 * @param   mixed        $value the value to prepend
980
	 * @since 2.0
981
	 */
982
	public static function prepend(&$arr, $key, $value = null)
983
	{
984
		$arr = (is_array($key) ? $key : array($key => $value)) + $arr;
985
	}
986
987
	/**
988
	 * Recursive in_array
989
	 *
990
	 * @param   mixed $needle   what to search for
991
	 * @param   array $haystack array to search in
992
	 * @param   bool  $strict
993
	 *
994
	 * @return  bool   wether the needle is found in the haystack.
995
	 * @since 2.0
996
	 */
997
	public static function inArrayRecursive($needle, $haystack, $strict = false)
998
	{
999
		foreach ($haystack as $value)
1000
		{
1001
			if (! $strict and $needle == $value)
1002
			{
1003
				return true;
1004
			}
1005
			elseif ($needle === $value)
1006
			{
1007
				return true;
1008
			}
1009
			elseif (is_array($value) and static::inArrayRecursive($needle, $value, $strict))
1010
			{
1011
				return true;
1012
			}
1013
		}
1014
1015
		return false;
1016
	}
1017
1018
	/**
1019
	 * Checks if the given array is a multidimensional array.
1020
	 *
1021
	 * @param   array $arr      the array to check
1022
	 * @param   bool  $all_keys if true, check that all elements are arrays
1023
	 *
1024
	 * @return  bool true if its a multidimensional array, false if not
1025
	 * @since 2.0
1026
	 */
1027
	public static function isMulti($arr, $all_keys = false)
1028
	{
1029
		$values = array_filter($arr, 'is_array');
1030
		return $all_keys ? count($arr) === count($values) : count($values) > 0;
1031
	}
1032
1033
	/**
1034
	 * Searches the array for a given value and returns the
1035
	 * corresponding key or default value.
1036
	 * If $recursive is set to true, then the Arr::search()
1037
	 * function will return a delimiter-notated key using $delimiter.
1038
	 *
1039
	 * @param   array  $array     The search array
1040
	 * @param   mixed  $value     The searched value
1041
	 * @param   string $default   The default value
1042
	 * @param   bool   $recursive Whether to get keys recursive
1043
	 * @param   string $delimiter The delimiter, when $recursive is true
1044
	 * @param   bool   $strict    If true, do a strict key comparison
1045
	 *
1046
	 * @return  mixed
1047
	 *
1048
	 * @throws \InvalidArgumentException
1049
	 * @since 2.0
1050
	 */
1051
	public static function search($array, $value, $default = null, $recursive = true, $delimiter = '.', $strict = false)
1052
	{
1053
		if (! is_array($array) and ! $array instanceof \ArrayAccess)
1054
		{
1055
			throw new \InvalidArgumentException('First parameter must be an array or ArrayAccess object.');
1056
		}
1057
1058
		if (! is_null($default) and ! is_int($default) and ! is_string($default))
1059
		{
1060
			throw new \InvalidArgumentException('Expects parameter 3 to be an string or integer or null.');
1061
		}
1062
1063
		if (! is_string($delimiter))
1064
		{
1065
			throw new \InvalidArgumentException('Expects parameter 5 must be an string.');
1066
		}
1067
1068
		$key = array_search($value, $array, $strict);
1069
1070
		if ($recursive and $key === false)
1071
		{
1072
			$keys = array();
1073
			foreach ($array as $k => $v)
1074
			{
1075
				if (is_array($v))
1076
				{
1077
					$rk = static::search($v, $value, $default, true, $delimiter, $strict);
1078
					if ($rk !== $default)
1079
					{
1080
						$keys = array($k, $rk);
1081
						break;
1082
					}
1083
				}
1084
			}
1085
			$key = count($keys) ? implode($delimiter, $keys) : false;
1086
		}
1087
1088
		return $key === false ? $default : $key;
1089
	}
1090
1091
	/**
1092
	 * Returns only unique values in an array. It does not sort. First value is used.
1093
	 *
1094
	 * @param   array $arr the array to dedup
1095
	 *
1096
	 * @return  array   array with only de-duped values
1097
	 * @since 2.0
1098
	 */
1099
	public static function unique($arr)
1100
	{
1101
		// filter out all duplicate values
1102
		return array_filter(
1103
			$arr,
1104
			function ($item)
1105
			{
1106
				// contrary to popular belief, this is not as static as you think...
1107
				static $vars = array();
1108
1109
				if (in_array($item, $vars, true))
1110
				{
1111
					// duplicate
1112
					return false;
1113
				}
1114
				else
1115
				{
1116
					// record we've had this value
1117
					$vars[] = $item;
1118
1119
					// unique
1120
					return true;
1121
				}
1122
			}
1123
		);
1124
	}
1125
1126
	/**
1127
	 * Calculate the sum of an array
1128
	 *
1129
	 * @param   array  $array the array containing the values
1130
	 * @param   string $key   key of the value to pluck
1131
	 *
1132
	 * @return  int  the sum value
1133
	 *
1134
	 * @throws \InvalidArgumentException
1135
	 * @since 2.0
1136
	 */
1137
	public static function sum($array, $key)
1138
	{
1139
		if (! is_array($array) and ! $array instanceof \ArrayAccess)
1140
		{
1141
			throw new \InvalidArgumentException('First parameter must be an array or ArrayAccess object.');
1142
		}
1143
1144
		return array_sum(static::pluck($array, $key));
1145
	}
1146
1147
	/**
1148
	 * Returns the array with all numeric keys re-indexed, and string keys untouched
1149
	 *
1150
	 * @param   array $arr the array to reindex
1151
	 *
1152
	 * @return  array   reindexed array
1153
	 * @since 2.0
1154
	 */
1155
	public static function reIndex($arr)
1156
	{
1157
		// reindex this level
1158
		$arr = array_merge($arr);
1159
1160
		foreach ($arr as &$v)
1161
		{
1162
			is_array($v) and $v = static::reIndex($v);
1163
		}
1164
1165
		return $arr;
1166
	}
1167
1168
	/**
1169
	 * Get the previous value or key from an array using the current array key
1170
	 *
1171
	 * @param   array  $array     the array containing the values
1172
	 * @param   string $key       key of the current entry to use as reference
1173
	 * @param   bool   $getValue  if true, return the previous value instead of the previous key
1174
	 * @param   bool   $strict    if true, do a strict key comparison
1175
	 *
1176
	 * @return  mixed  the value in the array, null if there is no previous value, or false if the key doesn't exist
1177
	 *
1178
	 * @throws \InvalidArgumentException
1179
	 * @since 2.0
1180
	 */
1181
	public static function previousByKey($array, $key, $getValue = false, $strict = false)
1182
	{
1183
		if (! is_array($array) and ! $array instanceof \ArrayAccess)
1184
		{
1185
			throw new \InvalidArgumentException('First parameter must be an array or ArrayAccess object.');
1186
		}
1187
1188
		// get the keys of the array
1189
		$keys = array_keys($array);
1190
1191
		// and do a lookup of the key passed
1192 View Code Duplication
		if (($index = array_search($key, $keys, $strict)) === false)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
1193
		{
1194
			// key does not exist
1195
			return false;
1196
		}
1197
1198
		// check if we have a previous key
1199
		elseif (! isset($keys[$index - 1]))
1200
		{
1201
			// there is none
1202
			return null;
1203
		}
1204
1205
		// return the value or the key of the array entry the previous key points to
1206
		return $getValue ? $array[$keys[$index - 1]] : $keys[$index - 1];
1207
	}
1208
1209
	/**
1210
	 * Get the next value or key from an array using the current array key
1211
	 *
1212
	 * @param   array  $array     the array containing the values
1213
	 * @param   string $key       key of the current entry to use as reference
1214
	 * @param   bool   $getValue  if true, return the next value instead of the next key
1215
	 * @param   bool   $strict    if true, do a strict key comparison
1216
	 *
1217
	 * @return  mixed  the value in the array, null if there is no next value, or false if the key doesn't exist
1218
	 *
1219
	 * @throws \InvalidArgumentException
1220
	 * @since 2.0
1221
	 */
1222
	public static function nextByKey($array, $key, $getValue = false, $strict = false)
1223
	{
1224
		if (! is_array($array) and ! $array instanceof \ArrayAccess)
1225
		{
1226
			throw new \InvalidArgumentException('First parameter must be an array or ArrayAccess object.');
1227
		}
1228
1229
		// get the keys of the array
1230
		$keys = array_keys($array);
1231
1232
		// and do a lookup of the key passed
1233 View Code Duplication
		if (($index = array_search($key, $keys, $strict)) === false)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
1234
		{
1235
			// key does not exist
1236
			return false;
1237
		}
1238
1239
		// check if we have a previous key
1240
		elseif (! isset($keys[$index + 1]))
1241
		{
1242
			// there is none
1243
			return null;
1244
		}
1245
1246
		// return the value or the key of the array entry the previous key points to
1247
		return $getValue ? $array[$keys[$index + 1]] : $keys[$index + 1];
1248
	}
1249
1250
	/**
1251
	 * Get the previous value or key from an array using the current array value
1252
	 *
1253
	 * @param   array  $array     the array containing the values
1254
	 * @param   string $value     value of the current entry to use as reference
1255
	 * @param   bool   $getValue  if true, return the previous value instead of the previous key
1256
	 * @param   bool   $strict    if true, do a strict key comparison
1257
	 *
1258
	 * @return  mixed  the value in the array, null if there is no previous value, or false if the key doesn't exist
1259
	 *
1260
	 * @throws \InvalidArgumentException
1261
	 * @since 2.0
1262
	 */
1263
	public static function previousByValue($array, $value, $getValue = true, $strict = false)
1264
	{
1265
		if (! is_array($array) and ! $array instanceof \ArrayAccess)
1266
		{
1267
			throw new \InvalidArgumentException('First parameter must be an array or ArrayAccess object.');
1268
		}
1269
1270
		// find the current value in the array
1271
		if (($key = array_search($value, $array, $strict)) === false)
1272
		{
1273
			// bail out if not found
1274
			return false;
1275
		}
1276
1277
		// get the list of keys, and find our found key
1278
		$keys = array_keys($array);
1279
		$index = array_search($key, $keys);
1280
1281
		// if there is no previous one, bail out
1282
		if (! isset($keys[$index - 1]))
1283
		{
1284
			return null;
1285
		}
1286
1287
		// return the value or the key of the array entry the previous key points to
1288
		return $getValue ? $array[$keys[$index - 1]] : $keys[$index - 1];
1289
	}
1290
1291
	/**
1292
	 * Get the next value or key from an array using the current array value
1293
	 *
1294
	 * @param   array  $array    the array containing the values
1295
	 * @param   string $value    value of the current entry to use as reference
1296
	 * @param   bool   $getValue if true, return the next value instead of the next key
1297
	 * @param   bool   $strict   if true, do a strict key comparison
1298
	 *
1299
	 * @return  mixed  the value in the array, null if there is no next value, or false if the key doesn't exist
1300
	 *
1301
	 * @throws \InvalidArgumentException
1302
	 * @since 2.0
1303
	 */
1304
	public static function nextByValue($array, $value, $getValue = true, $strict = false)
1305
	{
1306
		if (! is_array($array) and ! $array instanceof \ArrayAccess)
1307
		{
1308
			throw new \InvalidArgumentException('First parameter must be an array or ArrayAccess object.');
1309
		}
1310
1311
		// find the current value in the array
1312
		if (($key = array_search($value, $array, $strict)) === false)
1313
		{
1314
			// bail out if not found
1315
			return false;
1316
		}
1317
1318
		// get the list of keys, and find our found key
1319
		$keys = array_keys($array);
1320
		$index = array_search($key, $keys);
1321
1322
		// if there is no next one, bail out
1323
		if (! isset($keys[$index + 1]))
1324
		{
1325
			return null;
1326
		}
1327
1328
		// return the value or the key of the array entry the next key points to
1329
		return $getValue ? $array[$keys[$index + 1]] : $keys[$index + 1];
1330
	}
1331
1332
	/**
1333
	 * Return the subset of the array defined by the supplied keys.
1334
	 *
1335
	 * Returns $default for missing keys, as with Arr::get()
1336
	 *
1337
	 * @param   array $array   the array containing the values
1338
	 * @param   array $keys    list of keys (or indices) to return
1339
	 * @param   mixed $default value of missing keys; default null
1340
	 *
1341
	 * @return  array  An array containing the same set of keys provided.
1342
	 * @since 2.0
1343
	 */
1344
	public static function subset(array $array, array $keys, $default = null)
1345
	{
1346
		$result = array();
1347
1348
		foreach ($keys as $key)
1349
		{
1350
			static::set($result, $key, static::get($array, $key, $default));
1351
		}
1352
1353
		return $result;
1354
	}
1355
}
1356