1
|
|
|
<?php |
2
|
|
|
namespace Crossjoin\Json; |
3
|
|
|
|
4
|
|
|
use Crossjoin\Json\Exception\ConversionFailedException; |
5
|
|
|
use Crossjoin\Json\Exception\ExtensionRequiredException; |
6
|
|
|
use Crossjoin\Json\Exception\InvalidArgumentException; |
7
|
|
|
use Crossjoin\Json\Exception\NativeJsonErrorException; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* Class Converter |
11
|
|
|
* |
12
|
|
|
* @package Crossjoin\Json |
13
|
|
|
* @author Christoph Ziegenberg <[email protected]> |
14
|
|
|
*/ |
15
|
|
|
abstract class Converter |
16
|
|
|
{ |
17
|
|
|
const UTF8 = 'UTF-8'; |
18
|
|
|
const UTF16BE = 'UTF-16BE'; |
19
|
|
|
const UTF16LE = 'UTF-16LE'; |
20
|
|
|
const UTF32BE = 'UTF-32BE'; |
21
|
|
|
const UTF32LE = 'UTF-32LE'; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* @param string $string |
25
|
|
|
* @param string $fromEncoding |
26
|
|
|
* @param string $toEncoding |
27
|
|
|
* |
28
|
|
|
* @return string |
29
|
|
|
* @throws \Crossjoin\Json\Exception\InvalidArgumentException |
30
|
|
|
* @throws \Crossjoin\Json\Exception\ConversionFailedException |
31
|
|
|
* @throws \Crossjoin\Json\Exception\ExtensionRequiredException |
32
|
|
|
*/ |
33
|
|
|
public function convertEncoding($string, $fromEncoding, $toEncoding) |
34
|
|
|
{ |
35
|
|
|
// Check arguments |
36
|
|
|
if (!is_string($string)) { |
37
|
|
|
throw new InvalidArgumentException( |
38
|
|
|
sprintf("String expected for argument '%s'. Got '%s'.", 'json', gettype($string)), |
39
|
|
|
1478195990 |
40
|
|
|
); |
41
|
|
|
} |
42
|
|
|
if (!is_string($fromEncoding)) { |
43
|
|
|
throw new InvalidArgumentException( |
44
|
|
|
sprintf("String expected for argument '%s'. Got '%s'.", 'fromEncoding', gettype($fromEncoding)), |
45
|
|
|
1478195991 |
46
|
|
|
); |
47
|
|
|
} |
48
|
|
|
if (!is_string($toEncoding)) { |
49
|
|
|
throw new InvalidArgumentException( |
50
|
|
|
sprintf("String expected for argument '%s'. Got '%s'.", 'toEncoding', gettype($toEncoding)), |
51
|
|
|
1478195992 |
52
|
|
|
); |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
// Try different conversion functions, ordered by speed |
56
|
|
|
// @codeCoverageIgnoreStart |
57
|
|
|
if (function_exists('iconv')) { |
58
|
|
|
$string = iconv($fromEncoding, $toEncoding . '//IGNORE', $string); |
59
|
|
|
if ($string === false) { |
60
|
|
|
throw new ConversionFailedException('Error while converting the encoding.', 1478193725); |
61
|
|
|
} |
62
|
|
|
} elseif (class_exists('\\UConverter')) { |
63
|
|
|
/** @noinspection PhpUndefinedClassInspection */ |
64
|
|
|
$uConverter = new \UConverter($toEncoding, $fromEncoding); |
65
|
|
|
/** @noinspection PhpUndefinedMethodInspection */ |
66
|
|
|
$string = $uConverter->convert($string); |
67
|
|
|
} elseif (function_exists('mb_convert_encoding')) { |
68
|
|
|
$string = mb_convert_encoding($string, $toEncoding, $fromEncoding); |
69
|
|
|
} else { |
70
|
|
|
throw new ExtensionRequiredException( |
71
|
|
|
"The 'iconv', 'intl' or the 'Multibyte String' extension is required to convert the JSON encoding.", |
72
|
|
|
1478095252 |
73
|
|
|
); |
74
|
|
|
} |
75
|
|
|
// @codeCoverageIgnoreEnd |
76
|
|
|
|
77
|
|
|
return $string; |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* Removes the byte order mark (BOM) from the JSON text. This is not allowed in JSON, |
82
|
|
|
* but may be ignored when parsing it. |
83
|
|
|
* |
84
|
|
|
* @param string $string |
85
|
|
|
* |
86
|
|
|
* @return string |
87
|
|
|
* @throws \Crossjoin\Json\Exception\InvalidArgumentException |
88
|
|
|
*/ |
89
|
|
|
public function removeByteOrderMark($string) |
90
|
|
|
{ |
91
|
|
|
// Check arguments |
92
|
|
View Code Duplication |
if (!is_string($string)) { |
|
|
|
|
93
|
|
|
throw new InvalidArgumentException( |
94
|
|
|
sprintf("String expected for argument '%s'. Got '%s'.", 'string', gettype($string)), |
95
|
|
|
1478195910 |
96
|
|
|
); |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
return (string)preg_replace( |
100
|
|
|
'/^(?:' . |
101
|
|
|
'\xEF\xBB\xBF|' . // UTF-8 BOM |
102
|
|
|
'\x00\x00\xFE\xFF|' . // UTF-32BE BOM |
103
|
|
|
'\xFF\xFE\x00\x00|' . // UTF-32LE BOM (before UTF-16LE check!) |
104
|
|
|
'\xFE\xFF|' . // UTF-16BE BOM |
105
|
|
|
'\xFF\xFE' . // UTF-16LE BOM |
106
|
|
|
')/', |
107
|
|
|
'', |
108
|
|
|
$string |
109
|
|
|
); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* @return NativeJsonErrorException |
114
|
|
|
*/ |
115
|
|
|
protected function getNativeJsonErrorException() |
116
|
|
|
{ |
117
|
|
|
if (function_exists('\json_last_error_msg')) { |
118
|
|
|
return new NativeJsonErrorException(\json_last_error_msg(), \json_last_error()); |
119
|
|
|
} else { |
120
|
|
|
return new NativeJsonErrorException('An error occurred while encoding/decoding JSON.', \json_last_error()); |
121
|
|
|
} |
122
|
|
|
} |
123
|
|
|
} |
124
|
|
|
|
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.