not for the developers simply using it)
* improved: updated the user's manual to be inline with the version4 API and modern coding practices.
- The manual is now bundled in the default distribution tarball, and is easily viewable as html provided you can
+ The manual is now bundled in the default distribution tarball, and is easily viewable as html, provided you can
serve it using a webserver.
* fixed: the value for error 'no_http2' has been switched from 15 to 19 to avoid a collision
<?php
/**
* @author Gaetano Giunta
- * @copyright (C) 2005-2021 G. Giunta
+ * @copyright (C) 2005-2023 G. Giunta
* @license code licensed under the BSD License: see file license.txt
*
* @todo switch params for http compression from 0,1,2 to values to be used directly
<?php
/**
* @author Gaetano Giunta
- * @copyright (C) 2005-2021 G. Giunta
+ * @copyright (C) 2005-2023 G. Giunta
* @license code licensed under the BSD License: see file license.txt
*
* Parses GET/POST variables
<?php
/**
* @author Gaetano Giunta
- * @copyright (C) 2005-2021 G. Giunta
+ * @copyright (C) 2005-2023 G. Giunta
* @license code licensed under the BSD License: see file license.txt
*
* @todo add links to documentation from every option caption
* For an example of a transparent reverse-proxy, see the ReverseProxy class in package phpxmlrpc/extras.
*
* @author Gaetano Giunta
- * @copyright (C) 2006-2021 G. Giunta
+ * @copyright (C) 2006-2023 G. Giunta
* @license code licensed under the BSD License: see file license.txt
*/
/**
* Script used to convert docbook source to human-readable docs
*
- * @copyright (c) 2007-2022 G. Giunta
+ * @copyright (c) 2007-2023 G. Giunta
*
* @todo rename to something akin to xsltproc
*/
}
----
-===== Automatic type conversion
+===== Automatic type conversion [[autoserver]]
In the same spirit of simplification that inspired the Client's `$return_type` property, a similar property
is available within the server class: `$functions_parameters_type`. When set to the string 'phpvals', the functions
In order to extend the functionality offered by XML-RPC servers without impacting on the protocol, reserved methods are
supported.
-All methods starting with __system.__ are considered reserved by the server. PHP for XML-RPC itself provides four
+All methods starting with __system.__ are considered reserved by the server. PHPXMLRPC itself provides four
special methods, detailed in this chapter.
Note that all server objects will automatically respond to clients querying these methods, unless the property
When set to `TRUE`, php NULL values encoded into Value objects will get serialized using the `<EX:NIL/>` tag instead of
`<NIL/>`. Please note that both forms are always accepted as input regardless of the value of this variable.
+=== Errors and Logging [[logging]]
+
+Many of the classes in this library by default use the php error logging facilities to log errors in case there
+is some unexpected but non-fatal event happening, such as f.e. when an invalid xml-rpc request or response are received.
+Going straight to the log instead of triggering a php warning or error has the advantage of not breaking the xml-rpc
+output when the issue is happening within the context of an xmlrpc-server and `display_errors` is enabled.
+
+In case things are not going as you expect, please check the error log first for the presence of any messages from
+PHPXMLRPC which could be useful in troubleshooting what is going on under the hood.
+
+You can customize the way error messages are traced via the static method `setLogger` available for the classes
+`Client`, `Encoder`, `Request`, `Server` and `Value`. Keep in mind that for the moment, classes `Charset`, `HTTP` and
+`XMLParser` do not allow the same customization without hacking the `PhpXmlRpc\Logger` class. Last but not least, be
+aware that the same Logger is also responsible for echoing to screen the debug messages produced by the Client when its
+debug level has been set; this allows to customize the debugging process in the same way.
+
=== Helper classes and functions [[helpers]]
PHPXMLRPC contains some helper classes which you can use to make processing of XML-RPC requests easier.
if ($val) echo 'Found a value of type ' . $val->kindOf(); else echo 'Found invalid xml';
----
-=== Errors and Logging [[logging]]
-
-Many of the classes in this library by default use the php error logging facilities to log errors in case there
-is some unexpected but non-fatal event happening, such as f.e. when an invalid xml-rpc request or response are received.
-Going straight to the log instead of triggering a php warning or error has the advantage of not breaking the xml-rpc
-output when the issue is happening within the context of an xmlrpc-server and `display_errors` is enabled.
-
-In case things are not going as you expect, please check the error log first for the presence of any messages from
-PHPXMLRPC which could be useful in troubleshooting what is going on under the hood.
-
-You can customize the way error messages are traced via the static method `setLogger` available for the classes
-`Client`, `Encoder`, `Request`, `Server` and `Value`. Keep in mind that for the moment, classes `Charset`, `HTTP` and
-`XMLParser` do not allow the same customization without hacking the `PhpXmlRpc\Logger` class. Last but not least, be
-aware that the same Logger is also responsible for echoing to screen the debug messages produced by the Client when its
-debug level has been set; this allows to customize the debugging process in the same way.
-
=== Transferring PHP objects over XML-RPC
In case there is a (real) need to transfer php object instances over XML-RPC, the "usual" way would be to use a `serialize`
=== Code generation, Proxy objects & co.
-For the extremely lazy coder, helper functions have been added that allow to convert a php function into an xml-rpc method,
-and a remotely exposed xml-rpc method into a local php function - or a set of xml-rpc methods into a php class. Note that these come with many caveat.
+For the extremely lazy coder, helper functions have been added that allow to expose any pre-existing php functions (or
+all the public methods of a Class) as xml-rpc method handlers, and convert a remotely exposed xml-rpc method into a local
+php function - or a set of xml-rpc methods into a php class. This allows to use the library in a "transparent" fashion,
+ie. without having to deal with the Value, Client, Request and Response classes - but it comes with many gotchas and
+limitations.
-[[wrap_xmlrpc_method]]
-==== wrap_xmlrpc_method
+==== wrapXmlrpcMethod [[wrapxmlrpcmethod]]
- string wrap_xmlrpc_method($client, $methodname, $extra_options)
+ Closure|string|false PhpXmlRpc\Wrapper::wrapXmlrpcMethod(Client $client, string $methodName, array $extraOptions = [])
-Given an xml-rpc server and a method name, creates a php wrapper function that will call the remote method and return
-results using native php types for both params and results. The generated php function will return a Response object
-for failed xml-rpc calls.
+Given a pre-built client pointing to a given xml-rpc server and a method name, creates a php "wrapper" function that will
+call the remote method and return results using native php types for both params and results. The generated php function
+will return a Response object for failed xml-rpc calls.
The server must support the `system.methodSignature` xml-rpc method call for this function to work.
The client param must be a valid Client object, previously created with the address of the target xml-rpc server, and to
-which the preferred communication options have been set.
+which the preferred options for http communication have been set.
-The optional parameters can be passed as array key,value pairs in the extra_options param.
+The optional parameters can be passed as key,value pairs in the `$extra_options` argument.
-The signum optional param has the purpose
-of indicating which method signature to use, if the given server
-method has multiple signatures (defaults to 0).
+The `signum` option has the purpose of indicating which method signature to use, if the given xml-rpc method has
+multiple signatures (defaults to 0).
-The timeout and protocol optional params are the same as in the Client::send() method.
+The `timeout` and `protocol` options are the same as the arguments with same name of the `Client::send()` method.
-If set, the optional new_function_name parameter indicates which name should be used for the generated function. In case
+If set, the `new_function_name` option indicates which name should be used for the generated function. In case
it is not set the function name will be auto-generated.
-If the `return_source` optional parameter is
-set, the function will return the php source code to build the wrapper
-function, instead of evaluating it (useful to save the code and use it
-later as stand-alone xml-rpc client).
-
-If the `encode_php_objs` optional parameter is
-set, instances of php objects later passed as parameters to the newly
-created function will receive a 'special' treatment that allows the
-server to rebuild them as php objects instead of simple arrays. Note
-that this entails using a "slightly augmented" version of the xml-rpc
-protocol (i.e. using element attributes), which might not be understood
-by xml-rpc servers implemented using other libraries.
-
-If the `decode_php_objs` optional parameter is
-set, instances of php objects that have been appropriately encoded by
-the server using a coordinate option will be deserialized as php
-objects instead of simple arrays (the same class definition should be
+If the `return_source` option is set, the function will return the php source code of the wrapper function, instead of
+evaluating it. This useful to save the code and use it later as stand-alone xml-rpc client with no performance hit
+and no dependency on `system.methodSignature`.
+
+If the `encode_php_objs` option is set, instances of php objects later passed as parameters to the newly created function
+will receive a 'special' treatment that allows the server to rebuild them as php objects instead of simple arrays. Note
+that this entails using a "slightly augmented" version of the xml-rpc protocol (i.e. using element attributes), which
+might not be understood by xml-rpc servers implemented using other libraries; it works well when the server is built
+on top of phpxmlrpc.
+
+If the `decode_php_objs` option is set, instances of php objects that have been appropriately encoded by the server using
+a corresponding option will be deserialized as php objects instead of simple arrays (the same class definition should be
present server side and client side).
-__Note that this might pose a security risk__,
-since in order to rebuild the object instances their constructor
-method has to be invoked, and this means that the remote server can
-trigger execution of unforeseen php code on the client: not really a
-code injection, but almost. Please enable this option only when you
-trust the remote server.
-
-In case of an error during generation of the wrapper function,
-FALSE is returned, otherwise the name (or source code) of the new
-function.
-
-Known limitations: server must support
-system.methodsignature for the wanted xml-rpc
-method; for methods that expose multiple signatures, only one can be
-picked; for remote calls with nested xml-rpc params, the caller of the
-generated php function has to encode on its own the params passed to
-the php function if these are structs or arrays whose (sub)members
-include values of type base64.
-
-Note: calling the generated php function 'might' be slow: a new
-xml-rpc client is created on every invocation and an xmlrpc-connection
-opened+closed. An extra 'debug' param is appended to the parameter
-list of the generated php function, useful for debugging
+__Note that this might pose a security risk__, since in order to rebuild the object instances their constructor
+method has to be invoked, and this means that the remote server can trigger execution of unforeseen php code on the
+client: not really a code injection, but almost. Please enable this option only when you absolutely trust the remote server.
+
+In case of an error during generation of the wrapper function, FALSE is returned.
+
+Known limitations: the server must support system.methodsignature for the desired xml-rpc method; for methods that expose
+multiple signatures, only one can be picked; for remote calls with nested xml-rpc params, the caller of the
+generated php function has to encode on its own the params passed to the php function if these are structs or arrays
+whose (sub)members include values of type base64.
+
+Note: calling the generated php function 'might' be slow: a new xml-rpc client is created on every invocation and an
+xmlrpc-connection opened+closed.
+
+An extra 'debug' argument is appended to the argument list of the generated php function, useful for debugging
purposes.
Example usage:
[source, php]
----
use PhpXmlRpc\Client;
+use PhpXmlRpc\Wrapper;
$c = new Client('https://phpxmlrpc.sourceforge.net/server.php');
-$function = wrap_xmlrpc_method($client, 'examples.getStateName');
+$function = new Wrapper()->wrapXmlrpcMethod($client, 'examples.getStateName');
if (!$function)
- die('Cannot introspect remote method');
+ die('Failed introspecting remote method');
else {
- $stateno = 15;
- $statename = $function($a);
+ $stateNo = 15;
+ $stateName = $function($stateNo);
// NB: in real life, you should make sure you escape the received data with `htmlspecialchars` when echoing it as html
- if (is_a($statename, 'Response')) { // call failed
- echo 'Call failed: '.$statename->faultCode().'. Calling again with debug on';
- $function($a, true);
+ if (is_a($stateName, 'Response')) { // call failed
+ echo 'Call failed: '.$stateName->faultCode().'. Calling again with debug on...';
+ $function($stateNo, true);
}
else
- echo "OK, state nr. $stateno is $statename";
+ echo "OK, state nr. $stateNo is $stateName";
}
----
-==== wrap_php_function [[wrap_php_function]]
+==== wrapXmlrpcServer
+
+ string|array|false PhpXmlRpc\Wrapper::wrapXmlrpcServer(Client $client, array $extraOptions = [])
+
+Similar to wrapXmlrpcMethod, but instead of creating a single php function this creates a php class, whose methods match
+all the xml-rpc methods available on the remote server.
- array wrap_php_function(string $funcname, string $wrapper_function_name, array $extra_options)
+Note that a simpler alternative to this, doing no type-checks on the arguments of the invoked methods, and providing no
+support for IDE auto-completion, can be found in the __demo/client/proxy.php__ demo file.
+
+==== wrapPhpFunction [[wrapphpfunction]]
+
+ array|false PhpXmlRpc\Wrapper::wrapPhpFunction(Callable $callable, string $newFuncName = '', array $extraOptions = [])
Given a user-defined PHP function, create a PHP 'wrapper' function that can be exposed as xml-rpc method from a Server
object and called from remote clients, and return the appropriate definition to be added to a server's dispatch map.
-The optional `$wrapper_function_name` specifies the name that will be used for the auto-generated function.
+The optional `$newFuncName` specifies the name that will be used for the auto-generated function.
Since php is a typeless language, to infer types of input and output parameters, it relies on parsing the phpdoc-style
comment block associated with the given function. Usage of xml-rpc native types (such as datetime.dateTime.iso8601 and
retrieving number/type of params for those); the wrapped php function will not be able to programmatically return an
xml-rpc error response.
-If the `return_source` optional parameter is set, the function will return the php source code to build the wrapper
-function, instead of evaluating it (useful to save the code and use it
-later in a stand-alone xml-rpc server). It will be in the stored in the
-`source` member of the returned array.
+If the `return_source` option parameter is set, the function will return the php source code to build the wrapper
+function, instead of evaluating it (useful to save the code and use it later in a stand-alone xml-rpc server). It will b
+e in the stored in the `source` member of the returned array.
-If the `suppress_warnings` optional parameter
-is set, any runtime warning generated while processing the
-user-defined php function will be caught and not be printed in the
-generated xml response.
+If the `suppress_warnings` optional parameter is set, any runtime warning generated while processing the user-defined
+php function will be caught and not be printed in the generated xml response.
If the extra_options array contains the `encode_php_objs` value, wrapped functions returning php objects will generate
"special" xml-rpc responses: when the decoding of those responses is carried out by this same lib, using the
[source, php]
----
use PhpXmlRpc\Server;
+use PhpXmlRpc\Wrapper;
/**
* State name from state number decoder. NB: do NOT remove this comment block.
* @param integer $stateno the state number
-* @return string the name of the state (or error description)
+* @return string the name of the state (or an error description)
*/
function findstate($stateno)
{
// wrap php function, build xml-rpc server
$methods = array();
-$findstate_sig = wrap_php_function('findstate');
+$findstate_sig = new Wrapper()->wrapPhpFunction('findstate');
if ($findstate_sig)
$methods['examples.getStateName'] = $findstate_sig;
$srv = new Server($methods);
----
+Please note that similar results to the above, i.e. adding to the server's dispatch map an existing php function which
+is not aware of xml-rpc, can be obtained without the Wrapper class and the need for introspection, simply by setting
+`+$server->unctions_parameters_type = 'phpvals'+` and `+$server->exception_handling = 1+` (see chapter <<autoserver>>).
+The main difference is that, using the Wrapper class, you get for free the documentation for the xmlrpc-method.
+
+==== wrapPhpClass
+
+ array|false PhpXmlRpc\Wrapper::wrapPhpClass(string|object $className, array $extraOptions = [])
+
+Similar to `wrapPhpFunction`, it works on all public methods of a given object/class. The server must support both the
+`system.methodList` and `system.methodSignature` xml-rpc method calls for this function to work.
+
+==== Code generation
+
+Using the Wrapper class to create some code and execute it directly inline has the worst possible performances, as it
+relies on either using introspection of existing php code or making extra calls to the xml-rpc introspection methods
+of the server. It also does not provide the benefit of allowing IDEs to inspect the generated code and provide
+auto-completion for it, nor for security-minded developers to be able to examine it before executing it. It is thus
+recommended to always use the `return_source` option when using the Wrapper methods, and save to disk the generated code
+instead of executing it directly.
+
+
== Performances [[performances]]
Although the library is not designed to be the most memory-efficient nor the most fast possible implementation of the
* Benchmarking suite for the PHPXMLRPC lib.
*
* @author Gaetano Giunta
- * @copyright (c) 2005-2021 G. Giunta
+ * @copyright (c) 2005-2023 G. Giunta
* @license code licensed under the BSD License: see file license.txt
*
* @todo add a check for response ok in call testing
* Verify compatibility level of current php install with php-xmlrpc lib.
*
* @author Gaetano Giunta
- * @copyright (C) 2006-2021 G. Giunta
+ * @copyright (C) 2006-2023 G. Giunta
* @license code licensed under the BSD License: see file license.txt
*
* @todo add a test for php output buffering?
<?php
/**
* @author Gaetano Giunta
- * @copyright (C) 2006-2021 G. Giunta
+ * @copyright (C) 2006-2023 G. Giunta
* @license code licensed under the BSD License: see file license.txt
*/
* @return string
*
* @todo support notation `something[]` as 'array'
+ * @todo check if nil support is enabled when finding null
*/
public function php2XmlrpcType($phpType)
{
}
/**
- * Given a user-defined PHP function, create a PHP 'wrapper' function that can
- * be exposed as xmlrpc method from an xmlrpc server object and called from remote
- * clients (as well as its corresponding signature info).
+ * Given a user-defined PHP function, create a PHP 'wrapper' function that can be exposed as xmlrpc method from an
+ * xmlrpc server object and called from remote clients (as well as its corresponding signature info).
*
- * Since php is a typeless language, to infer types of input and output parameters,
- * it relies on parsing the javadoc-style comment block associated with the given
- * function. Usage of xmlrpc native types (such as datetime.dateTime.iso8601 and base64)
- * in the '@param' tag is also allowed, if you need the php function to receive/send
- * data in that particular format (note that base64 encoding/decoding is transparently
- * carried out by the lib, while datetime vals are passed around as strings)
+ * Since php is a typeless language, to infer types of input and output parameters, it relies on parsing the
+ * javadoc-style comment block associated with the given function. Usage of xmlrpc native types (such as
+ * datetime.dateTime.iso8601 and base64) in the '@param' tag is also allowed, if you need the php function to
+ * receive/send data in that particular format (note that base64 encoding/decoding is transparently carried out by
+ * the lib, while datetime values are passed around as strings)
*
* Known limitations:
- * - only works for user-defined functions, not for PHP internal functions
- * (reflection does not support retrieving number/type of params for those)
- * - functions returning php objects will generate special structs in xmlrpc responses:
- * when the xmlrpc decoding of those responses is carried out by this same lib, using
- * the appropriate param in php_xmlrpc_decode, the php objects will be rebuilt.
- * In short: php objects can be serialized, too (except for their resource members),
- * using this function.
- * Other libs might choke on the very same xml that will be generated in this case
- * (i.e. it has a nonstandard attribute on struct element tags)
+ * - only works for user-defined functions, not for PHP internal functions (reflection does not support retrieving
+ * number/type of params for those)
+ * - functions returning php objects will generate special structs in xmlrpc responses: when the xmlrpc decoding of
+ * those responses is carried out by this same lib, using the appropriate param in php_xmlrpc_decode, the php
+ * objects will be rebuilt.
+ * In short: php objects can be serialized, too (except for their resource members), using this function.
+ * Other libs might choke on the very same xml that will be generated in this case (i.e. it has a nonstandard
+ * attribute on struct element tags)
*
- * Note that since rel. 2.0RC3 the preferred method to have the server call 'standard'
- * php functions (ie. functions not expecting a single Request obj as parameter)
- * is by making use of the functions_parameters_type class member.
+ * Note that since rel. 2.0RC3 the preferred method to have the server call 'standard' php functions (ie. functions
+ * not expecting a single Request obj as parameter) is by making use of the $functions_parameters_type and
+ * $exception_handling properties.
*
- * @param callable $callable the PHP user function to be exposed as xmlrpc method/ a closure, function name, array($obj, 'methodname') or array('class', 'methodname') are ok
+ * @param \Callable $callable the PHP user function to be exposed as xmlrpc method: a closure, function name, array($obj, 'methodname') or array('class', 'methodname') are ok
* @param string $newFuncName (optional) name for function to be created. Used only when return_source in $extraOptions is true
* @param array $extraOptions (optional) array of options for conversion. valid values include:
* - bool return_source when true, php code w. function definition will be returned, instead of a closure
$func = new \ReflectionFunction($callable);
}
if ($func->isInternal()) {
- // Note: from PHP 5.1.0 onward, we will possibly be able to use invokeargs
- // instead of getparameters to fully reflect internal php functions ?
+ /// @todo from PHP 5.1.0 onward, we should be able to use invokeargs instead of getparameters to fully
+ /// reflect internal php functions
$this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': function to be wrapped is internal: ' . $plainFuncName);
return false;
}
* - string prefix used for the names of the xmlrpc methods created.
* - string replace_class_name use to completely replace the class name with the prefix in the generated method names. e.g. instead of \Some\Namespace\Class.method use prefixmethod
*
- * @return array|false false on failure
+ * @return array|false false on failure, or on array useable for the dispatch map
*/
public function wrapPhpClass($className, $extraOptions = array())
{
}
/**
- * Given an xmlrpc client and a method name, register a php wrapper function
- * that will call it and return results using native php types for both
- * params and results. The generated php function will return a Response
+ * Given an xmlrpc client and a method name, register a php wrapper function that will call it and return results
+ * using native php types for both arguments and results. The generated php function will return a Response
* object for failed xmlrpc calls.
*
* Known limitations:
- * - server must support system.methodsignature for the wanted xmlrpc method
- * - for methods that expose many signatures, only one can be picked (we
- * could in principle check if signatures differ only by number of params
- * and not by type, but it would be more complication than we can spare time)
- * - nested xmlrpc params: the caller of the generated php function has to
- * encode on its own the params passed to the php function if these are structs
- * or arrays whose (sub)members include values of type datetime or base64
+ * - server must support system.methodSignature for the target xmlrpc method
+ * - for methods that expose many signatures, only one can be picked (we could in principle check if signatures
+ * differ only by number of params and not by type, but it would be more complication than we can spare time for)
+ * - nested xmlrpc params: the caller of the generated php function has to encode on its own the params passed to
+ * the php function if these are structs or arrays whose (sub)members include values of type base64
*
- * Notes: the connection properties of the given client will be copied
- * and reused for the connection used during the call to the generated
- * php function.
- * Calling the generated php function 'might' be slow: a new xmlrpc client
- * is created on every invocation and an xmlrpc-connection opened+closed.
- * An extra 'debug' param is appended to param list of xmlrpc method, useful
+ * Notes: the connection properties of the given client will be copied and reused for the connection used during
+ * the call to the generated php function.
+ * Calling the generated php function 'might' be slightly slow: a new xmlrpc client is created on every invocation
+ * and an xmlrpc-connection opened+closed.
+ * An extra 'debug' argument, defaulting to 0, is appended to the argument list of the generated function, useful
* for debugging purposes.
*
* @param Client $client an xmlrpc client set up correctly to communicate with target server
* - bool debug set it to 1 or 2 to see debug results of querying server for method synopsis
* - int simple_client_copy set it to 1 to have a lightweight copy of the $client object made in the generated code (only used when return_source = true)
*
- * @return \closure|string[]|false false on failure, closure by default and array for return_source = true
+ * @return \Closure|string[]|false false on failure, closure by default and array for return_source = true
*
+ * @todo allow the created function to throw exceptions on method calls failures
* @todo allow caller to give us the method signature instead of querying for it, or just say 'skip it'
* @todo if we can not retrieve method signature, create a php function with varargs
- * @todo allow the created function to throw exceptions on method calls failures
* @todo if caller did not specify a specific sig, shall we support all of them?
* It might be hard (hence slow) to match based on type and number of arguments...
*/
$newFuncName = $this->newFunctionName($methodName, $newFuncName, $extraOptions);
$results = $this->buildWrapMethodSource($client, $methodName, $extraOptions, $newFuncName, $mSig, $mDesc);
- /* was: $results = $this->build_remote_method_wrapper_code($client, $methodName,
- $newFuncName, $mSig, $mDesc, $timeout, $protocol, $simpleClientCopy,
- $prefix, $decodePhpObjects, $encodePhpObjects, $decodeFault,
- $faultResponse, $namespace);*/
$results['function'] = $newFuncName;
}
$mSig = $response->value();
+ /// @todo what about return xml?
if ($client->return_type != 'phpvals') {
$decoder = new $decoderClass();
$mSig = $decoder->decode($mSig);
}
/**
+ * @internal made public just for Debugger usage
+ *
* @param Client $client
* @param string $methodName
* @param array $extraOptions
}
/**
- * Similar to wrapXmlrpcMethod, but will generate a php class that wraps
- * all xmlrpc methods exposed by the remote server as own methods.
- * For more details see wrapXmlrpcMethod.
+ * Similar to wrapXmlrpcMethod, but will generate a php class that wraps all xmlrpc methods exposed by the remote
+ * server as own methods.
+ * For a slimmer alternative, see the code in demo/client/proxy.php.
+ * Note that unlike wrapXmlrpcMethod, we always have to generate php code here. Since php 7 anon classes exist, but
+ * we do not support them yet...
*
- * For a slimmer alternative, see the code in demo/client/proxy.php
- *
- * Note that unlike wrapXmlrpcMethod, we always have to generate php code here. It seems that php 7 will have anon classes...
+ * @see wrapXmlrpcMethod for more details.
*
* @param Client $client the client obj all set to query the desired server
- * @param array $extraOptions list of options for wrapped code. See the ones from wrapXmlrpcMethod plus
- * - string method_filter regular expression
- * - string new_class_name
- * - string prefix
- * - bool simple_client_copy set it to true to avoid copying all properties of $client into the copy made in the new class
+ * @param array $extraOptions list of options for wrapped code. See the ones from wrapXmlrpcMethod, plus
+ * - string method_filter regular expression
+ * - string new_class_name
+ * - string prefix
+ * - bool simple_client_copy set it to true to avoid copying all properties of $client into the copy made in the new class
+ *
+ * @return string|array|false false on error, the name of the created class if all ok or an array with code, class name and comments (if the appropriate option is set in extra_options)
*
- * @return mixed false on error, the name of the created class if all ok or an array with code, class name and comments (if the appropriate option is set in extra_options)
+ * @todo add support for anonymous classes in the 'buildIt' case for php > 7
*/
public function wrapXmlrpcServer($client, $extraOptions = array())
{
$reqClass = $namespace . 'Request';
$decoderClass = $namespace . 'Encoder';
+ // retrieve the list of methods
$req = new $reqClass('system.listMethods');
$response = $client->send($req, $timeout, $protocol);
if ($response->faultCode()) {
$this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': could not retrieve method list from remote server');
return false;
- } else {
- $mList = $response->value();
- if ($client->return_type != 'phpvals') {
- $decoder = new $decoderClass();
- $mList = $decoder->decode($mList);
- }
- if (!is_array($mList) || !count($mList)) {
- $this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': could not retrieve meaningful method list from remote server');
+ }
+ $mList = $response->value();
+ /// @todo what about return_type = xml?
+ if ($client->return_type != 'phpvals') {
+ $decoder = new $decoderClass();
+ $mList = $decoder->decode($mList);
+ }
+ if (!is_array($mList) || !count($mList)) {
+ $this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': could not retrieve meaningful method list from remote server');
- return false;
- } else {
- // pick a suitable name for the new function, avoiding collisions
- if ($newClassName != '') {
- $xmlrpcClassName = $newClassName;
- } else {
- $xmlrpcClassName = $prefix . '_' . preg_replace(array('/\./', '/[^a-zA-Z0-9_\x7f-\xff]/'),
- array('_', ''), $client->server) . '_client';
- }
- while ($buildIt && class_exists($xmlrpcClassName)) {
- $xmlrpcClassName .= 'x';
- }
+ return false;
+ }
- /// @todo add function setdebug() to new class, to enable/disable debugging
- $source = "class $xmlrpcClassName\n{\npublic \$client;\n\n";
- $source .= "function __construct()\n{\n";
- $source .= $this->buildClientWrapperCode($client, $verbatimClientCopy, $prefix, $namespace);
- $source .= "\$this->client = \$client;\n}\n\n";
- $opts = array(
- 'return_source' => true,
- 'simple_client_copy' => 2, // do not produce code to copy the client object
- 'timeout' => $timeout,
- 'protocol' => $protocol,
- 'encode_php_objs' => $encodePhpObjects,
- 'decode_php_objs' => $decodePhpObjects,
- 'prefix' => $prefix,
- );
- /// @todo build phpdoc for class definition, too
- foreach ($mList as $mName) {
- if ($methodFilter == '' || preg_match($methodFilter, $mName)) {
- // note: this will fail if server exposes 2 methods called f.e. do.something and do_something
- $opts['new_function_name'] = preg_replace(array('/\./', '/[^a-zA-Z0-9_\x7f-\xff]/'),
- array('_', ''), $mName);
- $methodWrap = $this->wrapXmlrpcMethod($client, $mName, $opts);
- if ($methodWrap) {
- if (!$buildIt) {
- $source .= $methodWrap['docstring'];
- }
- $source .= $methodWrap['source'] . "\n";
- } else {
- $this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': will not create class method to wrap remote method ' . $mName);
- }
- }
- }
- $source .= "}\n";
- if ($buildIt) {
- $allOK = 0;
- eval($source . '$allOK=1;');
- if ($allOK) {
- return $xmlrpcClassName;
- } else {
- $this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': could not create class ' . $xmlrpcClassName . ' to wrap remote server ' . $client->server);
- return false;
+ // pick a suitable name for the new function, avoiding collisions
+ if ($newClassName != '') {
+ $xmlrpcClassName = $newClassName;
+ } else {
+ $xmlrpcClassName = $prefix . '_' . preg_replace(array('/\./', '/[^a-zA-Z0-9_\x7f-\xff]/'),
+ array('_', ''), $client->server) . '_client';
+ }
+ while ($buildIt && class_exists($xmlrpcClassName)) {
+ $xmlrpcClassName .= 'x';
+ }
+
+ /// @todo add method setDebug() to new class, to enable/disable debugging
+ $source = "class $xmlrpcClassName\n{\npublic \$client;\n\n";
+ $source .= "function __construct()\n{\n";
+ $source .= $this->buildClientWrapperCode($client, $verbatimClientCopy, $prefix, $namespace);
+ $source .= "\$this->client = \$client;\n}\n\n";
+ $opts = array(
+ 'return_source' => true,
+ 'simple_client_copy' => 2, // do not produce code to copy the client object
+ 'timeout' => $timeout,
+ 'protocol' => $protocol,
+ 'encode_php_objs' => $encodePhpObjects,
+ 'decode_php_objs' => $decodePhpObjects,
+ 'prefix' => $prefix,
+ );
+ /// @todo build phpdoc for class definition, too
+ foreach ($mList as $mName) {
+ if ($methodFilter == '' || preg_match($methodFilter, $mName)) {
+ // note: this will fail if server exposes 2 methods called f.e. do.something and do_something
+ $opts['new_function_name'] = preg_replace(array('/\./', '/[^a-zA-Z0-9_\x7f-\xff]/'),
+ array('_', ''), $mName);
+ $methodWrap = $this->wrapXmlrpcMethod($client, $mName, $opts);
+ if ($methodWrap) {
+ if (!$buildIt) {
+ $source .= $methodWrap['docstring'];
}
+ $source .= $methodWrap['source'] . "\n";
} else {
- return array('class' => $xmlrpcClassName, 'code' => $source, 'docstring' => '');
+ $this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': will not create class method to wrap remote method ' . $mName);
}
}
}
+ $source .= "}\n";
+ if ($buildIt) {
+ $allOK = 0;
+ eval($source . '$allOK=1;');
+ if ($allOK) {
+ return $xmlrpcClassName;
+ } else {
+ $this->getLogger()->errorLog('XML-RPC: ' . __METHOD__ . ': could not create class ' . $xmlrpcClassName . ' to wrap remote server ' . $client->server);
+ return false;
+ }
+ } else {
+ return array('class' => $xmlrpcClassName, 'code' => $source, 'docstring' => '');
+ }
}
/**
* @param int SSLVERSION
* @param string PROXYSERVER
*
- * @copyright (C) 2007-2021 G. Giunta
+ * @copyright (C) 2007-2023 G. Giunta
* @license code licensed under the BSD License: see file license.txt
*
* @todo rename both the class and the file. PhpXmlRpc_TestArgParser ?
/**
* Used to serve back the server-side code coverage results to phpunit-selenium
*
- * @copyright (C) 2007-2021 G. Giunta
+ * @copyright (C) 2007-2023 G. Giunta
* @license code licensed under the BSD License: see file license.txt
**/