Completed
Pull Request — 2.x (#2161)
by Christian
03:47
created

Configuration::addExceptionSection()   B

Complexity

Conditions 6
Paths 1

Size

Total Lines 110

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 84
CRAP Score 6.0004

Importance

Changes 0
Metric Value
dl 0
loc 110
ccs 84
cts 86
cp 0.9767
rs 7.3777
c 0
b 0
f 0
cc 6
nc 1
nop 1
crap 6.0004

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 79
    public function __construct(bool $debug)
42
    {
43 79
        $this->debug = $debug;
44 79
    }
45
46 78
    public function getConfigTreeBuilder(): TreeBuilder
47
    {
48 78
        $treeBuilder = new TreeBuilder('fos_rest');
49
50 78
        if (method_exists($treeBuilder, 'getRootNode')) {
51 78
            $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 78
            ->children()
58 78
                ->scalarNode('disable_csrf_role')->defaultNull()->end()
59 78
                ->arrayNode('access_denied_listener')
60 78
                    ->canBeEnabled()
61 78
                    ->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 78
                        })
70 78
                    ->end()
71 78
                    ->fixXmlConfig('format', 'formats')
72 78
                    ->children()
73 78
                        ->scalarNode('service')->defaultNull()->end()
74 78
                        ->arrayNode('formats')
75 78
                            ->useAttributeAsKey('name')
76 78
                            ->prototype('boolean')->end()
77 78
                        ->end()
78 78
                    ->end()
79 78
                ->end()
80 78
                ->scalarNode('unauthorized_challenge')->defaultNull()->end()
81 78
                ->arrayNode('param_fetcher_listener')
82 78
                    ->beforeNormalization()
83 78
                        ->ifString()
84 View Code Duplication
                        ->then(function ($v) {
85 1
                            return ['enabled' => in_array($v, ['force', 'true']), 'force' => 'force' === $v];
86 78
                        })
87 78
                    ->end()
88 78
                    ->canBeEnabled()
89 78
                    ->children()
90 78
                        ->booleanNode('force')->defaultFalse()->end()
91 78
                        ->scalarNode('service')->defaultNull()->end()
92 78
                    ->end()
93 78
                ->end()
94 78
                ->scalarNode('cache_dir')->cannotBeEmpty()->defaultValue('%kernel.cache_dir%/fos_rest')->end()
95 78
                ->arrayNode('allowed_methods_listener')
96 78
                    ->canBeEnabled()
97 78
                    ->children()
98 78
                        ->scalarNode('service')->defaultNull()->end()
99 78
                    ->end()
100 78
                ->end()
101 78
                ->arrayNode('routing_loader')
102 78
                    ->addDefaultsIfNotSet()
103 78
                    ->canBeDisabled()
104 78
                    ->beforeNormalization()
105
                        ->ifTrue(function ($v) { return false !== $v; })
106
                        ->then(function ($v) {
107 2
                            @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...
108
109 2
                            return $v;
110 78
                        })
111 78
                    ->end()
112 78
                    ->beforeNormalization()
113
                        ->ifTrue(function ($v) { return is_bool($v); })
114
                        ->then(function ($v) {
115
                            return [
116 58
                                'enabled' => $v,
117
                            ];
118 78
                        })
119 78
                    ->end()
120 78
                    ->children()
121 78
                        ->scalarNode('default_format')->defaultNull()->end()
122 78
                        ->scalarNode('prefix_methods')->defaultTrue()->end()
123 78
                        ->scalarNode('include_format')->defaultTrue()->end()
124 78
                    ->end()
125 78
                ->end()
126 78
                ->arrayNode('body_converter')
127 78
                    ->canBeEnabled()
128 78
                    ->children()
129 78
                        ->scalarNode('validate')
130 78
                            ->defaultFalse()
131 78
                            ->beforeNormalization()
132 78
                                ->ifTrue()
133
                                ->then(function ($value) {
134 3
                                    if (!class_exists(OptionsResolver::class)) {
135
                                        throw new InvalidConfigurationException("'body_converter.validate: true' requires OptionsResolver component installation ( composer require symfony/options-resolver )");
136
                                    }
137
138 3
                                    return $value;
139 78
                                })
140 78
                            ->end()
141 78
                        ->end()
142 78
                        ->scalarNode('validation_errors_argument')->defaultValue('validationErrors')->end()
143 78
                    ->end()
144 78
                ->end()
145 78
                ->arrayNode('service')
146 78
                    ->addDefaultsIfNotSet()
147 78
                    ->children()
148 78
                        ->scalarNode('router')->defaultValue('router')->end()
149 78
                        ->scalarNode('templating')
150
                            ->defaultValue(static function () {
151 6
                                @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...
152
153 6
                                return 'templating';
154 78
                            })
155 78
                            ->validate()
156
                                ->ifTrue(static function ($v) { return $v; })
157
                                ->then(static function ($v) {
158
                                    @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...
159
160
                                    return $v;
161 78
                                })
162 78
                            ->end()
163 78
                        ->end()
164 78
                        ->scalarNode('serializer')->defaultNull()->end()
165 78
                        ->scalarNode('view_handler')->defaultValue('fos_rest.view_handler.default')->end()
166 78
                        ->scalarNode('inflector')
167
                            ->defaultValue(static function () {
168
                                @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...
169
170
                                return 'fos_rest.inflector.doctrine';
171 78
                            })
172 78
                            ->defaultValue('fos_rest.inflector.doctrine')
173 78
                        ->end()
174 78
                        ->scalarNode('validator')->defaultValue('validator')->end()
175 78
                    ->end()
176 78
                ->end()
177 78
                ->arrayNode('serializer')
178 78
                    ->addDefaultsIfNotSet()
179 78
                    ->children()
180 78
                        ->scalarNode('version')->defaultNull()->end()
181 78
                        ->arrayNode('groups')
182 78
                            ->prototype('scalar')->end()
183 78
                        ->end()
184 78
                        ->booleanNode('serialize_null')->defaultFalse()->end()
185 78
                    ->end()
186 78
                ->end()
187 78
                ->arrayNode('zone')
188 78
                    ->cannotBeOverwritten()
189 78
                    ->prototype('array')
190 78
                    ->fixXmlConfig('ip')
191 78
                    ->children()
192 78
                        ->scalarNode('path')
193 78
                            ->defaultNull()
194 78
                            ->info('use the urldecoded format')
195 78
                            ->example('^/path to resource/')
196 78
                        ->end()
197 78
                        ->scalarNode('host')->defaultNull()->end()
198 78
                        ->arrayNode('methods')
199
                            ->beforeNormalization()->ifString()->then(function ($v) {
200
                                return preg_split('/\s*,\s*/', $v);
201 78
                            })->end()
202 78
                            ->prototype('scalar')->end()
203 78
                        ->end()
204 78
                        ->arrayNode('ips')
205
                            ->beforeNormalization()->ifString()->then(function ($v) {
206 1
                                return array($v);
207 78
                            })->end()
208 78
                            ->prototype('scalar')->end()
209 78
                        ->end()
210 78
                    ->end()
211 78
                ->end()
212 78
            ->end()
213 78
        ->end();
214
215 78
        $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...
216 78
        $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...
217 78
        $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...
218 78
        $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...
219 78
        $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...
220
221 78
        return $treeBuilder;
222
    }
