Completed
Push — master ( a9fbef...d9c97e )
by Xeriab
03:09
created

AbstractKonfig   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 326
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 1 Features 0
Metric Value
wmc 36
c 2
b 1
f 0
lcom 1
cbo 1
dl 0
loc 326
ccs 55
cts 55
cp 1
rs 8.8

17 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A getDefaults() 0 4 1
A all() 0 4 1
A __toString() 0 4 1
B has() 0 25 5
A get() 0 9 2
D set() 0 38 9
A delete() 0 9 2
A offsetGet() 0 4 1
A offsetExists() 0 4 1
A offsetSet() 0 4 1
A offsetUnset() 0 4 1
A valid() 0 4 2
A key() 0 4 2
A current() 0 4 2
A next() 0 4 2
A rewind() 0 4 2
1
<?php
2
3
/**
4
 * Konfig.
5
 *
6
 * Yet another simple configuration loader library.
7
 *
8
 * PHP version 5
9
 *
10
 * @category Library
11
 * @package  Konfig
12
 * @author   Xeriab Nabil (aka KodeBurner) <[email protected]>
13
 * @license  https://raw.github.com/xeriab/konfig/master/LICENSE MIT
14
 * @link     https://xeriab.github.io/projects/konfig
15
 */
16
17
namespace Exen\Konfig;
18
19
use ArrayAccess;
20
use Iterator;
21
22
/**
23
 * AbstractKonfig.
24
 *
25
 * Main Konfig abstract class.
26
 *
27
 * @category Main
28
 * @package  Konfig
29
 * @author   Xeriab Nabil (aka KodeBurner) <[email protected]>
30
 * @license  https://raw.github.com/xeriab/konfig/master/LICENSE MIT
31
 * @link     https://xeriab.github.io/projects/konfig
32
 *
33
 * @implements ArrayAccess
34
 * @implements Iterator
35
 * @implements KonfigInterface
36
 */
