Completed
Pull Request — master (#615)
by Asmir
01:42
created

Configuration::getConfigTreeBuilder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 19
ccs 14
cts 14
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 13
nc 1
nop 0
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 57
    public function __construct($debug = false)
35
    {
36 57
        $this->debug = $debug;
37 57
    }
38
39 57
    public function getConfigTreeBuilder()
40 1
    {
41 57
        $tb = new TreeBuilder();
42
43
        $root = $tb
44 57
            ->root('jms_serializer', 'array')
45 57
                ->children()
46 57
        ;
47
48 57
        $this->addHandlersSection($root);
49 57
        $this->addSubscribersSection($root);
50 57
        $this->addObjectConstructorsSection($root);
51 57
        $this->addSerializersSection($root);
52 57
        $this->addMetadataSection($root);
53 57
        $this->addVisitorsSection($root);
54 57
        $this->addContextSection($root);
55
56 57
        return $tb;
57
    }
58
59 57
    private function addHandlersSection(NodeBuilder $builder)
60
    {
61
        $builder
62 57
            ->arrayNode('handlers')
63 57
                ->addDefaultsIfNotSet()
64 57
                ->children()
65 57
                    ->arrayNode('datetime')
66 57
                        ->addDefaultsIfNotSet()
67 57
                        ->children()
68 57
                            ->scalarNode('default_format')->defaultValue(\DateTime::RFC3339)->end()
69 57
                            ->scalarNode('default_timezone')->defaultValue(date_default_timezone_get())->end()
70 57
                            ->scalarNode('cdata')->defaultTrue()->end()
71 57
                        ->end()
72 57
                    ->end()
73 57
                    ->arrayNode('array_collection')
74 57
                        ->addDefaultsIfNotSet()
75 57
                        ->children()
76 57
                            ->booleanNode('initialize_excluded')->defaultFalse()->end()
77 57
                        ->end()
78 57
                    ->end()
79 57
                ->end()
80 57
            ->end()
81
        ;
82 57
    }
83
84 57
    private function addSubscribersSection(NodeBuilder $builder)
85
    {
86
        $builder
87 57
            ->arrayNode('subscribers')
88 57
                ->addDefaultsIfNotSet()
89 57
                    ->children()
90 57
                        ->arrayNode('doctrine_proxy')
91 57
                        ->addDefaultsIfNotSet()
92 57
                        ->children()
93 57
                            ->booleanNode('initialize_excluded')->defaultFalse()->end()
94 57
                            ->booleanNode('initialize_virtual_types')->defaultFalse()->end()
95 57
                        ->end()
96 57
                    ->end()
97 57
                ->end()
98 57
            ->end()
99
        ;
100 57
    }
101
102 57
    private function addObjectConstructorsSection(NodeBuilder $builder)
103
    {
104
        $builder
105 57
            ->arrayNode('object_constructors')
106 57
                ->addDefaultsIfNotSet()
107 57
                    ->children()
108 57
                        ->arrayNode('doctrine')
109 57
                        ->addDefaultsIfNotSet()
110 57
                        ->children()
111 57
                            ->enumNode('fallback_strategy')
112 57
                                ->defaultValue("null")
113 57
                                ->values(["null", "exception", "fallback"])
114 57
                            ->end()
115 57
                        ->end()
116 57
                    ->end()
117 57
                ->end()
118 57
            ->end()
119
        ;
120 57
    }
121
122 57
    private function addSerializersSection(NodeBuilder $builder)
123
    {
124
        $builder
125 57
            ->arrayNode('property_naming')
126 57
                ->addDefaultsIfNotSet()
127 57
                ->beforeNormalization()
128 57
                    ->ifString()
129
                    ->then(function ($id) {
130 1
                        return array('id' => $id);
131 57
                    })
132 57
                ->end()
133 57
                ->children()
134 57
                    ->scalarNode('id')->cannotBeEmpty()->end()
135 57
                    ->scalarNode('separator')->defaultValue('_')->end()
136 57
                    ->booleanNode('lower_case')->defaultTrue()->end()
137 57
                    ->booleanNode('enable_cache')->defaultTrue()->end()
138 57
                ->end()
139 57
            ->end()
140 57
            ->arrayNode('expression_evaluator')
141 57
                ->addDefaultsIfNotSet()
142 57
                ->beforeNormalization()
143 57
                    ->ifString()
144
                    ->then(function ($id) {
145 1
                        return array('id' => $id);
146 57
                    })
147 57
                ->end()
148 57
                ->children()
149 57
                    ->scalarNode('id')
150
                        ->defaultValue(function () {
151 53
                            if (interface_exists('Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface')) {
152 53
                                return 'jms_serializer.expression_evaluator';
153
                            }
154
                            return null;
155 57
                        })
156 57
                        ->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 57
                            })