223
224 78
    private function addViewSection(ArrayNodeDefinition $rootNode)
225
    {
226
        $rootNode
227 78
            ->children()
228 78
                ->arrayNode('view')
229 78
                    ->fixXmlConfig('format', 'formats')
230 78
                    ->fixXmlConfig('mime_type', 'mime_types')
231 78
                    ->fixXmlConfig('templating_format', 'templating_formats')
232 78
                    ->fixXmlConfig('force_redirect', 'force_redirects')
233 78
                    ->addDefaultsIfNotSet()
234 78
                    ->children()
235 78
                        ->scalarNode('default_engine')
236
                            ->defaultValue(static function () {
237 6
                                @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...
238
239 6
                                return 'twig';
240 78
                            })
241 78
                            ->validate()
242
                                ->ifTrue(static function ($v) { return $v; })
243
                                ->then(static function ($v) {
244
                                    @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...
245
246
                                    return $v;
247 78
                                })
248 78
                            ->end()
249 78
                        ->end()
250 78
                        ->arrayNode('force_redirects')
251 78
                            ->useAttributeAsKey('name')
252 78
                            ->defaultValue(['html' => true])
253 78
                            ->prototype('boolean')->end()
254 78
                        ->end()
255 78
                        ->arrayNode('mime_types')
256 78
                            ->canBeEnabled()
257 78
                            ->beforeNormalization()
258 View Code Duplication
                                ->ifArray()->then(function ($v) {
259 1
                                    if (!empty($v) && empty($v['formats'])) {
260 1
                                        unset($v['enabled']);
261 1
                                        $v = ['enabled' => true, 'formats' => $v];
262
                                    }
263
264 1
                                    return $v;
265 78
                                })
266 78
                            ->end()
267 78
                            ->fixXmlConfig('format', 'formats')
268 78
                            ->children()
269 78
                                ->scalarNode('service')->defaultNull()->end()
270 78
                                ->arrayNode('formats')
271 78
                                    ->useAttributeAsKey('name')
272 78
                                    ->prototype('array')
273 78
                                        ->beforeNormalization()
274 78
                                            ->ifString()
275
                                            ->then(function ($v) { return array($v); })
276 78
                                        ->end()
277 78
                                        ->prototype('scalar')->end()
278 78
                                    ->end()
279 78
                                ->end()
280 78
                            ->end()
281 78
                        ->end()
282 78
                        ->arrayNode('formats')
283 78
                            ->useAttributeAsKey('name')
284 78
                            ->defaultValue(['json' => true, 'xml' => true])
285 78
                            ->prototype('boolean')->end()
286 78
                        ->end()
287 78
                        ->arrayNode('templating_formats')
288 78
                            ->setDeprecated('The "%path%.%node%" configuration key has been deprecated in FOSRestBundle 2.8.')
289 78
                            ->useAttributeAsKey('name')
290 78
                            ->defaultValue(['html' => true])
291 78
                            ->prototype('boolean')->end()
292 78
                        ->end()
293 78
                        ->arrayNode('view_response_listener')
294 78
                            ->beforeNormalization()
295 78
                                ->ifString()
296 View Code Duplication
                                ->then(function ($v) {
297 9
                                    return ['enabled' => in_array($v, ['force', 'true']), 'force' => 'force' === $v];
298 78
                                })
299 78
                            ->end()
300 78
                            ->canBeEnabled()
301 78
                            ->children()
302 78
                                ->booleanNode('force')->defaultFalse()->end()
303 78
                                ->scalarNode('service')->defaultNull()->end()
304 78
                            ->end()
305 78
                        ->end()
306 78
                        ->scalarNode('failed_validation')->defaultValue(Response::HTTP_BAD_REQUEST)->end()
307 78
                        ->scalarNode('empty_content')->defaultValue(Response::HTTP_NO_CONTENT)->end()
308 78
                        ->booleanNode('serialize_null')->defaultFalse()->end()
309 78
                        ->arrayNode('jsonp_handler')
310 78
                            ->canBeUnset()
311 78
                            ->children()
312 78
                                ->scalarNode('callback_param')->defaultValue('callback')->end()
313 78
                                ->scalarNode('mime_type')->defaultValue('application/javascript+jsonp')->end()
314 78
                            ->end()
315 78
                        ->end()
316 78
                    ->end()
317 78
                ->end()
318 78
            ->end();
319 78
    }
