1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace EightPoints\Bundle\GuzzleBundle\DependencyInjection; |
4
|
|
|
|
5
|
|
|
use function method_exists; |
6
|
|
|
use EightPoints\Bundle\GuzzleBundle\Log\Logger; |
7
|
|
|
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; |
8
|
|
|
use Symfony\Component\Config\Definition\Builder\TreeBuilder; |
9
|
|
|
use Symfony\Component\Config\Definition\ConfigurationInterface; |
10
|
|
|
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; |
11
|
|
|
|
12
|
|
|
class Configuration implements ConfigurationInterface |
13
|
|
|
{ |
14
|
|
|
/** |
15
|
|
|
* @var string |
16
|
|
|
*/ |
17
|
|
|
protected $alias; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* @var boolean |
21
|
|
|
*/ |
22
|
|
|
protected $debug; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* @var \EightPoints\Bundle\GuzzleBundle\PluginInterface[] |
26
|
|
|
*/ |
27
|
|
|
protected $plugins; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @param string $alias |
31
|
|
|
* @param boolean $debug |
32
|
|
|
* @param array $plugins |
33
|
|
|
*/ |
34
|
|
|
public function __construct(string $alias, bool $debug = false, array $plugins = []) |
35
|
|
|
{ |
36
|
|
|
$this->alias = $alias; |
37
|
|
|
$this->debug = $debug; |
38
|
|
|
$this->plugins = $plugins; |
39
|
|
|
} |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* Generates the configuration tree builder |
43
|
|
|
* |
44
|
|
|
* @throws \RuntimeException |
45
|
|
|
* |
46
|
|
|
* @return \Symfony\Component\Config\Definition\Builder\TreeBuilder |
47
|
|
|
*/ |
48
|
|
|
public function getConfigTreeBuilder() : TreeBuilder |
49
|
|
|
{ |
50
|
|
|
$builder = new TreeBuilder($this->alias); |
51
|
|
|
|
52
|
|
|
if (method_exists($builder, 'getRootNode')) { |
53
|
|
|
$root = $builder->getRootNode(); |
54
|
|
|
} else { |
55
|
|
|
// BC layer for symfony/config 4.1 and older |
56
|
|
|
$root = $builder->root($this->alias); |
|
|
|
|
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
$root |
60
|
|
|
->children() |
61
|
|
|
->append($this->createClientsNode()) |
62
|
|
|
->booleanNode('logging')->defaultValue($this->debug)->end() |
63
|
|
|
->booleanNode('profiling')->defaultValue($this->debug)->end() |
64
|
|
|
->integerNode('slow_response_time')->defaultValue(0)->end() |
65
|
|
|
->end() |
66
|
|
|
->end(); |
67
|
|
|
|
68
|
|
|
return $builder; |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* Create Clients Configuration |
73
|
|
|
* |
74
|
|
|
* @throws \RuntimeException |
75
|
|
|
* |
76
|
|
|
* @return \Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition |
77
|
|
|
*/ |
78
|
|
|
private function createClientsNode() : ArrayNodeDefinition |
79
|
|
|
{ |
80
|
|
|
$builder = new TreeBuilder('clients'); |
81
|
|
|
|
82
|
|
|
/** @var \Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition $node */ |
83
|
|
|
if (method_exists($builder, 'getRootNode')) { |
84
|
|
|
$node = $builder->getRootNode(); |
85
|
|
|
} else { |
86
|
|
|
// BC layer for symfony/config 4.1 and older |
87
|
|
|
$node = $builder->root('clients'); |
|
|
|
|
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** @var \Symfony\Component\Config\Definition\Builder\NodeBuilder $nodeChildren */ |
91
|
|
|
$nodeChildren = $node->useAttributeAsKey('name') |
|
|
|
|
92
|
|
|
->prototype('array') |
93
|
|
|
->children(); |
94
|
|
|
|
95
|
|
|
$nodeChildren->scalarNode('class')->defaultValue('%eight_points_guzzle.http_client.class%')->end() |
96
|
|
|
->scalarNode('base_url') |
|
|
|
|
97
|
|
|
->defaultValue(null) |
98
|
|
|
->validate() |
99
|
|
|
->ifTrue(function ($v) { |
100
|
|
|
return !is_string($v); |
101
|
|
|
}) |
102
|
|
|
->thenInvalid('base_url can be: string') |
103
|
|
|
->end() |
104
|
|
|
->end() |
105
|
|
|
->booleanNode('lazy')->defaultValue(false)->end() |
106
|
|
|
->integerNode('logging') |
107
|
|
|
->defaultValue(null) |
108
|
|
|
->beforeNormalization() |
109
|
|
|
->always(function ($value): int { |
110
|
|
|
if ($value === 1 || $value === true) { |
111
|
|
|
return Logger::LOG_MODE_REQUEST_AND_RESPONSE; |
112
|
|
|
} elseif ($value === 0 || $value === false) { |
113
|
|
|
return Logger::LOG_MODE_NONE; |
114
|
|
|
} else { |
115
|
|
|
return constant(Logger::class .'::LOG_MODE_' . strtoupper($value)); |
116
|
|
|
} |
117
|
|
|
}) |
118
|
|
|
->end() |
119
|
|
|
->end() |
120
|
|
|
->scalarNode('handler') |
121
|
|
|
->defaultValue(null) |
122
|
|
|
->validate() |
123
|
|
|
->ifTrue(function ($v) { |
124
|
|
|
return $v !== null && (!is_string($v) || !class_exists($v)); |
125
|
|
|
}) |
126
|
|
|
->thenInvalid('handler must be a valid FQCN for a loaded class') |
127
|
|
|
->end() |
128
|
|
|
->end() |
129
|
|
|
->arrayNode('options') |
130
|
|
|
->validate() |
131
|
|
|
->ifTrue(function ($options) { |
132
|
|
|
return count($options['form_params']) && count($options['multipart']); |
133
|
|
|
}) |
134
|
|
|
->thenInvalid('You cannot use form_params and multipart at the same time.') |
135
|
|
|
->end() |
136
|
|
|
->children() |
137
|
|
|
->arrayNode('headers') |
138
|
|
|
->useAttributeAsKey('name') |
139
|
|
|
->normalizeKeys(false) |
140
|
|
|
->prototype('scalar')->end() |
141
|
|
|
->end() |
142
|
|
|
->variableNode('allow_redirects') |
143
|
|
|
->validate() |
144
|
|
|
->ifTrue(function ($v) { |
145
|
|
|
return !is_array($v) && !is_bool($v); |
146
|
|
|
}) |
147
|
|
|
->thenInvalid('allow_redirects can be: bool or array') |
148
|
|
|
->end() |
149
|
|
|
->end() |
150
|
|
|
->variableNode('auth') |
151
|
|
|
->validate() |
152
|
|
|
->ifTrue(function ($v) { |
153
|
|
|
return !is_array($v) && !is_string($v); |
154
|
|
|
}) |
155
|
|
|
->thenInvalid('auth can be: string or array') |
156
|
|
|
->end() |
157
|
|
|
->end() |
158
|
|
|
->variableNode('query') |
159
|
|
|
->validate() |
160
|
|
|
->ifTrue(function ($v) { |
161
|
|
|
return !is_string($v) && !is_array($v); |
162
|
|
|
}) |
163
|
|
|
->thenInvalid('query can be: string or array') |
164
|
|
|
->end() |
165
|
|
|
->end() |
166
|
|
|
->arrayNode('curl') |
167
|
|
|
->beforeNormalization() |
168
|
|
|
->ifArray() |
169
|
|
|
->then(function (array $curlOptions) { |
170
|
|
|
$result = []; |
171
|
|
|
|
172
|
|
|
foreach ($curlOptions as $key => $value) { |
173
|
|
|
$optionName = 'CURLOPT_' . strtoupper($key); |
174
|
|
|
|
175
|
|
|
if (!defined($optionName)) { |
176
|
|
|
throw new InvalidConfigurationException(sprintf( |
177
|
|
|
'Invalid curl option in eight_points_guzzle: %s. ' . |
178
|
|
|
'Ex: use sslversion for CURLOPT_SSLVERSION option. ' . PHP_EOL . |
179
|
|
|
'See all available options: http://php.net/manual/en/function.curl-setopt.php', |
180
|
|
|
$key |
181
|
|
|
)); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
$result[constant($optionName)] = $value; |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
return $result; |
188
|
|
|
}) |
189
|
|
|
->end() |
190
|
|
|
->prototype('scalar') |
191
|
|
|
->end() |
192
|
|
|
->end() |
193
|
|
|
->variableNode('cert') |
194
|
|
|
->validate() |
195
|
|
|
->ifTrue(function ($v) { |
196
|
|
|
return !is_string($v) && (!is_array($v) || count($v) !== 2); |
197
|
|
|
}) |
198
|
|
|
->thenInvalid('cert can be: string or array with two entries (path and password)') |
199
|
|
|
->end() |
200
|
|
|
->end() |
201
|
|
|
->scalarNode('connect_timeout') |
202
|
|
|
->beforeNormalization() |
203
|
|
|
->always(function ($v) { |
204
|
|
|
return is_numeric($v) ? (float) $v : $v; |
205
|
|
|
}) |
206
|
|
|
->end() |
207
|
|
|
->validate() |
208
|
|
|
->ifTrue(function ($v) { |
209
|
|
|
return !is_float($v) && !(is_string($v) && strpos($v, 'env_') === 0); |
210
|
|
|
}) |
211
|
|
|
->thenInvalid('connect_timeout can be: float') |
212
|
|
|
->end() |
213
|
|
|
->end() |
214
|
|
|
->booleanNode('debug')->end() |
215
|
|
|
->variableNode('decode_content') |
216
|
|
|
->validate() |
217
|
|
|
->ifTrue(function ($v) { |
218
|
|
|
return !is_string($v) && !is_bool($v); |
219
|
|
|
}) |
220
|
|
|
->thenInvalid('decode_content can be: bool or string (gzip, compress, deflate, etc...)') |
221
|
|
|
->end() |
222
|
|
|
->end() |
223
|
|
|
->floatNode('delay')->end() |
224
|
|
|
->arrayNode('form_params') |
225
|
|
|
->useAttributeAsKey('name') |
226
|
|
|
->prototype('variable')->end() |
227
|
|
|
->end() |
228
|
|
|
->arrayNode('multipart') |
229
|
|
|
->prototype('variable')->end() |
230
|
|
|
->end() |
231
|
|
|
->scalarNode('sink') |
232
|
|
|
->validate() |
233
|
|
|
->ifTrue(function ($v) { |
234
|
|
|
return !is_string($v); |
235
|
|
|
}) |
236
|
|
|
->thenInvalid('sink can be: string') |
237
|
|
|
->end() |
238
|
|
|
->end() |
239
|
|
|
->booleanNode('http_errors')->end() |
240
|
|
|
->variableNode('expect') |
241
|
|
|
->validate() |
242
|
|
|
->ifTrue(function ($v) { |
243
|
|
|
return !is_bool($v) && !is_int($v); |
244
|
|
|
}) |
245
|
|
|
->thenInvalid('expect can be: bool or int') |
246
|
|
|
->end() |
247
|
|
|
->end() |
248
|
|
|
->variableNode('ssl_key') |
249
|
|
|
->validate() |
250
|
|
|
->ifTrue(function ($v) { |
251
|
|
|
return !is_string($v) && (!is_array($v) || count($v) !== 2); |
252
|
|
|
}) |
253
|
|
|
->thenInvalid('ssl_key can be: string or array with two entries (path and password)') |
254
|
|
|
->end() |
255
|
|
|
->end() |
256
|
|
|
->booleanNode('stream')->end() |
257
|
|
|
->booleanNode('synchronous')->end() |
258
|
|
|
->scalarNode('read_timeout') |
259
|
|
|
->beforeNormalization() |
260
|
|
|
->always(function ($v) { |
261
|
|
|
return is_numeric($v) ? (float) $v : $v; |
262
|
|
|
}) |
263
|
|
|
->end() |
264
|
|
|
->validate() |
265
|
|
|
->ifTrue(function ($v) { |
266
|
|
|
return !is_float($v) && !(is_string($v) && strpos($v, 'env_') === 0); |
267
|
|
|
}) |
268
|
|
|
->thenInvalid('read_timeout can be: float') |
269
|
|
|
->end() |
270
|
|
|
->end() |
271
|
|
|
->scalarNode('timeout') |
272
|
|
|
->beforeNormalization() |
273
|
|
|
->always(function ($v) { |
274
|
|
|
return is_numeric($v) ? (float) $v : $v; |
275
|
|
|
}) |
276
|
|
|
->end() |
277
|
|
|
->validate() |
278
|
|
|
->ifTrue(function ($v) { |
279
|
|
|
return !is_float($v) && !(is_string($v) && strpos($v, 'env_') === 0); |
280
|
|
|
}) |
281
|
|
|
->thenInvalid('timeout can be: float') |
282
|
|
|
->end() |
283
|
|
|
->end() |
284
|
|
|
->variableNode('verify') |
285
|
|
|
->validate() |
286
|
|
|
->ifTrue(function ($v) { |
287
|
|
|
return !is_bool($v) && !is_string($v); |
288
|
|
|
}) |
289
|
|
|
->thenInvalid('verify can be: bool or string') |
290
|
|
|
->end() |
291
|
|
|
->end() |
292
|
|
|
->booleanNode('cookies')->end() |
293
|
|
|
->arrayNode('proxy') |
294
|
|
|
->beforeNormalization() |
295
|
|
|
->ifString() |
296
|
|
|
->then(function($v) { return ['http'=> $v]; }) |
297
|
|
|
->end() |
298
|
|
|
->validate() |
299
|
|
|
->always(function($v) { |
300
|
|
|
if (empty($v['no'])) { |
301
|
|
|
unset($v['no']); |
302
|
|
|
} |
303
|
|
|
return $v; |
304
|
|
|
}) |
305
|
|
|
->end() |
306
|
|
|
->children() |
307
|
|
|
->scalarNode('http')->end() |
308
|
|
|
->scalarNode('https')->end() |
309
|
|
|
->arrayNode('no') |
310
|
|
|
->prototype('scalar')->end() |
311
|
|
|
->end() |
312
|
|
|
->end() |
313
|
|
|
->end() |
314
|
|
|
->scalarNode('version') |
315
|
|
|
->validate() |
316
|
|
|
->ifTrue(function ($v) { |
317
|
|
|
return !is_string($v) && !is_float($v); |
318
|
|
|
}) |
319
|
|
|
->thenInvalid('version can be: string or float') |
320
|
|
|
->end() |
321
|
|
|
->end() |
322
|
|
|
->end() |
323
|
|
|
->end(); |
324
|
|
|
|
325
|
|
|
$pluginsNode = $nodeChildren->arrayNode('plugin')->addDefaultsIfNotSet(); |
326
|
|
|
|
327
|
|
|
foreach ($this->plugins as $plugin) { |
328
|
|
|
$pluginNode = new ArrayNodeDefinition($plugin->getPluginName()); |
329
|
|
|
|
330
|
|
|
$plugin->addConfiguration($pluginNode); |
331
|
|
|
|
332
|
|
|
$pluginsNode->children()->append($pluginNode); |
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
return $node; |
|
|
|
|
336
|
|
|
} |
337
|
|
|
} |
338
|
|
|
|
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.