Completed
Push — master ( 578197...422f48 )
by Daniel
02:50
created

Access::pull()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4286
cc 1
eloc 4
nc 1
nop 3
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 $current = $value;
27
        }
28
29
        $keys    = $this->splitPath($key);
30
        $current =& $array;
31
32
        while (count($keys) > 1) {
33
            $key = array_shift($keys);
34
35
            // If the key doesn't exist at this depth, we will just create an empty array
36
            // to hold the next value, allowing us to create the arrays to hold final
37
            // values at the correct depth. Then we'll keep digging into the array.
38
            if (!isset($current[$key]) || !is_array($current[$key])) {
39
                $current[$key] = [];
40
            }
41
42
            $current =& $current[$key];
43
        }
44
45
        $current[array_shift($keys)] = $value;
46
47
        return $array;
48
    }
49
50
    /**
51
     * Get an item from an array using "dot" notation.
52
     *
53
     * @param array           $array
54
     * @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...
55
     * @param mixed           $default
56
     *
57
     * @return mixed
58
     */
59
    public function get(array $array, $key = null, $default = null)
60
    {
61
        if ($key === null) {
62
            return $array;
63
        }
64
65
        if (isset($array[$key])) {
66
            return $array[$key];
67
        }
68
69 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...
70
            if (!array_key_exists($segment, $array)) {
71
                return $this->value($default);
72
            }
73
74
            $array = $array[$segment];
75
        }
76
77
        return $array;
78
    }
79
80
    /**
81
     * Add an element to the array at a specific location
82
     * using the "dot" notation.
83
     *
84
     * @param array $array
85
     * @param $key
86
     * @param $value
87
     *
88
     * @return array
89
     */
90
    public function add(array $array, $key, $value)
91
    {
92
        $target = $this->get($array, $key, []);
93
94
        if (!is_array($target)) {
95
            $target = [$target];
96
        }
97
98
        $target[] = $value;
99
        $this->set($array, $key, $target);
100
101
        return $array;
102
    }
103
104
    /**
105
     * Check if an item exists in an array using "dot" notation.
106
     *
107
     * @param array  $array
108
     * @param string $key
109
     *
110
     * @return bool
111
     */
112
    public function has(array $array, $key)
113
    {
114
        if (empty($array) || is_null($key)) {
115
            return false;
116
        }
117
118
        if (array_key_exists($key, $array)) {
119
            return true;
120
        }
121
122 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...
123
            if (!array_key_exists($segment, $array)) {
124
                return false;
125
            }
126
127
            $array = $array[$segment];
128
        }
129
130
        return true;
131
    }
132
133
    /**
134
     * Updates data at the given path.
135
     *
136
     * @param array        $array
137
     * @param array|string $key
138
     * @param callable     $cb Callback to update the value.
139
     *
140
     * @return mixed Updated data.
141
     */
142
    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...
143
    {
144
        $keys    = $this->splitPath($key);
145
        $current =& $array;
146
147
        foreach ($keys as $key) {
148
            if (!isset($current[$key])) {
149
                return $array;
150
            }
151
152
            $current =& $current[$key];
153
        }
154
155
        $current = call_user_func($cb, $current);
156
157
        return $array;
158
    }
159
160
    /**
161
     * Remove one or many array items from a given array using "dot" notation.
162
     *
163
     * @param array        $array
164
     * @param array|string $keys
165
     */
166
    public function forget(array $array, $keys)
167
    {
168
        $original =& $array;
169
        $keys     = (array) $keys;
170
171
        if (count($keys) === 0) {
172
            return;
173
        }
174
175
        foreach ($keys as $key) {
176
            $parts = $this->splitPath($key);
177
178
            // clean up before each pass
179
            $array =& $original;
180
181
            while (count($parts) > 1) {
182
                $part = array_shift($parts);
183
184
                if (isset($array[$part]) && is_array($array[$part])) {
185
                    $array =& $array[$part];
186
                } else {
187
                    continue 2;
188
                }
189
            }
190
191
            unset($array[array_shift($parts)]);
192
        }
193
    }
194
195
    /**
196
     * Reset all numerical indexes of an array (start from zero).
197
     * Non-numerical indexes will stay untouched. Returns a new array.
198
     *
199
     * @param array      $array
200
     * @param bool|false $deep
201
     *
202
     * @return array
203
     */
204
    public function reset(array $array, $deep = false)
205
    {
206
        $target = [];
207
208
        foreach ($array as $key => $value) {
209
            if ($deep && is_array($value)) {
210
                $value = $this->reset($value);
211
            }
212
213
            if (is_numeric($key)) {
214
                $target[] = $value;
215
            } else {
216
                $target[$key] = $value;
217
            }
218
        }
219
220
        return $target;
221
    }
222
223
    /**
224
     * Get all of the given array except for a specified array of items.
225
     *
226
     * @param array    $array
227
     * @param string[] $keys
228
     *
229
     * @return array
230
     */
231
    public function except(array $array, $keys)
232
    {
233
        $this->forget($array, $keys);
234
235
        return $array;
236
    }
237
}
238