320
321 78
    private function addBodyListenerSection(ArrayNodeDefinition $rootNode)
322
    {
323 78
        $decodersDefaultValue = ['json' => 'fos_rest.decoder.json'];
324 78
        if (class_exists(XmlEncoder::class)) {
325 78
            $decodersDefaultValue['xml'] = 'fos_rest.decoder.xml';
326
        }
327
        $rootNode
328 78
            ->children()
329 78
                ->arrayNode('body_listener')
330 78
                    ->fixXmlConfig('decoder', 'decoders')
331 78
                    ->addDefaultsIfNotSet()
332 78
                    ->canBeUnset()
333 78
                    ->canBeDisabled()
334 78
                    ->children()
335 78
                        ->scalarNode('service')->defaultNull()->end()
336 78
                        ->scalarNode('default_format')->defaultNull()->end()
337 78
                        ->booleanNode('throw_exception_on_unsupported_content_type')
338 78
                            ->defaultFalse()
339 78
                        ->end()
340 78
                        ->arrayNode('decoders')
341 78
                            ->useAttributeAsKey('name')
342 78
                            ->defaultValue($decodersDefaultValue)
343 78
                            ->prototype('scalar')->end()
344 78
                        ->end()
345 78
                        ->arrayNode('array_normalizer')
346 78
                            ->addDefaultsIfNotSet()
347 78
                            ->beforeNormalization()
348
                                ->ifString()->then(function ($v) {
349 1
                                    return ['service' => $v];
350 78
                                })
351 78
                            ->end()
352 78
                            ->children()
353 78
                                ->scalarNode('service')->defaultNull()->end()
354 78
                                ->booleanNode('forms')->defaultFalse()->end()
355 78
                            ->end()
356 78
                        ->end()
357 78
                    ->end()
358 78
                ->end()
359 78
            ->end();
360 78
    }
