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) {
69 $this->namespace = $namespace;
76 public function __destruct() {
77 if (self
::$refcnt && !--self
::$refcnt) {
78 xmlrpc_server_destroy(self
::$xmlrpc);
85 * @param string $namespace
86 * @return XmlRpcServer
88 public static function factory($namespace) {
89 return new XmlRpcServer($namespace);
93 * Run all servers and send response
95 * @param array $options
97 public static function run(array $options = null) {
98 self
::initialize(false, true);
99 HttpResponse
::setContentType("text/xml; charset=". self
::$encoding);
100 echo xmlrpc_server_call_method(self
::$xmlrpc, self
::$xmlreq, null,
101 array("encoding" => self
::$encoding) +
(array) $options);
105 * Test hook; call instead of XmlRpcServer::run()
107 * @param string $method
108 * @param array $params
109 * @param array $options
111 public static function test($method, array $params, array $options = null) {
112 self
::$xmlreq = xmlrpc_encode_request($method, $params);
117 * Optional XMLRPC error handler
122 public static function error($code, $msg) {
123 echo xmlrpc_encode(array("faultCode" => $code, "faultString" => $msg));
127 * Register a single method
129 * @param string $name
130 * @param mixed $callback
131 * @param mixed $dispatch
134 public function registerMethod($name, $callback, $dispatch = null, array $spec = null) {
135 if (!is_callable($callback, false, $cb_name)) {
136 throw new Exception("$cb_name is not a valid callback");
138 if (isset($dispatch)) {
139 if (!is_callable($dispatch, false, $cb_name)) {
140 throw new Exception("$cb_name is not a valid callback");
142 xmlrpc_server_register_method(self
::$xmlrpc, $name, $dispatch);
143 self
::$handle[$name] = $callback;
145 xmlrpc_server_register_method(self
::$xmlrpc, $name, $callback);
149 xmlrpc_server_add_introspection_data(self
::$xmlrpc, $spec);
154 * Register an XmlRpcRequestHandler for this server instance
156 * @param XmlRpcRequestHandler $handler
158 public function registerHandler(XmlRpcRequestHandler
$handler) {
159 $this->handler
= $handler;
161 foreach (get_class_methods($handler) as $method) {
162 if (!strncmp($method, "xmlrpc", 6)) {
163 $this->registerMethod(
164 $this->method($method, $handler->getNamespace()),
165 array($handler, $method), array($this, "dispatch"));
169 $handler->getIntrospectionData($spec);
170 if (is_array($spec)) {
171 xmlrpc_server_add_introspection_data(self
::$xmlrpc, $spec);
175 private function method($method, $namespace = null) {
176 if (!strlen($namespace)) {
177 $namespace = strlen($this->namespace) ?
$this->namespace : "xmlrpc";
179 return $namespace .".". strtolower($method[6]) . substr($method, 7);
182 private function dispatch($method, array $params = null) {
183 if (array_key_exists($method, self
::$handle)) {
184 return call_user_func(self
::$handle[$method], $params);
186 throw new Exception("Unknown XMLRPC method: $method");
189 private static function initialize($server = true, $data = false) {
191 if (!self
::$xmlreq && !(self
::$xmlreq = http_get_request_body())) {
192 throw new Exception("Failed to fetch XMLRPC request body");
196 if (!self
::$xmlrpc && !(self
::$xmlrpc = xmlrpc_server_create())) {
197 throw new Exception("Failed to initialize XMLRPC server");
205 * XmlRpcRequestHandler
207 * Define XMLRPC methods with an "xmlrpc" prefix, eg:
209 * class IntOp implements XmlRpcRequestHandler {
210 * public function getNamespace() {
213 * public function getInstrospectionData(array &$spec = null) {
215 * // XMLRPC method name: int.sumValues
216 * public function xmlrpcSumValues(array $values) {
217 * return array_sum($values);
222 interface XmlRpcRequestHandler
{
223 public function getNamespace();
224 public function getIntrospectionData(array &$spec = null);
228 * XmlRpcRequestHandlerStub
230 abstract class XmlRpcRequestHandlerStub
implements XmlRpcRequestHandler
{
231 public function getNamespace() {
233 public function getIntrospectionData(array &$spec = null) {