summaryrefslogtreecommitdiffstats
path: root/library/Icinga/Data/ConfigObject.php
blob: c9a313444b429f608c8d5b9c51da7cc63ff399dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
<?php
/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */

namespace Icinga\Data;

use Iterator;
use ArrayAccess;
use Icinga\Data\DataArray\ArrayDatasource;
use Icinga\Exception\ProgrammingError;

/**
 * Container for configuration values
 */
class ConfigObject extends ArrayDatasource implements Iterator, ArrayAccess
{
    /**
     * Create a new config
     *
     * @param   array   $data   The data to initialize the new config with
     */
    public function __construct(array $data = array())
    {
        // Convert all embedded arrays to ConfigObjects as well
        foreach ($data as & $value) {
            if (is_array($value)) {
                $value = new static($value);
            }
        }

        parent::__construct($data);
    }

    /**
     * Deep clone this config
     */
    public function __clone()
    {
        $array = array();
        foreach ($this->data as $key => $value) {
            if ($value instanceof self) {
                $array[$key] = clone $value;
            } else {
                $array[$key] = $value;
            }
        }

        $this->data = $array;
    }

    /**
     * Reset the current position of $this->data
     *
     * @return  void
     */
    public function rewind(): void
    {
        reset($this->data);
    }

    /**
     * Return the section's or property's value of the current iteration
     *
     * @return  mixed
     */
    #[\ReturnTypeWillChange]
    public function current()
    {
        return current($this->data);
    }

    /**
     * Return whether the position of the current iteration is valid
     *
     * @return  bool
     */
    public function valid(): bool
    {
        return key($this->data) !== null;
    }

    /**
     * Return the section's or property's name of the current iteration
     *
     * @return  string
     */
    public function key(): string
    {
        return key($this->data);
    }

    /**
     * Advance the position of the current iteration and return the new section's or property's value
     *
     * @return  void
     */
    public function next(): void
    {
        next($this->data);
    }

    /**
     * Return whether the given section or property is set
     *
     * @param   string  $key    The name of the section or property
     *
     * @return  bool
     */
    public function __isset($key)
    {
        return isset($this->data[$key]);
    }

    /**
     * Return the value for the given property or the config for the given section
     *
     * @param   string  $key    The name of the property or section
     *
     * @return  mixed|NULL      The value or NULL in case $key does not exist
     */
    public function __get($key)
    {
        return $this->get($key);
    }

    /**
     * Add a new property or section
     *
     * @param   string  $key    The name of the new property or section
     * @param   mixed   $value  The value to set for the new property or section
     */
    public function __set($key, $value)
    {
        if (is_array($value)) {
            $this->data[$key] = new static($value);
        } else {
            $this->data[$key] = $value;
        }
    }

    /**
     * Remove the given property or section
     *
     * @param   string  $key    The property or section to remove
     */
    public function __unset($key)
    {
        unset($this->data[$key]);
    }

    /**
     * Return whether the given section or property is set
     *
     * @param   string  $key    The name of the section or property
     *
     * @return  bool
     */
    public function offsetExists($key): bool
    {
        return isset($this->$key);
    }

    /**
     * Return the value for the given property or the config for the given section
     *
     * @param   string  $key    The name of the property or section
     *
     * @return  ?mixed      The value or NULL in case $key does not exist
     */
    #[\ReturnTypeWillChange]
    public function offsetGet($key)
    {
        return $this->get($key);
    }

    /**
     * Add a new property or section
     *
     * @param   string  $key        The name of the new property or section
     * @param   mixed   $value      The value to set for the new property or section
     *
     * @throws  ProgrammingError    If the key is null
     */
    public function offsetSet($key, $value): void
    {
        if ($key === null) {
            throw new ProgrammingError('Appending values without an explicit key is not supported');
        }

        $this->$key = $value;
    }

    /**
     * Remove the given property or section
     *
     * @param   string  $key    The property or section to remove
     */
    public function offsetUnset($key): void
    {
        unset($this->$key);
    }

    /**
     * Return whether this config has any data
     *
     * @return  bool
     */
    public function isEmpty()
    {
        return empty($this->data);
    }

    /**
     * Return the value for the given property or the config for the given section
     *
     * @param   string  $key        The name of the property or section
     * @param   mixed   $default    The value to return in case the property or section is missing
     *
     * @return  mixed
     */
    public function get($key, $default = null)
    {
        if (array_key_exists($key, $this->data)) {
            return $this->data[$key];
        }

        return $default;
    }

    /**
     * Return all section and property names
     *
     * @return  array
     */
    public function keys()
    {
        return array_keys($this->data);
    }

    /**
     * Return this config's data as associative array
     *
     * @return  array
     */
    public function toArray()
    {
        $array = array();
        foreach ($this->data as $key => $value) {
            if ($value instanceof self) {
                $array[$key] = $value->toArray();
            } else {
                $array[$key] = $value;
            }
        }

        return $array;
    }

    /**
     * Merge the given data with this config
     *
     * @param   array|ConfigObject $data An array or a config
     *
     * @return  $this
     */
    public function merge($data)
    {
        if ($data instanceof self) {
            $data = $data->toArray();
        }

        foreach ($data as $key => $value) {
            if (array_key_exists($key, $this->data)) {
                if (is_array($value)) {
                    if ($this->data[$key] instanceof self) {
                        $this->data[$key]->merge($value);
                    } else {
                        $this->data[$key] = new static($value);
                    }
                } else {
                    $this->data[$key] = $value;
                }
            } else {
                $this->data[$key] = is_array($value) ? new static($value) : $value;
            }
        }

        return $this;
    }
}