Completed
Pull Request — master (#883)
by
unknown
03:34
created

JsonSerializationVisitor::visitBoolean()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 3
crap 2
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
        }
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
        }
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
        }
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
        }
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
        } 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
            } else {
122 65
                $rs[$k] = $v;
123
            }
124
        }
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
        }
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
        }
149
150 83
        if ($this->root instanceof \stdClass && 0 === $this->dataStack->count()) {
151 68
            $this->root = $rs;
152
        }
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 16
            return;
164
        }
165
166 77
        if (true === $metadata->skipWhenEmpty) {
167 2
           if (($v instanceof \ArrayObject || \is_array($v)) && 0 === count($v)) {
168 2
               return;
169
           }
170
           if ('' === $v) {
171
            return; 
172
           }
173
        }
174
175 76
        if ($this->namingStrategy instanceof AdvancedNamingStrategyInterface) {
176 1
            $k = $this->namingStrategy->getPropertyName($metadata, $context);
177
        } else {
178 75
            $k = $this->namingStrategy->translateName($metadata);
179
        }
180
181 76
        if ($metadata->inline) {
182 3
            if (\is_array($v) || ($v instanceof \ArrayObject)) {
183 3
                $this->data = array_merge($this->data, (array) $v);
184
            }
185
        } else {
186 75
            $this->data[$k] = $v;
187
        }
188 76
    }
189
190
    /**
191
     * Allows you to add additional data to the current object/root element.
192
     * @deprecated use setData instead
193
     * @param string $key
194
     * @param integer|float|boolean|string|array|null $value This value must either be a regular scalar, or an array.
195
     *                                                       It must not contain any objects anymore.
196
     */
197 1
    public function addData($key, $value)
198
    {
199 1
        if (isset($this->data[$key])) {
200
            throw new InvalidArgumentException(sprintf('There is already data for "%s".', $key));
201
        }
202
203 1
        $this->data[$key] = $value;
204 1
    }
205
206
    /**
207
     * Checks if some data key exists.
208
     *
209
     * @param string $key
210
     * @return boolean
211
     */
212 1
    public function hasData($key)
213
    {
214 1
        return isset($this->data[$key]);
215
    }
216
217
    /**
218
     * Allows you to replace existing data on the current object/root element.
219
     *
220
     * @param string $key
221
     * @param integer|float|boolean|string|array|null $value This value must either be a regular scalar, or an array.
222
     *                                                       It must not contain any objects anymore.
223
     */
224 1
    public function setData($key, $value)
225
    {
226 1
        $this->data[$key] = $value;
227 1
    }
228
229 148
    public function getRoot()
230
    {
231 148
        return $this->root;
232
    }
233
234
    /**
235
     * @param array|\ArrayObject $data the passed data must be understood by whatever encoding function is applied later.
236
     */
237 8
    public function setRoot($data)
238
    {
239 8
        $this->root = $data;
240 8
    }
241
242
243 136
    public function getResult()
244
    {
245 136
        $result = @json_encode($this->getRoot(), $this->options);
246
247 136
        switch (json_last_error()) {
248 136
            case JSON_ERROR_NONE:
249 134
                return $result;
250
251 2
            case JSON_ERROR_UTF8:
252 2
                throw new \RuntimeException('Your data could not be encoded because it contains invalid UTF8 characters.');
253
254
            default:
255
                throw new \RuntimeException(sprintf('An error occurred while encoding your data (error code %d).', json_last_error()));
256
        }
257
    }
258
259
    public function getOptions()
260
    {
261
        return $this->options;
262
    }
263
264
    public function setOptions($options)
265
    {
266
        $this->options = (integer)$options;
267
    }
268
}
269