Completed
Push — master ( 8f26c7...01b05c )
by Christian
04:45 queued 04:41
created

Configuration::addExceptionSection()   B

Complexity

Conditions 6
Paths 1

Size

Total Lines 86

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 70
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 86
ccs 70
cts 70
cp 1
rs 7.6832
c 0
b 0
f 0
cc 6
nc 1
nop 1
crap 6

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