Passed
Push — master ( 8bd912...d93388 )
by Alan
06:58 queued 02:20
created

Bundle/DependencyInjection/Configuration.php (6 issues)

1
<?php
2
3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection;
15
16
use ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\DocumentMetadata;
17
use ApiPlatform\Core\Exception\FilterValidationException;
18
use ApiPlatform\Core\Exception\InvalidArgumentException;
19
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
20
use Doctrine\Bundle\MongoDBBundle\DoctrineMongoDBBundle;
21
use Doctrine\ORM\OptimisticLockException;
22
use Doctrine\ORM\Version as DoctrineOrmVersion;
23
use Elasticsearch\Client as ElasticsearchClient;
24
use FOS\UserBundle\FOSUserBundle;
25
use GraphQL\GraphQL;
26
use Symfony\Bundle\FullStack;
0 ignored issues
show
The type Symfony\Bundle\FullStack was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
27
use Symfony\Bundle\MercureBundle\MercureBundle;
28
use Symfony\Bundle\TwigBundle\TwigBundle;
29
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
30
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
31
use Symfony\Component\Config\Definition\ConfigurationInterface;
32
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
33
use Symfony\Component\HttpFoundation\Response;
34
use Symfony\Component\Messenger\MessageBusInterface;
35
use Symfony\Component\Serializer\Exception\ExceptionInterface as SerializerExceptionInterface;
36
37
/**
38
 * The configuration of the bundle.
39
 *
40
 * @author Kévin Dunglas <[email protected]>
41
 * @author Baptiste Meyer <[email protected]>
42
 */
