Completed
Pull Request — master (#1506)
by Guilh
15:57 queued 11:18
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

Importance

Changes 0
Metric Value
c 0
b 0
f 0
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
     * Default debug mode value.
33
     *
34
     * @var bool
35
     */
36
    private $debug;
37
38
    /**
39
     * @param bool $debug
40
     */
41 58
    public function __construct($debug)
42
    {
43 58
        $this->debug = (bool) $debug;
44 58
    }
45
46
    /**
47
     * Generates the configuration tree.
48
     *
49
     * @return TreeBuilder
50
     */
51 57
    public function getConfigTreeBuilder()
52
    {
53 57
        $treeBuilder = new TreeBuilder();
54 57
        $rootNode = $treeBuilder->root('fos_rest', 'array');
55
56
        $rootNode
57 57
            ->children()
58 57
                ->scalarNode('disable_csrf_role')->defaultNull()->end()
59 57
                ->arrayNode('access_denied_listener')
60 57
                    ->canBeEnabled()
61 57
                    ->beforeNormalization()
62 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...
63
     unset($v['enabled']);
64
     $v = ['enabled' => true, 'formats' => $v];
65
 }
66
67 57
return $v; })
68 57
                    ->end()
69 57
                    ->fixXmlConfig('format', 'formats')
70 57
                    ->children()
71 57
                        ->scalarNode('service')->defaultNull()->end()
72 57
                        ->arrayNode('formats')
73 57
                            ->useAttributeAsKey('name')
74 57
                            ->prototype('boolean')->end()
75 57
                        ->end()
76 57
                    ->end()
77 57
                ->end()
78 57
                ->scalarNode('unauthorized_challenge')->defaultNull()->end()
79 57
                ->arrayNode('param_fetcher_listener')
80 57
                    ->beforeNormalization()
81 57
                        ->ifString()
82 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...
83 57
                    ->end()
84 57
                    ->canBeEnabled()
85 57
                    ->children()
86 57
                        ->booleanNode('enabled')->defaultFalse()->end()
87 57
                        ->booleanNode('force')->defaultFalse()->end()
88 57
                        ->scalarNode('service')->defaultNull()->end()
89 57
                    ->end()
90 57
                ->end()
91 57
                ->scalarNode('cache_dir')->cannotBeEmpty()->defaultValue('%kernel.cache_dir%/fos_rest')->end()
92 57
                ->arrayNode('allowed_methods_listener')
93 57
                    ->canBeEnabled()
94 57
                    ->children()
95 57
                        ->scalarNode('service')->defaultNull()->end()
96 57
                    ->end()
97 57
                ->end()
98 57
                ->arrayNode('routing_loader')
99 57
                    ->addDefaultsIfNotSet()
100 57
                    ->children()
101 57
                        ->scalarNode('default_format')->defaultNull()->end()
102 57
                        ->scalarNode('include_format')->defaultTrue()->end()
103 57
                    ->end()
104 57
                ->end()
105 57
                ->arrayNode('body_converter')
106 57
                    ->addDefaultsIfNotSet()
107 57
                    ->children()
108 57
                        ->scalarNode('enabled')->defaultFalse()->end()
109 57
                        ->scalarNode('validate')->defaultFalse()->end()
110 57
                        ->scalarNode('validation_errors_argument')->defaultValue('validationErrors')->end()
111 57
                    ->end()
112 57
                ->end()
113 57
                ->arrayNode('service')
114 57
                    ->addDefaultsIfNotSet()
115 57
                    ->children()
116 57
                        ->scalarNode('router')->defaultValue('router')->end()
117 57
                        ->scalarNode('templating')->defaultValue('templating')->end()
118 57
                        ->scalarNode('serializer')->defaultNull()->end()
119 57
                        ->scalarNode('view_handler')->defaultValue('fos_rest.view_handler.default')->end()
120 57
                        ->scalarNode('inflector')->defaultValue('fos_rest.inflector.doctrine')->end()
121 57
                        ->scalarNode('validator')->defaultValue('validator')->end()
122 57
                    ->end()
123 57
                ->end()
124 57
                ->arrayNode('serializer')
125 57
                    ->addDefaultsIfNotSet()
126 57
                    ->children()
127 57
                        ->scalarNode('version')->defaultNull()->end()