163 57
                        ->end()
164 57
                ->end()
165 57
            ->end()
166
        ;
167 57
    }
168
169 57
    private function addMetadataSection(NodeBuilder $builder)
170
    {
171
        $builder
172 57
            ->arrayNode('metadata')
173 57
                ->addDefaultsIfNotSet()
174 57
                ->fixXmlConfig('directory', 'directories')
175 57
                ->children()
176
177 57
                    ->arrayNode('warmup')
178 57
                        ->addDefaultsIfNotSet()
179 57
                        ->children()
180 57
                            ->arrayNode('directories')
181 57
                                ->scalarPrototype()->end()
182 57
                            ->end()
183 57
                        ->end()
184 57
                    ->end()
185
186 57
                    ->scalarNode('cache')->defaultValue('file')->end()
187 57
                    ->booleanNode('debug')->defaultValue($this->debug)->end()
188 57
                    ->arrayNode('file_cache')
189 57
                        ->addDefaultsIfNotSet()
190 57
                        ->children()
191 57
                            ->scalarNode('dir')->defaultValue('%kernel.cache_dir%/jms_serializer')->end()
192 57
                        ->end()
193 57
                    ->end()
194 57
                    ->booleanNode('auto_detection')->defaultTrue()->end()
195 57
                    ->booleanNode('infer_types_from_doctrine_metadata')
196 57
                        ->info('Infers type information from Doctrine metadata if no explicit type has been defined for a property.')
197 57
                        ->defaultTrue()
198 57
                    ->end()
199 57
                    ->arrayNode('directories')
200 57
                        ->useAttributeAsKey('name')
201 57
                        ->prototype('array')
202 57
                            ->children()
203 57
                                ->scalarNode('path')->isRequired()->end()
204 57
                                ->scalarNode('namespace_prefix')->defaultValue('')->end()
205 57
                            ->end()
206 57
                        ->end()
207 57
                    ->end()
208 57
            ->end()
209
        ;
210 57
    }
211
212 57
    private function addVisitorsSection(NodeBuilder $builder)
213
    {
214
        $builder
215 57
            ->arrayNode('visitors')
216 57
                ->addDefaultsIfNotSet()
217 57
                ->children()
218 57
                    ->arrayNode('json')
219 57
                        ->addDefaultsIfNotSet()
220 57
                        ->children()
221 57
                            ->scalarNode('options')
222 57
                                ->defaultValue(0)
223 57
                                ->beforeNormalization()
224
                                    ->ifArray()->then(function($v) {
225 1
                                        $options = 0;
226 1
                                        foreach ($v as $option) {
227 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...
228
                                                $options |= (int) $option;
229 1
                                            } elseif (defined($option)) {
230 1
                                                $options |= constant($option);
231 1
                                            } else {
232
                                                throw new InvalidArgumentException('Expected either an integer representing one of the JSON_ constants, or a string of the constant itself.');
233
                                            }
234 1
                                        }
235
236 1
                                        return $options;
237 57
                                    })
238 57
                                ->end()
239 57
                                ->beforeNormalization()
