Move api docs to phpdoc (wip); fix wrong property name in Response class
[plcapi.git] / src / Server.php
index d8e591d..b098d68 100644 (file)
@@ -11,12 +11,14 @@ class Server
      * Array defining php functions exposed as xmlrpc methods by this server.
      */
     protected $dmap = array();
+
     /**
      * Defines how functions in dmap will be invoked: either using an xmlrpc request object
      * or plain php values.
      * Valid strings are 'xmlrpcvals', 'phpvals' or 'epivals'
      */
     public $functions_parameters_type = 'xmlrpcvals';
+
     /**
      * Option used for fine-tuning the encoding the php values returned from
      * functions registered in the dispatch map when the functions_parameters_types
@@ -24,11 +26,13 @@ class Server
      * @see Encoder::encode for a list of values
      */
     public $phpvals_encoding_options = array('auto_dates');
+
     /**
      * Controls whether the server is going to echo debugging messages back to the client as comments in response body.
      * Valid values: 0,1,2,3
      */
     public $debug = 1;
+
     /**
      * Controls behaviour of server when the invoked user function throws an exception:
      * 0 = catch it and return an 'internal error' xmlrpc response (default)
@@ -36,26 +40,32 @@ class Server
      * 2 = allow the exception to float to the upper layers
      */
     public $exception_handling = 0;
+
     /**
      * When set to true, it will enable HTTP compression of the response, in case
      * the client has declared its support for compression in the request.
      * Set at constructor time.
      */
     public $compress_response = false;
+
     /**
      * List of http compression methods accepted by the server for requests. Set at constructor time.
      * NB: PHP supports deflate, gzip compressions out of the box if compiled w. zlib
      */
     public $accepted_compression = array();
-    /// shall we serve calls to system.* methods?
+
+    /// Shall we serve calls to system.* methods?
     public $allow_system_funcs = true;
+
     /**
      * List of charset encodings natively accepted for requests.
-     *  Set at constructor time.
+     * Set at constructor time.
+     * UNUSED so far...
      */
     public $accepted_charset_encodings = array();
+
     /**
-     * charset encoding to be used for response.
+     * Charset encoding to be used for response.
      * NB: if we can, we will convert the generated response from internal_encoding to the intended one.
      * Can be: a supported xml encoding (only UTF-8 and ISO-8859-1 at present, unless mbstring is enabled),
      * null (leave unspecified in response, convert output stream to US_ASCII),
@@ -64,10 +74,12 @@ class Server
      * NB: pretty dangerous if you accept every charset and do not have mbstring enabled)
      */
     public $response_charset_encoding = '';
+
     /**
      * Storage for internal debug info.
      */
     protected $debug_info = '';
+
     /**
      * Extra data passed at runtime to method handling functions. Used only by EPI layer
      */
@@ -179,7 +191,9 @@ class Server
      * @param string $data the request body. If null, the http POST request will be examined
      * @param bool $returnPayload When true, return the response but do not echo it or any http header
      *
