Completed
Pull Request — master (#615)
by Asmir
06:59 queued 03:47
created

Configuration::addMetadataSection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 50
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 45
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 50
rs 9.3333
c 1
b 0
f 0
ccs 45
cts 45
cp 1
cc 1
eloc 45
nc 1
nop 1
crap 1
1
<?php
2
3
/*
4
 * Copyright 2011 Johannes M. Schmitt <[email protected]>
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
namespace JMS\SerializerBundle\DependencyInjection;
20
21
use JMS\Serializer\Exception\InvalidArgumentException;
22
use Symfony\Component\Config\Definition\Builder\NodeBuilder;
23
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
24
use Symfony\Component\Config\Definition\ConfigurationInterface;
25
use Symfony\Component\Config\Definition\Exception\InvalidTypeException;
26
27
class Configuration implements ConfigurationInterface
28
{
29
    private $debug;
30
31
    /**
32
     * @param boolean $debug
33
     */
34 59
    public function __construct($debug = false)
35
    {
36 59
        $this->debug = $debug;
37 59
    }
38
39 59
    public function getConfigTreeBuilder()
40 1
    {
41 59
        $tb = new TreeBuilder();
42
43
        $root = $tb
44 59
            ->root('jms_serializer', 'array')
45 59
                ->children()
46 59
        ;
47
48 59
        $this->addHandlersSection($root);
49 59
        $this->addSubscribersSection($root);
50 59
        $this->addObjectConstructorsSection($root);
51 59
        $this->addSerializersSection($root);
52 59
        $this->addMetadataSection($root);
53 59
        $this->addVisitorsSection($root);
54 59
        $this->addContextSection($root);
55
56 59
        return $tb;
57
    }
58
59 59
    private function addHandlersSection(NodeBuilder $builder)
60
    {
61
        $builder
62 59
            ->arrayNode('handlers')
63 59
                ->addDefaultsIfNotSet()
64 59
                ->children()
65 59
                    ->arrayNode('datetime')
66 59
                        ->addDefaultsIfNotSet()
67 59
                        ->children()
68 59
                            ->scalarNode('default_format')->defaultValue(\DateTime::RFC3339)->end()
69 59
                            ->scalarNode('default_timezone')->defaultValue(date_default_timezone_get())->end()
70 59
                            ->scalarNode('cdata')->defaultTrue()->end()
71 59
                        ->end()
72 59
                    ->end()
73 59
                    ->arrayNode('array_collection')
74 59
                        ->addDefaultsIfNotSet()
75 59
                        ->children()
76 59
                            ->booleanNode('initialize_excluded')->defaultFalse()->end()
77 59
                        ->end()
78 59
                    ->end()
79 59
                ->end()
80 59
            ->end()
81
        ;
82 59
    }
83
84 59
    private function addSubscribersSection(NodeBuilder $builder)
85
    {
86
        $builder
87 59
            ->arrayNode('subscribers')
88 59
                ->addDefaultsIfNotSet()
89 59
                    ->children()
90 59
                        ->arrayNode('doctrine_proxy')
91 59
                        ->addDefaultsIfNotSet()
92 59
                        ->children()
93 59
                            ->booleanNode('initialize_excluded')->defaultFalse()->end()
94 59
                            ->booleanNode('initialize_virtual_types')->defaultFalse()->end()
95 59
                        ->end()
96 59
                    ->end()
97 59
                ->end()
98 59
            ->end()
99
        ;
100 59
    }
101
102 59
    private function addObjectConstructorsSection(NodeBuilder $builder)
103
    {
104
        $builder
105 59
            ->arrayNode('object_constructors')
106 59
                ->addDefaultsIfNotSet()
107 59
                    ->children()
108 59
                        ->arrayNode('doctrine')
109 59
                        ->addDefaultsIfNotSet()
110 59
                        ->children()
111 59
                            ->enumNode('fallback_strategy')
112 59
                                ->defaultValue("null")
113 59
                                ->values(["null", "exception", "fallback"])
114 59
                            ->end()
115 59
                        ->end()
116 59
                    ->end()
117 59
                ->end()
118 59
            ->end()
119
        ;
120 59
    }
121
122 59
    private function addSerializersSection(NodeBuilder $builder)
123
    {
124
        $builder
125 59
            ->arrayNode('property_naming')
126 59
                ->addDefaultsIfNotSet()
127 59
                ->beforeNormalization()
128 59
                    ->ifString()
129
                    ->then(function ($id) {
130 1
                        return array('id' => $id);
131 59
                    })
132 59
                ->end()
133 59
                ->children()
134 59
                    ->scalarNode('id')->cannotBeEmpty()->end()
135 59
                    ->scalarNode('separator')->defaultValue('_')->end()
136 59
                    ->booleanNode('lower_case')->defaultTrue()->end()
137 59
                    ->booleanNode('enable_cache')->defaultTrue()->end()
138 59
                ->end()
139 59
            ->end()
140 59
            ->arrayNode('expression_evaluator')
141 59
                ->addDefaultsIfNotSet()
142 59
                ->beforeNormalization()
143 59
                    ->ifString()
144
                    ->then(function ($id) {
145 1
                        return array('id' => $id);
146 59
                    })
147 59
                ->end()
148 59
                ->children()
149 59
                    ->scalarNode('id')
150
                        ->defaultValue(function () {
151 55
                            if (interface_exists('Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface')) {
152 55
                                return 'jms_serializer.expression_evaluator';
153
                            }
154
                            return null;
155 59
                        })
156 59
                        ->validate()
157
                            ->always(function($v) {
158 3
                                if (!empty($v) && !interface_exists('Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface')) {
159
                                    throw new InvalidArgumentException('You need at least symfony/expression language v2.6 or v3.0 to use the expression evaluator features');
160
                                }
161 3
                                return $v;
162 59
                            })
163 59
                        ->end()
164 59
                ->end()
165 59
            ->end()
166
        ;
167 59
    }
168
169 59
    private function addMetadataSection(NodeBuilder $builder)
170
    {
171
        $builder
172 59
            ->arrayNode('metadata')
173 59
                ->addDefaultsIfNotSet()
174 59
                ->fixXmlConfig('directory', 'directories')
175 59
                ->children()
176
177 59
                    ->arrayNode('warmup')
178 59
                        ->addDefaultsIfNotSet()
179 59
                        ->children()
180 59
                            ->arrayNode('paths')
181 59
                                ->addDefaultsIfNotSet()
182 59
                                ->children()
183 59
                                    ->arrayNode('included')
184 59
                                        ->prototype('scalar')->end()
185 59
                                    ->end()
186 59
                                    ->arrayNode('excluded')
187 59
                                        ->prototype('scalar')->end()
188 59
                                    ->end()
189 59
                                ->end()
190 59
                            ->end()
191 59
                        ->end()
192 59
                    ->end()
193
194 59
                    ->scalarNode('cache')->defaultValue('file')->end()
195 59
                    ->booleanNode('debug')->defaultValue($this->debug)->end()
196 59
                    ->arrayNode('file_cache')
197 59
                        ->addDefaultsIfNotSet()
198 59
                        ->children()
199 59
                            ->scalarNode('dir')->defaultValue('%kernel.cache_dir%/jms_serializer')->end()
200 59
                        ->end()
201 59
                    ->end()
202 59
                    ->booleanNode('auto_detection')->defaultTrue()->end()
203 59
                    ->booleanNode('infer_types_from_doctrine_metadata')
204 59
                        ->info('Infers type information from Doctrine metadata if no explicit type has been defined for a property.')
205 59
                        ->defaultTrue()
206 59
                    ->end()
207 59
                    ->arrayNode('directories')
208 59
                        ->useAttributeAsKey('name')
209 59
                        ->prototype('array')
210 59
                            ->children()
211 59
                                ->scalarNode('path')->isRequired()->end()
212 59
                                ->scalarNode('namespace_prefix')->defaultValue('')->end()
213 59
                            ->end()
214 59
                        ->end()
215 59
                    ->end()
216 59
            ->end()
217
        ;
218 59
    }
219
220 59
    private function addVisitorsSection(NodeBuilder $builder)
221
    {
222
        $builder
223 59
            ->arrayNode('visitors')
224 59
                ->addDefaultsIfNotSet()
225 59
                ->children()
226 59
                    ->arrayNode('json')
227 59
                        ->addDefaultsIfNotSet()
228 59
                        ->children()
229 59
                            ->scalarNode('options')
230 59
                                ->defaultValue(0)
231 59
                                ->beforeNormalization()
232
                                    ->ifArray()->then(function($v) {
233 1
                                        $options = 0;
234 1
                                        foreach ($v as $option) {
235 1 View Code Duplication
                                            if (is_numeric($option)) {
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...
236
                                                $options |= (int) $option;
237 1
                                            } elseif (defined($option)) {
238 1
                                                $options |= constant($option);
239 1
                                            } else {
240
                                                throw new InvalidArgumentException('Expected either an integer representing one of the JSON_ constants, or a string of the constant itself.');
241
                                            }
242 1
                                        }
243
244 1
                                        return $options;
245 59
                                    })
246 59
                                ->end()
247 59
                                ->beforeNormalization()
248
                                    ->ifString()->then(function($v) {
249 1 View Code Duplication
                                        if (is_numeric($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...
250
                                            $value = (int) $v;
251 1
                                        } elseif (defined($v)) {
252 1
                                            $value = constant($v);
253 1
                                        } else {
254
                                            throw new InvalidArgumentException('Expected either an integer representing one of the JSON_ constants, or a string of the constant itself.');
255
                                        }
256
257 1
                                        return $value;
258 59
                                    })
259 59
                                ->end()
260 59
                                ->validate()
261
                                    ->always(function($v) {
262 3
                                        if (!is_int($v)) {
263
                                            throw new InvalidArgumentException('Expected either integer value or a array of the JSON_ constants.');
264
                                        }
265
266 3
                                        return $v;
267 59
                                    })
268 59
                                ->end()
269 59
                            ->end()
270 59
                        ->end()
271 59
                    ->end()
272 59
                    ->arrayNode('xml')
273 59
                        ->fixXmlConfig('whitelisted-doctype', 'doctype_whitelist')
274 59
                        ->addDefaultsIfNotSet()
275 59
                        ->children()
276 59
                            ->arrayNode('doctype_whitelist')
277 59
                                ->prototype('scalar')->end()
278 59
                            ->end()
279 59
                            ->booleanNode('format_output')
280 59
                                ->defaultTrue()
281 59
                            ->end()
282 59
                        ->end()
283 59
                    ->end()
284 59
                ->end()
285 59
            ->end()
286
        ;
287 59
    }
288
289 59
    private function addContextSection(NodeBuilder $builder)
290
    {
291
        $root = $builder
292 59
                    ->arrayNode('default_context')
293 59
                    ->addDefaultsIfNotSet();
294
295 59
        $this->createContextNode($root->children(), 'serialization');
296 59
        $this->createContextNode($root->children(), 'deserialization');
297 59
    }
298
299 59
    private function createContextNode(NodeBuilder $builder, $name)
300
    {
301
        $builder
302 59
            ->arrayNode($name)
303 59
                ->addDefaultsIfNotSet()
304 59
                ->beforeNormalization()
305 59
                    ->ifString()
306
                    ->then(function ($id) {
307 1
                        return array('id' => $id);
308 59
                    })
309 59
                ->end()
310
                ->validate()->always(function ($v) {
311 6
                    if (!empty($v['id'])) {
312 2
                        return array('id' => $v['id']);
313
                    }
314 4
                    return $v;
315 59
                })->end()
316 59
                ->children()
317 59
                    ->scalarNode('id')->cannotBeEmpty()->end()
318 59
                    ->scalarNode('serialize_null')
319 59
                        ->validate()->always(function ($v) {
320
                            if (!in_array($v, array(true, false, NULL), true)){
321
                                throw new InvalidTypeException("Expected boolean or NULL for the serialize_null option");
322
                            }
323
                            return $v;
324 59
                        })
325 59
                        ->ifNull()->thenUnset()
326 59
                        ->end()
327 59
                        ->info('Flag if null values should be serialized')
328 59
                    ->end()
329 59
                    ->scalarNode('enable_max_depth_checks')
330 59
                        ->info('Flag to enable the max-depth exclusion strategy')
331 59
                    ->end()
332 59
                    ->arrayNode('attributes')
333 59
                        ->fixXmlConfig('attribute')
334 59
                        ->useAttributeAsKey('key')
335 59
                        ->prototype('scalar')->end()
336 59
                        ->info('Arbitrary key-value data for context')
337 59
                    ->end()
338 59
                    ->arrayNode('groups')
339 59
                        ->fixXmlConfig('group')
340 59
                        ->prototype('scalar')->end()
341 59
                        ->info('Default serialization groups')
342 59
                    ->end()
343 59
                    ->scalarNode('version')
344 59
                        ->validate()->ifNull()->thenUnset()->end()
345 59
                        ->info('Application version to use in exclusion strategies')
346 59
                    ->end()
347 59
                ->end()
348 59
            ->end();
349 59
    }
350
}
351