improve server demos: adopt more modern coding practices; docs
authorgggeek <giunta.gaetano@gmail.com>
Tue, 10 Jan 2023 00:12:30 +0000 (00:12 +0000)
committergggeek <giunta.gaetano@gmail.com>
Tue, 10 Jan 2023 00:12:30 +0000 (00:12 +0000)
demo/server/discuss.php
demo/server/methodProviders/functions.php
demo/server/methodProviders/interop.php
demo/server/methodProviders/testsuite.php
demo/server/methodProviders/validator1.php
demo/server/methodProviders/wrapper.php
demo/server/server.php
tests/5ServerTest.php

index 2a49004..6f2f905 100644 (file)
@@ -15,6 +15,7 @@ use PhpXmlRpc\Response;
 use PhpXmlRpc\Server;
 use PhpXmlRpc\Value;
 
+// NB: this class is totally unaware of the existence of xml-rpc or phpxmlrpc
 class CommentManager
 {
     protected $dbFile = "/tmp/comments.db";
@@ -87,6 +88,8 @@ class CommentManager
     }
 }
 
+// Here starts the mapping of CommentManager's methods into xml-rpc methods
+
 $manager = new CommentManager();
 
 $addComment_sig = array(array(Value::$xmlrpcInt, Value::$xmlrpcString, Value::$xmlrpcString, Value::$xmlrpcString));
@@ -99,8 +102,6 @@ $getComments_sig = array(array(Value::$xmlrpcArray, Value::$xmlrpcString));
 $getComments_doc = 'Returns an array of comments for a given ID, which is the sole argument. Each array item is a struct ' .
     'containing name and comment text.';
 
