Completed
Push — master ( 603fa9...c5e232 )
by Daniel
03:00
created

Access::except()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 6
rs 9.4286
cc 1
eloc 3
nc 1
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
     * Add an element to an array if it doesn't exist.
51
     *
52
     * @param array  $array
53
     * @param string $key
54
     * @param string $value
55
     *
56
     * @return array
57
     */
58
    public function add(array $array, $key, $value)
59
    {
60
        if (!isset($array[$key])) {
61
            $array[$key] = $value;
62
        }
63
64
        return $array;
65
    }
66
67
    /**
68
     * Get an item from an array using "dot" notation.
69
     *
70
     * @param array           $array
71
     * @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...
72
     * @param mixed           $default
73
     *
74
     * @return mixed
75
     */
76
    public function get(array $array, $key = null, $default = null)
77
    {
78
        if ($key === null) {
79
            return $array;
80
        }
81
82
        if (isset($array[$key])) {
83
            return $array[$key];
84
        }
85
86 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...
87
            if (!array_key_exists($segment, $array)) {
88
                return $this->value($default);
89
            }
90
91
            $array = $array[$segment];
92
        }
93
94
        return $array;
95
    }
96
97
    /**
98
     * Check if an item exists in an array using "dot" notation.
99
     *
100
     * @param array  $array
101
     * @param string $key
102
     *
103
     * @return bool
104
     */
105
    public function has(array $array, $key)
106
    {
107
        if (empty($array) || is_null($key)) {
108
            return false;
109
        }
110
111
        if (array_key_exists($key, $array)) {
112
            return true;
113
        }
114
115 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...
116
            if (!array_key_exists($segment, $array)) {
117
                return false;
118
            }
119
120
            $array = $array[$segment];
121
        }
122
123
        return true;
124
    }
125
126
    /**
127
     * Updates data at the given path.
128
     *
129
     * @param array        $array
130
     * @param array|string $key
131
     * @param callable     $cb Callback to update the value.
132
     *
133
     * @return mixed Updated data.
134
     */
135
    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...
136
    {
137
        $keys    = $this->splitPath($key);
138
        $current =& $array;
139
140
        foreach ($keys as $key) {
141
            if (!isset($current[$key])) {
142
                return $array;
143
            }
144
145
            $current =& $current[$key];
146
        }
147
148
        $current = call_user_func($cb, $current);
149
150
        return $array;
151
    }
152
153
    /**
154
     * Remove one or many array items from a given array using "dot" notation.
155
     *
156
     * @param array        $array
157
     * @param array|string $keys
158
     */
159
    public function forget(array &$array, $keys)
160
    {
161
        $original = &$array;
162
        $keys     = (array) $keys;
163
164
        if (count($keys) === 0) {
165
            return;
166
        }
167
168
        foreach ($keys as $key) {
169
            $parts = $this->splitPath($key);
170
171
            // clean up before each pass
172
            $array = &$original;
173
174
            while (count($parts) > 1) {
175
                $part = array_shift($parts);
176
177
                if (isset($array[$part]) && is_array($array[$part])) {
178
                    $array = &$array[$part];
179
                } else {
180
                    continue 2;
181
                }
182
            }
183
184
            unset($array[array_shift($parts)]);
185
        }
186
    }
187
188
    /**
189
     * Get all of the given array except for a specified array of items.
190
     *
191
     * @param array    $array
192
     * @param string[] $keys
193
     *
194
     * @return array
195
     */
196
    public function except($array, $keys)
197
    {
198
        $this->forget($array, $keys);
199
200
        return $array;
201
    }
202
}
203