1
|
|
|
<?php |
2
|
|
|
namespace Crossjoin\Json; |
3
|
|
|
|
4
|
|
|
use Crossjoin\Json\Exception\ConversionFailedException; |
5
|
|
|
use Crossjoin\Json\Exception\EncodingNotSupportedException; |
6
|
|
|
use Crossjoin\Json\Exception\InvalidArgumentException; |
7
|
|
|
use Crossjoin\Json\Exception\NativeJsonErrorException; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* Class Encoder |
11
|
|
|
* |
12
|
|
|
* @package Crossjoin\Json |
13
|
|
|
* @author Christoph Ziegenberg <[email protected]> |
14
|
|
|
*/ |
15
|
|
|
class Encoder extends Converter |
16
|
|
|
{ |
17
|
|
|
const UTF16 = self::UTF16BE; |
18
|
|
|
const UTF32 = self::UTF32BE; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* @var string |
22
|
|
|
*/ |
23
|
|
|
private $encoding = self::UTF8; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* Encoder constructor. |
27
|
|
|
* |
28
|
|
|
* @param string $encoding |
29
|
|
|
* @throws \Crossjoin\Json\Exception\EncodingNotSupportedException |
30
|
|
|
* @throws \Crossjoin\Json\Exception\InvalidArgumentException |
31
|
|
|
*/ |
32
|
|
|
public function __construct($encoding = self::UTF8) |
33
|
|
|
{ |
34
|
|
|
$this->setEncoding($encoding); |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @return string |
39
|
|
|
*/ |
40
|
|
|
public function getEncoding() |
41
|
|
|
{ |
42
|
|
|
return $this->encoding; |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @param string $encoding |
47
|
|
|
* |
48
|
|
|
* @throws \Crossjoin\Json\Exception\EncodingNotSupportedException |
49
|
|
|
* @throws \Crossjoin\Json\Exception\InvalidArgumentException |
50
|
|
|
*/ |
51
|
|
|
public function setEncoding($encoding) |
52
|
|
|
{ |
53
|
|
|
if (is_string($encoding)) { |
54
|
|
|
if (in_array($encoding, array(self::UTF8, self::UTF16BE, self::UTF16LE, self::UTF32BE, self::UTF32LE), true)) { |
55
|
|
|
$this->encoding = $encoding; |
56
|
|
|
} else { |
57
|
|
|
throw new EncodingNotSupportedException(sprintf("Unsupported encoding '%s'.", $encoding), 1478101930); |
58
|
|
|
} |
59
|
|
|
} else { |
60
|
|
|
throw new InvalidArgumentException( |
61
|
|
|
sprintf("String expected for argument '%s'. Got '%s'.", 'encoding', gettype($encoding)), |
62
|
|
|
1478196374 |
63
|
|
|
); |
64
|
|
|
} |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* @param mixed $value |
69
|
|
|
* @param int $options |
70
|
|
|
* @param int $depth |
71
|
|
|
* |
72
|
|
|
* @return string |
73
|
|
|
* @throws \Crossjoin\Json\Exception\NativeJsonErrorException |
74
|
|
|
* @throws \Crossjoin\Json\Exception\InvalidArgumentException |
75
|
|
|
* @throws \Crossjoin\Json\Exception\ExtensionRequiredException |
76
|
|
|
* @throws \Crossjoin\Json\Exception\ConversionFailedException |
77
|
|
|
*/ |
78
|
|
|
public function encode($value, $options = 0, $depth = 512) |
79
|
|
|
{ |
80
|
|
|
// Check arguments |
81
|
|
View Code Duplication |
if (!is_int($options)) { |
|
|
|
|
82
|
|
|
throw new InvalidArgumentException( |
83
|
|
|
sprintf("Integer expected for argument '%s'. Got '%s'.", 'options', gettype($options)), |
84
|
|
|
1478418109 |
85
|
|
|
); |
86
|
|
|
} |
87
|
|
View Code Duplication |
if (!is_int($depth)) { |
|
|
|
|
88
|
|
|
throw new InvalidArgumentException( |
89
|
|
|
sprintf("Integer expected for argument '%s'. Got '%s'.", 'depth', gettype($depth)), |
90
|
|
|
1478418110 |
91
|
|
|
); |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
$toEncoding = $this->getEncoding(); |
95
|
|
|
|
96
|
|
|
// Try to encode the data |
97
|
|
|
// @codeCoverageIgnoreStart |
98
|
|
|
if (version_compare(PHP_VERSION, '5.5.0', '>=')) { |
99
|
|
|
$json = \json_encode($value, $options, $depth); |
100
|
|
|
} else { |
101
|
|
|
// Although the json_last_error() function exists, json_encode() in PHP < 5.5.0 sometimes |
102
|
|
|
// triggers an error, for example when an unsupported type is tried to be encoded. We |
103
|
|
|
// suppress these errors and throw an own exception instead. |
104
|
|
|
$json = @\json_encode($value, $options); |
105
|
|
|
if ($value !== null && $json === 'null') { |
106
|
|
|
throw new InvalidArgumentException('The type tried to encode is not supported.', 1478445896); |
107
|
|
|
} |
108
|
|
|
} |
109
|
|
|
// @codeCoverageIgnoreEnd |
110
|
|
|
|
111
|
|
View Code Duplication |
if ($json === false) { |
|
|
|
|
112
|
|
|
if (function_exists('\json_last_error_msg')) { |
113
|
|
|
throw new NativeJsonErrorException(\json_last_error_msg(), \json_last_error()); |
114
|
|
|
} else { |
115
|
|
|
throw new NativeJsonErrorException('An error occurred while encoding JSON.', \json_last_error()); |
116
|
|
|
} |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
// Convert |
120
|
|
|
if ($toEncoding !== self::UTF8) { |
121
|
|
|
$json = $this->convertEncoding($json, self::UTF8, $toEncoding); |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
return $json; |
125
|
|
|
} |
126
|
|
|
} |
127
|
|
|
|
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.