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

Access::reset()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 18
rs 8.8571
cc 5
eloc 10
nc 5
nop 2
1
<?php
2
namespace Narrowspark\Arr;
3
4
use Narrowspark\Arr\Traits\SplitPathTrait;
5
use Narrowspark\Arr\Traits\ValueTrait;
6
7
class Access
8
{
9
    use SplitPathTrait;
10
    use ValueTrait;
11
12
    /**
13
     * Set an array item to a given value using "dot" notation.
14
     *
15
     * If no key is given to the method, the entire array will be replaced.
16
     *
17
     * @param array  $array
18
     * @param string $key
19
     * @param mixed  $value
20
     *
21
     * @return array
22
     */
23
    public function set(array &$array, $key, $value)
24
    {
25
        if ($key === null) {
26
            return $array = $value;
27
        }
28
29
        $keys = $this->splitPath($key);
30
31
        while (count($keys) > 1) {
32
            $key = array_shift($keys);
33
34
            // If the key doesn't exist at this depth, we will just create an empty array
35
            // to hold the next value, allowing us to create the arrays to hold final
36
            // values at the correct depth. Then we'll keep digging into the array.
37
            if (!isset($array[$key]) || !is_array($array[$key])) {
38
                $array[$key] = [];
39
            }
40
41
            $array = &$array[$key];
42
        }
43
44
        $array[array_shift($keys)] = $value;
45
46
        return $array;
47
    }
48
49
    /**
50
     * Get an item from an array using "dot" notation.
51
     *
52
     * @param array           $array
53
     * @param string|callable $key
0 ignored issues
show
Documentation introduced by
Should the type for parameter $key not be callable|null? Also, consider making the array more specific, something like array<String>, or String[].

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. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

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

Loading history...
54
     * @param mixed           $default
55
     *
56
     * @return mixed
57
     */
58
    public function get(array $array, $key = null, $default = null)
59
    {
60
        if ($key === null) {
61
            return $array;
62
        }
63
64
        if (isset($array[$key])) {
65
            return $array[$key];
66
        }
67
68 View Code Duplication
        foreach ($this->splitPath($key) as $segment) {
0 ignored issues
show
Documentation introduced by
$key is of type callable, but the function expects a array|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...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
69
            if (!array_key_exists($segment, $array)) {
70
                return $this->value($default);
71
            }
72
73
            $array = $array[$segment];
74
        }
75
76
        return $array;
77
    }
78
79
    /**
80
     * Add an element to the array at a specific location
81
     * using the "dot" notation.
82
     *
83
     * @param array $array
84
     * @param $key
85
     * @param $value
86
     *
87
     * @return array
88
     */
89
    public function add(array &$array, $key, $value)
90
    {
91
        $target = $this->get($array, $key, []);
92
93
        if (!is_array($target)) {
94
            $target = [$target];
95
        }
96
97
        $target[] = $value;
98
        $this->set($array, $key, $target);
99
100
        return $array;
101
    }
102
103
    /**
104
     * Check if an item exists in an array using "dot" notation.
105
     *
106
     * @param array  $array
107
     * @param string $key
108
     *
109
     * @return bool
110
     */
111
    public function has(array $array, $key)
112
    {
113
        if (empty($array) || is_null($key)) {
114
            return false;
115
        }
116
117
        if (array_key_exists($key, $array)) {
118
            return true;
119
        }
120
121 View Code Duplication
        foreach ($this->splitPath($key) as $segment) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
122
            if (!array_key_exists($segment, $array)) {
123
                return false;
124
            }
125
126
            $array = $array[$segment];
127
        }
128
129
        return true;
130
    }
131
132
    /**
133
     * Updates data at the given path.
134
     *
135
     * @param array        $array
136
     * @param array|string $key
137
     * @param callable     $cb Callback to update the value.
138
     *
139
     * @return mixed Updated data.
140
     */
141
    public function update(array $array, $key, callable $cb)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $cb. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
142
    {
143
        $keys    = $this->splitPath($key);
144
        $current =& $array;
145
146
        foreach ($keys as $key) {
147
            if (!isset($current[$key])) {
148
                return $array;
149
            }
150
151
            $current =& $current[$key];
152
        }
153
154
        $current = call_user_func($cb, $current);
155
156
        return $array;
157
    }
158
159
    /**
160
     * Remove one or many array items from a given array using "dot" notation.
161
     *
162
     * @param array        $array
163
     * @param array|string $keys
164
     */
165
    public function forget(array &$array, $keys)
166
    {
167
        $original = &$array;
168
        $keys     = (array) $keys;
169
170
        if (count($keys) === 0) {
171
            return;
172
        }
173
174
        foreach ($keys as $key) {
175
            $parts = $this->splitPath($key);
176
177
            // clean up before each pass
178
            $array = &$original;
179
180
            while (count($parts) > 1) {
181
                $part = array_shift($parts);
182
183
                if (isset($array[$part]) && is_array($array[$part])) {
184
                    $array = &$array[$part];
185
                } else {
186
                    continue 2;
187
                }
188
            }
189
190
            unset($array[array_shift($parts)]);
191
        }
192
    }
193
194
    /**
195
     * Reset all numerical indexes of an array (start from zero).
196
     * Non-numerical indexes will stay untouched. Returns a new array.
197
     *
198
     * @param array      $array
199
     * @param bool|false $deep
200
     *
201
     * @return array
202
     */
203
    public function reset(array $array, $deep = false)
204
    {
205
        $target = [];
206
207
        foreach ($array as $key => $value) {
208
            if ($deep && is_array($value)) {
209
                $value = $this->reset($value);
210
            }
211
212
            if (is_numeric($key)) {
213
                $target[] = $value;
214
            } else {
215
                $target[$key] = $value;
216
            }
217
        }
218
219
        return $target;
220
    }
221
222
    /**
223
     * Get all of the given array except for a specified array of items.
224
     *
225
     * @param array    $array
226
     * @param string[] $keys
227
     *
228
     * @return array
229
     */
230
    public function except(array $array, $keys)
231
    {
232
        $this->forget($array, $keys);
233
234
        return $array;
235
    }
236
}
237