37
abstract class AbstractKonfig implements ArrayAccess, Iterator, KonfigInterface
38
{
39
    /**
40
     * Stores the configuration items.
41
     *
42
     * @var array Data
43
     *
44
     * @since 0.1.0
45
     */
46
    protected $data = [];
47
48
    /**
49
     * Caches the configuration data.
50
     *
51
     * @var array Cache
52
     *
53
     * @since 0.1.0
54
     */
55
    protected $cache = [];
56
57
    /**
58
     * Random value used as a not-found check in get().
59
     *
60
     * @var string
61
     *
62
     * @since 0.1.0
63
     */
64
    protected static $defaultCheckValue;
65
66
    /**
67
     * Constructor method and sets default options, if any.
68
     *
69
     * @param array $input Input
70
     */
71 3
    public function __construct($input)
72
    {
73 3
        $this->data = Arr::mergeAssoc($this->getDefaults(), $input);
74
        //$this->data = array_merge($this->getDefaults(), $input);
75 3
    }
76
77
    /**
78
     * Override this method in your own subclass to provide an array of default
79
     * options and values.
80
     *
81
     * @return array
82
     *
83
     * @since              0.1.0
84
     * @codeCoverageIgnore
85
     */
86
    protected function getDefaults()
87
    {
88
        return [];
89
    }
90
91
    // KONFIGINTERFACE METHODS
92
93
    /**
94
     * {@inheritdoc}
95
     *
96
     * @return array Gets configuration items array
97
     */
98 3
    public function all()
99
    {
100 3
        return $this->data;
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     *
106
     * @param string $key Configuration item key name item
107
     *
108
     * @return bool Returns true if the configuration item key exists
109
     *
110
     * @since              0.1.0
111
     * @codeCoverageIgnore
112
     */
113
    public function has($key)
114
    {
115
        // Check if already cached
116
        if (Arr::get($this->cache, $key) || isset($this->cache[$key])) {
117
            return true;
118
        }
119
120
        $chunks = explode('.', $key);
121
        $root = $this->data;
122
123
        // Nested case
124
        foreach ($chunks as $chunk) {
125
            if (array_key_exists($chunk, $root)) {
126
                $root = $root[$chunk];
127
                continue;
128
            } else {
129
                return false;
130
            }
131
        }
132
133
        // Set cache for the given key
134
        $this->cache[$key] = $root;
135
136
        return true;
137
    }
138
139
    /**
140
     * {@inheritdoc}
141
     *
142
     * @param string            $key     Configuration item key name item
143
     * @param string|array|null $default Default configuration
144
     *
145
     * @return string|array|null Default configuration
146
     */
147 24
    public function get($key, $default = null)
148
    {
149 24
        if ($this->has($key)) {
150
            // return $this->cache[$key];
151 12
            return Arr::get($this->data, $key);
152
        }
153
154 12
        return $default;
155
    }
156
157
    /**
158
     * {@inheritdoc}
159
     *
160
     * @param string $key   Configuration item key name
161
     * @param mixed  $value Configuration item value
162
     *
163
     * @return void Void
164
     */
165 18
    public function set($key, $value)
166
    {
167 18
        $chunks = explode('.', $key);
168 18
        $root = &$this->data;
169 18
        $cacheKey = '';
170
171
        // Look for the key, creating nested keys if needed
172 18
        while ($part = array_shift($chunks)) {
173 18
            if ($cacheKey != '') {
174 12
                $cacheKey .= '.';
175 4
            }
176
177 18
            $cacheKey .= $part;
178
179 18
            if (!isset($root[$part]) && count($chunks)) {
180 3
                $root[$part] = [];
181 1
            }
182
183 18
            $root = &$root[$part];
184
185
            // Unset all old nested cache
186 18
            if (isset($this->cache[$cacheKey])) {
187 9
                unset($this->cache[$cacheKey]);
188 3
            }
189
190
            // Unset all old nested cache in case of array
191 18
            if (count($chunks) == 0) {
192 18
                foreach ($this->cache as $cacheLocalKey => $cacheValue) {
193 6
                    if (substr($cacheLocalKey, 0, strlen($cacheKey)) === $cacheKey) {
194 5
                        unset($this->cache[$cacheLocalKey]);
195 1
                    }
196 6
                }
197 6
            }
198 6
        }
199
200
        // Assign value at target node
201 18
        $this->cache[$key] = $root = $value;
202 18
    }
203
204
    /**
205
     * {@inheritdoc}
206
     *
207
     * @param string $key Configuration item key name
208
     *
209
     * @return             bool
210
     * @codeCoverageIgnore
211
     */
212
    public function delete($key)
213
    {
214
        if (isset($this->cache[$key])) {
215
            // unset($this->cache[$key]);
216
            Arr::delete($this->cache, $key);
217
        }
218
219
        return Arr::delete($this->data, $key);
220
    }
221
222
    // ARRAYACCESS METHODS
223
224
    /**
225
     * Gets a value using the offset as a key.
226
     *
227
     * @param string $offset Configuration item key name
228
     *
229
     * @return mixed Configuration item
230
     *
231
     * @since 0.1.0
232
     */
233 6
    public function offsetGet($offset)
234
    {
235 6
        return $this->get($offset);
236
    }
237
238
    /**
239
     * Checks if a key exists.
240
     *
241
     * @param string $offset Configuration item key name
242
     *
243
     * @return bool
244
     *
245
     * @since 0.1.0
246
     */
247 6
    public function offsetExists($offset)
248
    {
249 6
        return $this->has($offset);
250
    }
251
252
    /**
253
     * Sets a value using the offset as a key.
254
     *
255
     * @param string $offset Configuration item key name
256
     * @param mixed  $value  Configuration item value
257
     *
258
     * @return void Void
259
     * @since  0.1.0
260
     */
261 3
    public function offsetSet($offset, $value)
262
    {
263 3
        $this->set($offset, $value);
264 3
    }
265
266
    /**
267
     * Deletes a key and its value.
268
     *
269
     * @param string $offset Configuration item key name
270
     *
271
     * @return void Void
272
     * @since  0.1.0
273
     */
274 3
    public function offsetUnset($offset)
275
    {
276 3
        $this->set($offset, null);
277 3
    }
278
279
    // ITERATOR METHODS
280
281
    /**
282
     * Tests whether the iterator's current index is valid.
283
     *
284
     * @return bool True if the current index is valid; false otherwise
285
     *
286
     * @since 0.1.0
287
     */
288 3
    public function valid()
289
    {
290 3
        return is_array($this->data) ? key($this->data) !== null : false;
291
    }
292
293
    /**
294
     * Returns the data array index referenced by its internal cursor.
295
     *
296
     * @return mixed The index referenced by the data array's internal cursor.
297
     * If the array is empty or undefined or there is no element at the cursor,
298
     * the function returns null.
299
     *
300
     * @since 0.1.0
301
     */
302 3
    public function key()
303
    {
304 3
        return is_array($this->data) ? key($this->data) : null;
305
    }
306
307
    /**
308
     * Returns the data array element referenced by its internal cursor.
309
     *
310
     * @return mixed The element referenced by the data array's internal cursor.
311
     * If the array is empty or there is no element at the cursor,
312
     * the function returns false. If the array is undefined, the function
313
     * returns null
314
     *
315
     * @since 0.1.0
316
     */
317 3
    public function current()
318
    {
319 3
        return is_array($this->data) ? current($this->data) : null;
320
    }
321
322
    /**
323
     * Moves the data array's internal cursor forward one element.
324
     *
325
     * @return mixed The element referenced by the data array's internal cursor
326
     * after the move is completed. If there are no more elements in the
327
     * array after the move, the function returns false. If the data array
328
     * is undefined, the function returns null.
329
     *
330
     * @since 0.1.0
331
     */
332 3
    public function next()
333
    {
334 3
        return is_array($this->data) ? next($this->data) : null;
335
    }
336
337
    /**
338
     * Moves the data array's internal cursor to the first element.
339
     *
340
     * @return mixed The element referenced by the data array's internal cursor
341
     * after the move is completed. If the data array is empty, the function
342
     * returns false. If the data array is undefined, the function returns null.
343
     *
344
     * @since 0.1.0
345
     */
346 3
    public function rewind()
347
    {
348 3
        return is_array($this->data) ? reset($this->data) : null;
349
    }
350
351
    /**
352
     * __toString.
353
     *
354
     * @return             string
355
     * @since              0.1.2
356
     * @codeCoverageIgnore
357
     */
358
    public function __toString()
359
    {
360
        return 'Exen\Konfig\AbstractKonfig' . PHP_EOL;
361
    }
362
}
363
364
// END OF ./src/AbstractKonfig.php FILE
365