1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace TomPHP\ContainerConfigurator; |
4
|
|
|
|
5
|
|
|
use Assert\Assertion; |
6
|
|
|
use InvalidArgumentException; |
7
|
|
|
use TomPHP\ContainerConfigurator\Exception\NoMatchingFilesException; |
8
|
|
|
use TomPHP\ContainerConfigurator\Exception\UnknownSettingException; |
9
|
|
|
|
10
|
|
|
final class Configurator |
11
|
|
|
{ |
12
|
|
|
const SETTING_PREFIX = 'config_prefix'; |
13
|
|
|
const SETTING_SEPARATOR = 'config_separator'; |
14
|
|
|
const SETTING_SERVICES_KEY = 'services_key'; |
15
|
|
|
const SETTING_INFLECTORS_KEY = 'inflectors_key'; |
16
|
|
|
const SETTING_DEFAULT_SINGLETON_SERVICES = 'default_singleton_services'; |
17
|
|
|
|
18
|
|
|
const FILE_READERS = [ |
19
|
|
|
'.json' => FileReader\JSONFileReader::class, |
20
|
|
|
'.php' => FileReader\PHPFileReader::class, |
21
|
|
|
'.yaml' => FileReader\YAMLFileReader::class, |
22
|
|
|
'.yml' => FileReader\YAMLFileReader::class, |
23
|
|
|
]; |
24
|
|
|
|
25
|
|
|
const CONTAINER_ADAPTERS = [ |
26
|
|
|
\League\Container\Container::class => League\LeagueContainerAdapter::class, |
27
|
|
|
\Pimple\Container::class => Pimple\PimpleContainerAdapter::class, |
28
|
|
|
]; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* @var ApplicationConfig |
32
|
|
|
*/ |
33
|
|
|
private $config; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @var FileReader\ReaderFactory |
37
|
|
|
*/ |
38
|
|
|
private $readerFactory; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @var array |
42
|
|
|
*/ |
43
|
|
|
private $settings = [ |
44
|
|
|
self::SETTING_PREFIX => 'config', |
45
|
|
|
self::SETTING_SEPARATOR => '.', |
46
|
|
|
self::SETTING_SERVICES_KEY => 'di.services', |
47
|
|
|
self::SETTING_INFLECTORS_KEY => 'di.inflectors', |
48
|
|
|
self::SETTING_DEFAULT_SINGLETON_SERVICES => false, |
49
|
|
|
]; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* @var string |
53
|
|
|
*/ |
54
|
|
|
private static $containerIdentifier; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* @api |
58
|
|
|
* |
59
|
|
|
* @return Configurator |
60
|
|
|
*/ |
61
|
|
|
public static function apply() |
62
|
|
|
{ |
63
|
|
|
return new self(); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
private function __construct() |
67
|
|
|
{ |
68
|
|
|
$this->config = new ApplicationConfig([]); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* @api |
73
|
|
|
* |
74
|
|
|
* @return string |
75
|
|
|
*/ |
76
|
|
|
public static function container() |
77
|
|
|
{ |
78
|
|
|
if (!self::$containerIdentifier) { |
79
|
|
|
self::$containerIdentifier = uniqid(__CLASS__ . '::CONTAINER_ID::'); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
return self::$containerIdentifier; |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* @api |
87
|
|
|
* |
88
|
|
|
* @param array $config |
89
|
|
|
* |
90
|
|
|
* @return Configurator |
91
|
|
|
*/ |
92
|
|
|
public function configFromArray(array $config) |
93
|
|
|
{ |
94
|
|
|
$this->config->merge($config); |
95
|
|
|
|
96
|
|
|
return $this; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* @api |
101
|
|
|
* |
102
|
|
|
* @param string $filename |
103
|
|
|
* |
104
|
|
|
* @return Configurator |
105
|
|
|
*/ |
106
|
|
|
public function configFromFile($filename) |
107
|
|
|
{ |
108
|
|
|
Assertion::file($filename); |
109
|
|
|
|
110
|
|
|
$this->readFileAndMergeConfig($filename); |
111
|
|
|
|
112
|
|
|
return $this; |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* @api |
117
|
|
|
* |
118
|
|
|
* @param string $pattern |
119
|
|
|
* |
120
|
|
|
* @throws NoMatchingFilesException |
121
|
|
|
* @throws InvalidArgumentException |
122
|
|
|
* |
123
|
|
|
* @return Configurator |
124
|
|
|
*/ |
125
|
|
|
public function configFromFiles($pattern) |
126
|
|
|
{ |
127
|
|
|
Assertion::string($pattern); |
128
|
|
|
|
129
|
|
|
$locator = new FileReader\FileLocator(); |
130
|
|
|
|
131
|
|
|
$files = $locator->locate($pattern); |
132
|
|
|
|
133
|
|
|
if (count($files) === 0) { |
134
|
|
|
throw NoMatchingFilesException::fromPattern($pattern); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
foreach ($files as $filename) { |
138
|
|
|
$this->readFileAndMergeConfig($filename); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
return $this; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* @api |
146
|
|
|
* |
147
|
|
|
* @param string $name |
148
|
|
|
* @param mixed $value |
149
|
|
|
* |
150
|
|
|
* @throws UnknownSettingException |
151
|
|
|
* @throws InvalidArgumentException |
152
|
|
|
* |
153
|
|
|
* @return Configurator |
154
|
|
|
*/ |
155
|
|
|
public function withSetting($name, $value) |
156
|
|
|
{ |
157
|
|
|
Assertion::string($name); |
158
|
|
|
Assertion::scalar($value); |
159
|
|
|
|
160
|
|
|
if (!array_key_exists($name, $this->settings)) { |
161
|
|
|
throw UnknownSettingException::fromSetting($name, array_keys($this->settings)); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
$this->settings[$name] = $value; |
165
|
|
|
|
166
|
|
|
return $this; |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
/** |
170
|
|
|
* @api |
171
|
|
|
* |
172
|
|
|
* @param object $container |
173
|
|
|
* |
174
|
|
|
* @return void |
175
|
|
|
*/ |
176
|
|
|
public function to($container) |
177
|
|
|
{ |
178
|
|
|
$this->config->setSeparator($this->settings[self::SETTING_SEPARATOR]); |
179
|
|
|
|
180
|
|
|
$factory = new ContainerAdapterFactory(self::CONTAINER_ADAPTERS); |
181
|
|
|
|
182
|
|
|
$configurator = $factory->create($container); |
183
|
|
|
|
184
|
|
|
$configurator->addApplicationConfig($this->config, $this->settings[self::SETTING_PREFIX]); |
185
|
|
|
|
186
|
|
View Code Duplication |
if (isset($this->config[$this->settings[self::SETTING_SERVICES_KEY]])) { |
|
|
|
|
187
|
|
|
$configurator->addServiceConfig(new ServiceConfig( |
188
|
|
|
$this->config[$this->settings[self::SETTING_SERVICES_KEY]], |
189
|
|
|
$this->settings[self::SETTING_DEFAULT_SINGLETON_SERVICES] |
190
|
|
|
)); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
View Code Duplication |
if (isset($this->config[$this->settings[self::SETTING_INFLECTORS_KEY]])) { |
|
|
|
|
194
|
|
|
$configurator->addInflectorConfig(new InflectorConfig( |
195
|
|
|
$this->config[$this->settings[self::SETTING_INFLECTORS_KEY]] |
196
|
|
|
)); |
197
|
|
|
} |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
/** |
201
|
|
|
* @param string $filename |
202
|
|
|
* |
203
|
|
|
* @return void |
204
|
|
|
*/ |
205
|
|
|
private function readFileAndMergeConfig($filename) |
206
|
|
|
{ |
207
|
|
|
$reader = $this->getReaderFor($filename); |
208
|
|
|
|
209
|
|
|
$this->config->merge($reader->read($filename)); |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* @param string $filename |
214
|
|
|
* |
215
|
|
|
* @return FileReader\FileReader |
216
|
|
|
*/ |
217
|
|
|
private function getReaderFor($filename) |
218
|
|
|
{ |
219
|
|
|
if (!$this->readerFactory) { |
220
|
|
|
$this->readerFactory = new FileReader\ReaderFactory(self::FILE_READERS); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
return $this->readerFactory->create($filename); |
224
|
|
|
} |
225
|
|
|
} |
226
|
|
|
|
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.