From 2c1080ef778df76820d7671ccd6de982058d5246 Mon Sep 17 00:00:00 2001
From: Marina Glancy <marina@moodle.com>
Date: Wed, 6 Sep 2017 14:32:32 +0800
Subject: [PATCH] MDL-60091 webservice: enhancements to WS test client

---
 admin/webservice/testclient.php       |   4 +-
 admin/webservice/testclient_forms.php | 268 +++++++++++++++-----------
 webservice/upgrade.txt                |   3 +
 3 files changed, 164 insertions(+), 111 deletions(-)

diff --git a/admin/webservice/testclient.php b/admin/webservice/testclient.php
index 444e384fd97..e56c325f12f 100644
--- a/admin/webservice/testclient.php
+++ b/admin/webservice/testclient.php
@@ -54,7 +54,7 @@ foreach ($allfunctions as $f) {
         //some plugins may want to have own test client forms
         include_once($CFG->dirroot.'/'.$finfo->testclientpath);
     }
-    $class = $f->name.'_form';
+    $class = $f->name.'_testclient_form';
     if (class_exists($class)) {
         $functions[$f->name] = $f->name;
         continue;
@@ -103,7 +103,7 @@ if (!$function or !$protocol) {
     die;
 }
 
-$class = $function.'_form';
+$class = $function.'_testclient_form';
 
 $mform = new $class(null, array('authmethod' => $authmethod));
 $mform->set_data(array('function'=>$function, 'protocol'=>$protocol));
diff --git a/admin/webservice/testclient_forms.php b/admin/webservice/testclient_forms.php
index b01b78bb746..9f89f309070 100644
--- a/admin/webservice/testclient_forms.php
+++ b/admin/webservice/testclient_forms.php
@@ -29,19 +29,23 @@ class webservice_test_client_form extends moodleform {
 // === Test client forms ===
 
 /**
- * Form class for create_categories() web service function test.
+ * Base class for implementations of WS test client forms.
  *
  * @package   core_webservice
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- * @copyright 2012 Fabio Souto
+ * @copyright 2017 Marina Glancy
  */
-class core_course_create_categories_form extends moodleform {
+abstract class webservice_test_client_base_form extends moodleform {
+
+    /**
+     * Definition of the parameters used by this WS function
+     */
+    protected abstract function test_client_definition();
+
     /**
      * The form definition.
      */
     public function definition() {
-        global $CFG;
-
         $mform = $this->_form;
 
         $mform->addElement('header', 'wstestclienthdr', get_string('testclient', 'webservice'));
@@ -59,19 +63,7 @@ class core_course_create_categories_form extends moodleform {
         }
 
         $mform->addElement('hidden', 'authmethod', $data['authmethod']);
-        $mform->setType('authmethod', core_user::get_property_type('auth'));
-        $mform->addElement('text', 'name[0]', 'name[0]');
-        $mform->addElement('text', 'parent[0]', 'parent[0]');
-        $mform->addElement('text', 'idnumber[0]', 'idnumber[0]');
-        $mform->addElement('text', 'description[0]', 'description[0]');
-        $mform->addElement('text', 'name[1]', 'name[1]');
-        $mform->addElement('text', 'parent[1]', 'parent[1]');
-        $mform->addElement('text', 'idnumber[1]', 'idnumber[1]');
-        $mform->addElement('text', 'description[1]', 'description[1]');
-        $mform->setType('name', core_user::get_property_type('firstname'));
-        $mform->setType('parent', core_user::get_property_type('id'));
-        $mform->setType('idnumber', core_user::get_property_type('idnumber'));
-        $mform->setType('description', core_user::get_property_type('description'));
+        $mform->setType('authmethod', PARAM_ALPHA);
 
         $mform->addElement('hidden', 'function');
         $mform->setType('function', PARAM_PLUGIN);
@@ -79,6 +71,8 @@ class core_course_create_categories_form extends moodleform {
         $mform->addElement('hidden', 'protocol');
         $mform->setType('protocol', PARAM_ALPHA);
 
+        $this->test_client_definition();
+
         $this->add_action_buttons(true, get_string('execute', 'webservice'));
     }
 
@@ -90,19 +84,51 @@ class core_course_create_categories_form extends moodleform {
         if (!$data = $this->get_data()) {
             return null;
         }
-        // Remove unused from form data.
-        unset($data->submitbutton);
-        unset($data->protocol);
-        unset($data->function);
-        unset($data->wsusername);
-        unset($data->wspassword);
-        unset($data->token);
-        unset($data->authmethod);
+        return array_diff_key((array)$data, ['submitbutton' => 1, 'protocol' => 1, 'function' => 1,
+            'wsusername' => 1, 'wspassword' => 1, 'token' => 1, 'authmethod' => 1]);
+    }
+}
+
+/**
+ * Form class for create_categories() web service function test.
+ *
+ * @package   core_webservice
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @copyright 2012 Fabio Souto
+ */
+class core_course_create_categories_testclient_form extends webservice_test_client_base_form {
+    /**
+     * The form definition.
+     */
+    protected function test_client_definition() {
+        $mform = $this->_form;
+        $mform->addElement('text', 'name[0]', 'name[0]');
+        $mform->addElement('text', 'parent[0]', 'parent[0]');
+        $mform->addElement('text', 'idnumber[0]', 'idnumber[0]');
+        $mform->addElement('text', 'description[0]', 'description[0]');
+        $mform->addElement('text', 'name[1]', 'name[1]');
+        $mform->addElement('text', 'parent[1]', 'parent[1]');
+        $mform->addElement('text', 'idnumber[1]', 'idnumber[1]');
+        $mform->addElement('text', 'description[1]', 'description[1]');
+        $mform->setType('name', PARAM_TEXT);
+        $mform->setType('parent', PARAM_INT);
+        $mform->setType('idnumber', PARAM_RAW);
+        $mform->setType('description', PARAM_RAW);
+    }
+
+    /**
+     * Get the parameters that the user submitted using the form.
+     * @return array|null
+     */
+    public function get_params() {
+        if (!$data = $this->get_data()) {
+            return null;
+        }
 
         $params = array();
         $params['categories'] = array();
         for ($i=0; $i<10; $i++) {
-            if (empty($data->name[$i]) or empty($data->parent[$i])) {
+            if (empty($data->name[$i])) {
                 continue;
             }
             $params['categories'][] = array('name'=>$data->name[$i], 'parent'=>$data->parent[$i],
@@ -119,48 +145,21 @@ class core_course_create_categories_form extends moodleform {
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @copyright 2012 Fabio Souto
  */
-class core_course_delete_categories_form extends moodleform {
+class core_course_delete_categories_testclient_form extends webservice_test_client_base_form {
     /**
      * The form definition.
      */
-    public function definition() {
-        global $CFG;
-
+    protected function test_client_definition() {
         $mform = $this->_form;
-
-        $mform->addElement('header', 'wstestclienthdr', get_string('testclient', 'webservice'));
-
-        // Note: these values are intentionally PARAM_RAW - we want users to test any rubbish as parameters.
-        $data = $this->_customdata;
-        if ($data['authmethod'] == 'simple') {
-            $mform->addElement('text', 'wsusername', 'wsusername');
-            $mform->setType('wsusername', core_user::get_property_type('username'));
-            $mform->addElement('text', 'wspassword', 'wspassword');
-            $mform->setType('wspassword', core_user::get_property_type('password'));
-        } else if ($data['authmethod'] == 'token') {
-            $mform->addElement('text', 'token', 'token');
-            $mform->setType('token', PARAM_RAW_TRIMMED);
-        }
-
-        $mform->addElement('hidden', 'authmethod', $data['authmethod']);
-        $mform->setType('authmethod', core_user::get_property_type('auth'));
         $mform->addElement('text', 'id[0]', 'id[0]');
         $mform->addElement('text', 'newparent[0]', 'newparent[0]');
         $mform->addElement('text', 'recursive[0]', 'recursive[0]');
         $mform->addElement('text', 'id[1]', 'id[1]');
         $mform->addElement('text', 'newparent[1]', 'newparent[1]');
         $mform->addElement('text', 'recursive[1]', 'recursive[1]');
-        $mform->setType('id', core_user::get_property_type('id'));
+        $mform->setType('id', PARAM_INT);
         $mform->setType('newparent', PARAM_INT);
         $mform->setType('recursive', PARAM_BOOL);
-
-        $mform->addElement('hidden', 'function');
-        $mform->setType('function', PARAM_PLUGIN);
-
-        $mform->addElement('hidden', 'protocol');
-        $mform->setType('protocol', PARAM_ALPHA);
-
-        $this->add_action_buttons(true, get_string('execute', 'webservice'));
     }
 
     /**
@@ -171,15 +170,6 @@ class core_course_delete_categories_form extends moodleform {
         if (!$data = $this->get_data()) {
             return null;
         }
-        // Remove unused from form data.
-        unset($data->submitbutton);
-        unset($data->protocol);
-        unset($data->function);
-        unset($data->wsusername);
-        unset($data->wspassword);
-        unset($data->token);
-        unset($data->authmethod);
-
         $params = array();
         $params['categories'] = array();
         for ($i=0; $i<10; $i++) {
@@ -207,31 +197,12 @@ class core_course_delete_categories_form extends moodleform {
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @copyright 2012 Fabio Souto
  */
-class core_course_update_categories_form extends moodleform {
+class core_course_update_categories_testclient_form extends webservice_test_client_base_form {
     /**
      * The form definition.
      */
-    public function definition() {
-        global $CFG;
-
+    protected function test_client_definition() {
         $mform = $this->_form;
-
-        $mform->addElement('header', 'wstestclienthdr', get_string('testclient', 'webservice'));
-
-        // Note: these values are intentionally PARAM_RAW - we want users to test any rubbish as parameters.
-        $data = $this->_customdata;
-        if ($data['authmethod'] == 'simple') {
-            $mform->addElement('text', 'wsusername', 'wsusername');
-            $mform->setType('wsusername', core_user::get_property_type('username'));
-            $mform->addElement('text', 'wspassword', 'wspassword');
-            $mform->setType('wspassword', core_user::get_property_type('password'));
-        } else if ($data['authmethod'] == 'token') {
-            $mform->addElement('text', 'token', 'token');
-            $mform->setType('token', PARAM_RAW_TRIMMED);
-        }
-
-        $mform->addElement('hidden', 'authmethod', $data['authmethod']);
-        $mform->setType('authmethod', core_user::get_property_type('auth'));
         $mform->addElement('text', 'id[0]', 'id[0]');
         $mform->addElement('text', 'name[0]', 'name[0]');
         $mform->addElement('text', 'parent[0]', 'parent[0]');
@@ -242,19 +213,11 @@ class core_course_update_categories_form extends moodleform {
         $mform->addElement('text', 'parent[1]', 'parent[1]');
         $mform->addElement('text', 'idnumber[1]', 'idnumber[1]');
         $mform->addElement('text', 'description[1]', 'description[1]');
-        $mform->setType('id', core_user::get_property_type('id'));
-        $mform->setType('name', core_user::get_property_type('firstname'));
+        $mform->setType('id', PARAM_INT);
+        $mform->setType('name', PARAM_TEXT);
         $mform->setType('parent', PARAM_INT);
-        $mform->setType('idnumber', core_user::get_property_type('idnumber'));
-        $mform->setType('description', core_user::get_property_type('description'));
-
-        $mform->addElement('hidden', 'function');
-        $mform->setType('function', PARAM_PLUGIN);
-
-        $mform->addElement('hidden', 'protocol');
-        $mform->setType('protocol', PARAM_ALPHA);
-
-        $this->add_action_buttons(true, get_string('execute', 'webservice'));
+        $mform->setType('idnumber', PARAM_RAW);
+        $mform->setType('description', PARAM_RAW);
     }
 
     /**
@@ -265,15 +228,6 @@ class core_course_update_categories_form extends moodleform {
         if (!$data = $this->get_data()) {
             return null;
         }
-        // Remove unused from form data.
-        unset($data->submitbutton);
-        unset($data->protocol);
-        unset($data->function);
-        unset($data->wsusername);
-        unset($data->wspassword);
-        unset($data->token);
-        unset($data->authmethod);
-
         $params = array();
         $params['categories'] = array();
         for ($i=0; $i<10; $i++) {
@@ -299,4 +253,100 @@ class core_course_update_categories_form extends moodleform {
         }
         return $params;
     }
-}
\ No newline at end of file
+}
+
+/**
+ * Test class for WS function core_fetch_notifications
+ *
+ * @package   core_webservice
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @copyright 2017 Marina Glancy
+ */
+class core_fetch_notifications_testclient_form extends webservice_test_client_base_form {
+    /**
+     * The form definition.
+     */
+    protected function test_client_definition() {
+        $mform = $this->_form;
+        $mform->addElement('text', 'contextid', 'contextid');
+        $mform->setType('contextid', PARAM_INT);
+        $mform->setDefault('contextid', context_system::instance()->id);
+    }
+}
+
+/**
+ * Test class for WS function get_site_info
+ *
+ * @package   core_webservice
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @copyright 2017 Marina Glancy
+ */
+class core_webservice_get_site_info_testclient_form extends webservice_test_client_base_form {
+    /**
+     * The form definition.
+     */
+    protected function test_client_definition() {
+    }
+}
+
+/**
+ * Test class for WS function core_get_string
+ *
+ * @package   core_webservice
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @copyright 2017 Marina Glancy
+ */
+class core_get_string_testclient_form extends webservice_test_client_base_form {
+    /**
+     * The form definition.
+     */
+    protected function test_client_definition() {
+        $mform = $this->_form;
+        $mform->addElement('text', 'stringid', 'stringid');
+        $mform->setType('stringid', PARAM_STRINGID);
+        $mform->addElement('text', 'component', 'component');
+        $mform->setType('component', PARAM_COMPONENT);
+        $mform->addElement('text', 'lang', 'lang');
+        $mform->setType('lang', PARAM_LANG);
+        $mform->addElement('text', 'stringparams_name[1]', 'Parameter 1 name');
+        $mform->setType('stringparams_name[1]', PARAM_ALPHANUMEXT);
+        $mform->addElement('text', 'stringparams_value[1]', 'Parameter 1 value');
+        $mform->setType('stringparams_value[1]', PARAM_RAW);
+        $mform->addElement('text', 'stringparams_name[2]', 'Parameter 2 name');
+        $mform->setType('stringparams_name[2]', PARAM_ALPHANUMEXT);
+        $mform->addElement('text', 'stringparams_value[2]', 'Parameter 2 value');
+        $mform->setType('stringparams_value[2]', PARAM_RAW);
+        $mform->addElement('text', 'stringparams_name[3]', 'Parameter 3 name');
+        $mform->setType('stringparams_name[3]', PARAM_ALPHANUMEXT);
+        $mform->addElement('text', 'stringparams_value[3]', 'Parameter 3 value');
+        $mform->setType('stringparams_value[3]', PARAM_RAW);
+        $mform->addElement('static', 'paramnote', '', 'If a parameter is not an object, only specify "Parameter 1 value"');
+    }
+
+    /**
+     * Get the parameters that the user submitted using the form.
+     * @return array|null
+     */
+    public function get_params() {
+        $params = parent::get_params();
+        if ($params === null) {
+            return null;
+        }
+
+        $params['stringparams'] = [];
+        for ($idx = 1; $idx <= 3; $idx++) {
+            $name = isset($params['stringparams_name'][$idx]) ? strval($params['stringparams_name'][$idx]) : '';
+            $value = isset($params['stringparams_value'][$idx]) ? strval($params['stringparams_value'][$idx]) : '';
+            if ($name !== '' || $value !== '') {
+                if ($name === '') {
+                    $params['stringparams'][] = ['value' => $value];
+                } else {
+                    $params['stringparams'][] = ['name' => $name, 'value' => $value];
+                }
+            }
+        }
+        unset($params['stringparams_name']);
+        unset($params['stringparams_value']);
+        return $params;
+    }
+}
diff --git a/webservice/upgrade.txt b/webservice/upgrade.txt
index 2301a7c6e24..8867faead4a 100644
--- a/webservice/upgrade.txt
+++ b/webservice/upgrade.txt
@@ -7,6 +7,9 @@ This information is intended for authors of webservices, not people writing webs
 
 * External function core_webservice_external::get_site_info() now returns the calendar type used in the site and
   by the user in the sitecalendartype and usercalendartype fields.
+* Implementations of forms for test clients now must follow naming schema: WSFUNCTIONNAME_testclient_form
+  The old naming schema WSFUNCTIONNAME_form caused conflicts with existing classes.
+  New class webservice_test_client_base_form can be used as a base class for such forms.
 
 === 3.2 ===