Completed
Push — master ( 7e34da...6641a9 )
by
unknown
16:58
created

HalJsonFormat::formatJson()   C

Complexity

Conditions 16
Paths 17

Size

Total Lines 60
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 60
rs 6.2854
cc 16
eloc 50
nc 17
nop 1

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
namespace Aoe\Restler\System\Restler\Format;
3
4
use Luracast\Restler\Data\Object;
5
use Luracast\Restler\Format\Format;
6
use Luracast\Restler\RestException;
7
8
class HalJsonFormat extends Format
9
{
10
    /**
11
     * @var boolean|null  shim for json_encode option JSON_PRETTY_PRINT set
12
     * it to null to use smart defaults
13
     */
14
    public static $prettyPrint = null;
15
16
    /**
17
     * @var boolean|null  shim for json_encode option JSON_UNESCAPED_SLASHES
18
     * set it to null to use smart defaults
19
     */
20
    public static $unEscapedSlashes = null;
21
22
    /**
23
     * @var boolean|null  shim for json_encode JSON_UNESCAPED_UNICODE set it
24
     * to null to use smart defaults
25
     */
26
    public static $unEscapedUnicode = null;
27
28
    /**
29
     * @var boolean|null  shim for json_decode JSON_BIGINT_AS_STRING set it to
30
     * null to
31
     * use smart defaults
32
     */
33
    public static $bigIntAsString = null;
34
35
    /**
36
     * @var boolean|null  shim for json_decode JSON_NUMERIC_CHECK set it to
37
     * null to
38
     * use smart defaults
39
     */
40
    public static $numbersAsNumbers = null;
41
42
    const MIME = 'application/hal+json';
43
    const EXTENSION = 'json';
44
45
    public function encode($data, $humanReadable = false)
46
    {
47
        if (!is_null(self::$prettyPrint)) {
48
            $humanReadable = self::$prettyPrint;
49
        }
50
        if (is_null(self::$unEscapedSlashes)) {
51
            self::$unEscapedSlashes = $humanReadable;
52
        }
53
        if (is_null(self::$unEscapedUnicode)) {
54
            self::$unEscapedUnicode = $this->charset == 'utf-8';
55
        }
56
57
        $options = 0;
58
59
        if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) // PHP >= 5.4
60
            || PHP_MAJOR_VERSION > 5 // PHP >= 6.0
61
        ) {
62
            if ($humanReadable) {
63
                $options |= JSON_PRETTY_PRINT;
64
            }
65
66
            if (self::$unEscapedSlashes) {
67
                $options |= JSON_UNESCAPED_SLASHES;
68
            }
69
70
            if (self::$bigIntAsString) {
71
                $options |= JSON_BIGINT_AS_STRING;
72
            }
73
74
            if (self::$unEscapedUnicode) {
75
                $options |= JSON_UNESCAPED_UNICODE;
76
            }
77
78
            if (self::$numbersAsNumbers) {
79
                $options |= JSON_NUMERIC_CHECK;
80
            }
81
82
            $result = json_encode(Object::toArray($data, true), $options);
83
            $this->handleJsonError();
84
85
            return $result;
86
        }
87
88
        $result = json_encode(Object::toArray($data, true));
89
        $this->handleJsonError();
90
91
        if ($humanReadable) {
92
            $result = $this->formatJson($result);
93
        }
94
95
        if (self::$unEscapedUnicode) {
96
            $result = preg_replace_callback(
97
                '/\\\u(\w\w\w\w)/',
98
                function ($matches) {
99
                    if (function_exists('mb_convert_encoding')) {
100
                        return mb_convert_encoding(pack('H*', $matches[1]), 'UTF-8', 'UTF-16BE');
101
                    } else {
102
                        return iconv('UTF-16BE', 'UTF-8', pack('H*', $matches[1]));
103
                    }
104
                },
105
                $result
106
            );
107
        }
108
109
        if (self::$unEscapedSlashes) {
110
            $result = str_replace('\/', '/', $result);
111
        }
112
113
        return $result;
114
    }
115
116
    public function decode($data)
