1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Magium\Configuration\File\Configuration; |
4
|
|
|
|
5
|
|
|
use Magium\Configuration\Config\InvalidConfigurationLocationException; |
6
|
|
|
use Magium\Configuration\Config\InvalidDirectoryException; |
7
|
|
|
use Magium\Configuration\File\AdapterInterface; |
8
|
|
|
use Magium\Configuration\File\InvalidFileException; |
9
|
|
|
|
10
|
|
|
class ConfigurationFileRepository implements \ArrayAccess, \Iterator, \Countable |
11
|
|
|
{ |
12
|
|
|
protected $files = []; |
13
|
|
|
protected $secureBases = []; |
14
|
|
|
protected $supportedTypes = []; |
15
|
|
|
|
16
|
|
|
protected static $me; |
17
|
|
|
|
18
|
|
|
protected function __construct() {} |
19
|
|
|
|
20
|
25 |
|
public static function getInstance(array $secureBases = [], array $configurationFiles = []) |
21
|
|
|
{ |
22
|
25 |
|
if (!self::$me instanceof self) { |
23
|
24 |
|
self::$me = new self(); |
24
|
|
|
} |
25
|
25 |
|
foreach ($secureBases as $base) { |
26
|
6 |
|
self::$me->addSecureBase($base); |
27
|
|
|
} |
28
|
24 |
|
if ($configurationFiles) { |
|
|
|
|
29
|
4 |
|
$supportedTypes = self::$me->getSupportedTypes($configurationFiles); |
30
|
4 |
|
self::$me->buildConfigurationFileList($configurationFiles, $supportedTypes); |
31
|
|
|
} |
32
|
22 |
|
return self::$me; |
33
|
|
|
} |
34
|
|
|
|
35
|
31 |
|
public static function reset() |
36
|
|
|
{ |
37
|
31 |
|
self::$me = null; |
38
|
31 |
|
} |
39
|
|
|
|
40
|
4 |
|
protected function buildConfigurationFileList(array $configurationFiles, array $supportedTypes) |
41
|
|
|
{ |
42
|
4 |
|
foreach ($configurationFiles as $file) { |
43
|
4 |
|
$fileName = basename($file); |
44
|
4 |
|
$typeFound = false; |
45
|
4 |
|
foreach ($supportedTypes as $type) { |
46
|
4 |
|
if (strpos($fileName, '.' . $type) !== false) { |
47
|
3 |
|
$class = 'Magium\Configuration\File\Configuration\\' . ucfirst($type) . 'File'; |
48
|
3 |
|
$configurationFile = new $class($file); |
49
|
2 |
|
$this->registerConfigurationFile($configurationFile); |
50
|
2 |
|
$typeFound = true; |
51
|
|
|
} |
52
|
|
|
} |
53
|
3 |
|
if (!$typeFound) { |
54
|
1 |
|
throw new UnsupportedFileTypeException( |
55
|
1 |
|
sprintf( |
56
|
1 |
|
'File %s does not have a supported file extension: %s', |
57
|
1 |
|
$file, |
58
|
1 |
|
implode(',', $supportedTypes) |
59
|
|
|
)) |
60
|
|
|
; |
61
|
|
|
} |
62
|
|
|
} |
63
|
2 |
|
} |
64
|
|
|
|
65
|
4 |
|
protected function getSupportedTypes(array $configurationFiles) |
66
|
|
|
{ |
67
|
4 |
|
if (!count($this->supportedTypes)) { |
68
|
|
|
|
69
|
4 |
|
if (!empty($configurationFiles)) { |
70
|
4 |
|
$checkSupportedTypes = glob(__DIR__ . '/*File.php'); |
71
|
4 |
|
foreach ($checkSupportedTypes as $file) { |
72
|
4 |
|
$file = basename($file); |
73
|
4 |
|
if ($file != 'AbstractConfigurationFile.php') { |
74
|
4 |
|
$match = null; |
75
|
4 |
|
if (preg_match('/^([a-zA-Z]+)File.php$/', $file, $match)) { |
76
|
4 |
|
$this->supportedTypes[] = strtolower($match[1]); |
77
|
|
|
} |
78
|
|
|
} |
79
|
|
|
} |
80
|
|
|
} |
81
|
|
|
} |
82
|
4 |
|
return $this->supportedTypes; |
83
|
|
|
} |
84
|
|
|
|
85
|
6 |
|
public function count() |
86
|
|
|
{ |
87
|
6 |
|
return count($this->files); |
88
|
|
|
} |
89
|
|
|
|
90
|
5 |
|
public function registerConfigurationFile(AdapterInterface $file) |
91
|
|
|
{ |
92
|
5 |
|
if (!isset($this->files[$file->getFile()])) { |
93
|
5 |
|
$this->files[$file->getFile()] = $file; |
94
|
|
|
} |
95
|
|
|
|
96
|
5 |
|
} |
97
|
|
|
|
98
|
8 |
|
public function addSecureBase($base) |
99
|
|
|
{ |
100
|
8 |
|
$path = realpath($base); |
101
|
8 |
|
if (!is_dir($path)) { |
102
|
1 |
|
throw new InvalidDirectoryException('Unable to determine real path for directory: ' . $base); |
103
|
|
|
} |
104
|
7 |
|
if (!in_array($path, $this->secureBases)) { |
105
|
7 |
|
$this->secureBases[] = $path; |
106
|
|
|
} |
107
|
7 |
|
} |
108
|
|
|
|
109
|
5 |
|
protected function checkFileLocation(AdapterInterface $file) |
110
|
|
|
{ |
111
|
5 |
|
$path = realpath($file->getFile()); |
112
|
5 |
|
$inSecurePath = false; |
113
|
5 |
|
foreach ($this->secureBases as $base) { |
114
|
4 |
|
if (strpos($path, $base) === 0) { |
115
|
4 |
|
$inSecurePath = true; |
116
|
4 |
|
break; |
117
|
|
|
} |
118
|
|
|
} |
119
|
|
|
|
120
|
5 |
|
if (!$inSecurePath) { |
121
|
1 |
|
throw new InvalidConfigurationLocationException($path . ' is not in one of the designated secure configuration paths.'); |
122
|
|
|
} |
123
|
4 |
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* Retrieves a list of secure base directories |
127
|
|
|
* |
128
|
|
|
* @return array |
129
|
|
|
*/ |
130
|
|
|
|
131
|
1 |
|
public function getSecureBases() |
132
|
|
|
{ |
133
|
1 |
|
return $this->secureBases; |
134
|
|
|
} |
135
|
|
|
|
136
|
5 |
|
public function current() |
137
|
|
|
{ |
138
|
5 |
|
$current = current($this->files); |
139
|
5 |
|
$this->checkFileLocation($current); |
140
|
4 |
|
return $current; |
141
|
|
|
} |
142
|
|
|
|
143
|
4 |
|
public function next() |
144
|
|
|
{ |
145
|
4 |
|
$next = next($this->files); |
146
|
4 |
|
if (!is_bool($next)) { |
147
|
2 |
|
$this->checkFileLocation($next); |
148
|
|
|
} |
149
|
4 |
|
return $next; |
150
|
|
|
} |
151
|
|
|
|
152
|
5 |
|
public function key() |
153
|
|
|
{ |
154
|
5 |
|
return key($this->files); |
155
|
|
|
} |
156
|
|
|
|
157
|
5 |
|
public function valid() |
158
|
|
|
{ |
159
|
5 |
|
$key = $this->key(); |
160
|
5 |
|
$var = ($key !== NULL && $key !== FALSE); |
161
|
5 |
|
return $var; |
162
|
|
|
} |
163
|
|
|
|
164
|
5 |
|
public function rewind() |
165
|
|
|
{ |
166
|
5 |
|
return reset($this->files); |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
public function offsetExists($offset) |
170
|
|
|
{ |
171
|
|
|
return isset($this->files[$offset]); |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
public function offsetGet($offset) |
175
|
|
|
{ |
176
|
|
|
$get = $this->files[$offset]; |
177
|
|
|
$this->checkFileLocation($get); |
178
|
|
|
return $get; |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
public function offsetSet($offset, $value) |
182
|
|
|
{ |
183
|
|
|
$this->registerConfigurationFile($value); |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
public function offsetUnset($offset) |
187
|
|
|
{ |
188
|
|
|
unset($this->files[$offset]); |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
} |
192
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.