]> git.mjollnir.org Git - moodle.git/commitdiff
webservice MDL-20803 add web service documentation generator
authorjerome mouneyrac <jerome@moodle.com>
Sun, 13 Dec 2009 10:48:22 +0000 (10:48 +0000)
committerjerome mouneyrac <jerome@moodle.com>
Sun, 13 Dec 2009 10:48:22 +0000 (10:48 +0000)
group/externallib.php
lang/en_utf8/webservice.php
webservice/wsdoc.php
webservice/wsdocrenderer.php [new file with mode: 0644]

index b3074e9fdcab0146993cb378f42f0c12d24177ce..3dea054d1fe6ec682dad4b7d75196000bb5cd1e2 100644 (file)
@@ -43,7 +43,7 @@ class moodle_group_external extends external_api {
                             'description' => new external_value(PARAM_RAW, 'group description text'),
                             'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
                         )
-                    )
+                    ), 'List of group object. A group has a courseid, a name, a description and an enrolment key.'
                 )
             )
         );
@@ -103,7 +103,7 @@ class moodle_group_external extends external_api {
                     'description' => new external_value(PARAM_RAW, 'group description text'),
                     'enrolmentkey' => new external_value(PARAM_RAW, 'group enrol secret phrase'),
                 )
-            )
+            ), 'List of group object. A group has an id, a courseid, a name, a description and an enrolment key.'
         );
     }
 
