Completed
Push — master ( f986e2...b5207e )
by Guilh
07:46
created

FOSRestExtension::loadException()   B

Complexity

Conditions 5
Paths 7

Size

Total Lines 29
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 5.1158

Importance

Changes 0
Metric Value
dl 0
loc 29
ccs 20
cts 24
cp 0.8333
rs 8.439
c 0
b 0
f 0
cc 5
eloc 20
nc 7
nop 3
crap 5.1158
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\ContainerBuilder;
16
use Symfony\Component\DependencyInjection\DefinitionDecorator;
17
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
18
use Symfony\Component\DependencyInjection\Reference;
19
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
20
use Symfony\Component\HttpFoundation\Response;
21
22
class FOSRestExtension extends Extension
23
{
24
    /**
25
     * {@inheritdoc}
26
     */
27 1
    public function getConfiguration(array $config, ContainerBuilder $container)
28
    {
29 1
        return new Configuration($container->getParameter('kernel.debug'));
30
    }
31
32
    /**
33
     * Loads the services based on your application configuration.
34
     *
35
     * @param array            $configs
36
     * @param ContainerBuilder $container
37
     *
38
     * @throws \InvalidArgumentException
39
     * @throws \LogicException
40
     */
41 55
    public function load(array $configs, ContainerBuilder $container)
42
    {
43 55
        $configuration = new Configuration($container->getParameter('kernel.debug'));
44 55
        $config = $this->processConfiguration($configuration, $configs);
45
46 50
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
47 50
        $loader->load('view.xml');
48 50
        $loader->load('routing.xml');
49 50
        $loader->load('request.xml');
50 50
        $loader->load('serializer.xml');
51
52 50
        $container->getDefinition('fos_rest.routing.loader.controller')->replaceArgument(4, $config['routing_loader']['default_format']);
53 50
        $container->getDefinition('fos_rest.routing.loader.yaml_collection')->replaceArgument(4, $config['routing_loader']['default_format']);
54 50
        $container->getDefinition('fos_rest.routing.loader.xml_collection')->replaceArgument(4, $config['routing_loader']['default_format']);
55
56 50
        $container->getDefinition('fos_rest.routing.loader.yaml_collection')->replaceArgument(2, $config['routing_loader']['include_format']);
57 50
        $container->getDefinition('fos_rest.routing.loader.xml_collection')->replaceArgument(2, $config['routing_loader']['include_format']);
58 50
        $container->getDefinition('fos_rest.routing.loader.reader.action')->replaceArgument(3, $config['routing_loader']['include_format']);
59
60
        // The validator service alias is only set if validation is enabled for the request body converter
61 50
        $validator = $config['service']['validator'];
62 50
        unset($config['service']['validator']);
63
64 50
        foreach ($config['service'] as $key => $service) {
65 50
            if (null !== $service) {
66 50
                $container->setAlias('fos_rest.'.$key, $service);
67 50
            }
68 50
        }
69
70 50
        $this->loadForm($config, $loader, $container);
71 50
        $this->loadException($config, $loader, $container);
72 50
        $this->loadBodyConverter($config, $validator, $loader, $container);
73 50
        $this->loadView($config, $loader, $container);
74
75 50
        $this->loadBodyListener($config, $loader, $container);
76 50
        $this->loadFormatListener($config, $loader, $container);
77 50
        $this->loadVersioning($config, $loader, $container);
78 50
        $this->loadParamFetcherListener($config, $loader, $container);
79 50
        $this->loadAllowedMethodsListener($config, $loader, $container);
80 50
        $this->loadAccessDeniedListener($config, $loader, $container);
81 50
        $this->loadZoneMatcherListener($config, $loader, $container);
82
83
        // Needs RequestBodyParamConverter and View Handler loaded.
84 50
        $this->loadSerializer($config, $container);
85 50
    }
86
87 50
    private function loadForm(array $config, XmlFileLoader $loader, ContainerBuilder $container)
88
    {
89 50
        if (!empty($config['disable_csrf_role'])) {
90 1
            $loader->load('forms.xml');
91 1
            $container->getDefinition('fos_rest.form.extension.csrf_disable')->replaceArgument(1, $config['disable_csrf_role']);
92 1
        }
93 50
    }
94
95 50
    private function loadAccessDeniedListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
96
    {
97 50
        if ($config['access_denied_listener']['enabled'] && !empty($config['access_denied_listener']['formats'])) {
98
            $loader->load('access_denied_listener.xml');
99
100
            $service = $container->getDefinition('fos_rest.access_denied_listener');
101
102
            if (!empty($config['access_denied_listener']['service'])) {
103
                $service->clearTag('kernel.event_subscriber');
104
            }
105
106
            $service->replaceArgument(0, $config['access_denied_listener']['formats']);
107
            $service->replaceArgument(1, $config['unauthorized_challenge']);
108
        }
109 50
    }
110
111 50 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...
112
    {
113 50
        if ($config['allowed_methods_listener']['enabled']) {
114 2
            if (!empty($config['allowed_methods_listener']['service'])) {
115
                $service = $container->getDefinition('fos_rest.allowed_methods_listener');
116
                $service->clearTag('kernel.event_listener');
117
            }
118
119 2
            $loader->load('allowed_methods_listener.xml');
120
121 2
            $container->getDefinition('fos_rest.allowed_methods_loader')->replaceArgument(1, $config['cache_dir']);
122 2
        }
123 50
    }
124
125 50
    private function loadBodyListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
126
    {
127 50
        if ($config['body_listener']['enabled']) {
128 49
            $loader->load('body_listener.xml');
129
130 49
            $service = $container->getDefinition('fos_rest.body_listener');
131
132 49
            if (!empty($config['body_listener']['service'])) {
133
                $service->clearTag('kernel.event_listener');
134
            }
135
136 49
            $service->replaceArgument(1, $config['body_listener']['throw_exception_on_unsupported_content_type']);
137 49
            $service->addMethodCall('setDefaultFormat', array($config['body_listener']['default_format']));
138
139 49
            $container->getDefinition('fos_rest.decoder_provider')->replaceArgument(1, $config['body_listener']['decoders']);
140
141 49
            $arrayNormalizer = $config['body_listener']['array_normalizer'];
142
143 49
            if (null !== $arrayNormalizer['service']) {
144 3
                $bodyListener = $container->getDefinition('fos_rest.body_listener');
145 3
                $bodyListener->addArgument(new Reference($arrayNormalizer['service']));
146 3
                $bodyListener->addArgument($arrayNormalizer['forms']);
147 3
            }
148 49
        }
149 50
    }
150
151 50
    private function loadFormatListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
152
    {
153 50 View Code Duplication
        if ($config['format_listener']['enabled'] && !empty($config['format_listener']['rules'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
154 6
            $loader->load('format_listener.xml');
155
156 6
            if (!empty($config['format_listener']['service'])) {
157
                $service = $container->getDefinition('fos_rest.format_listener');
158
                $service->clearTag('kernel.event_listener');
159
            }
160
161 6
            $container->setParameter(
162 6
                'fos_rest.format_listener.rules',
163 6
                $config['format_listener']['rules']
164 6
            );
165 6
        }
166 50
    }
167
168 50
    private function loadVersioning(array $config, XmlFileLoader $loader, ContainerBuilder $container)
169
    {
170 50
        if (!empty($config['versioning']['enabled'])) {
171 2
            $loader->load('versioning.xml');
172
173 2
            $versionListener = $container->getDefinition('fos_rest.versioning.listener');
174 2
            $versionListener->replaceArgument(2, $config['versioning']['default_version']);
175
176 2
            $resolvers = [];
177 2 View Code Duplication
            if ($config['versioning']['resolvers']['query']['enabled']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
178 2
                $resolvers['query'] = $container->getDefinition('fos_rest.versioning.query_parameter_resolver');
179 2
                $resolvers['query']->replaceArgument(0, $config['versioning']['resolvers']['query']['parameter_name']);
180 2
            }
181 2 View Code Duplication
            if ($config['versioning']['resolvers']['custom_header']['enabled']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
182 2
                $resolvers['custom_header'] = $container->getDefinition('fos_rest.versioning.header_resolver');
183 2
                $resolvers['custom_header']->replaceArgument(0, $config['versioning']['resolvers']['custom_header']['header_name']);
184 2
            }
185 2 View Code Duplication
            if ($config['versioning']['resolvers']['media_type']['enabled']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
186 2
                $resolvers['media_type'] = $container->getDefinition('fos_rest.versioning.media_type_resolver');
187 2
                $resolvers['media_type']->replaceArgument(0, $config['versioning']['resolvers']['media_type']['regex']);
188 2
            }
189
190 2
            $chainResolver = $container->getDefinition('fos_rest.versioning.chain_resolver');
191 2
            foreach ($config['versioning']['guessing_order'] as $resolver) {
192 2
                if (isset($resolvers[$resolver])) {
193 2
                    $chainResolver->addMethodCall('addResolver', [$resolvers[$resolver]]);
194 2
                }
195 2
            }
196 2
        }
197 50
    }
198
199 50 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...
200
    {
201 50
        if ($config['param_fetcher_listener']['enabled']) {
202 4
            $loader->load('param_fetcher_listener.xml');
203
204 4
            if (!empty($config['param_fetcher_listener']['service'])) {
205
                $service = $container->getDefinition('fos_rest.param_fetcher_listener');
206
                $service->clearTag('kernel.event_listener');
207
            }
208
209 4
            if ($config['param_fetcher_listener']['force']) {
210 1
                $container->getDefinition('fos_rest.param_fetcher_listener')->replaceArgument(1, true);
211 1
            }
212 4
        }
213 50
    }
214
215 50
    private function loadBodyConverter(array $config, $validator, XmlFileLoader $loader, ContainerBuilder $container)
216
    {
217 50
        if (empty($config['body_converter'])) {
218
            return;
219
        }
220
221 50
        if (!empty($config['body_converter']['enabled'])) {
222 2
            $loader->load('request_body_param_converter.xml');
223
224 2
            if (!empty($config['body_converter']['validation_errors_argument'])) {
225 2
                $container->getDefinition('fos_rest.converter.request_body')->replaceArgument(4, $config['body_converter']['validation_errors_argument']);
226 2
            }
227 2
        }
228
229 50
        if (!empty($config['body_converter']['validate'])) {
230 2
            $container->setAlias('fos_rest.validator', $validator);
231 2
        }
232 50
    }
233
234 50
    private function loadView(array $config, XmlFileLoader $loader, ContainerBuilder $container)
235
    {
236 50
        if (!empty($config['view']['jsonp_handler'])) {
237 1
            $handler = new DefinitionDecorator($config['service']['view_handler']);
238 1
            $handler->setPublic(true);
239
240 1
            $jsonpHandler = new Reference('fos_rest.view_handler.jsonp');
241 1
            $handler->addMethodCall('registerHandler', ['jsonp', [$jsonpHandler, 'createResponse']]);
242 1
            $container->setDefinition('fos_rest.view_handler', $handler);
243
244 1
            $container->getDefinition('fos_rest.view_handler.jsonp')->replaceArgument(0, $config['view']['jsonp_handler']['callback_param']);
245
246 1
            if (empty($config['view']['mime_types']['jsonp'])) {
247 1
                $config['view']['mime_types']['jsonp'] = $config['view']['jsonp_handler']['mime_type'];
248 1
            }
249 1
        }
250
251 50 View Code Duplication
        if ($config['view']['mime_types']['enabled']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
252 2
            $loader->load('mime_type_listener.xml');
253
254 2
            if (!empty($config['mime_type_listener']['service'])) {
255
                $service = $container->getDefinition('fos_rest.mime_type_listener');
256
                $service->clearTag('kernel.event_listener');
257
            }
258
259 2
            $container->getDefinition('fos_rest.mime_type_listener')->replaceArgument(0, $config['view']['mime_types']['formats']);
260 2
        }
261
262 50 View Code Duplication
        if ($config['view']['view_response_listener']['enabled']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
263 8
            $loader->load('view_response_listener.xml');
264 8
            $service = $container->getDefinition('fos_rest.view_response_listener');
265
266 8
            if (!empty($config['view_response_listener']['service'])) {
267
                $service->clearTag('kernel.event_listener');
268
            }
269
270 8
            $service->replaceArgument(1, $config['view']['view_response_listener']['force']);
271 8
        }
272
273 50
        $formats = [];
274 50 View Code Duplication
        foreach ($config['view']['formats'] as $format => $enabled) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
275 50
            if ($enabled) {
276 50
                $formats[$format] = false;
277 50
            }
278 50
        }
279 50 View Code Duplication
        foreach ($config['view']['templating_formats'] as $format => $enabled) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
280 50
            if ($enabled) {
281 50
                $formats[$format] = true;
282 50
            }
283 50
        }
284
285 50
        $container->getDefinition('fos_rest.routing.loader.yaml_collection')->replaceArgument(3, $formats);
286 50
        $container->getDefinition('fos_rest.routing.loader.xml_collection')->replaceArgument(3, $formats);
287 50
        $container->getDefinition('fos_rest.routing.loader.reader.action')->replaceArgument(4, $formats);
288
289 50
        foreach ($config['view']['force_redirects'] as $format => $code) {
290 50
            if (true === $code) {
291 50
                $config['view']['force_redirects'][$format] = Response::HTTP_FOUND;
292 50
            }
293 50
        }
294
295 50 View Code Duplication
        if (!is_numeric($config['view']['failed_validation'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
296
            $config['view']['failed_validation'] = constant('\Symfony\Component\HttpFoundation\Response::'.$config['view']['failed_validation']);
297
        }
298
299 50
        $defaultViewHandler = $container->getDefinition('fos_rest.view_handler.default');
300 50
        $defaultViewHandler->replaceArgument(4, $formats);
301 50
        $defaultViewHandler->replaceArgument(5, $config['view']['failed_validation']);
302
303 50 View Code Duplication
        if (!is_numeric($config['view']['empty_content'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
304
            $config['view']['empty_content'] = constant('\Symfony\Component\HttpFoundation\Response::'.$config['view']['empty_content']);
305
        }
306
307 50
        $defaultViewHandler->replaceArgument(6, $config['view']['empty_content']);
308 50
        $defaultViewHandler->replaceArgument(7, $config['view']['serialize_null']);
309 50
        $defaultViewHandler->replaceArgument(8, $config['view']['force_redirects']);
310 50
        $defaultViewHandler->replaceArgument(9, $config['view']['default_engine']);
311 50
    }
312
313 50
    private function loadException(array $config, XmlFileLoader $loader, ContainerBuilder $container)
314
    {
315 50
        if ($config['exception']['enabled']) {
316 14
            $loader->load('exception_listener.xml');
317
318 14
            if (!empty($config['exception']['service'])) {
319
                $service = $container->getDefinition('fos_rest.exception_listener');
320
                $service->clearTag('kernel.event_subscriber');
321
            }
322
323 14
            if ($config['exception']['exception_controller']) {
324
                $container->getDefinition('fos_rest.exception_listener')->replaceArgument(0, $config['exception']['exception_controller']);
325 14
            } elseif (isset($container->getParameter('kernel.bundles')['TwigBundle'])) {
326 4
                $container->getDefinition('fos_rest.exception_listener')->replaceArgument(0, 'fos_rest.exception.twig_controller:showAction');
327 4
            }
328
329 14
            $container->getDefinition('fos_rest.exception.codes_map')
330 14
                ->replaceArgument(0, $config['exception']['codes']);
331 14
            $container->getDefinition('fos_rest.exception.messages_map')
332 14
                ->replaceArgument(0, $config['exception']['messages']);
333
334 14
            $container->getDefinition('fos_rest.exception.controller')
335 14
                ->replaceArgument(2, $config['exception']['debug']);
336 14
            $container->getDefinition('fos_rest.serializer.exception_normalizer.jms')
337 14
                ->replaceArgument(1, $config['exception']['debug']);
338 14
            $container->getDefinition('fos_rest.serializer.exception_normalizer.symfony')
339 14
                ->replaceArgument(1, $config['exception']['debug']);
340 14
        }
341 50
    }
342
343 50
    private function loadSerializer(array $config, ContainerBuilder $container)
344
    {
345 50
        $bodyConverter = $container->hasDefinition('fos_rest.converter.request_body') ? $container->getDefinition('fos_rest.converter.request_body') : null;
346 50
        $viewHandler = $container->getDefinition('fos_rest.view_handler.default');
347
348 50 View Code Duplication
        if (!empty($config['serializer']['version'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
349 1
            if ($bodyConverter) {
350
                $bodyConverter->replaceArgument(2, $config['serializer']['version']);
351
            }
352 1
            $viewHandler->addMethodCall('setExclusionStrategyVersion', array($config['serializer']['version']));
353 1
        }
354
355 50 View Code Duplication
        if (!empty($config['serializer']['groups'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
356 1
            if ($bodyConverter) {
357
                $bodyConverter->replaceArgument(1, $config['serializer']['groups']);
358
            }
359 1
            $viewHandler->addMethodCall('setExclusionStrategyGroups', array($config['serializer']['groups']));
360 1
        }
361
362 50
        $viewHandler->addMethodCall('setSerializeNullStrategy', array($config['serializer']['serialize_null']));
363 50
    }
364
365 50
    private function loadZoneMatcherListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
366
    {
367 50
        if (!empty($config['zone'])) {
368 2
            $loader->load('zone_matcher_listener.xml');
369 2
            $zoneMatcherListener = $container->getDefinition('fos_rest.zone_matcher_listener');
370
371 2
            foreach ($config['zone'] as $zone) {
372 2
                $matcher = $this->createZoneRequestMatcher($container,
373 2
                    $zone['path'],
374 2
                    $zone['host'],
375 2
                    $zone['methods'],
376 2
                    $zone['ips']
377 2
                );
378
379 2
                $zoneMatcherListener->addMethodCall('addRequestMatcher', array($matcher));
380 2
            }
381 2
        }
382 50
    }
383
384 2
    private function createZoneRequestMatcher(ContainerBuilder $container, $path = null, $host = null, $methods = array(), $ip = null)
385
    {
386 2
        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...
387
            $methods = array_map('strtoupper', (array) $methods);
388
        }
389
390 2
        $serialized = serialize(array($path, $host, $methods, $ip));
391 2
        $id = 'fos_rest.zone_request_matcher.'.md5($serialized).sha1($serialized);
392
393
        // only add arguments that are necessary
394 2
        $arguments = array($path, $host, $methods, $ip);
395 2
        while (count($arguments) > 0 && !end($arguments)) {
396 2
            array_pop($arguments);
397 2
        }
398
399
        $container
400 2
            ->setDefinition($id, new DefinitionDecorator('fos_rest.zone_request_matcher'))
401 2
            ->setArguments($arguments)
402
        ;
403
404 2
        return new Reference($id);
405
    }
406
}
407