117
    {
118
        if (empty($data)) {
119
            return null;
120
        }
121
122
        $options = 0;
123
        if (self::$bigIntAsString) {
124
            if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) // PHP >= 5.4
125
                || PHP_MAJOR_VERSION > 5 // PHP >= 6.0
126
            ) {
127
                $options |= JSON_BIGINT_AS_STRING;
128
            } else {
129
                $data = preg_replace(
130
                    '/:\s*(\-?\d+(\.\d+)?([e|E][\-|\+]\d+)?)/',
131
                    ': "$1"',
132
                    $data
133
                );
134
            }
135
        }
136
137
        try {
138
            $decoded = json_decode($data, $options);
139
            $this->handleJsonError();
140
        } catch (\RuntimeException $e) {
141
            throw new RestException(400, $e->getMessage());
142
        }
143
144
        if (strlen($data) && $decoded === null || $decoded === $data) {
145
            throw new RestException(400, 'Error parsing JSON');
146
        }
147
148
        return Object::toArray($decoded);
149
    }
150
151
    /**
152
     * Pretty print JSON string
153
     *
154
     * @param  string $json
155
     *
156
     * @return string formatted json
157
     */
158
    private function formatJson($json)
159
    {
160
        $tab = '  ';
161
        $newJson = '';
162
        $indentLevel = 0;
163
        $inString = false;
164
        $len = strlen($json);
165
        for ($c = 0; $c < $len; $c++) {
166
            $char = $json [$c];
167
            switch ($char) {
168
                case '{':
169
                case '[':
170
                    if (!$inString) {
171
                        $newJson .= $char . "\n" .
172
                            str_repeat($tab, $indentLevel + 1);
173
                        $indentLevel++;
174
                    } else {
175
                        $newJson .= $char;
176
                    }
177
                    break;
178
                case '}':
179
                case ']':
180
                    if (!$inString) {
181
                        $indentLevel--;
182
                        $newJson .= "\n" .
183
                            str_repeat($tab, $indentLevel) . $char;
184
                    } else {
185
                        $newJson .= $char;
186
                    }
187
                    break;
188
                case ',':
189
                    if (!$inString) {
190
                        $newJson .= ",\n" .
191
                            str_repeat($tab, $indentLevel);
192
                    } else {
193
                        $newJson .= $char;
194
                    }
195
                    break;
196
                case ':':
197
                    if (!$inString) {
198
                        $newJson .= ': ';
199
                    } else {
200
                        $newJson .= $char;
201
                    }
202
                    break;
203
                case '"':
204
                    if ($c == 0) {
205
                        $inString = true;
206
                    } elseif ($c > 0 && $json [$c - 1] != '\\') {
207
                        $inString = !$inString;
208
                    }
209
                    break;
210
                default:
211
                    $newJson .= $char;
212
                    break;
213
            }
214
        }
215
216
        return $newJson;
217
    }
218
219
    /**
220
     * Throws an exception if an error occurred during the last JSON encoding/decoding
221
     *
222
     * @return void
223
     * @throws \RuntimeException
224
     */
225
    protected function handleJsonError()
226
    {
227
        if (function_exists('json_last_error_msg') && json_last_error() !== JSON_ERROR_NONE) {
228
            // PHP >= 5.5.0
229
            $message = json_last_error_msg();
230
        } elseif (function_exists('json_last_error')) {
231
            // PHP >= 5.3.0
232
233
            switch (json_last_error()) {
234
                case JSON_ERROR_NONE:
235
                    break;
236
                case JSON_ERROR_DEPTH:
237
                    $message = 'maximum stack depth exceeded';
238
                    break;
239
                case JSON_ERROR_STATE_MISMATCH:
240
                    $message = 'underflow or the modes mismatch';
241
                    break;
242
                case JSON_ERROR_CTRL_CHAR:
243
                    $message = 'unexpected control character found';
244
                    break;
245
                case JSON_ERROR_SYNTAX:
246
                    $message = 'malformed JSON';
247
                    break;
248
                case JSON_ERROR_UTF8:
249
                    $message = 'malformed UTF-8 characters, possibly ' .
250
                        'incorrectly encoded';
251
                    break;
252
                default:
253
                    $message = 'unknown error';
254
                    break;
255
            }
256
        }
257
258
        if (isset($message)) {
259
            throw new \RuntimeException('Error encoding/decoding JSON: '. $message);
260
        }
261
    }
262
}
263