3 XmlRpcServer
::setContentType("text/xml");
4 XmlRpcServer
::capture();
7 * XMLRPC Server, very KISS
10 * NOTE: requires ext/xmlrpc
15 * class Handler extends XmlRpcRequestHandlerStub {
16 * public function xmlrpcPing(array $values) {
21 * XmlRpcServer::factory("namespace")->registerHandler(new Handler);
22 * XmlRpcServer::run();
23 * } catch (Exception $ex) {
24 * XmlRpcServer::error($ex->getCode(), $ex->getMessage());
28 * @copyright Michael Wallner, <mike@iworks.at>
29 * @license BSD, revised
34 class XmlRpcServer
extends HttpResponse
41 public static $encoding = "iso-8859-1";
51 * RPC handler attached to this server instance
53 * @var XmlRpcRequestHandler
57 private static $xmlreq;
58 private static $xmlrpc;
59 private static $refcnt = 0;
60 private static $handle = array();
63 * Create a new XmlRpcServer instance
65 * @param string $namespace
66 * @param string $encoding
68 public function __construct($namespace)
70 $this->namespace = $namespace;
77 public function __destruct()
79 if (self
::$refcnt && !--self
::$refcnt) {
80 xmlrpc_server_destroy(self
::$xmlrpc);
87 * @param string $namespace
88 * @return XmlRpcServer
90 public static function factory($namespace)
92 return new XmlRpcServer($namespace);
96 * Run all servers and send response
98 * @param array $options
100 public static function run(array $options = null)
102 self
::initialize(false, true);
103 self
::setContentType("text/xml; charset=". self
::$encoding);
104 echo xmlrpc_server_call_method(self
::$xmlrpc, self
::$xmlreq, null,
105 array("encoding" => self
::$encoding) +
(array) $options);
109 * Test hook; call instead of XmlRpcServer::run()
111 * @param string $method
112 * @param array $params
113 * @param array $options
115 public static function test($method, array $params, array $options = null)
117 self
::$xmlreq = xmlrpc_encode_request($method, $params);
122 * Optional XMLRPC error handler
127 public static function error($code, $msg)
129 echo xmlrpc_encode(array("faultCode" => $code, "faultString" => $msg));
133 * Register a single method
135 * @param string $name
136 * @param mixed $callback
137 * @param mixed $dispatch
140 public function registerMethod($name, $callback, $dispatch = null, array $spec = null)
142 if (!is_callable($callback, false, $cb_name)) {
143 throw new Exception("$cb_name is not a valid callback");
145 if (isset($dispatch)) {
146 if (!is_callable($dispatch, false, $cb_name)) {
147 throw new Exception("$cb_name is not a valid callback");
149 xmlrpc_server_register_method(self
::$xmlrpc, $name, $dispatch);
150 self
::$handle[$name] = $callback;
152 xmlrpc_server_register_method(self
::$xmlrpc, $name, $callback);
156 xmlrpc_server_add_introspection_data(self
::$xmlrpc, $spec);
161 * Register an XmlRpcRequestHandler for this server instance
163 * @param XmlRpcRequestHandler $handler
165 public function registerHandler(XmlRpcRequestHandler
$handler)
167 $this->handler
= $handler;
169 foreach (get_class_methods($handler) as $method) {
170 if (!strncmp($method, "xmlrpc", 6)) {
171 $this->registerMethod(
172 $this->method($method, $handler->getNamespace()),
173 array($handler, $method), array($this, "dispatch"));
177 $handler->getIntrospectionData($spec);
178 if (is_array($spec)) {
179 xmlrpc_server_add_introspection_data(self
::$xmlrpc, $spec);
183 private function method($method, $namespace = null)
185 if (!strlen($namespace)) {
186 $namespace = strlen($this->namespace) ?
$this->namespace : "xmlrpc";
188 return $namespace .".". strtolower($method[6]) . substr($method, 7);
191 private function dispatch($method, array $params = null)
193 if (array_key_exists($method, self
::$handle)) {
194 return call_user_func(self
::$handle[$method], $params);
196 throw new Exception("Unknown XMLRPC method: $method");
199 private static function initialize($server = true, $data = false)
202 if (!self
::$xmlreq && !(self
::$xmlreq = http_get_request_body())) {
203 throw new Exception("Failed to fetch XMLRPC request body");
207 if (!self
::$xmlrpc && !(self
::$xmlrpc = xmlrpc_server_create())) {
208 throw new Exception("Failed to initialize XMLRPC server");
216 * XmlRpcRequestHandler
218 * Define XMLRPC methods with an "xmlrpc" prefix, eg:
220 * class IntOp implements XmlRpcRequestHandler {
221 * public function getNamespace() {
224 * public function getInstrospectionData(array &$spec = null) {
226 * // XMLRPC method name: int.sumValues
227 * public function xmlrpcSumValues(array $values) {
228 * return array_sum($values);
233 interface XmlRpcRequestHandler
235 public function getNamespace();
236 public function getIntrospectionData(array &$spec = null);
240 * XmlRpcRequestHandlerStub
242 abstract class XmlRpcRequestHandlerStub
implements XmlRpcRequestHandler
244 public function getNamespace()
247 public function getIntrospectionData(array &$spec = null)