Completed
Push — 2.x ( 0e1f1b...77cf8b )
by Christian
41s queued 16s
created

FOSRestExtension::loadView()   F

Complexity

Conditions 20
Paths 19440

Size

Total Lines 102

Duplication

Lines 36
Ratio 35.29 %

Code Coverage

Tests 60
CRAP Score 20.1819

Importance

Changes 0
Metric Value
dl 36
loc 102
ccs 60
cts 65
cp 0.9231
rs 0
c 0
b 0
f 0
cc 20
nc 19440
nop 3
crap 20.1819

How to fix   Long Method    Complexity   

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 FOS\RestBundle\View\ViewHandler;
15
use Symfony\Component\Config\FileLocator;
16
use Symfony\Component\DependencyInjection\Alias;
17
use Symfony\Component\DependencyInjection\ChildDefinition;
18
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
19
use Symfony\Component\DependencyInjection\ContainerBuilder;
20
use Symfony\Component\DependencyInjection\ContainerInterface;
21
use Symfony\Component\DependencyInjection\DefinitionDecorator;
22
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
23
use Symfony\Component\DependencyInjection\Reference;
24
use Symfony\Component\Form\AbstractType;
25
use Symfony\Component\Form\Extension\Core\Type\FormType;
26
use Symfony\Component\HttpFoundation\Response;
27
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
28
use Symfony\Component\Validator\Constraint;
29
30
class FOSRestExtension extends Extension
31
{
32
    /**
33
     * {@inheritdoc}
34
     */
35 16
    public function getConfiguration(array $config, ContainerBuilder $container)
36
    {
37 16
        return new Configuration($container->getParameter('kernel.debug'));
38
    }
39
40 58
    public function load(array $configs, ContainerBuilder $container)
41
    {
42 58
        $configuration = new Configuration($container->getParameter('kernel.debug'));
43 58
        $config = $this->processConfiguration($configuration, $configs);
44
45 53
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
46 53
        $loader->load('view.xml');
47 53
        $loader->load('routing.xml');
48 53
        $loader->load('request.xml');
49 53
        $loader->load('serializer.xml');
50
51 53
        $restRouteLoader = $container->getDefinition('fos_rest.routing.loader.controller');
52
53 53
        if ($config['routing_loader']['parse_controller_name']) {
54 4
            $restRouteLoader->addArgument(new Reference('controller_name_converter', ContainerInterface::NULL_ON_INVALID_REFERENCE));
55
        }
56
57 53
        $restRouteLoader->addArgument(new Reference('fos_rest.routing.loader.reader.controller'));
58 53
        $restRouteLoader->addArgument($config['routing_loader']['default_format']);
59
60 53
        $container->getDefinition('fos_rest.routing.loader.yaml_collection')->replaceArgument(4, $config['routing_loader']['default_format']);
61 53
        $container->getDefinition('fos_rest.routing.loader.xml_collection')->replaceArgument(4, $config['routing_loader']['default_format']);
62
63 53
        $container->getDefinition('fos_rest.routing.loader.yaml_collection')->replaceArgument(2, $config['routing_loader']['include_format']);
64 53
        $container->getDefinition('fos_rest.routing.loader.xml_collection')->replaceArgument(2, $config['routing_loader']['include_format']);
65 53
        $container->getDefinition('fos_rest.routing.loader.reader.action')->replaceArgument(3, $config['routing_loader']['include_format']);
66 53
        $container->getDefinition('fos_rest.routing.loader.reader.action')->replaceArgument(5, $config['routing_loader']['prefix_methods']);
67
68 53
        foreach ($config['service'] as $key => $service) {
69 53
            if ('validator' === $service && empty($config['body_converter']['validate'])) {
70 50
                continue;
71
            }
72
73 53
            if (null !== $service) {
74 53
                if ('view_handler' === $key) {
75 53
                    $container->setAlias('fos_rest.'.$key, new Alias($service, true));
76 53
                } elseif('templating' === $key) {
77 6
                    $alias = new Alias($service);
78
79 6
                    if (method_exists($alias, 'setDeprecated')) {
80 6
                        $alias->setDeprecated(true, 'The "%alias_id%" service alias is deprecated since FOSRestBundle 2.8.');
81
                    }
82
83 6
                    $container->setAlias('fos_rest.'.$key, $alias);
84
                } else {
85 53
                    $container->setAlias('fos_rest.'.$key, $service);
86
                }
87
            }
88
        }
89
90 53
        $this->loadForm($config, $loader, $container);
91 53
        $this->loadException($config, $loader, $container);
92 53
        $this->loadBodyConverter($config, $loader, $container);
93 53
        $this->loadView($config, $loader, $container);
94
95 53
        $this->loadBodyListener($config, $loader, $container);
96 53
        $this->loadFormatListener($config, $loader, $container);
97 53
        $this->loadVersioning($config, $loader, $container);
98 53
        $this->loadParamFetcherListener($config, $loader, $container);
99 53
        $this->loadAllowedMethodsListener($config, $loader, $container);
100 53
        $this->loadAccessDeniedListener($config, $loader, $container);
101 53
        $this->loadZoneMatcherListener($config, $loader, $container);
102
103
        // Needs RequestBodyParamConverter and View Handler loaded.
104 53
        $this->loadSerializer($config, $container);
105 53
    }
106
107 53
    private function loadForm(array $config, XmlFileLoader $loader, ContainerBuilder $container)
108
    {
109 53
        if (!empty($config['disable_csrf_role'])) {
110 2
            $loader->load('forms.xml');
111
112 2
            $definition = $container->getDefinition('fos_rest.form.extension.csrf_disable');
113 2
            $definition->replaceArgument(1, $config['disable_csrf_role']);
114
115
            // BC for Symfony < 2.8: the extended_type attribute is used on higher versions
116 2
            if (!method_exists(AbstractType::class, 'getBlockPrefix')) {
117
                $definition->addTag('form.type_extension', ['alias' => 'form']);
118
            } else {
119 2
                $definition->addTag('form.type_extension', ['extended_type' => FormType::class]);
120
            }
121
        }
122 53
    }
123
124 53
    private function loadAccessDeniedListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
125
    {
126 53
        if ($config['access_denied_listener']['enabled'] && !empty($config['access_denied_listener']['formats'])) {
127
            $loader->load('access_denied_listener.xml');
128
129
            $service = $container->getDefinition('fos_rest.access_denied_listener');
130
131
            if (!empty($config['access_denied_listener']['service'])) {
132
                $service->clearTag('kernel.event_subscriber');
133
            }
134
135
            $service->replaceArgument(0, $config['access_denied_listener']['formats']);
136
            $service->replaceArgument(1, $config['unauthorized_challenge']);
137
        }
138 53
    }
139
140 53
    private function loadAllowedMethodsListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
141
    {
142 53
        if ($config['allowed_methods_listener']['enabled']) {
143 3
            if (!empty($config['allowed_methods_listener']['service'])) {
144
                $service = $container->getDefinition('fos_rest.allowed_methods_listener');
145
                $service->clearTag('kernel.event_listener');
146
            }
147
148 3
            $loader->load('allowed_methods_listener.xml');
149
150 3
            $container->getDefinition('fos_rest.allowed_methods_loader')->replaceArgument(1, $config['cache_dir']);
151
        }
152 53
    }
153
154 53
    private function loadBodyListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
155
    {
156 53
        if ($config['body_listener']['enabled']) {
157 52
            $loader->load('body_listener.xml');
158
159 52
            $service = $container->getDefinition('fos_rest.body_listener');
160
161 52
            if (!empty($config['body_listener']['service'])) {
162
                $service->clearTag('kernel.event_listener');
163
            }
164
165 52
            $service->replaceArgument(1, $config['body_listener']['throw_exception_on_unsupported_content_type']);
166 52
            $service->addMethodCall('setDefaultFormat', array($config['body_listener']['default_format']));
167
168 52
            $container->getDefinition('fos_rest.decoder_provider')->replaceArgument(1, $config['body_listener']['decoders']);
169
170 52
            if (class_exists(ServiceLocatorTagPass::class)) {
171 52
                $decoderServicesMap = array();
172
173 52
                foreach ($config['body_listener']['decoders'] as $id) {
174 52
                    $decoderServicesMap[$id] = new Reference($id);
175
                }
176
177 52
                $decodersServiceLocator = ServiceLocatorTagPass::register($container, $decoderServicesMap);
178 52
                $container->getDefinition('fos_rest.decoder_provider')->replaceArgument(0, $decodersServiceLocator);
179
            }
180
181 52
            $arrayNormalizer = $config['body_listener']['array_normalizer'];
182
183 52
            if (null !== $arrayNormalizer['service']) {
184 3
                $bodyListener = $container->getDefinition('fos_rest.body_listener');
185 3
                $bodyListener->addArgument(new Reference($arrayNormalizer['service']));
186 3
                $bodyListener->addArgument($arrayNormalizer['forms']);
187
            }
188
        }
189 53
    }
190
191 53
    private function loadFormatListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
192
    {
193 53 View Code Duplication
        if ($config['format_listener']['enabled'] && !empty($config['format_listener']['rules'])) {
194 6
            $loader->load('format_listener.xml');
195
196 6
            if (!empty($config['format_listener']['service'])) {
197
                $service = $container->getDefinition('fos_rest.format_listener');
198
                $service->clearTag('kernel.event_listener');
199
            }
200
201 6
            $container->setParameter(
202 6
                'fos_rest.format_listener.rules',
203 6
                $config['format_listener']['rules']
204
            );
205
        }
206 53
    }
207
208 53
    private function loadVersioning(array $config, XmlFileLoader $loader, ContainerBuilder $container)
209
    {
210 53
        if (!empty($config['versioning']['enabled'])) {
211 2
            $loader->load('versioning.xml');
212
213 2
            $versionListener = $container->getDefinition('fos_rest.versioning.listener');
214 2
            $versionListener->replaceArgument(1, $config['versioning']['default_version']);
215
216 2
            $resolvers = [];
217 2 View Code Duplication
            if ($config['versioning']['resolvers']['query']['enabled']) {
218 2
                $resolvers['query'] = $container->getDefinition('fos_rest.versioning.query_parameter_resolver');
219 2
                $resolvers['query']->replaceArgument(0, $config['versioning']['resolvers']['query']['parameter_name']);
220
            }
221 2 View Code Duplication
            if ($config['versioning']['resolvers']['custom_header']['enabled']) {
222 2
                $resolvers['custom_header'] = $container->getDefinition('fos_rest.versioning.header_resolver');
223 2
                $resolvers['custom_header']->replaceArgument(0, $config['versioning']['resolvers']['custom_header']['header_name']);
224
            }
225 2 View Code Duplication
            if ($config['versioning']['resolvers']['media_type']['enabled']) {
226 2
                $resolvers['media_type'] = $container->getDefinition('fos_rest.versioning.media_type_resolver');
227 2
                $resolvers['media_type']->replaceArgument(0, $config['versioning']['resolvers']['media_type']['regex']);
228
            }
229
230 2
            $chainResolver = $container->getDefinition('fos_rest.versioning.chain_resolver');
231 2
            foreach ($config['versioning']['guessing_order'] as $resolver) {
232 2
                if (isset($resolvers[$resolver])) {
233 2
                    $chainResolver->addMethodCall('addResolver', [$resolvers[$resolver]]);
234
                }
235
            }
236
        }
237 53
    }
238
239 53
    private function loadParamFetcherListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
240
    {
241 53
        if ($config['param_fetcher_listener']['enabled']) {
242 5
            if (!class_exists(Constraint::class)) {
243
                @trigger_error('Enabling the fos_rest.param_fetcher_listener option when the Symfony Validator component is not installed is deprecated since FOSRestBundle 2.6 and will throw an exception in 3.0. Disable the feature or install the symfony/validator package.', 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...
244
            }
245
246 5
            $loader->load('param_fetcher_listener.xml');
247
248 5
            if (!empty($config['param_fetcher_listener']['service'])) {
249
                $service = $container->getDefinition('fos_rest.param_fetcher_listener');
250
                $service->clearTag('kernel.event_listener');
251
            }
252
253 5
            if ($config['param_fetcher_listener']['force']) {
254 1
                $container->getDefinition('fos_rest.param_fetcher_listener')->replaceArgument(1, true);
255
            }
256
        }
257 53
    }
258
259 53
    private function loadBodyConverter(array $config, XmlFileLoader $loader, ContainerBuilder $container)
260
    {
261 53
        if (!$this->isConfigEnabled($container, $config['body_converter'])) {
262 46
            return;
263
        }
264
265 7
        $loader->load('request_body_param_converter.xml');
266
267 7
        if (!empty($config['body_converter']['validation_errors_argument'])) {
268 7
            $container->getDefinition('fos_rest.converter.request_body')->replaceArgument(4, $config['body_converter']['validation_errors_argument']);
269
        }
270 7
    }
271
272 53
    private function loadView(array $config, XmlFileLoader $loader, ContainerBuilder $container)
273
    {
274 53
        if (!empty($config['view']['jsonp_handler'])) {
275 1
            $childDefinitionClass = class_exists(ChildDefinition::class) ? ChildDefinition::class : DefinitionDecorator::class;
276 1
            $handler = new $childDefinitionClass($config['service']['view_handler']);
277 1
            $handler->setPublic(true);
278
279 1
            $jsonpHandler = new Reference('fos_rest.view_handler.jsonp');
280 1
            $handler->addMethodCall('registerHandler', ['jsonp', [$jsonpHandler, 'createResponse']]);
281 1
            $container->setDefinition('fos_rest.view_handler', $handler);
282
283 1
            $container->getDefinition('fos_rest.view_handler.jsonp')->replaceArgument(0, $config['view']['jsonp_handler']['callback_param']);
284
285 1
            if (empty($config['view']['mime_types']['jsonp'])) {
286 1
                $config['view']['mime_types']['jsonp'] = $config['view']['jsonp_handler']['mime_type'];
287
            }
288
        }
289
290 53 View Code Duplication
        if ($config['view']['mime_types']['enabled']) {
291 3
            $loader->load('mime_type_listener.xml');
292
293 3
            if (!empty($config['mime_type_listener']['service'])) {
294
                $service = $container->getDefinition('fos_rest.mime_type_listener');
295
                $service->clearTag('kernel.event_listener');
296
            }
297
298 3
            $container->getDefinition('fos_rest.mime_type_listener')->replaceArgument(0, $config['view']['mime_types']['formats']);
299
        }
300
301 53 View Code Duplication
        if ($config['view']['view_response_listener']['enabled']) {
302 9
            $loader->load('view_response_listener.xml');
303 9
            $service = $container->getDefinition('fos_rest.view_response_listener');
304
305 9
            if (!empty($config['view_response_listener']['service'])) {
306
                $service->clearTag('kernel.event_listener');
307
            }
308
309 9
            $service->replaceArgument(1, $config['view']['view_response_listener']['force']);
310
        }
311
312 53
        $formats = [];
313 53 View Code Duplication
        foreach ($config['view']['formats'] as $format => $enabled) {
314 53
            if ($enabled) {
315 53
                $formats[$format] = false;
316
            }
317
        }
318 53 View Code Duplication
        foreach ($config['view']['templating_formats'] as $format => $enabled) {
319 53
            if ($enabled) {
320 53
                $formats[$format] = true;
321
            }
322
        }
323
324 53
        $container->getDefinition('fos_rest.routing.loader.yaml_collection')->replaceArgument(3, $formats);
325 53
        $container->getDefinition('fos_rest.routing.loader.xml_collection')->replaceArgument(3, $formats);
326 53
        $container->getDefinition('fos_rest.routing.loader.reader.action')->replaceArgument(4, $formats);
327
328 53
        foreach ($config['view']['force_redirects'] as $format => $code) {
329 7
            if (true === $code) {
330 7
                $config['view']['force_redirects'][$format] = Response::HTTP_FOUND;
331
            }
332
        }
333
334 53 View Code Duplication
        if (!is_numeric($config['view']['failed_validation'])) {
335
            $config['view']['failed_validation'] = constant('\Symfony\Component\HttpFoundation\Response::'.$config['view']['failed_validation']);
336
        }
337
338 53 View Code Duplication
        if (!is_numeric($config['view']['empty_content'])) {
339
            $config['view']['empty_content'] = constant('\Symfony\Component\HttpFoundation\Response::'.$config['view']['empty_content']);
340
        }
341
342 53
        $defaultViewHandler = $container->getDefinition('fos_rest.view_handler.default');
343
344 53
        if ([] !== $config['view']['force_redirects']) {
345 7
            @trigger_error('Not setting the "fos_rest.view.force_redirects" configuration option to an empty array is deprecated since FOSRestBundle 2.8.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
346
        }
347
348 53
        if (null === $config['service']['templating'] && [] === $config['view']['force_redirects'] && null === $config['view']['default_engine']) {
349 46
            $defaultViewHandler->setFactory([ViewHandler::class, 'create']);
350 46
            $defaultViewHandler->setArguments([
351 46
                new Reference('fos_rest.router'),
352 46
                new Reference('fos_rest.serializer'),
353 46
                new Reference('request_stack'),
354 46
                $formats,
355 46
                $config['view']['failed_validation'],
356 46
                $config['view']['empty_content'],
357 46
                $config['view']['serialize_null'],
358
            ]);
359
        } else {
360 7
            $defaultViewHandler->setArguments([
361 7
                new Reference('fos_rest.router'),
362 7
                new Reference('fos_rest.serializer'),
363 7
                new Reference('fos_rest.templating', ContainerInterface::NULL_ON_INVALID_REFERENCE),
364 7
                new Reference('request_stack'),
365 7
                $formats,
366 7
                $config['view']['failed_validation'],
367 7
                $config['view']['empty_content'],
368 7
                $config['view']['serialize_null'],
369 7
                $config['view']['force_redirects'],
370 7
                $config['view']['default_engine'],
371
            ]);
372
        }
373 53
    }
374
375 53
    private function loadException(array $config, XmlFileLoader $loader, ContainerBuilder $container)
376
    {
377 53
        if ($config['exception']['enabled']) {
378 49
            $loader->load('exception_listener.xml');
379
380 49
            if (!empty($config['exception']['service'])) {
381
                $service = $container->getDefinition('fos_rest.exception_listener');
382
                $service->clearTag('kernel.event_subscriber');
383
            }
384
385 49
            $controller = $config['exception']['exception_controller'] ?? null;
386
387 49
            $container->getDefinition('fos_rest.exception_listener')->replaceArgument(0, $controller);
388
389 49
            $container->getDefinition('fos_rest.exception.codes_map')
390 49
                ->replaceArgument(0, $config['exception']['codes']);
391 49
            $container->getDefinition('fos_rest.exception.messages_map')
392 49
                ->replaceArgument(0, $config['exception']['messages']);
393
394 49
            $container->getDefinition('fos_rest.exception.controller')
395 49
                ->replaceArgument(2, $config['exception']['debug']);
396 49
            $container->getDefinition('fos_rest.serializer.exception_normalizer.jms')
397 49
                ->replaceArgument(1, $config['exception']['debug']);
398 49
            $container->getDefinition('fos_rest.serializer.exception_normalizer.symfony')
399 49
                ->replaceArgument(1, $config['exception']['debug']);
400
        }
401 53
    }
402
403 53
    private function loadSerializer(array $config, ContainerBuilder $container)
404
    {
405 53
        $bodyConverter = $container->hasDefinition('fos_rest.converter.request_body') ? $container->getDefinition('fos_rest.converter.request_body') : null;
406 53
        $viewHandler = $container->getDefinition('fos_rest.view_handler.default');
407 53
        $options = array();
408
409 53 View Code Duplication
        if (!empty($config['serializer']['version'])) {
410
            if ($bodyConverter) {
411
                $bodyConverter->replaceArgument(2, $config['serializer']['version']);
412
            }
413
            $options['exclusionStrategyVersion'] = $config['serializer']['version'];
414
        }
415
416 53 View Code Duplication
        if (!empty($config['serializer']['groups'])) {
417
            if ($bodyConverter) {
418
                $bodyConverter->replaceArgument(1, $config['serializer']['groups']);
419
            }
420
            $options['exclusionStrategyGroups'] = $config['serializer']['groups'];
421
        }
422
423 53
        $options['serializeNullStrategy'] = $config['serializer']['serialize_null'];
424 53
        $viewHandler->addArgument($options);
425 53
    }
426
427 53
    private function loadZoneMatcherListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
428
    {
429 53
        if (!empty($config['zone'])) {
430 1
            $loader->load('zone_matcher_listener.xml');
431 1
            $zoneMatcherListener = $container->getDefinition('fos_rest.zone_matcher_listener');
432
433 1
            foreach ($config['zone'] as $zone) {
434 1
                $matcher = $this->createZoneRequestMatcher(
435 1
                    $container,
436 1
                    $zone['path'],
437 1
                    $zone['host'],
438 1
                    $zone['methods'],
439 1
                    $zone['ips']
440
                );
441
442 1
                $zoneMatcherListener->addMethodCall('addRequestMatcher', array($matcher));
443
            }
444
        }
445 53
    }
446
447 1
    private function createZoneRequestMatcher(ContainerBuilder $container, $path = null, $host = null, $methods = array(), $ip = null)
448
    {
449 1
        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...
450
            $methods = array_map('strtoupper', (array) $methods);
451
        }
452
453 1
        $serialized = serialize(array($path, $host, $methods, $ip));
454 1
        $id = 'fos_rest.zone_request_matcher.'.md5($serialized).sha1($serialized);
455
456
        // only add arguments that are necessary
457 1
        $arguments = array($path, $host, $methods, $ip);
458 1
        while (count($arguments) > 0 && !end($arguments)) {
459 1
            array_pop($arguments);
460
        }
461
462 1
        $childDefinitionClass = class_exists(ChildDefinition::class) ? ChildDefinition::class : DefinitionDecorator::class;
463
        $container
464 1
            ->setDefinition($id, new $childDefinitionClass('fos_rest.zone_request_matcher'))
465 1
            ->setArguments($arguments)
466
        ;
467
468 1
        return new Reference($id);
469
    }
470
}
471