1
1
<?php
2
2
namespace YOCLIB \JSONRPC ;
3
3
4
- class Message{
4
+ use JsonException ;
5
+
6
+ abstract class Message{
7
+
8
+ private object $ value ;
9
+
10
+ /**
11
+ * @param object $value
12
+ */
13
+ private function __construct (object $ value ){
14
+ $ this ->value = $ value ;
15
+ }
16
+
17
+ /**
18
+ * @return string
19
+ */
20
+ public function toJSON (): string {
21
+ return json_encode ($ this ->value );
22
+ }
23
+
24
+ /**
25
+ * @param $id
26
+ * @param string $method
27
+ * @param array $params
28
+ * @return RequestMessage
29
+ */
30
+ public static function createRequestMessageV1 ($ id ,string $ method ,array $ params =[]): RequestMessage {
31
+ return new RequestMessage ((object ) [
32
+ 'id ' => $ id ,
33
+ 'method ' => $ method ,
34
+ 'params ' => $ params ,
35
+ ]);
36
+ }
37
+
38
+ /**
39
+ * @param $id
40
+ * @param string $method
41
+ * @param array $params
42
+ * @return NotificationMessage
43
+ */
44
+ public static function createNotificationMessageV1 (string $ method ,array $ params =[]): NotificationMessage {
45
+ return new NotificationMessage ((object ) [
46
+ 'id ' => null ,
47
+ 'method ' => $ method ,
48
+ 'params ' => $ params ,
49
+ ]);
50
+ }
51
+
52
+ /**
53
+ * @param $id
54
+ * @param $result
55
+ * @param object|string|null $error
56
+ * @return RequestMessage
57
+ * @throws JSONRPCException
58
+ */
59
+ public static function createResponseMessageV1 ($ id ,$ result =null ,$ error =null ): RequestMessage {
60
+ if (!is_null ($ result ) && !is_null ($ error )){
61
+ throw new JSONRPCException ('[V1] Only one property "result" or "error" can be non null. ' );
62
+ }
63
+ if (!is_object ($ error ) && !is_string ($ error ) && !is_null ($ error )){
64
+ throw new JSONRPCException ('[V1] The "error" property in request MUST be an string, object or null. ' );
65
+ }
66
+ return new RequestMessage ((object ) [
67
+ 'id ' => $ id ,
68
+ 'result ' => $ result ,
69
+ 'error ' => $ error ,
70
+ ]);
71
+ }
72
+
73
+ /**
74
+ * @param string $json
75
+ * @param bool $strictId
76
+ * @return Message[]|array|Message
77
+ * @throws JSONRPCException
78
+ */
79
+ public static function parse (string $ json ,bool $ strictId =true ){
80
+ try {
81
+ $ message = json_decode ($ json ,false ,512 ,JSON_THROW_ON_ERROR );
82
+ }catch (JsonException $ e ){
83
+ throw new JSONRPCException ('[V1] Failed to decode JSON. ' );
84
+ }
85
+ if (is_array ($ message )){
86
+ $ messages = [];
87
+ foreach ($ message AS $ msg ){
88
+ $ messages [] = self ::handleMessage ($ msg ,$ strictId );
89
+ }
90
+ return $ messages ;
91
+ }
92
+ return self ::handleMessage ($ message ,$ strictId );
93
+ }
94
+
95
+ /**
96
+ * @param $message
97
+ * @param bool $strictId
98
+ * @return Message
99
+ * @throws JSONRPCException
100
+ */
101
+ private static function handleMessage ($ message ,bool $ strictId =true ){
102
+ if (isset ($ message ['jsonrpc ' ]) && $ message ['jsonrpc ' ]==='2.0 ' ){
103
+ return self ::handleMessageV2 ($ message ,$ strictId );
104
+ }else {
105
+ return self ::handleMessageV1 ($ message ,$ strictId );
106
+ }
107
+ }
108
+
109
+ private static function handleMessageV2 ($ message ,bool $ strictId =true ){
110
+ return null ;
111
+ }
112
+
113
+
114
+ private static function isRequestV1 ($ message ): bool {
115
+ return property_exists ($ message ,'method ' ) || property_exists ($ message ,'params ' );
116
+ }
117
+
118
+ private static function isResponseV1 ($ message ): bool {
119
+ return property_exists ($ message ,'result ' ) || property_exists ($ message ,'error ' );
120
+ }
121
+
122
+ /**
123
+ * @param object $message
124
+ * @return void
125
+ * @throws JSONRPCException
126
+ */
127
+ private static function validateMethodPropertyV1 (object $ message ){
128
+ if (!property_exists ($ message ,'method ' )){
129
+ throw new JSONRPCException ('[V1] Missing "method" property in request. ' );
130
+ }
131
+ if (!is_string ($ message ->method )){
132
+ throw new JSONRPCException ('[V1] The "method" property in request MUST be a string. ' );
133
+ }
134
+ }
135
+
136
+ /**
137
+ * @param $message
138
+ * @return void
139
+ * @throws JSONRPCException
140
+ */
141
+ private static function validateParamsPropertyV1 ($ message ){
142
+ if (!property_exists ($ message ,'params ' )){
143
+ throw new JSONRPCException ('[V1] Missing "params" property in request. ' );
144
+ }
145
+ if (!is_array ($ message ['params ' ])){
146
+ throw new JSONRPCException ('[V1] The "params" property in request MUST be an array. ' );
147
+ }
148
+ }
149
+
150
+ /**
151
+ * @param $message
152
+ * @return void
153
+ * @throws JSONRPCException
154
+ */
155
+ private static function validateResultPropertyV1 ($ message ){
156
+ if (!property_exists ($ message ,'result ' )){
157
+ throw new JSONRPCException ('[V1] Missing "result" property in request. ' );
158
+ }
159
+ }
160
+
161
+ /**
162
+ * @param $message
163
+ * @return void
164
+ * @throws JSONRPCException
165
+ */
166
+ private static function validateErrorPropertyV1 ($ message ){
167
+ if (!property_exists ($ message ,'error ' )){
168
+ throw new JSONRPCException ('[V1] Missing "error" property in request. ' );
169
+ }
170
+ if (!is_object ($ message ->error ) && !is_string ($ message ->error ) && !is_null ($ message ->error )){
171
+ throw new JSONRPCException ('[V1] The "error" property in request MUST be an string, object or null. ' );
172
+ }
173
+ }
174
+
175
+ /**
176
+ * @param $message
177
+ * @param bool $strictId
178
+ * @return Message
179
+ * @throws JSONRPCException
180
+ */
181
+ private static function handleMessageV1 ($ message ,bool $ strictId =true ){
182
+ if (self ::isRequestV1 ($ message )){
183
+ self ::validateMethodPropertyV1 ($ message );
184
+ self ::validateParamsPropertyV1 ($ message );
185
+
186
+ if (property_exists ($ message ,'id ' ) && $ strictId ?($ message ->id !==null ):($ message ->id )){
187
+ return new RequestMessage ($ message );
188
+ }else {
189
+ return new NotificationMessage ($ message );
190
+ }
191
+ }elseif (self ::isResponseV1 ($ message )){
192
+ self ::validateResultPropertyV1 ($ message );
193
+ self ::validateErrorPropertyV1 ($ message );
194
+ if (!is_null ($ message ->result ) && !is_null ($ message ->error )){
195
+ throw new JSONRPCException ('[V1] Only one property "result" or "error" can be non null. ' );
196
+ }
197
+
198
+ if (property_exists ($ message ,'id ' )){
199
+ return new ResponseMessage ($ message );
200
+ }else {
201
+ throw new JSONRPCException ('[V1] Missing "id" property in response. ' );
202
+ }
203
+ }else {
204
+ throw new JSONRPCException ('[V1] Unknown message type. ' );
205
+ }
206
+ }
5
207
6
208
}
0 commit comments