1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Anax\Configure; |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* Load configuration for a specified item, look in several places for the |
7
|
|
|
* configuration files or directories. Return the configuration as the value |
8
|
|
|
* received from the configuration file. |
9
|
|
|
*/ |
10
|
|
|
class Configuration |
11
|
|
|
{ |
12
|
|
|
/** |
13
|
|
|
* @var array $dirs where to look for configuration items. |
14
|
|
|
*/ |
15
|
|
|
protected $dirs = []; |
16
|
|
|
|
17
|
|
|
|
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* @var array $mapping mapping items to specific configuration file, mainly |
21
|
|
|
* useful for testing various configuration files. |
22
|
|
|
*/ |
23
|
|
|
protected $mapping = []; |
24
|
|
|
|
25
|
|
|
|
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Set a specific configuration file to load for a particluar item. |
29
|
|
|
* |
30
|
|
|
* @param string $item the item to map. |
31
|
|
|
* @param string $file file to load configuration from. |
32
|
|
|
* |
33
|
|
|
* @return self to allow chaining. |
34
|
|
|
*/ |
35
|
1 |
|
public function setMapping(string $item, string $file) : object |
36
|
|
|
{ |
37
|
1 |
|
$this->mapping[$item] = $file; |
38
|
1 |
|
return $this; |
39
|
|
|
} |
40
|
|
|
|
41
|
|
|
|
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Set the directories where to look for configuration |
45
|
|
|
* items (files, directories) to load. |
46
|
|
|
* |
47
|
|
|
* @throws Exception when the path to any of the directories are incorrect. |
48
|
|
|
* |
49
|
|
|
* @param array $dirs with the path to the config directories to search in. |
50
|
|
|
* |
51
|
|
|
* @return self to allow chaining. |
52
|
|
|
*/ |
53
|
8 |
|
public function setBaseDirectories(array $dirs): object |
54
|
|
|
{ |
55
|
8 |
|
if (empty($dirs)) { |
56
|
1 |
|
throw new Exception("The array for configuration directories can not be empty."); |
57
|
|
|
} |
58
|
|
|
|
59
|
7 |
|
foreach ($dirs as $dir) { |
60
|
7 |
|
if (!(is_readable($dir) && is_dir($dir))) { |
61
|
7 |
|
throw new Exception("The configuration dir '$dir' is not a valid path."); |
62
|
|
|
} |
63
|
|
|
} |
64
|
|
|
|
65
|
6 |
|
$this->dirs = $dirs; |
66
|
6 |
|
return $this; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
|
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* Read configuration from file or directory, if a file, look though all |
73
|
|
|
* base dirs and use the first configuration that is found. A configuration |
74
|
|
|
* item can be combined from a file and a directory, when available in the |
75
|
|
|
* same base directory. |
76
|
|
|
* |
77
|
|
|
* The resulting configuration is always an array, its structure contains |
78
|
|
|
* values from each individual configuration file, like this. |
79
|
|
|
* |
80
|
|
|
* $config = [ |
81
|
|
|
* "file" => filename for file.php, |
82
|
|
|
* "config" => result returned from file.php, |
83
|
|
|
* "items" => [ |
84
|
|
|
* [ |
85
|
|
|
* "file" => filename for dir/file1.php, |
86
|
|
|
* "config" => result returned from dir/file1.php, |
87
|
|
|
* ], |
88
|
|
|
* [ |
89
|
|
|
* "file" => filename for dir/file2.php, |
90
|
|
|
* "config" => result returned from dir/file2.php, |
91
|
|
|
* ], |
92
|
|
|
* ]. |
93
|
|
|
* ] |
94
|
|
|
* |
95
|
|
|
* The configuration files in the directory are loaded per alphabetical |
96
|
|
|
* order. |
97
|
|
|
* |
98
|
|
|
* @param string $item is a name representing the module and is used to |
99
|
|
|
* combine the path to search for. |
100
|
|
|
* |
101
|
|
|
* @throws Exception when configuration item can not be found. |
102
|
|
|
* @throws Exception when $dirs are empty. |
103
|
|
|
* |
104
|
|
|
* @return array with returned value from the loaded configuration. |
105
|
|
|
*/ |
106
|
6 |
|
public function load(string $item) : array |
107
|
|
|
{ |
108
|
6 |
|
if (empty($this->dirs)) { |
109
|
1 |
|
throw new Exception("The array for configuration directories can not be empty."); |
110
|
|
|
} |
111
|
|
|
|
112
|
5 |
|
$found = false; |
113
|
5 |
|
$config = []; |
114
|
5 |
|
$mapping = $this->mapping[$item] ?? null; |
115
|
5 |
|
if ($mapping) { |
116
|
1 |
|
$config["file"] = $mapping; |
117
|
1 |
|
$config["config"] = require $mapping; |
118
|
1 |
|
return $config; |
119
|
|
|
} |
120
|
|
|
|
121
|
4 |
|
foreach ($this->dirs as $dir) { |
122
|
4 |
|
$path = "$dir/$item"; |
123
|
4 |
|
$file = "$path.php"; |
124
|
|
|
|
125
|
|
|
// The configuration is found in ONLY a file |
126
|
4 |
View Code Duplication |
if (is_readable($path) && is_file($path)) { |
|
|
|
|
127
|
|
|
$found = true; |
128
|
|
|
$config["file"] = $path; |
129
|
|
|
$config["config"] = require $path; |
130
|
|
|
break; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
// The configuration is found in a file |
134
|
4 |
View Code Duplication |
if (is_readable($file) && is_file($file)) { |
|
|
|
|
135
|
2 |
|
$found = true; |
136
|
2 |
|
$config["file"] = $file; |
137
|
2 |
|
$config["config"] = require $file; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
// The configuration is found in a directory |
141
|
4 |
|
if (is_readable($path) && is_dir($path)) { |
142
|
2 |
|
$found = true; |
143
|
2 |
|
$config["items"] = $this->loadFromDir($path); |
144
|
|
|
} |
145
|
|
|
|
146
|
4 |
|
if ($found) { |
147
|
4 |
|
break; |
148
|
|
|
} |
149
|
|
|
} |
150
|
|
|
|
151
|
4 |
|
if (!$found) { |
152
|
1 |
|
throw new Exception("Configure item '$item' can not be found."); |
153
|
|
|
} |
154
|
|
|
|
155
|
3 |
|
return $config; |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
|
159
|
|
|
|
160
|
|
|
/** |
161
|
|
|
* Read configuration a directory, loop through all files and add |
162
|
|
|
* them into the $config array as: |
163
|
|
|
* [ |
164
|
|
|
* [ |
165
|
|
|
* "file" => filename for dir/file1.php, |
166
|
|
|
* "config" => result returned from dir/file1.php, |
167
|
|
|
* ], |
168
|
|
|
* [ |
169
|
|
|
* "file" => filename for dir/file2.php, |
170
|
|
|
* "config" => result returned from dir/file2.php, |
171
|
|
|
* ], |
172
|
|
|
* ]. |
173
|
|
|
* |
174
|
|
|
* @param string $path is the path to the directory containing config files. |
175
|
|
|
* |
176
|
|
|
* @return array with configuration for each file. |
177
|
|
|
*/ |
178
|
2 |
|
public function loadFromDir(string $path): array |
179
|
|
|
{ |
180
|
2 |
|
$config = []; |
181
|
2 |
|
foreach (glob("$path/*.php") as $file) { |
182
|
2 |
|
$config[] = [ |
183
|
2 |
|
"file" => $file, |
184
|
2 |
|
"config" => require $file, |
185
|
|
|
]; |
186
|
|
|
} |
187
|
|
|
|
188
|
2 |
|
return $config; |
189
|
|
|
} |
190
|
|
|
} |
191
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.