-// NB: take care not to output anything else after this call, as it will mess up the responses and it will be hard to
-// debug. In case you have to do so, at least re-emit a correct Content-Length http header (requires output buffering)
 $srv = new Server(array(
     "discuss.addComment" => array(
         "function" => array($manager, "addComment"),
@@ -120,4 +121,6 @@ $srv->functions_parameters_type = 'phpvals';
 // let code exceptions float all the way to the remote caller as xml-rpc faults - it helps debugging
 $srv->exception_handling = 1;
 
+// NB: take care not to output anything else after this call, as it will mess up the responses and it will be hard to
+// debug. In case you have to do so, at least re-emit a correct Content-Length http header (requires output buffering)
 $srv->service();
index dededd8..cdb0e9b 100644 (file)
@@ -5,7 +5,19 @@
  * To use this, use something akin to:
  * $signatures = include('functions.php');
  *
- * Simplest possible way to implement webservices: create xml-rpc-aware php functions in the global namespace
+ * Demoes a simple possible way to implement webservices without cluttering the global scope: create xml-rpc-aware static
+ * methods in a class, and use them for the Server's dispatch map without the need to instantiate an object.
+ *
+ * Alternative implementation strategies are possible as well:
+ * 1. same as above, but use non-static class methods
+ * 2. define functions in the global scope to be used as xml-rpc method handlers: see interop.php, validator1.php
+ * 3. define xml-rpc method handlers as anonymous functions directly within the dispatch map
+ * 4. use php methods or functions which are not aware of xml-rpc and let the Server do all the necessary type conversion:
+ *    see discuss.php
+ * 5. use the PhpXmlRpc\Wrapper class to achieve the same as in point 4, with no need to manually write the dispatch map
+ *    configuration (but taking instead a performance hit)
+ * 6. use the PhpXmlRpc\Wrapper class to generate php code in offline mode, achieving the same as in point 5 with no
+ *    performance hit at runtime
  */
 
 use PhpXmlRpc\Encoder;
@@ -13,317 +25,286 @@ use PhpXmlRpc\Response;
 use PhpXmlRpc\Server;
 use PhpXmlRpc\Value;
 
-// a PHP version of the state-number server
-// send me an integer and I'll sell you a state
-
-$GLOBALS['stateNames'] = array(
-    "Alabama", "Alaska", "Arizona", "Arkansas", "California",
-    "Colorado", "Columbia", "Connecticut", "Delaware", "Florida",
-    "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas",
-    "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan",
-    "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada",
-    "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina",
-    "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island",
-    "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont",
-    "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming",
-);
-
-$findstate_sig = array(array(Value::$xmlrpcString, Value::$xmlrpcInt));
-$findstate_doc = 'When passed an integer between 1 and 51 returns the name of a US state, where the integer is the ' .
-    'index of that state name in an alphabetic order.';
-function findState($req)
-{
-    $err = "";
-    // get the first param
-    $sno = $req->getParam(0);
-
-    // param must be there and of the correct type: server object does the validation for us
-
-    // extract the value of the state number
-    $snv = $sno->scalarval();
-    // look it up in our array (zero-based)
-    if (isset($GLOBALS['stateNames'][$snv - 1])) {
-        $stateName = $GLOBALS['stateNames'][$snv - 1];
-    } else {
-        // not there, so complain
-        $err = "I don't have a state for the index '" . $snv . "'";
-    }
-
-    // if we generated an error, create an error return response
-    if ($err) {
-        return new Response(0, PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser, $err);
-    } else {
-        // otherwise, we create the right response with the state name
-        return new Response(new Value($stateName));
-    }
-}
-
-// Sorting demo
-//
-// send me an array of structs thus:
-//
-// Dave 35
-// Edd  45
-// Fred 23
-// Barney 37
-//
-// and I'll return it to you in sorted order
-
-function agesorter_compare($a, $b)
+class exampleMethods
 {
-    /// @todo move away from usage of globals for such a simple case
-    global $agesorter_arr;
-
-    // don't even ask me _why_ these come padded with hyphens, I couldn't tell you :p
-    $a = str_replace("-", "", $a);
-    $b = str_replace("-", "", $b);
+    public static $stateNames = array(
+        "Alabama", "Alaska", "Arizona", "Arkansas", "California",
+        "Colorado", "Columbia", "Connecticut", "Delaware", "Florida",
+        "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas",
+        "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan",
+        "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada",
+        "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina",
+        "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island",
+        "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont",
+        "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming",
+    );
+
+    public static $findstate_sig = array(array('string', 'int'));
+    public static $findstate_doc = 'When passed an integer between 1 and 51 returns the name of a US state, where the integer is the index of that state name in an alphabetic order.';
+    public static function findState($req)
+    {
+        $err = '';
+
+        // get the first param
+        // param must be there and of the correct type: server object does the validation for us
+        $sno = $req->getParam(0);
+
+        // extract the value of the state number
+        $snv = $sno->scalarval();
+
+        // look it up in our array (zero-based)
+        if (isset(self::$stateNames[$snv - 1])) {
+            $stateName = self::$stateNames[$snv - 1];
+        } else {
+            // not there, so complain
+            $err = "I don't have a state for the index '" . $snv . "'";
+        }
 
-    if ($agesorter_arr[$a] == $agesorter_arr[$b]) {
-        return 0;
+        if ($err != '') {
+            // if we generated an error, create an error return response
+            return new Response(0, PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser, $err);
+        } else {
+            // otherwise, we create the right response with the state name
+            return new Response(new Value($stateName));
+        }
     }
 
-    return ($agesorter_arr[$a] > $agesorter_arr[$b]) ? -1 : 1;
-}
-
-$agesorter_sig = array(array(Value::$xmlrpcArray, Value::$xmlrpcArray));
-$agesorter_doc = 'Send this method an array of [string, int] structs, eg:
+    public static $agesorter_sig = array(array('array', 'array'));
+    public static $agesorter_doc = 'Send this method an array of [string, int] structs, eg:
 <pre>
  Dave   35
  Edd    45
  Fred   23
  Barney 37
 </pre>
-And the array will be returned with the entries sorted by their numbers.
-';
-function ageSorter($req)
-{
-    global $agesorter_arr;
-
-    Server::xmlrpc_debugmsg("Entering 'agesorter'");
-    // get the parameter
-    $sno = $req->getParam(0);
-    // error string for [if|when] things go wrong
-    $err = "";
-    $agar = array();
-
-    $max = $sno->count();
-    Server::xmlrpc_debugmsg("Found $max array elements");
-    foreach ($sno as $i => $rec) {
-        if ($rec->kindOf() != "struct") {
-            $err = "Found non-struct in array at element $i";
-            break;
+And the array will be returned with the entries sorted by their numbers.';
+    public static function ageSorter($req)
+    {
+        Server::xmlrpc_debugmsg("Entering 'agesorter'");
+
+        // error string for [if|when] things go wrong
+        $err = '';
+
+        // get the parameter, turn it into an easy-to-manipulate php array
+        $enc = new Encoder();
+        $v = $enc->decode($req->getParam(0));
+
+        $max = count($v);
+        Server::xmlrpc_debugmsg("Found $max array elements");
+
+        // extract name and age from struct. The values nested inside it were not type-checked, so we do it
+        $agar = array();
+        foreach ($v as $i => $rec) {
+            if (!is_array($rec)) {
+                $err = "Found non-struct in array at element $i";
+                break;
+            }
+            if (!isset($rec['name']) || !isset($rec['age'])) {
+                Server::xmlrpc_debugmsg("Invalid array element $i: miss name or age");
+                continue;
+            }
+            $agar[$rec["name"]] = $rec["age"];
         }
-        // extract name and age from struct
-        $n = $rec["name"];
-        $a = $rec["age"];
-        // $n and $a are Values,
-        // so get the scalarval from them
-        $agar[$n->scalarval()] = $a->scalarval();
-    }
 
-    // create the output value
-    $v = new Value(array(), Value::$xmlrpcArray);
-
-    $agesorter_arr = $agar;
-    // hack, must make global as uksort() won't
-    // allow us to pass any other auxiliary information
-    uksort($agesorter_arr, 'agesorter_compare');
-    foreach($agesorter_arr as $key => $val) {
-        // recreate each struct element
-        $v[] = new Value(
-            array(
-                "name" => new Value($key),
-                "age" => new Value($val, "int")
-            ),
-            Value::$xmlrpcStruct
-        );
-    }
+        if ($err != '') {
+            Server::xmlrpc_debugmsg("Aborting 'agesorter'");
+            return new Response(0, PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser, $err);
+        }
 
-    if ($err) {
-        return new Response(0, PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser, $err);
-    } else {
-        return new Response($v);
-    }
-}
+        asort($agar);
 
-$addtwo_sig = array(array(Value::$xmlrpcInt, Value::$xmlrpcInt, Value::$xmlrpcInt));
-$addtwo_doc = 'Add two integers together and return the result';
-function addTwo($req)
-{
-    $s = $req->getParam(0);
-    $t = $req->getParam(1);
+        // create the output value
+        $o = array();
+        foreach ($agar as $name => $age) {
+            $o[] = array("name" => $name, "age" => $age);
+        }
 
-    return new Response(new Value($s->scalarval() + $t->scalarval(), Value::$xmlrpcInt));
-}
+        Server::xmlrpc_debugmsg("Leaving 'agesorter'");
 
-$addtwodouble_sig = array(array(Value::$xmlrpcDouble, Value::$xmlrpcDouble, Value::$xmlrpcDouble));
-$addtwodouble_doc = 'Add two doubles together and return the result';
-function addTwoDouble($req)
-{
-    $s = $req->getParam(0);
-    $t = $req->getParam(1);
+        return new Response($enc->encode($o));
+    }
 
-    return new Response(new Value($s->scalarval() + $t->scalarval(), Value::$xmlrpcDouble));
-}
+    public static $addtwo_sig = array(array('int', 'int', 'int'));
+    public static $addtwo_doc = 'Add two integers together and return the result';
+    public static function addTwo($req)
+    {
+        $s = $req->getParam(0);
+        $t = $req->getParam(1);
 
-$stringecho_sig = array(array(Value::$xmlrpcString, Value::$xmlrpcString));
-$stringecho_doc = 'Accepts a string parameter, returns the string.';
-function stringEcho($req)
-{
-    // just sends back a string
-    return new Response(new Value($req->getParam(0)->scalarval()));
-}
+        return new Response(new Value($s->scalarval() + $t->scalarval(), Value::$xmlrpcInt));
+    }
 
-$echoback_sig = array(array(Value::$xmlrpcString, Value::$xmlrpcString));
-$echoback_doc = 'Accepts a string parameter, returns the entire incoming payload';
-function echoBack($req)
-{
-    // just sends back a string with what i got sent to me, just escaped, that's all
-    $s = "I got the following message:\n" . $req->serialize();
+    public static $addtwodouble_sig = array(array('double', 'double', 'double'));
+    public static $addtwodouble_doc = 'Add two doubles together and return the result';
+    public static function addTwoDouble($req)
+    {
+        $s = $req->getParam(0);
+        $t = $req->getParam(1);
 
-    return new Response(new Value($s));
-}
+        return new Response(new Value($s->scalarval() + $t->scalarval(), Value::$xmlrpcDouble));
+    }
 
-$echosixtyfour_sig = array(array(Value::$xmlrpcString, Value::$xmlrpcBase64));
-$echosixtyfour_doc = 'Accepts a base64 parameter and returns it decoded as a string';
-function echoSixtyFour($req)
-{
-    // Accepts an encoded value, but sends it back as a normal string.
-    // This is to test that base64 encoding is working as expected
-    $incoming = $req->getParam(0);
+    public static $stringecho_sig = array(array('string', 'string'));
+    public static $stringecho_doc = 'Accepts a string parameter, returns the string.';
+    function stringEcho($req)
+    {
+        // just sends back a string
+        return new Response(new Value($req->getParam(0)->scalarval()));
+    }
 
-    return new Response(new Value($incoming->scalarval(), Value::$xmlrpcString));
-}
+    public static $echoback_sig = array(array('string', 'string'));
+    public static $echoback_doc = 'Accepts a string parameter, returns the entire incoming payload';
+    function echoBack($req)
+    {
+        // just sends back a string with what I got sent to me, that's all (escaping for xml is automatic)
+        $s = "I got the following message:\n" . $req->serialize();
 
-$bitflipper_sig = array(array(Value::$xmlrpcArray, Value::$xmlrpcArray));
-$bitflipper_doc = 'Accepts an array of booleans, and returns them inverted';
-function bitFlipper($req)
-{
-    $v = $req->getParam(0);
-    $rv = new Value(array(), Value::$xmlrpcArray);
+        return new Response(new Value($s));
+    }
 
-    foreach ($v as $b) {
-        if ($b->scalarval()) {
-            $rv[] = new Value(false, Value::$xmlrpcBoolean);
-        } else {
-            $rv[] = new Value(true, Value::$xmlrpcBoolean);
-        }
+    public static $echosixtyfour_sig = array(array('string', 'base64'));
+    public static $echosixtyfour_doc = 'Accepts a base64 parameter and returns it decoded as a string';
+    function echoSixtyFour($req)
+    {
+        // Accepts an encoded value, but sends it back as a normal string.
+        // This is to test that base64 encoding is working as expected
+        $incoming = $req->getParam(0);
+
+        return new Response(new Value($incoming->scalarval(), Value::$xmlrpcString));
     }
 
-    return new Response($rv);
-}
+    public static $bitflipper_sig = array(array('array', 'array'));
+    public static $bitflipper_doc = 'Accepts an array of booleans, and returns them inverted';
+    function bitFlipper($req)
+    {
+        $v = $req->getParam(0);
+        $rv = new Value(array(), Value::$xmlrpcArray);
+
+        foreach ($v as $b) {
+            if ($b->scalarval()) {
+                $rv[] = new Value(false, Value::$xmlrpcBoolean);
+            } else {
+                $rv[] = new Value(true, Value::$xmlrpcBoolean);
+            }
+        }
 
+        return new Response($rv);
+    }
 
-$mailsend_sig = array(array(
-    Value::$xmlrpcBoolean, Value::$xmlrpcString, Value::$xmlrpcString,
-    Value::$xmlrpcString, Value::$xmlrpcString, Value::$xmlrpcString,
-    Value::$xmlrpcString, Value::$xmlrpcString,
-));
-$mailsend_doc = 'mail.send(recipient, subject, text, sender, cc, bcc, mimetype)<br/>
+    public static $mailsend_sig = array(array(
+        'boolean', 'string', 'string',
+        'string', 'string', 'string',
+        'string', 'string',
+    ));
+    public static $mailsend_doc = 'mail.send(recipient, subject, text, sender, cc, bcc, mimetype)<br/>
 recipient, cc, and bcc are strings, comma-separated lists of email addresses, as described above.<br/>
 subject is a string, the subject of the message.<br/>
 sender is a string, it\'s the email address of the person sending the message. This string can not be
 a comma-separated list, it must contain a single email address only.<br/>
 text is a string, it contains the body of the message.<br/>
-mimetype, a string, is a standard MIME type, for example, text/plain.
-';
-// WARNING; this functionality depends on the sendmail -t option
-// it may not work with Windows machines properly; particularly
-// the Bcc option. Sneak on your friends at your own risk!
-function mailSend($req)
-{
-    $err = "";
-
-    $mTo = $req->getParam(0);
-    $mSub = $req->getParam(1);
-    $mBody = $req->getParam(2);
-    $mFrom = $req->getParam(3);
-    $mCc = $req->getParam(4);
-    $mBcc = $req->getParam(5);
-    $mMime = $req->getParam(6);
-
-    if ($mTo->scalarval() == "") {
-        $err = "Error, no 'To' field specified";
-    }
+mimetype, a string, is a standard MIME type, for example, text/plain.';
+    /**
+     * WARNING: this functionality depends on the sendmail -t option, it may not work with Windows machines properly;
+     * particularly the Bcc option.
+     * Sneak on your friends at your own risk!
+     */
+    public static function mailSend($req)
+    {
+        $err = "";
+
+        $mTo = $req->getParam(0);
+        $mSub = $req->getParam(1);
+        $mBody = $req->getParam(2);
+        $mFrom = $req->getParam(3);
+        $mCc = $req->getParam(4);
+        $mBcc = $req->getParam(5);
+        $mMime = $req->getParam(6);
+
+        if ($mTo->scalarval() == "") {
+            $err = "Error, no 'To' field specified";
+        }
 
-    if ($mFrom->scalarval() == "") {
-        $err = "Error, no 'From' field specified";
-    }
+        if ($mFrom->scalarval() == "") {
+            $err = "Error, no 'From' field specified";
+        }
 
-    $msgHdr = "From: " . $mFrom->scalarval() . "\n";
-    $msgHdr .= "To: " . $mTo->scalarval() . "\n";
+        /// @todo in real life, we should check for presence of return characters to avoid header injection!
 
-    if ($mCc->scalarval() != "") {
-        $msgHdr .= "Cc: " . $mCc->scalarval() . "\n";
-    }
-    if ($mBcc->scalarval() != "") {
-        $msgHdr .= "Bcc: " . $mBcc->scalarval() . "\n";
-    }
-    if ($mMime->scalarval() != "") {
-        $msgHdr .= "Content-type: " . $mMime->scalarval() . "\n";
-    }
-    $msgHdr .= "X-Mailer: XML-RPC for PHP mailer 1.0";
+        $msgHdr = "From: " . $mFrom->scalarval() . "\n";
+        $msgHdr .= "To: " . $mTo->scalarval() . "\n";
 
-    if ($err == "") {
-        if (!mail("", $mSub->scalarval(), $mBody->scalarval(), $msgHdr)
-        ) {
-            $err = "Error, could not send the mail.";
+        if ($mCc->scalarval() != "") {
+            $msgHdr .= "Cc: " . $mCc->scalarval() . "\n";
+        }
+        if ($mBcc->scalarval() != "") {
+            $msgHdr .= "Bcc: " . $mBcc->scalarval() . "\n";
+        }
+        if ($mMime->scalarval() != "") {
+            $msgHdr .= "Content-type: " . $mMime->scalarval() . "\n";
+        }
+        $msgHdr .= "X-Mailer: XML-RPC for PHP mailer 1.0";
+
+        if ($err == "") {
+            if (!mail("", $mSub->scalarval(), $mBody->scalarval(), $msgHdr)) {
+                $err = "Error, could not send the mail.";
+            }
         }
-    }
 
-    if ($err) {
-        return new Response(0, PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser, $err);
-    } else {
-        return new Response(new Value(true, Value::$xmlrpcBoolean));
+        if ($err) {
+            return new Response(0, PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser, $err);
+        } else {
+            return new Response(new Value(true, Value::$xmlrpcBoolean));
+        }
     }
+
 }
 
 return array(
     "examples.getStateName" => array(
-        "function" => "findState",
-        "signature" => $findstate_sig,
-        "docstring" => $findstate_doc,
+        "function" => array("exampleMethods", "findState"),
+        "signature" => exampleMethods::$findstate_sig,
+        "docstring" => exampleMethods::$findstate_doc,
     ),
     "examples.sortByAge" => array(
-        "function" => "ageSorter",
-        "signature" => $agesorter_sig,
-        "docstring" => $agesorter_doc,
+        "function" => array("exampleMethods", "ageSorter"),
+        "signature" => exampleMethods::$agesorter_sig,
+        "docstring" => exampleMethods::$agesorter_doc,
     ),
     "examples.addtwo" => array(
-        "function" => "addTwo",
-        "signature" => $addtwo_sig,
-        "docstring" => $addtwo_doc,
+        "function" => array("exampleMethods", "addTwo"),
+        "signature" => exampleMethods::$addtwo_sig,
+        "docstring" => exampleMethods::$addtwo_doc,
     ),
     "examples.addtwodouble" => array(
-        "function" => "addTwoDouble",
-        "signature" => $addtwodouble_sig,
-        "docstring" => $addtwodouble_doc,
+        "function" => array("exampleMethods", "addTwoDouble"),
+        "signature" => exampleMethods::$addtwodouble_sig,
+        "docstring" => exampleMethods::$addtwodouble_doc,
     ),
     "examples.stringecho" => array(
-        "function" => "stringEcho",
-        "signature" => $stringecho_sig,
-        "docstring" => $stringecho_doc,
+        "function" => array("exampleMethods", "stringEcho"),
+        "signature" => exampleMethods::$stringecho_sig,
+        "docstring" => exampleMethods::$stringecho_doc,
     ),
     "examples.echo" => array(
-        "function" => "echoBack",
-        "signature" => $echoback_sig,
-        "docstring" => $echoback_doc,
+        "function" => array("exampleMethods", "echoBack"),
+        "signature" => exampleMethods::$echoback_sig,
+        "docstring" => exampleMethods::$echoback_doc,
     ),
     "examples.decode64" => array(
-        "function" => "echoSixtyFour",
-        "signature" => $echosixtyfour_sig,
-        "docstring" => $echosixtyfour_doc,
+        "function" => array("exampleMethods", "echoSixtyFour"),
+        "signature" => exampleMethods::$echosixtyfour_sig,
+        "docstring" => exampleMethods::$echosixtyfour_doc,
     ),
     "examples.invertBooleans" => array(
-        "function" => "bitFlipper",
-        "signature" => $bitflipper_sig,
-        "docstring" => $bitflipper_doc,
+        "function" => array("exampleMethods", "bitFlipper"),
+        "signature" => exampleMethods::$bitflipper_sig,
+        "docstring" => exampleMethods::$bitflipper_doc,
     ),
 
     // left in as an example, but disabled by default, to avoid this being abused if left on an open server
     /*"mail.send" => array(
-        "function" => "mailSend",
-        "signature" => $mailsend_sig,
-        "docstring" => $mailsend_doc,
+        "function" => array("exampleMethods", "mailSend"),
+        "signature" => exampleMethods::$mailsend_sig,
+        "docstring" => exampleMethods::$mailsend_doc,
     ),*/
 );
index 54f00d4..345d151 100644 (file)
@@ -45,79 +45,23 @@ $i_echoBase64_doc = "Echoes base64.";
 $i_echoDate_sig = array(array(Value::$xmlrpcDateTime, Value::$xmlrpcDateTime));
 $i_echoDate_doc = "Echoes dateTime.";
 
-function i_echoParam($req)
-{
-    $s = $req->getParam(0);
-
-    return new Response($s);
-}
-
-function i_echoString($req)
-{
-    return i_echoParam($req);
-}
-
-function i_echoInteger($req)
-{
-    return i_echoParam($req);
-}
-
-function i_echoFloat($req)
-{
-    return i_echoParam($req);
-}
-
-function i_echoStruct($req)
-{
-    return i_echoParam($req);
-}
-
-function i_echoStringArray($req)
-{
-    return i_echoParam($req);
-}
-
-function i_echoIntegerArray($req)
-{
-    return i_echoParam($req);
-}
-
-function i_echoFloatArray($req)
-{
-    return i_echoParam($req);
-}
-
-function i_echoStructArray($req)
-{
-    return i_echoParam($req);
-}
-
-function i_echoValue($req)
-{
-    return i_echoParam($req);
-}
+$i_whichToolkit_sig = array(array(Value::$xmlrpcStruct));
+$i_whichToolkit_doc = "Returns a struct containing the following strings: toolkitDocsUrl, toolkitName, toolkitVersion, toolkitOperatingSystem.";
 
-function i_echoBase64($req)
+function i_echoParam($req)
 {
-    return i_echoParam($req);
-}
+    $v = $req->getParam(0);
 
-function i_echoDate($req)
-{
-    return i_echoParam($req);
+    return new Response($v);
 }
 
-$i_whichToolkit_sig = array(array(Value::$xmlrpcStruct));
-$i_whichToolkit_doc = "Returns a struct containing the following strings: toolkitDocsUrl, toolkitName, toolkitVersion, toolkitOperatingSystem.";
-
 function i_whichToolkit($req)
 {
-    global $SERVER_SOFTWARE;
     $ret = array(
         "toolkitDocsUrl" => "https://gggeek.github.io/phpxmlrpc/",
         "toolkitName" => PhpXmlRpc\PhpXmlRpc::$xmlrpcName,
         "toolkitVersion" => PhpXmlRpc\PhpXmlRpc::$xmlrpcVersion,
-        "toolkitOperatingSystem" => isset($SERVER_SOFTWARE) ? $SERVER_SOFTWARE : $_SERVER['SERVER_SOFTWARE'],
+        "toolkitOperatingSystem" => $_SERVER['SERVER_SOFTWARE'],
     );
 
     $encoder = new PhpXmlRpc\Encoder();
@@ -126,57 +70,57 @@ function i_whichToolkit($req)
 
 return array(
     "interopEchoTests.echoString" => array(
-        "function" => "i_echoString",
+        "function" => "i_echoParam",
         "signature" => $i_echoString_sig,
         "docstring" => $i_echoString_doc,
     ),
     "interopEchoTests.echoStringArray" => array(
-        "function" => "i_echoStringArray",
+        "function" => "i_echoParam",
         "signature" => $i_echoStringArray_sig,
         "docstring" => $i_echoStringArray_doc,
     ),
     "interopEchoTests.echoInteger" => array(
-        "function" => "i_echoInteger",
+        "function" => "i_echoParam",
         "signature" => $i_echoInteger_sig,
         "docstring" => $i_echoInteger_doc,
     ),
     "interopEchoTests.echoIntegerArray" => array(
-        "function" => "i_echoIntegerArray",
+        "function" => "i_echoParam",
         "signature" => $i_echoIntegerArray_sig,
         "docstring" => $i_echoIntegerArray_doc,
     ),
     "interopEchoTests.echoFloat" => array(
-        "function" => "i_echoFloat",
+        "function" => "i_echoParam",
         "signature" => $i_echoFloat_sig,
         "docstring" => $i_echoFloat_doc,
     ),
     "interopEchoTests.echoFloatArray" => array(
-        "function" => "i_echoFloatArray",
+        "function" => "i_echoParam",
         "signature" => $i_echoFloatArray_sig,
         "docstring" => $i_echoFloatArray_doc,
     ),
     "interopEchoTests.echoStruct" => array(
-        "function" => "i_echoStruct",
+        "function" => "i_echoParam",
         "signature" => $i_echoStruct_sig,
         "docstring" => $i_echoStruct_doc,
     ),
     "interopEchoTests.echoStructArray" => array(
-        "function" => "i_echoStructArray",
+        "function" => "i_echoParam",
         "signature" => $i_echoStructArray_sig,
         "docstring" => $i_echoStructArray_doc,
     ),
     "interopEchoTests.echoValue" => array(
-        "function" => "i_echoValue",
+        "function" => "i_echoParam",
         "signature" => $i_echoValue_sig,
         "docstring" => $i_echoValue_doc,
     ),
     "interopEchoTests.echoBase64" => array(
-        "function" => "i_echoBase64",
+        "function" => "i_echoParam",
         "signature" => $i_echoBase64_sig,
         "docstring" => $i_echoBase64_doc,
     ),
     "interopEchoTests.echoDate" => array(
-        "function" => "i_echoDate",
+        "function" => "i_echoParam",
         "signature" => $i_echoDate_sig,
         "docstring" => $i_echoDate_doc,
     ),
index 61b79d0..6b6cd5a 100644 (file)
@@ -92,9 +92,9 @@ return array(
     // Greek word 'kosme'. NB: NOT a valid ISO8859 string!
     // NB: we can only register this when setting internal encoding to UTF-8, or it will break system.listMethods
     "tests.utf8methodname." . 'κόσμε' => array(
-        "function" => "stringEcho",
-        "signature" => $stringecho_sig,
-        //"docstring" => $stringecho_doc,
+        "function" => "exampleMethods::stringEcho",
+        "signature" => exampleMethods::$stringecho_sig,
+        "docstring" => exampleMethods::$stringecho_doc,
     ),
     /*"tests.iso88591methodname." . chr(224) . chr(252) . chr(232) => array(
         "function" => "stringEcho",
@@ -105,6 +105,6 @@ return array(
     'tests.getStateName.12' => array(
         "function" => "findStateWithNulls",
         "signature" => $findstate12_sig,
-        //"docstring" => $findstate_doc,
+        "docstring" => exampleMethods::$findstate_doc,
     ),
 );
index 4024eb6..4dc17aa 100644 (file)
@@ -80,8 +80,7 @@ function v1_moderateSizeArrayCheck($req)
     $first = $ar[0];
     $last = $ar[$sz - 1];
 
-    return new Response(new Value($first->scalarval() .
-        $last->scalarval(), Value::$xmlrpcString));
+    return new Response(new Value($first->scalarval() . $last->scalarval(), Value::$xmlrpcString));
 }
 
 $v1_simpleStructReturn_sig = array(array(Value::$xmlrpcStruct, Value::$xmlrpcInt));
index 488b977..e128ff0 100644 (file)
@@ -26,10 +26,8 @@ use PhpXmlRpc\Value;
  */
 function plain_findstate($stateNo)
 {
-    global $stateNames;
-
-    if (isset($stateNames[$stateNo - 1])) {
-        return $stateNames[$stateNo - 1];
+     if (isset(exampleMethods::$stateNames[$stateNo - 1])) {
+        return exampleMethods::$stateNames[$stateNo - 1];
     } else {
         // not, there so complain
         throw new Exception("I don't have a state for the index '" . $stateNo . "'", PhpXmlRpc\PhpXmlRpc::$xmlrpcerruser);
@@ -46,7 +44,7 @@ $findstate2_sig = $wrapper->wrapPhpFunction('plain_findstate');
 /**
  * Used to test usage of object methods in dispatch maps and in wrapper code.
  */
-class xmlrpcServerMethodsContainer
+class handlersContainer
 {
     /**
      * Method used to test logging of php warnings generated by user functions.
@@ -104,29 +102,29 @@ class xmlrpcServerMethodsContainer
     }
 }
 
-$findstate3_sig = $wrapper->wrapPhpFunction(array('xmlrpcServerMethodsContainer', 'findState'));
+$findstate3_sig = $wrapper->wrapPhpFunction(array('handlersContainer', 'findState'));
 
-$obj = new xmlrpcServerMethodsContainer();
-$findstate4_sig = $wrapper->wrapPhpFunction(array($obj, 'findstate'));
+$instance = new handlersContainer();
+$findstate4_sig = $wrapper->wrapPhpFunction(array($instance, 'findstate'));
 
-$findstate5_sig = $wrapper->wrapPhpFunction('xmlrpcServerMethodsContainer::findState', '', array('return_source' => true));
+$findstate5_sig = $wrapper->wrapPhpFunction('handlersContainer::findState', '', array('return_source' => true));
 eval($findstate5_sig['source']);
 
 $findstate6_sig = $wrapper->wrapPhpFunction('plain_findstate', '', array('return_source' => true));
 eval($findstate6_sig['source']);
 
-$findstate7_sig = $wrapper->wrapPhpFunction(array('xmlrpcServerMethodsContainer', 'findState'), '', array('return_source' => true));
+$findstate7_sig = $wrapper->wrapPhpFunction(array('handlersContainer', 'findState'), '', array('return_source' => true));
 eval($findstate7_sig['source']);
 
-$findstate8_sig = $wrapper->wrapPhpFunction(array($obj, 'findstate'), '', array('return_source' => true));
+$findstate8_sig = $wrapper->wrapPhpFunction(array($instance, 'findstate'), '', array('return_source' => true));
 eval($findstate8_sig['source']);
 
-$findstate9_sig = $wrapper->wrapPhpFunction('xmlrpcServerMethodsContainer::findState', '', array('return_source' => true));
+$findstate9_sig = $wrapper->wrapPhpFunction('handlersContainer::findState', '', array('return_source' => true));
 eval($findstate9_sig['source']);
 
 $findstate10_sig = array(
     /// @todo add a demo and test with closure usage
-    "function" => function ($req) { return findState($req); },
+    "function" => function ($req) { return exampleMethods::findState($req); },
     "signature" => array(array(Value::$xmlrpcString, Value::$xmlrpcInt)),
     "docstring" => 'When passed an integer between 1 and 51 returns the name of a US state, where the integer is the ' .
         'index of that state name in an alphabetic order.',
@@ -135,7 +133,7 @@ $findstate10_sig = array(
 $findstate11_sig = $wrapper->wrapPhpFunction(function ($stateNo) { return plain_findstate($stateNo); });
 
 /// @todo do we really need a new instance ?
-$c = new xmlrpcServerMethodsContainer();
+$c = new handlersContainer();
 
 $moreSignatures = $wrapper->wrapPhpClass($c, array('prefix' => 'tests.', 'method_type' => 'all'));
 
@@ -163,11 +161,11 @@ return array_merge(
         'tests.returnPhpObject' => $returnObj_sig,
         // signature omitted on purpose
         "tests.generatePHPWarning" => array(
-            "function" => array($obj, "phpWarningGenerator"),
+            "function" => array($instance, "phpWarningGenerator"),
         ),
         // signature omitted on purpose
         "tests.raiseException" => array(
-            "function" => array($obj, "exceptionGenerator"),
+            "function" => array($instance, "exceptionGenerator"),
         ),
     )
 );
index 93691b6..4177927 100644 (file)
 require_once __DIR__ . "/_prepend.php";
 
 use PhpXmlRpc\PhpXmlRpc;
-use PhpXmlRpc\Response;
 use PhpXmlRpc\Server;
-use PhpXmlRpc\Value;
 
 // Most of the code used to implement the webservices, and their signatures, are stowed away in neatly organized files,
 // each demoing a different topic
 
-// The simplest way of implementing webservices: as xml-rpc-aware global functions
+// One of the simplest way of implementing webservices: as xml-rpc-aware methods of a php object
 $signatures1 = include(__DIR__.'/methodProviders/functions.php');
 
-// Definitions of webservices used for interoperability testing
+// Even simpler? webservices defined using php functions in the global scope: definitions of webservices used for
+// interoperability testing
 $signatures2 = include(__DIR__.'/methodProviders/interop.php');
 $signatures3 = include(__DIR__.'/methodProviders/validator1.php');
 
-// And finally a few examples inline
-/// @todo bring back a few, basic examples here
-$signatures = array();
+// See also discuss.php for a different take: implementing webservices out of php code which is not aware of xml-rpc
 
-$signatures = array_merge($signatures, $signatures1, $signatures2, $signatures3);
+$signatures = array_merge($signatures1, $signatures2, $signatures3);
 
-if (defined('TESTMODE')) {
+if (defined('TESTMODE') || true) {
     // Webservices used only by the testsuite - do not use them in production
     $signatures4 = include(__DIR__.'/methodProviders/testsuite.php');
     $signatures5 = include(__DIR__.'/methodProviders/wrapper.php');
index 23e8094..7b3f721 100644 (file)
@@ -271,8 +271,8 @@ class ServerTest extends PhpXmlRpc_PolyfillTestCase
         // (used on the server side) sort it out
         $this->addQueryParams(array('DETECT_ENCODINGS' => array('EUC-JP', 'UTF-8')));
         $v = $this->send(mb_convert_encoding($str, 'EUC-JP', 'UTF-8'));
-        $this->assertEquals($sendString, $v->scalarval());
         PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'ISO-8859-1';
+        $this->assertEquals($sendString, $v->scalarval());
     }
 
     public function testExoticCharsetsRequests3()
@@ -319,10 +319,10 @@ class ServerTest extends PhpXmlRpc_PolyfillTestCase
             new xmlrpcval('hello')
         ));
         $v = $this->send($m);
+        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'ISO-8859-1';
         if ($v) {
             $this->assertEquals('hello', $v->scalarval());
         }
-        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'ISO-8859-1';
     }
 
     public function testAddingDoubles()
@@ -830,7 +830,7 @@ And turned it into nylon';
 
     public function testServerWrappedClass()
     {
-        $m = new xmlrpcmsg('tests.xmlrpcServerMethodsContainer.findState', array(
+        $m = new xmlrpcmsg('tests.handlersContainer.findState', array(
             new xmlrpcval(23, 'int'),
         ));
         $v = $this->send($m);
@@ -1008,7 +1008,7 @@ And turned it into nylon';
 
     public function testServerComments()
     {
-        $m = new xmlrpcmsg('tests.xmlrpcServerMethodsContainer.debugMessageGenerator', array(
+        $m = new xmlrpcmsg('tests.handlersContainer.debugMessageGenerator', array(
             new xmlrpcval('hello world', 'string'),
         ));
         $r = $this->send($m, 0, true);