240
                                    ->ifString()->then(function($v) {
241 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...
242
                                            $value = (int) $v;
243 1
                                        } elseif (defined($v)) {
244 1
                                            $value = constant($v);
245 1
                                        } else {
246
                                            throw new InvalidArgumentException('Expected either an integer representing one of the JSON_ constants, or a string of the constant itself.');
247
                                        }
248
249 1
                                        return $value;
250 57
                                    })
251 57
                                ->end()
252 57
                                ->validate()
253
                                    ->always(function($v) {
254 3
                                        if (!is_int($v)) {
255
                                            throw new InvalidArgumentException('Expected either integer value or a array of the JSON_ constants.');
256
                                        }
257
258 3
                                        return $v;
259 57
                                    })
260 57
                                ->end()
261 57
                            ->end()
262 57
                        ->end()
263 57
                    ->end()
264 57
                    ->arrayNode('xml')
265 57
                        ->fixXmlConfig('whitelisted-doctype', 'doctype_whitelist')
266 57
                        ->addDefaultsIfNotSet()
267 57
                        ->children()
268 57
                            ->arrayNode('doctype_whitelist')
269 57
                                ->prototype('scalar')->end()
270 57
                            ->end()
271 57
                            ->booleanNode('format_output')
272 57
                                ->defaultTrue()
273 57
                            ->end()
274 57
                        ->end()
275 57
                    ->end()
276 57
                ->end()
277 57
            ->end()
278
        ;
279 57
    }
280
281 57
    private function addContextSection(NodeBuilder $builder)
282
    {
283
        $root = $builder
284 57
                    ->arrayNode('default_context')
285 57
                    ->addDefaultsIfNotSet();
286
287 57
        $this->createContextNode($root->children(), 'serialization');
288 57
        $this->createContextNode($root->children(), 'deserialization');
289 57
    }
290
291 57
    private function createContextNode(NodeBuilder $builder, $name)
292
    {
293
        $builder
294 57
            ->arrayNode($name)
295 57
                ->addDefaultsIfNotSet()
296 57
                ->beforeNormalization()
297 57
                    ->ifString()
298
                    ->then(function ($id) {
299 1
                        return array('id' => $id);
300 57
                    })
301 57
                ->end()
302
                ->validate()->always(function ($v) {
303 6
                    if (!empty($v['id'])) {
304 2
                        return array('id' => $v['id']);
305
                    }
306 4
                    return $v;
307 57
                })->end()
308 57
                ->children()
309 57
                    ->scalarNode('id')->cannotBeEmpty()->end()
310 57
                    ->scalarNode('serialize_null')
311 57
                        ->validate()->always(function ($v) {
312
                            if (!in_array($v, array(true, false, NULL), true)){
313
                                throw new InvalidTypeException("Expected boolean or NULL for the serialize_null option");
314
                            }
315
                            return $v;
316 57
                        })
317 57
                        ->ifNull()->thenUnset()
318 57
                        ->end()
319 57
                        ->info('Flag if null values should be serialized')
320 57
                    ->end()
321 57
                    ->scalarNode('enable_max_depth_checks')
322 57
                        ->info('Flag to enable the max-depth exclusion strategy')
323 57
                    ->end()
324 57
                    ->arrayNode('attributes')
325 57
                        ->fixXmlConfig('attribute')
326 57
                        ->useAttributeAsKey('key')
327 57
                        ->prototype('scalar')->end()
328 57
                        ->info('Arbitrary key-value data for context')
329 57
                    ->end()
330 57
                    ->arrayNode('groups')
331 57
                        ->fixXmlConfig('group')
332 57
                        ->prototype('scalar')->end()
333 57
                        ->info('Default serialization groups')
334 57
                    ->end()
335 57
                    ->scalarNode('version')
336 57
                        ->validate()->ifNull()->thenUnset()->end()
337 57
                        ->info('Application version to use in exclusion strategies')
338 57
                    ->end()
339 57
                ->end()
340 57
            ->end();
341 57
    }
342
}
343