DataSet::isPath()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 3
Bugs 2 Features 0
Metric Value
c 3
b 2
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 2
eloc 2
nc 2
nop 1
crap 2
1
<?php
2
3
namespace Zerg;
4
5
/**
6
 * DataSet is wrapper to array of data, that cat search and paste data by it's path.
7
 *
8
 * @since 0.1
9
 * @package Zerg
10
 */
11
class DataSet implements \ArrayAccess, \Iterator
12
{
13
    /**
14
     * @var array Data wrapped by DataSet.
15
     * */
16
    private $data = [];
17
18
    /**
19
     * @var array Pointer of current insert/read position in internal format.
20
     *
21
     * The path is represented as an array of strings representing a route
22
     * through the levels of the DataSet to the required value.
23
     */
24
    private $currentPath = [];
25
26
    /**
27
     * @param array $data Data to be wrapped.
28
     */
29 30
    public function __construct(array $data = [])
30
    {
31 30
        $this->setData($data);
32 30
    }
33
34
    /**
35
     * Get wrapped data.
36
     *
37
     * @return array Currently wrapped data.
38
     */
39 7
    public function getData()
40
    {
41 7
        return $this->data;
42
    }
43
44
    /**
45
     * Assign new data to DataSet.
46
     *
47
     * @param array $data Data to be wrapped by DataSet.
48
     */
49 30
    public function setData(array $data)
50
    {
51 30
        $this->data = $data;
52 30
    }
53
54
    /**
55
     * Move into a level.
56
     *
57
     * @param string|int $level The level to move into.
58
     */
59 11
    public function push($level)
60
    {
61 11
        array_push($this->currentPath, $level);
62 11
    }
63
64
    /**
65
     * Move back out of the current level.
66
     */
67 1
    public function pop()
68
    {
69 1
        array_pop($this->currentPath);
70 1
    }
71
72
    /**
73
     * Set a value in the current level.
74
     *
75
     * @param string|int $name The name of the value to add.
76
     * @param string|int|array|null $value The value to add.
77
     */
78 12
    public function setValue($name, $value)
79
    {
80 12
        $child = & $this->data;
81
82 12 View Code Duplication
        foreach ($this->currentPath as $part) {
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...
83 4
            if (isset($child[$part])) {
84 1
                $child = & $child[$part];
85 1
            } else {
86 4
                $child[$part] = [];
87 4
                $child = & $child[$part];
88
            }
89 12
        }
90
91 12
        $child[$name] = $value;
92 12
    }
93
94
    /**
95
     * Get a value by name from the current level.
96
     *
97
     * @param string|int $name The name of the value to retrieve.
98
     * @return string|int|array|null The found value. Returns null if the value cannot be found.
99
     */
100 2
    public function getValue($name)
101
    {
102 2
        $child = & $this->data;
103
104 2 View Code Duplication
        foreach ($this->currentPath as $part) {
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...
105 2
            if (isset($child[$part])) {
106 1
                $child = & $child[$part];
107 1
            } else {
108 1
                return null;
109
            }
110 2
        }
111
112 2
        return isset($child[$name]) ? $child[$name] : null;
113
    }
114
115
    /**
116
     * Find a value by path within the DataSet instance.
117
     *
118
     * @see $currentPath
119
     * @param string|array $path Path in internal or human format.
120
     * @return string|int|array|null The found value. Returns null if the value cannot be found.
121
     */
122 11
    public function getValueByPath($path)
123
    {
124 11
        if (is_string($path)) {
125 5
            $path = $this->parsePath($path);
126 5
        }
127
128 11
        $child = $this->data;
129
130 11 View Code Duplication
        foreach ($path as $part) {
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...
131 9
            if (isset($child[$part])) {
132 9
                $child = $child[$part];
133 9
            } else {
134 2
                return null;
135
            }
136 11
        }
137
138 10
        return $child;
139
    }
140
141
    /**
142
     * Assign a value by path within the DataSet instance,
143
     * overwrites any existing value.
144
     *
145
     * @see $currentPath
146
     * @param string|array $path A path in internal or human format.
147
     * @param string|int|array|null $value The value to assign.
148
     */
149 2
    public function setValueByPath($path, $value)
150
    {
151 2
        if (is_string($path)) {
152 1
            $path = $this->parsePath($path);
153 1
        }
154
155 2
        $endPart = array_pop($path);
156 2
        $child = & $this->data;
157
158 2 View Code Duplication
        foreach ($path as $part) {
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...
159 2
            if (isset($child[$part])) {
160 1
                $child = & $child[$part];
161 1
            } else {
162 1
                $child[$part] = [];
163 1
                $child = & $child[$part];
164
            }
165 2
        }
166
167 2
        $child[$endPart] = $value;
168 2
    }
169
170
    /**
171
     * Transform human path to internal DataSet format.
172
     *
173
     * @see $currentPath
174
     * @param string $path Path in human format ('/a/b' or 'a/../b' or './b/c').
175
     * @return array Path in internal format.
176
     * @throws Field\ConfigurationException If path could not be parsed.
177
     */
178 16
    public function parsePath($path)
179
    {
180 16
        $parts = explode('/', trim($path, '/'));
181
182 16
        $pathArray = [];
183 16
        if ($parts[0] == '.') {
184 6
            $pathArray = $this->currentPath;
185 6
            array_shift($parts);
186 6
        }
187
188 16
        foreach ($parts as $part) {
189 16
            if ($part == '..') {
190 7
                if (count($pathArray)) {
191 4
                    array_pop($pathArray);
192 4
                } else {
193 5
                    throw new Field\ConfigurationException("Invalid path. To many '..', can't move higher root.");
194
                }
195 4
            } else {
196 12
                $pathArray[] = $part;
197
            }
198 13
        }
199
200 11
        return $pathArray;
201
    }
202
203
    /**
204
     * Determines whether a given string is a DataSet path.
205
     *
206
     * @param mixed $value Tested string.
207
     * @return bool Whether tested string is a DataSet path.
208
     * @since 0.2
209
     */
210 44
    public static function isPath($value)
211
    {
212 44
        return is_string($value) && strpos($value, '/') !== false;
213
    }
214
215
    /**
216
     * Recursively find value by path.
217
     *
218
     * @param string $value Value path.
219
     * @return array|int|null|string
220
     * @since 1.0
221
     */
222 5
    public function resolvePath($value)
223
    {
224
        do {
225 5
            $value = $this->getValueByPath($value);
226 5
        } while (self::isPath($value));
227
228 5
        return $value;
229
    }
230
231
    /**
232
     * Return current internal read|write position.
233
     *
234
     * @return array
235
     */
236 3
    public function getCurrentPath()
237
    {
238 3
        return $this->currentPath;
239
    }
240
241
    /**
242
     * Return value, stored in DataSet by current internal read|write position.
243
     *
244
     * @return array|int|null|string
245
     */
246 3
    public function getValueByCurrentPath()
247
    {
248 3
        return $this->getValueByPath($this->getCurrentPath());
249
    }
250
251
    /**
252
     * @inheritdoc
253
     * */
254 1
    public function current()
255
    {
256 1
        return current($this->data);
257
    }
258
259
    /**
260
     * @inheritdoc
261
     * */
262 3
    public function next()
263
    {
264 3
        next($this->data);
265 3
    }
266
267
    /**
268
     * @inheritdoc
269
     * */
270 3
    public function key()
271
    {
272 3
        return key($this->data);
273
    }
274
275
    /**
276
     * @inheritdoc
277
     * */
278 3
    public function valid()
279
    {
280 3
        return isset($this->data[$this->key()]);
281
    }
282
283
    /**
284
     * @inheritdoc
285
     * */
286 3
    public function rewind()
287
    {
288 3
        reset($this->data);
289 3
    }
290
291
    /**
292
     * @inheritdoc
293
     * */
294 2
    public function offsetExists($offset)
295
    {
296 2
        return isset($this->data[$offset]);
297
    }
298
299
    /**
300
     * @inheritdoc
301
     * */
302 3
    public function offsetGet($offset)
303
    {
304 3
        return $this->data[$offset];
305
    }
306
307
    /**
308
     * @inheritdoc
309
     * */
310 1
    public function offsetSet($offset, $value)
311
    {
312 1
        $this->data[$offset] = $value;
313 1
    }
314
315
    /**
316
     * @inheritdoc
317
     * */
318 1
    public function offsetUnset($offset)
319
    {
320 1
        unset($this->data[$offset]);
321
    }
322
}