Passed
Branch master (c5c3fa)
by Nate
03:35
created

JsonDecodeReader   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 224
Duplicated Lines 26.34 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 32
lcom 1
cbo 3
dl 59
loc 224
ccs 98
cts 98
cp 1
rs 9.6
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 2
A beginArray() 8 8 1
A beginObject() 0 6 1
A nextBoolean() 0 10 1
A nextDouble() 0 10 1
A nextInteger() 0 10 1
A nextString() 15 15 2
C peek() 10 61 15
B getPath() 15 15 6
A push() 11 11 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/*
3
 * Copyright (c) Nate Brunette.
4
 * Distributed under the MIT License (http://opensource.org/licenses/MIT)
5
 */
6
7
namespace Tebru\Gson\Internal;
8
9
use ArrayIterator;
10
use stdClass;
11
use Tebru\Gson\Exception\MalformedJsonException;
12
use Tebru\Gson\JsonToken;
13
14
/**
15
 * Class JsonDecodeReader
16
 *
17
 * @author Nate Brunette <[email protected]>
18
 */
19
final class JsonDecodeReader extends JsonReader
20
{
21
    /**
22
     * Constructor
23
     *
24
     * @param string $json
25
     * @throws \Tebru\Gson\Exception\MalformedJsonException If the json cannot be decoded
26
     */
27 83
    public function __construct(string $json)
28
    {
29 83
        $this->push(json_decode($json));
30
31 83
        if (json_last_error() !== JSON_ERROR_NONE) {
32 1
            throw new MalformedJsonException(sprintf('Could not decode json, the error message was: "%s"', json_last_error_msg()));
33
        }
34 82
    }
35
36
    /**
37
     * Consumes the next token and asserts it's the beginning of a new array
38
     *
39
     * @return void
40
     * @throws \Tebru\Gson\Exception\UnexpectedJsonTokenException If the next token is not BEGIN_ARRAY
41
     */
42 24 View Code Duplication
    public function beginArray(): void
1 ignored issue
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...
43
    {
44 24
        $this->expect(JsonToken::BEGIN_ARRAY);
45
46 23
        $array = $this->pop();
47 23
        $this->push(new ArrayIterator($array), ArrayIterator::class);
48 23
        $this->pathIndices[$this->stackSize - 1] = 0;
49 23
    }
50
51
    /**
52
     * Consumes the next token and asserts it's the beginning of a new object
53
     *
54
     * @return void
55
     * @throws \Tebru\Gson\Exception\UnexpectedJsonTokenException If the next token is not BEGIN_OBJECT
56
     */
57 24
    public function beginObject(): void
58
    {
59 24
        $this->expect(JsonToken::BEGIN_OBJECT);
60
61 23
        $this->push(new StdClassIterator($this->pop()), StdClassIterator::class);
62 23
    }
63
64
    /**
65
     * Consumes the value of the next token, asserts it's a boolean and returns it
66
     *
67
     * @return bool
68
     * @throws \Tebru\Gson\Exception\UnexpectedJsonTokenException If the next token is not BOOLEAN
69
     */
70 6
    public function nextBoolean(): bool
71
    {
72 6
        $this->expect(JsonToken::BOOLEAN);
73
74 6
        $result = (bool)$this->pop();
75
76 6
        $this->incrementPathIndex();
77
78 6
        return $result;
79
    }
80
81
    /**
82
     * Consumes the value of the next token, asserts it's a double and returns it
83
     *
84
     * @return double
85
     * @throws \Tebru\Gson\Exception\UnexpectedJsonTokenException If the next token is not NUMBER
86
     */
87 3
    public function nextDouble(): float
88
    {
89 3
        $this->expect(JsonToken::NUMBER);
90
91 2
        $result = (float)$this->pop();
92
93 2
        $this->incrementPathIndex();
94
95 2
        return $result;
96
    }
97
98
    /**
99
     * Consumes the value of the next token, asserts it's an int and returns it
100
     *
101
     * @return int
102
     * @throws \Tebru\Gson\Exception\UnexpectedJsonTokenException If the next token is not NUMBER
103
     */
104 15
    public function nextInteger(): int
105
    {
106 15
        $this->expect(JsonToken::NUMBER);
107
108 14
        $result = (int)$this->pop();
109
110 14
        $this->incrementPathIndex();
111
112 14
        return $result;
113
    }
114
115
    /**
116
     * Consumes the value of the next token, asserts it's a string and returns it
117
     *
118
     * @return string
119
     * @throws \Tebru\Gson\Exception\UnexpectedJsonTokenException If the next token is not NAME or STRING
120
     */
121 13 View Code Duplication
    public function nextString(): string
1 ignored issue
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...
122
    {
123 13
        $peek = $this->peek();
124 13
        if ($peek === JsonToken::NAME) {
125 1
            return $this->nextName();
126
        }
127
128 12
        $this->expect(JsonToken::STRING);
129
130 11
        $result = (string)$this->pop();
131
132 11
        $this->incrementPathIndex();
133
134 11
        return $result;
135
    }
136
137
    /**
138
     * Returns an enum representing the type of the next token without consuming it
139
     *
140
     * @return string
141
     */
142 81
    public function peek(): string
143
    {
144 81
        if (null !== $this->currentToken) {
145 22
            return $this->currentToken;
146
        }
147
148 81
        if (0 === $this->stackSize) {
149 1
            $this->currentToken = JsonToken::END_DOCUMENT;
150
151 1
            return $this->currentToken;
152
        }
153
154 81
        $token = null;
155 81
        $element = $this->stack[$this->stackSize - 1];
156
157 81
        switch ($this->stackTypes[$this->stackSize - 1]) {
158 81
            case 'array':
159 25
                $token = JsonToken::BEGIN_ARRAY;
160 25
                break;
161 77
            case 'string':
162 18
                $token = JsonToken::STRING;
163 18
                break;
164 65
            case 'double':
165 1
                $token = JsonToken::NUMBER;
166 1
                break;
167 64
            case 'integer':
168 30
                $token = JsonToken::NUMBER;
169 30
                break;
170 50
            case 'boolean':
171 8
                return JsonToken::BOOLEAN;
172 46
            case 'NULL':
173 2
                $token = JsonToken::NULL;
174 2
                break;
175 44
            case StdClassIterator::class:
176
                /** @var StdClassIterator $element */
177 21
                $token = $element->valid() ? JsonToken::NAME : JsonToken::END_OBJECT;
178 21
                break;
179 44 View Code Duplication
            case ArrayIterator::class:
1 ignored issue
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...
180
                /** @var ArrayIterator $element */
181 21
                if ($element->valid()) {
182 17
                    $this->push($element->current());
183 17
                    $element->next();
184
185 17
                    $token = $this->peek();
186
                } else {
187 9
                    $token = JsonToken::END_ARRAY;
188
                }
189 21
                break;
190 27
            case 'object':
191 27
                switch (get_class($element)) {
192 27
                    case stdClass::class:
193 27
                        $token = JsonToken::BEGIN_OBJECT;
194 27
                        break;
195
                }
196 27
                break;
197
        }
198
199 77
        $this->currentToken = $token;
200
201 77
        return $this->currentToken;
202
    }
203
204
    /**
205
     * Get the current read path in json xpath format
206
     *
207
     * @return string
208
     */
209 23 View Code Duplication
    public function getPath(): string
1 ignored issue
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...
210
    {
211 23
        $result = '$';
212 23
        foreach ($this->stack as $index => $item) {
213 21
            if ($item instanceof ArrayIterator && isset($this->pathIndices[$index])) {
214 9
                $result .= '['.$this->pathIndices[$index].']';
215
            }
216
217 21
            if ($item instanceof StdClassIterator && isset($this->pathNames[$index])) {
218 21
                $result .= '.'.$this->pathNames[$index];
219
            }
220
        }
221
222 23
        return $result;
223
    }
224
225
    /**
226
     * Push an element onto the stack
227
     *
228
     * @param mixed $element
229
     * @param string $type
0 ignored issues
show
Documentation introduced by
Should the type for parameter $type not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
230
     */
231 83 View Code Duplication
    protected function push($element, $type = null): void
1 ignored issue
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...
232
    {
233 83
        if (null === $type) {
234 83
            $type = gettype($element);
235
        }
236
237 83
        $this->stack[$this->stackSize] = $element;
238 83
        $this->stackTypes[$this->stackSize] = $type;
239 83
        $this->stackSize++;
240 83
        $this->currentToken = null;
241 83
    }
242
}
243