AbstractConfig::offsetExists()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace FigTree\Config;
4
5
use ArrayIterator;
6
use Traversable;
7
use FigTree\Exceptions\{
8
	InvalidFileException,
9
	InvalidPathException,
10
	UnreadablePathException,
11
};
12
use FigTree\Config\Exceptions\ReadOnlyException;
13
use FigTree\Config\Contracts\ConfigInterface;
14
15
abstract class AbstractConfig implements ConfigInterface
16
{
17
	/**
18
	 * Paths of underlying Config files.
19
	 */
20
	protected array $paths = [];
21
22
	/**
23
	 * Configuration data.
24
	 */
25
	protected array $data = [];
26
27
	/**
28
	 * Indicates if Config data has already been read.
29
	 */
30
	protected bool $isRead = false;
31
32
	/**
33
	 * Get the paths of the underlying Config files.
34
	 *
35
	 * @return array
36
	 */
37
	public function getPaths(): array
38
	{
39
		return $this->paths;
40
	}
41
42
	/**
43
	 * Magic method to handle key_exists/isset checks of an array value on the object.
44
	 *
45
	 * @param string|int $offset
46
	 *
47
	 * @return boolean
48
	 */
49
	public function offsetExists($offset): bool
50
	{
51
		$this->read();
52
53
		return key_exists($offset, $this->data);
54
	}
55
56
	/**
57
	 * Magic method to handle retrieval of an array value on the object.
58
	 *
59
	 * @param string|int $offset
60
	 *
61
	 * @return mixed
62
	 */
63
	public function offsetGet($offset)
64
	{
65
		return $this->read()->data[$offset] ?? null;
66
	}
67
68
	/**
69
	 * Magic method to handle modification of an array value on the object.
70
	 *
71
	 * @param string|int $offset
72
	 * @param mixed $value
73
	 *
74
	 * @return void
75
	 *
76
	 * @throws \FigTree\Config\Exceptions\ReadOnlyException
77
	 */
78
	public function offsetSet($offset, $value): void
79
	{
80
		throw new ReadOnlyException($offset);
81
	}
82
83
	/**
84
	 * Magic method to handle removal of an array value on the object.
85
	 *
86
	 * @param string|int $offset
87
	 *
88
	 * @return void
89
	 *
90
	 * @throws \FigTree\Config\Exceptions\ReadOnlyException
91
	 */
92
	public function offsetUnset($offset): void
93
	{
94
		throw new ReadOnlyException($offset);
95
	}
96
97
	/**
98
	 * Convert the object into an array.
99
	 *
100
	 * @return array
101
	 */
102
	public function toArray(): array
103
	{
104
		return $this->read()->data;
105
	}
106
107
	/**
108
	 * Convert the object into JSON.
109
	 *
110
	 * @param integer $options
111
	 * @param integer $depth
112
	 *
113
	 * @return string
114
	 */
115
	public function toJson(int $options = 0, int $depth = 512): string
116
	{
117
		if (($options & JSON_THROW_ON_ERROR) === 0) {
118
			$options |= JSON_THROW_ON_ERROR;
119
		}
120
121
		return json_encode($this, $options, $depth);
122
	}
123
124
	/**
125
	 * Convert the object into a string.
126
	 *
127
	 * @return string
128
	 */
129
	public function toString(): string
130
	{
131
		return $this->__toString();
132
	}
133
134
	/**
135
	 * Magic method called on JSON serialization of the object.
136
	 *
137
	 * @return array The data to be serialized.
138
	 */
139
	public function jsonSerialize()
140
	{
141
		return $this->toArray();
142
	}
143
144
	/**
145
	 * Magic method called during serialization to a string.
146
	 *
147
	 * @return string
148
	 */
149
	public function __toString()
150
	{
151
		return serialize($this);
152
	}
153
154
	/**
155
	 * Retrieve an external iterator.
156
	 *
157
	 * @return \Traversable
158
	 */
159
	public function getIterator(): Traversable
160
	{
161
		return new ArrayIterator($this->data);
162
	}
163
164
	/**
165
	 * Resolve the given filename of a Config file, add it to the
166
	 * array of files, and mark the Config as unread.
167
	 *
168
	 * @param string $fileName
169
	 *
170
	 * @return $this
171
	 *
172
	 * @throws \FigTree\Exceptions\InvalidPathException
173
	 * @throws \FigTree\Exceptions\InvalidFileException
174
	 */
175
	protected function addPath(string $fileName): ConfigInterface
176
	{
177
		$path = realpath($fileName);
178
179
		if (empty($path)) {
180
			throw new InvalidPathException($fileName);
181
		}
182
183
		if (!is_file($path)) {
184
			throw new InvalidFileException($path);
185
		}
186
187
		$this->paths[] = $path;
188
189
		$this->isRead = false;
190
191
		return $this;
192
	}
193
194
	/**
195
	 * Clear and read in all Config data.
196
	 *
197
	 * @return $this
198
	 */
199
	protected function read()
200
	{
201
		if ($this->isRead) {
202
			return $this;
203
		}
204
205
		$this->data = [];
206
207
		foreach ($this->paths as $path) {
208
			$this->readFile($path);
209
		}
210
211
		$this->isRead = true;
212
213
		return $this;
214
	}
215
216
	/**
217
	 * Read the result of the Config file into the object's data.
218
	 *
219
	 * @param string $path
220
	 *
221
	 * @return $this
222
	 *
223
	 * @throws \FigTree\Exceptions\UnreadablePathException
224
	 * @throws \FigTree\Config\Exceptions\InvalidConfigFileException
225
	 */
226
	protected function readFile(string $path): ConfigInterface
227
	{
228
		if (!is_readable($path)) {
229
			throw new UnreadablePathException($path);
230
		}
231
232
		$reader = $this->createReader();
233
234
		$data = $reader->read($path);
235
236
		$this->data = array_replace_recursive($this->data, $data);
237
238
		return $this;
239
	}
240
}
241