-     * @return Response the response object (usually not used by caller...)
+     * @return Response|string the response object (usually not used by caller...) or its xml serialization
+     *
+     * @throws \Exception in case the executed method does throw an exception (and depending on server configuration)
      */
     public function service($data = null, $returnPayload = false)
     {
@@ -191,13 +205,14 @@ class Server
         // reset internal debug info
         $this->debug_info = '';
 
-        // Echo back what we received, before parsing it
+        // Save what we received, before parsing it
         if ($this->debug > 1) {
             $this->debugmsg("+++GOT+++\n" . $data . "\n+++END+++");
         }
 
         $r = $this->parseRequestHeaders($data, $reqCharset, $respCharset, $respEncoding);
         if (!$r) {
+            // this actually executes the request
             $r = $this->parseRequest($data, $reqCharset);
         }
 
@@ -344,7 +359,7 @@ class Server
     /**
      * Parse http headers received along with xmlrpc request. If needed, inflate request.
      *
-     * @return mixed null on success or a Response
+     * @return mixed Response|null on success or an error Response
      */
     protected function parseRequestHeaders(&$data, &$reqEncoding, &$respEncoding, &$respCompression)
     {
@@ -446,6 +461,8 @@ class Server
      * @param string $reqEncoding (optional) the charset encoding of the xml request
      *
      * @return Response
+     *
+     * @throws \Exception in case the executed method does throw an exception (and depending on server configuration)
      */
     public function parseRequest($data, $reqEncoding = '')
     {
@@ -545,10 +562,13 @@ class Server
      *
      * @return Response
      *
-     * @throws \Exception in case the executed method does throw an exception (and depending on )
+     * @throws \Exception in case the executed method does throw an exception (and depending on server configuration)
      */
     protected function execute($req, $params = null, $paramTypes = null)
     {
+        static::$_xmlrpcs_occurred_errors = '';
+        static::$_xmlrpc_debuginfo = '';
+
         if (is_object($req)) {
             $methName = $req->method();
         } else {
@@ -603,7 +623,6 @@ class Server
         // verify that function to be invoked is in fact callable
         if (!is_callable($func)) {
             error_log("XML-RPC: " . __METHOD__ . ": function '$funcName' registered as method handler is not callable");
-
             return new Response(
                 0,
                 PhpXmlRpc::$xmlrpcerr['server_error'],
@@ -616,6 +635,7 @@ class Server
         if ($this->debug > 2) {
             self::$_xmlrpcs_prev_ehandler = set_error_handler(array('\PhpXmlRpc\Server', '_xmlrpcs_errorHandler'));
         }
+
         try {
             // Allow mixed-convention servers
             if (is_object($req)) {
@@ -670,6 +690,13 @@ class Server
             // in the called function, we wrap it in a proper error-response
             switch ($this->exception_handling) {
                 case 2:
+                    if ($this->debug > 2) {
+                        if (self::$_xmlrpcs_prev_ehandler) {
+                            set_error_handler(self::$_xmlrpcs_prev_ehandler);
+                        } else {
+                            restore_error_handler();
+                        }
+                    }
                     throw $e;
                     break;
                 case 1:
@@ -899,7 +926,7 @@ class Server
         if ($call->kindOf() != 'struct') {
             return static::_xmlrpcs_multicall_error('notstruct');
         }
-        $methName = @$call->structmem('methodName');
+        $methName = @$call['methodName'];
         if (!$methName) {
             return static::_xmlrpcs_multicall_error('nomethod');
         }
@@ -910,20 +937,18 @@ class Server
             return static::_xmlrpcs_multicall_error('recursion');
         }
 
-        $params = @$call->structmem('params');
+        $params = @$call['params'];
         if (!$params) {
             return static::_xmlrpcs_multicall_error('noparams');
         }
         if ($params->kindOf() != 'array') {
             return static::_xmlrpcs_multicall_error('notarray');
         }
-        $numParams = $params->arraysize();
 
         $req = new Request($methName->scalarval());
-        for ($i = 0; $i < $numParams; $i++) {
-            if (!$req->addParam($params->arraymem($i))) {
-                $i++;
-
+        foreach($params as $i => $param) {
+            if (!$req->addParam($param)) {
+                $i++; // for error message, we count params from 1
                 return static::_xmlrpcs_multicall_error(new Response(0,
                     PhpXmlRpc::$xmlrpcerr['incorrect_params'],
                     PhpXmlRpc::$xmlrpcstr['incorrect_params'] . ": probable xml error in param " . $i));
@@ -966,7 +991,7 @@ class Server
         $pt = array();
         $wrapper = new Wrapper();
         foreach ($call['params'] as $val) {
-            $pt[] = $wrapper->php_2_xmlrpc_type(gettype($val));
+            $pt[] = $wrapper->php2XmlrpcType(gettype($val));
         }
 
         $result = $server->execute($call['methodName'], $call['params'], $pt);
@@ -984,10 +1009,8 @@ class Server
         // let accept a plain list of php parameters, beside a single xmlrpc msg object
         if (is_object($req)) {
             $calls = $req->getParam(0);
-            $numCalls = $calls->arraysize();
-            for ($i = 0; $i < $numCalls; $i++) {
-                $call = $calls->arraymem($i);
-                $result[$i] = static::_xmlrpcs_multicall_do_call($server, $call);
+            foreach($calls as $call) {
+                $result[] = static::_xmlrpcs_multicall_do_call($server, $call);
             }
         } else {
             $numCalls = count($req);