361
362 78
    private function addFormatListenerSection(ArrayNodeDefinition $rootNode)
363
    {
364
        $rootNode
365 78
            ->children()
366 78
                ->arrayNode('format_listener')
367 78
                    ->fixXmlConfig('rule', 'rules')
368 78
                    ->addDefaultsIfNotSet()
369 78
                    ->canBeUnset()
370 78
                    ->beforeNormalization()
371
                        ->ifTrue(function ($v) {
372
                            // check if we got an assoc array in rules
373 9
                            return isset($v['rules'])
374 9
                                && is_array($v['rules'])
375 9
                                && array_keys($v['rules']) !== range(0, count($v['rules']) - 1);
376 78
                        })
377
                        ->then(function ($v) {
378 1
                            $v['rules'] = [$v['rules']];
379
380 1
                            return $v;
381 78
                        })
382 78
                    ->end()
383 78
                    ->canBeEnabled()
384 78
                    ->children()
385 78
                        ->scalarNode('service')->defaultNull()->end()
386 78
                        ->arrayNode('rules')
387 78
                            ->performNoDeepMerging()
388 78
                            ->prototype('array')
389 78
                                ->fixXmlConfig('priority', 'priorities')
390 78
                                ->fixXmlConfig('attribute', 'attributes')
391 78
                                ->children()
392 78
                                    ->scalarNode('path')->defaultNull()->info('URL path info')->end()
393 78
                                    ->scalarNode('host')->defaultNull()->info('URL host name')->end()
394 78
                                    ->variableNode('methods')->defaultNull()->info('Method for URL')->end()
395 78
                                    ->arrayNode('attributes')
396 78
                                        ->useAttributeAsKey('name')
397 78
                                        ->prototype('variable')->end()
398 78
                                    ->end()
399 78
                                    ->booleanNode('stop')->defaultFalse()->end()
400 78
                                    ->booleanNode('prefer_extension')->defaultTrue()->end()
401 78
                                    ->scalarNode('fallback_format')->defaultValue('html')->end()
402 78
                                    ->arrayNode('priorities')
403
                                        ->beforeNormalization()->ifString()->then(function ($v) {
404
                                            return preg_split('/\s*,\s*/', $v);
405 78
                                        })->end()
406 78
                                        ->prototype('scalar')->end()
407 78
                                    ->end()
408 78
                                ->end()
409 78
                            ->end()
410 78
                        ->end()
411 78
                    ->end()
412 78
                ->end()
413 78
            ->end();
414 78
    }
415
416 78
    private function addVersioningSection(ArrayNodeDefinition $rootNode)
417
    {
418
        $rootNode
419 78
        ->children()
420 78
            ->arrayNode('versioning')
421 78
                ->canBeEnabled()
422 78
                ->children()
423 78
                    ->scalarNode('default_version')->defaultNull()->end()
424 78
                    ->arrayNode('resolvers')
425 78
                        ->addDefaultsIfNotSet()
426 78
                        ->children()
427 78
                            ->arrayNode('query')
428 78
                                ->canBeDisabled()
429 78
                                ->children()
430 78
                                    ->scalarNode('parameter_name')->defaultValue('version')->end()
431 78
                                ->end()
432 78
                            ->end()
433 78
                            ->arrayNode('custom_header')
434 78
                                ->canBeDisabled()
435 78
                                ->children()
436 78
                                    ->scalarNode('header_name')->defaultValue('X-Accept-Version')->end()
437 78
                                ->end()
438 78
                            ->end()
439 78
                            ->arrayNode('media_type')
440 78
                                ->canBeDisabled()
441 78
                                ->children()
442 78
                                    ->scalarNode('regex')->defaultValue('/(v|version)=(?P<version>[0-9\.]+)/')->end()
443 78
                                ->end()
444 78
                            ->end()
445 78
                        ->end()
446 78
                    ->end()
447 78
                    ->arrayNode('guessing_order')
448 78
                        ->defaultValue(['query', 'custom_header', 'media_type'])
449 78
                        ->validate()
450
                            ->ifTrue(function ($v) {
451
                                foreach ($v as $resolver) {
452
                                    if (!in_array($resolver, ['query', 'custom_header', 'media_type'])) {
453
                                        return true;
454
                                    }
455
                                }
456 78
                            })
457 78
                            ->thenInvalid('Versioning guessing order can only contain "query", "custom_header", "media_type".')
458 78
                        ->end()
459 78
                        ->prototype('scalar')->end()
460 78
                    ->end()
461 78
                ->end()
462 78
            ->end()
463 78
        ->end();
464 78
    }
