Passed
Push — master ( aed439...4d7571 )
by Stephen
01:06 queued 29s
created

ArrayUtility::set()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
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
     * Merge arrays into the existing array.
159
     *
160
     * @param ...$arrays
161
     * @return $this
162
     */
163
    public function merge(...$arrays): self
164
    {
165
        return $this->set(array_merge($this->array, ...$arrays));
166
    }
167
168
    /**
169
     * Remove a key from an array & return the key's value.
170
     *
171
     * @param string $key
172
     * @return mixed
173
     */
174
    public function pop(string $key)
175
    {
176
        // Get the value
177
        $value = $this->array[$key];
178
179
        // Remove the value from the array
180
        unset($this->array[$key]);
181
182
        // Return the value
183
        return $value;
184
    }
185
186
    /**
187
     * Remove a key from an array & the new array without the key.
188
     *
189
     * @param array|string $keys
190
     * @return self
191
     */
192
    public function unset($keys): self
193
    {
194
        // Remove the values from the array
195
        foreach ((array) $keys as $key) {
196
            unset($this->array[$key]);
197
        }
198
199
        // Return the new array
200
        return $this->set($this->array);
201
    }
202
203
    /**
204
     * Return a flat array of values that were found in the $first array that are not found in the $second.
205
     *
206
     * @param array $array
207
     * @return self
208
     */
209
    public function diffFlat(array $array): self
210
    {
211
        $collection = collect($this->array)
212
            ->diff($array)
213
            ->flatten();
214
215
        return $this->set($collection->toArray());
216
    }
217
218
    /**
219
     * Retrieve a random array of elements.
220
     *
221
     * @param int $items
222
     * @return self
223
     */
224
    public function random(int $items): self
225
    {
226
        // Get a random array of keys
227
        $keys = array_rand($this->array, $items);
228
229
        // Return array with only the randomly selected keys
230
        return $this->set(
231
            array_filter(
232
                $this->array,
233
                function ($value, $key) use ($keys) {
234
                    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

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