+ if (count($parsVariations) == 0) {
+ // only known good synopsis = no parameters
+ $parsVariations[] = array();
+ $minPars = 0;
+ } else {
+ $minPars = count($parsVariations[0]);
+ }
+
+ if ($minPars) {
+ // add to code the check for min params number
+ // NB: this check needs to be done BEFORE decoding param values
+ $innerCode = "\$paramcount = \$req->getNumParams();\n" .
+ "if (\$paramcount < $minPars) return new {$namespace}Response(0, " . PhpXmlRpc::$xmlrpcerr['incorrect_params'] . ", '" . PhpXmlRpc::$xmlrpcstr['incorrect_params'] . "');\n" . $innerCode;
+ } else {
+ $innerCode = "\$paramcount = \$req->getNumParams();\n" . $innerCode;
+ }
+
+ $innerCode .= "\$np = false;\n";
+ // since there are no closures in php, if we are given an object instance,
+ // we store a pointer to it in a global var...
+ if (is_array($callable) && is_object($callable[0])) {
+ $GLOBALS['xmlrpcWPFObjHolder'][$newFuncName] = &$callable[0];
+ $innerCode .= "\$obj =& \$GLOBALS['xmlrpcWPFObjHolder']['$newFuncName'];\n";
+ $realFuncName = '$obj->' . $callable[1];
+ } else {
+ $realFuncName = $plainFuncName;
+ }
+ foreach ($parsVariations as $pars) {
+ $innerCode .= "if (\$paramcount == " . count($pars) . ") \$retval = {$catchWarnings}$realFuncName(" . implode(',', $pars) . "); else\n";
+ }
+ $innerCode .= "\$np = true;\n";
+ $innerCode .= "if (\$np) return new {$namespace}Response(0, " . PhpXmlRpc::$xmlrpcerr['incorrect_params'] . ", '" . PhpXmlRpc::$xmlrpcstr['incorrect_params'] . "'); else {\n";
+ //$innerCode .= "if (\$_xmlrpcs_error_occurred) return new Response(0, $GLOBALS['xmlrpcerr']user, \$_xmlrpcs_error_occurred); else\n";
+ $innerCode .= "if (is_a(\$retval, '{$namespace}Response')) return \$retval; else\n";
+ if ($funcDesc['returns'] == Value::$xmlrpcDateTime || $funcDesc['returns'] == Value::$xmlrpcBase64) {
+ $innerCode .= "return new {$namespace}Response(new {$namespace}Value(\$retval, '{$funcDesc['returns']}'));";
+ } else {
+ if ($encodePhpObjects) {
+ $innerCode .= "return new {$namespace}Response(\$encoder->encode(\$retval, array('encode_php_objs')));\n";
+ } else {
+ $innerCode .= "return new {$namespace}Response(\$encoder->encode(\$retval));\n";
+ }
+ }
+ // shall we exclude functions returning by ref?
+ // if($func->returnsReference())
+ // return false;
+
+ $code = "function $newFuncName(\$req) {\n" . $innerCode . "}\n}";
+
+ return $code;
+ }
+
+ /**
+ * Given a user-defined PHP class or php object, map its methods onto a list of
+ * PHP 'wrapper' functions that can be exposed as xmlrpc methods from an xmlrpc server
+ * object and called from remote clients (as well as their corresponding signature info).
+ *
+ * @param mixed $className the name of the class whose methods are to be exposed as xmlrpc methods, or an object instance of that class
+ * @param array $extraOptions see the docs for wrap_php_method for basic options, plus
+ * - string method_type: 'static', 'nonstatic', 'all' and 'auto' (default); the latter will switch between static and non-static depending on whether $className is a class name or object instance
+ * - string method_filter: a regexp used to filter methods to wrap based on their names
+ * - string $prefix/ used for the names of the xmlrpc methods created
+ *
+ * @return array or false on failure
+ *
+ * @todo get_class_methods will return both static and non-static methods.
+ * we have to differentiate the action, depending on whether we received a class name or object
+ */
+ public function wrap_php_class($className, $extraOptions = array())
+ {
+ $methodFilter = isset($extraOptions['method_filter']) ? $extraOptions['method_filter'] : '';
+ $methodType = isset($extraOptions['method_type']) ? $extraOptions['method_type'] : 'auto';
+ $prefix = isset($extraOptions['prefix']) ? $extraOptions['prefix'] : '';
+
+ $results = array();
+ $mList = get_class_methods($className);
+ foreach ($mList as $mName) {
+ if ($methodFilter == '' || preg_match($methodFilter, $mName)) {
+ $func = new \ReflectionMethod($className, $mName);
+ if (!$func->isPrivate() && !$func->isProtected() && !$func->isConstructor() && !$func->isDestructor() && !$func->isAbstract()) {
+ if (($func->isStatic() && ($methodType == 'all' || $methodType == 'static' || ($methodType == 'auto' && is_string($className)))) ||
+ (!$func->isStatic() && ($methodType == 'all' || $methodType == 'nonstatic' || ($methodType == 'auto' && is_object($className))))
+ ) {
+ $methodWrap = $this->wrap_php_function(array($className, $mName), '', $extraOptions);
+ if ($methodWrap) {
+ if (is_object($className)) {
+ $realClassName = get_class($className);
+ }else {
+ $realClassName = $className;
+ }
+ $results[$prefix."$realClassName.$mName"] = $methodWrap;