Completed
Push — 2.x ( ab09c4...e83ec2 )
by Christian
15s queued 11s
created

Configuration::getConfigTreeBuilder()   B

Complexity

Conditions 5
Paths 2

Size

Total Lines 177

Duplication

Lines 11
Ratio 6.21 %

Code Coverage

Tests 134
CRAP Score 5.0109

Importance

Changes 0
Metric Value
dl 11
loc 177
ccs 134
cts 145
cp 0.9241
rs 7.6888
c 0
b 0
f 0
cc 5
nc 2
nop 0
crap 5.0109

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 68
    public function __construct(bool $debug)
42
    {
43 68
        $this->debug = $debug;
44 68
    }
45
46 67
    public function getConfigTreeBuilder(): TreeBuilder
47
    {
48 67
        $treeBuilder = new TreeBuilder('fos_rest');
49
50 67
        if (method_exists($treeBuilder, 'getRootNode')) {
51 67
            $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 67
            ->children()
58 67
                ->scalarNode('disable_csrf_role')->defaultNull()->end()
59 67
                ->arrayNode('access_denied_listener')
60 67
                    ->canBeEnabled()
61 67
                    ->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 67
                        })
70 67
                    ->end()
71 67
                    ->fixXmlConfig('format', 'formats')
72 67
                    ->children()
73 67
                        ->scalarNode('service')->defaultNull()->end()
74 67
                        ->arrayNode('formats')
75 67
                            ->useAttributeAsKey('name')
76 67
                            ->prototype('boolean')->end()
77 67
                        ->end()
78 67
                    ->end()
79 67
                ->end()
80 67
                ->scalarNode('unauthorized_challenge')->defaultNull()->end()
81 67
                ->arrayNode('param_fetcher_listener')
82 67
                    ->beforeNormalization()
83 67
                        ->ifString()
84 View Code Duplication
                        ->then(function ($v) {
85 1
                            return ['enabled' => in_array($v, ['force', 'true']), 'force' => 'force' === $v];
86 67
                        })
87 67
                    ->end()
88 67
                    ->canBeEnabled()
89 67
                    ->children()
90 67
                        ->booleanNode('force')->defaultFalse()->end()
91 67
                        ->scalarNode('service')->defaultNull()->end()
92 67
                    ->end()
93 67
                ->end()
94 67
                ->scalarNode('cache_dir')->cannotBeEmpty()->defaultValue('%kernel.cache_dir%/fos_rest')->end()
95 67
                ->arrayNode('allowed_methods_listener')
96 67
                    ->canBeEnabled()
97 67
                    ->children()
98 67
                        ->scalarNode('service')->defaultNull()->end()
99 67
                    ->end()
100 67
                ->end()
101 67
                ->arrayNode('routing_loader')
102 67
                    ->addDefaultsIfNotSet()
103 67
                    ->canBeDisabled()
104 67
                    ->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 67
                        })
111 67
                    ->end()
112 67
                    ->beforeNormalization()
113
                        ->ifTrue(function ($v) { return is_bool($v); })
114
                        ->then(function ($v) {
115
                            return [
116 51
                                'enabled' => $v,
117
                            ];
118 67
                        })
119 67
                    ->end()
120 67
                    ->children()
121 67
                        ->scalarNode('default_format')->defaultNull()->end()
122 67
                        ->scalarNode('prefix_methods')->defaultTrue()->end()
123 67
                        ->scalarNode('include_format')->defaultTrue()->end()
124 67
                    ->end()
125 67
                ->end()
126 67
                ->arrayNode('body_converter')
127 67
                    ->canBeEnabled()
128 67
                    ->children()
129 67
                        ->scalarNode('validate')
130 67
                            ->defaultFalse()
131 67
                            ->beforeNormalization()
132 67
                                ->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 67
                                })
140 67
                            ->end()
141 67
                        ->end()
142 67
                        ->scalarNode('validation_errors_argument')->defaultValue('validationErrors')->end()
