Passed
Push — main ( 40cf44...6c3117 )
by Andrey
01:28
created

Arr::longestStringLength()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 2
rs 10
1
<?php
2
3
namespace Helldar\Support\Helpers;
4
5
use ArrayAccess;
6
use Helldar\Support\Facades\Helpers\Filesystem\File;
7
use Helldar\Support\Facades\Tools\Stub;
8
use Helldar\Support\Tools\Stub as StubTool;
9
10
class Arr
11
{
12
    /**
13
     * Renaming array keys.
14
     * As the second parameter, a callback function is passed, which determines the actions for processing the value.
15
     * The output of the function must be a string with a name.
16
     *
17
     * @param  array  $array
18
     * @param  callable  $callback
19
     *
20
     * @return array
21
     */
22 4
    public function renameKeys(array $array, callable $callback): array
23
    {
24 4
        $result = [];
25
26 4
        foreach ($array as $key => $value) {
27 4
            $new = $callback($key, $value);
28
29 4
            $result[$new] = $value;
30
        }
31
32 4
        return $result;
33
    }
34
35
    /**
36
     * Renaming array keys with map.
37
     *
38
     * @param  array  $array
39
     * @param  array  $map
40
     *
41
     * @return array
42
     */
43 2
    public function renameKeysMap(array $array, array $map): array
44
    {
45 2
        return $this->renameKeys($array, static function ($key) use ($map) {
46 2
            return $map[$key] ?? $key;
47 2
        });
48
    }
49
50
    /**
51
     * Get the size of the longest text element of the array.
52
     *
53
     * @param  array  $array
54
     *
55
     * @return int
56
     */
57 2
    public function longestStringLength(array $array): int
58
    {
59 2
        return ! empty($array)
60 2
            ? max(array_map('mb_strlen', $array))
61 2
            : 0;
62
    }
63
64
    /**
65
     * Push one a unique element onto the end of array.
66
     *
67
     * @param  array  $array
68
     * @param  array|mixed  $values
69
     *
70
     * @return array
71
     */
72 2
    public function addUnique(array $array, $values): array
73
    {
74 2
        if ($this->isArrayable($values)) {
0 ignored issues
show
Bug introduced by
It seems like $values can also be of type array; however, parameter $value of Helldar\Support\Helpers\Arr::isArrayable() does only seem to accept null, 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

74
        if ($this->isArrayable(/** @scrutinizer ignore-type */ $values)) {
Loading history...
75 2
            foreach ($values as $value) {
76 2
                $array = $this->addUnique($array, $value);
77
            }
78
        } else {
79 2
            array_push($array, $values);
80
        }
81
82 2
        return array_values(array_unique($array));
83
    }
84
85
    /**
86
     * Sort an associative array in the order specified by an array of keys.
87
     *
88
     * Example:
89
     *
90
     *  $arr = ['q' => 1, 'r' => 2, 's' => 5, 'w' => 123];
91
     *
92
     *  Arr::sortByKeys($arr, ['q', 'w', 'e']);
93
     *
94
     * print_r($arr);
95
     *
96
     *   Array
97
     *   (
98
     *     [q] => 1
99
     *     [w] => 123
100
     *     [r] => 2
101
     *     [s] => 5
102
     *   )
103
     *
104
     * @see https://gist.github.com/Ellrion/a3145621f936aa9416f4c04987533d8d#file-helper-php
105
     *
106
     * @param  array  $array
107
     * @param  array  $sorter
108
     *
109
     * @return array
110
     */
111 2
    public function sortByKeys(array $array, array $sorter): array
112
    {
113 2
        $sorter = array_intersect($sorter, array_keys($array));
114 2
        $array  = array_merge(array_flip($sorter), $array);
115
116 2
        return $array;
117
    }
118
119
    /**
120
     * Merge one or more arrays recursively.
121
     * Don't forget that numeric keys NOT will be renumbered!
122
     *
123
     * @param  array[]  ...$arrays
124
     *
125
     * @return array
126
     */
127 2
    public function merge(...$arrays): array
128
    {
129 2
        $result = [];
130
131 2
        foreach ($arrays as $array) {
132 2
            foreach ($array as $key => $value) {
133 2
                if (is_array($value)) {
134 2
                    $value = $this->merge($result[$key] ?? [], $value);
135
                }
136
137 2
                $result[$key] = $value;
138
            }
139
        }
140
141 2
        ksort($result);
142
143 2
        return $result;
144
    }
145
146
    /**
147
     * If the given value is not an array and not null, wrap it in one.
148
     *
149
     * @param  null  $value
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $value is correct as it would always require null to be passed?
Loading history...
150
     *
151
     * @return array
152
     */
153 42
    public function wrap($value = null): array
154
    {
155 42
        if (is_array($value)) {
0 ignored issues
show
introduced by
The condition is_array($value) is always false.
Loading history...
156 16
            return $value;
157
        }
158
159 36
        return ! empty($value) ? [$value] : [];
160
    }
161
162
    /**
163
     * Get the instance as an array.
164
     *
165
     * @param  mixed  $value
166
     *
167
     * @return array
168
     */
169 2
    public function toArray($value = null): array
170
    {
171 2
        if (is_object($value)) {
172 2
            $value = method_exists($value, 'toArray') ? $value->toArray() : get_object_vars($value);
173
        }
174
175 2
        $array = $this->wrap($value);
176
177 2
        foreach ($array as &$item) {
178 2
            $item = $this->isArrayable($item) ? $this->toArray($item) : $item;
179
        }
180
181 2
        return $array;
182
    }
183
184
    /**
185
     * Determine if the given key exists in the provided array.
186
     *
187
     * @param  array|\ArrayAccess  $array
188
     * @param  mixed  $key
189
     *
190
     * @return bool
191
     */
192 30
    public function exists($array, $key): bool
193
    {
194 30
        if ($array instanceof ArrayAccess) {
195 2
            return $array->offsetExists($key);
196
        }
197
198 30
        return isset($array[$key]);
199
    }
200
201
    /**
202
     * Get an item from an array.
203
     *
204
     * @param  array|ArrayAccess  $array
205
     * @param  mixed  $key
206
     * @param  mixed|null  $default
207
     *
208
     * @return mixed|null
209
     */
210 30
    public function get($array, $key, $default = null)
211
    {
212 30
        return $array[$key] ?? $default;
213
    }
214
215
    /**
216
     * If the element key exists, then return the name of the key, otherwise the default value.
217
     *
218
     * @param  array|ArrayAccess  $array
219
     * @param  mixed  $key
220
     * @param  null  $default
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $default is correct as it would always require null to be passed?
Loading history...
221
     *
222
     * @return mixed|null
223
     */
224 28
    public function getKey($array, $key, $default = null)
225
    {
226 28
        return $this->exists($array, $key) ? $key : $default;
227
    }
228
229
    /**
230
     * Get all of the given array except for a specified array of keys.
231
     *
232
     * @param  array|ArrayAccess  $array
233
     * @param $keys
234
     *
235
     * @return array
236
     */
237 2
    public function except($array, $keys): array
238
    {
239 2
        $keys = (array) $keys;
240
241 2
        return array_filter($array, static function ($key) use ($keys) {
0 ignored issues
show
Bug introduced by
It seems like $array can also be of type ArrayAccess; however, parameter $array of array_filter() 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

241
        return array_filter(/** @scrutinizer ignore-type */ $array, static function ($key) use ($keys) {
Loading history...
242 2
            return empty($keys) || ! in_array($key, $keys);
243 2
        }, ARRAY_FILTER_USE_KEY);
244
    }
245
246
    /**
247
     * Get a subset of the items from the given array.
248
     *
249
     * @param  array|ArrayAccess  $array
250
     * @param  array|string  $keys
251
     *
252
     * @return array
253
     */
254 2
    public function only($array, $keys): array
255
    {
256 2
        return array_intersect_key($array, array_flip((array) $keys));
0 ignored issues
show
Bug introduced by
It seems like $array can also be of type ArrayAccess; however, parameter $array1 of array_intersect_key() 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

256
        return array_intersect_key(/** @scrutinizer ignore-type */ $array, array_flip((array) $keys));
Loading history...
257
    }
258
259
    /**
260
     * Applies the callback to the elements of the given arrays.
261
     *
262
     * @param  array|ArrayAccess  $array
263
     * @param  callable  $callback
264
     *
265
     * @return array
266
     */
267 2
    public function map($array, callable $callback): array
268
    {
269 2
        foreach ($array as $key => &$value) {
270 2
            $value = $callback($value, $key);
271
        }
272
273 2
        return $array;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $array could return the type ArrayAccess which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
274
    }
275
276
    /**
277
     * Check if the item is an array.
278
     *
279
     * @param  null  $value
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $value is correct as it would always require null to be passed?
Loading history...
280
     *
281
     * @return bool
282
     */
283 6
    public function isArrayable($value = null): bool
284
    {
285 6
        return is_array($value) || is_object($value) || $value instanceof ArrayAccess;
286
    }
287
288
    /**
289
     * Determines if the array or arrayable object is empty.
290
     *
291
     * @param  mixed  $value
292
     *
293
     * @return bool
294
     */
295 8
    public function isEmpty($value): bool
296
    {
297 8
        $value = is_object($value) && method_exists($value, 'toArray') ? $value->toArray() : $value;
298 8
        $value = is_object($value) ? (array) $value : $value;
299
300 8
        return is_array($value) && empty($value);
301
    }
302
303
    /**
304
     * Determines if the value is doesn't empty.
305
     *
306
     * @param  mixed  $value
307
     *
308
     * @return bool
309
     */
310 2
    public function isDoesntEmpty($value): bool
311
    {
312 2
        return ! $this->isEmpty($value);
313
    }
314
315
    /**
316
     * Save array to php or json file.
317
     *
318
     * @param  array|ArrayAccess  $array
319
     * @param  string  $path
320
     * @param  bool  $is_json
321
     * @param  bool  $sort_keys
322
     * @param  int  $json_flags
323
     */
324 6
    public function store($array, string $path, bool $is_json = false, bool $sort_keys = false, int $json_flags = 0): void
325
    {
326 6
        $is_json
327 4
            ? $this->storeAsJson($path, $array, $sort_keys, $json_flags)
328 2
            : $this->storeAsArray($path, $array, $sort_keys);
329 6
    }
330
331
    /**
332
     * Save array to json file.
333
     *
334
     * @param  string  $path
335
     * @param  array|ArrayAccess  $array
336
     * @param  bool  $sort_keys
337
     * @param  int  $flags
338
     */
339 8
    public function storeAsJson(string $path, $array, bool $sort_keys = false, int $flags = 0): void
340
    {
341 8
        $this->prepareToStore($path, StubTool::JSON, $array, static function (array $array) use ($flags) {
0 ignored issues
show
Bug introduced by
It seems like $array can also be of type ArrayAccess; however, parameter $array of Helldar\Support\Helpers\Arr::prepareToStore() 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

341
        $this->prepareToStore($path, StubTool::JSON, /** @scrutinizer ignore-type */ $array, static function (array $array) use ($flags) {
Loading history...
342 8
            return json_encode($array, $flags);
343 8
        }, $sort_keys);
344 8
    }
345
346
    /**
347
     * Save array to php file.
348
     *
349
     * @param  string  $path
350
     * @param  array|ArrayAccess  $array
351
     * @param  bool  $sort_keys
352
     */
353 4
    public function storeAsArray(string $path, $array, bool $sort_keys = false): void
354
    {
355 4
        $this->prepareToStore($path, StubTool::PHP_ARRAY, $array, static function (array $array) {
0 ignored issues
show
Bug introduced by
It seems like $array can also be of type ArrayAccess; however, parameter $array of Helldar\Support\Helpers\Arr::prepareToStore() 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

355
        $this->prepareToStore($path, StubTool::PHP_ARRAY, /** @scrutinizer ignore-type */ $array, static function (array $array) {
Loading history...
356 4
            return var_export($array, true);
357 4
        }, $sort_keys);
358 4
    }
359
360
    /**
361
     * Prepare an array for writing to a file.
362
     *
363
     * @param  string  $path
364
     * @param  string  $stub
365
     * @param  array  $array
366
     * @param  callable  $replace
367
     * @param  bool  $sort_keys
368
     */
369 12
    protected function prepareToStore(string $path, string $stub, array $array, callable $replace, bool $sort_keys = false): void
370
    {
371 12
        if ($sort_keys) {
372 6
            ksort($array);
373
        }
374
375 12
        $content = Stub::replace($stub, [
376 12
            '{{slot}}' => $replace($array),
377
        ]);
378
379 12
        File::store($path, $content);
380 12
    }
381
}
382