Completed
Push — master ( 6fed26...e3ac15 )
by Guilh
08:12
created

DependencyInjection/FOSRestExtension.php (1 issue)

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