Skip to content

Commit ad4d735

Browse files
committed
6.1.0
1 parent a7e331a commit ad4d735

File tree

3 files changed

+122
-45
lines changed

3 files changed

+122
-45
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
66
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
77

8+
## [6.1.0] - 2020-02-28
9+
### Added
10+
- The "Client::preEncode" and "Client::postDecode" methods have been added to allow
11+
advanced users to inspect and tweak the inner workings of the JSON-RPC library.
12+
- The "Server::rawReply" method has been added to complement the new "Client" methods.
13+
814
## [6.0.0] - 2019-07-25
915
### Changed
1016
- There are now two types of responses--an "ErrorResponse" and a "ResultResponse"--

src/Client.php

Lines changed: 74 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -90,37 +90,65 @@ public function notify($method, array $arguments = null): self
9090
}
9191

9292
/**
93-
* Encodes the requests as a valid JSON-RPC 2.0 string
93+
* Encodes the request(s) as a valid JSON-RPC 2.0 string
9494
*
95-
* This also resets the Client, so you can perform more queries using
96-
* the same Client object.
95+
* This also resets the Client, so you can use the same Client object
96+
* to perform more queries.
9797
*
98-
* @return null|string
98+
* @return string|null
9999
* Returns a valid JSON-RPC 2.0 message string
100100
* Returns null if there is nothing to encode
101101
*/
102102
public function encode()
103103
{
104-
$count = count($this->requests);
104+
$input = $this->preEncode();
105105

106-
if ($count === 0) {
106+
if ($input === null) {
107107
return null;
108108
}
109109

110-
if ($count === 1) {
111-
$input = array_shift($this->requests);
110+
return json_encode($input);
111+
}
112+
113+
/**
114+
* Encodes the request(s) as a JSON-RPC 2.0 array, but does NOT perform
115+
* the final "json_encode" step which is necessary to turn the array
116+
* into a valid JSON-RPC 2.0 string. This gives you the opportunity
117+
* to inspect or modify the raw data, or to alter the encoding algorithm.
118+
*
119+
* When you're finished manipulating the request, you are responsible for
120+
* JSON-encoding the value to construct the final JSON-RPC 2.0 string.
121+
* @see self::encode()
122+
*
123+
* This also resets the Client, so you can use the same Client object
124+
* to perform more queries.
125+
*
126+
* @return array|null
127+
* Returns a JSON-RPC 2.0 request array
128+
* Returns null if no requests have been queued
129+
*/
130+
public function preEncode()
131+
{
132+
$n = count($this->requests);
133+
134+
if ($n === 0) {
135+
return null;
136+
}
137+
138+
if ($n === 1) {
139+
$input = $this->requests[0];
112140
} else {
113141
$input = $this->requests;
114142
}
115143

116144
$this->reset();
117145

118-
return json_encode($input);
146+
return $input;
119147
}
120148

121149
/**
122150
* Translates a JSON-RPC 2.0 server reply into an array of "Response"
123-
* objects
151+
* objects.
124152
*
125153
* @param string $json
126154
* String reply from a JSON-RPC 2.0 server
@@ -133,21 +161,48 @@ public function encode()
133161
*/
134162
public function decode(string $json)
135163
{
136-
set_error_handler(__CLASS__ . '::onError');
164+
$input = json_decode($json, true);
137165

138-
try {
139-
$input = json_decode($json, true);
140-
} finally {
141-
restore_error_handler();
142-
}
166+
$errorCode = json_last_error();
167+
168+
if ($errorCode !== 0) {
169+
$errorMessage = json_last_error_msg();
170+
$jsonException = new ErrorException($errorMessage, $errorCode);
143171

144-
if (($input === null) && (strtolower(trim($json)) !== 'null')) {
145172
$valueText = self::getValueText($json);
146-
throw new ErrorException("Invalid JSON: {$valueText}");
173+
throw new ErrorException("Invalid JSON: {$valueText}", 0, E_ERROR, __FILE__, __LINE__, $jsonException);
147174
}
148175

176+
return $this->postDecode($input);
177+
}
178+
179+
/**
180+
* Translates a JSON-decoded server reply into an array of "Response"
181+
* objects.
182+
*
183+
* This gives you the opportunity to use your own modified "json_decode"
184+
* algorithm, or to inspect or modify the server response before it is
185+
* processed under the JSON-RPC 2.0 specifications. This can be handy
186+
* if you're tweaking or extending the JSON-RPC 2.0 format.
187+
*
188+
* Before calling this method, you are responsible for JSON-decoding
189+
* the server reply string. You should have that decoded array value
190+
* to use as the input here.
191+
* @see self::decode()
192+
*
193+
* @param mixed $input
194+
* An array containing the JSON-decoded server reply
195+
*
196+
* @return Response[]
197+
* Returns a zero-indexed array of "Response" objects
198+
*
199+
* @throws ErrorException
200+
* Throws an "ErrorException" if the reply was not well-formed
201+
*/
202+
public function postDecode($input)
203+
{
149204
if (!$this->getResponses($input, $responses)) {
150-
$valueText = self::getValueText($json);
205+
$valueText = self::getValueText($input);
151206
throw new ErrorException("Invalid JSON-RPC 2.0 response: {$valueText}");
152207
}
153208

@@ -308,12 +363,4 @@ private function getBatchResponses($input, &$responses)
308363

309364
return true;
310365
}
311-
312-
public static function onError($level, $message, $file, $line)
313-
{
314-
$message = trim($message);
315-
$code = 0;
316-
317-
throw new ErrorException($message, $code, $level, $file, $line);
318-
}
319366
}

src/Server.php

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -47,40 +47,64 @@ public function __construct(Evaluator $evaluator)
4747
}
4848

4949
/**
50-
* Processes the user input, and prepares a response (if necessary).
50+
* Processes a JSON-RPC 2.0 client request string and prepares a valid
51+
* response.
5152
*
5253
* @param string $json
5354
* Single request object, or an array of request objects, as a JSON string.
5455
*
55-
* @return string|null
56-
* Returns a response object (or an error object) as a JSON string, when a query is made.
57-
* Returns an array of response/error objects as a JSON string, when multiple queries are made.
58-
* Returns null, when no response is necessary.
56+
* @return null|string
57+
* Returns null when no response is necessary.
58+
* Returns a response/error object, as a JSON string, when a query is made.
59+
* Returns an array of response/error objects, as a JSON string, when multiple queries are made.
60+
* @see Responses\ResultResponse
61+
* @see Responses\ErrorResponse
5962
*/
6063
public function reply($json)
6164
{
62-
if ($this->getInput($json, $input)) {
63-
$output = $this->processInput($input);
65+
if (is_string($json)) {
66+
$input = json_decode($json, true);
6467
} else {
65-
$output = $this->parseError();
68+
$input = null;
6669
}
6770

68-
if ($output === null) {
69-
return null;
71+
$reply = $this->rawReply($input);
72+
73+
if (is_array($reply)) {
74+
$output = json_encode($reply);
75+
} else {
76+
$output = null;
7077
}
7178

72-
return json_encode($output);
79+
return $output;
7380
}
7481

75-
private function getInput($json, &$input)
82+
/**
83+
* Processes a JSON-RPC 2.0 client request array and prepares a valid
84+
* response. This method skips the JSON encoding and decoding steps,
85+
* so you can use your own alternative encoding algorithm, or extend
86+
* the JSON-RPC 2.0 format.
87+
*
88+
* When you use this method, you are taking responsibility for
89+
* performing the necessary JSON encoding and decoding steps yourself.
90+
* @see self::reply()
91+
*
92+
* @param mixed $input
93+
* An array containing the JSON-decoded client request.
94+
*
95+
* @return null|array
96+
* Returns null if no reply is necessary
97+
* Returns the JSON-RPC 2.0 server reply as an array
98+
*/
99+
public function rawReply($input)
76100
{
77-
if (!is_string($json)) {
78-
return false;
101+
if (is_array($input)) {
102+
$reply = $this->processInput($input);
103+
} else {
104+
$reply = $this->parseError();
79105
}
80106

81-
$input = json_decode($json, true);
82-
83-
return is_array($input);
107+
return $reply;
84108
}
85109

86110
/**
@@ -94,7 +118,7 @@ private function getInput($json, &$input)
94118
* Returns an array of response/error objects when multiple queries are made.
95119
* Returns null when no response is necessary.
96120
*/
97-
private function processInput($input)
121+
private function processInput(array $input)
98122
{
99123
if (count($input) === 0) {
100124
return $this->requestError();

0 commit comments

Comments
 (0)