Passed
Push — master ( 8638e9...a09c87 )
by Alain
02:55
created

AbstractConfig::getKeyArguments()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 0
loc 16
ccs 9
cts 9
cp 1
rs 9.2
cc 4
eloc 9
nc 5
nop 1
crap 4
1
<?php
2
/**
3
 * Abstract Config Object
4
 *
5
 * @package   BrightNucleus\Config
6
 * @author    Alain Schlesser <[email protected]>
7
 * @license   GPL-2.0+
8
 * @link      http://www.brightnucleus.com/
9
 * @copyright 2016 Alain Schlesser, Bright Nucleus
10
 */
11
12
namespace BrightNucleus\Config;
13
14
use ArrayObject;
15
use BadMethodCallException;
16
use Exception;
17
use OutOfRangeException;
18
19
/**
20
 * Config loader used to load config PHP files as objects.
21
 *
22
 * @since      0.1.0
23
 *
24
 * @package    BrightNucleus\Config
25
 * @author     Alain Schlesser <[email protected]>
26
 */
27
abstract class AbstractConfig extends ArrayObject implements ConfigInterface
28
{
29
30
    /**
31
     * Array of strings that are used as delimiters to parse configuration keys.
32
     *
33
     * @since 0.1.6
34
     *
35
     * @var array
36
     */
37
    protected $delimiter = ['\\', '/', '.'];
38
39
    /**
40
     * Instantiate the AbstractConfig object.
41
     *
42
     * @since 0.1.0
43
     * @since 0.1.6 Accepts a delimiter to parse configuration keys.
44
     *
45
     * @param array                $config    Array with settings.
46
     * @param string[]|string|null $delimiter A string or array of strings that are used as delimiters to parse
47
     *                                        configuration keys. Defaults to "\", "/" & ".".
48
     */
49 2
    public function __construct(array $config, $delimiter = null)
50
    {
51
        // Make sure the config entries can be accessed as properties.
52 2
        parent::__construct($config, ArrayObject::ARRAY_AS_PROPS);
53
54 2
        if (null !== $delimiter) {
55 1
            $this->delimiter = (array)$delimiter;
56
        }
57 2
    }
58
59
    /**
60
     * Get the value of a specific key.
61
     *
62
     * To get a value several levels deep, add the keys for each level as a comma-separated list.
63
     *
64
     * @since 0.1.0
65
     * @since 0.1.4 Accepts list of keys.
66
     *
67
     * @param string ... List of keys.
68
     * @return mixed
69
     * @throws BadMethodCallException If no argument was provided.
70
     * @throws OutOfRangeException If an unknown key is requested.
71
     */
72 2
    public function getKey()
73
    {
74 2
        $keys = $this->getKeyArguments(func_get_args());
75 2
        \Assert\thatAll($keys)->string()->notEmpty();
76
77 2
        if (! $this->hasKey($keys)) {
78 1
            throw new OutOfRangeException(
79
                sprintf(
80 1
                    _('The configuration key %1$s does not exist.'),
81 1
                    implode('->', $keys)
82
                )
83
            );
84
        }
85
86 2
        $keys  = array_reverse($keys);
87 2
        $array = $this->getArrayCopy();
88 2
        while (count($keys) > 0) {
89 2
            $key   = array_pop($keys);
90 2
            $array = $array[$key];
91
        }
92
93 2
        return $array;
94
    }
95
96
    /**
97
     * Check whether the Config has a specific key.
98
     *
99
     * To check a value several levels deep, add the keys for each level as a comma-separated list.
100
     *
101
     * @since 0.1.0
102
     * @since 0.1.4 Accepts list of keys.
103
     *
104
     * @param string ... List of keys.
105
     * @return bool
106
     */
107 2
    public function hasKey()
108
    {
109
        try {
110 2
            $keys = array_reverse($this->getKeyArguments(func_get_args()));
111 2
            \Assert\thatAll($keys)->string()->notEmpty();
112
113 2
            $array = $this->getArrayCopy();
114 2
            while (count($keys) > 0) {
115 2
                $key = array_pop($keys);
116 2
                if (! array_key_exists($key, $array)) {
117 2
                    return false;
118
                }
119 2
                $array = $array[$key];
120
            }
121 1
        } catch (Exception $exception) {
122 1
            return false;
123
        }
124
125 2
        return true;
126
    }
127
128
    /**
129
     * Get a (multi-dimensional) array of all the configuration settings.
130
     *
131
     * @since 0.1.4
132
     *
133
     * @return array
134
     */
135 1
    public function getAll()
136
    {
137 1
        return $this->getArrayCopy();
138
    }
139
140
    /**
141
     * Get the an array with all the keys
142
     *
143
     * @since 0.1.0
144
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<integer|string>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
145
     */
146 1
    public function getKeys()
147
    {
148 1
        return array_keys((array)$this);
149
    }
150
151
    /**
152
     * Recursively extract the configuration key arguments from an arbitrary array.
153
     *
154
     * @since 0.1.6
155
     *
156
     * @param array $arguments Array as fetched through get_func_args().
157
     * @return array Array of strings.
158
     * @throws BadMethodCallException If no argument was provided.
159
     */
160 4
    protected function getKeyArguments($arguments)
161
    {
162 4
        \Assert\that($arguments)->isArray()->notEmpty();
163
164 3
        $keys = [];
165 3
        foreach ($arguments as $argument) {
166 3
            if (is_array($argument)) {
167 3
                $keys = array_merge($keys, $this->getKeyArguments($argument));
168
            }
169 3
            if (is_string($argument)) {
170 3
                $keys = array_merge($keys, $this->parseKeysString($argument));
171
            }
172
        }
173
174 3
        return $keys;
175
    }
176
177
    /**
178
     * Extract individual keys from a delimited string.
179
     *
180
     * @since 0.1.6
181
     *
182
     * @param string $keyString Delimited string of keys.
183
     * @return array Array of key strings.
184
     */
185 1
    protected function parseKeysString($keyString)
186
    {
187 1
        \Assert\that($keyString)->string()->notEmpty();
188
189
        // Replace all of the configured delimiters by the first one, so that we can then use explode().
190 1
        $normalizedString = str_replace($this->delimiter, $this->delimiter[0], $keyString);
191
192 1
        return (array)explode($this->delimiter[0], $normalizedString);
193
    }
194
195
    /**
196
     * Validate the Config file.
197
     *
198
     * @since  0.1.0
199
     * @return boolean
200
     */
201
    abstract public function isValid();
202
}
203