public static function handleInvoke(Request $request, $targetObject, $function, &$arg)
 {
     $namedObject = $arg[0];
     $source = $namedObject->defaultAdapt()->source;
     $operation = $namedObject->defaultAdapt()->operation;
     $bodys = $namedObject->defaultAdapt()->body->getBody();
     $arguments = array();
     foreach ($bodys as $body) {
         $arguments[] = $body->defaultAdapt();
     }
     $arguments = unserialize(str_replace('s:6:"userid";', 's:3:"uid";', serialize($arguments)));
     $result = services_method_call($source . "." . $operation, $arguments);
     $result = unserialize(str_replace('s:3:"uid";', 's:6:"userid";', serialize($result)));
     return $result;
 }
 public function handle()
 {
     //A method is required, no matter what
     if (empty($this->method_name)) {
         return $this->error(JSONRPC_ERROR_REQUEST, t("The received JSON not a valid JSON-RPC Request"));
     }
     //Find the method
     $methods = services_get_all();
     $args = array();
     foreach ($methods as $method) {
         if ($method['#method'] == $this->method_name) {
             $this->method = $method;
             break;
         }
     }
     if (!isset($this->method)) {
         // No method found is a fatal error
         return $this->error(JSONRPC_ERROR_PROCEDURE_NOT_FOUND, t("Invalid method @method", array('@method' => $request)));
     }
     //If needed, check if parameters can be omitted
     $arg_count = count($this->method['#args']);
     if (!isset($this->params)) {
         for ($i = 0; $i < $arg_count; $i++) {
             $arg = $this->method['#args'][$i];
             if (!$arg['#optional']) {
                 if (empty($this->in['params'])) {
                     return $this->error(JSONRPC_ERROR_PARAMS, t("No parameters recieved, the method '@method' has required parameters.", array('@method' => $this->method_name)));
                 } else {
                     return $this->error(JSONRPC_ERROR_PARSE, t("Missing parameters, the likely reason is malformed json, the method '@method' has required parameters.", array('@method' => $this->method_name)));
                 }
             }
         }
     }
     // Map parameters to arguments, the 1.1 draft is more generous than the 2.0 proposal when
     // it comes to parameter passing. 1.1-d allows mixed positional and named parameters while
     // 2.0-p forces the client to choose between the two.
     //
     // 2.0 proposal on parameters: http://groups.google.com/group/json-rpc/web/json-rpc-1-2-proposal#parameters-positional-and-named
     // 1.1 draft on parameters: http://json-rpc.org/wd/JSON-RPC-1-1-WD-20060807.html#NamedPositionalParameters
     if ($this->array_is_assoc($this->params)) {
         $this->args = array();
         //Create a assoc array to look up indexes for parameter names
         $arg_dict = array();
         for ($i = 0; $i < $arg_count; $i++) {
             $arg = $this->method['#args'][$i];
             $arg_dict[$arg['#name']] = $i;
         }
         foreach ($this->params as $key => $value) {
             if ($this->major_version == 1 && preg_match('/^\\d+$/', $key)) {
                 //A positional argument (only allowed in v1.1 calls)
                 if ($key >= $arg_count) {
                     //Index outside bounds
                     return $this->error(JSONRPC_ERROR_PARAMS, t("Positional parameter with a position outside the bounds (index: @index) recieved", array('@index' => $key)));
                 } else {
                     $this->args[intval($key)] = $value;
                 }
             } else {
                 //Associative key
                 if (!isset($arg_dict[$key])) {
                     //Unknown parameter
                     return $this->error(JSONRPC_ERROR_PARAMS, t("Unknown named parameter '@name' recieved", array('@name' => $key)));
                 } else {
                     $this->args[$arg_dict[$key]] = $value;
                 }
             }
         }
     } else {
         //Non associative arrays can be mapped directly
         $param_count = count($this->params);
         if ($param_count > $arg_count) {
             return $this->error(JSONRPC_ERROR_PARAMS, t("Too many arguments recieved, the method '@method' only takes '@num' argument(s)", array('@method' => $this->method_name, '@num' => $arg_count)));
         }
         $this->args = $this->params;
     }
     //Validate arguments
     for ($i = 0; $i < $arg_count; $i++) {
         $val = $this->args[$i];
         $arg = $this->method['#args'][$i];
         if (isset($val)) {
             //If we have data
             //Only array-type parameters accepts arrays
             if (is_array($val) && $arg['#type'] != 'array') {
                 return $this->error_wrong_type($arg, 'array');
             } else {
                 if (($arg['#type'] == 'int' || $arg['#type'] == 'float') && !is_numeric($val)) {
                     return $this->error_wrong_type($arg, 'string');
                 }
             }
         } else {
             if (!$arg['#optional']) {
                 //Trigger error if a required parameter is missing
                 return $this->error(JSONRPC_ERROR_PARAMS, t("Argument '@name' is required but was not recieved", array('@name' => $arg['#name'])));
             }
         }
     }
     // We are returning JSON, so tell the browser.
     drupal_set_header('Content-Type: application/json; charset=utf-8');
     //Call service method
     try {
         $result = services_method_call($this->method['#method'], $this->args);
         if (is_array($result) && isset($result['#error']) && $result['#error'] === TRUE) {
             return $this->error(JSONRPC_ERROR_INTERNAL_ERROR, $result['#message']);
         } else {
             return $this->result($result);
         }
     } catch (Exception $e) {
         return $this->error(JSONRPC_ERROR_INTERNAL_ERROR, $e->getMessage());
     }
 }