Completed
Pull Request — master (#859)
by
unknown
04:25
created

JsonSerializationVisitor::visitProperty()   C

Complexity

Conditions 11
Paths 7

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 11

Importance

Changes 0
Metric Value
dl 0
loc 25
ccs 18
cts 18
cp 1
rs 5.2653
c 0
b 0
f 0
cc 11
eloc 15
nc 7
nop 3
crap 11

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * Copyright 2016 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\Serializer;
20
21
use JMS\Serializer\Exception\InvalidArgumentException;
22
use JMS\Serializer\Metadata\ClassMetadata;
23
use JMS\Serializer\Metadata\PropertyMetadata;
24
use JMS\Serializer\Naming\AdvancedNamingStrategyInterface;
25
26
class JsonSerializationVisitor extends GenericSerializationVisitor
0 ignored issues
show
Deprecated Code introduced by
The class JMS\Serializer\GenericSerializationVisitor has been deprecated.

This class, trait or interface has been deprecated.

Loading history...
27
{
28
    private $options = 0;
29
30
    private $navigator;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
31
    private $root;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
32
    private $dataStack;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
33
    private $data;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
34
35 147
    public function setNavigator(GraphNavigator $navigator)
36
    {
37 147
        $this->navigator = $navigator;
38 147
        $this->root = null;
39 147
        $this->dataStack = new \SplStack;
40 147
    }
41
42
    /**
43
     * @return GraphNavigator
44
     */
45
    public function getNavigator()
46
    {
47
        return $this->navigator;
48
    }
49
50 29
    public function visitNull($data, array $type, Context $context)
51
    {
52 29
        return null;
53
    }
54
55 91
    public function visitString($data, array $type, Context $context)
56
    {
57 91
        if (null === $this->root) {
58 9
            $this->root = $data;
59 9
        }
60
61 91
        return (string)$data;
62
    }
63
64 9
    public function visitBoolean($data, array $type, Context $context)
65
    {
66 9
        if (null === $this->root) {
67 5
            $this->root = $data;
68 5
        }
69
70 9
        return (boolean)$data;
71
    }
72
73 26
    public function visitInteger($data, array $type, Context $context)
74
    {
75 26
        if (null === $this->root) {
76 4
            $this->root = $data;
77 4
        }
78
79 26
        return (int)$data;
80
    }
81
82 13
    public function visitDouble($data, array $type, Context $context)
83
    {
84 13
        if (null === $this->root) {
85 7
            $this->root = $data;
86 7
        }
87
88 13
        return (float)$data;
89
    }
90
91
    /**
92
     * @param array $data
93
     * @param array $type
94
     * @param Context $context
95
     * @return mixed
96
     */
97 71
    public function visitArray($data, array $type, Context $context)
98
    {
99 71
        $this->dataStack->push($data);
100
101 71
        $isHash = isset($type['params'][1]);
102
103 71
        if (null === $this->root) {
104 49
            $this->root = $isHash ? new \ArrayObject() : array();
105 49
            $rs = &$this->root;
106 49
        } else {
107 24
            $rs = $isHash ? new \ArrayObject() : array();
108
        }
109
110 71
        $isList = isset($type['params'][0]) && !isset($type['params'][1]);
111
112 71
        foreach ($data as $k => $v) {
113 65
            $v = $this->navigator->accept($v, $this->getElementType($type), $context);
114
115 65
            if (null === $v && $context->shouldSerializeNull() !== true) {
116 3
                continue;
117
            }
118
119 65
            if ($isList) {
120 17
                $rs[] = $v;
121 17
            } else {
122 52
                $rs[$k] = $v;
123
            }
124 71
        }
125
126 71
        $this->dataStack->pop();
127 71
        return $rs;
128
    }
129
130 84
    public function startVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context)
131
    {
132 84
        if (null === $this->root) {
133 69
            $this->root = new \stdClass;
134 69
        }
135
136 84
        $this->dataStack->push($this->data);
137 84
        $this->data = array();
138 84
    }
139
140 83
    public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context)
