Completed
Push — master ( 010fd7...92a758 )
by
unknown
05:33
created

DependencyInjection/FOSRestExtension.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
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(1, $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
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
        $options = array();
386 2
387 2 View Code Duplication
        if (!empty($config['serializer']['version'])) {
388 2
            if ($bodyConverter) {
389
                $bodyConverter->replaceArgument(2, $config['serializer']['version']);
390 2
            }
391 2
            $options['exclusionStrategyVersion'] = $config['serializer']['version'];
392 2
        }
393 50
394 View Code Duplication
        if (!empty($config['serializer']['groups'])) {
395 2
            if ($bodyConverter) {
396
                $bodyConverter->replaceArgument(1, $config['serializer']['groups']);
397 2
            }
398
            $options['exclusionStrategyGroups'] = $config['serializer']['groups'];
399
        }
400
401 2
        $options['serializeNullStrategy'] = $config['serializer']['serialize_null'];
402 2
        $viewHandler->addArgument($options);
403
    }
404
405 2
    private function loadZoneMatcherListener(array $config, XmlFileLoader $loader, ContainerBuilder $container)
406 2
    {
407 2
        if (!empty($config['zone'])) {
408 2
            $loader->load('zone_matcher_listener.xml');
409
            $zoneMatcherListener = $container->getDefinition('fos_rest.zone_matcher_listener');
410
411 2
            foreach ($config['zone'] as $zone) {
412 2
                $matcher = $this->createZoneRequestMatcher($container,
413
                    $zone['path'],
414
                    $zone['host'],
415 2
                    $zone['methods'],
416
                    $zone['ips']
417
                );
418
419
                $zoneMatcherListener->addMethodCall('addRequestMatcher', array($matcher));
420
            }
421
        }
422
    }
423
424
    private function createZoneRequestMatcher(ContainerBuilder $container, $path = null, $host = null, $methods = array(), $ip = null)
425
    {
426
        if ($methods) {
427
            $methods = array_map('strtoupper', (array) $methods);
428
        }
429
430
        $serialized = serialize(array($path, $host, $methods, $ip));
431
        $id = 'fos_rest.zone_request_matcher.'.md5($serialized).sha1($serialized);
432
433
        // only add arguments that are necessary
434
        $arguments = array($path, $host, $methods, $ip);
435
        while (count($arguments) > 0 && !end($arguments)) {
436
            array_pop($arguments);
437
        }
438
439
        $childDefinitionClass = class_exists(ChildDefinition::class) ? ChildDefinition::class : DefinitionDecorator::class;
440
        $container
441
            ->setDefinition($id, new $childDefinitionClass('fos_rest.zone_request_matcher'))
442
            ->setArguments($arguments)
443
        ;
444
445
        return new Reference($id);
446
    }
447
}
448