JsonWriter::writeValue()   D
last analyzed

Complexity

Conditions 19
Paths 19

Size

Total Lines 66
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 37
CRAP Score 19.0487

Importance

Changes 3
Bugs 1 Features 0
Metric Value
eloc 43
c 3
b 1
f 0
dl 0
loc 66
ccs 37
cts 39
cp 0.9487
rs 4.5166
cc 19
nc 19
nop 2
crap 19.0487

How to fix   Long Method    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
namespace POData\Writers\Json;
4
5
6
use POData\Writers\Json\IndentedTextWriter;
7
8
/**
9
 * Class JsonWriter
10
 * @package POData\Writers\Json
11
 */
12
class JsonWriter
13
{
14
    /**
15
     * Json datetime format.
16
     *
17
     */
18
    private $_jsonDateTimeFormat = "\/Date(%s)\/";
0 ignored issues
show
introduced by
The private property $_jsonDateTimeFormat is not used, and could be removed.
Loading history...
19
20
21
    /**
22
     * Writer to write text into
23
     *
24
     */
25
    private $_writer;
26
27
    /**
28
     * scope of the json text - object, array, etc
29
     *
30
     */
31
    private $_scopes = array();
32
33
    /**
34
     * Various scope types for Json writer
35
     *
36
     */
37
    private $_scopeType = array('Array' => 0, 'Object' => 1);
38
39
    /**
40
     * Creates a new instance of Json writer
41
     *
42
     * @param string $writer writer to which text needs to be written
43
     */
44 256
    public function __construct($writer)
45
    {
46 256
        $this->_writer = new IndentedTextWriter($writer);
47
48
    }
49
50
    public function clear()
51
    {
52
        $this->_writer->clear();
53
    }
54
55
    /**
56
     * End the current scope
57
     *
58
     * @return JsonWriter
59
     */
60 64
    public function endScope()
61
    {
62 64
        $this->_writer
63 64
            ->writeLine()
64 64
            ->decreaseIndent();
65
66 64
        if (array_pop($this->_scopes)->type == $this->_scopeType['Array']) {
67 35
            $this->_writer->writeValue("]");
68
        } else {
69 63
            $this->_writer->writeValue("}");
70
        }
71
72 64
        return $this;
73
74
    }
75
76
    /**
77
     * Start the array scope
78
     *
79
     * @return JsonWriter
80
     */
81 35
    public function startArrayScope()
82
    {
83 35
        $this->_startScope($this->_scopeType['Array']);
84 35
        return $this;
85
    }
86
87
88
    /**
89
     * Write the "results" header for the data array
90
     *
91
     * @return JsonWriter
92
     */
93
    public function writeDataArrayName()
94
    {
95
        $this->writeName($this->dataArrayName);
0 ignored issues
show
Bug Best Practice introduced by
The property dataArrayName does not exist on POData\Writers\Json\JsonWriter. Did you maybe forget to declare it?
Loading history...
96
        return $this;
97
    }
98
99
    /**
100
     * Start the object scope
101
     *
102
     * @return JsonWriter
103
     */
104 63
    public function startObjectScope()
105
    {
106 63
        $this->_startScope($this->_scopeType['Object']);
107 63
        return $this;
108
    }
109
110
    /**
111
     * Write the name for the object property
112
     *
113
     * @param string $name name of the object property
114
     *
115
     * @return JsonWriter
116
     */
117 63
    public function writeName($name)
118
    {
119 63
        $currentScope = end($this->_scopes);
120 63
        if ($currentScope && $currentScope->type == $this->_scopeType['Object']) {
121 63
            if ($currentScope->objectCount != 0) {
122 51
                $this->_writer->writeTrimmed(", ");
123
            }
124
125 63
            $currentScope->objectCount++;
126
        }
127
128 63
        $this->_writeCore($name, true /*quotes*/);
129 63
        $this->_writer->writeTrimmed(": ");
130
131 63
        return $this;
132
    }
133
134
    /**
135
     * JSON write a basic data type (string, number, boolean, null)
136
     *
137
     * @param mixed  $value value to be written
138
     * @param string $type  data type of the value
139
     *
140
     * @return JsonWriter
141
     */
142 77
    public function writeValue($value, $type = null)
143
    {
144
        switch ($type) {
145 77
            case 'Edm.Boolean':
146 76
            case 'Edm.Int16':
147 71
            case 'Edm.Int32':
148 70
            case 'Edm.Byte':
149 69
            case 'Edm.SByte':
150 33
                $this->_writeCore($value, /* quotes */ false);
151 33
                break;
152
153
154 68
            case 'Edm.Int64':
155 67
            case 'Edm.Guid':
156 66
            case 'Edm.Decimal':
157 65
            case 'Edm.Binary':
158 6
                $this->_writeCore($value, /* quotes */ true);
159 6
                break;
160
161 64
            case 'Edm.Single':
162 63
            case 'Edm.Double':
163 6
                if (is_infinite($value) || is_nan($value)) {
164 2
                    $this->_writeCore("null", /* quotes */ true);
165
                } else {
166 6
                    $this->_writeCore($value, /* quotes */ false);
167
                }
168
169 6
                break;
170
171
172 62
            case 'Edm.DateTime':
173 7
                $dateTime = new \DateTime($value, new \DateTimeZone('UTC'));
174 7
                $formattedDateTime = $dateTime->format('Y-m-d\TH:i:s');
175 7
                $this->_writeCore($formattedDateTime, /* quotes */ true);
176 7
                break;
177 60
            case 'Edm.Date':
178
                $this->_writeCore($value, /* quotes */ true);
179
                break;
180
181
182 60
            case 'Edm.String':
183 27
                if (is_null($value)) {
184 1
                    $this->_writeCore("null", /* quotes */ false);
185
                } else {
186 27
                    $jsonEncoded = json_encode($value);
187
                    //json_encode always escapes a solidus (forward slash, %x2F),
188
                    //this will be a problem when encoding urls
189
                    //JSON_UNESCAPED_SLASHES not available in earlier versions of php 5.3
190
                    //So removing escaping forward slashes manually
191 27
                    $jsonEncoded = str_replace('\\/', '/', $jsonEncoded);
192
                    //since json_encode is already appending chords
193
                    //there is no need to set it again
194 27
                    $this->_writeCore($jsonEncoded, /* quotes */ false);
195
                }
196 27
                break;
197
198
199
            default:
200 55
                if (is_string($value)) {
201 55
                    $this->_writeCore($this->_quoteJScriptString($value), /* quotes */ true);
202
                } else {
203 8
                    $this->_writeCore(json_encode($value), false);
204
                }
205
        }
206
207 77
        return $this;
208
    }
209
210
    /**
211
     * Returns the string value with special characters escaped
212
     *
213
     * @param string $string input string value
214
     *
215
     * Returns the string value with special characters escaped.
216
     *
217
     * @return string
218
     */
219 55
    private function _quoteJScriptString(string $string) : string
220
    {
221
        // Escape ( " \ / \n \r \t \b \f) characters with a backslash.
222 55
        $search  = array('\\', "\n", "\t", "\r", "\b", "\f", '"');
223 55
        $replace = array('\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\"');
224 55
        $processedString = str_replace($search, $replace, $string);
225
        // Escape some ASCII characters(0x08, 0x0c)
226 55
        $processedString = str_replace(array(chr(0x08), chr(0x0C)), array('\b', '\f'), $processedString);
227 55
        return $processedString;
228
    }
229
230
    /**
231
     * Write the string value with/without quotes
232
     *
233
     * @param string $text   value to be written
234
     * @param string $quotes put quotes around the value if this value is true
235
     *
236
     * @return void
237
     */
238 79
    private function _writeCore(string $text, bool $quotes)
239
    {
240 79
        if (count($this->_scopes) != 0) {
241 64
            $currentScope = end($this->_scopes);
242 64
            if ($currentScope->type == $this->_scopeType['Array']) {
243 9
                if ($currentScope->objectCount != 0) {
244 9
                    $this->_writer->writeTrimmed(", ");
245
                }
246
247 9
                $currentScope->objectCount++;
248
            }
249
        }
250
251 79
        if ($quotes && $text !== 'null') {
252 70
            $this->_writer->writeValue('"');
253
        }
254
255 79
        $this->_writer->writeValue($text);
256 79
        if ($quotes && $text !== 'null') {
257 70
            $this->_writer->writeValue('"');
258
        }
259
    }
260
261
    /**
262
     * Start the scope given the scope type
263
     *
264
     * @param int $type scope type
265
     *
266
     * @return void
267
     */
268 64
    private function _startScope($type)
269
    {
270 64
        if (count($this->_scopes) != 0) {
271 49
            $currentScope = end($this->_scopes);
272 49
            if (($currentScope->type == $this->_scopeType['Array'])
273 49
                && ($currentScope->objectCount != 0)
274
            ) {
275 21
                $this->_writer->writeTrimmed(", ");
276
            }
277
278 49
            $currentScope->objectCount++;
279
        }
280
281 64
        $scope = new Scope($type);
282 64
        array_push($this->_scopes, $scope);
283
284 64
        if ($type == $this->_scopeType['Array']) {
285 35
            $this->_writer->writeValue("[");
286
        } else {
287 63
            $this->_writer->writeValue("{");
288
        }
289
290 64
        $this->_writer
291 64
            ->increaseIndent()
292 64
            ->writeLine();
293
    }
294
295
    /**
296
     * return the indented result
297
     *
298
     * @return string
299
     */
300 79
    public function getJsonOutput()
301
    {
302 79
        return $this->_writer->getResult();
303
    }
304
}
305
306
307
308
/**
309
 * class representing scope information
310
*
311
 */
312
class Scope
313
{
314
    /**
315
     * keeps the count of the nested scopes
316
     *
317
     */
318
    public $objectCount;
319
320
    /**
321
     *  keeps the type of the scope
322
     *
323
     */
324
    public $type;
325
326
    /**
327
     * Creates a new instance of scope type
328
     *
329
     * @param int $type type of the scope
330
     */
331 64
    public function __construct($type)
332
    {
333 64
        $this->type = $type;
334 64
        $this->objectCount = 0;
335
    }
336
337
}
338