Passed
Push — master ( c0a3a7...3b84a4 )
by Jeroen
58:51
created

EmptyKeyEncoding::decode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 4
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
ccs 3
cts 3
cp 1
crap 1
1
<?php
2
namespace Elgg\Json;
3
4
/**
5
 * Encode and decode JSON while converting empty string keys to a unique token.
6
 *
7
 * This gets around PHP's limitation of not allowing empty string object property names.
8
 * https://bugs.php.net/bug.php?id=46600
9
 *
10
 * @package    Elgg.Core
11
 * @subpackage Json
12
 * @access     private
13
 */
14
class EmptyKeyEncoding {
15
16
	/**
17
	 * @var string
18
	 */
19
	protected $token;
20
21
	/**
22
	 * Constructor
23
	 *
24
	 * @param string $empty_key Optional key to replace "" keys with in JSON decode
25
	 */
26 2
	public function __construct($empty_key = '') {
27 2
		if (!$empty_key) {
28 1
			$empty_key = sha1(microtime(true) . mt_rand());
0 ignored issues
show
Bug introduced by Steve Clay
The call to mt_rand() has too few arguments starting with min. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

28
			$empty_key = sha1(microtime(true) . /** @scrutinizer ignore-call */ mt_rand());

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
29
		}
30 2
		$this->token = $empty_key;
31 2
	}
32
33
	/**
34
	 * Get the key that represents an empty string key in JSON
35
	 *
36
	 * @return string
37
	 */
38 1
	public function getEmptyKey() {
39 1
		return $this->token;
40
	}
41
42
	/**
43
	 * Decode JSON while converting empty keys to a unique token.
44
	 *
45
	 * @param string $json    JSON string
46
	 * @param bool   $assoc   Convert objects to assoc arrays?
47
	 * @param int    $depth   Allowed recursion depth
48
	 * @param int    $options Bitmask json_decode options
49
	 *
50
	 * @return mixed
51
	 * @see json_decode
52
	 */
53 1
	public function decode($json, $assoc = false, $depth = 512, $options = 0) {
54
		// Replace empty keys with the unique token
55 1
		$json = preg_replace('~([^"\\\\])""\\s*\\:~', "$1\"{$this->token}\":", $json, -1, $count);
1 ignored issue
show
Comprehensibility Best Practice introduced by Steve Clay
The variable $1 seems to be never defined.
Loading history...
56
57 1
		return json_decode($json, $assoc, $depth, $options);
58
	}
59
60
	/**
61
	 * Encode JSON while converting unique token keys to empty strings
62
	 *
63
	 * @param mixed $value   Value to encode
64
	 * @param int   $options Encoding options
65
	 * @param int   $depth   Allowed recursion depth. Do not set this before PHP 5.5
66
	 *
67
	 * @return string|false
68
	 */
69 2
	public function encode($value, $options = 0, $depth = 512) {
70 2
		if ($depth == 512) {
71
			// PHP 5.4 and earlier will choke if depth is passed in
72 2
			$json = json_encode($value, $options);
73
		} else {
74
			$json = json_encode($value, $options, $depth);
75
		}
76
77
		// Replace unique tokens with empty strings
78 2
		if (is_string($json)) {
79 2
			$json = str_replace("\"{$this->token}\"", '""', $json);
80
		}
81
82 2
		return $json;
83
	}
84
}
85