@@ -114,7 +114,8 @@ class moodle_group_external extends external_api {
     public static function get_groups_parameters() {
         return new external_function_parameters(
             array(
-                'groupids' => new external_multiple_structure(new external_value(PARAM_INT, 'Group ID')),
+                'groupids' => new external_multiple_structure(new external_value(PARAM_INT, 'Group ID')
+                        ,'List of group id. A group id is an integer.'),
             )
         );
     }
index 5d392f245d9d308b18bdcbc2f95bde028f78968a..ac90f51e2b66b457b718afeefbc2f7124a894223 100644 (file)
@@ -6,12 +6,17 @@ $string['addfunctionhelp'] = 'Select the function to add to the service.';
 $string['addrequiredcapability'] = 'Assign/Unassign the required capability';
 $string['addservice'] = 'Add a new service: $a->name (id: $a->id)';
 $string['actwebserviceshhdr'] = 'Active web service protocols';
+$string['apiexplorer'] = 'API explorer';
+$string['apiexplorernotavalaible'] = 'API explorer not available yet.';
+$string['arguments'] = 'Arguments';
 $string['configwebserviceplugins'] = 'For security reasons enable only protocols that are used.';
 $string['deleteservice'] = 'Delete the service: $a->name (id: $a->id)';
 $string['deleteserviceconfirm'] = 'Do you really want to delete external service \"$a\"?';
 $string['disabledwarning'] = 'All webs service protocols are disabled, the \Enable web services\" setting can be found in the \"Advanced features\" section.';
 $string['editservice'] = 'Edit the service: $a->name (id: $a->id)';
 $string['enabled'] = 'Enabled';
+$string['error'] = 'Error: $a';
+$string['errorcodes'] = 'Error Codes';
 $string['execute'] = 'Execute';
 $string['executewarnign'] = 'WARNING: if you press execute your database will be modified and changes can not be reverted automatically!';
 $string['externalservices'] = 'External services';
@@ -22,15 +27,21 @@ $string['function'] = 'Function';
 $string['functions'] = 'Functions';
 $string['iprestriction'] = 'IP restriction';
 $string['manageprotocols'] = 'Manage protocols';
+$string['noerrorcode'] = 'No error code';
 $string['norequiredcapability'] = 'No required capability';
+$string['optional'] = 'Optional';
 $string['potusers'] = 'Not authorised users';
 $string['potusersmatching'] = 'Not authorised users matching';
 $string['protocol'] = 'Protocol';
 $string['removefunction'] = 'Remove';
 $string['removefunctionconfirm'] = 'Do you really want to remove function \"$a->function\" from service \"$a->service\"?';
+$string['requireauthentication'] = 'This method requires authentication with xxx permission.';
+$string['required'] = 'Required';
 $string['requiredcapability'] = 'Required capability';
-$string['selectedcapabilitydoesntexit'] = 'The currently set required capability ($a) doesn\'t exist anymore. Please change it and save the changes.';
+$string['response'] = 'Response';
+$string['restcode'] = 'REST code';
 $string['restrictedusers'] = 'Authorised users only';
+$string['selectedcapabilitydoesntexit'] = 'The currently set required capability ($a) doesn\'t exist anymore. Please change it and save the changes.';
 $string['selectedcapability'] = 'Selected';
 $string['servicename'] = 'Service name';
 $string['servicesbuiltin'] = 'Built-in services';
@@ -41,3 +52,9 @@ $string['serviceuserssettings'] = 'Change settings for the authorised users';
 $string['testclient'] = 'Web service test client';
 $string['validuntil'] = 'Valid until';
 $string['webservices'] = 'Web services';
+$string['wsdocumentation'] = 'Web service documentation';
+$string['wsdocumentationintro'] = 'Following a listing of web service functions available for the username <b>$a</b>.<br/>In order to create a client we advice you to read the <a href=\"http://docs.moodle.org/en/Development:Creating_a_web_service_and_a_web_service_function#Create_your_own_client\">Moodle documentation</a>';
+$string['wsdocumentationlogin'] = 'Enter your web service username and password.';
+$string['wspassword'] = 'Web service password';
+$string['wsusername'] = 'Web service username';
+$string['xmlrpcstructure'] = 'XML-RPC structure';
index b7d09e2a44c71abf72167f7b46662728dc998716..4e28bef300373e745e174cbf1a14677adf9eb0a8 100644 (file)
 //                                                                       //
 ///////////////////////////////////////////////////////////////////////////
 
-// TODO: this needs to be rewritten to use the new description format
-//       the problem here is that the list of functions is different for each use or even token
-//       I guess this should be moved to server itself and it should require user auth,
-//       SOAP does already support WSDL when parameters &wsdl=1 used
-die('TODO');
 
-/**
- * This file generate a web service documentation in HTML
- * This documentation describe how to call a Moodle Web Service
- */
+// disable moodle specific debug messages and any errors in output
+define('NO_DEBUG_DISPLAY', true);
+define('NO_MOODLE_COOKIES', true);
+
 require_once('../config.php');
+require_once('./wsdocrenderer.php');
 require_once('lib.php');
-$protocol = optional_param('protocol',"soap",PARAM_ALPHA);
-$username = optional_param('username',"",PARAM_ALPHA);
-$password = optional_param('password',"",PARAM_ALPHA);
 
-/// TODO Retrieve user (authentication)
-$user = "";
 
-/// PAGE settings
-$PAGE->set_course($COURSE);
-$PAGE->set_url('webservice/wsdoc.php');
-$PAGE->set_title(get_string('wspagetitle', 'webservice'));
-$PAGE->set_heading(get_string('wspagetitle', 'webservice'));
-$PAGE->set_generaltype("form");
+/**
+ * This class generate the web service documentation specific to one
+ * web service user
+ * @package   webservice
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @author    Jerome Mouneyrac
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class webservice_documentation_generator {
+
+    /** @property array all external function description
+     *  they  */
+    protected $functions;
+
+     /** @property string $username name of local user */
+    protected $username = null;
 
-// Display the documentation
-echo $OUTPUT->header();
-generate_documentation($protocol); //documentation relatif to the protocol
-generate_functionlist($protocol, $user); //documentation relatif to the available function
-echo $OUTPUT->footer();
+    /** @property string $password password of the local user */
+    protected $password = null;
 
+    /**
+     * Contructor
+     */
+    public function __construct() {
+        $this->functionsdescriptions = array();
+        $this->functions = array();
+    }
 
-function generate_functionlist($protocol, $user) {
+    /**
+     * Run the documentation generation
+     * @param bool $simple use simple authentication
+     * @return void
+     */
+    public function run() {
 
-    /// retrieve all function that the user can access
-    /// =>
-    /// retrieve all function that are available into enable services that
-    /// have (no restriction user or the user is into the restricted user list)
-    ///      and (no required capability or the user has the required capability)
+        // init all properties from the request data
+        $this->get_authentication_parameters();
 
-        // do SQL request here
+        // this sets up $USER TODO: and $SESSION for the environment.php
+        try {
+            $this->authenticate_user();
+        } catch(moodle_exception $e) {
+            $errormessage = $e->debuginfo;
+            $displayloginpage = true;
+        }
 
-    /// load once all externallib.php of the retrieved functions
+        if (!empty($displayloginpage)){
+            $this->display_login_page_html($errormessage);
+        } else {
+            // make a descriptions list of all function that user is allowed to excecute
+            $this->generate_documentation();
 
-    /// foreach retrieved functions display the description
+            //finally display the documentation
+            $this->display_documentation_html();
+        }
 
-        // in order to display the description we need to use an algo similar to the validation
-        // every time we get a scalar value, we need to convert it into a human readable value as
-        // PARAM_INT => 'integer' or PARAM_TEXT => 'string' or PARAM_BOOL => 'boolean' ...
+        die;
+    }
 
-}
 
+///////////////////////////
+/////// CLASS METHODS /////
+///////////////////////////
 
-/**
- * Generate documentation specific to a protocol
- * @param string $protocol
- */
-function generate_documentation($protocol) {
-    switch ($protocol) {
-
-        case "soap":
-            $documentation = get_string('soapdocumentation','webservice');
-            break;
-        case "xmlrpc":
-            $documentation = get_string('xmlrpcdocumentation','webservice');
-            break;
-        default:
-            break;
+    /**
+     * This method parses the $_REQUEST superglobal and looks for
+     * the following information:
+     *  user authentication - username+password
+     * @return void
+     */
+    protected function get_authentication_parameters() {
+            if (isset($_REQUEST['wsusername'])) {
+                $this->username = $_REQUEST['wsusername'];
+            }
+            if (isset($_REQUEST['wspassword'])) {
+                $this->password = $_REQUEST['wspassword'];
+            }
     }
-    echo $documentation;
-    echo "<strong style=\"color:orange\">".get_string('wsuserreminder','webservice')."</strong>";
 
-}
+    /**
+     * Generate the documentation specific to the auhenticated webservice user
+     * @return void
+     */
+    protected function generate_documentation() {
+        global $USER, $DB;
 
+    /// first of all get a complete list of services user is allowed to access
+        $params = array();
+        $wscond1 = '';
+        $wscond2 = '';
+
+        // make sure the function is listed in at least one service user is allowed to use
+        // allow access only if:
+        //  1/ entry in the external_services_users table if required
+        //  2/ validuntil not reached
+        //  3/ has capability if specified in service desc
+        //  4/ iprestriction
+
+        $sql = "SELECT s.*, NULL AS iprestriction
+                  FROM {external_services} s
+                  JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 0)
+                 WHERE s.enabled = 1 $wscond1
+
+                 UNION
+
+                SELECT s.*, su.iprestriction
+                  FROM {external_services} s
+                  JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 1)
+                  JOIN {external_services_users} su ON (su.externalserviceid = s.id AND su.userid = :userid)
+                 WHERE s.enabled = 1 AND su.validuntil IS NULL OR su.validuntil < :now $wscond2";
+
+        $params = array_merge($params, array('userid'=>$USER->id, 'now'=>time()));
+
+        $serviceids = array();
+        $rs = $DB->get_recordset_sql($sql, $params);
+
+        // make sure user may access at least one service
+        $remoteaddr = getremoteaddr();
+        $allowed = false;
+        foreach ($rs as $service) {
+            if (isset($serviceids[$service->id])) {
+                continue;
+            }
+            if ($service->requiredcapability and !has_capability($service->requiredcapability, $this->restricted_context)) {
+                continue; // cap required, sorry
+            }
+            if ($service->iprestriction and !address_in_subnet($remoteaddr, $service->iprestriction)) {
+                continue; // wrong request source ip, sorry
+            }
+            $serviceids[$service->id] = $service->id;
+        }
+        $rs->close();
+
+        // now get the list of all functions
+        if ($serviceids) {
+            list($serviceids, $params) = $DB->get_in_or_equal($serviceids);
+            $sql = "SELECT f.*
+                      FROM {external_functions} f
+                     WHERE f.name IN (SELECT sf.functionname
+                                        FROM {external_services_functions} sf
+                                       WHERE sf.externalserviceid $serviceids)";
+            $functions = $DB->get_records_sql($sql, $params);
+        } else {
+            $functions = array();
+        }
+
+        foreach ($functions as $function) {
+            $this->functions[$function->name] = external_function_info($function);
+        }
+    }
+
+     /**
+     * Authenticate user using username+password
+     * This function sets up $USER global.
+     * called into the Moodle header
+     * @return void
+     */
+    protected function authenticate_user() {
+        global $CFG, $DB, $USER;
+
+        if (!NO_MOODLE_COOKIES) {
+            throw new coding_exception('Cookies must be disabled!');
+        }
+
+        if (!is_enabled_auth('webservice')) {
+            throw new webservice_access_exception('WS auth not enabled');
+        }
+
+        if (!$auth = get_auth_plugin('webservice')) {
+            throw new webservice_access_exception('WS auth missing');
+        }
+        
+        if (!$this->username) {
+            throw new webservice_access_exception('Missing username');
+        }
+
+        if (!$this->password) {
+            throw new webservice_access_exception('Missing password');
+        }
+
+        if (!$auth->user_login_webservice($this->username, $this->password)) {
+            throw new webservice_access_exception('Wrong username or password');
+        }
+
+        $USER = $DB->get_record('user', array('username'=>$this->username, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0), '*', MUST_EXIST);
+
+
+    }
+
+////////////////////////////////////////////////
+///// DISPLAY METHODS                      /////
+////////////////////////////////////////////////
+
+    /**
+     * Generate and display the documentation
+     */
+    protected function display_documentation_html() {
+        global $PAGE, $OUTPUT, $SITE;
+
+        $PAGE->set_url('/webservice/wsdoc');
+        $PAGE->set_docs_path('');
+        $PAGE->set_title($SITE->fullname." ".get_string('wsdocumentation', 'webservice'));
+        $PAGE->set_heading($SITE->fullname." ".get_string('wsdocumentation', 'webservice'));
+        $PAGE->set_generaltype('popup');
+
+        echo $OUTPUT->header();
+        $renderer = $PAGE->theme->get_renderer('core_wsdoc',$OUTPUT);
+        echo $renderer->documentation_html($this->functions, $this->username);
+        echo $OUTPUT->footer();
+
+    }
+
+    /**
+     * Display login page to the web service documentation
+     * @global <type> $PAGE
+     * @global <type> $OUTPUT
+     * @global <type> $SITE
+     * @global <type> $CFG
+     * @param string $errormessage error message displayed if wrong login
+     */
+     protected function display_login_page_html($errormessage) {
+        global $PAGE, $OUTPUT, $SITE, $CFG;
+
+        $PAGE->set_url('/webservice/wsdoc');
+        $PAGE->set_docs_path('');
+        $PAGE->set_title($SITE->fullname." ".get_string('wsdocumentation', 'webservice'));
+        $PAGE->set_heading($SITE->fullname." ".get_string('wsdocumentation', 'webservice'));
+        $PAGE->set_generaltype('popup');
+
+        echo $OUTPUT->header();
+        $renderer = $PAGE->theme->get_renderer('core_wsdoc',$OUTPUT);
+        echo $renderer->login_page_html($errormessage);
+        echo $OUTPUT->footer();
 
-/**
- * Convert a Moodle type (PARAM_ALPHA, PARAM_NUMBER,...) as a SOAP type (string, interger,...)
- * @param integer $moodleparam
- * @return string  SOAP type
- */
-function converterMoodleParamIntoWsParam($moodleparam) {
-    switch ($moodleparam) {
-        case PARAM_NUMBER:
-            return "integer";
-            break;
-        case PARAM_INT:
-            return "integer";
-            break;
-        case PARAM_BOOL:
-            return "boolean";
-            break;
-        case PARAM_ALPHANUM:
-            return "string";
-            break;
-        case PARAM_ALPHA:
-            return "string";
-            break;
-        case PARAM_RAW:
-            return "string";
-            break;
-        case PARAM_ALPHANUMEXT:
-            return "string";
-            break;
-        case PARAM_NOTAGS:
-            return "string";
-            break;
-        case PARAM_TEXT:
-            return "string";
-            break;
     }
+
 }
+
+
+///////////////////////////
+/////// RUN THE SCRIPT ////
+///////////////////////////
+
+//run the documentation generator
+$generator = new webservice_documentation_generator();
+$generator->run();
+die;
diff --git a/webservice/wsdocrenderer.php b/webservice/wsdocrenderer.php
new file mode 100644 (file)
index 0000000..192637d
--- /dev/null
@@ -0,0 +1,282 @@
+<?php
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// This file is part of Moodle - http://moodle.org/                      //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//                                                                       //
+// Moodle is free software: you can redistribute it and/or modify        //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation, either version 3 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// Moodle is distributed in the hope that it will be useful,             //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details.                          //
+//                                                                       //
+// You should have received a copy of the GNU General Public License     //
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.       //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ * Web service documentation renderer.
+ * @package   webservice
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @author    Jerome Mouneyrac
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+class moodle_core_wsdoc_renderer extends moodle_renderer_base {
+
+    /**
+     * Create documentation for a description object
+     * @param object $params a part of parameter/return description
+     * @return string the html to display
+     */
+    public function detailed_html_description($params) {
+        $paramdesc = "";
+        if (!empty($params->desc)) {
+            $paramdesc = "<span style=\"color:#2A33A6\"><i>//".$params->desc."</i></span><br/>";
+        }
+        if ($params instanceof external_multiple_structure) {
+
+            return $paramdesc."list of ( <br/>". $this->detailed_html_description($params->content).")";
+        } else if ($params instanceof external_single_structure) {
+            //var_dump($params->keys);
+            $singlestructuredesc = $paramdesc."object {<br/>";
+            foreach ($params->keys as $attributname => $attribut) {
+                $singlestructuredesc .= "<b>".$attributname."</b> ".$this->detailed_html_description($params->keys[$attributname]);
+            }
+            $singlestructuredesc .= "} <br/>";
+            return $singlestructuredesc;
+        } else {
+            switch($params->type) {
+                case PARAM_BOOL: // 0 or 1 only for now
+                case PARAM_INT:
+                    $type = 'int';
+                    break;
+                case PARAM_FLOAT;
+                    $type = 'double';
+                    break;
+                default:
+                    $type = 'string';
+            }
+            return $type." ".$paramdesc;
+        }
+
+
+    }
+
+    /**
+     * Create description in indented xml format
+     * It is indented in order to be displayed into <pre> tag
+     * @param object $returndescription
+     * @param string $indentation composed by space only
+     * @return string the html to diplay
+     */
+    public function description_in_indented_xml_format($returndescription, $indentation = "") {
+        $indentation = $indentation . "    ";
+        $brakeline = <<<EOF
+
+
+EOF;
+        if ($returndescription instanceof external_multiple_structure) {
+            $return  = $indentation."<MULTIPLE>".$brakeline;
+            $return .= $this->description_in_indented_xml_format($returndescription->content, $indentation);
+            $return .= $indentation."</MULTIPLE>".$brakeline;
+            return $return;
+        } else if ($returndescription instanceof external_single_structure) {
+            $singlestructuredesc = $indentation."<SINGLE>".$brakeline;
+            $keyindentation = $indentation."    ";
+            foreach ($returndescription->keys as $attributname => $attribut) {
+                $singlestructuredesc .= $keyindentation."<KEY name=\"".$attributname."\">".$brakeline.
+                        $this->description_in_indented_xml_format($returndescription->keys[$attributname], $keyindentation).
+                        $keyindentation."</KEY>".$brakeline;
+            }
+            $singlestructuredesc .= $indentation."</SINGLE>".$brakeline;
+            return $singlestructuredesc;
+        } else {
+            switch($returndescription->type) {
+                case PARAM_BOOL: // 0 or 1 only for now
+                case PARAM_INT:
+                    $type = 'int';
+                    break;
+                case PARAM_FLOAT;
+                    $type = 'double';
+                    break;
+                default:
+                    $type = 'string';
+            }
+            return $indentation."<VALUE>".$type."</VALUE>".$brakeline;
+        }
+    }
+
+    /**
+     * Return the REST response (xml code display in <pre> tag)
+     * @param string $functionname
+     * @param object $returndescription
+     * @return string the html to diplay
+     */
+    public function rest_response_html($functionname, $returndescription) {
+
+        $restresponsehtml = "";
+
+        $restresponsehtml .= "<pre>";
+        $restresponsehtml .= "<div style=\"border:solid 1px #DEDEDE;background:#FEEBE5;color:#222222;padding:4px;\">";
+        $restresponsehtml .= '<b>REST code</b><br/>';
+        $brakeline = <<<EOF
+
+
+EOF;
+        $content  = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>".$brakeline."<RESPONSE>".$brakeline;
+        $content .= $this->description_in_indented_xml_format($returndescription);
+        $content .="</RESPONSE>".$brakeline;
+        $restresponsehtml .= htmlentities($content);
+        $restresponsehtml .= "</div>";
+        $restresponsehtml .= "</pre>";
+        return $restresponsehtml;
+    }
+
+    /**
+     * This display all the documentation
+     * @param array $functions contains all decription objects
+     * @param string $username
+     * @return string the html to diplay
+     */
+    public function documentation_html($functions, $username) {
+
+        $documentationhtml = "";
+
+        $documentationhtml .= "<table style=\"margin-left:auto; margin-right:auto;\"><tr><td>";
+        $documentationhtml .= get_string('wsdocumentationintro', 'webservice', $username);
+        $documentationhtml .= "<br/><br/><br/>";
+
+        foreach ($functions as $functionname => $description) {
+            $documentationhtml .= print_collapsible_region_start('', 'aera_'.$functionname,"<strong>".$functionname."</strong>",false,true,true);
+
+            $documentationhtml .= "<br/>";
+            $documentationhtml .= "<div style=\"border:solid 1px #DEDEDE;background:#E2E0E0;color:#222222;padding:4px;\">";
+            $documentationhtml .= $description->description;
+            $documentationhtml .= "</div>";
+            $documentationhtml .= "<br/><br/>";
+
+            $documentationhtml .= "<span style=\"color:#EA33A6\">Authentication</span><br/>";
+            $documentationhtml .= "<span style=\"font-size:80%\">";
+            $documentationhtml .= get_string('requireauthentication', 'webservice'/*,$description->type*/);
+            $documentationhtml .= "</span>";
+            $documentationhtml .= "<br/><br/>";
+
+            $documentationhtml .= "<span style=\"color:#EA33A6\">".get_string('arguments', 'webservice')."</span><br/>";
+            foreach ($description->parameters_desc->keys as $paramname => $paramdesc) {
+                $documentationhtml .= "<span style=\"font-size:80%\">";
+                $required = $paramdesc->required?get_string('required', 'webservice'):get_string('optional', 'webservice');
+                $documentationhtml .= "<b>".$paramname . "</b> (" .$required. ")<br/>";
+                $documentationhtml .= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;".$paramdesc->desc." <br/><br/>";
+                $documentationhtml .= "<div style=\"border:solid 1px #DEDEDE;background:#FFF1BC;color:#222222;padding:4px;\">";
+                $documentationhtml .= "<pre>";
+                $documentationhtml .= print_collapsible_region_start('', 'aera_'.$functionname."_".$paramname,'<b>'.get_string('xmlrpcstructure', 'webservice').'</b>',false,true,true);
+                //echo '<b>'.get_string('xmlrpcstructure', 'webservice').'</b><br/>';
+                $documentationhtml .= $this->detailed_html_description($paramdesc);
+                $documentationhtml .= print_collapsible_region_end(true);
+                $documentationhtml .= "</pre>";
+                $documentationhtml .= "</div><br/>";
+                $documentationhtml .= "<pre>";
+                $documentationhtml .= "<div style=\"border:solid 1px #DEDEDE;background:#FEEBE5;color:#222222;padding:4px;\">";
+                $documentationhtml .= '<b>'.get_string('restcode', 'webservice').'</b><br/>';
+                $documentationhtml .= htmlentities($this->description_in_indented_xml_format($paramdesc));
+                $documentationhtml .= "</div>";
+                $documentationhtml .= "</pre>";
+                $documentationhtml .= "</span>";
+            }
+            $documentationhtml .= "<br/><br/>";
+
+            $documentationhtml .= "<span style=\"color:#EA33A6\">".get_string('response', 'webservice')."</span><br/>";
+            $documentationhtml .= "<span style=\"font-size:80%\">";
+            if (!empty($description->returns_desc->desc)) {
+                $documentationhtml .= $description->returns_desc->desc."<br/><br/>";
+            }
+
+            if (!empty($description->returns_desc)) {
+                $documentationhtml .= "<div style=\"border:solid 1px #DEDEDE;background:#FFF1BC;color:#222222;padding:4px;\">";
+                $documentationhtml .= "<pre>";
+                $documentationhtml .= print_collapsible_region_start('', 'aera_'.$functionname."_xmlrpc_return",'<b>'.get_string('xmlrpcstructure', 'webservice').'</b>',false,true,true);
+                //echo '<b>'.get_string('xmlrpcstructure', 'webservice').'</b><br/>';
+                $documentationhtml .= $this->detailed_html_description($description->returns_desc);
+                $documentationhtml .= print_collapsible_region_end(true);
+                $documentationhtml .= "</pre>";
+                $documentationhtml .= "</div><br/>";
+                $documentationhtml .=$this->rest_response_html($functionname, $description->returns_desc);
+            }
+            $documentationhtml .= "</span>";
+            $documentationhtml .= "<br/><br/>";
+
+
+
+            $documentationhtml .= "<span style=\"color:#EA33A6\">".get_string('errorcodes', 'webservice')."</span><br/>";
+            $documentationhtml .= "<span style=\"font-size:80%\">";
+            $documentationhtml .= get_string('noerrorcode', 'webservice');
+            $documentationhtml .= "</span>";
+            $documentationhtml .= "<br/><br/>";
+
+
+            $documentationhtml .= "<span style=\"color:#EA33A6\">".get_string('apiexplorer', 'webservice')."</span><br/>";
+            $documentationhtml .= "<span style=\"font-size:80%\">";
+            $documentationhtml .= get_string('apiexplorernotavalaible', 'webservice');
+            $documentationhtml .= "</span>";
+            $documentationhtml .= "<br/><br/>";
+
+            $documentationhtml .= print_collapsible_region_end(true);
+        }
+
+        $documentationhtml .= "</td></tr></table>";
+        return $documentationhtml;
+
+    }
+
+    /**
+     * Return the login page html
+     * @param string $errormessage - the error message to display
+     * @return string the html to diplay
+     */
+    public function login_page_html($errormessage) {
+        global $CFG, $OUTPUT;
+
+        $htmlloginpage = "";
+        $htmlloginpage .= "<table style=\"margin-left:auto; margin-right:auto;\"><tr><td>";
+        $htmlloginpage .= get_string('wsdocumentationlogin', 'webservice');
+        $htmlloginpage .= "<br/><br/><br/>";
+
+//        echo get_string('error','webservice',$errormessage);
+//        echo "<br/><br/>";
+
+        //login form - we cannot use moodle form are we don't have sessionkey
+        $form = new html_form();
+        $form->url = new moodle_url($CFG->wwwroot.'/webservice/wsdoc.php', array()); // Required
+        $form->button = new html_button();
+        $form->button->text = get_string('wsdocumentation','webservice'); // Required
+        $form->button->disabled = false;
+        $form->button->title = get_string('wsdocumentation','webservice');
+        $form->method = 'post';
+
+        $field = new html_field();
+        $field->name = 'wsusername';
+        $field->value = get_string('wsusername', 'webservice');
+        $field->style = 'width: 30em;';
+        $contents = $OUTPUT->textfield($field);
+        $contents .= "<br/><br/>";
+        $field = new html_field();
+        $field->name = 'wspassword';
+        $field->value = get_string('wspassword', 'webservice');
+        $field->style = 'width: 30em;';
+        $contents .= $OUTPUT->textfield($field);
+        $contents .= "<br/><br/>";
+
+        $htmlloginpage .= $OUTPUT->form($form, $contents);
+
+
+        $htmlloginpage .= "</td></tr></table>";
+        return $htmlloginpage;
+
+    }
+}