Completed
Push — master ( 0d2b02...169528 )
by Christian
02:34 queued 12s
created

FOSRestExtension::loadParamFetcherListener()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 5.5069

Importance

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