143 67
                    ->end()
144 67
                ->end()
145 67
                ->arrayNode('service')
146 67
                    ->addDefaultsIfNotSet()
147 67
                    ->children()
148 67
                        ->scalarNode('router')->defaultValue('router')->end()
149 67
                        ->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 67
                            })
155 67
                            ->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 67
                                })
162 67
                            ->end()
163 67
                        ->end()
164 67
                        ->scalarNode('serializer')->defaultNull()->end()
165 67
                        ->scalarNode('view_handler')->defaultValue('fos_rest.view_handler.default')->end()
166 67
                        ->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 67
                            })
172 67
                            ->defaultValue('fos_rest.inflector.doctrine')
173 67
                        ->end()
174 67
                        ->scalarNode('validator')->defaultValue('validator')->end()
175 67
                    ->end()
176 67
                ->end()
177 67
                ->arrayNode('serializer')
178 67
                    ->addDefaultsIfNotSet()
179 67
                    ->children()
180 67
                        ->scalarNode('version')->defaultNull()->end()
181 67
                        ->arrayNode('groups')
182 67
                            ->prototype('scalar')->end()
183 67
                        ->end()
184 67
                        ->booleanNode('serialize_null')->defaultFalse()->end()
185 67
                    ->end()
186 67
                ->end()
187 67
                ->arrayNode('zone')
188 67
                    ->cannotBeOverwritten()
189 67
                    ->prototype('array')
190 67
                    ->fixXmlConfig('ip')
191 67
                    ->children()
192 67
                        ->scalarNode('path')
193 67
                            ->defaultNull()
194 67
                            ->info('use the urldecoded format')
195 67
                            ->example('^/path to resource/')
196 67
                        ->end()
197 67
                        ->scalarNode('host')->defaultNull()->end()
198 67
                        ->arrayNode('methods')
199
                            ->beforeNormalization()->ifString()->then(function ($v) {
200
                                return preg_split('/\s*,\s*/', $v);
201 67
                            })->end()
202 67
                            ->prototype('scalar')->end()
203 67
                        ->end()
204 67
                        ->arrayNode('ips')
205
                            ->beforeNormalization()->ifString()->then(function ($v) {
206 1
                                return array($v);
207 67
                            })->end()
208 67
                            ->prototype('scalar')->end()
209 67
                        ->end()
210 67
                    ->end()
211 67
                ->end()
212 67
            ->end()
213 67
        ->end();
214
215 67
        $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 67
        $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 67
        $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 67
        $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 67
        $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 67
        return $treeBuilder;
222
    }
223
224 67
    private function addViewSection(ArrayNodeDefinition $rootNode)
225
    {
226
        $rootNode
227 67
            ->children()
228 67
                ->arrayNode('view')
229 67
                    ->fixXmlConfig('format', 'formats')
230 67
                    ->fixXmlConfig('mime_type', 'mime_types')
231 67
                    ->fixXmlConfig('templating_format', 'templating_formats')
232 67
                    ->fixXmlConfig('force_redirect', 'force_redirects')
233 67
                    ->addDefaultsIfNotSet()
234 67
                    ->children()
235 67
                        ->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 67
                            })
241 67
                            ->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 67
                                })
248 67
                            ->end()
249 67
                        ->end()
250 67
                        ->arrayNode('force_redirects')
251 67
                            ->useAttributeAsKey('name')
252 67
                            ->defaultValue(['html' => true])
253 67
                            ->prototype('boolean')->end()
254 67
                        ->end()
255 67
                        ->arrayNode('mime_types')
256 67
                            ->canBeEnabled()
257 67
                            ->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 67
                                })
266 67
                            ->end()
267 67
                            ->fixXmlConfig('format', 'formats')
268 67
                            ->children()
269 67
                                ->scalarNode('service')->defaultNull()->end()
270 67
                                ->arrayNode('formats')
