1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Http\HttplugBundle\DependencyInjection; |
4
|
|
|
|
5
|
|
|
use Symfony\Component\Config\Definition\ArrayNode; |
6
|
|
|
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; |
7
|
|
|
use Symfony\Component\Config\Definition\Builder\TreeBuilder; |
8
|
|
|
use Symfony\Component\Config\Definition\ConfigurationInterface; |
9
|
|
|
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* This class contains the configuration information for the bundle. |
13
|
|
|
* |
14
|
|
|
* This information is solely responsible for how the different configuration |
15
|
|
|
* sections are normalized, and merged. |
16
|
|
|
* |
17
|
|
|
* @author David Buchmann <[email protected]> |
18
|
|
|
* @author Tobias Nyholm <[email protected]> |
19
|
|
|
*/ |
20
|
|
|
class Configuration implements ConfigurationInterface |
21
|
|
|
{ |
22
|
|
|
/** |
23
|
|
|
* {@inheritdoc} |
24
|
|
|
*/ |
25
|
|
|
public function getConfigTreeBuilder() |
26
|
|
|
{ |
27
|
|
|
$treeBuilder = new TreeBuilder(); |
28
|
|
|
$rootNode = $treeBuilder->root('httplug'); |
29
|
|
|
|
30
|
|
|
$this->configureClients($rootNode); |
31
|
|
|
$this->configurePlugins($rootNode); |
32
|
|
|
|
33
|
|
|
$rootNode |
34
|
|
|
->validate() |
35
|
|
|
->ifTrue(function ($v) { |
36
|
|
|
return !empty($v['classes']['client']) |
37
|
|
|
|| !empty($v['classes']['message_factory']) |
38
|
|
|
|| !empty($v['classes']['uri_factory']) |
39
|
|
|
|| !empty($v['classes']['stream_factory']); |
40
|
|
|
}) |
41
|
|
|
->then(function ($v) { |
42
|
|
|
foreach ($v['classes'] as $key => $class) { |
43
|
|
|
if (null !== $class && !class_exists($class)) { |
44
|
|
|
throw new InvalidConfigurationException(sprintf( |
45
|
|
|
'Class %s specified for httplug.classes.%s does not exist.', |
46
|
|
|
$class, |
47
|
|
|
$key |
48
|
|
|
)); |
49
|
|
|
} |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
return $v; |
53
|
|
|
}) |
54
|
|
|
->end() |
55
|
|
|
->children() |
56
|
|
|
->arrayNode('main_alias') |
57
|
|
|
->addDefaultsIfNotSet() |
58
|
|
|
->info('Configure which service the main alias point to.') |
59
|
|
|
->children() |
60
|
|
|
->scalarNode('client')->defaultValue('httplug.client.default')->end() |
61
|
|
|
->scalarNode('message_factory')->defaultValue('httplug.message_factory.default')->end() |
62
|
|
|
->scalarNode('uri_factory')->defaultValue('httplug.uri_factory.default')->end() |
63
|
|
|
->scalarNode('stream_factory')->defaultValue('httplug.stream_factory.default')->end() |
64
|
|
|
->end() |
65
|
|
|
->end() |
66
|
|
|
->arrayNode('classes') |
67
|
|
|
->addDefaultsIfNotSet() |
68
|
|
|
->info('Overwrite a service class instead of using the discovery mechanism.') |
69
|
|
|
->children() |
70
|
|
|
->scalarNode('client')->defaultNull()->end() |
71
|
|
|
->scalarNode('message_factory')->defaultNull()->end() |
72
|
|
|
->scalarNode('uri_factory')->defaultNull()->end() |
73
|
|
|
->scalarNode('stream_factory')->defaultNull()->end() |
74
|
|
|
->end() |
75
|
|
|
->end() |
76
|
|
|
->arrayNode('toolbar') |
77
|
|
|
->addDefaultsIfNotSet() |
78
|
|
|
->info('Extend the debug profiler with inforation about requests.') |
79
|
|
|
->children() |
80
|
|
|
->enumNode('enabled') |
81
|
|
|
->info('If "auto" (default), the toolbar is activated when kernel.debug is true. You can force the toolbar on and off by changing this option.') |
82
|
|
|
->values([true, false, 'auto']) |
83
|
|
|
->defaultValue('auto') |
84
|
|
|
->end() |
85
|
|
|
->scalarNode('formatter')->defaultNull()->end() |
86
|
|
|
->end() |
87
|
|
|
->end() |
88
|
|
|
->end(); |
89
|
|
|
|
90
|
|
|
return $treeBuilder; |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
protected function configureClients(ArrayNodeDefinition $root) |
94
|
|
|
{ |
95
|
|
|
$root->children() |
96
|
|
|
->arrayNode('clients') |
97
|
|
|
->useAttributeAsKey('name') |
98
|
|
|
->prototype('array') |
99
|
|
|
->children() |
100
|
|
|
->scalarNode('factory') |
101
|
|
|
->isRequired() |
102
|
|
|
->cannotBeEmpty() |
103
|
|
|
->info('The service id of a factory to use when creating the adapter.') |
104
|
|
|
->end() |
105
|
|
|
->arrayNode('plugins') |
106
|
|
|
->info('A list of service ids of plugins. The order is important.') |
107
|
|
|
->prototype('scalar')->end() |
108
|
|
|
->end() |
109
|
|
|
->variableNode('config')->defaultValue([])->end() |
110
|
|
|
->end() |
111
|
|
|
->end(); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* @param ArrayNodeDefinition $root |
116
|
|
|
*/ |
117
|
|
|
protected function configurePlugins(ArrayNodeDefinition $root) |
118
|
|
|
{ |
119
|
|
|
$root->children() |
120
|
|
|
->arrayNode('plugins') |
121
|
|
|
->addDefaultsIfNotSet() |
122
|
|
|
->children() |
123
|
|
|
->append($this->addAuthenticationPluiginNode()) |
124
|
|
|
|
125
|
|
|
->arrayNode('cache') |
126
|
|
|
->canBeEnabled() |
127
|
|
|
->addDefaultsIfNotSet() |
128
|
|
|
->children() |
129
|
|
|
->scalarNode('cache_pool') |
130
|
|
|
->info('This must be a service id to a service implementing Psr\Cache\CacheItemPoolInterface') |
131
|
|
|
->isRequired() |
132
|
|
|
->cannotBeEmpty() |
133
|
|
|
->end() |
134
|
|
|
->scalarNode('stream_factory') |
135
|
|
|
->info('This must be a service id to a service implementing Http\Message\StreamFactory') |
136
|
|
|
->defaultValue('httplug.stream_factory') |
137
|
|
|
->cannotBeEmpty() |
138
|
|
|
->end() |
139
|
|
|
->arrayNode('config') |
140
|
|
|
->addDefaultsIfNotSet() |
141
|
|
|
->children() |
142
|
|
|
->scalarNode('default_ttl')->defaultNull()->end() |
143
|
|
|
->scalarNode('respect_cache_headers')->defaultTrue()->end() |
144
|
|
|
->end() |
145
|
|
|
->end() |
146
|
|
|
->end() |
147
|
|
|
->end() // End cache plugin |
148
|
|
|
|
149
|
|
|
->arrayNode('cookie') |
150
|
|
|
->canBeEnabled() |
151
|
|
|
->children() |
152
|
|
|
->scalarNode('cookie_jar') |
153
|
|
|
->info('This must be a service id to a service implementing Http\Message\CookieJar') |
154
|
|
|
->isRequired() |
155
|
|
|
->cannotBeEmpty() |
156
|
|
|
->end() |
157
|
|
|
->end() |
158
|
|
|
->end() // End cookie plugin |
159
|
|
|
|
160
|
|
|
->arrayNode('decoder') |
161
|
|
|
->canBeDisabled() |
162
|
|
|
->addDefaultsIfNotSet() |
163
|
|
|
->children() |
164
|
|
|
->scalarNode('use_content_encoding')->defaultTrue()->end() |
165
|
|
|
->end() |
166
|
|
|
->end() // End decoder plugin |
167
|
|
|
|
168
|
|
|
->arrayNode('history') |
169
|
|
|
->canBeEnabled() |
170
|
|
|
->children() |
171
|
|
|
->scalarNode('journal') |
172
|
|
|
->info('This must be a service id to a service implementing Http\Client\Plugin\Journal') |
173
|
|
|
->isRequired() |
174
|
|
|
->cannotBeEmpty() |
175
|
|
|
->end() |
176
|
|
|
->end() |
177
|
|
|
->end() // End history plugin |
178
|
|
|
|
179
|
|
|
->arrayNode('logger') |
180
|
|
|
->canBeDisabled() |
181
|
|
|
->addDefaultsIfNotSet() |
182
|
|
|
->children() |
183
|
|
|
->scalarNode('logger') |
184
|
|
|
->info('This must be a service id to a service implementing Psr\Log\LoggerInterface') |
185
|
|
|
->defaultValue('logger') |
186
|
|
|
->cannotBeEmpty() |
187
|
|
|
->end() |
188
|
|
|
->scalarNode('formatter') |
189
|
|
|
->info('This must be a service id to a service implementing Http\Message\Formatter') |
190
|
|
|
->defaultNull() |
191
|
|
|
->end() |
192
|
|
|
->end() |
193
|
|
|
->end() // End logger plugin |
194
|
|
|
|
195
|
|
|
->arrayNode('redirect') |
196
|
|
|
->canBeDisabled() |
197
|
|
|
->addDefaultsIfNotSet() |
198
|
|
|
->children() |
199
|
|
|
->scalarNode('preserve_header')->defaultTrue()->end() |
200
|
|
|
->scalarNode('use_default_for_multiple')->defaultTrue()->end() |
201
|
|
|
->end() |
202
|
|
|
->end() // End redirect plugin |
203
|
|
|
|
204
|
|
|
->arrayNode('retry') |
205
|
|
|
->canBeDisabled() |
206
|
|
|
->addDefaultsIfNotSet() |
207
|
|
|
->children() |
208
|
|
|
->scalarNode('retry')->defaultValue(1)->end() |
209
|
|
|
->end() |
210
|
|
|
->end() // End retry plugin |
211
|
|
|
|
212
|
|
|
->arrayNode('stopwatch') |
213
|
|
|
->canBeDisabled() |
214
|
|
|
->addDefaultsIfNotSet() |
215
|
|
|
->children() |
216
|
|
|
->scalarNode('stopwatch') |
217
|
|
|
->info('This must be a service id to a service extending Symfony\Component\Stopwatch\Stopwatch') |
218
|
|
|
->defaultValue('debug.stopwatch') |
219
|
|
|
->cannotBeEmpty() |
220
|
|
|
->end() |
221
|
|
|
->end() |
222
|
|
|
->end() // End stopwatch plugin |
223
|
|
|
|
224
|
|
|
->end() |
225
|
|
|
->end() |
226
|
|
|
->end(); |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
/** |
230
|
|
|
* Add configuration for authentication plugin |
231
|
|
|
* |
232
|
|
|
* @return ArrayNodeDefinition|\Symfony\Component\Config\Definition\Builder\NodeDefinition |
233
|
|
|
*/ |
234
|
|
|
private function addAuthenticationPluiginNode() |
235
|
|
|
{ |
236
|
|
|
$builder = new TreeBuilder(); |
237
|
|
|
$node = $builder->root('authentication'); |
238
|
|
|
$node |
239
|
|
|
->useAttributeAsKey('name') |
240
|
|
|
->prototype('array') |
241
|
|
|
->validate() |
242
|
|
|
->always() |
243
|
|
|
->then(function($config) { |
244
|
|
|
switch ($config['type']) { |
245
|
|
View Code Duplication |
case 'basic': |
|
|
|
|
246
|
|
|
if (empty($config['username']) || empty($config['password'])) { |
247
|
|
|
throw new InvalidConfigurationException('Authentication "basic" requires both "username" and "password".'); |
248
|
|
|
} |
249
|
|
|
break; |
250
|
|
|
case 'bearer': |
251
|
|
|
if (empty($config['bearer'])) { |
252
|
|
|
throw new InvalidConfigurationException('Authentication "bearer" requires a "token".'); |
253
|
|
|
} |
254
|
|
|
break; |
255
|
|
|
case 'service': |
256
|
|
|
if (empty($config['service'])) { |
257
|
|
|
throw new InvalidConfigurationException('Authentication "service" requires a "service".'); |
258
|
|
|
} |
259
|
|
|
break; |
260
|
|
View Code Duplication |
case 'wsse': |
|
|
|
|
261
|
|
|
if (empty($config['username']) || empty($config['password'])) { |
262
|
|
|
throw new InvalidConfigurationException('Authentication "wsse" requires both "username" and "password".'); |
263
|
|
|
} |
264
|
|
|
break; |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
return $config; |
268
|
|
|
}) |
269
|
|
|
->end() |
270
|
|
|
->children() |
271
|
|
|
->enumNode('type') |
272
|
|
|
->values(['basic', 'bearer', 'wsse', 'service']) |
273
|
|
|
->isRequired() |
274
|
|
|
->cannotBeEmpty() |
275
|
|
|
->end() |
276
|
|
|
->scalarNode('username')->end() |
277
|
|
|
->scalarNode('password')->end() |
278
|
|
|
->scalarNode('token')->end() |
279
|
|
|
->scalarNode('service')->end() |
280
|
|
|
->end() |
281
|
|
|
->end() |
282
|
|
|
->end(); // End authentication plugin |
283
|
|
|
|
284
|
|
|
return $node; |
285
|
|
|
} |
286
|
|
|
} |
287
|
|
|
|
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.