128 57
                        ->arrayNode('groups')
129 57
                            ->prototype('scalar')->end()
130 57
                        ->end()
131 57
                        ->booleanNode('serialize_null')->defaultFalse()->end()
132 57
                    ->end()
133 57
                ->end()
134 57
                ->arrayNode('zone')
135 57
                    ->cannotBeOverwritten()
136 57
                    ->prototype('array')
137 57
                    ->fixXmlConfig('ip')
138 57
                    ->children()
139 57
                        ->scalarNode('path')
140 57
                            ->defaultNull()
141 57
                            ->info('use the urldecoded format')
142 57
                            ->example('^/path to resource/')
143 57
                        ->end()
144 57
                        ->scalarNode('host')->defaultNull()->end()
145 57
                        ->arrayNode('methods')
146
                            ->beforeNormalization()->ifString()->then(function ($v) { return preg_split('/\s*,\s*/', $v); })->end()
147 57
                            ->prototype('scalar')->end()
148 57
                        ->end()
149 57
                        ->arrayNode('ips')
150
                            ->beforeNormalization()->ifString()->then(function ($v) { return array($v); })->end()
151 57
                            ->prototype('scalar')->end()
152 57
                        ->end()
153 57
                    ->end()
154 57
                ->end()
155 57
            ->end()
156 57
        ->end();
157
158 57
        $this->addViewSection($rootNode);
159 57
        $this->addExceptionSection($rootNode);
160 57
        $this->addBodyListenerSection($rootNode);
161 57
        $this->addFormatListenerSection($rootNode);
162 57
        $this->addVersioningSection($rootNode);
163
164 57
        return $treeBuilder;
165
    }
166
167 57
    private function addViewSection(ArrayNodeDefinition $rootNode)
168
    {
169
        $rootNode
170 57
            ->children()
171 57
                ->arrayNode('view')
172 57
                    ->fixXmlConfig('format', 'formats')
173 57
                    ->fixXmlConfig('mime_type', 'mime_types')
174 57
                    ->fixXmlConfig('templating_format', 'templating_formats')
175 57
                    ->fixXmlConfig('force_redirect', 'force_redirects')
176 57
                    ->addDefaultsIfNotSet()
177 57
                    ->children()
178 57
                        ->scalarNode('default_engine')->defaultValue('twig')->end()
179 57
                        ->arrayNode('force_redirects')
180 57
                            ->useAttributeAsKey('name')
181 57
                            ->defaultValue(['html' => true])
182 57
                            ->prototype('boolean')->end()
183 57
                        ->end()
184 57
                        ->arrayNode('mime_types')
185 57
                            ->canBeEnabled()
186 57
                            ->beforeNormalization()
187 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...
188 1
                                    if (!empty($v) && empty($v['formats'])) {
189 1
                                        unset($v['enabled']);
190 1
                                        $v = ['enabled' => true, 'formats' => $v];
191 1
                                    }
192
193 1
                                    return $v;
194 57
                                })
195 57
                            ->end()
196 57
                            ->fixXmlConfig('format', 'formats')
197 57
                            ->children()
198 57
                                ->scalarNode('service')->defaultNull()->end()
199 57
                                ->arrayNode('formats')
200 57
                                    ->useAttributeAsKey('name')
201 57
                                    ->prototype('variable')->end()
202 57
                                ->end()
203 57
                            ->end()
204 57
                        ->end()
205 57
                        ->arrayNode('formats')
206 57
                            ->useAttributeAsKey('name')
207 57
                            ->defaultValue(['json' => true, 'xml' => true])
208 57
                            ->prototype('boolean')->end()
209 57
                        ->end()
210 57
                        ->arrayNode('templating_formats')
211 57
                            ->useAttributeAsKey('name')
212 57
                            ->defaultValue(['html' => true])
213 57
                            ->prototype('boolean')->end()
214 57
                        ->end()
215 57
                        ->arrayNode('view_response_listener')
216 57
                            ->beforeNormalization()
217 57
                                ->ifString()
218 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...
219 57
                            ->end()
220 57
                            ->canBeEnabled()
221 57
                            ->children()
222 57
                                ->booleanNode('enabled')->defaultFalse()->end()
223 57
                                ->booleanNode('force')->defaultFalse()->end()
224 57
                                ->scalarNode('service')->defaultNull()->end()