141
    {
142 83
        $rs = $this->data;
143 83
        $this->data = $this->dataStack->pop();
144
145
        // Force JSON output to "{}" instead of "[]" if it contains either no properties or all properties are null.
146 83
        if (empty($rs)) {
147 11
            $rs = new \ArrayObject();
0 ignored issues
show
Bug Compatibility introduced by
The expression new \ArrayObject(); of type ArrayObject adds the type ArrayObject to the return on line 154 which is incompatible with the return type of the parent method JMS\Serializer\GenericSe...itor::endVisitingObject of type array.
Loading history...
148 11
        }
149
150 83
        if ($this->root instanceof \stdClass && 0 === $this->dataStack->count()) {
151 68
            $this->root = $rs;
152 68
        }
153
154 83
        return $rs;
155
    }
156
157 80
    public function visitProperty(PropertyMetadata $metadata, $data, Context $context)
158
    {
159 80
        $v = $this->accessor->getValue($data, $metadata);
160
161 79
        $v = $this->navigator->accept($v, $metadata->type, $context);
162 79
        if ((null === $v && $context->shouldSerializeNull() !== true)
163 77
            || (true === $metadata->skipWhenEmpty && ($v instanceof \ArrayObject || is_array($v)) && 0 === count($v))
164 79
        ) {
165 17
            return;
166
        }
167
168 76
        if ($this->namingStrategy instanceof AdvancedNamingStrategyInterface) {
169 1
            $k = $this->namingStrategy->getPropertyName($metadata, $context);
170 1
        } else {
171 75
            $k = $this->namingStrategy->translateName($metadata);
172
        }
173
174 76
        if ($metadata->inline) {
175 3
            if (is_array($v) || ($v instanceof \ArrayObject)) {
176 3
                $this->data = array_merge($this->data, (array) $v);
177 3
            }
178 3
        } else {
179 75
            $this->data[$k] = $v;
180
        }
181 76
    }
182
183
    /**
184
     * Allows you to add additional data to the current object/root element.
185
     * @deprecated use setData instead
186
     * @param string $key
187
     * @param integer|float|boolean|string|array|null $value This value must either be a regular scalar, or an array.
188
     *                                                       It must not contain any objects anymore.
189
     */
190 1
    public function addData($key, $value)
191
    {
192 1
        if (isset($this->data[$key])) {
193
            throw new InvalidArgumentException(sprintf('There is already data for "%s".', $key));
194
        }
195
196 1
        $this->data[$key] = $value;
197 1
    }
198
199
    /**
200
     * Checks if some data key exists.
201
     *
202
     * @param string $key
203
     * @return boolean
204
     */
205 1
    public function hasData($key)
206
    {
207 1
        return isset($this->data[$key]);
208
    }
209
210
    /**
211
     * Allows you to replace existing data on the current object/root element.
212
     *
213
     * @param string $key
214
     * @param integer|float|boolean|string|array|null $value This value must either be a regular scalar, or an array.
215
     *                                                       It must not contain any objects anymore.
216
     */
217 1
    public function setData($key, $value)
218
    {
219 1
        $this->data[$key] = $value;
220 1
    }
221
222 148
    public function getRoot()
223
    {
224 148
        return $this->root;
225
    }
226
227
    /**
228
     * @param array|\ArrayObject $data the passed data must be understood by whatever encoding function is applied later.
229
     */
230 8
    public function setRoot($data)
231
    {
232 8
        $this->root = $data;
233 8
    }
234
235
236 136
    public function getResult()
237
    {
238 136
        $result = @json_encode($this->getRoot(), $this->options);
239
240 136
        switch (json_last_error()) {
241 136
            case JSON_ERROR_NONE:
242 134
                return $result;
243
244 2
            case JSON_ERROR_UTF8:
245 2
                throw new \RuntimeException('Your data could not be encoded because it contains invalid UTF8 characters.');
246
247
            default:
248
                throw new \RuntimeException(sprintf('An error occurred while encoding your data (error code %d).', json_last_error()));
249
        }
250
    }
251
252
    public function getOptions()
253
    {
254
        return $this->options;
255
    }
256
257
    public function setOptions($options)
258
    {
259
        $this->options = (integer)$options;
260
    }
261
}
262