Completed
Push — master ( be0e93...348a3c )
by Daniel
02:48
created

Enumerator::random()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 8
rs 9.4286
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
namespace Narrowspark\Arr;
3
4
use ArrayAccess;
5
use Narrowspark\Arr\Traits\SplitPathTrait;
6
use Narrowspark\Arr\Traits\ValueTrait;
7
8
class Enumerator
9
{
10
    use SplitPathTrait;
11
    use ValueTrait;
12
13
    /**
14
     * Return the first element in an array passing a given truth test.
15
     *
16
     * @param array    $array
17
     * @param callable $callback
18
     * @param mixed    $default
19
     *
20
     * @return mixed
21
     */
22
    public function first($array, callable $callback, $default = null)
23
    {
24
        foreach ($array as $key => $value) {
25
            if (call_user_func($callback, $key, $value)) {
26
                return $value;
27
            }
28
        }
29
30
        return $this->value($default);
31
    }
32
33
    /**
34
     * Return the last element in an array passing a given truth test.
35
     *
36
     * @param array    $array
37
     * @param callable $callback
38
     * @param mixed    $default
39
     *
40
     * @return mixed
41
     */
42
    public function last($array, callable $callback, $default = null)
43
    {
44
        return $this->first(array_reverse($array), $callback, $default);
45
    }
46
47
    /**
48
    * Get a random element from the array supplied
49
    *
50
    * @param array $array the source array
51
    *
52
    * @return mixed
53
    */
54
    public static function random(Array $array)
55
    {
56
        // Get random index
57
        $index = rand(0, count($array) - 1);
58
59
        // Return element
60
        return $this->value($array[$index]);
0 ignored issues
show
Bug introduced by
The variable $this does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
61
    }
62
63
    /**
64
     * Get a subset of the items from the given array.
65
     *
66
     * @param string[] $array
67
     * @param string[] $keys
68
     *
69
     * @return string[]
70
     */
71
    public function only($array, $keys)
72
    {
73
        return array_intersect_key($array, array_flip((array) $keys));
74
    }
75
76
    /**
77
     * Get a value from the array, and remove it.
78
     *
79
     * @param array       $array
80
     * @param string      $key
81
     * @param string|null $default
82
     *
83
     * @return mixed
84
     */
85
    public function pull(array &$array, $key, $default = null)
86
    {
87
        $value = $this->get($array, $key, $default);
0 ignored issues
show
Bug introduced by
The method get() does not seem to exist on object<Narrowspark\Arr\Enumerator>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
88
89
        $this->forget($array, $key);
0 ignored issues
show
Bug introduced by
The method forget() does not seem to exist on object<Narrowspark\Arr\Enumerator>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
90
91
        return $value;
92
    }
93
94
    /**
95
     * Pluck an array of values from an array.
96
     *
97
     * @param array|\ArrayAccess $array
98
     * @param string             $value
99
     * @param string|null        $key
100
     *
101
     * @return array
102
     */
103
    public function pluck(array $array, $value, $key = null)
104
    {
105
        $results = [];
106
107
        list($value, $key) = $this->explodePluckParameters($value, $key);
108
109
        // If the key is "null", we will just append the value to the array and keep
110
        // looping. Otherwise we will key the array using the value of the key we
111
        // received from the developer. Then we'll return the final array form.
112
        if (is_null($key)) {
113
            foreach ($array as $item) {
114
                $results[] = $this->dataGet($item, $value);
115
            }
116
        } else {
117
            foreach ($array as $item) {
118
                $results[$this->dataGet($item, $key)] = $this->dataGet($item, $value);
119
            }
120
        }
121
122
        return $results;
123
    }
124
125
    /**
126
     * Filter the array using the given Closure.
127
     *
128
     * @param array    $array
129
     * @param callable $callback
130
     *
131
     * @return array
132
     */
133
    public function where(array $array, callable $callback)
134
    {
135
        $filtered = [];
136
137
        foreach ($array as $key => $value) {
138
            if (call_user_func($callback, $key, $value)) {
139
                $filtered[$key] = $value;
140
            }
141
        }
142
143
        return $filtered;
144
    }
145
146
    /**
147
     * Get an item from an array or object using "dot" notation.
148
     *
149
     * @param mixed        $target
150
     * @param string|array $key
151
     * @param string       $default
0 ignored issues
show
Documentation introduced by
Should the type for parameter $default not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
152
     *
153
     * @return mixed
154
     */
155
    public function dataGet($target, $key, $default = null)
156
    {
157
        if (is_null($key)) {
158
            return $target;
159
        }
160
161
        $key = is_array($key) ? $key : $this->splitPath($key);
162
163
        while (($segment = array_shift($key)) !== null) {
164
            if ($segment === '*') {
165
                if (!is_array($target) && !$target instanceof ArrayAccess) {
166
                    return $this->value($default);
167
                }
168
169
                $result = $this->pluck($target, $key);
0 ignored issues
show
Documentation introduced by
$key is of type array, but the function expects a string.

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...
Bug introduced by
It seems like $target defined by parameter $target on line 155 can also be of type object<ArrayAccess>; however, Narrowspark\Arr\Enumerator::pluck() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
170
171
                return in_array('*', $key, true) ? $this->collapse($result) : $result;
172
            }
173
174
            if (is_array($target)) {
175
                if (!array_key_exists($segment, $target)) {
176
                    return $this->value($default);
177
                }
178
179
                $target = $target[$segment];
180
            } elseif ($target instanceof ArrayAccess) {
181
                if (!isset($target[$segment])) {
182
                    return $this->value($default);
183
                }
184
185
                $target = $target[$segment];
186
            } elseif (is_object($target)) {
187
                if (!isset($target->{$segment})) {
188
                    return $this->value($default);
189
                }
190
191
                $target = $target->{$segment};
192
            } else {
193
                return $this->value($default);
194
            }
195
        }
196
197
        return $target;
198
    }
199
200
    /**
201
     * Push an item onto the beginning of an array.
202
     *
203
     * @param array $array
204
     * @param mixed $value
205
     * @param mixed $key
206
     *
207
     * @return array
208
     */
209
    public function prepend(array $array, $value, $key = null)
210
    {
211
        if (is_null($key)) {
212
            array_unshift($array, $value);
213
        } else {
214
            $array = [$key => $value] + $array;
215
        }
216
217
        return $array;
218
    }
219
220
    /**
221
     * Collapse an array of arrays into a single array.
222
     *
223
     * @param array $array
224
     *
225
     * @return array
226
     */
227
    public function collapse(array $array)
228
    {
229
        $results = [];
230
231
        foreach ($array as $values) {
232
            if (!is_array($values)) {
233
                continue;
234
            }
235
236
            $results = array_merge($results, $values);
237
        }
238
239
        return $results;
240
    }
241
242
    /**
243
     * Replace a given pattern with each value in the array in sequentially.
244
     *
245
     * @param string $pattern
246
     * @param array  $replacements
247
     * @param string $subject
248
     *
249
     * @return string
250
     */
251
    public function pregReplaceSub($pattern, &$replacements, $subject)
252
    {
253
        return preg_replace_callback($pattern, function ($match) use (&$replacements) {
1 ignored issue
show
Unused Code introduced by
The parameter $match 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...
254
            return array_shift($replacements);
255
        }, $subject);
256
    }
257
258
    /**
259
     * A shorter way to run a match on the array's keys rather than the values.
260
     *
261
     * @param string $pattern
262
     * @param array  $input
263
     * @param int    $flags
264
     *
265
     * @return array
266
     */
267
    public function pregGrepKeys($pattern, array $input, $flags = 0)
268
    {
269
        return array_intersect_key($input, array_flip(preg_grep($pattern, array_keys($input), $flags)));
270
    }
271
272
    /**
273
     * Index the array by array of keys.
274
     *
275
     * @param array     $data
276
     * @param array     $keys
277
     * @param bool|true $unique
278
     *
279
     * @return array
280
     */
281
    public function getIndexedByKeys(array $data, array $keys, $unique = true)
282
    {
283
        $result = [];
284
285
        foreach ($data as $value) {
286
            $this->indexByKeys($result, $value, $keys, $unique);
287
        }
288
289
        return $result;
290
    }
291
292
    /**
293
     * Converts array of arrays to one-dimensional array, where key is $keyName and value is $valueName.
294
     *
295
     * @param array        $array
296
     * @param string       $keyName
297
     * @param string|array $valueName
298
     *
299
     * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
300
     */
301
    public function getIndexedValues(array $array, $keyName, $valueName)
302
    {
303
        array_flip($this->pluck($array, $keyName, $valueName));
0 ignored issues
show
Bug introduced by
It seems like $valueName defined by parameter $valueName on line 301 can also be of type array; however, Narrowspark\Arr\Enumerator::pluck() does only seem to accept string|null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
304
    }
305
306
    /**
307
     * @param array     $result
308
     * @param array     $toSave
309
     * @param array     $keys
310
     * @param bool|true $unique
311
     */
312
    protected function indexByKeys(array &$result, array $toSave, array $keys, $unique = true)
313
    {
314
        foreach ($keys as $key) {
315
            if (!isset($result[$toSave[$key]])) {
316
                $result[$toSave[$key]] = [];
317
            }
318
319
            $result = &$result[$toSave[$key]];
320
        }
321
322
        if ($unique) {
323
            $result = $toSave;
324
        } else {
325
            $result[] = $toSave;
326
        }
327
    }
328
329
    /**
330
     * Explode the "value" and "key" arguments passed to "pluck".
331
     *
332
     * @param string      $value
333
     * @param string|null $key
334
     *
335
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
336
     */
337
    protected function explodePluckParameters($value, $key)
338
    {
339
        $value = is_array($value) ? $value : $this->splitPath($key);
340
341
        $key = is_null($key) || is_array($key) ? $key : $this->splitPath($key);
342
343
        return [$value, $key];
344
    }
345
}
346