271 67
                                    ->useAttributeAsKey('name')
272 67
                                    ->prototype('array')
273 67
                                        ->beforeNormalization()
274 67
                                            ->ifString()
275
                                            ->then(function ($v) { return array($v); })
276 67
                                        ->end()
277 67
                                        ->prototype('scalar')->end()
278 67
                                    ->end()
279 67
                                ->end()
280 67
                            ->end()
281 67
                        ->end()
282 67
                        ->arrayNode('formats')
283 67
                            ->useAttributeAsKey('name')
284 67
                            ->defaultValue(['json' => true, 'xml' => true])
285 67
                            ->prototype('boolean')->end()
286 67
                        ->end()
287 67
                        ->arrayNode('templating_formats')
288 67
                            ->setDeprecated('The "%path%.%node%" configuration key has been deprecated in FOSRestBundle 2.8.')
289 67
                            ->useAttributeAsKey('name')
290 67
                            ->defaultValue(['html' => true])
291 67
                            ->prototype('boolean')->end()
292 67
                        ->end()
293 67
                        ->arrayNode('view_response_listener')
294 67
                            ->beforeNormalization()
295 67
                                ->ifString()
296 View Code Duplication
                                ->then(function ($v) {
297 7
                                    return ['enabled' => in_array($v, ['force', 'true']), 'force' => 'force' === $v];
298 67
                                })
299 67
                            ->end()
300 67
                            ->canBeEnabled()
301 67
                            ->children()
302 67
                                ->booleanNode('force')->defaultFalse()->end()
303 67
                                ->scalarNode('service')->defaultNull()->end()
304 67
                            ->end()
305 67
                        ->end()
306 67
                        ->scalarNode('failed_validation')->defaultValue(Response::HTTP_BAD_REQUEST)->end()
307 67
                        ->scalarNode('empty_content')->defaultValue(Response::HTTP_NO_CONTENT)->end()
308 67
                        ->booleanNode('serialize_null')->defaultFalse()->end()
309 67
                        ->arrayNode('jsonp_handler')
310 67
                            ->canBeUnset()
311 67
                            ->children()
312 67
                                ->scalarNode('callback_param')->defaultValue('callback')->end()
313 67
                                ->scalarNode('mime_type')->defaultValue('application/javascript+jsonp')->end()
314 67
                            ->end()
315 67
                        ->end()
316 67
                    ->end()
317 67
                ->end()
318 67
            ->end();
319 67
    }
320
321 67
    private function addBodyListenerSection(ArrayNodeDefinition $rootNode)
322
    {
323 67
        $decodersDefaultValue = ['json' => 'fos_rest.decoder.json'];
324 67
        if (class_exists(XmlEncoder::class)) {
325 67
            $decodersDefaultValue['xml'] = 'fos_rest.decoder.xml';
326
        }
327
        $rootNode
328 67
            ->children()
329 67
                ->arrayNode('body_listener')
330 67
                    ->fixXmlConfig('decoder', 'decoders')
331 67
                    ->addDefaultsIfNotSet()
332 67
                    ->canBeUnset()
333 67
                    ->canBeDisabled()
334 67
                    ->children()
335 67
                        ->scalarNode('service')->defaultNull()->end()
336 67
                        ->scalarNode('default_format')->defaultNull()->end()
337 67
                        ->booleanNode('throw_exception_on_unsupported_content_type')
338 67
                            ->defaultFalse()
339 67
                        ->end()
340 67
                        ->arrayNode('decoders')
341 67
                            ->useAttributeAsKey('name')
342 67
                            ->defaultValue($decodersDefaultValue)
343 67
                            ->prototype('scalar')->end()
344 67
                        ->end()
345 67
                        ->arrayNode('array_normalizer')
346 67
                            ->addDefaultsIfNotSet()
347 67
                            ->beforeNormalization()
348
                                ->ifString()->then(function ($v) {
349 1
                                    return ['service' => $v];
350 67
                                })
351 67
                            ->end()
352 67
                            ->children()
353 67
                                ->scalarNode('service')->defaultNull()->end()
354 67
                                ->booleanNode('forms')->defaultFalse()->end()
355 67
                            ->end()
356 67
                        ->end()
357 67
                    ->end()
358 67
                ->end()
359 67
            ->end();
360 67
    }
