Completed
Push — 9.0-dev ( 6e45f1...606dea )
by Radu
03:34
created

ArrayStorage::set()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 5
eloc 12
c 2
b 0
f 0
nc 4
nop 3
dl 0
loc 17
rs 8.8571
1
<?php
2
namespace WebServCo\Framework;
3
4
final class ArrayStorage
5
{
6
    /**
7
     * Parse the setting key to make sure it's a simple string
8
     * or an array.
9
     */
10
    private static function parseSetting($setting)
11
    {
12
        if (is_string($setting) &&
13
        false !== strpos($setting, \WebServCo\Framework\Settings::DIVIDER)) {
14
            return explode(\WebServCo\Framework\Settings::DIVIDER, $setting);
15
        }
16
        return $setting;
17
    }
18
    
19
    /**
20
     * Retrieve a value from a storage array.
21
     *
22
     * @param array $storage
23
     * @param mixed $setting Can be an array, a string,
24
     *                          or a special formatted string
25
     *                          (eg 'app/path/project').
26
     * @param mixed $defaultValue
27
     * @return mixed
28
     */
29
    public static function get($storage, $setting = null, $defaultValue = false)
30
    {
31
        $setting = self::parseSetting($setting);
32
        
33
        if (empty($setting) || empty($storage)) {
34
            return $defaultValue;
35
        }
36
        
37
        /**
38
         * If $setting is an array, process it recursively.
39
         */
40
        if (is_array($setting)) {
41
            /**
42
             * Check if we have the first $setting element in the
43
             * configuration data array.
44
             */
45
            if (array_key_exists(0, $setting) && array_key_exists($setting[0], $storage)) {
46
                /**
47
                 * Remove first element from $setting.
48
                 */
49
                $key = array_shift($setting);
50
                /**
51
                 * At the end of the recursion $setting will be
52
                 * an empty array. In this case we simply return the
53
                 * current configuration data.
54
                 */
55
                if (empty($setting)) {
56
                    return $storage[$key];
57
                }
58
                /**
59
                 * Go down one element in the configuration data
60
                 * and call the method again, with the remainig setting.
61
                 */
62
                return self::get($storage[$key], $setting, $defaultValue);
63
            }
64
            /**
65
             * The requested setting doesn't exist in our
66
             * configuration data array.
67
             */
68
            return $defaultValue;
69
        }
70
        
71
        /**
72
         * If we arrive here, $setting must be a simple string.
73
         */
74
        if (array_key_exists($setting, $storage)) {
75
            return $storage[$setting];
76
        }
77
        
78
        /**
79
         * If we got this far, there is no data to return.
80
         */
81
        return $defaultValue;
82
    }
83
    
84
    /**
85
     * Sets a value in a storage array.
86
     *
87
     * @param array $storage
88
     * @param mixed $setting Can be an array, a string,
89
     *                          or a special formatted string
90
     *                          (eg 'app/path/project').
91
     * @param mixed $value The value to be stored.
92
     *
93
     * @return array The storage array with new data.
94
     * @throws \ErrorException
95
     */
96
    public static function set($storage, $setting, $value)
97
    {
98
        if (!is_array($storage) || empty($setting)) {
99
            throw new \ErrorException('Invalid parameters specified');
100
        }
101
        $setting = self::parseSetting($setting);
102
        if (is_array($setting)) {
103
            $reference = &$storage;
104
            foreach ($setting as $item) {
105
                $reference = &$reference[$item];
106
            }
107
            $reference = $value;
108
            unset($reference);
109
            return $storage;
110
        }
111
        $storage[$setting] = $value;
112
        return $storage;
113
    }
114
    
115
    /**
116
     * Append data to a storage array.
117
     *
118
     * @param array $storage
119
     * @param mixed $data
120
     * @return array
121
     * @throws \ErrorException
122
     */
123
    public static function append($storage, $data = [])
124
    {
125
        if (!is_array($storage) || !is_array($data)) {
126
            throw new \ErrorException('Invalid parameters specified');
127
        }
128
        foreach ($data as $setting => $value) {
129
            if (array_key_exists($setting, $storage) &&
130
                is_array($storage[$setting]) &&
131
                is_array($value)
132
            ) {
133
                $storage[$setting] = self::append($storage[$setting], $value);
134
            } else {
135
                $storage[$setting] = $value;
136
            }
137
        }
138
        return $storage;
139
    }
140
    
141
    /**
142
     * Removes a setting from a storage array.
143
     *
144
     * @param array $storage
145
     * @param mixed $setting Can be an array, a string,
146
     *                          or a special formatted string
147
     *                          (eg 'app/path/project').
148
     *
149
     * @return array The updated storage array.
150
     * @throws \ErrorException
151
     */
152
    public static function remove($storage, $setting)
153
    {
154
        if (!is_array($storage) || empty($setting)) {
155
            throw new \ErrorException('Invalid parameters specified');
156
        }
157
        
158
        $setting = self::parseSetting($setting);
159
        
160
        if (empty($setting)) {
161
            throw new \ErrorException('Empty setting');
162
        }
163
        
164
        if (is_array($setting)) {
165
            return self::removeByIndex($storage, $setting);
166
        }
167
        if (!array_key_exists($setting, $storage)) {
168
            throw new \ErrorException(
169
                sprintf('"%s" does not exist in storage object', $setting)
170
            );
171
        }
172
        unset($storage[$setting]);
173
        return $storage;
174
    }
175
    
176
    /**
177
     * Remove index from multi-dimensional array.
178
     *
179
     * https://stackoverflow.com/questions/26661828/
180
     *
181
     * @param array $array
182
     *   The array to remove the index from.
183
     * @param array $indices
184
     *   Indexed array containing the indices chain up to the index that should be
185
     *   removed.
186
     * @return array
187
     *   The array with the index removed.
188
     * @throws \ErrorException
189
     *   If the index does not exist within the array.
190
     */
191
    protected static function removeByIndex($array, $indices)
192
    {
193
        if (!is_array($array) || !is_array($indices)) {
0 ignored issues
show
introduced by
The condition ! is_array($array) || ! is_array($indices) can never be true.
Loading history...
194
            throw new \ErrorException('Invalid parameters specified');
195
        }
196
        // Create a reference to the original array.
197
        $a = &$array;
198
        // Count all passed indices, remove one because arrays are zero based.
199
        $c = count($indices) - 1;
200
        // Iterate over all passed indices.
201
        for ($i = 0; $i <= $c; ++$i) {
202
            // Make sure the index to go down for deletion actually exists.
203
            if (!array_key_exists($indices[$i], $a)) {
204
                throw new \ErrorException(
205
                    sprintf('"%s" does not exist in storage object', $indices[$i])
206
                );
207
            }
208
            // This is the target if we reached the last index that was passed.
209
            if ($i === $c) {
210
                unset($a[$indices[$i]]);
211
            } elseif (is_array($a[$indices[$i]])) {
212
                // Make sure we have an array to go further down.
213
                $a = &$a[$indices[$i]];
214
            } else {
215
                throw new \ErrorException(
216
                    sprintf('"%s" does not exist in storage object', $indices[$i])
217
                );
218
            }
219
        }
220
        return $array;
221
    }
222
}
223