XmlRpcServer extends HttpResponse : HttpResponse : Development PHP Source Code


PHP Source Code » Development » HttpResponse »

 

XmlRpcServer extends HttpResponse


<?php

XmlRpcServer
::setContentType("text/xml");
XmlRpcServer::capture();

/**
 * XMLRPC Server, very KISS
 * $Id: XmlRpcServer.php,v 1.2 2006/10/10 19:35:01 mike Exp $
 * 
 * NOTE: requires ext/xmlrpc
 * 
 * Usage:
 * <code>
 * <?php
 *     class Handler extends XmlRpcRequestHandlerStub {
 *         public function xmlrpcPing(array $values) {
 *             return true;
 *         }
 *     }
 *     try {
 *         XmlRpcServer::factory("namespace")->registerHandler(new Handler);
 *         XmlRpcServer::run();
 *     } catch (Exception $ex) {
 *         XmlRpcServer::error($ex->getCode(), $ex->getMessage());
 *  }
 * </code>
 * 
 * @copyright   Michael Wallner, <mike@iworks.at>
 * @license     BSD, revised
 * @package     pecl/http
 * @version     $Revision: 1.2 $
 */

class XmlRpcServer extends HttpResponse
{
    
/**
     * Server charset
     *
     * @var string
     */
    
public static $encoding "iso-8859-1";
    
    
/**
     * RPC namespace
     *
     * @var string
     */
    
public $namespace;
    
    
/**
     * RPC handler attached to this server instance
     *
     * @var XmlRpcRequestHandler
     */
    
protected $handler;
    
    private static 
$xmlreq;
    private static 
$xmlrpc;
    private static 
$refcnt 0;
    private static 
$handle = array();
    
    
/**
     * Create a new XmlRpcServer instance
     *
     * @param string $namespace
     * @param string $encoding
     */
    
public function __construct($namespace)
    {
        
$this->namespace $namespace;
        
self::initialize();
    }
    
    
/**
     * Destructor
     */
    
public function __destruct()
    {
        if (
self::$refcnt && !--self::$refcnt) {
            
xmlrpc_server_destroy(self::$xmlrpc);
        }
    }
    
    
/**
     * Static factory
     *
     * @param string $namespace
     * @return XmlRpcServer
     */
    
public static function factory($namespace)
    {
        return new 
XmlRpcServer($namespace);
    }
    
    
/**
     * Run all servers and send response
     *
     * @param array $options
     */
    
public static function run(array $options null)
    {
        
self::initialize(falsetrue);
        
self::setContentType("text/xml; charset="self::$encoding);
        echo 
xmlrpc_server_call_method(self::$xmlrpcself::$xmlreqnull
            array(
"encoding" => self::$encoding) + (array) $options);
    }
    
    
/**
     * Test hook; call instead of XmlRpcServer::run()
     *
     * @param string $method
     * @param array $params
     * @param array $options
     */
    
public static function test($method, array $params, array $options null)
    {
        
self::$xmlreq xmlrpc_encode_request($method$params);
        
self::run();
    }
    
    
/**
     * Optional XMLRPC error handler
     *
     * @param int $code
     * @param string $msg
     */
    
public static function error($code$msg)
    {
        echo 
xmlrpc_encode(array("faultCode" => $code"faultString" => $msg));
    }
    
    
/**
     * Register a single method
     *
     * @param string $name
     * @param mixed $callback
     * @param mixed $dispatch
     * @param array $spec
     */
    
public function registerMethod($name$callback$dispatch null, array $spec null)
    {
        if (!
is_callable($callbackfalse$cb_name)) {
            throw new 
Exception("$cb_name is not a valid callback");
        }
        if (isset(
$dispatch)) {
            if (!
is_callable($dispatchfalse$cb_name)) {
                throw new 
Exception("$cb_name is not a valid callback");
            }
            
xmlrpc_server_register_method(self::$xmlrpc$name$dispatch);
            
self::$handle[$name] = $callback;
        } else {
            
xmlrpc_server_register_method(self::$xmlrpc$name$callback);
        }
        
        if (isset(
$spec)) {
            
xmlrpc_server_add_introspection_data(self::$xmlrpc$spec);
        }
    }
    
    
/**
     * Register an XmlRpcRequestHandler for this server instance
     *
     * @param XmlRpcRequestHandler $handler
     */
    
public function registerHandler(XmlRpcRequestHandler $handler)
    {
        
$this->handler $handler;
        
        foreach (
get_class_methods($handler) as $method) {
            if (!
strncmp($method"xmlrpc"6)) {
                
$this->registerMethod(
                    
$this->method($method$handler->getNamespace()), 
                    array(
$handler$method), array($this"dispatch"));
            }
        }
        
        
$handler->getIntrospectionData($spec);
        if (
is_array($spec)) {
            
xmlrpc_server_add_introspection_data(self::$xmlrpc$spec);
        }
    }
    
    private function 
method($method$namespace null)
    {
        if (!
strlen($namespace)) {
            
$namespace strlen($this->namespace) ? $this->namespace "xmlrpc";
        }
        return 
$namespace ."."strtolower($method[6]) . substr($method7);
    }
    
    private function 
dispatch($method, array $params null)
    {
        if (
array_key_exists($methodself::$handle)) {
            return 
call_user_func(self::$handle[$method], $params);
        }
        throw new 
Exception("Unknown XMLRPC method: $method");
    }
    
    private static function 
initialize($server true$data false)
    {
        if (
$data) {
            if (!
self::$xmlreq && !(self::$xmlreq http_get_request_body())) {
                throw new 
Exception("Failed to fetch XMLRPC request body");
            }
        }
        if (
$server) {
            if (!
self::$xmlrpc && !(self::$xmlrpc xmlrpc_server_create())) {
                throw new 
Exception("Failed to initialize XMLRPC server");
            }
            ++
self::$refcnt;
        }
    }
}

/**
 * XmlRpcRequestHandler
 * 
 * Define XMLRPC methods with an "xmlrpc" prefix, eg:
 * <code>
 *     class IntOp implements XmlRpcRequestHandler {
 *         public function getNamespace() {
 *             return "int";
 *         }
 *         public function getInstrospectionData(array &$spec = null) {
 *         }
 *         // XMLRPC method name: int.sumValues
 *        public function xmlrpcSumValues(array $values) {
 *             return array_sum($values);
 *        }
 *     }
 * </code>
 */
interface XmlRpcRequestHandler
{
    public function 
getNamespace();
    public function 
getIntrospectionData(array &$spec null);
}

/**
 * XmlRpcRequestHandlerStub
 */
abstract class XmlRpcRequestHandlerStub implements XmlRpcRequestHandler
{
    public function 
getNamespace()
    {
    }
    public function 
getIntrospectionData(array &$spec null)
    {
    }
}

?>


HTML code for linking to this page:

Follow Navioo On Twitter

PHP Source Code

 Navioo Development
» HttpResponse