Passed
Pull Request — master (#43)
by Stephen
02:17
created

ArrayUtility::only()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 5
rs 10
1
<?php
2
3
namespace Sfneal\Helpers\Arrays\Utils;
4
5
use Illuminate\Support\Collection;
6
7
class ArrayUtility
8
{
9
    /**
10
     * @var array
11
     */
12
    private $array;
13
14
    /**
15
     * ArrayHelpers constructor.
16
     *
17
     * @param array $array
18
     */
19
    public function __construct(array $array)
20
    {
21
        $this->array = $array;
22
    }
23
24
    /**
25
     * Retrieve the $array property.
26
     *
27
     * @return array
28
     */
29
    public function get(): array
30
    {
31
        return $this->array;
32
    }
33
34
    /**
35
     * Retrieve a collection instance of the $array property.
36
     *
37
     * @return Collection
38
     */
39
    public function collect(): Collection
40
    {
41
        return collect($this->array);
42
    }
43
44
    /**
45
     * Set the $array property.
46
     *
47
     * @param array $array
48
     * @return $this
49
     */
50
    protected function set(array $array): self
51
    {
52
        $this->array = $array;
53
54
        return $this;
55
    }
56
57
    /**
58
     * Returns a chunked array with calculated chunk size.
59
     *
60
     * @param int $min
61
     * @param int|null $max
62
     * @param bool $no_remainders
63
     * @param bool $preserve_keys
64
     * @return self
65
     */
66
    public function chunks(int $min = 0, int $max = null, bool $no_remainders = false, bool $preserve_keys = true): self
67
    {
68
        $chunks = array_chunk(
69
            $this->array,
70
            (new ChunkSizer(count($this->array), $min, $max))->execute(),
71
            $preserve_keys
72
        );
73
74
        // Check if the first chunk is the same length as the last chunk
75
        if ($no_remainders && count($chunks[0]) != count(array_reverse($chunks)[0])) {
76
            $remainder = array_pop($chunks);
77
            $last_chunk = array_pop($chunks);
78
79
            // Add the remainder chunk to the last equal sized chunk
80
            $chunks[] = array_merge($last_chunk, $remainder);
81
        }
82
83
        return $this->set($chunks);
84
    }
85
86
    /**
87
     * Flatten a multidimensional array into a 2D array without nested keys.
88
     *
89
     * @param bool $nest_keys
90
     * @param string $separator
91
     * @return self
92
     */
93
    public function flattenKeys(bool $nest_keys = true, string $separator = '_'): self
94
    {
95
        // todo: possible use while loop for multi level nesting?
96
        $flat = [];
97
        foreach (array_keys($this->array) as $key) {
98
            if (is_array($this->array[$key])) {
99
                // If the key is an array, add each children keys to flattened array
100
                foreach ($this->array[$key] as $k => $v) {
101
                    if ($nest_keys) {
102
                        $flat[$key.$separator.$k] = $v;
103
                    } else {
104
                        $flat[$k] = $v;
105
                    }
106
                }
107
            } else {
108
                $flat[$key] = $this->array[$key];
109
            }
110
        }
111
112
        return $this->set($flat);
113
    }
114
115
    /**
116
     * Remove particular keys from a multidimensional array.
117
     *
118
     * @param array|string $keys
119
     * @return self
120
     */
121
    public function removeKeys($keys): self
122
    {
123
        $all_keys = array_keys($this->array);
124
        foreach ((array) $keys as $key) {
125
            if (in_array($key, $all_keys)) {
126
                unset($this->array[$key]);
127
            }
128
        }
129
130
        return $this->set($this->array);
131
    }
132
133
    /**
134
     * Remove specific arrays of keys without altering the original $array.
135
     *
136
     * @param array $except
137
     * @return self
138
     */
139
    public function except(array $except): self
140
    {
141
        return new self(array_diff_key($this->array, array_flip((array) $except)));
142
    }
143
144
    /**
145
     * Retrieve an array with only the keys provided in the $only param.
146
     *
147
     * @param array $only
148
     * @return self
149
     */
150
    public function only(array $only): self
151
    {
152
        return $this->set(array_filter($this->array, function ($key) use ($only) {
153
            return in_array($key, $only);
154
        }, ARRAY_FILTER_USE_KEY));
155
    }
156
157
    /**
158
     * Remove a key from an array & return the key's value.
159
     *
160
     * @param string $key
161
     * @return mixed
162
     */
163
    public function pop(string $key)
164
    {
165
        // Get the value
166
        $value = $this->array[$key];
167
168
        // Remove the value from the array
169
        unset($this->array[$key]);
170
171
        // Return the value
172
        return $value;
173
    }
174
175
    /**
176
     * Remove a key from an array & the new array without the key.
177
     *
178
     * @param array|string $keys
179
     * @return self
180
     */
181
    public function unset($keys): self
182
    {
183
        // Remove the values from the array
184
        foreach ((array) $keys as $key) {
185
            unset($this->array[$key]);
186
        }
187
188
        // Return the new array
189
        return $this->set($this->array);
190
    }
191
192
    /**
193
     * Return a flat array of values that were found in the $first array that are not found in the $second.
194
     *
195
     * @param array $array
196
     * @return self
197
     */
198
    public function diffFlat(array $array): self
199
    {
200
        $collection = collect($this->array)
201
            ->diff($array)
202
            ->flatten();
203
204
        return $this->set($collection->toArray());
205
    }
206
207
    /**
208
     * Retrieve a random array of elements.
209
     *
210
     * @param int $items
211
     * @return self
212
     */
213
    public function random(int $items): self
214
    {
215
        // Get a random array of keys
216
        $keys = array_rand($this->array, $items);
217
218
        // Return array with only the randomly selected keys
219
        return $this->set(
220
            array_filter(
221
                $this->array,
222
                function ($value, $key) use ($keys) {
223
                    return in_array($key, $keys);
0 ignored issues
show
Bug introduced by
It seems like $keys can also be of type integer and string; however, parameter $haystack of in_array() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

223
                    return in_array($key, /** @scrutinizer ignore-type */ $keys);
Loading history...
224
                },
225
                ARRAY_FILTER_USE_BOTH
226
            )
227
        );
228
    }
229
230
    /**
231
     * Determine if all values in an array of key => value pairs are unique.
232
     *
233
     * @return bool
234
     */
235
    public function valuesUnique(): bool
236
    {
237
        try {
238
            // Count the number of unique array values
239
            // Check to see if there is more than unique array_value
240
            return count(array_unique(array_values($this->array))) >= count(array_values($this->array));
241
        }
242
243
        // Handle nested arrays by comparing number unique keys
244
        catch (\ErrorException $exception) {
245
            $values = [];
246
            $valueCount = 0;
247
            foreach (array_values($this->array) as $value) {
248
                $values = array_merge($values, $value);
249
                $valueCount += count($value);
250
            }
251
252
            return count($values) == $valueCount;
253
        }
254
    }
255
256
    /**
257
     * Determine if all array_values are equal to a certain value.
258
     *
259
     * @param mixed $value
260
     * @return bool
261
     */
262
    public function valuesEqual($value): bool
263
    {
264
        // Check if all array values are equal to a certain value
265
        return count(array_keys($this->array, $value)) == count($this->array);
266
    }
267
268
    /**
269
     * Determine if all array_values are NOT equal to a certain value.
270
     *
271
     * @param mixed $value
272
     * @return bool
273
     */
274
    public function valuesNotEqual($value): bool
275
    {
276
        return ! $this->valuesEqual($value);
277
    }
278
279
    /**
280
     * Determine if an array is multidimensional and has keys.
281
     *
282
     * @return bool
283
     */
284
    public function hasKeys(): bool
285
    {
286
        // Array doesn't have keys if the array is the same as the array values
287
        if ($this->array == array_values($this->array)) {
288
            return false;
289
        }
290
291
        return count($this->array) == count($this->array, COUNT_RECURSIVE);
292
    }
293
294
    /**
295
     * Determine if all values in an array are null.
296
     *
297
     * @return bool
298
     */
299
    public function valuesNull(): bool
300
    {
301
        return $this->valuesEqual(null);
302
    }
303
}
304