Completed
Push — revert-array-value-isset ( f6dcb2 )
by Carsten
10:01 queued 03:26
created

BaseArrayHelper::getValue()   D

Complexity

Conditions 10
Paths 19

Size

Total Lines 33
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 10

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 33
ccs 21
cts 21
cp 1
rs 4.8196
cc 10
eloc 19
nc 19
nop 3
crap 10

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\helpers;
9
10
use Yii;
11
use yii\base\Arrayable;
12
use yii\base\InvalidParamException;
13
14
/**
15
 * BaseArrayHelper provides concrete implementation for [[ArrayHelper]].
16
 *
17
 * Do not use BaseArrayHelper. Use [[ArrayHelper]] instead.
18
 *
19
 * @author Qiang Xue <[email protected]>
20
 * @since 2.0
21
 */
22
class BaseArrayHelper
23
{
24
    /**
25
     * Converts an object or an array of objects into an array.
26
     * @param object|array|string $object the object to be converted into an array
27
     * @param array $properties a mapping from object class names to the properties that need to put into the resulting arrays.
28
     * The properties specified for each class is an array of the following format:
29
     *
30
     * ```php
31
     * [
32
     *     'app\models\Post' => [
33
     *         'id',
34
     *         'title',
35
     *         // the key name in array result => property name
36
     *         'createTime' => 'created_at',
37
     *         // the key name in array result => anonymous function
38
     *         'length' => function ($post) {
39
     *             return strlen($post->content);
40
     *         },
41
     *     ],
42
     * ]
43
     * ```
44
     *
45
     * The result of `ArrayHelper::toArray($post, $properties)` could be like the following:
46
     *
47
     * ```php
48
     * [
49
     *     'id' => 123,
50
     *     'title' => 'test',
51
     *     'createTime' => '2013-01-01 12:00AM',
52
     *     'length' => 301,
53
     * ]
54
     * ```
55
     *
56
     * @param boolean $recursive whether to recursively converts properties which are objects into arrays.
57
     * @return array the array representation of the object
58
     */
59 1
    public static function toArray($object, $properties = [], $recursive = true)
60
    {
61 1
        if (is_array($object)) {
62 1
            if ($recursive) {
63 1
                foreach ($object as $key => $value) {
64 1
                    if (is_array($value) || is_object($value)) {
65 1
                        $object[$key] = static::toArray($value, $properties, true);
66 1
                    }
67 1
                }
68 1
            }
69
70 1
            return $object;
71 1
        } elseif (is_object($object)) {
72 1
            if (!empty($properties)) {
73 1
                $className = get_class($object);
74 1
                if (!empty($properties[$className])) {
75 1
                    $result = [];
76 1
                    foreach ($properties[$className] as $key => $name) {
77 1
                        if (is_int($key)) {
78 1
                            $result[$name] = $object->$name;
79 1
                        } else {
80 1
                            $result[$key] = static::getValue($object, $name);
81
                        }
82 1
                    }
83
84 1
                    return $recursive ? static::toArray($result, $properties) : $result;
85
                }
86
            }
87 1
            if ($object instanceof Arrayable) {
88
                $result = $object->toArray([], [], $recursive);
89
            } else {
90 1
                $result = [];
91 1
                foreach ($object as $key => $value) {
92 1
                    $result[$key] = $value;
93 1
                }
94
            }
95
96 1
            return $recursive ? static::toArray($result) : $result;
97
        } else {
98
            return [$object];
99
        }
100
    }
101
102
    /**
103
     * Merges two or more arrays into one recursively.
104
     * If each array has an element with the same string key value, the latter
105
     * will overwrite the former (different from array_merge_recursive).
106
     * Recursive merging will be conducted if both arrays have an element of array
107
     * type and are having the same key.
108
     * For integer-keyed elements, the elements from the latter array will
109
     * be appended to the former array.
110
     * @param array $a array to be merged to
111
     * @param array $b array to be merged from. You can specify additional
112
     * arrays via third argument, fourth argument etc.
113
     * @return array the merged array (the original arrays are not changed.)
114
     */
115 1744
    public static function merge($a, $b)
0 ignored issues
show
Unused Code introduced by
The parameter $a is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $b is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
116
    {
117 1744
        $args = func_get_args();
118 1744
        $res = array_shift($args);
119 1744
        while (!empty($args)) {
120 1744
            $next = array_shift($args);
121 1744
            foreach ($next as $k => $v) {
122 518
                if (is_int($k)) {
123 2
                    if (isset($res[$k])) {
124 2
                        $res[] = $v;
125 2
                    } else {
126
                        $res[$k] = $v;
127
                    }
128 518
                } elseif (is_array($v) && isset($res[$k]) && is_array($res[$k])) {
129 30
                    $res[$k] = self::merge($res[$k], $v);
130 30
                } else {
131 518
                    $res[$k] = $v;
132
                }
133 1744
            }
134 1744
        }
135
136 1744
        return $res;
137
    }
138
139
    /**
140
     * Retrieves the value of an array element or object property with the given key or property name.
141
     * If the key does not exist in the array or object, the default value will be returned instead.
142
     *
143
     * The key may be specified in a dot format to retrieve the value of a sub-array or the property
144
     * of an embedded object. In particular, if the key is `x.y.z`, then the returned value would
145
     * be `$array['x']['y']['z']` or `$array->x->y->z` (if `$array` is an object). If `$array['x']`
146
     * or `$array->x` is neither an array nor an object, the default value will be returned.
147
     * Note that if the array already has an element `x.y.z`, then its value will be returned
148
     * instead of going through the sub-arrays. So it is better to be done specifying an array of key names
149
     * like `['x', 'y', 'z']`.
150
     *
151
     * Below are some usage examples,
152
     *
153
     * ```php
154
     * // working with array
155
     * $username = \yii\helpers\ArrayHelper::getValue($_POST, 'username');
156
     * // working with object
157
     * $username = \yii\helpers\ArrayHelper::getValue($user, 'username');
158
     * // working with anonymous function
159
     * $fullName = \yii\helpers\ArrayHelper::getValue($user, function ($user, $defaultValue) {
160
     *     return $user->firstName . ' ' . $user->lastName;
161
     * });
162
     * // using dot format to retrieve the property of embedded object
163
     * $street = \yii\helpers\ArrayHelper::getValue($users, 'address.street');
164
     * // using an array of keys to retrieve the value
165
     * $value = \yii\helpers\ArrayHelper::getValue($versions, ['1.0', 'date']);
166
     * ```
167
     *
168
     * @param array|object $array array or object to extract value from
169
     * @param string|\Closure|array $key key name of the array element, an array of keys or property name of the object,
170
     * or an anonymous function returning the value. The anonymous function signature should be:
171
     * `function($array, $defaultValue)`.
172
     * The possibility to pass an array of keys is available since version 2.0.4.
173
     * @param mixed $default the default value to be returned if the specified array key does not exist. Not used when
174
     * getting value from an object.
175
     * @return mixed the value of the element if found, default value otherwise
176
     * @throws InvalidParamException if $array is neither an array nor an object.
177
     */
178 44
    public static function getValue($array, $key, $default = null)
179
    {
180 44
        if ($key instanceof \Closure) {
181 4
            return $key($array, $default);
182
        }
183
184 43
        if (is_array($key)) {
185 2
            $lastKey = array_pop($key);
186 2
            foreach ($key as $keyPart) {
187 2
                $array = static::getValue($array, $keyPart);
188 2
            }
189 2
            $key = $lastKey;
190 2
        }
191
192 43
        if (is_array($array) && array_key_exists($key, $array)) {
193 30
            return $array[$key];
194
        }
195
196 23
        if (($pos = strrpos($key, '.')) !== false) {
197 9
            $array = static::getValue($array, substr($key, 0, $pos), $default);
198 9
            $key = substr($key, $pos + 1);
199 9
        }
200
201 23
        if (is_object($array)) {
202
            // this is expected to fail if the property does not exist, or __get() is not implemented
203
            // it is not reliably possible to check whether a property is accessable beforehand
204 4
            return $array->$key;
205 19
        } elseif (is_array($array)) {
206 19
            return array_key_exists($key, $array) ? $array[$key] : $default;
207
        } else {
208 2
            return $default;
209
        }
210
    }
211
212
    /**
213
     * Removes an item from an array and returns the value. If the key does not exist in the array, the default value
214
     * will be returned instead.
215
     *
216
     * Usage examples,
217
     *
218
     * ```php
219
     * // $array = ['type' => 'A', 'options' => [1, 2]];
220
     * // working with array
221
     * $type = \yii\helpers\ArrayHelper::remove($array, 'type');
222
     * // $array content
223
     * // $array = ['options' => [1, 2]];
224
     * ```
225
     *
226
     * @param array $array the array to extract value from
227
     * @param string $key key name of the array element
228
     * @param mixed $default the default value to be returned if the specified key does not exist
229
     * @return mixed|null the value of the element if found, default value otherwise
230
     */
231 52
    public static function remove(&$array, $key, $default = null)
232
    {
233 52
        if (is_array($array) && (isset($array[$key]) || array_key_exists($key, $array))) {
234 20
            $value = $array[$key];
235 20
            unset($array[$key]);
236
237 20
            return $value;
238
        }
239
240 50
        return $default;
241
    }
242
243
    /**
244
     * Indexes an array according to a specified key.
245
     * The input array should be multidimensional or an array of objects.
246
     *
247
     * The key can be a key name of the sub-array, a property name of object, or an anonymous
248
     * function which returns the key value given an array element.
249
     *
250
     * If a key value is null, the corresponding array element will be discarded and not put in the result.
251
     *
252
     * For example,
253
     *
254
     * ```php
255
     * $array = [
256
     *     ['id' => '123', 'data' => 'abc'],
257
     *     ['id' => '345', 'data' => 'def'],
258
     * ];
259
     * $result = ArrayHelper::index($array, 'id');
260
     * // the result is:
261
     * // [
262
     * //     '123' => ['id' => '123', 'data' => 'abc'],
263
     * //     '345' => ['id' => '345', 'data' => 'def'],
264
     * // ]
265
     *
266
     * // using anonymous function
267
     * $result = ArrayHelper::index($array, function ($element) {
268
     *     return $element['id'];
269
     * });
270
     * ```
271
     *
272
     * @param array $array the array that needs to be indexed
273
     * @param string|\Closure $key the column name or anonymous function whose result will be used to index the array
274
     * @return array the indexed array
275
     */
276 1
    public static function index($array, $key)
277
    {
278 1
        $result = [];
279 1
        foreach ($array as $element) {
280 1
            $value = static::getValue($element, $key);
281 1
            $result[$value] = $element;
282 1
        }
283
284 1
        return $result;
285
    }
286
287
    /**
288
     * Returns the values of a specified column in an array.
289
     * The input array should be multidimensional or an array of objects.
290
     *
291
     * For example,
292
     *
293
     * ```php
294
     * $array = [
295
     *     ['id' => '123', 'data' => 'abc'],
296
     *     ['id' => '345', 'data' => 'def'],
297
     * ];
298
     * $result = ArrayHelper::getColumn($array, 'id');
299
     * // the result is: ['123', '345']
300
     *
301
     * // using anonymous function
302
     * $result = ArrayHelper::getColumn($array, function ($element) {
303
     *     return $element['id'];
304
     * });
305
     * ```
306
     *
307
     * @param array $array
308
     * @param string|\Closure $name
309
     * @param boolean $keepKeys whether to maintain the array keys. If false, the resulting array
310
     * will be re-indexed with integers.
311
     * @return array the list of column values
312
     */
313 6
    public static function getColumn($array, $name, $keepKeys = true)
314
    {
315 6
        $result = [];
316 6
        if ($keepKeys) {
317 6
            foreach ($array as $k => $element) {
318 6
                $result[$k] = static::getValue($element, $name);
319 6
            }
320 6
        } else {
321 1
            foreach ($array as $element) {
322 1
                $result[] = static::getValue($element, $name);
323 1
            }
324
        }
325
326 6
        return $result;
327
    }
328
329
    /**
330
     * Builds a map (key-value pairs) from a multidimensional array or an array of objects.
331
     * The `$from` and `$to` parameters specify the key names or property names to set up the map.
332
     * Optionally, one can further group the map according to a grouping field `$group`.
333
     *
334
     * For example,
335
     *
336
     * ```php
337
     * $array = [
338
     *     ['id' => '123', 'name' => 'aaa', 'class' => 'x'],
339
     *     ['id' => '124', 'name' => 'bbb', 'class' => 'x'],
340
     *     ['id' => '345', 'name' => 'ccc', 'class' => 'y'],
341
     * ];
342
     *
343
     * $result = ArrayHelper::map($array, 'id', 'name');
344
     * // the result is:
345
     * // [
346
     * //     '123' => 'aaa',
347
     * //     '124' => 'bbb',
348
     * //     '345' => 'ccc',
349
     * // ]
350
     *
351
     * $result = ArrayHelper::map($array, 'id', 'name', 'class');
352
     * // the result is:
353
     * // [
354
     * //     'x' => [
355
     * //         '123' => 'aaa',
356
     * //         '124' => 'bbb',
357
     * //     ],
358
     * //     'y' => [
359
     * //         '345' => 'ccc',
360
     * //     ],
361
     * // ]
362
     * ```
363
     *
364
     * @param array $array
365
     * @param string|\Closure $from
366
     * @param string|\Closure $to
367
     * @param string|\Closure $group
368
     * @return array
369
     */
370 9
    public static function map($array, $from, $to, $group = null)
371
    {
372 9
        $result = [];
373 9
        foreach ($array as $element) {
374 9
            $key = static::getValue($element, $from);
375 9
            $value = static::getValue($element, $to);
376 9
            if ($group !== null) {
377 1
                $result[static::getValue($element, $group)][$key] = $value;
378 1
            } else {
379 9
                $result[$key] = $value;
380
            }
381 9
        }
382
383 9
        return $result;
384
    }
385
386
    /**
387
     * Checks if the given array contains the specified key.
388
     * This method enhances the `array_key_exists()` function by supporting case-insensitive
389
     * key comparison.
390
     * @param string $key the key to check
391
     * @param array $array the array with keys to check
392
     * @param boolean $caseSensitive whether the key comparison should be case-sensitive
393
     * @return boolean whether the array contains the specified key
394
     */
395 1
    public static function keyExists($key, $array, $caseSensitive = true)
396
    {
397 1
        if ($caseSensitive) {
398 1
            return array_key_exists($key, $array);
399
        } else {
400 1
            foreach (array_keys($array) as $k) {
401 1
                if (strcasecmp($key, $k) === 0) {
402 1
                    return true;
403
                }
404 1
            }
405
406 1
            return false;
407
        }
408
    }
409
410
    /**
411
     * Sorts an array of objects or arrays (with the same structure) by one or several keys.
412
     * @param array $array the array to be sorted. The array will be modified after calling this method.
413
     * @param string|\Closure|array $key the key(s) to be sorted by. This refers to a key name of the sub-array
414
     * elements, a property name of the objects, or an anonymous function returning the values for comparison
415
     * purpose. The anonymous function signature should be: `function($item)`.
416
     * To sort by multiple keys, provide an array of keys here.
417
     * @param integer|array $direction the sorting direction. It can be either `SORT_ASC` or `SORT_DESC`.
418
     * When sorting by multiple keys with different sorting directions, use an array of sorting directions.
419
     * @param integer|array $sortFlag the PHP sort flag. Valid values include
420
     * `SORT_REGULAR`, `SORT_NUMERIC`, `SORT_STRING`, `SORT_LOCALE_STRING`, `SORT_NATURAL` and `SORT_FLAG_CASE`.
421
     * Please refer to [PHP manual](http://php.net/manual/en/function.sort.php)
422
     * for more details. When sorting by multiple keys with different sort flags, use an array of sort flags.
423
     * @throws InvalidParamException if the $direction or $sortFlag parameters do not have
424
     * correct number of elements as that of $key.
425
     */
426 5
    public static function multisort(&$array, $key, $direction = SORT_ASC, $sortFlag = SORT_REGULAR)
427
    {
428 5
        $keys = is_array($key) ? $key : [$key];
429 5
        if (empty($keys) || empty($array)) {
430
            return;
431
        }
432 5
        $n = count($keys);
433 5
        if (is_scalar($direction)) {
434 1
            $direction = array_fill(0, $n, $direction);
435 5
        } elseif (count($direction) !== $n) {
436
            throw new InvalidParamException('The length of $direction parameter must be the same as that of $keys.');
437
        }
438 5
        if (is_scalar($sortFlag)) {
439 5
            $sortFlag = array_fill(0, $n, $sortFlag);
440 5
        } elseif (count($sortFlag) !== $n) {
441
            throw new InvalidParamException('The length of $sortFlag parameter must be the same as that of $keys.');
442
        }
443 5
        $args = [];
444 5
        foreach ($keys as $i => $key) {
445 5
            $flag = $sortFlag[$i];
446 5
            $args[] = static::getColumn($array, $key);
447 5
            $args[] = $direction[$i];
448 5
            $args[] = $flag;
449 5
        }
450 5
        $args[] = &$array;
451 5
        call_user_func_array('array_multisort', $args);
452 5
    }
453
454
    /**
455
     * Encodes special characters in an array of strings into HTML entities.
456
     * Only array values will be encoded by default.
457
     * If a value is an array, this method will also encode it recursively.
458
     * Only string values will be encoded.
459
     * @param array $data data to be encoded
460
     * @param boolean $valuesOnly whether to encode array values only. If false,
461
     * both the array keys and array values will be encoded.
462
     * @param string $charset the charset that the data is using. If not set,
463
     * [[\yii\base\Application::charset]] will be used.
464
     * @return array the encoded data
465
     * @see http://www.php.net/manual/en/function.htmlspecialchars.php
466
     */
467 1
    public static function htmlEncode($data, $valuesOnly = true, $charset = null)
468
    {
469 1
        if ($charset === null) {
470 1
            $charset = Yii::$app->charset;
471 1
        }
472 1
        $d = [];
473 1
        foreach ($data as $key => $value) {
474 1
            if (!$valuesOnly && is_string($key)) {
475 1
                $key = htmlspecialchars($key, ENT_QUOTES, $charset);
476 1
            }
477 1
            if (is_string($value)) {
478 1
                $d[$key] = htmlspecialchars($value, ENT_QUOTES, $charset);
479 1
            } elseif (is_array($value)) {
480 1
                $d[$key] = static::htmlEncode($value, $valuesOnly, $charset);
481 1
            } else {
482 1
                $d[$key] = $value;
483
            }
484 1
        }
485
486 1
        return $d;
487
    }
488
489
    /**
490
     * Decodes HTML entities into the corresponding characters in an array of strings.
491
     * Only array values will be decoded by default.
492
     * If a value is an array, this method will also decode it recursively.
493
     * Only string values will be decoded.
494
     * @param array $data data to be decoded
495
     * @param boolean $valuesOnly whether to decode array values only. If false,
496
     * both the array keys and array values will be decoded.
497
     * @return array the decoded data
498
     * @see http://www.php.net/manual/en/function.htmlspecialchars-decode.php
499
     */
500 1
    public static function htmlDecode($data, $valuesOnly = true)
501
    {
502 1
        $d = [];
503 1
        foreach ($data as $key => $value) {
504 1
            if (!$valuesOnly && is_string($key)) {
505 1
                $key = htmlspecialchars_decode($key, ENT_QUOTES);
506 1
            }
507 1
            if (is_string($value)) {
508 1
                $d[$key] = htmlspecialchars_decode($value, ENT_QUOTES);
509 1
            } elseif (is_array($value)) {
510 1
                $d[$key] = static::htmlDecode($value);
511 1
            } else {
512 1
                $d[$key] = $value;
513
            }
514 1
        }
515
516 1
        return $d;
517
    }
518
519
    /**
520
     * Returns a value indicating whether the given array is an associative array.
521
     *
522
     * An array is associative if all its keys are strings. If `$allStrings` is false,
523
     * then an array will be treated as associative if at least one of its keys is a string.
524
     *
525
     * Note that an empty array will NOT be considered associative.
526
     *
527
     * @param array $array the array being checked
528
     * @param boolean $allStrings whether the array keys must be all strings in order for
529
     * the array to be treated as associative.
530
     * @return boolean whether the array is associative
531
     */
532 116
    public static function isAssociative($array, $allStrings = true)
533
    {
534 116
        if (!is_array($array) || empty($array)) {
535 98
            return false;
536
        }
537
538 34
        if ($allStrings) {
539 34
            foreach ($array as $key => $value) {
540 34
                if (!is_string($key)) {
541 1
                    return false;
542
                }
543 34
            }
544 34
            return true;
545
        } else {
546 1
            foreach ($array as $key => $value) {
547 1
                if (is_string($key)) {
548 1
                    return true;
549
                }
550
            }
551
            return false;
552
        }
553
    }
554
555
    /**
556
     * Returns a value indicating whether the given array is an indexed array.
557
     *
558
     * An array is indexed if all its keys are integers. If `$consecutive` is true,
559
     * then the array keys must be a consecutive sequence starting from 0.
560
     *
561
     * Note that an empty array will be considered indexed.
562
     *
563
     * @param array $array the array being checked
564
     * @param boolean $consecutive whether the array keys must be a consecutive sequence
565
     * in order for the array to be treated as indexed.
566
     * @return boolean whether the array is associative
567
     */
568 1
    public static function isIndexed($array, $consecutive = false)
569
    {
570 1
        if (!is_array($array)) {
571 1
            return false;
572
        }
573
574 1
        if (empty($array)) {
575 1
            return true;
576
        }
577
578 1
        if ($consecutive) {
579 1
            return array_keys($array) === range(0, count($array) - 1);
580
        } else {
581 1
            foreach ($array as $key => $value) {
582 1
                if (!is_int($key)) {
583
                    return false;
584
                }
585 1
            }
586 1
            return true;
587
        }
588
    }
589
590
    /**
591
     * Check whether an array or [[\Traversable]] contains an element.
592
     *
593
     * This method does the same as the PHP function [in_array()](http://php.net/manual/en/function.in-array.php)
594
     * but it does not only work for arrays but also objects that implement the [[\Traversable]] interface.
595
     * @param mixed $needle The value to look for.
596
     * @param array|\Traversable $haystack The set of values to search.
597
     * @param boolean $strict Whether to enable strict (`===`) comparison.
598
     * @return boolean `true` if `$needle` was found in `$haystack`, `false` otherwise.
599
     * @throws \InvalidArgumentException if `$haystack` is neither traversable nor an array.
600
     * @see http://php.net/manual/en/function.in-array.php
601
     */
602 10
    public static function isIn($needle, $haystack, $strict = false)
603
    {
604 10
        if ($haystack instanceof \Traversable) {
605 3
            foreach($haystack as $value) {
606 3
                if ($needle == $value && (!$strict || $needle === $haystack)) {
607 3
                    return true;
608
                }
609 2
            }
610 10
        } elseif (is_array($haystack)) {
611 10
            return in_array($needle, $haystack, $strict);
612
        } else {
613
            throw new \InvalidArgumentException('Argument $haystack must be an array or implement Traversable');
614
        }
615
616 2
        return false;
617
    }
618
619
    /**
620
     * Checks whether an array or [[\Traversable]] is a subset of another array or [[\Traversable]].
621
     *
622
     * This method will return `true`, if all elements of `$needles` are contained in
623
     * `$haystack`. If at least one element is missing, `false` will be returned.
624
     * @param array|\Traversable $needles The values that must **all** be in `$haystack`.
625
     * @param array|\Traversable $haystack The set of value to search.
626
     * @param boolean $strict Whether to enable strict (`===`) comparison.
627
     * @throws \InvalidArgumentException if `$haystack` or `$needles` is neither traversable nor an array.
628
     * @return boolean `true` if `$needles` is a subset of `$haystack`, `false` otherwise.
629
     */
630 5
    public static function isSubset($needles, $haystack, $strict = false)
631
    {
632 5
        if (is_array($needles) || $needles instanceof \Traversable) {
633 5
            foreach($needles as $needle) {
634 4
                if (!static::isIn($needle, $haystack, $strict)) {
635 3
                    return false;
636
                }
637 4
            }
638 4
            return true;
639
        } else {
640
            throw new \InvalidArgumentException('Argument $needles must be an array or implement Traversable');
641
        }
642
    }
643
}
644