Total Complexity | 30 |
Total Lines | 147 |
Duplicated Lines | 0 % |
Coverage | 100% |
Changes | 7 | ||
Bugs | 0 | Features | 2 |
1 | <?php declare(strict_types=1); |
||
66 | class Config extends Arguments implements Configuration |
||
67 | { |
||
68 | public string $root = ''; |
||
69 | private bool $silent = false; |
||
70 | |||
71 | /** |
||
72 | * Config constructor. |
||
73 | * |
||
74 | * @param string $root Path to which files are read relative from. |
||
75 | * When the config object is created by an application/library |
||
76 | * this is the application's root path |
||
77 | * @param Data|null $defaults [optional] An Optional config object with default values |
||
78 | */ |
||
79 | 25 | public function __construct(string $root = '', Data $defaults = null) |
|
80 | { |
||
81 | 25 | parent::__construct($defaults ? $defaults->toArray() : []); |
|
82 | 25 | if (!$this->root = $root) { |
|
83 | 24 | $this->root = getcwd(); |
|
84 | } |
||
85 | } |
||
86 | |||
87 | /** |
||
88 | * Bad method calls can be suppressed and allow the app |
||
89 | * to continue execution by setting the silent(true). |
||
90 | * |
||
91 | * The app should handle their configuration appropriately. |
||
92 | * |
||
93 | * @param string $name Method name |
||
94 | * @param array|null $arguments [optional] |
||
95 | * @return Configuration |
||
96 | * @throws Exception |
||
97 | */ |
||
98 | 3 | public function __call(string $name, array|null $arguments): Configuration |
|
99 | { |
||
100 | 3 | if (false === $this->silent) { |
|
101 | 2 | throw new Exception('Unable to load the configuration file ' . current($arguments)); |
|
102 | } |
||
103 | 1 | return $this; |
|
104 | } |
||
105 | |||
106 | 1 | public function build(string $context): Configuration |
|
107 | { |
||
108 | 1 | throw new Exception('Configuration factory should implement the method ' . __METHOD__); |
|
109 | } |
||
110 | |||
111 | 1 | public function withParameters(array $parameters): Configuration |
|
112 | { |
||
113 | 1 | return $this->import($parameters); |
|
114 | } |
||
115 | |||
116 | 2 | public function fromObject(object|string $object): Configuration |
|
117 | { |
||
118 | 2 | if (is_string($object) && class_exists($object)) { |
|
119 | 1 | $object = new $object; |
|
120 | } |
||
121 | 2 | $this->root = $object->rootPath ?: $this->root; |
|
122 | 2 | return $this->import(iterator_to_array($object)); |
|
|
|||
123 | } |
||
124 | |||
125 | 2 | public function fromJsonFile(string $filename): Configuration |
|
126 | { |
||
127 | 2 | return $this->loadDataFrom($filename, |
|
128 | 2 | fn() => json_decode(file_get_contents($filename), true) |
|
129 | 2 | ); |
|
130 | } |
||
131 | |||
132 | 3 | public function fromIniFile(string $filename): Configuration |
|
133 | { |
||
134 | 3 | return $this->loadDataFrom($filename, |
|
135 | 3 | fn() => parse_ini_file($filename, true, INI_SCANNER_TYPED) ?: [] |
|
136 | 3 | ); |
|
137 | } |
||
138 | |||
139 | 4 | public function fromEnvFile(string $filename, string $namespace = ''): Configuration |
|
140 | { |
||
141 | try { |
||
142 | 4 | $data = parse_ini_file($this->filename($filename), true, INI_SCANNER_TYPED) ?: []; |
|
143 | 3 | env('', null, $this->filter($data, $namespace, false)); |
|
144 | 1 | } catch (Exception $e) { |
|
145 | 1 | error_log('[Configuration error]: ' . $e->getMessage()); |
|
146 | 1 | env('', null, []); |
|
147 | } finally { |
||
148 | 4 | return $this; |
|
149 | } |
||
150 | } |
||
151 | |||
152 | 5 | public function fromEnvVariable(string $variable): Configuration |
|
153 | { |
||
154 | 5 | if (false === empty($filename = getenv($variable))) { |
|
155 | 3 | $extension = ucfirst(pathinfo($filename, PATHINFO_EXTENSION)); |
|
156 | 3 | return call_user_func([$this, "from{$extension}File"], $filename); |
|
157 | } |
||
158 | 2 | if (false === $this->silent) { |
|
159 | 1 | throw new Exception(strtr('The environment variable ":variable" is not set |
|
160 | and as such configuration could not be loaded. Set this variable and |
||
161 | 1 | make it point to a configuration file', [':variable' => $variable])); |
|
162 | } |
||
163 | 1 | error_log('[Configuration error]: ' . (error_get_last()['message'] ?? "env var: $variable")); |
|
164 | 1 | return $this; |
|
165 | } |
||
166 | |||
167 | 4 | public function fromPhpFile(string $filename): Configuration |
|
168 | { |
||
169 | 4 | return $this->loadDataFrom($filename, fn() => include $filename); |
|
170 | } |
||
171 | |||
172 | 5 | public function fromEnvironment( |
|
173 | array $variableNames, |
||
174 | string $namespace = '', |
||
175 | bool $lowercase = true, |
||
176 | bool $trim = true): Configuration |
||
177 | { |
||
178 | 5 | $data = []; |
|
179 | 5 | foreach ($variableNames as $variable) { |
|
180 | 5 | $value = getenv($variable); |
|
181 | 5 | $data[] = $variable . '=' . (false === $value ? 'null' : $value); |
|
182 | } |
||
183 | 5 | $data = parse_ini_string(join(PHP_EOL, $data), true, INI_SCANNER_TYPED) ?: []; |
|
184 | 5 | $this->import($this->filter($data, $namespace, $lowercase, $trim)); |
|
185 | 5 | return $this; |
|
186 | } |
||
187 | |||
188 | 2 | public function silent(bool $silent): Configuration |
|
189 | { |
||
190 | 2 | $this->silent = $silent; |
|
191 | 2 | return $this; |
|
192 | } |
||
193 | |||
194 | 1 | public function namespace( |
|
201 | } |
||
202 | |||
203 | 9 | protected function loadDataFrom(string $filename, callable $loader): Configuration |
|
204 | { |
||
206 | } |
||
207 | |||
208 | 13 | private function filename(string $filename): string |
|
209 | { |
||
210 | 13 | return ('/' !== $filename[0]) |
|
211 | 5 | ? $this->root . '/' . $filename |
|
212 | 13 | : $filename; |
|
213 | } |
||
214 | } |
||
215 |