Completed
Push — master ( 0206c4...e90e98 )
by Guilh
9s
created

Configuration::addBodyListenerSection()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 34
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 31
CRAP Score 1
Metric Value
dl 0
loc 34
ccs 31
cts 31
cp 1
rs 8.8571
cc 1
eloc 32
nc 1
nop 1
crap 1
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\Definition\Builder\ArrayNodeDefinition;
15
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
16
use Symfony\Component\Config\Definition\ConfigurationInterface;
17
use Symfony\Component\HttpFoundation\Response;
18
19
/**
20
 * This class contains the configuration information for the bundle.
21
 *
22
 * This information is solely responsible for how the different configuration
23
 * sections are normalized, and merged.
24
 *
25
 * @author Lukas Kahwe Smith <[email protected]>
26
 *
27
 * @internal
28
 */
29
final class Configuration implements ConfigurationInterface
30
{
31
    /**
32
     * Generates the configuration tree.
33
     *
34
     * @return TreeBuilder
35
     */
36 47
    public function getConfigTreeBuilder()
37
    {
38 47
        $treeBuilder = new TreeBuilder();
39 47
        $rootNode = $treeBuilder->root('fos_rest', 'array');
40
41
        $rootNode
42 47
            ->children()
43 47
                ->scalarNode('disable_csrf_role')->defaultNull()->end()
44 47
                ->arrayNode('access_denied_listener')
45 47
                    ->canBeEnabled()
46 47
                    ->beforeNormalization()
47 View Code Duplication
                        ->ifArray()->then(function ($v) { if (!empty($v) && empty($v['formats'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
48
     unset($v['enabled']);
49
     $v = ['enabled' => true, 'formats' => $v];
50
 }
51
52 47
return $v; })
53 47
                    ->end()
54 47
                    ->fixXmlConfig('format', 'formats')
55 47
                    ->children()
56 47
                        ->scalarNode('service')->defaultNull()->end()
57 47
                        ->arrayNode('formats')
58 47
                            ->useAttributeAsKey('name')
59 47
                            ->prototype('boolean')->end()
60 47
                        ->end()
61 47
                    ->end()
62 47
                ->end()
63 47
                ->scalarNode('unauthorized_challenge')->defaultNull()->end()
64 47
                ->arrayNode('param_fetcher_listener')
65 47
                    ->beforeNormalization()
66 47
                        ->ifString()
67 View Code Duplication
                        ->then(function ($v) { return ['enabled' => in_array($v, ['force', 'true']), 'force' => 'force' === $v]; })
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
68 47
                    ->end()
69 47
                    ->canBeEnabled()
70 47
                    ->children()
71 47
                        ->booleanNode('enabled')->defaultFalse()->end()
72 47
                        ->booleanNode('force')->defaultFalse()->end()
73 47
                        ->scalarNode('service')->defaultNull()->end()
74 47
                    ->end()
75 47
                ->end()
76 47
                ->scalarNode('cache_dir')->cannotBeEmpty()->defaultValue('%kernel.cache_dir%/fos_rest')->end()
77 47
                ->arrayNode('allowed_methods_listener')
78 47
                    ->canBeEnabled()
79 47
                    ->children()
80 47
                        ->scalarNode('service')->defaultNull()->end()
81 47
                    ->end()
82 47
                ->end()
83 47
                ->arrayNode('routing_loader')
84 47
                    ->addDefaultsIfNotSet()
85 47
                    ->children()
86 47
                        ->scalarNode('default_format')->defaultNull()->end()
87 47
                        ->scalarNode('include_format')->defaultTrue()->end()
88 47
                    ->end()
89 47
                ->end()
90 47
                ->arrayNode('body_converter')
91 47
                    ->addDefaultsIfNotSet()
92 47
                    ->children()
93 47
                        ->scalarNode('enabled')->defaultFalse()->end()
94 47
                        ->scalarNode('validate')->defaultFalse()->end()
95 47
                        ->scalarNode('validation_errors_argument')->defaultValue('validationErrors')->end()
96 47
                    ->end()
97 47
                ->end()
98 47
                ->arrayNode('service')
99 47
                    ->addDefaultsIfNotSet()
100 47
                    ->children()
101 47
                        ->scalarNode('router')->defaultValue('router')->end()
102 47
                        ->scalarNode('templating')->defaultValue('templating')->end()
103 47
                        ->scalarNode('serializer')->defaultNull()->end()
104 47
                        ->scalarNode('view_handler')->defaultValue('fos_rest.view_handler.default')->end()
105 47
                        ->scalarNode('exception_handler')->defaultValue('fos_rest.view.exception_wrapper_handler')->end()
106 47
                        ->scalarNode('inflector')->defaultValue('fos_rest.inflector.doctrine')->end()
107 47
                        ->scalarNode('validator')->defaultValue('validator')->end()
108 47
                    ->end()
109 47
                ->end()
110 47
                ->arrayNode('serializer')
111 47
                    ->addDefaultsIfNotSet()
112 47
                    ->children()
113 47
                        ->scalarNode('version')->defaultNull()->end()
114 47
                        ->arrayNode('groups')
115 47
                            ->prototype('scalar')->end()
116 47
                        ->end()
117 47
                        ->booleanNode('serialize_null')->defaultFalse()->end()
118 47
                    ->end()
119 47
                ->end()
120 47
                ->arrayNode('zone')
121 47
                    ->cannotBeOverwritten()
122 47
                    ->prototype('array')
123 47
                    ->fixXmlConfig('ip')
124 47
                    ->children()
125 47
                        ->scalarNode('path')
126 47
                            ->defaultNull()
127 47
                            ->info('use the urldecoded format')
128 47
                            ->example('^/path to resource/')
129 47
                        ->end()
130 47
                        ->scalarNode('host')->defaultNull()->end()
131 47
                        ->arrayNode('methods')
132
                            ->beforeNormalization()->ifString()->then(function ($v) { return preg_split('/\s*,\s*/', $v); })->end()
133 47
                            ->prototype('scalar')->end()
134 47
                        ->end()
135 47
                        ->arrayNode('ips')
136
                            ->beforeNormalization()->ifString()->then(function ($v) { return array($v); })->end()
137 47
                            ->prototype('scalar')->end()
138 47
                        ->end()
139 47
                    ->end()
140 47
                ->end()
141 47
            ->end()
142 47
        ->end();
143
144 47
        $this->addViewSection($rootNode);
145 47
        $this->addExceptionSection($rootNode);
146 47
        $this->addBodyListenerSection($rootNode);
147 47
        $this->addFormatListenerSection($rootNode);
148 47
        $this->addVersioningSection($rootNode);
149
150 47
        return $treeBuilder;
151
    }
152
153 47
    private function addViewSection(ArrayNodeDefinition $rootNode)
154
    {
155
        $rootNode
156 47
            ->children()
157 47
                ->arrayNode('view')
158 47
                    ->fixXmlConfig('format', 'formats')
159 47
                    ->fixXmlConfig('mime_type', 'mime_types')
160 47
                    ->fixXmlConfig('templating_format', 'templating_formats')
161 47
                    ->fixXmlConfig('force_redirect', 'force_redirects')
162 47
                    ->addDefaultsIfNotSet()
163 47
                    ->children()
164 47
                        ->scalarNode('default_engine')->defaultValue('twig')->end()
165 47
                        ->arrayNode('force_redirects')
166 47
                            ->useAttributeAsKey('name')
167 47
                            ->defaultValue(['html' => true])
168 47
                            ->prototype('boolean')->end()
169 47
                        ->end()
170 47
                        ->arrayNode('mime_types')
171 47
                            ->canBeEnabled()
172 47
                            ->beforeNormalization()
173 View Code Duplication
                                ->ifArray()->then(function ($v) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
174 1
                                    if (!empty($v) && empty($v['formats'])) {
175 1
                                        unset($v['enabled']);
176 1
                                        $v = ['enabled' => true, 'formats' => $v];
177 1
                                    }
178
179 1
                                    return $v;
180 47
                                })
181 47
                            ->end()
182 47
                            ->fixXmlConfig('format', 'formats')
183 47
                            ->children()
184 47
                                ->scalarNode('service')->defaultNull()->end()
185 47
                                ->arrayNode('formats')
186 47
                                    ->useAttributeAsKey('name')
187 47
                                    ->prototype('variable')->end()
188 47
                                ->end()
189 47
                            ->end()
190 47
                        ->end()
191 47
                        ->arrayNode('formats')
192 47
                            ->useAttributeAsKey('name')
193 47
                            ->defaultValue(['json' => true, 'xml' => true])
194 47
                            ->prototype('boolean')->end()
195 47
                        ->end()
196 47
                        ->arrayNode('templating_formats')
197 47
                            ->useAttributeAsKey('name')
198 47
                            ->defaultValue(['html' => true])
199 47
                            ->prototype('boolean')->end()
200 47
                        ->end()
201 47
                        ->arrayNode('view_response_listener')
202 47
                            ->beforeNormalization()
203 47
                                ->ifString()
204 View Code Duplication
                                ->then(function ($v) { return ['enabled' => in_array($v, ['force', 'true']), 'force' => 'force' === $v]; })
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
205 47
                            ->end()
206 47
                            ->canBeEnabled()
207 47
                            ->children()
208 47
                                ->booleanNode('enabled')->defaultFalse()->end()
209 47
                                ->booleanNode('force')->defaultFalse()->end()
210 47
                                ->scalarNode('service')->defaultNull()->end()
211 47
                            ->end()
212 47
                        ->end()
213 47
                        ->scalarNode('failed_validation')->defaultValue(Response::HTTP_BAD_REQUEST)->end()
214 47
                        ->scalarNode('empty_content')->defaultValue(Response::HTTP_NO_CONTENT)->end()
215 47
                        ->scalarNode('exception_wrapper_handler')->defaultNull()->end()
216 47
                        ->booleanNode('serialize_null')->defaultFalse()->end()
217 47
                        ->arrayNode('jsonp_handler')
218 47
                            ->canBeUnset()
219 47
                            ->children()
220 47
                                ->scalarNode('callback_param')->defaultValue('callback')->end()
221 47
                                ->scalarNode('mime_type')->defaultValue('application/javascript+jsonp')->end()
222 47
                            ->end()
223 47
                        ->end()
224 47
                    ->end()
225 47
                ->end()
226 47
            ->end();
227 47
    }
228
229 47
    private function addBodyListenerSection(ArrayNodeDefinition $rootNode)
230
    {
231
        $rootNode
232 47
            ->children()
233 47
                ->arrayNode('body_listener')
234 47
                    ->fixXmlConfig('decoder', 'decoders')
235 47
                    ->addDefaultsIfNotSet()
236 47
                    ->canBeUnset()
237 47
                    ->canBeDisabled()
238 47
                    ->children()
239 47
                        ->scalarNode('service')->defaultNull()->end()
240 47
                        ->scalarNode('default_format')->defaultNull()->end()
241 47
                        ->booleanNode('throw_exception_on_unsupported_content_type')
242 47
                            ->defaultFalse()
243 47
                        ->end()
244 47
                        ->arrayNode('decoders')
245 47
                            ->useAttributeAsKey('name')
246 47
                            ->defaultValue(['json' => 'fos_rest.decoder.json', 'xml' => 'fos_rest.decoder.xml'])
247 47
                            ->prototype('scalar')->end()
248 47
                        ->end()
249 47
                        ->arrayNode('array_normalizer')
250 47
                            ->addDefaultsIfNotSet()
251 47
                            ->beforeNormalization()
252
                                ->ifString()->then(function ($v) { return ['service' => $v]; })
253 47
                            ->end()
254 47
                            ->children()
255 47
                                ->scalarNode('service')->defaultNull()->end()
256 47
                                ->booleanNode('forms')->defaultFalse()->end()
257 47
                            ->end()
258 47
                        ->end()
259 47
                    ->end()
260 47
                ->end()
261 47
            ->end();
262 47
    }
263
264 47
    private function addFormatListenerSection(ArrayNodeDefinition $rootNode)
265
    {
266
        $rootNode
267 47
            ->children()
268 47
                ->arrayNode('format_listener')
269 47
                    ->fixXmlConfig('rule', 'rules')
270 47
                    ->addDefaultsIfNotSet()
271 47
                    ->canBeUnset()
272 47
                    ->beforeNormalization()
273
                        ->ifTrue(function ($v) {
274
                            // check if we got an assoc array in rules
275 7
                            return isset($v['rules'])
276 7
                                && is_array($v['rules'])
277 7
                                && array_keys($v['rules']) !== range(0, count($v['rules']) - 1);
278 47
                        })
279
                        ->then(function ($v) {
280 1
                            $v['rules'] = [$v['rules']];
281
282 1
                            return $v;
283 47
                        })
284 47
                    ->end()
285 47
                    ->canBeEnabled()
286 47
                    ->validate()
287
                        ->ifTrue(function ($v) { return empty($v['rules']) && !empty($v['media_type']['enabled']); })
288 47
                        ->thenInvalid('To enable the "media_type" setting, a "rules" setting must also needs to be defined for the "format_listener"')
289 47
                    ->end()
290 47
                    ->children()
291 47
                        ->scalarNode('service')->defaultNull()->end()
292 47
                        ->arrayNode('rules')
293 47
                            ->cannotBeOverwritten()
294 47
                            ->prototype('array')
295 47
                                ->fixXmlConfig('priority', 'priorities')
296 47
                                ->children()
297 47
                                    ->scalarNode('path')->defaultNull()->info('URL path info')->end()
298 47
                                    ->scalarNode('host')->defaultNull()->info('URL host name')->end()
299 47
                                    ->variableNode('methods')->defaultNull()->info('Method for URL')->end()
300 47
                                    ->booleanNode('stop')->defaultFalse()->end()
301 47
                                    ->booleanNode('prefer_extension')->defaultTrue()->end()
302 47
                                    ->scalarNode('fallback_format')->defaultValue('html')->end()
303 47
                                    ->scalarNode('exception_fallback_format')->defaultNull()->end()
304 47
                                    ->arrayNode('priorities')
305
                                        ->beforeNormalization()->ifString()->then(function ($v) { return preg_split('/\s*,\s*/', $v); })->end()
306 47
                                        ->prototype('scalar')->end()
307 47
                                    ->end()
308 47
                                ->end()
309 47
                            ->end()
310 47
                        ->end()
311 47
                    ->end()
312 47
                ->end()
313 47
            ->end();
314 47
    }
315
316 47
    private function addVersioningSection(ArrayNodeDefinition $rootNode)
317
    {
318
        $rootNode
319 47
        ->children()
320 47
            ->arrayNode('versioning')
321 47
                ->canBeEnabled()
322 47
                ->children()
323 47
                    ->scalarNode('default_version')->defaultNull()->end()
324 47
                    ->arrayNode('resolvers')
325 47
                        ->addDefaultsIfNotSet()
326 47
                        ->children()
327 47
                            ->arrayNode('query')
328 47
                                ->canBeDisabled()
329 47
                                ->children()
330 47
                                    ->scalarNode('parameter_name')->defaultValue('version')->end()
331 47
                                ->end()
332 47
                            ->end()
333 47
                            ->arrayNode('custom_header')
334 47
                                ->canBeDisabled()
335 47
                                ->children()
336 47
                                    ->scalarNode('header_name')->defaultValue('X-Accept-Version')->end()
337 47
                                ->end()
338 47
                            ->end()
339 47
                            ->arrayNode('media_type')
340 47
                                ->canBeDisabled()
341 47
                                ->children()
342 47
                                    ->scalarNode('regex')->defaultValue('/(v|version)=(?P<version>[0-9\.]+)/')->end()
343 47
                                ->end()
344 47
                            ->end()
345 47
                        ->end()
346 47
                    ->end()
347 47
                    ->arrayNode('guessing_order')
348 47
                        ->defaultValue(['query', 'custom_header', 'media_type'])
349 47
                        ->validate()
350
                            ->ifTrue(function ($v) {
351 1
                                foreach ($v as $resolver) {
352 1
                                    if (!in_array($resolver, ['query', 'custom_header', 'media_type'])) {
353
                                        return true;
354
                                    }
355 1
                                }
356 47
                            })
357 47
                            ->thenInvalid('Versioning guessing order can only contain "query", "custom_header", "media_type".')
358 47
                        ->end()
359 47
                        ->prototype('scalar')->end()
360 47
                    ->end()
361 47
                ->end()
362 47
            ->end()
363 47
        ->end();
364 47
    }
365
366 47
    private function addExceptionSection(ArrayNodeDefinition $rootNode)
367
    {
368
        $rootNode
369 47
            ->children()
370 47
                ->arrayNode('exception')
371 47
                    ->fixXmlConfig('code', 'codes')
372 47
                    ->fixXmlConfig('message', 'messages')
373 47
                    ->addDefaultsIfNotSet()
374 47
                    ->canBeEnabled()
375 47
                    ->children()
376 47
                        ->scalarNode('exception_controller')->defaultNull()->end()
377 47
                        ->arrayNode('codes')
378 47
                            ->useAttributeAsKey('name')
379 47
                            ->validate()
380
                                ->ifTrue(function ($v) { return 0 !== count(array_filter($v, function ($i) { return !defined('Symfony\Component\HttpFoundation\Response::'.$i) && !is_int($i); })); })
381 47
                                ->thenInvalid('Invalid HTTP code in fos_rest.exception.codes, see Symfony\Component\HttpFoundation\Response for all valid codes.')
382 47
                            ->end()
383 47
                            ->prototype('scalar')->end()
384 47
                        ->end()
385 47
                        ->arrayNode('messages')
386 47
                            ->useAttributeAsKey('name')
387 47
                            ->prototype('boolean')->end()
388 47
                        ->end()
389 47
                    ->end()
390 47
                ->end()
391 47
            ->end();
392 47
    }
393
}
394