Completed
Pull Request — 2.x (#2181)
by Christian
03:52
created

Configuration::addViewSection()   B

Complexity

Conditions 3
Paths 1

Size

Total Lines 96

Duplication

Lines 11
Ratio 11.46 %

Code Coverage

Tests 82
CRAP Score 3.0001

Importance

Changes 0
Metric Value
dl 11
loc 96
ccs 82
cts 84
cp 0.9762
rs 8.0872
c 0
b 0
f 0
cc 3
nc 1
nop 1
crap 3.0001

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the FOSRestBundle package.
5
 *
6
 * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
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
namespace FOS\RestBundle\DependencyInjection;
13
14
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
15
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
16
use Symfony\Component\Config\Definition\ConfigurationInterface;
17
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
18
use Symfony\Component\HttpFoundation\Response;
19
use Symfony\Component\OptionsResolver\OptionsResolver;
20
use Symfony\Component\Serializer\Encoder\XmlEncoder;
21
22
/**
23
 * This class contains the configuration information for the bundle.
24
 *
25
 * This information is solely responsible for how the different configuration
26
 * sections are normalized, and merged.
27
 *
28
 * @author Lukas Kahwe Smith <[email protected]>
29
 *
30
 * @internal
31
 */
32
final class Configuration implements ConfigurationInterface
33
{
34
    /**
35
     * Default debug mode value.
36
     *
37
     * @var bool
38
     */
39
    private $debug;
40
41 81
    public function __construct(bool $debug)
42
    {
43 81
        $this->debug = $debug;
44 81
    }
45
46 80
    public function getConfigTreeBuilder(): TreeBuilder
47
    {
48 80
        $treeBuilder = new TreeBuilder('fos_rest');
49
50 80
        if (method_exists($treeBuilder, 'getRootNode')) {
51 80
            $rootNode = $treeBuilder->getRootNode();
52
        } else {
53
            $rootNode = $treeBuilder->root('fos_rest');
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Component\Config...der\TreeBuilder::root() has been deprecated with message: since Symfony 4.3, pass the root name to the constructor instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
54
        }
55
56
        $rootNode
57 80
            ->children()
58 80
                ->scalarNode('disable_csrf_role')->defaultNull()->end()
59 80
                ->arrayNode('access_denied_listener')
60 80
                    ->canBeEnabled()
61 80
                    ->beforeNormalization()
62 View Code Duplication
                        ->ifArray()->then(function ($v) {
63
                            if (!empty($v) && empty($v['formats'])) {
64
                                unset($v['enabled']);
65
                                $v = ['enabled' => true, 'formats' => $v];
66
                            }
67
68
                            return $v;
69 80
                        })
70 80
                    ->end()
71 80
                    ->fixXmlConfig('format', 'formats')
72 80
                    ->children()
73 80
                        ->scalarNode('service')->defaultNull()->end()
74 80
                        ->arrayNode('formats')
75 80
                            ->useAttributeAsKey('name')
76 80
                            ->prototype('boolean')->end()
77 80
                        ->end()
78 80
                    ->end()
79 80
                ->end()
80 80
                ->scalarNode('unauthorized_challenge')->defaultNull()->end()
81 80
                ->arrayNode('param_fetcher_listener')
82 80
                    ->beforeNormalization()
83 80
                        ->ifString()
84 View Code Duplication
                        ->then(function ($v) {
85 1
                            return ['enabled' => in_array($v, ['force', 'true']), 'force' => 'force' === $v];
86 80
                        })
87 80
                    ->end()
88 80
                    ->canBeEnabled()
89 80
                    ->children()
90 80
                        ->booleanNode('force')->defaultFalse()->end()
91 80
                        ->scalarNode('service')->defaultNull()->end()
92 80
                    ->end()
93 80
                ->end()
94 80
                ->scalarNode('cache_dir')->cannotBeEmpty()->defaultValue('%kernel.cache_dir%/fos_rest')->end()
95 80
                ->arrayNode('allowed_methods_listener')
96 80
                    ->canBeEnabled()
97 80
                    ->children()
98 80
                        ->scalarNode('service')->defaultNull()->end()
99 80
                    ->end()
100 80
                ->end()
101 80
                ->arrayNode('routing_loader')
102 80
                    ->addDefaultsIfNotSet()
103 80
                    ->beforeNormalization()
104
                        ->ifTrue(function ($v) { return isset($v['enabled']) && false !== $v['enabled']; })
105
                        ->then(function ($v) {
106
                            @trigger_error('Enabling the route generation feature is deprecated since FOSRestBundle 2.8.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
107
108
                            return $v;
109 80
                        })
110 80
                    ->end()
111 80
                    ->beforeNormalization()
112
                        ->ifTrue(function ($v) { return is_bool($v); })
113
                        ->then(function ($v) {
114
                            return [
115 63
                                'enabled' => $v,
116
                            ];
117 80
                        })
118 80
                    ->end()
119 80
                    ->children()
120 80
                        ->booleanNode('enabled')
121
                            ->defaultValue(function () {
122 6
                                @trigger_error('Enabling the route generation feature is deprecated since FOSRestBundle 2.8.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
123
124 6
                                return true;
125 80
                            })
126 80
                        ->end()
127 80
                        ->scalarNode('default_format')->defaultNull()->end()
128 80
                        ->scalarNode('prefix_methods')->defaultTrue()->end()
129 80
                        ->scalarNode('include_format')->defaultTrue()->end()
130 80
                    ->end()
131 80
                ->end()
132 80
                ->arrayNode('body_converter')
133 80
                    ->canBeEnabled()
134 80
                    ->children()
135 80
                        ->scalarNode('validate')
136 80
                            ->defaultFalse()
137 80
                            ->beforeNormalization()
138 80
                                ->ifTrue()
139
                                ->then(function ($value) {
140 3
                                    if (!class_exists(OptionsResolver::class)) {
141
                                        throw new InvalidConfigurationException("'body_converter.validate: true' requires OptionsResolver component installation ( composer require symfony/options-resolver )");
142
                                    }
143
144 3
                                    return $value;
145 80
                                })
146 80
                            ->end()
147 80
                        ->end()
148 80
                        ->scalarNode('validation_errors_argument')->defaultValue('validationErrors')->end()
149 80
                    ->end()
150 80
                ->end()
151 80
                ->arrayNode('service')
152 80
                    ->addDefaultsIfNotSet()
153 80
                    ->children()
154 80
                        ->scalarNode('router')->defaultValue('router')->end()
155 80
                        ->scalarNode('templating')
156
                            ->defaultValue(static function () {
157 5
                                @trigger_error('Not setting the "fos_rest.service.templating" configuration option to "null" is deprecated since FOSRestBundle 2.8.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
158
159 5
                                return 'templating';
160 80
                            })
161 80
                            ->validate()
162
                                ->ifTrue(static function ($v) { return $v; })
163
                                ->then(static function ($v) {
164
                                    @trigger_error('Not setting the "fos_rest.service.templating" configuration option to "null" is deprecated since FOSRestBundle 2.8.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
165
166
                                    return $v;
167 80
                                })
168 80
                            ->end()
169 80
                        ->end()
170 80
                        ->scalarNode('serializer')->defaultNull()->end()
171 80
                        ->scalarNode('view_handler')->defaultValue('fos_rest.view_handler.default')->end()
172 80
                        ->scalarNode('inflector')
173
                            ->defaultValue(static function () {
174
                                @trigger_error('Not setting the "fos_rest.service.inflector" configuration option to "null" is deprecated since FOSRestBundle 2.8.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
175
176
                                return 'fos_rest.inflector.doctrine';
177 80
                            })
178 80
                            ->defaultValue('fos_rest.inflector.doctrine')
179 80
                        ->end()
180 80
                        ->scalarNode('validator')->defaultValue('validator')->end()
181 80
                    ->end()
182 80
                ->end()
183 80
                ->arrayNode('serializer')
184 80
                    ->addDefaultsIfNotSet()
185 80
                    ->children()
186 80
                        ->scalarNode('version')->defaultNull()->end()
187 80
                        ->arrayNode('groups')
188 80
                            ->prototype('scalar')->end()
189 80
                        ->end()
190 80
                        ->booleanNode('serialize_null')->defaultFalse()->end()
191 80
                    ->end()
192 80
                ->end()
193 80
                ->arrayNode('zone')
194 80
                    ->cannotBeOverwritten()
195 80
                    ->prototype('array')
196 80
                    ->fixXmlConfig('ip')
197 80
                    ->children()
198 80
                        ->scalarNode('path')
199 80
                            ->defaultNull()
200 80
                            ->info('use the urldecoded format')
201 80
                            ->example('^/path to resource/')
202 80
                        ->end()
203 80
                        ->scalarNode('host')->defaultNull()->end()
204 80
                        ->arrayNode('methods')
205
                            ->beforeNormalization()->ifString()->then(function ($v) {
206
                                return preg_split('/\s*,\s*/', $v);
207 80
                            })->end()
208 80
                            ->prototype('scalar')->end()
209 80
                        ->end()
210 80
                        ->arrayNode('ips')
211
                            ->beforeNormalization()->ifString()->then(function ($v) {
212 1
                                return array($v);
213 80
                            })->end()
214 80
                            ->prototype('scalar')->end()
215 80
                        ->end()
216 80
                    ->end()
217 80
                ->end()
218 80
            ->end()
219 80
        ->end();
220
221 80
        $this->addViewSection($rootNode);
0 ignored issues
show
Compatibility introduced by
$rootNode of type object<Symfony\Component...Builder\NodeDefinition> is not a sub-type of object<Symfony\Component...er\ArrayNodeDefinition>. It seems like you assume a child class of the class Symfony\Component\Config...\Builder\NodeDefinition to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
222 80
        $this->addExceptionSection($rootNode);
0 ignored issues
show
Compatibility introduced by
$rootNode of type object<Symfony\Component...Builder\NodeDefinition> is not a sub-type of object<Symfony\Component...er\ArrayNodeDefinition>. It seems like you assume a child class of the class Symfony\Component\Config...\Builder\NodeDefinition to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
223 80
        $this->addBodyListenerSection($rootNode);
0 ignored issues
show
Compatibility introduced by
$rootNode of type object<Symfony\Component...Builder\NodeDefinition> is not a sub-type of object<Symfony\Component...er\ArrayNodeDefinition>. It seems like you assume a child class of the class Symfony\Component\Config...\Builder\NodeDefinition to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
224 80
        $this->addFormatListenerSection($rootNode);
0 ignored issues
show
Compatibility introduced by
$rootNode of type object<Symfony\Component...Builder\NodeDefinition> is not a sub-type of object<Symfony\Component...er\ArrayNodeDefinition>. It seems like you assume a child class of the class Symfony\Component\Config...\Builder\NodeDefinition to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
225 80
        $this->addVersioningSection($rootNode);
0 ignored issues
show
Compatibility introduced by
$rootNode of type object<Symfony\Component...Builder\NodeDefinition> is not a sub-type of object<Symfony\Component...er\ArrayNodeDefinition>. It seems like you assume a child class of the class Symfony\Component\Config...\Builder\NodeDefinition to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
226
227 80
        return $treeBuilder;
228
    }
229
230 80
    private function addViewSection(ArrayNodeDefinition $rootNode)
231
    {
232
        $rootNode
233 80
            ->children()
234 80
                ->arrayNode('view')
235 80
                    ->fixXmlConfig('format', 'formats')
236 80
                    ->fixXmlConfig('mime_type', 'mime_types')
237 80
                    ->fixXmlConfig('templating_format', 'templating_formats')
238 80
                    ->fixXmlConfig('force_redirect', 'force_redirects')
239 80
                    ->addDefaultsIfNotSet()
240 80
                    ->children()
241 80
                        ->scalarNode('default_engine')
242
                            ->defaultValue(static function () {
243 5
                                @trigger_error('Not setting the "fos_rest.view.default_engine" configuration option to "null" is deprecated since FOSRestBundle 2.8.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
244
245 5
                                return 'twig';
246 80
                            })
247 80
                            ->validate()
248
                                ->ifTrue(static function ($v) { return $v; })
249
                                ->then(static function ($v) {
250
                                    @trigger_error('Not setting the "fos_rest.view.default_engine" configuration option to "null" is deprecated since FOSRestBundle 2.8.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
251
252
                                    return $v;
253 80
                                })
254 80
                            ->end()
255 80
                        ->end()
256 80
                        ->arrayNode('force_redirects')
257 80
                            ->useAttributeAsKey('name')
258 80
                            ->defaultValue(['html' => true])
259 80
                            ->prototype('boolean')->end()
260 80
                        ->end()
261 80
                        ->arrayNode('mime_types')
262 80
                            ->canBeEnabled()
263 80
                            ->beforeNormalization()
264 View Code Duplication
                                ->ifArray()->then(function ($v) {
265 1
                                    if (!empty($v) && empty($v['formats'])) {
266 1
                                        unset($v['enabled']);
267 1
                                        $v = ['enabled' => true, 'formats' => $v];
268
                                    }
269
270 1
                                    return $v;
271 80
                                })
272 80
                            ->end()
273 80
                            ->fixXmlConfig('format', 'formats')
274 80
                            ->children()
275 80
                                ->scalarNode('service')->defaultNull()->end()
276 80
                                ->arrayNode('formats')
277 80
                                    ->useAttributeAsKey('name')
278 80
                                    ->prototype('array')
279 80
                                        ->beforeNormalization()
280 80
                                            ->ifString()
281
                                            ->then(function ($v) { return array($v); })
282 80
                                        ->end()
283 80
                                        ->prototype('scalar')->end()
284 80
                                    ->end()
285 80
                                ->end()
286 80
                            ->end()
287 80
                        ->end()
288 80
                        ->arrayNode('formats')
289 80
                            ->useAttributeAsKey('name')
290 80
                            ->defaultValue(['json' => true, 'xml' => true])
291 80
                            ->prototype('boolean')->end()
292 80
                        ->end()
293 80
                        ->arrayNode('templating_formats')
294 80
                            ->setDeprecated('The "%path%.%node%" configuration key has been deprecated in FOSRestBundle 2.8.')
295 80
                            ->useAttributeAsKey('name')
296 80
                            ->defaultValue(['html' => true])
297 80
                            ->prototype('boolean')->end()
298 80
                        ->end()
299 80
                        ->arrayNode('view_response_listener')
300 80
                            ->beforeNormalization()
301 80
                                ->ifString()
302 View Code Duplication
                                ->then(function ($v) {
303 9
                                    return ['enabled' => in_array($v, ['force', 'true']), 'force' => 'force' === $v];
304 80
                                })
305 80
                            ->end()
306 80
                            ->canBeEnabled()
307 80
                            ->children()
308 80
                                ->booleanNode('force')->defaultFalse()->end()
309 80
                                ->scalarNode('service')->defaultNull()->end()
310 80
                            ->end()
311 80
                        ->end()
312 80
                        ->scalarNode('failed_validation')->defaultValue(Response::HTTP_BAD_REQUEST)->end()
313 80
                        ->scalarNode('empty_content')->defaultValue(Response::HTTP_NO_CONTENT)->end()
314 80
                        ->booleanNode('serialize_null')->defaultFalse()->end()
315 80
                        ->arrayNode('jsonp_handler')
316 80
                            ->canBeUnset()
317 80
                            ->children()
318 80
                                ->scalarNode('callback_param')->defaultValue('callback')->end()
319 80
                                ->scalarNode('mime_type')->defaultValue('application/javascript+jsonp')->end()
320 80
                            ->end()
321 80
                        ->end()
322 80
                    ->end()
323 80
                ->end()
324 80
            ->end();
325 80
    }
326
327 80
    private function addBodyListenerSection(ArrayNodeDefinition $rootNode)
328
    {
329 80
        $decodersDefaultValue = ['json' => 'fos_rest.decoder.json'];
330 80
        if (class_exists(XmlEncoder::class)) {
331 80
            $decodersDefaultValue['xml'] = 'fos_rest.decoder.xml';
332
        }
333
        $rootNode
334 80
            ->children()
335 80
                ->arrayNode('body_listener')
336 80
                    ->fixXmlConfig('decoder', 'decoders')
337 80
                    ->addDefaultsIfNotSet()
338 80
                    ->canBeUnset()
339 80
                    ->canBeDisabled()
340 80
                    ->children()
341 80
                        ->scalarNode('service')->defaultNull()->end()
342 80
                        ->scalarNode('default_format')->defaultNull()->end()
343 80
                        ->booleanNode('throw_exception_on_unsupported_content_type')
344 80
                            ->defaultFalse()
345 80
                        ->end()
346 80
                        ->arrayNode('decoders')
347 80
                            ->useAttributeAsKey('name')
348 80
                            ->defaultValue($decodersDefaultValue)
349 80
                            ->prototype('scalar')->end()
350 80
                        ->end()
351 80
                        ->arrayNode('array_normalizer')
352 80
                            ->addDefaultsIfNotSet()
353 80
                            ->beforeNormalization()
354
                                ->ifString()->then(function ($v) {
355 1
                                    return ['service' => $v];
356 80
                                })
357 80
                            ->end()
358 80
                            ->children()
359 80
                                ->scalarNode('service')->defaultNull()->end()
360 80
                                ->booleanNode('forms')->defaultFalse()->end()
361 80
                            ->end()
362 80
                        ->end()
363 80
                    ->end()
364 80
                ->end()
365 80
            ->end();
366 80
    }
367
368 80
    private function addFormatListenerSection(ArrayNodeDefinition $rootNode)
369
    {
370
        $rootNode
371 80
            ->children()
372 80
                ->arrayNode('format_listener')
373 80
                    ->fixXmlConfig('rule', 'rules')
374 80
                    ->addDefaultsIfNotSet()
375 80
                    ->canBeUnset()
376 80
                    ->beforeNormalization()
377
                        ->ifTrue(function ($v) {
378
                            // check if we got an assoc array in rules
379 9
                            return isset($v['rules'])
380 9
                                && is_array($v['rules'])
381 9
                                && array_keys($v['rules']) !== range(0, count($v['rules']) - 1);
382 80
                        })
383
                        ->then(function ($v) {
384 1
                            $v['rules'] = [$v['rules']];
385
386 1
                            return $v;
387 80
                        })
388 80
                    ->end()
389 80
                    ->canBeEnabled()
390 80
                    ->children()
391 80
                        ->scalarNode('service')->defaultNull()->end()
392 80
                        ->arrayNode('rules')
393 80
                            ->performNoDeepMerging()
394 80
                            ->prototype('array')
395 80
                                ->fixXmlConfig('priority', 'priorities')
396 80
                                ->fixXmlConfig('attribute', 'attributes')
397 80
                                ->children()
398 80
                                    ->scalarNode('path')->defaultNull()->info('URL path info')->end()
399 80
                                    ->scalarNode('host')->defaultNull()->info('URL host name')->end()
400 80
                                    ->variableNode('methods')->defaultNull()->info('Method for URL')->end()
401 80
                                    ->arrayNode('attributes')
402 80
                                        ->useAttributeAsKey('name')
403 80
                                        ->prototype('variable')->end()
404 80
                                    ->end()
405 80
                                    ->booleanNode('stop')->defaultFalse()->end()
406 80
                                    ->booleanNode('prefer_extension')->defaultTrue()->end()
407 80
                                    ->scalarNode('fallback_format')->defaultValue('html')->end()
408 80
                                    ->arrayNode('priorities')
409
                                        ->beforeNormalization()->ifString()->then(function ($v) {
410
                                            return preg_split('/\s*,\s*/', $v);
411 80
                                        })->end()
412 80
                                        ->prototype('scalar')->end()
413 80
                                    ->end()
414 80
                                ->end()
415 80
                            ->end()
416 80
                        ->end()
417 80
                    ->end()
418 80
                ->end()
419 80
            ->end();
420 80
    }
421
422 80
    private function addVersioningSection(ArrayNodeDefinition $rootNode)
423
    {
424
        $rootNode
425 80
        ->children()
426 80
            ->arrayNode('versioning')
427 80
                ->canBeEnabled()
428 80
                ->children()
429 80
                    ->scalarNode('default_version')->defaultNull()->end()
430 80
                    ->arrayNode('resolvers')
431 80
                        ->addDefaultsIfNotSet()
432 80
                        ->children()
433 80
                            ->arrayNode('query')
434 80
                                ->canBeDisabled()
435 80
                                ->children()
436 80
                                    ->scalarNode('parameter_name')->defaultValue('version')->end()
437 80
                                ->end()
438 80
                            ->end()
439 80
                            ->arrayNode('custom_header')
440 80
                                ->canBeDisabled()
441 80
                                ->children()
442 80
                                    ->scalarNode('header_name')->defaultValue('X-Accept-Version')->end()
443 80
                                ->end()
444 80
                            ->end()
445 80
                            ->arrayNode('media_type')
446 80
                                ->canBeDisabled()
447 80
                                ->children()
448 80
                                    ->scalarNode('regex')->defaultValue('/(v|version)=(?P<version>[0-9\.]+)/')->end()
449 80
                                ->end()
450 80
                            ->end()
451 80
                        ->end()
452 80
                    ->end()
453 80
                    ->arrayNode('guessing_order')
454 80
                        ->defaultValue(['query', 'custom_header', 'media_type'])
455 80
                        ->validate()
456
                            ->ifTrue(function ($v) {
457
                                foreach ($v as $resolver) {
458
                                    if (!in_array($resolver, ['query', 'custom_header', 'media_type'])) {
459
                                        return true;
460
                                    }
461
                                }
462 80
                            })
463 80
                            ->thenInvalid('Versioning guessing order can only contain "query", "custom_header", "media_type".')
464 80
                        ->end()
465 80
                        ->prototype('scalar')->end()
466 80
                    ->end()
467 80
                ->end()
468 80
            ->end()
469 80
        ->end();
470 80
    }
471
472 80
    private function addExceptionSection(ArrayNodeDefinition $rootNode)
473
    {
474
        $rootNode
475 80
            ->children()
476 80
                ->arrayNode('exception')
477 80
                    ->fixXmlConfig('code', 'codes')
478 80
                    ->fixXmlConfig('message', 'messages')
479 80
                    ->addDefaultsIfNotSet()
480 80
                    ->canBeEnabled()
481 80
                    ->children()
482 80
                        ->booleanNode('map_exception_codes')
483 80
                            ->defaultFalse()
484 80
                            ->info('Enables an event listener that maps exception codes to response status codes based on the map configured with the "fos_rest.exception.codes" option.')
485 80
                        ->end()
486 80
                        ->booleanNode('exception_listener')
487
                            ->defaultValue(function () {
488 14
                                @trigger_error('Enabling the "fos_rest.exception.exception_listener" option is deprecated since FOSRestBundle 2.8.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
489
490 14
                                return true;
491 80
                            })
492 80
                            ->beforeNormalization()
493 80
                                ->ifTrue()
494
                                ->then(function ($v) {
495
                                    @trigger_error('Enabling the "fos_rest.exception.exception_listener" option is deprecated since FOSRestBundle 2.8.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
496
497
                                    return $v;
498 80
                                })
499 80
                            ->end()
500 80
                        ->end()
501 80
                        ->scalarNode('exception_controller')
502 80
                            ->defaultNull()
503 80
                            ->setDeprecated('The "%path%.%node%" option is deprecated since FOSRestBundle 2.8.')
504 80
                        ->end()
505 80
                        ->booleanNode('serialize_exceptions')
506
                            ->defaultValue(function () {
507 9
                                @trigger_error('Enabling the "fos_rest.exception.serialize_exceptions" option is deprecated since FOSRestBundle 2.8.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
508
509 9
                                return true;
510 80
                            })
511 80
                            ->beforeNormalization()
512 80
                                ->ifTrue()
513
                                ->then(function ($v) {
514 8
                                    @trigger_error('Enabling the "fos_rest.exception.serialize_exceptions" option is deprecated since FOSRestBundle 2.8.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
515
516 8
                                    return $v;
517 80
                                })
518 80
                            ->end()
519 80
                        ->end()
520 80
                        ->enumNode('flatten_exception_format')
521 80
                            ->defaultValue('legacy')
522 80
                            ->values(['legacy', 'rfc7807'])
523 80
                        ->end()
524 80
                        ->scalarNode('service')
525 80
                            ->defaultNull()
526 80
                            ->setDeprecated('The "%path%.%node%" option is deprecated since FOSRestBundle 2.8.')
527 80
                        ->end()
528 80
                        ->arrayNode('codes')
529 80
                            ->useAttributeAsKey('name')
530 80
                            ->beforeNormalization()
531 80
                                ->ifArray()
532
                                ->then(function (array $items) {
533 13
                                    foreach ($items as &$item) {
534 13
                                        if (is_int($item)) {
535 3
                                            continue;
536
                                        }
537
538 10
                                        if (!defined(sprintf('%s::%s', Response::class, $item))) {
539 9
                                            throw new InvalidConfigurationException(sprintf('Invalid HTTP code in fos_rest.exception.codes, see %s for all valid codes.', Response::class));
540
                                        }
541
542 1
                                        $item = constant(sprintf('%s::%s', Response::class, $item));
543
                                    }
544
545 4
                                    return $items;
546 80
                                })
547 80
                            ->end()
548 80
                            ->prototype('integer')->end()
549
550 80
                            ->validate()
551 80
                            ->ifArray()
552
                                ->then(function (array $items) {
553 4
                                    foreach ($items as $class => $code) {
554 4
                                        $this->testExceptionExists($class);
555
                                    }
556
557 3
                                    return $items;
558 80
                                })
559 80
                            ->end()
560 80
                        ->end()
561 80
                        ->arrayNode('messages')
562 80
                            ->useAttributeAsKey('name')
563 80
                            ->prototype('boolean')->end()
564 80
                            ->validate()
565 80
                                ->ifArray()
566
                                ->then(function (array $items) {
567 12
                                    foreach ($items as $class => $nomatter) {
568 12
                                        $this->testExceptionExists($class);
569
                                    }
570
571 11
                                    return $items;
572 80
                                })
573 80
                            ->end()
574 80
                        ->end()
575 80
                        ->booleanNode('debug')
576 80
                            ->defaultValue($this->debug)
577 80
                        ->end()
578 80
                    ->end()
579 80
                ->end()
580 80
            ->end();
581 80
    }
582
583 16
    private function testExceptionExists(string $throwable)
584
    {
585 16
        if (!is_subclass_of($throwable, \Throwable::class)) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \Throwable::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
586 2
            throw new InvalidConfigurationException(sprintf('FOSRestBundle exception mapper: Could not load class "%s" or the class does not extend from "%s". Most probably this is a configuration problem.', $throwable, \Throwable::class));
587
        }
588 14
    }
589
}
590