43
final class Configuration implements ConfigurationInterface
44
{
45
    /**
46
     * {@inheritdoc}
47
     */
48
    public function getConfigTreeBuilder()
49
    {
50
        if (method_exists(TreeBuilder::class, 'getRootNode')) {
51
            $treeBuilder = new TreeBuilder('api_platform');
52
            $rootNode = $treeBuilder->getRootNode();
53
        } else {
54
            $treeBuilder = new TreeBuilder();
55
            $rootNode = $treeBuilder->root('api_platform');
0 ignored issues
show
Deprecated Code introduced by
The function Symfony\Component\Config...der\TreeBuilder::root() has been deprecated: since Symfony 4.3, pass the root name to the constructor instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

55
            $rootNode = /** @scrutinizer ignore-deprecated */ $treeBuilder->root('api_platform');

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.

Loading history...
56
        }
57
58
        $rootNode
59
            ->beforeNormalization()
60
                ->ifTrue(static function ($v) {
61
                    return false === ($v['enable_swagger'] ?? null);
62
                })
63
                ->then(static function ($v) {
64
                    $v['swagger']['versions'] = [];
65
66
                    return $v;
67
                })
68
            ->end()
69
            ->children()
70
                ->scalarNode('title')
71
                    ->info('The title of the API.')
72
                    ->cannotBeEmpty()
73
                    ->defaultValue('')
74
                ->end()
75
                ->scalarNode('description')
76
                    ->info('The description of the API.')
77
                    ->cannotBeEmpty()
78
                    ->defaultValue('')
79
                ->end()
80
                ->scalarNode('version')
81
                    ->info('The version of the API.')
82
                    ->cannotBeEmpty()
83
                    ->defaultValue('0.0.0')
84
                ->end()
85
                ->booleanNode('show_webby')->defaultTrue()->info('If true, show Webby on the documentation page')->end()
86
                ->scalarNode('default_operation_path_resolver')
87
                    ->defaultValue('api_platform.operation_path_resolver.underscore')
88
                    ->setDeprecated('The use of the `default_operation_path_resolver` has been deprecated in 2.1 and will be removed in 3.0. Use `path_segment_name_generator` instead.')
89
                    ->info('Specify the default operation path resolver to use for generating resources operations path.')
90
                ->end()
91
                ->scalarNode('name_converter')->defaultNull()->info('Specify a name converter to use.')->end()
92
                ->scalarNode('path_segment_name_generator')->defaultValue('api_platform.path_segment_name_generator.underscore')->info('Specify a path name generator to use.')->end()
93
                ->booleanNode('allow_plain_identifiers')->defaultFalse()->info('Allow plain identifiers, for example "id" instead of "@id" when denormalizing a relation.')->end()
94
                ->arrayNode('validator')
95
                    ->addDefaultsIfNotSet()
96
                    ->children()
97
                        ->variableNode('serialize_payload_fields')->defaultValue([])->info('Enable the serialization of payload fields when a validation error is thrown.')->end()
98
                    ->end()
99
                ->end()
100
                ->arrayNode('eager_loading')
101
                    ->canBeDisabled()
102
                    ->addDefaultsIfNotSet()
103
                    ->children()
104
                        ->booleanNode('fetch_partial')->defaultFalse()->info('Fetch only partial data according to serialization groups. If enabled, Doctrine ORM entities will not work as expected if any of the other fields are used.')->end()
105
                        ->integerNode('max_joins')->defaultValue(30)->info('Max number of joined relations before EagerLoading throws a RuntimeException')->end()
106
                        ->booleanNode('force_eager')->defaultTrue()->info('Force join on every relation. If disabled, it will only join relations having the EAGER fetch mode.')->end()
107
                    ->end()
108
                ->end()
109
                ->booleanNode('enable_fos_user')->defaultValue(class_exists(FOSUserBundle::class))->info('Enable the FOSUserBundle integration.')->end()
110
                ->booleanNode('enable_nelmio_api_doc')
111
                    ->defaultFalse()
112
                    ->setDeprecated('Enabling the NelmioApiDocBundle integration has been deprecated in 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform.')
113
                    ->info('Enable the NelmioApiDocBundle integration.')
114
                ->end()
115
                ->booleanNode('enable_swagger')->defaultTrue()->info('Enable the Swagger documentation and export.')->end()
116
                ->booleanNode('enable_swagger_ui')->defaultValue(class_exists(TwigBundle::class))->info('Enable Swagger UI')->end()
117
                ->booleanNode('enable_re_doc')->defaultValue(class_exists(TwigBundle::class))->info('Enable ReDoc')->end()
118
                ->booleanNode('enable_entrypoint')->defaultTrue()->info('Enable the entrypoint')->end()
119
                ->booleanNode('enable_docs')->defaultTrue()->info('Enable the docs')->end()
120
                ->booleanNode('enable_profiler')->defaultTrue()->info('Enable the data collector and the WebProfilerBundle integration.')->end()
121
                ->arrayNode('collection')
122
                    ->addDefaultsIfNotSet()
123
                    ->children()
124
                        ->scalarNode('exists_parameter_name')->defaultValue('exists')->cannotBeEmpty()->info('The name of the query parameter to filter on nullable field values.')->end()
125
                        ->scalarNode('order')->defaultValue('ASC')->info('The default order of results.')->end() // Default ORDER is required for postgresql and mysql >= 5.7 when using LIMIT/OFFSET request
126
                        ->scalarNode('order_parameter_name')->defaultValue('order')->cannotBeEmpty()->info('The name of the query parameter to order results.')->end()
127
                        ->arrayNode('pagination')
128
                            ->canBeDisabled()
129
                            ->addDefaultsIfNotSet()
130
                            ->children()
131
                                ->booleanNode('enabled')->defaultTrue()->info('To enable or disable pagination for all resource collections by default.')->end()
132
                                ->booleanNode('partial')->defaultFalse()->info('To enable or disable partial pagination for all resource collections by default when pagination is enabled.')->end()
133
                                ->booleanNode('client_enabled')->defaultFalse()->info('To allow the client to enable or disable the pagination.')->end()
134
                                ->booleanNode('client_items_per_page')->defaultFalse()->info('To allow the client to set the number of items per page.')->end()
135
                                ->booleanNode('client_partial')->defaultFalse()->info('To allow the client to enable or disable partial pagination.')->end()
136
                                ->integerNode('items_per_page')->defaultValue(30)->info('The default number of items per page.')->end()
137
                                ->integerNode('maximum_items_per_page')->defaultNull()->info('The maximum number of items per page.')->end()
138
                                ->scalarNode('page_parameter_name')->defaultValue('page')->cannotBeEmpty()->info('The default name of the parameter handling the page number.')->end()
139
                                ->scalarNode('enabled_parameter_name')->defaultValue('pagination')->cannotBeEmpty()->info('The name of the query parameter to enable or disable pagination.')->end()
140
                                ->scalarNode('items_per_page_parameter_name')->defaultValue('itemsPerPage')->cannotBeEmpty()->info('The name of the query parameter to set the number of items per page.')->end()
141
                                ->scalarNode('partial_parameter_name')->defaultValue('partial')->cannotBeEmpty()->info('The name of the query parameter to enable or disable partial pagination.')->end()
142
                            ->end()
143
                        ->end()
144
                    ->end()
145
                ->end()
146
                ->arrayNode('mapping')
147
                    ->addDefaultsIfNotSet()
148
                    ->children()
149
                        ->arrayNode('paths')
150
                            ->prototype('scalar')->end()
151
                        ->end()
152
                    ->end()
153
                ->end()
154
                ->arrayNode('resource_class_directories')
155
                    ->prototype('scalar')->end()
156
                ->end()
157
            ->end();
158
159
        $this->addDoctrineOrmSection($rootNode);
160
        $this->addDoctrineMongoDbOdmSection($rootNode);
161
        $this->addOAuthSection($rootNode);
162
        $this->addGraphQlSection($rootNode);
163
        $this->addSwaggerSection($rootNode);
164
        $this->addHttpCacheSection($rootNode);
165
        $this->addMercureSection($rootNode);
166
        $this->addMessengerSection($rootNode);
167
        $this->addElasticsearchSection($rootNode);
168
169
        $this->addExceptionToStatusSection($rootNode);
170
171
        $this->addFormatSection($rootNode, 'formats', [
172
            'jsonld' => ['mime_types' => ['application/ld+json']],
173
            'json' => ['mime_types' => ['application/json']], // Swagger support
174
            'html' => ['mime_types' => ['text/html']], // Swagger UI support
175
        ]);
176
        $this->addFormatSection($rootNode, 'patch_formats', []);
177
        $this->addFormatSection($rootNode, 'error_formats', [
178
            'jsonproblem' => ['mime_types' => ['application/problem+json']],
179
            'jsonld' => ['mime_types' => ['application/ld+json']],
180
        ]);
181
182
        return $treeBuilder;
183
    }
184
185
    private function addDoctrineOrmSection(ArrayNodeDefinition $rootNode): void
186
    {
187
        $rootNode
188
            ->children()
189
                ->arrayNode('doctrine')
190
                    ->{class_exists(DoctrineBundle::class) && class_exists(DoctrineOrmVersion::class) ? 'canBeDisabled' : 'canBeEnabled'}()
191
                ->end()
192
            ->end();
193
    }
194
195
    private function addDoctrineMongoDbOdmSection(ArrayNodeDefinition $rootNode): void
196
    {
197
        $rootNode
198
            ->children()
199
                ->arrayNode('doctrine_mongodb_odm')
200
                    ->{class_exists(DoctrineMongoDBBundle::class) ? 'canBeDisabled' : 'canBeEnabled'}()
201
                ->end()
202
            ->end();
203
    }
204
205
    private function addOAuthSection(ArrayNodeDefinition $rootNode): void
206
    {
207
        $rootNode
208
            ->children()
209
                ->arrayNode('oauth')
210
                    ->canBeEnabled()
211
                    ->addDefaultsIfNotSet()
212
                    ->children()
213
                        ->scalarNode('clientId')->defaultValue('')->info('The oauth client id.')->end()
214
                        ->scalarNode('clientSecret')->defaultValue('')->info('The oauth client secret.')->end()
0 ignored issues
show
The method scalarNode() does not exist on Symfony\Component\Config...der\NodeParentInterface. It seems like you code against a sub-type of Symfony\Component\Config...der\NodeParentInterface such as Symfony\Component\Config...ion\Builder\NodeBuilder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

214
                        ->/** @scrutinizer ignore-call */ scalarNode('clientSecret')->defaultValue('')->info('The oauth client secret.')->end()
Loading history...
215
                        ->scalarNode('type')->defaultValue('oauth2')->info('The oauth client secret.')->end()
216
                        ->scalarNode('flow')->defaultValue('application')->info('The oauth flow grant type.')->end()
217
                        ->scalarNode('tokenUrl')->defaultValue('/oauth/v2/token')->info('The oauth token url.')->end()
218
                        ->scalarNode('authorizationUrl')->defaultValue('/oauth/v2/auth')->info('The oauth authentication url.')->end()
219
                        ->arrayNode('scopes')
220
                            ->prototype('scalar')->end()
221
                        ->end()
222
                    ->end()
223
                ->end()
224
            ->end();
225
    }
226
227
    private function addGraphQlSection(ArrayNodeDefinition $rootNode): void
228
    {
229
        $rootNode
230
            ->children()
231
                ->arrayNode('graphql')
232
                    ->{class_exists(GraphQL::class) ? 'canBeDisabled' : 'canBeEnabled'}()
233
                    ->addDefaultsIfNotSet()
234
                    ->children()
235
                        ->scalarNode('default_ide')->defaultValue('graphiql')->end()
236
                        ->arrayNode('graphiql')
237
                            ->{class_exists(GraphQL::class) && class_exists(TwigBundle::class) ? 'canBeDisabled' : 'canBeEnabled'}()
238
                        ->end()
239
                        ->arrayNode('graphql_playground')
240
                            ->{class_exists(GraphQL::class) && class_exists(TwigBundle::class) ? 'canBeDisabled' : 'canBeEnabled'}()
241
                        ->end()
242
                        ->arrayNode('collection')
243
                            ->addDefaultsIfNotSet()
244
                            ->children()
245
                                ->arrayNode('pagination')
246
                                    ->canBeDisabled()
247
                                ->end()
248
                            ->end()
249
                        ->end()
250
                    ->end()
251
                ->end()
252
            ->end();
253
    }
254
255
    private function addSwaggerSection(ArrayNodeDefinition $rootNode): void
256
    {
257
        $defaultVersions = [2, 3];
258
259
        $rootNode
260
            ->children()
261
                ->arrayNode('swagger')
262
                    ->addDefaultsIfNotSet()
263
                    ->children()
264
                        ->arrayNode('versions')
265
                            ->info('The active versions of OpenAPI to be exported or used in the swagger_ui. The first value is the default.')
266
                            ->defaultValue($defaultVersions)
267
                            ->beforeNormalization()
268
                                ->always(static function ($v) {
269
                                    if (!\is_array($v)) {
270
                                        $v = [$v];
271
                                    }
272
273
                                    foreach ($v as &$version) {
274
                                        $version = (int) $version;
275
                                    }
276
277
                                    return $v;
278
                                })
279
                            ->end()
280
                            ->validate()
281
                                ->ifTrue(function ($v) use ($defaultVersions) {
282
                                    return $v !== array_intersect($v, $defaultVersions);
283
                                })
284
                                ->thenInvalid(sprintf('Only the versions %s are supported. Got %s.', implode(' and ', $defaultVersions), '%s'))
285
                            ->end()
286
                            ->prototype('scalar')->end()
0 ignored issues
show
The method prototype() does not exist on Symfony\Component\Config...\Builder\NodeDefinition. It seems like you code against a sub-type of Symfony\Component\Config...\Builder\NodeDefinition such as Symfony\Component\Config...der\ArrayNodeDefinition. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

286
                            ->/** @scrutinizer ignore-call */ prototype('scalar')->end()
Loading history...
287
                        ->end()
288
                        ->arrayNode('api_keys')
289
                            ->prototype('array')
290
                                ->children()
291
                                    ->scalarNode('name')
292
                                        ->info('The name of the header or query parameter containing the api key.')
293
                                    ->end()
294
                                    ->enumNode('type')
295
                                        ->info('Whether the api key should be a query parameter or a header.')
296
                                        ->values(['query', 'header'])
297
                                    ->end()
298
                                ->end()
299
                            ->end()
300
                        ->end()
301
                    ->end()
302
                ->end()
303
            ->end();
304
    }
305
306
    private function addHttpCacheSection(ArrayNodeDefinition $rootNode): void
307
    {
308
        $rootNode
309
            ->children()
310
                ->arrayNode('http_cache')
311
                    ->addDefaultsIfNotSet()
312
                    ->children()
313
                        ->booleanNode('etag')->defaultTrue()->info('Automatically generate etags for API responses.')->end()
314
                        ->integerNode('max_age')->defaultNull()->info('Default value for the response max age.')->end()
0 ignored issues
show
The method integerNode() does not exist on Symfony\Component\Config...der\NodeParentInterface. It seems like you code against a sub-type of Symfony\Component\Config...der\NodeParentInterface such as Symfony\Component\Config...ion\Builder\NodeBuilder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

314
                        ->/** @scrutinizer ignore-call */ integerNode('max_age')->defaultNull()->info('Default value for the response max age.')->end()
Loading history...
315
                        ->integerNode('shared_max_age')->defaultNull()->info('Default value for the response shared (proxy) max age.')->end()
316
                        ->arrayNode('vary')
317
                            ->defaultValue(['Accept'])
318
                            ->prototype('scalar')->end()
319
                            ->info('Default values of the "Vary" HTTP header.')
320
                        ->end()
321
                        ->booleanNode('public')->defaultNull()->info('To make all responses public by default.')->end()
322
                        ->arrayNode('invalidation')
323
                            ->info('Enable the tags-based cache invalidation system.')
324
                            ->canBeEnabled()
325
                            ->children()
326
                                ->arrayNode('varnish_urls')
327
                                    ->defaultValue([])
328
                                    ->prototype('scalar')->end()
329
                                    ->info('URLs of the Varnish servers to purge using cache tags when a resource is updated.')
330
                                ->end()
331
                                ->variableNode('request_options')
332
                                    ->defaultValue([])
333
                                    ->validate()
334
                                        ->ifTrue(function ($v) { return false === \is_array($v); })
335
                                        ->thenInvalid('The request_options parameter must be an array.')
336
                                    ->end()
337
                                    ->info('To pass options to the client charged with the request.')
338
                                ->end()
339
                            ->end()
340
                        ->end()
341
                    ->end()
342
                ->end()
343
            ->end();
344
    }
345
346
    private function addMercureSection(ArrayNodeDefinition $rootNode): void
347
    {
348
        $rootNode
349
            ->children()
350
                ->arrayNode('mercure')
351
                    ->{class_exists(MercureBundle::class) ? 'canBeDisabled' : 'canBeEnabled'}()
352
                    ->children()
353
                        ->scalarNode('hub_url')
354
                            ->defaultNull()
355
                            ->info('The URL sent in the Link HTTP header. If not set, will default to the URL for MercureBundle\'s default hub.')
356
                        ->end()
357
                    ->end()
358
                ->end()
359
            ->end();
360
    }
361
362
    private function addMessengerSection(ArrayNodeDefinition $rootNode): void
363
    {
364
        $rootNode
365
            ->children()
366
                ->arrayNode('messenger')
367
                    ->{!class_exists(FullStack::class) && interface_exists(MessageBusInterface::class) ? 'canBeDisabled' : 'canBeEnabled'}()
368
                ->end()
369
            ->end();
370
    }
371
372
    private function addElasticsearchSection(ArrayNodeDefinition $rootNode): void
373
    {
374
        $rootNode
375
            ->children()
376
                ->arrayNode('elasticsearch')
377
                    ->canBeEnabled()
378
                    ->addDefaultsIfNotSet()
379
                    ->children()
380
                        ->booleanNode('enabled')
381
                            ->defaultFalse()
382
                            ->validate()
383
                                ->ifTrue()
384
                                ->then(static function (bool $v): bool {
385
                                    if (!class_exists(ElasticsearchClient::class)) {
386
                                        throw new InvalidConfigurationException('The elasticsearch/elasticsearch package is required for Elasticsearch support.');
387
                                    }
388
389
                                    return $v;
390
                                })
391
                            ->end()
392
                        ->end()
393
                        ->arrayNode('hosts')
0 ignored issues
show
The method arrayNode() does not exist on Symfony\Component\Config...der\NodeParentInterface. It seems like you code against a sub-type of Symfony\Component\Config...der\NodeParentInterface such as Symfony\Component\Config...ion\Builder\NodeBuilder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

393
                        ->/** @scrutinizer ignore-call */ arrayNode('hosts')
Loading history...
394
                            ->beforeNormalization()->castToArray()->end()
395
                            ->defaultValue([])
396
                            ->prototype('scalar')->end()
397
                        ->end()
398
                        ->arrayNode('mapping')
399
                            ->normalizeKeys(false)
400
                            ->useAttributeAsKey('resource_class')
401
                            ->prototype('array')
402
                                ->children()
403
                                    ->scalarNode('index')->defaultNull()->end()
404
                                    ->scalarNode('type')->defaultValue(DocumentMetadata::DEFAULT_TYPE)->end()
405
                                ->end()
406
                            ->end()
407
                        ->end()
408
                    ->end()
409
                ->end()
410
            ->end();
411
    }
412
413
    /**
414
     * @throws InvalidConfigurationException
415
     */
416
    private function addExceptionToStatusSection(ArrayNodeDefinition $rootNode): void
417
    {
418
        $rootNode
419
            ->children()
420
                ->arrayNode('exception_to_status')
421
                    ->defaultValue([
422
                        SerializerExceptionInterface::class => Response::HTTP_BAD_REQUEST,
423
                        InvalidArgumentException::class => Response::HTTP_BAD_REQUEST,
424
                        FilterValidationException::class => Response::HTTP_BAD_REQUEST,
425
                        OptimisticLockException::class => Response::HTTP_CONFLICT,
426
                    ])
427
                    ->info('The list of exceptions mapped to their HTTP status code.')
428
                    ->normalizeKeys(false)
429
                    ->useAttributeAsKey('exception_class')
430
                    ->beforeNormalization()
431
                        ->ifArray()
432
                        ->then(function (array $exceptionToStatus) {
433
                            foreach ($exceptionToStatus as &$httpStatusCode) {
434
                                if (\is_int($httpStatusCode)) {
435
                                    continue;
436
                                }
437
438
                                if (\defined($httpStatusCodeConstant = sprintf('%s::%s', Response::class, $httpStatusCode))) {
439
                                    @trigger_error(sprintf('Using a string "%s" as a constant of the "%s" class is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3. Use the Symfony\'s custom YAML extension for PHP constants instead (i.e. "!php/const %s").', $httpStatusCode, Response::class, $httpStatusCodeConstant), E_USER_DEPRECATED);
440
441
                                    $httpStatusCode = \constant($httpStatusCodeConstant);
442
                                }
443
                            }
444
445
                            return $exceptionToStatus;
446
                        })
447
                    ->end()
448
                    ->prototype('integer')->end()
449
                    ->validate()
450
                        ->ifArray()
451
                        ->then(function (array $exceptionToStatus) {
452
                            foreach ($exceptionToStatus as $httpStatusCode) {
453
                                if ($httpStatusCode < 100 || $httpStatusCode >= 600) {
454
                                    throw new InvalidConfigurationException(sprintf('The HTTP status code "%s" is not valid.', $httpStatusCode));
455
                                }
456
                            }
457
458
                            return $exceptionToStatus;
459
                        })
460
                    ->end()
461
                ->end()
462
            ->end();
463
    }
464
465
    private function addFormatSection(ArrayNodeDefinition $rootNode, string $key, array $defaultValue): void
466
    {
467
        $rootNode
468
            ->children()
469
                ->arrayNode($key)
470
                    ->defaultValue($defaultValue)
471
                    ->info('The list of enabled formats. The first one will be the default.')
472
                    ->normalizeKeys(false)
473
                    ->useAttributeAsKey('format')
474
                    ->beforeNormalization()
475
                        ->ifArray()
476
                        ->then(function ($v) {
477
                            foreach ($v as $format => $value) {
478
                                if (isset($value['mime_types'])) {
479
                                    continue;
480
                                }
481
482
                                $v[$format] = ['mime_types' => $value];
483
                            }
484
485
                            return $v;
486
                        })
487
                    ->end()
488
                    ->prototype('array')
489
                        ->children()
490
                            ->arrayNode('mime_types')->prototype('scalar')->end()->end()
491
                        ->end()
492
                    ->end()
493
                ->end()
494
            ->end();
495
    }
496
}
497