465
466 78
    private function addExceptionSection(ArrayNodeDefinition $rootNode)
467
    {
468
        $rootNode
469 78
            ->children()
470 78
                ->arrayNode('exception')
471 78
                    ->fixXmlConfig('code', 'codes')
472 78
                    ->fixXmlConfig('message', 'messages')
473 78
                    ->addDefaultsIfNotSet()
474 78
                    ->canBeEnabled()
475 78
                    ->children()
476 78
                        ->booleanNode('map_exception_codes')
477 78
                            ->defaultFalse()
478 78
                            ->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.')
479 78
                        ->end()
480 78
                        ->booleanNode('exception_listener')
481
                            ->defaultValue(function () {
482 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...
483
484 14
                                return true;
485 78
                            })
486 78
                            ->beforeNormalization()
487 78
                                ->ifTrue()
488
                                ->then(function ($v) {
489
                                    @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...
490
491
                                    return $v;
492 78
                                })
493 78
                            ->end()
494 78
                        ->end()
495 78
                        ->scalarNode('exception_controller')
496 78
                            ->defaultNull()
497 78
                            ->setDeprecated('The "%path%.%node%" option is deprecated since FOSRestBundle 2.8.')
498 78
                        ->end()
499 78
                        ->booleanNode('serialize_exceptions')
500
                            ->defaultValue(function () {
501 10
                                @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...
502
503 10
                                return true;
504 78
                            })
505 78
                            ->beforeNormalization()
506 78
                                ->ifTrue()
507
                                ->then(function ($v) {
508 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...
509
510 8
                                    return $v;
511 78
                                })
512 78
                            ->end()
513 78
                        ->end()
514 78
                        ->enumNode('flatten_exception_format')
515 78
                            ->defaultValue('legacy')
516 78
                            ->values(['legacy', 'rfc7807'])
517 78
                        ->end()
518 78
                        ->scalarNode('service')
519 78
                            ->defaultNull()
520 78
                            ->setDeprecated('The "%path%.%node%" option is deprecated since FOSRestBundle 2.8.')
521 78
                        ->end()
522 78
                        ->arrayNode('codes')
523 78
                            ->useAttributeAsKey('name')
524 78
                            ->beforeNormalization()
525 78
                                ->ifArray()
526
                                ->then(function (array $items) {
527 13
                                    foreach ($items as &$item) {
528 13
                                        if (is_int($item)) {
529 3
                                            continue;
530
                                        }
531
532 10
                                        if (!defined(sprintf('%s::%s', Response::class, $item))) {
533 9
                                            throw new InvalidConfigurationException(sprintf('Invalid HTTP code in fos_rest.exception.codes, see %s for all valid codes.', Response::class));
534
                                        }
535
536 1
                                        $item = constant(sprintf('%s::%s', Response::class, $item));
537
                                    }
538
539 4
                                    return $items;
540 78
                                })
541 78
                            ->end()
542 78
                            ->prototype('integer')->end()
543
544 78
                            ->validate()
545 78
                            ->ifArray()
546
                                ->then(function (array $items) {
547 4
                                    foreach ($items as $class => $code) {
548 4
                                        $this->testExceptionExists($class);
549
                                    }
550
551 3
                                    return $items;
552 78
                                })
553 78
                            ->end()
554 78
                        ->end()
555 78
                        ->arrayNode('messages')
556 78
                            ->useAttributeAsKey('name')
557 78
                            ->prototype('boolean')->end()
558 78
                            ->validate()
559 78
                                ->ifArray()
560
                                ->then(function (array $items) {
561 12
                                    foreach ($items as $class => $nomatter) {
562 12
                                        $this->testExceptionExists($class);
563
                                    }
564
565 11
                                    return $items;
566 78
                                })
567 78
                            ->end()
568 78
                        ->end()
569 78
                        ->booleanNode('debug')
570 78
                            ->defaultValue($this->debug)
571 78
                        ->end()
572 78
                    ->end()
573 78
                ->end()
574 78
            ->end();
575 78
    }
576
577 16
    private function testExceptionExists(string $exception)
578
    {
579 16
        if (!is_subclass_of($exception, \Exception::class) && !is_a($exception, \Exception::class, true)) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \Exception::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
580 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.', $exception, \Exception::class));
581
        }
582 14
    }
583
}
584