Passed
Pull Request — master (#26)
by Nate
07:26
created

JsonElementWriter::topIsObjectStart()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 10
cc 3
nc 3
nop 0
crap 3
1
<?php
2
/*
3
 * Copyright (c) Nate Brunette.
4
 * Distributed under the MIT License (http://opensource.org/licenses/MIT)
5
 */
6
7
declare(strict_types=1);
8
9
namespace Tebru\Gson\Internal;
10
11
use JsonSerializable;
12
use LogicException;
13
use Tebru\Gson\Element\JsonArray;
14
use Tebru\Gson\Element\JsonElement;
15
use Tebru\Gson\Element\JsonNull;
16
use Tebru\Gson\Element\JsonObject;
17
use Tebru\Gson\Element\JsonPrimitive;
18
use Tebru\Gson\JsonWritable;
19
20
/**
21
 * Class JsonElementWriter
22
 *
23
 * @author Nate Brunette <[email protected]>
24
 */
25
final class JsonElementWriter implements JsonWritable, JsonSerializable
26
{
27
    /**
28
     * True if we should serialize nulls
29
     *
30
     * @var bool
31
     */
32
    private $serializeNull = false;
33
34
    /**
35
     * Stack of values to be written
36
     *
37
     * @var array
38
     */
39
    private $stack = [];
40
    
41
    /**
42
     * Size of the stack array
43
     *
44
     * @var int
45
     */
46
    private $stackSize = 0;
47
48
    /**
49
     * A cache of the parsing state corresponding to the stack
50
     *
51
     * @var int[]
52
     */
53
    private $stackStates = [];
54
55
    /**
56
     * When serializing an object, store the name that should be serialized
57
     *
58
     * @var
59
     */
60
    private $pendingName;
61
62
    /**
63
     * The final result that will be json encoded
64
     *
65
     * @var JsonElement
66
     */
67
    private $result;
68
69
    /**
70
     * Begin writing array
71
     *
72
     * @return JsonWritable
73
     * @throws \LogicException
74
     */
75 6 View Code Duplication
    public function beginArray(): JsonWritable
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
76
    {
77 6
        if ($this->stackSize > 0 && $this->stackStates[$this->stackSize - 1] === self::STATE_OBJECT_NAME) {
78 1
            throw new LogicException('Cannot call beginArray() before name() during object serialization');
79
        }
80
81 5
        $array = new JsonArray();
82 5
        $this->push($array);
83 5
        $this->stack[] = $array;
84 5
        $this->stackStates[$this->stackSize] = self::STATE_ARRAY;
85 5
        $this->stackSize++;
86
87 5
        return $this;
88
    }
89
90
    /**
91
     * End writing array
92
     *
93
     * @return JsonWritable
94
     * @throws \LogicException
95
     */
96 4 View Code Duplication
    public function endArray(): JsonWritable
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
97
    {
98 4
        if ($this->stackSize === 0 || $this->stackStates[$this->stackSize - 1] !== self::STATE_ARRAY) {
99 2
            throw new LogicException('Cannot call endArray() if not serializing array');
100
        }
101
102 2
        \array_pop($this->stack);
103 2
        $this->stackSize--;
104
105 2
        return $this;
106
    }
107
108
    /**
109
     * Begin writing object
110
     *
111
     * @return JsonWritable
112
     * @throws \LogicException
113
     */
114 17 View Code Duplication
    public function beginObject(): JsonWritable
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
115
    {
116 17
        if ($this->stackSize > 0 && $this->stackStates[$this->stackSize - 1] === self::STATE_OBJECT_NAME) {
117 1
            throw new LogicException('Cannot call beginObject() before name() during object serialization');
118
        }
119
120 17
        $class = new JsonObject();
121 17
        $this->push($class);
122 17
        $this->stack[$this->stackSize] = $class;
123 17
        $this->stackStates[$this->stackSize] = self::STATE_OBJECT_NAME;
124 17
        $this->stackSize++;
125
126 17
        return $this;
127
    }
128
129
    /**
130
     * End writing object
131
     *
132
     * @return JsonWritable
133
     * @throws \LogicException
134
     */
135 7 View Code Duplication
    public function endObject(): JsonWritable
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
136
    {
137 7
        if ($this->stackSize === 0 || $this->stackStates[$this->stackSize - 1] !== self::STATE_OBJECT_NAME) {
138 2
            throw new LogicException('Cannot call endObject() if not serializing object');
139
        }
140
141 5
        \array_pop($this->stack);
142 5
        $this->stackSize--;
143
144 5
        return $this;
145
    }
146
147
    /**
148
     * Writes a property name
149
     *
150
     * @param string $name
151
     * @return JsonWritable
152
     * @throws \LogicException
153
     */
154 5 View Code Duplication
    public function name(string $name): JsonWritable
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
155
    {
156 5
        if ($this->stackStates[$this->stackSize - 1] !== self::STATE_OBJECT_NAME) {
157 1
            throw new LogicException('Cannot call name() at this point.  Either name() has already been called or object serialization has not been started');
158
        }
159
160 5
        $this->pendingName = $name;
161 5
        $this->stackStates[$this->stackSize - 1] = self::STATE_OBJECT_VALUE;
162
163 5
        return $this;
164
    }
165
166
    /**
167
     * Write an integer value
168
     *
169
     * @param int $value
170
     * @return JsonWritable
171
     * @throws \LogicException
172
     */
173 4 View Code Duplication
    public function writeInteger(int $value): JsonWritable
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
174
    {
175 4
        if ($this->stackSize > 0 && $this->stackStates[$this->stackSize - 1] === self::STATE_OBJECT_NAME) {
176 1
            throw new LogicException('Cannot call writeInteger() before name() during object serialization');
177
        }
178
179 3
        return $this->push(JsonPrimitive::create($value));
180
    }
181
182
    /**
183
     * Write a float value
184
     *
185
     * @param float $value
186
     * @return JsonWritable
187
     * @throws \LogicException
188
     */
189 3 View Code Duplication
    public function writeFloat(float $value): JsonWritable
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
190
    {
191 3
        if ($this->stackSize > 0 && $this->stackStates[$this->stackSize - 1] === self::STATE_OBJECT_NAME) {
192 1
            throw new LogicException('Cannot call writeFloat() before name() during object serialization');
193
        }
194
195 2
        return $this->push(JsonPrimitive::create($value));
196
    }
197
198
    /**
199
     * Write a string value
200
     *
201
     * @param string $value
202
     * @return JsonWritable
203
     * @throws \LogicException
204
     */
205 4 View Code Duplication
    public function writeString(string $value): JsonWritable
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
206
    {
207 4
        if ($this->stackSize > 0 && $this->stackStates[$this->stackSize - 1] === self::STATE_OBJECT_NAME) {
208 1
            throw new LogicException('Cannot call writeString() before name() during object serialization');
209
        }
210
211 3
        return $this->push(JsonPrimitive::create($value));
212
    }
213
214
    /**
215
     * Write a boolean value
216
     *
217
     * @param boolean $value
218
     * @return JsonWritable
219
     * @throws \LogicException
220
     */
221 3 View Code Duplication
    public function writeBoolean(bool $value): JsonWritable
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
222
    {
223 3
        if ($this->stackSize > 0 && $this->stackStates[$this->stackSize - 1] === self::STATE_OBJECT_NAME) {
224 1
            throw new LogicException('Cannot call writeBoolean() before name() during object serialization');
225
        }
226
227 2
        return $this->push(JsonPrimitive::create($value));
228
    }
229
230
    /**
231
     * Write a null value if we are serializing nulls, otherwise
232
     * skip the value.  If this is a property value, that property
233
     * should be skipped as well.
234
     *
235
     * @return JsonWritable
236
     * @throws \LogicException
237
     */
238 5 View Code Duplication
    public function writeNull(): JsonWritable
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
239
    {
240 5
        if ($this->stackSize > 0 && $this->stackStates[$this->stackSize - 1] === self::STATE_OBJECT_NAME) {
241 1
            throw new LogicException('Cannot call writeNull() before name() during object serialization');
242
        }
243
244 4
        if ($this->serializeNull) {
245 2
            return $this->push(new JsonNull());
246
        }
247
248
        // if we're not serializing nulls
249 2
        if (null !== $this->pendingName) {
250 1
            $this->stackStates[$this->stackSize - 1] = self::STATE_OBJECT_NAME;
251 1
            $this->pendingName = null;
252
        }
253
254 2
        return $this;
255
    }
256
257
    /**
258
     * Sets whether nulls are serialized
259
     *
260
     * @param bool $serializeNull
261
     * @return void
262
     */
263 2
    public function setSerializeNull(bool $serializeNull): void
264
    {
265 2
        $this->serializeNull = $serializeNull;
266 2
    }
267
268
    /**
269
     * Specify data which should be serialized to JSON
270
     *
271
     * @return mixed
272
     */
273 17
    public function jsonSerialize()
274
    {
275 17
        if (null === $this->result) {
276 1
            return null;
277
        }
278
279 16
        return $this->result->jsonSerialize();
280
    }
281
282
    /**
283
     * Get the result as a json element
284
     *
285
     * @return JsonElement
286
     */
287 1
    public function toJsonElement(): JsonElement
288
    {
289 1
        return $this->result;
290
    }
291
292
    /**
293
     * Push a value to the result or current array/object
294
     *
295
     * @param JsonElement $value
296
     * @return JsonWritable
297
     * @throws \LogicException
298
     */
299 29
    private function push(JsonElement $value): JsonWritable
300
    {
301 29 View Code Duplication
        if (0 === $this->stackSize) {
302 29
            if (null !== $this->result) {
303 2
                throw new LogicException('Attempting to write two different types');
304
            }
305
306 29
            $this->result = $value;
307
308 29
            return $this;
309
        }
310
311 5
        switch ($this->stackStates[$this->stackSize - 1]) {
312 5 View Code Duplication
            case self::STATE_OBJECT_VALUE:
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...
313 3
                $this->stack[$this->stackSize - 1]->add($this->pendingName, $value);
314 3
                $this->stackStates[$this->stackSize - 1] = self::STATE_OBJECT_NAME;
315 3
                $this->pendingName = null;
316 3
                break;
317 2 View Code Duplication
            case self::STATE_ARRAY:
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...
318 2
                $this->stack[$this->stackSize - 1]->addJsonElement($value);
319 2
                $this->stackStates[$this->stackSize - 1] = self::STATE_ARRAY;
320 2
                break;
321
322
        }
323
324 5
        return $this;
325
    }
326
}
327