361
362 67
    private function addFormatListenerSection(ArrayNodeDefinition $rootNode)
363
    {
364
        $rootNode
365 67
            ->children()
366 67
                ->arrayNode('format_listener')
367 67
                    ->fixXmlConfig('rule', 'rules')
368 67
                    ->addDefaultsIfNotSet()
369 67
                    ->canBeUnset()
370 67
                    ->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 67
                        })
377
                        ->then(function ($v) {
378 1
                            $v['rules'] = [$v['rules']];
379
380 1
                            return $v;
381 67
                        })
382 67
                    ->end()
383 67
                    ->canBeEnabled()
384 67
                    ->children()
385 67
                        ->scalarNode('service')->defaultNull()->end()
386 67
                        ->arrayNode('rules')
387 67
                            ->performNoDeepMerging()
388 67
                            ->prototype('array')
389 67
                                ->fixXmlConfig('priority', 'priorities')
390 67
                                ->fixXmlConfig('attribute', 'attributes')
391 67
                                ->children()
392 67
                                    ->scalarNode('path')->defaultNull()->info('URL path info')->end()
393 67
                                    ->scalarNode('host')->defaultNull()->info('URL host name')->end()
394 67
                                    ->variableNode('methods')->defaultNull()->info('Method for URL')->end()
395 67
                                    ->arrayNode('attributes')
396 67
                                        ->useAttributeAsKey('name')
397 67
                                        ->prototype('variable')->end()
398 67
                                    ->end()
399 67
                                    ->booleanNode('stop')->defaultFalse()->end()
400 67
                                    ->booleanNode('prefer_extension')->defaultTrue()->end()
401 67
                                    ->scalarNode('fallback_format')->defaultValue('html')->end()
402 67
                                    ->arrayNode('priorities')
403
                                        ->beforeNormalization()->ifString()->then(function ($v) {
404
                                            return preg_split('/\s*,\s*/', $v);
405 67
                                        })->end()
406 67
                                        ->prototype('scalar')->end()
407 67
                                    ->end()
408 67
                                ->end()
409 67
                            ->end()
410 67
                        ->end()
411 67
                    ->end()
412 67
                ->end()
413 67
            ->end();
414 67
    }
415
416 67
    private function addVersioningSection(ArrayNodeDefinition $rootNode)
417
    {
418
        $rootNode
419 67
        ->children()
420 67
            ->arrayNode('versioning')
421 67
                ->canBeEnabled()
422 67
                ->children()
423 67
                    ->scalarNode('default_version')->defaultNull()->end()
424 67
                    ->arrayNode('resolvers')
425 67
                        ->addDefaultsIfNotSet()
426 67
                        ->children()
427 67
                            ->arrayNode('query')
428 67
                                ->canBeDisabled()
429 67
                                ->children()
430 67
                                    ->scalarNode('parameter_name')->defaultValue('version')->end()
431 67
                                ->end()
432 67
                            ->end()
433 67
                            ->arrayNode('custom_header')
434 67
                                ->canBeDisabled()
435 67
                                ->children()
436 67
                                    ->scalarNode('header_name')->defaultValue('X-Accept-Version')->end()
437 67
                                ->end()
438 67
                            ->end()
439 67
                            ->arrayNode('media_type')
440 67
                                ->canBeDisabled()
441 67
                                ->children()
442 67
                                    ->scalarNode('regex')->defaultValue('/(v|version)=(?P<version>[0-9\.]+)/')->end()
443 67
                                ->end()
444 67
                            ->end()
445 67
                        ->end()
446 67
                    ->end()
447 67
                    ->arrayNode('guessing_order')
448 67
                        ->defaultValue(['query', 'custom_header', 'media_type'])
449 67
                        ->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 67
                            })
