Completed
Push — master ( 9b0e05...ad477a )
by Christian
16:13 queued 06:14
created

FOSRestExtension::loadException()   B

Complexity

Conditions 7
Paths 17

Size

Total Lines 41

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 28
CRAP Score 7.0957

Importance

Changes 0
Metric Value
dl 0
loc 41
ccs 28
cts 32
cp 0.875
rs 8.3306
c 0
b 0
f 0
cc 7
nc 17
nop 3
crap 7.0957
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\FileLocator;
15
use Symfony\Component\DependencyInjection\Alias;
16
use Symfony\Component\DependencyInjection\ChildDefinition;
17
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
18
use Symfony\Component\DependencyInjection\ContainerBuilder;
19
use Symfony\Component\DependencyInjection\DefinitionDecorator;
20
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
21
use Symfony\Component\DependencyInjection\Reference;
22
use Symfony\Component\Form\AbstractType;
23
use Symfony\Component\Form\Extension\Core\Type\FormType;
24
use Symfony\Component\HttpFoundation\Response;
25
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
26
use Symfony\Component\HttpKernel\Kernel;
27
28
class FOSRestExtension extends Extension
29 1
{
30
    /**
31 1
     * {@inheritdoc}
32
     */
33
    public function getConfiguration(array $config, ContainerBuilder $container)
34
    {
35
        return new Configuration($container->getParameter('kernel.debug'));
36
    }
37
38
    /**
39
     * Loads the services based on your application configuration.
40
     *
41
     * @param array            $configs
42
     * @param ContainerBuilder $container
43 55
     *
44
     * @throws \InvalidArgumentException
45 55
     * @throws \LogicException
46 55
     */
47
    public function load(array $configs, ContainerBuilder $container)
48 50
    {
49 50
        $configuration = new Configuration($container->getParameter('kernel.debug'));
50 50
        $config = $this->processConfiguration($configuration, $configs);
51 50
52 50
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
53
        $loader->load('view.xml');
54 50
        $loader->load('routing.xml');
55 50
        $loader->load('request.xml');
56 50
        $loader->load('serializer.xml');
57
58 50
        $container->getDefinition('fos_rest.routing.loader.controller')->replaceArgument(4, $config['routing_loader']['default_format']);
59 50
        $container->getDefinition('fos_rest.routing.loader.yaml_collection')->replaceArgument(4, $config['routing_loader']['default_format']);
60 50
        $container->getDefinition('fos_rest.routing.loader.xml_collection')->replaceArgument(4, $config['routing_loader']['default_format']);
61
62
        $container->getDefinition('fos_rest.routing.loader.yaml_collection')->replaceArgument(2, $config['routing_loader']['include_format']);
63 50
        $container->getDefinition('fos_rest.routing.loader.xml_collection')->replaceArgument(2, $config['routing_loader']['include_format']);
64 50
        $container->getDefinition('fos_rest.routing.loader.reader.action')->replaceArgument(3, $config['routing_loader']['include_format']);
65
        $container->getDefinition('fos_rest.routing.loader.reader.action')->replaceArgument(5, $config['routing_loader']['prefix_methods']);
66 50
67 50
        foreach ($config['service'] as $key => $service) {
68 50
            if ('validator' === $service && empty($config['body_converter']['validate'])) {
69 50
                continue;
70 50
            }
71
72 50
            if (null !== $service) {
73 50
                if ('view_handler' === $key) {
74 50
                    $container->setAlias('fos_rest.'.$key, new Alias($service, true));
75 50
                } else {
76
                    $container->setAlias('fos_rest.'.$key, $service);
77 50
                }
78 50
            }
79 50
        }
80 50
81 50
        $this->loadForm($config, $loader, $container);
82 50
        $this->loadException($config, $loader, $container);
83 50
        $this->loadBodyConverter($config, $loader, $container);
84
        $this->loadView($config, $loader, $container);
85
86 50
        $this->loadBodyListener($config, $loader, $container);
87 50
        $this->loadFormatListener($config, $loader, $container);
88
        $this->loadVersioning($config, $loader, $container);
89 50
        $this->loadParamFetcherListener($config, $loader, $container);
90
        $this->loadAllowedMethodsListener($config, $loader, $container);
91 50
        $this->loadAccessDeniedListener($config, $loader, $container);
92 1
        $this->loadZoneMatcherListener($config, $loader, $container);
93
94 1
        // Needs RequestBodyParamConverter and View Handler loaded.
95 1
        $this->loadSerializer($config, $container);
96
    }
97
98 1
    private function loadForm(array $config, XmlFileLoader $loader, ContainerBuilder $container)
99
    {
100
        if (!empty($config['disable_csrf_role'])) {
101 1
            $loader->load('forms.xml');
102
103 1
            $definition = $container->getDefinition('fos_rest.form.extension.csrf_disable');
104 50
            $definition->replaceArgument(1, $config['disable_csrf_role']);
105
106 50
            // BC for Symfony < 2.8: the extended_type attribute is used on higher versions
107
            if (!method_exists(AbstractType::class, 'getBlockPrefix')) {
108 50
                $definition->addTag('form.type_extension', ['alias' => 'form']);
109
            } else {
110
                $definition->addTag('form.type_extension', ['extended_type' => FormType::class]);
111
            }
112
        }
113
    }
114
115
    private function loadAccessDeniedListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
116
    {
117
        if ($config['access_denied_listener']['enabled'] && !empty($config['access_denied_listener']['formats'])) {
118
            $loader->load('access_denied_listener.xml');
119
120 50
            $service = $container->getDefinition('fos_rest.access_denied_listener');
121
122 50
            if (!empty($config['access_denied_listener']['service'])) {
123
                $service->clearTag('kernel.event_subscriber');
124 50
            }
125 2
126
            $service->replaceArgument(0, $config['access_denied_listener']['formats']);
127
            $service->replaceArgument(1, $config['unauthorized_challenge']);
128
        }
129
    }
130 2
131 View Code Duplication
    private function loadAllowedMethodsListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
132 2
    {
133 2
        if ($config['allowed_methods_listener']['enabled']) {
134 50
            if (!empty($config['allowed_methods_listener']['service'])) {
135
                $service = $container->getDefinition('fos_rest.allowed_methods_listener');
136 50
                $service->clearTag('kernel.event_listener');
137
            }
138 50
139 49
            $loader->load('allowed_methods_listener.xml');
140
141 49
            $container->getDefinition('fos_rest.allowed_methods_loader')->replaceArgument(1, $config['cache_dir']);
142
        }
143 49
    }
144
145
    private function loadBodyListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
146
    {
147 49
        if ($config['body_listener']['enabled']) {
148 49
            $loader->load('body_listener.xml');
149
150 49
            $service = $container->getDefinition('fos_rest.body_listener');
151
152 49
            if (!empty($config['body_listener']['service'])) {
153
                $service->clearTag('kernel.event_listener');
154 49
            }
155 3
156 3
            $service->replaceArgument(1, $config['body_listener']['throw_exception_on_unsupported_content_type']);
157 3
            $service->addMethodCall('setDefaultFormat', array($config['body_listener']['default_format']));
158 3
159 49
            $container->getDefinition('fos_rest.decoder_provider')->replaceArgument(1, $config['body_listener']['decoders']);
160 50
161
            if (class_exists(ServiceLocatorTagPass::class)) {
162 50
                $decoderServicesMap = array();
163
164 50
                foreach ($config['body_listener']['decoders'] as $id) {
165 6
                    $decoderServicesMap[$id] = new Reference($id);
166
                }
167 6
168
                $decodersServiceLocator = ServiceLocatorTagPass::register($container, $decoderServicesMap);
169
                $container->getDefinition('fos_rest.decoder_provider')->replaceArgument(0, $decodersServiceLocator);
170
            }
171
172 6
            $arrayNormalizer = $config['body_listener']['array_normalizer'];
173 6
174 6
            if (null !== $arrayNormalizer['service']) {
175 6
                $bodyListener = $container->getDefinition('fos_rest.body_listener');
176 6
                $bodyListener->addArgument(new Reference($arrayNormalizer['service']));
177 50
                $bodyListener->addArgument($arrayNormalizer['forms']);
178
            }
179 50
        }
180
    }
181 50
182 2
    private function loadFormatListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
183
    {
184 2 View Code Duplication
        if ($config['format_listener']['enabled'] && !empty($config['format_listener']['rules'])) {
185 2
            $loader->load('format_listener.xml');
186
187 2
            if (!empty($config['format_listener']['service'])) {
188 2
                $service = $container->getDefinition('fos_rest.format_listener');
189 2
                $service->clearTag('kernel.event_listener');
190 2
            }
191 2
192 2
            $container->setParameter(
193 2
                'fos_rest.format_listener.rules',
194 2
                $config['format_listener']['rules']
195 2
            );
196 2
        }
197 2
    }
198 2
199 2
    private function loadVersioning(array $config, XmlFileLoader $loader, ContainerBuilder $container)
200
    {
201 2
        if (!empty($config['versioning']['enabled'])) {
202 2
            $loader->load('versioning.xml');
203 2
204 2
            $versionListener = $container->getDefinition('fos_rest.versioning.listener');
205 2
            $versionListener->replaceArgument(2, $config['versioning']['default_version']);
206 2
207 2
            $resolvers = [];
208 50 View Code Duplication
            if ($config['versioning']['resolvers']['query']['enabled']) {
209
                $resolvers['query'] = $container->getDefinition('fos_rest.versioning.query_parameter_resolver');
210 50
                $resolvers['query']->replaceArgument(0, $config['versioning']['resolvers']['query']['parameter_name']);
211
            }
212 50 View Code Duplication
            if ($config['versioning']['resolvers']['custom_header']['enabled']) {
213 4
                $resolvers['custom_header'] = $container->getDefinition('fos_rest.versioning.header_resolver');
214
                $resolvers['custom_header']->replaceArgument(0, $config['versioning']['resolvers']['custom_header']['header_name']);
215 4
            }
216 View Code Duplication
            if ($config['versioning']['resolvers']['media_type']['enabled']) {
217
                $resolvers['media_type'] = $container->getDefinition('fos_rest.versioning.media_type_resolver');
218
                $resolvers['media_type']->replaceArgument(0, $config['versioning']['resolvers']['media_type']['regex']);
219
            }
220 4
221 1
            $chainResolver = $container->getDefinition('fos_rest.versioning.chain_resolver');
222 1
            foreach ($config['versioning']['guessing_order'] as $resolver) {
223 4
                if (isset($resolvers[$resolver])) {
224 50
                    $chainResolver->addMethodCall('addResolver', [$resolvers[$resolver]]);
225
                }
226 50
            }
227
        }
228 50
    }
229
230 View Code Duplication
    private function loadParamFetcherListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
231
    {
232 50
        if ($config['param_fetcher_listener']['enabled']) {
233 2
            $loader->load('param_fetcher_listener.xml');
234
235 2
            if (!empty($config['param_fetcher_listener']['service'])) {
236 2
                $service = $container->getDefinition('fos_rest.param_fetcher_listener');
237 2
                $service->clearTag('kernel.event_listener');
238 2
            }
239
240 50
            if ($config['param_fetcher_listener']['force']) {
241 2
                $container->getDefinition('fos_rest.param_fetcher_listener')->replaceArgument(1, true);
242 2
            }
243 50
        }
244
    }
245 50
246
    private function loadBodyConverter(array $config, XmlFileLoader $loader, ContainerBuilder $container)
247 50
    {
248 1
        if (!$this->isConfigEnabled($container, $config['body_converter'])) {
249 1
            return;
250
        }
251 1
252 1
        $loader->load('request_body_param_converter.xml');
253 1
254
        if (!empty($config['body_converter']['validation_errors_argument'])) {
255 1
            $container->getDefinition('fos_rest.converter.request_body')->replaceArgument(4, $config['body_converter']['validation_errors_argument']);
256
        }
257 1
    }
258 1
259 1
    private function loadView(array $config, XmlFileLoader $loader, ContainerBuilder $container)
260 1
    {
261
        if (!empty($config['view']['jsonp_handler'])) {
262 50
            $childDefinitionClass = class_exists(ChildDefinition::class) ? ChildDefinition::class : DefinitionDecorator::class;
263 2
            $handler = new $childDefinitionClass($config['service']['view_handler']);
264
            $handler->setPublic(true);
265 2
266
            $jsonpHandler = new Reference('fos_rest.view_handler.jsonp');
267
            $handler->addMethodCall('registerHandler', ['jsonp', [$jsonpHandler, 'createResponse']]);
268
            $container->setDefinition('fos_rest.view_handler', $handler);
269
270 2
            $container->getDefinition('fos_rest.view_handler.jsonp')->replaceArgument(0, $config['view']['jsonp_handler']['callback_param']);
271 2
272
            if (empty($config['view']['mime_types']['jsonp'])) {
273 50
                $config['view']['mime_types']['jsonp'] = $config['view']['jsonp_handler']['mime_type'];
274 8
            }
275 8
        }
276
277 8 View Code Duplication
        if ($config['view']['mime_types']['enabled']) {
278
            $loader->load('mime_type_listener.xml');
279
280
            if (!empty($config['mime_type_listener']['service'])) {
281 8
                $service = $container->getDefinition('fos_rest.mime_type_listener');
282 8
                $service->clearTag('kernel.event_listener');
283
            }
284 50
285 50
            $container->getDefinition('fos_rest.mime_type_listener')->replaceArgument(0, $config['view']['mime_types']['formats']);
286 50
        }
287 50
288 50 View Code Duplication
        if ($config['view']['view_response_listener']['enabled']) {
289 50
            $loader->load('view_response_listener.xml');
290 50
            $service = $container->getDefinition('fos_rest.view_response_listener');
291 50
292 50
            if (!empty($config['view_response_listener']['service'])) {
293 50
                $service->clearTag('kernel.event_listener');
294 50
            }
295
296 50
            $service->replaceArgument(1, $config['view']['view_response_listener']['force']);
297 50
        }
298 50
299
        $formats = [];
300 50 View Code Duplication
        foreach ($config['view']['formats'] as $format => $enabled) {
301 50
            if ($enabled) {
302 50
                $formats[$format] = false;
303 50
            }
304 50
        }
305 View Code Duplication
        foreach ($config['view']['templating_formats'] as $format => $enabled) {
306 50
            if ($enabled) {
307
                $formats[$format] = true;
308
            }
309
        }
310 50
311 50
        $container->getDefinition('fos_rest.routing.loader.yaml_collection')->replaceArgument(3, $formats);
312 50
        $container->getDefinition('fos_rest.routing.loader.xml_collection')->replaceArgument(3, $formats);
313
        $container->getDefinition('fos_rest.routing.loader.reader.action')->replaceArgument(4, $formats);
314 50
315
        foreach ($config['view']['force_redirects'] as $format => $code) {
316
            if (true === $code) {
317
                $config['view']['force_redirects'][$format] = Response::HTTP_FOUND;
318 50
            }
319 50
        }
320 50
321 50 View Code Duplication
        if (!is_numeric($config['view']['failed_validation'])) {
322 50
            $config['view']['failed_validation'] = constant('\Symfony\Component\HttpFoundation\Response::'.$config['view']['failed_validation']);
323
        }
324 50
325
        $defaultViewHandler = $container->getDefinition('fos_rest.view_handler.default');
326 50
        $defaultViewHandler->replaceArgument(4, $formats);
327 14
        $defaultViewHandler->replaceArgument(5, $config['view']['failed_validation']);
328
329 14 View Code Duplication
        if (!is_numeric($config['view']['empty_content'])) {
330
            $config['view']['empty_content'] = constant('\Symfony\Component\HttpFoundation\Response::'.$config['view']['empty_content']);
331
        }
332
333
        $defaultViewHandler->replaceArgument(6, $config['view']['empty_content']);
334 14
        $defaultViewHandler->replaceArgument(7, $config['view']['serialize_null']);
335
        $defaultViewHandler->replaceArgument(8, $config['view']['force_redirects']);
336 14
        $defaultViewHandler->replaceArgument(9, $config['view']['default_engine']);
337 4
    }
338 4
339
    private function loadException(array $config, XmlFileLoader $loader, ContainerBuilder $container)
340 14
    {
341 14
        if ($config['exception']['enabled']) {
342 14
            $loader->load('exception_listener.xml');
343 14
344
            if (!empty($config['exception']['service'])) {
345 14
                $service = $container->getDefinition('fos_rest.exception_listener');
346 14
                $service->clearTag('kernel.event_subscriber');
347 14
            }
348 14
349 14
            if (Kernel::VERSION_ID >= 40100) {
350 14
                $controller = 'fos_rest.exception.controller::showAction';
351 14
            } else {
352 50
                $controller = 'fos_rest.exception.controller:showAction';
353
            }
354 50
355
            if ($config['exception']['exception_controller']) {
356 50
                $controller = $config['exception']['exception_controller'];
357 50
            } elseif (isset($container->getParameter('kernel.bundles')['TwigBundle'])) {
358
                if (Kernel::VERSION_ID >= 40100) {
359 50
                    $controller = 'fos_rest.exception.twig_controller::showAction';
360 1
                } else {
361
                    $controller = 'fos_rest.exception.twig_controller:showAction';
362
                }
363 1
            }
364 1
365
            $container->getDefinition('fos_rest.exception_listener')->replaceArgument(0, $controller);
366 50
367 1
            $container->getDefinition('fos_rest.exception.codes_map')
368
                ->replaceArgument(0, $config['exception']['codes']);
369
            $container->getDefinition('fos_rest.exception.messages_map')
370 1
                ->replaceArgument(0, $config['exception']['messages']);
371 1
372
            $container->getDefinition('fos_rest.exception.controller')
373 50
                ->replaceArgument(2, $config['exception']['debug']);
374 50
            $container->getDefinition('fos_rest.serializer.exception_normalizer.jms')
375
                ->replaceArgument(1, $config['exception']['debug']);
376 50
            $container->getDefinition('fos_rest.serializer.exception_normalizer.symfony')
377
                ->replaceArgument(1, $config['exception']['debug']);
378 50
        }
379 2
    }
380 2
381
    private function loadSerializer(array $config, ContainerBuilder $container)
382 2
    {
383 2
        $bodyConverter = $container->hasDefinition('fos_rest.converter.request_body') ? $container->getDefinition('fos_rest.converter.request_body') : null;
384 2
        $viewHandler = $container->getDefinition('fos_rest.view_handler.default');
385 2
386 2 View Code Duplication
        if (!empty($config['serializer']['version'])) {
387 2
            if ($bodyConverter) {
388 2
                $bodyConverter->replaceArgument(2, $config['serializer']['version']);
389
            }
390 2
            $viewHandler->addMethodCall('setExclusionStrategyVersion', array($config['serializer']['version']));
391 2
        }
392 2
393 50 View Code Duplication
        if (!empty($config['serializer']['groups'])) {
394
            if ($bodyConverter) {
395 2
                $bodyConverter->replaceArgument(1, $config['serializer']['groups']);
396
            }
397 2
            $viewHandler->addMethodCall('setExclusionStrategyGroups', array($config['serializer']['groups']));
398
        }
399
400
        $viewHandler->addMethodCall('setSerializeNullStrategy', array($config['serializer']['serialize_null']));
401 2
    }
402 2
403
    private function loadZoneMatcherListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
404
    {
405 2
        if (!empty($config['zone'])) {
406 2
            $loader->load('zone_matcher_listener.xml');
407 2
            $zoneMatcherListener = $container->getDefinition('fos_rest.zone_matcher_listener');
408 2
409
            foreach ($config['zone'] as $zone) {
410
                $matcher = $this->createZoneRequestMatcher($container,
411 2
                    $zone['path'],
412 2
                    $zone['host'],
413
                    $zone['methods'],
414
                    $zone['ips']
415 2
                );
416
417
                $zoneMatcherListener->addMethodCall('addRequestMatcher', array($matcher));
418
            }
419
        }
420
    }
421
422
    private function createZoneRequestMatcher(ContainerBuilder $container, $path = null, $host = null, $methods = array(), $ip = null)
423
    {
424
        if ($methods) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $methods of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
425
            $methods = array_map('strtoupper', (array) $methods);
426
        }
427
428
        $serialized = serialize(array($path, $host, $methods, $ip));
429
        $id = 'fos_rest.zone_request_matcher.'.md5($serialized).sha1($serialized);
430
431
        // only add arguments that are necessary
432
        $arguments = array($path, $host, $methods, $ip);
433
        while (count($arguments) > 0 && !end($arguments)) {
434
            array_pop($arguments);
435
        }
436
437
        $childDefinitionClass = class_exists(ChildDefinition::class) ? ChildDefinition::class : DefinitionDecorator::class;
438
        $container
439
            ->setDefinition($id, new $childDefinitionClass('fos_rest.zone_request_matcher'))
440
            ->setArguments($arguments)
441
        ;
442
443
        return new Reference($id);
444
    }
445
}
446