225 57
                            ->end()
226 57
                        ->end()
227 57
                        ->scalarNode('failed_validation')->defaultValue(Response::HTTP_BAD_REQUEST)->end()
228 57
                        ->scalarNode('empty_content')->defaultValue(Response::HTTP_NO_CONTENT)->end()
229 57
                        ->booleanNode('serialize_null')->defaultFalse()->end()
230 57
                        ->arrayNode('jsonp_handler')
231 57
                            ->canBeUnset()
232 57
                            ->children()
233 57
                                ->scalarNode('callback_param')->defaultValue('callback')->end()
234 57
                                ->scalarNode('mime_type')->defaultValue('application/javascript+jsonp')->end()
235 57
                            ->end()
236 57
                        ->end()
237 57
                    ->end()
238 57
                ->end()
239 57
            ->end();
240 57
    }
241
242 57
    private function addBodyListenerSection(ArrayNodeDefinition $rootNode)
243
    {
244
        $rootNode
245 57
            ->children()
246 57
                ->arrayNode('body_listener')
247 57
                    ->fixXmlConfig('decoder', 'decoders')
248 57
                    ->addDefaultsIfNotSet()
249 57
                    ->canBeUnset()
250 57
                    ->canBeDisabled()
251 57
                    ->children()
252 57
                        ->scalarNode('service')->defaultNull()->end()
253 57
                        ->scalarNode('default_format')->defaultNull()->end()
254 57
                        ->booleanNode('throw_exception_on_unsupported_content_type')
255 57
                            ->defaultFalse()
256 57
                        ->end()
257 57
                        ->arrayNode('decoders')
258 57
                            ->useAttributeAsKey('name')
259 57
                            ->defaultValue(['json' => 'fos_rest.decoder.json', 'xml' => 'fos_rest.decoder.xml'])
260 57
                            ->prototype('scalar')->end()
261 57
                        ->end()
262 57
                        ->arrayNode('array_normalizer')
263 57
                            ->addDefaultsIfNotSet()
264 57
                            ->beforeNormalization()
265
                                ->ifString()->then(function ($v) { return ['service' => $v]; })
266 57
                            ->end()
267 57
                            ->children()
268 57
                                ->scalarNode('service')->defaultNull()->end()
269 57
                                ->booleanNode('forms')->defaultFalse()->end()
270 57
                            ->end()
271 57
                        ->end()
272 57
                    ->end()
273 57
                ->end()
274 57
            ->end();
275 57
    }
276
277 57
    private function addFormatListenerSection(ArrayNodeDefinition $rootNode)
278
    {
279
        $rootNode
280 57
            ->children()
281 57
                ->arrayNode('format_listener')
282 57
                    ->fixXmlConfig('rule', 'rules')
283 57
                    ->addDefaultsIfNotSet()
284 57
                    ->canBeUnset()
285 57
                    ->beforeNormalization()
286
                        ->ifTrue(function ($v) {
287
                            // check if we got an assoc array in rules
288 8
                            return isset($v['rules'])
289 8
                                && is_array($v['rules'])
290 8
                                && array_keys($v['rules']) !== range(0, count($v['rules']) - 1);
291 57
                        })
292
                        ->then(function ($v) {
293 1
                            $v['rules'] = [$v['rules']];
294
295 1
                            return $v;
296 57
                        })
297 57
                    ->end()
298 57
                    ->canBeEnabled()
299 57
                    ->children()
300 57
                        ->scalarNode('service')->defaultNull()->end()
301 57
                        ->arrayNode('rules')
302 57
                            ->cannotBeOverwritten()
303 57
                            ->prototype('array')
304 57
                                ->fixXmlConfig('priority', 'priorities')
305 57
                                ->fixXmlConfig('attribute', 'attributes')
306 57
                                ->children()
307 57
                                    ->scalarNode('path')->defaultNull()->info('URL path info')->end()
308 57
                                    ->scalarNode('host')->defaultNull()->info('URL host name')->end()
309 57
                                    ->variableNode('methods')->defaultNull()->info('Method for URL')->end()
310 57
                                    ->arrayNode('attributes')
311 57
                                        ->useAttributeAsKey('name')
312 57
                                        ->prototype('variable')->end()
313 57
                                    ->end()
314 57
                                    ->booleanNode('stop')->defaultFalse()->end()
315 57
                                    ->booleanNode('prefer_extension')->defaultTrue()->end()
316 57
                                    ->scalarNode('fallback_format')->defaultValue('html')->end()
317 57
                                    ->arrayNode('priorities')
318
                                        ->beforeNormalization()->ifString()->then(function ($v) { return preg_split('/\s*,\s*/', $v); })->end()
319 57
                                        ->prototype('scalar')->end()
320 57
                                    ->end()
321 57
                                ->end()
322 57
                            ->end()
323 57
                        ->end()
324 57
                    ->end()
325 57
                ->end()
326 57
            ->end();
327 57
    }