457 67
                            ->thenInvalid('Versioning guessing order can only contain "query", "custom_header", "media_type".')
458 67
                        ->end()
459 67
                        ->prototype('scalar')->end()
460 67
                    ->end()
461 67
                ->end()
462 67
            ->end()
463 67
        ->end();
464 67
    }
465
466 67
    private function addExceptionSection(ArrayNodeDefinition $rootNode)
467
    {
468
        $rootNode
469 67
            ->children()
470 67
                ->arrayNode('exception')
471 67
                    ->fixXmlConfig('code', 'codes')
472 67
                    ->fixXmlConfig('message', 'messages')
473 67
                    ->addDefaultsIfNotSet()
474 67
                    ->canBeEnabled()
475 67
                    ->children()
476 67
                        ->scalarNode('exception_controller')
477
                            ->defaultValue(static function () {
478 4
                                @trigger_error('Not setting the "fos_rest.exception.exception_controller" configuration option is deprecated since FOSRestBundle 2.8. Its default value will be set to "fos_rest.exception.controller::showAction" in 3.0.', 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...
479
480 4
                                return null;
481 67
                            })
482 67
                            ->validate()
483
                                ->ifTrue(static function ($v) { return null === $v; })
484
                                ->then(static function ($v) {
485
                                    @trigger_error('Not setting the "fos_rest.exception.exception_controller" configuration option is deprecated since FOSRestBundle 2.8. Its default value will be set to "fos_rest.exception.controller::showAction" in 3.0.', 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...
486
487
                                    return $v;
488 67
                                })
489 67
                            ->end()
490 67
                        ->end()
491 67
                        ->scalarNode('service')->defaultNull()->end()
492 67
                        ->arrayNode('codes')
493 67
                            ->useAttributeAsKey('name')
494 67
                            ->beforeNormalization()
495 67
                                ->ifArray()
496
                                ->then(function (array $items) {
497 13
                                    foreach ($items as &$item) {
498 13
                                        if (is_int($item)) {
499 3
                                            continue;
500
                                        }
501
502 10
                                        if (!defined(sprintf('%s::%s', Response::class, $item))) {
503 9
                                            throw new InvalidConfigurationException(sprintf('Invalid HTTP code in fos_rest.exception.codes, see %s for all valid codes.', Response::class));
504
                                        }
505
506 1
                                        $item = constant(sprintf('%s::%s', Response::class, $item));
507
                                    }
508
509 4
                                    return $items;
510 67
                                })
511 67
                            ->end()
512 67
                            ->prototype('integer')->end()
513
514 67
                            ->validate()
515 67
                            ->ifArray()
516
                                ->then(function (array $items) {
517 4
                                    foreach ($items as $class => $code) {
518 4
                                        $this->testExceptionExists($class);
519
                                    }
520
521 3
                                    return $items;
522 67
                                })
523 67
                            ->end()
524 67
                        ->end()
525 67
                        ->arrayNode('messages')
526 67
                            ->useAttributeAsKey('name')
527 67
                            ->prototype('boolean')->end()
528 67
                            ->validate()
529 67
                                ->ifArray()
530
                                ->then(function (array $items) {
531 4
                                    foreach ($items as $class => $nomatter) {
532 4
                                        $this->testExceptionExists($class);
533
                                    }
534
535 3
                                    return $items;
536 67
                                })
537 67
                            ->end()
538 67
                        ->end()
539 67
                        ->booleanNode('debug')
540 67
                            ->defaultValue($this->debug)
541 67
                        ->end()
542 67
                    ->end()
543 67
                ->end()
544 67
            ->end();
545 67
    }
546
547 8
    private function testExceptionExists(string $exception)
548
    {
549 8
        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...
550 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));
551
        }
552 6
    }
553
}
554