Completed
Push — master ( 3bae86...d2e5ad )
by Tobias
08:00 queued 11s
created

Configuration   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 491
Duplicated Lines 4.48 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 97.61%

Importance

Changes 0
Metric Value
wmc 24
lcom 1
cbo 6
dl 22
loc 491
ccs 408
cts 418
cp 0.9761
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B getConfigTreeBuilder() 11 146 4
B addViewSection() 11 85 3
A addBodyListenerSection() 0 49 2
A addFormatListenerSection() 0 53 3
A addVersioningSection() 0 49 3
B addExceptionSection() 0 87 6
A testExceptionExists() 0 6 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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