4 * @author Robin J. Rogge <rrogge@bigpoint.net>
5 * @link https://github.com/pradosoft/prado
6 * @copyright 2010 Bigpoint GmbH
7 * @license https://github.com/pradosoft/prado/blob/master/COPYRIGHT
15 * Note: When using setIsNotification(true), *every* following request is also
16 * considered to be a notification until you use setIsNotification(false).
20 * First, you can use the factory:
22 * $_rpcClient = TRpcClient::create('xml', 'http://host/server');
23 * $_result = $_rpcClient->remoteMethodName($param, $otherParam);
28 * $_result = TRpcClient::create('json', 'http://host/server')->remoteMethod($param, ...);
31 * Second, you can also use the specific implementation directly:
33 * $_rpcClient = new TXmlRpcClient('http://host/server');
34 * $_result = $_rpcClient->remoteMethod($param, ...);
39 * $_result = TXmlRpcClient('http://host/server')->hello();
42 * @author Robin J. Rogge <rrogge@bigpoint.net>
44 * @package System.Util
48 class TRpcClient extends TApplicationComponent
51 * @var string url of the RPC server
56 * @var boolean whether the request is a notification and therefore should not care about the result (default: false)
58 private $_isNotification = false;
63 * @param string url to RPC server
64 * @param boolean whether requests are considered to be notifications (completely ignoring the response) (default: false)
66 public function __construct($serverUrl, $isNotification = false)
68 $this->_serverUrl = $serverUrl;
69 $this->_isNotification = TPropertyValue::ensureBoolean($isNotification);
75 * Creates an instance of the requested RPC client type
76 * @return TRpcClient instance
77 * @throws TApplicationException if an unsupported RPC client type was specified
79 public static function create($type, $serverUrl, $isNotification = false)
81 if(($_handler = constant('TRpcClientTypesEnumerable::'.strtoupper($type))) === null)
82 throw new TApplicationException('rpcclient_unsupported_handler');
84 return new $_handler($serverUrl, $isNotification);
88 * Creates a stream context resource
89 * @param mixed $content
90 * @param string $contentType mime type
92 protected function createStreamContext($content, $contentType)
94 return stream_context_create(array(
97 'header' => "Content-Type: {$contentType}",
104 * Performs the actual request
105 * @param string RPC server URL
106 * @param array payload data
107 * @param string request mime type
109 protected function performRequest($serverUrl, $payload, $mimeType)
111 if(($_response = @file_get_contents($serverUrl, false, $this->createStreamContext($payload, $mimeType))) === false)
112 throw new TRpcClientRequestException('Request failed ("'.$http_response_header[0].'")');
120 * @return boolean whether requests are considered to be notifications (completely ignoring the response)
122 public function getIsNotification()
124 return $this->_isNotification;
128 * @param string boolean whether the requests are considered to be notifications (completely ignoring the response) (default: false)
130 public function setIsNotification($bool)
132 $this->_isNotification = TPropertyValue::ensureBoolean($bool);
136 * @return string url of the RPC server
138 public function getServerUrl()
140 return $this->_serverUrl;
144 * @param string url of the RPC server
146 public function setServerUrl($value)
148 $this->_serverUrl = $value;
153 * TRpcClientTypesEnumerable class
155 * @author Robin J. Rogge <rrogge@bigpoint.net>
157 * @package System.Util
161 class TRpcClientTypesEnumerable extends TEnumerable
163 const JSON = 'TJsonRpcClient';
164 const XML = 'TXmlRpcClient';
168 * TRpcClientRequestException class
170 * This Exception is fired if the RPC request fails because of transport problems e.g. when
171 * there is no RPC server responding on the given remote host.
173 * @author Robin J. Rogge <rrogge@bigpoint.net>
175 * @package System.Util
179 class TRpcClientRequestException extends TApplicationException
184 * TRpcClientResponseException class
186 * This Exception is fired when the
188 * @author Robin J. Rogge <rrogge@bigpoint.net>
190 * @package System.Util
194 class TRpcClientResponseException extends TApplicationException
197 * @param string error message
198 * @param integer error code (optional)
200 public function __construct($errorMessage, $errorCode = null)
202 $this->setErrorCode($errorCode);
204 parent::__construct($errorMessage);
209 * TJsonRpcClient class
211 * Note: When using setIsNotification(true), *every* following request is also
212 * considered to be a notification until you use setIsNotification(false).
216 * $_rpcClient = new TJsonRpcClient('http://host/server');
217 * $_result = $_rpcClient->remoteMethod($param, $otherParam);
219 * $_result = TJsonRpcClient::create('http://host/server')->remoteMethod($param, $otherParam);
222 * @author Robin J. Rogge <rrogge@bigpoint.net>
224 * @package System.Util
228 class TJsonRpcClient extends TRpcClient
233 * @param string RPC method name
234 * @param array RPC method parameters
235 * @return mixed RPC request result
236 * @throws TRpcClientRequestException if the client fails to connect to the server
237 * @throws TRpcClientResponseException if the response represents an RPC fault
239 public function __call($method, $parameters)
242 $_response = $this->performRequest($this->getServerUrl(), $this->encodeRequest($method, $parameters), 'application/json');
244 // skip response handling if the request was just a notification request
245 if($this->isNotification)
249 if(($_response = json_decode($_response, true)) === null)
250 throw new TRpcClientResponseException('Empty response received');
252 // handle error response
253 if(!is_null($_response['error']))
254 throw new TRpcClientResponseException($_response['error']);
256 return $_response['result'];
262 * @param string method name
263 * @param array method parameters
265 public function encodeRequest($method, $parameters)
268 $_requestId = ($_requestId === null) ? 1 : $_requestId + 1;
270 return json_encode(array(
272 'params' => $parameters,
273 'id' => $this->isNotification ? null : $_requestId
278 * Creates an instance of TJsonRpcClient
279 * @param string url of the rpc server
280 * @param boolean whether the requests are considered to be notifications (completely ignoring the response) (default: false)
282 public static function create($type, $serverUrl, $isNotification = false)
284 return new self($serverUrl, $isNotification);
289 * TXmlRpcClient class
291 * Note: When using setIsNotification(true), *every* following request is also
292 * considered to be a notification until you use setIsNotification(false).
296 * $_rpcClient = new TXmlRpcClient('http://remotehost/rpcserver');
297 * $_rpcClient->remoteMethod($param, $otherParam);
300 * @author Robin J. Rogge <rrogge@bigpoint.net>
302 * @package System.Util
306 class TXmlRpcClient extends TRpcClient
311 * @param string RPC method name
312 * @param array RPC method parameters
313 * @return mixed RPC request result
314 * @throws TRpcClientRequestException if the client fails to connect to the server
315 * @throws TRpcClientResponseException if the response represents an RPC fault
317 public function __call($method, $parameters)
320 $_response = $this->performRequest($this->getServerUrl(), $this->encodeRequest($method, $parameters), 'text/xml');
322 // skip response handling if the request was just a notification request
323 if($this->isNotification)
327 if(($_response = xmlrpc_decode($_response)) === null)
328 throw new TRpcClientResponseException('Empty response received');
330 // handle error response
331 if(xmlrpc_is_fault($_response))
332 throw new TRpcClientResponseException($_response['faultString'], $_response['faultCode']);
340 * @param string method name
341 * @param array method parameters
343 public function encodeRequest($method, $parameters)
345 return xmlrpc_encode_request($method, $parameters);
349 * Creates an instance of TXmlRpcClient
350 * @param string url of the rpc server
351 * @param boolean whether the requests are considered to be notifications (completely ignoring the response) (default: false)
353 public static function create($type, $serverUrl, $isNotification = false)
355 return new self($serverUrl, $isNotification);