Passed
Push — master ( f01127...1785b4 )
by Marcio
02:45
created

IteratorDot::flatten()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 11
dl 0
loc 17
rs 9.6111
c 1
b 0
f 0
cc 5
nc 6
nop 3
1
<?php
2
3
/**
4
 * Dot - PHP dot notation access to arrays
5
 *
6
 * @author  Riku Särkinen <[email protected]>
7
 * @link    https://github.com/adbario/php-dot-notation
8
 * @license https://github.com/adbario/php-dot-notation/blob/2.x/LICENSE.md (MIT License)
9
 */
10
11
namespace Ballybran\Core\Collections\Collection;
12
13
use Countable;
14
use ArrayIterator;
15
16
/**
17
 * Dot
18
 *
19
 * This class provides a dot notation access and helper functions for
20
 * working with arrays of data. Inspired by Laravel Collection.
21
 */
22
class IteratorDot implements Countable
23
{
24
    /**
25
     * The stored items
26
     *
27
     * @var array
28
     */
29
    protected $items = [];
30
    
31
    /**
32
     *  elements
33
     *
34
     * @var array
35
     */
36
    protected $elements;
37
38
    /**
39
     * Create a new Dot instance
40
     *
41
     * @param mixed $items
42
     */
43
    public function __construct($items = [])
44
    {
45
        $this->elements = $this->getArrayItems($items);
46
    }
47
48
    /**
49
     * Set a given key / value pair or pairs
50
     * if the key doesn't exist already
51
     *
52
     * @param array|int|string $keys
53
     * @param mixed $value
54
     */
55
    public function add($keys, $value = null)
56
    {
57
        if (is_array($keys)) {
58
            foreach ($keys as $key => $value) {
59
                $this->add($key, $value);
60
            }
61
        } elseif (is_null($this->get($keys))) {
62
            $this->set($keys, $value);
63
        }
64
    }
65
66
    /**
67
     * Return all the stored items
68
     *
69
     * @return array
70
     */
71
    public function all()
72
    {
73
        return $this->elements;
74
    }
75
76
    /**
77
     * Delete the contents of a given key or keys
78
     *
79
     * @param array|int|string|null $keys
80
     */
81
    public function clear($keys = null)
82
    {
83
        if (is_null($keys)) {
84
            $this->elements = [];
85
            return;
86
        }
87
        $keys = (array)$keys;
88
        foreach ($keys as $key) {
89
            $this->set($key, []);
90
        }
91
    }
92
93
    /**
94
     * Delete the given key or keys
95
     *
96
     * @param array|int|string $keys
97
     */
98
    public function delete($keys)
99
    {
100
        $keys = (array)$keys;
101
        foreach ($keys as $key) {
102
            if ($this->exists($this->elements, $key)) {
103
                unset($this->elements[$key]);
104
                continue;
105
            }
106
            $items = &$this->elements;
107
            $segments = explode('.', $key);
108
            $lastSegment = array_pop($segments);
109
            foreach ($segments as $segment) {
110
                if (!isset($items[$segment]) || !is_array($items[$segment])) {
111
                    continue 2;
112
                }
113
                $items = &$items[$segment];
114
            }
115
            unset($items[$lastSegment]);
116
        }
117
    }
118
119
    /**
120
     * Checks if the given key exists in the provided array.
121
     *
122
     * @param  array $array Array to validate
123
     * @param  int|string $key The key to look for
124
     *
125
     * @return bool
126
     */
127
    private function exists($array, $key)
128
    {
129
        return array_key_exists($key, $array);
130
    }
131
132
    /**
133
     * Flatten an array with the given character as a key delimiter
134
     *
135
     * @param  string $delimiter
136
     * @param  array|null $items
137
     * @param  string $prepend
138
     * @return array
139
     */
140
    public function flatten($delimiter = '.', $items = null, $prepend = '')
141
    {
142
        $flatten = [];
143
        if (is_null($items)) {
144
            $items = $this->elements;
145
        }
146
        foreach ($items as $key => $value) {
147
            if (is_array($value) && !empty($value)) {
148
                $flatten = array_merge(
149
                    $flatten,
150
                    $this->flatten($delimiter, $value, $prepend . $key . $delimiter)
151
                );
152
            } else {
153
                $flatten[$prepend . $key] = $value;
154
            }
155
        }
156
        return $flatten;
157
    }
158
159
    /**
160
     * Return the value of a given key
161
     *
162
     * @param  int|string|null $key
163
     * @param  mixed $default
164
     * @return mixed
165
     */
166
    public function get($key = null, $default = null)
167
    {
168
        if (is_null($key)) {
169
            return $this->elements;
170
        }
171
        if ($this->exists($this->elements, $key)) {
172
            return $this->elements[$key];
173
        }
174
        if (false === strpos($key, '.')) {
175
            return $default;
176
        }
177
        $items = $this->elements;
178
        foreach (explode('.', $key) as $segment) {
179
            if (!is_array($items) || !$this->exists($items, $segment)) {
180
                return $default;
181
            }
182
            $items = &$items[$segment];
183
        }
184
        return $items;
185
    }
186
187
    /**
188
     * Return the given items as an array
189
     *
190
     * @param  mixed $items
191
     * @return array
192
     */
193
    protected function getArrayItems($items)
194
    {
195
        if (is_array($items)) {
196
            return $items;
197
        } elseif ($items instanceof self) {
198
            return $items->all();
199
        }
200
        return (array)$items;
201
    }
202
203
    /**
204
     * Check if a given key or keys exists
205
     *
206
     * @param  array|int|string $keys
207
     * @return bool
208
     */
209
    public function has($keys)
210
    {
211
        $keys = (array)$keys;
212
        if ( empty($this->elements) || $keys === []) {
213
            return false;
214
        }
215
        foreach ($keys as $key) {
216
            $items = $this->elements;
217
            if ($this->exists($items, $key)) {
218
                continue;
219
            }
220
            foreach (explode('.', $key) as $segment) {
221
                if (!is_array($items) || !$this->exists($items, $segment)) {
222
                    return false;
223
                }
224
                $items = $items[$segment];
225
            }
226
        }
227
        return true;
228
    }
229
230
    /**
231
     * Check if a given key or keys are empty
232
     *
233
     * @param  array|int|string|null $keys
234
     * @return bool
235
     */
236
    public function isEmpty($keys = null)
237
    {
238
        if (is_null($keys)) {
239
            return empty($this->elements);
240
        }
241
        $keys = (array)$keys;
242
        foreach ($keys as $key) {
243
            if (!empty($this->get($key))) {
244
                return false;
245
            }
246
        }
247
        return true;
248
    }
249
250
    /**
251
     * Merge a given array or a Dot object with the given key
252
     * or with the whole Dot object
253
     *
254
     * @param array|string|self $key
255
     * @param array $value
256
     */
257
    public function merge($key, $value = null)
258
    {
259
        if (is_array($key)) {
260
            $this->elements = array_merge($this->elements, $key);
261
        } elseif (is_string($key)) {
262
            $items = (array)$this->get($key);
263
            $value = array_merge($items, $this->getArrayItems($value));
264
            $this->set($key, $value);
265
        } 
266
         $this->elements = array_merge($this->elements, $key->all());
267
        
268
    }
269
270
    /**
271
     * Return the value of a given key and
272
     * delete the key
273
     *
274
     * @param  int|string|null $key
275
     * @param  mixed $default
276
     * @return mixed
277
     */
278
    public function pull($key = null, $default = null)
279
    {
280
        if (is_null($key)) {
281
            $value = $this->all();
282
            $this->clear();
283
            return $value;
284
        }
285
        $value = $this->get($key, $default);
286
        $this->delete($key);
287
        return $value;
288
    }
289
290
    /**
291
     * Push a given value to the end of the array
292
     * in a given key
293
     *
294
     * @param mixed $key
295
     * @param mixed $value
296
     */
297
    public function push($key, $value = null)
298
    {
299
        if (is_null($value)) {
300
            $this->elements[] = $key;
301
            return;
302
        }
303
        $items = $this->get($key);
304
        if (is_array($items) || is_null($items)) {
305
            $items[] = $value;
306
            $this->set($key, $items);
307
        }
308
    }
309
310
    /**
311
     * Set a given key / value pair or pairs
312
     *
313
     * @param array|int|string $keys
314
     * @param mixed $value
315
     */
316
    public function set($keys, $value = null)
317
    {
318
        if (is_array($keys)) {
319
            foreach ($keys as $key => $value) {
320
                $this->set($key, $value);
321
            }
322
            return;
323
        }
324
        $items = &$this->elements;
325
        foreach (explode('.', $keys) as $key) {
326
            if (!isset($items[$key]) || !is_array($items[$key])) {
327
                $items[$key] = [];
328
            }
329
            $items = &$items[$key];
330
        }
331
        $items = $value;
332
    }
333
334
    /**
335
     * Replace all items with a given array
336
     *
337
     * @param mixed $items
338
     */
339
    public function setArray($items)
340
    {
341
        $this->elements = $this->getArrayItems($items);
342
    }
343
344
    /**
345
     * Replace all items with a given array as a reference
346
     *
347
     * @param array $items
348
     */
349
    public function setReference(array &$items)
350
    {
351
        $this->elements = &$items;
352
    }
353
354
    /**
355
     * Return the value of a given key or all the values as JSON
356
     *
357
     * @param  mixed $key
358
     * @param  int $options
359
     * @return string
360
     */
361
    public function toJson($key = null, $options = 0)
362
    {
363
        if (is_string($key)) {
364
            return json_encode($this->get($key), $options);
365
        }
366
        $options = $key === null ? 0 : $key;
367
        return json_encode($this->elements, $options);
368
    }
369
370
    /*
371
     * --------------------------------------------------------------
372
     * Countable interface
373
     * --------------------------------------------------------------
374
     */
375
    /**
376
     * Return the number of items in a given key
377
     *
378
     * @param  int|string|null $key
379
     * @return int
380
     */
381
    public function count($key = null)
382
    {
383
        return count($this->get($key));
384
    }
385
    
386
}