Completed
Pull Request — dev (#22)
by Ben
14:52
created

Config::all()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Benrowe\Laravel\Config;
4
5
use Illuminate\Contracts\Config\Repository;
6
use Illuminate\Support\Arr;
7
8
/**
9
 * Config class
10
 * Transforms a flattened key/value array configuration into a multi-dimensional
11
 * config handler
12
 */
13
class Config implements Repository
14
{
15
    /**
16
     * @var string The delimiter used in the array keys to specify the heirachy
17
     */
18
    const KEY_DELIMITER = '.';
19
20
    /**
21
     * @var string the pattern to match array keys
22
     */
23
    const ARRAY_PATTERN = "/\[([0-9]+)\]$/";
24
25
    /**
26
     * The configuration data
27
     * @var array
28
     */
29
    private $data;
30
31
    /**
32
     * constructor
33
     * The initial data
34
     *
35
     * @param array $data the flattened data
36
     */
37
    public function __construct($data)
38
    {
39
        $this->data = $this->dataDecode($data);
40
    }
41
42
    /**
43
     * Reduce the configuration to a simple key/value array, despite the heirachy
44
     * of information
45
     *
46
     * @return array
47
     */
48
    public function flatten()
49
    {
50
        return $this->dataEncode($this->data);
51
    }
52
53
    /**
54
     * Create/Update a configuration value
55
     *
56
     * @param string $key
57
     * @param mixed $value
58
     */
59
    public function set($key, $value = null)
60
    {
61
        Arr::set($this->data, $key, $value);
62
    }
63
64
    /**
65
     * Get the configuration value based on it's key
66
     *
67
     * @param  string $key
68
     * @param  mixed $default
69
     * @return mixed
70
     */
71
    public function get($key, $default = null)
72
    {
73
        return Arr::get($this->data, $key, $default);
74
    }
75
76
    /***
77
      * Get all of the configuration data in it's hierarchical state
78
      */
79
    public function all()
80
    {
81
        return $this->data;
82
    }
83
84
    /**
85
     * From an item from the configuration
86
     *
87
     * @param  string $key
88
     * @return boolean
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
89
     */
90
    public function forget($key)
91
    {
92
        return Arr::forget($this->data, $key);
93
    }
94
95
    /**
96
     * Clear all of the settings from the configuration
97
     *
98
     * @return boolean
99
     */
100
    public function clear()
101
    {
102
        if (!empty($this->data)) {
103
            $this->data = [];
104
            return true;
105
        }
106
        return false;
107
    }
108
109
    /**
110
     * Check if a configuration setting exists
111
     *
112
     * @param  string $key
113
     * @return boolean
114
     */
115
    public function has($key)
116
    {
117
        return Arr::has($this->data, $key);
118
    }
119
120
    /**
121
     * Prepend a value onto the key.
122
     *
123
     * If that existing key is not  an array it will be converted into an array
124
     * and the the value will be the first element of the array
125
     *
126
     * @param  string $key
127
     * @param  mixed $value
128
     * @return void
129
     */
130
    public function prepend($key, $value)
131
    {
132
        $existing = $this->getAsArray($key);
133
        array_unshift($existing, $value);
134
        $this->set($key, $existing);
135
    }
136
137
    /**
138
     * Push a value onto the key
139
     *
140
     * If that existing key is not  an array it will be converted into an array
141
     * and the the value will be the first element of the array
142
     *
143
     * @param  string $key
144
     * @param  mixed $value
145
     * @return void
146
     */
147
    public function push($key, $value)
148
    {
149
        $existing = $this->getAsArray($key);
150
        array_push($existing, $value);
151
        $this->set($key, $existing);
152
    }
153
154
    /**
155
     * Get the value, as an array
156
     *
157
     * @param  string $key
158
     * @return array any existing value will be converted to the first element
159
     *               of the array
160
     */
161
    private function getAsArray($key)
162
    {
163
        $value = $this->get($key);
164
        if (!is_array($value)) {
165
            $value = !is_null($value) ? [$value] : [];
166
        }
167
        return $value;
168
    }
169
170
    /**
171
     * Converts the flat key/value from the storage engine
172
     * to a heirachy structure based on the key sytax
173
     *
174
     * @param  array $data
175
     * @return array
176
     */
177
    private function dataDecode($data)
178
    {
179
        // preprocess the keys into a unique list where the array values are
180
        // stored against the same key
181
182
        $data = $this->unpackArray($data);
183
184
        $newData = [];
185
        foreach ($data as $key => $value) {
186
            Arr::set($newData, $key, $value);
187
        }
188
189
        return $newData;
190
    }
191
192
    /**
193
     * unpack the keys that are structured for arrays so that they no
194
     * longer have the [] syntax at the end. Rather they're now a proper
195
     * array.
196
     *
197
     * @param  array $data [description]
198
     * @return array
199
     */
200
    private function unpackArray($data)
201
    {
202
        $arrKeys = array_filter($data, function ($val) {
203
            return preg_match(self::ARRAY_PATTERN, $val);
204
        });
205
        foreach ($arrKeys as $key => $value) {
206
            $newKey = preg_replace(self::ARRAY_PATTERN, '', $key);
207
            if (!isset($data[$newKey])) {
208
                $data[$newKey] = [];
209
            }
210
            $data[$newKey][] = $value;
211
            unset($data[$key]);
212
        }
213
        return $data;
214
    }
215
216
    /**
217
     * Flatten a multi-dimensional array into a linear key/value list
218
     *
219
     * @param  array $data
220
     * @return array
221
     */
222
    private function dataEncode($data, $prefix = null)
223
    {
224
        $newData = [];
225
        foreach ($data as $key => $value) {
226
            if (is_array($value)) {
227
                $newData = array_merge($newData, $this->encodeArray($key, $value, $prefix));
228
                continue;
229
            }
230
            $newData[$prefix.$key] = $value;
231
        }
232
        return $newData;
233
    }
234
235
    /**
236
     * Encode the array of values against the provided key
237
     *
238
     * @param  string $key
239
     * @param  array  $value  either an associative or keyed array
240
     * @param  string $prefix
0 ignored issues
show
Documentation introduced by
Should the type for parameter $prefix not be string|null?

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.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
241
     * @return array
242
     */
243
    private function encodeArray($key, array $value, $prefix = null)
244
    {
245
        $data = [];
246
        if (!Arr::isAssoc($value)) {
247
            foreach ($value as $index => $val) {
248
                $data[$prefix.$key.'['.$index.']'] = $val;
249
            }
250
            return $data;
251
        }
252
        return $this->dataEncode($value, $prefix.$key.self::KEY_DELIMITER);
253
    }
254
}
255