328
329 57
    private function addVersioningSection(ArrayNodeDefinition $rootNode)
330
    {
331
        $rootNode
332 57
        ->children()
333 57
            ->arrayNode('versioning')
334 57
                ->canBeEnabled()
335 57
                ->children()
336 57
                    ->scalarNode('default_version')->defaultNull()->end()
337 57
                    ->arrayNode('resolvers')
338 57
                        ->addDefaultsIfNotSet()
339 57
                        ->children()
340 57
                            ->arrayNode('query')
341 57
                                ->canBeDisabled()
342 57
                                ->children()
343 57
                                    ->scalarNode('parameter_name')->defaultValue('version')->end()
344 57
                                ->end()
345 57
                            ->end()
346 57
                            ->arrayNode('custom_header')
347 57
                                ->canBeDisabled()
348 57
                                ->children()
349 57
                                    ->scalarNode('header_name')->defaultValue('X-Accept-Version')->end()
350 57
                                ->end()
351 57
                            ->end()
352 57
                            ->arrayNode('media_type')
353 57
                                ->canBeDisabled()
354 57
                                ->children()
355 57
                                    ->scalarNode('regex')->defaultValue('/(v|version)=(?P<version>[0-9\.]+)/')->end()
356 57
                                ->end()
357 57
                            ->end()
358 57
                        ->end()
359 57
                    ->end()
360 57
                    ->arrayNode('guessing_order')
361 57
                        ->defaultValue(['query', 'custom_header', 'media_type'])
362 57
                        ->validate()
363
                            ->ifTrue(function ($v) {
364 1
                                foreach ($v as $resolver) {
365 1
                                    if (!in_array($resolver, ['query', 'custom_header', 'media_type'])) {
366
                                        return true;
367
                                    }
368 1
                                }
369 57
                            })
370 57
                            ->thenInvalid('Versioning guessing order can only contain "query", "custom_header", "media_type".')
371 57
                        ->end()
372 57
                        ->prototype('scalar')->end()
373 57
                    ->end()
374 57
                ->end()
375 57
            ->end()
376 57
        ->end();
377 57
    }
378
379 57
    private function addExceptionSection(ArrayNodeDefinition $rootNode)
380
    {
381
        $rootNode
382 57
            ->children()
383 57
                ->arrayNode('exception')
384 57
                    ->fixXmlConfig('code', 'codes')
385 57
                    ->fixXmlConfig('message', 'messages')
386 57
                    ->addDefaultsIfNotSet()
387 57
                    ->canBeEnabled()
388 57
                    ->children()
389 57
                        ->scalarNode('exception_controller')->defaultNull()->end()
390 57
                        ->arrayNode('codes')
391 57
                            ->useAttributeAsKey('name')
392 57
                            ->validate()
393
                                ->ifTrue(function ($v) { return 0 !== count(array_filter($v, function ($i) { return !defined('Symfony\Component\HttpFoundation\Response::'.$i) && !is_int($i); })); })
394 57
                                ->thenInvalid('Invalid HTTP code in fos_rest.exception.codes, see Symfony\Component\HttpFoundation\Response for all valid codes.')
395 57
                            ->end()
396 57
                            ->prototype('scalar')->end()
397 57
                        ->end()
398 57
                        ->arrayNode('messages')
399 57
                            ->useAttributeAsKey('name')
400 57
                            ->prototype('boolean')->end()
401 57
                        ->end()
402 57
                        ->booleanNode('debug')
403 57
                            ->defaultValue($this->debug)
404 57
                        ->end()
405 57
                    ->end()
406 57
                ->end()
407 57
            ->end();
408 57
    }
409
}
410