]> git.mjollnir.org Git - moodle.git/commitdiff
webservice MDL-12886 refactor web service description + implement clean_function_para...
authorjerome <jerome>
Tue, 25 Aug 2009 05:35:59 +0000 (05:35 +0000)
committerjerome <jerome>
Tue, 25 Aug 2009 05:35:59 +0000 (05:35 +0000)
lib/moodleexternal.php [new file with mode: 0644]
user/external.php
webservice/lib.php
webservice/soap/lib.php
webservice/soap/testclient/zend/zend_soap_client.php [moved from webservice/soap/testclient/zend_soap_client.php with 72% similarity]
webservice/wsdoc.php [new file with mode: 0644]

diff --git a/lib/moodleexternal.php b/lib/moodleexternal.php
new file mode 100644 (file)
index 0000000..67098a2
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+/*
+* Created on 01/12/2008
+ *
+ * Moodle base webservice api
+ *
+ * @author Jerome Mouneyrac
+ */
+
+/**
+ * DO NOT USE ANYTHING FROM THIS FILE - WORK IN PROGRESS
+ */
+abstract class moodle_external {
+
+    protected $descriptions;
+
+    /**
+     * Constructor - We set the description of this API in order to be access by Web service
+     */
+    function __construct () {
+        $this->descriptions = array();
+    }
+
+    /**
+     *
+     *  @param string $functionname
+     *  @return array
+     */
+    public function get_function_webservice_description($functionname) {
+        if (key_exists($functionname, $this->descriptions)) {
+            return $this->descriptions[$functionname];
+        }
+        else {
+            return false;
+        }
+    }
+
+    /**
+     *
+     * @return array
+     */
+    public function get_descriptions() {
+        return $this->descriptions;
+    }
+
+    /**
+     * This function clean params, because it should only be called by external itself, it has to be protected (server should not call it)
+     * @param array $params
+     */
+    protected function clean_function_params($functionname, &$params) {
+        $description = $this->get_function_webservice_description($functionname);
+         varlog($functionname);
+        foreach ($params as $param) { //we are applying the algo for all params
+            $key = key($description['params']); //get next key of the description array => params need to be ordered !         
+            $this->clean_params($description['params'][$key], $param);
+           
+        }
+    }
+
+    /**
+     *
+     * @param <type> $params
+     */
+    protected function clean_params($description, &$params) {
+        if (!is_array($params)) {
+             $paramvalue = clean_param($params, $description);
+        } else {
+        foreach ($params as $paramname => &$paramvalue) {
+            if (is_array($paramvalue)) { //it's a list
+            //A description array does not support list of different objects
+            //it's why we retrieve the first key, because there should be only one key
+                $this->clean_params($description[key($description)], $paramvalue);
+            }
+            else {
+                if (is_object($paramvalue)) { //is it a object
+                    $this->clean_object_types($description[$paramname], $paramvalue);
+                }
+                else { //it's a primary type
+                    $paramvalue = clean_param($paramvalue, $description[$paramname]);
+                }
+            }
+             
+
+        }
+
+        }
+    }
+
+    protected function  clean_object_types($objectdescription, &$paramobject) {
+        foreach (get_object_vars($paramobject) as $propertyname => $propertyvalue) {
+            if (is_array($propertyvalue)) {
+                $this->clean_params($objectdescription->$propertyname, $propertyvalue);
+                $paramobject->$propertyname = $propertyvalue;
+            } else {
+                $paramobject->$propertyname = clean_param($propertyvalue, $objectdescription->$propertyname);
+
+            }
+        }
+    }
+
+}
+?>
index 2d3b9baca6cc25ff67fca696c4006e90bb75d9b7..5697d3463ae703ebd46dc5da48c3a84567f36343 100644 (file)
@@ -22,6 +22,7 @@
  * @copyright Copyright (c) 1999 onwards Martin Dougiamas     http://dougiamas.com
  * @license   http://www.gnu.org/copyleft/gpl.html     GNU GPL License
  */
+require_once(dirname(dirname(__FILE__)) . '/lib/moodleexternal.php');
 require_once(dirname(dirname(__FILE__)) . '/user/lib.php');
 
 /**
@@ -29,31 +30,79 @@ require_once(dirname(dirname(__FILE__)) . '/user/lib.php');
  *
  * @author Jerome Mouneyrac
  */
-final class user_external {
+final class user_external extends moodle_external {
+
+/**
+ * Constructor - We set the description of this API in order to be access by Web service
+ */
+    function __construct () {
+        $this->descriptions = array();
+        ///The desciption of the web service
+
+        $user = new stdClass();
+        $user->password = PARAM_ALPHANUMEXT;
+        $user->auth = PARAM_ALPHANUMEXT;
+        $user->confirmed = PARAM_NUMBER;
+        $user->username = PARAM_ALPHANUMEXT;
+        $user->idnumber = PARAM_ALPHANUMEXT;
+        $user->firstname = PARAM_ALPHANUMEXT;
+        $user->lastname = PARAM_ALPHANUMEXT;
+        $user->email = PARAM_NOTAGS;
+        $user->emailstop = PARAM_NUMBER;
+        $user->lang = PARAM_ALPHA;
+        $user->theme = PARAM_ALPHANUM;
+        $user->timezone = PARAM_ALPHANUMEXT;
+        $user->mailformat = PARAM_ALPHA;
+        $user->description = PARAM_TEXT;
+        $user->city = PARAM_ALPHANUMEXT;
+        $user->country = PARAM_ALPHANUMEXT;
+
+        $this->descriptions['create_users']   = array( 'params' => array('users' => array($user)),
+            'optionalinformation' => 'All params are not mandatory',
+            'return' => array('userids' => array(PARAM_NUMBER)));
+
+        $user = new stdClass();
+        $user->id = PARAM_NUMBER;
+        $user->auth = PARAM_ALPHANUMEXT;
+        $user->confirmed = PARAM_NUMBER;
+        $user->username = PARAM_ALPHANUMEXT;
+        $user->idnumber = PARAM_ALPHANUMEXT;
+        $user->firstname = PARAM_ALPHANUMEXT;
+        $user->lastname = PARAM_ALPHANUMEXT;
+        $user->email = PARAM_NOTAGS;
+        $user->emailstop = PARAM_NUMBER;
+        $user->lang = PARAM_ALPHA;
+        $user->theme = PARAM_ALPHANUM;
+        $user->timezone = PARAM_ALPHANUMEXT;
+        $user->mailformat = PARAM_ALPHA;
+        $user->description = PARAM_TEXT;
+        $user->city = PARAM_ALPHANUMEXT;
+        $user->country = PARAM_ALPHANUMEXT;
+
+        $this->descriptions['get_users']     = array( 'params' => array('search'=> PARAM_ALPHANUM),
+            'optionalparams' => 'All params are not mandatory',
+            'return' => array('user' => array( $user)));
+
+
+        $this->descriptions['delete_users']   = array( 'params' => array('usernames' => array(PARAM_ALPHANUMEXT)),
+            'optionalparams' => 'All params are not mandatory',
+            'return' => array('result' => PARAM_BOOL));
+
+        $user->newusername = PARAM_ALPHANUMEXT;
+        $this->descriptions['update_users']   = array( 'params' => array('users' => array($user),
+            'optionalparams' => 'All params are not mandatory',
+            'return' => array('result' => PARAM_BOOL)));
+    }
 
     /**
      * Retrieve all user
      * @param array|struct $params - need to be define as struct for XMLRPC
-     * @subparam string $params->search - the string to search
      * @return object $return
-     * @subreturn integer $return:user->id
-     * @subreturn integer $return:user->auth
-     * @subreturn integer $return:user->confirmed
-     * @subreturn string $return:user->username
-     * @subreturn string $return:user->idnumber
-     * @subreturn string $return:user->firstname
-     * @subreturn string $return:user->lastname
-     * @subreturn string $return:user->email
-     * @subreturn string $return:user->emailstop
-     * @subreturn string $return:user->lang
-     * @subreturn string $return:user->theme
-     * @subreturn string $return:user->timezone
-     * @subreturn string $return:user->mailformat
      */
-    static function get_users($params) {
+    public function get_users($params) {
         global $USER;
 
-        $params['search'] = clean_param($params['search'], PARAM_ALPHANUM);
+        $this->clean_function_params('get_users', $params);
 
         if (has_capability('moodle/user:viewdetails', get_context_instance(CONTEXT_SYSTEM))) {
             return get_users(true, $params['search'], false, null, 'firstname ASC','', '', '', 1000, 'id, auth, confirmed, username, idnumber, firstname, lastname, email, emailstop, lang, theme, timezone, mailformat, city, description, country');
@@ -63,90 +112,19 @@ final class user_external {
         }
     }
 
-     /**
+    /**
      * Create multiple users
      * @param array|struct $params - need to be define as struct for XMLRPC
-     * @subparam string $params:user->username
-     * @subparam string $params:user->firstname
-     * @subparam string $params:user->lastname
-     * @subparam string $params:user->email
-     * @subparam string $params:user->password
      * @return array $return ids of new user
-     * @subreturn integer $return:id user id
      */
-    static function create_users($params) {
+    public function create_users($params) {
         global $USER;
         if (has_capability('moodle/user:create', get_context_instance(CONTEXT_SYSTEM))) {
             $userids = array();
-            foreach ($params as $userparams) {
-
-                $user = new stdClass();
-                if (array_key_exists('email', $userparams)) {
-                    $user->email =  clean_param($userparams['email'], PARAM_NOTAGS);
-                }
-
-                if (array_key_exists('password', $userparams)) {
-                    $user->password =  clean_param($userparams['password'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('idnumber', $userparams)) {
-                    $user->idnumber =  clean_param($userparams['idnumber'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('description', $userparams)) {
-                    $user->description =  clean_param($userparams['description'], PARAM_TEXT);
-                }
-
-                if (array_key_exists('username', $userparams)) {
-                    $user->username =  clean_param($userparams['username'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('auth', $userparams)) {
-                    $user->auth =  clean_param($userparams['auth'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('confirmed', $userparams)) {
-                    $user->confirmed =  clean_param($userparams['confirmed'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('firstname', $userparams)) {
-                    $user->firstname =  clean_param($userparams['firstname'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('lastname', $userparams)) {
-                    $user->lastname =  clean_param($userparams['lastname'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('emailstop', $userparams)) {
-                    $user->emailstop =  clean_param($userparams['emailstop'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('lang', $userparams)) {
-                    $user->lang =  clean_param($userparams['lang'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('theme', $userparams)) {
-                    $user->theme =  clean_param($userparams['theme'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('timezone', $userparams)) {
-                    $user->timezone =  clean_param($userparams['timezone'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('city', $userparams)) {
-                    $user->city =  clean_param($userparams['city'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('country', $userparams)) {
-                    $user->country =  clean_param($userparams['country'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('mailformat', $userparams)) {
-                    $user->mailformat =  clean_param($userparams['mailformat'], PARAM_ALPHANUMEXT);
-                }
-
+            $this->clean_function_params('create_users', $params);
+            foreach ($params['users'] as $user) {
                 try {
-                    $userids[$userparams['username']] = create_user($user);
+                    $userids[$user->username] = create_user($user);
                 }
                 catch (dml_write_exception $e) {
                     throw new moodle_exception('wscouldnotcreateeuserindb');
@@ -159,27 +137,24 @@ final class user_external {
         }
     }
 
-     /**
+    /**
      * Delete multiple users
      * @global object $DB
      * @param array|struct $params - need to be define as struct for XMLRPC
-     * @subparam string $params:user->username
      * @return boolean result true if success
      */
-    static function delete_users($params) {
+    public function delete_users($params) {
         global $DB,$USER;
         $deletionsuccessfull = true;
         if (has_capability('moodle/user:delete', get_context_instance(CONTEXT_SYSTEM))) {
-            foreach ($params as $userparams) {
-
-                $username  = clean_param($userparams['username'], PARAM_ALPHANUMEXT);
 
+            $this->clean_function_params('delete_users', $params);
+            foreach ($params['usernames'] as $username) {
                 $user = $DB->get_record('user', array('username'=>$username, 'mnethostid'=>1));
-
                 if (empty($user)) {
                     throw new moodle_exception('wscouldnotdeletenoexistinguser');
                 }
-
+                
                 if (!delete_user($user)) {
                     $deletionsuccessfull = false; //this function is in moodlelib.php
                 }
@@ -191,87 +166,27 @@ final class user_external {
         }
     }
 
-     /**
+    /**
      * Update some users information
      * @global object $DB
      * @param array|struct $params - need to be define as struct for XMLRPC
-     * @subparam string $params:user->username
-     * @subparam string $params:user->newusername
-     * @subparam string $params:user->firstname
      * @return boolean result true if success
      */
-    static function update_users($params) {
+    public function update_users($params) {
         global $DB,$USER;
         if (has_capability('moodle/user:update', get_context_instance(CONTEXT_SYSTEM))) {
             $updatesuccessfull = true;
 
-            foreach ($params as $userparams) {
-                if (array_key_exists('username', $userparams)) {
-                    $username =  clean_param($userparams['username'], PARAM_NOTAGS);
-                }
+            $this->clean_function_params('update_users', $params);
 
-                $user = $DB->get_record('user', array('username'=>$username, 'mnethostid'=>1));
+            foreach ($params['users'] as $paramuser) {
+
+                $user = $DB->get_record('user', array('username'=> $paramuser->username, 'mnethostid'=>1));
 
                 if (empty($user)) {
                     throw new moodle_exception('wscouldnotupdatenoexistinguser');
                 }
-
-                if (array_key_exists('email', $userparams)) {
-                    $user->email =  clean_param($userparams['email'], PARAM_NOTAGS);
-                }
-
-                if (array_key_exists('description', $userparams)) {
-                    $user->description =  clean_param($userparams['description'], PARAM_TEXT);
-                }
-
-                if (array_key_exists('newusername', $userparams)) {
-                    $user->username =  clean_param($userparams['newusername'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('auth', $userparams)) {
-                    $user->auth =  clean_param($userparams['auth'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('confirmed', $userparams)) {
-                    $user->confirmed =  clean_param($userparams['confirmed'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('firstname', $userparams)) {
-                    $user->firstname =  clean_param($userparams['firstname'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('lastname', $userparams)) {
-                    $user->lastname =  clean_param($userparams['lastname'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('emailstop', $userparams)) {
-                    $user->emailstop =  clean_param($userparams['emailstop'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('lang', $userparams)) {
-                    $user->lang =  clean_param($userparams['lang'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('theme', $userparams)) {
-                    $user->theme =  clean_param($userparams['theme'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('timezone', $userparams)) {
-                    $user->timezone =  clean_param($userparams['timezone'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('city', $userparams)) {
-                    $user->city =  clean_param($userparams['city'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('country', $userparams)) {
-                    $user->country =  clean_param($userparams['country'], PARAM_ALPHANUMEXT);
-                }
-
-                if (array_key_exists('mailformat', $userparams)) {
-                    $user->mailformat =  clean_param($userparams['mailformat'], PARAM_ALPHANUMEXT);
-                }
-
+                $user->username = $paramuser->newusername;
                 try {
                     if( !update_user($user)) {
                         $updatesuccessfull = false;
index 891ff6f97c9d5f1a20ce17393b2ab50c38129886..6424137d9c3afdbc82d0a6dd6c83b38dad48fdbc 100644 (file)
@@ -48,9 +48,11 @@ final class webservice_lib {
                 $path = $directorypath . '/' . $file;
                 ///browse the subfolder
                 if( is_dir($path) ) {
+                    if ($file != 'db') { //we don't want to browse the 'db' subfolder of webservice folder
                     require_once($path."/lib.php");
                     $classname = $file."_server";
                     $protocols[] = new $classname;
+                    }
                 }
                 ///retrieve api.php file
                 else  {
@@ -593,12 +595,12 @@ class ws_authentication {
      * @param array|struct $params
      * @return integer
      */
-    function get_token($params) {
+    function get_token($params) {     
         if ($params['username'] == 'wsuser' && $params['password'] == 'wspassword') {
             return '456';
         } else {
             throw new moodle_exception('wrongusernamepassword');
-        }
+        }      
     }
 }
 
index a6c1bc13df65975a5bcc9dbee4ea89afcee22f64..c32ab5c1fdc20f8b3791f31638b8c3621768a384 100644 (file)
@@ -108,7 +108,6 @@ final class soap_server extends webservice_server {
                 $classpath = optional_param('classpath',null,PARAM_ALPHANUM);
             }
             require_once(dirname(__FILE__) . '/../../'.$classpath.'/external.php');
-
             /// run the server
             if(isset($_GET['wsdl'])) {
                 $autodiscover = new Zend_Soap_AutoDiscover();
similarity index 72%
rename from webservice/soap/testclient/zend_soap_client.php
rename to webservice/soap/testclient/zend/zend_soap_client.php
index c753fc89f6c9ac3bc806751db4f46a10d8b9bdd8..88b68fe6139379d7cf1f8a5242e00c39c17d1b06 100644 (file)
  * Zend Soap sclient
  */
 
-require_once('../../../config.php');
-require_once('../lib.php');
+require_once('../../../../config.php');
+require_once('../../lib.php');
+
+
+
 include "Zend/Loader.php";
 Zend_Loader::registerAutoload();
 
+$PAGE->set_course($COURSE);
+$PAGE->set_url('webservice/soap/testclient/zend/zend_soap_client.php');
+
 ///Display Moodle page header
-print_header('Soap test client', 'Soap test client'.":", true);
+$PAGE->set_title('Soap test client');
+$PAGE->set_heading('Soap test client');
+echo $OUTPUT->header();
+//print_header('Soap test client', 'Soap test client'.":", true);
 
 /// check that webservices are enable into your Moodle
 /// WARNING: it makes sens here only because this client runs on the same machine as the 
@@ -43,16 +52,34 @@ if (!webservice_lib::display_webservices_availability("soap")) {
     echo "<br/><br/>";
     echo "Please fix the previous problem(s), the testing session has been interupted.";
     echo $OUTPUT->footer();
+    //  print_footer();
     exit();
 }
 
+/// Following some code in order to print the authentication WSDL into the end of the source code page
+/*
+    $client = new Zend_Http_Client($CFG->wwwroot."/webservice/soap/server.php?wsdl", array(
+        'maxredirects' => 0,
+        'timeout'      => 30));
+    $response = $client->request();
+    $wsdl = $response->getBody();
+    print $wsdl;
+    exit();
+*/
+
+
 /// authenticate => get a conversation token from the server
 /// You need a wsuser/wspassword user in the remote Moodle
 $client = new Zend_Soap_Client($CFG->wwwroot."/webservice/soap/server.php?wsdl");
 try {
+
+    $params = new stdClass();
+    $params->username = 'wsuser';
+    $params->password = 'wspassword';
     $token = $client->get_token(array('username' => "wsuser", 'password' => "wspassword"));
+    //$token = $client->get_token($params);
     print "<pre>\n";
-     print "<br><br><strong>Token: </strong>".$token;
+    print "<br><br><strong>Token: </strong>".$token;
     print "</pre>";
 } catch (exception $exception) {
     print "<br><br><strong>An exception occured during authentication: \n</strong>";
@@ -64,17 +91,16 @@ try {
 
 /// Following some code in order to print the WSDL into the end of the source code page
 /// Change the classpath to get specific service
-/*
-    $client = new Zend_Http_Client($CFG->wwwroot."/webservice/soap/server.php?token=".$token."&classpath=user&wsdl", array(
-        'maxredirects' => 0,
-        'timeout'      => 30));
-    $response = $client->request();
-    $wsdl = $response->getBody();
-    print $wsdl;
-    exit();
- *
- */
+/**
+ $client = new Zend_Http_Client($CFG->wwwroot."/webservice/soap/server.php?token=".$token."&classpath=user&wsdl", array(
+ 'maxredirects' => 0,
+ 'timeout'      => 30));
+ $response = $client->request();
+ $wsdl = $response->getBody();
+ print $wsdl;
+ exit();
+ **/
+
 
 /// build the Zend SOAP client from the remote WSDL
 $client = new Zend_Soap_Client($CFG->wwwroot."/webservice/soap/server.php?token=".$token."&classpath=user&wsdl");
@@ -97,7 +123,13 @@ print "</pre>";
 print "<br><br><strong>Create user:</strong>";
 print "<pre>\n";
 try {
-    var_dump($client->create_users(array(array('username' => "mockuser66",'firstname' => "firstname6",'lastname' => "lastname6",'email' => "mockuser6@mockuser6.com",'password' => "password6"))));
+    $user = new stdClass();
+    $user->password = "password6";
+    $user->email = "mockuser6@mockuser6.com";
+    $user->username = "mockuser66";
+    $user->firstname = "firstname6";
+    $user->lastname = "lastname6";
+    var_dump($client->create_users(array('users' => array($user))));
 } catch (exception $exception) {
     print $exception;
     print "<br><br><strong>An exception occured: \n</strong>";
@@ -109,7 +141,12 @@ print "</pre>";
 print "<br><br><strong>Update user:</strong>";
 print "<pre>\n";
 try {
-    var_dump($client->update_users(array(array('username' => "mockuser66",'newusername' => "mockuser6b",'firstname' => "firstname6b"))));
+    $user1 = new stdClass();
+    $user1->email = "mockuser6@mockuser6.com";
+    $user1->username = "mockuser66";
+    $user1->newusername = 'mockuser6b';
+    $user1->firstname = "firstname6b";
+    var_dump($client->update_users(array('users' => array($user1))));
 } catch (exception $exception) {
     print $exception;
     print "<br><br><strong>An exception occured: \n</strong>";
@@ -121,7 +158,7 @@ print "</pre>";
 print "<br><br><strong>Delete user:</strong>";
 print "<pre>\n";
 try {
-    var_dump($client->delete_users(array(array('username' => "mockuser6b"))));
+    var_dump($client->delete_users(array('usernames' => array("mockuser6b"))));
 } catch (exception $exception) {
     print $exception;
     print "<br><br><strong>An exception occured: \n</strong>";
@@ -131,6 +168,7 @@ print "</pre>";
 
 /// Display Moodle page footer
 echo $OUTPUT->footer();
+//print_footer();
 
 
 /**
@@ -144,4 +182,4 @@ function printLastRequestResponse($client) {
     print "</pre>";
 }
 
-?>
+?>
\ No newline at end of file
diff --git a/webservice/wsdoc.php b/webservice/wsdoc.php
new file mode 100644 (file)
index 0000000..e612e22
--- /dev/null
@@ -0,0 +1,265 @@
+<?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/>.       //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ * This file generate a web service documentation in HTML
+ * This documentation describe how to call a Moodle Web Service
+ */
+require_once('../config.php');
+require_once('lib.php');
+$protocol = optional_param('protocol',"soap",PARAM_ALPHA);
+
+/// 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'));
+echo $OUTPUT->header();
+webservice_lib::display_webservices_availability($protocol);
+generate_documentation($protocol);
+generate_functionlist();
+echo $OUTPUT->footer();
+
+
+
+/**
+ * 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;
+    }
+    echo $documentation;
+    echo "<strong style=\"color:orange\">".get_string('wsuserreminder','webservice')."</strong>";
+
+}
+
+
+/**
+ * Generate web service function list
+ * @global object $CFG
+ */
+function generate_functionlist () {
+    global $CFG;
+    $documentation = "<H2>".get_string('functionlist','webservice')."</H2>";
+
+    //retrieve all external file
+    $externalfiles = array();
+    $externalfunctions = array();
+    setListApiFiles($externalfiles, $CFG->dirroot);
+
+    foreach ($externalfiles as $file) {
+        require($file);
+
+        $classpath = substr($file,strlen($CFG->dirroot)+1); //remove the dir root + / from the file path
+        $classpath = substr($classpath,0,strlen($classpath) - 13); //remove /external.php from the classpath
+        $classpath = str_replace('/','_',$classpath); //convert all / into _
+        $classname = $classpath."_external";
+        $api = new $classname();
+        $documentation .= "<H3><u>".get_string('moodlepath','webservice').": ".$classpath."</u></H3><ul>";
+        if ($classname == "user_external") {
+            $description = $api->get_descriptions();
+            var_dump("<pre>");
+            convertDescriptionType($description);
+            var_dump("</pre>");
+            foreach ($description as $functionname => $functiondescription) {
+                $documentation .= <<<EOF
+        <li><b>{$functionname}(</b>
+EOF;
+                $arrayparams = array();
+                $comma="";
+                foreach($functiondescription['params'] as $param => $type) {
+                //  $type = converterMoodleParamIntoWsParam($type);
+                    $documentation .= <<<EOF
+                <span style=color:green>{$comma} {$type} <b>{$param}</b>
+EOF;
+                    if (empty($comma)) {
+                        $comma = ',';
+                    }
+                }
+                $documentation .= <<<EOF
+                    <b></span>)</b> :
+EOF;
+                if (array_key_exists('return', $functiondescription)) {
+                    foreach($functiondescription['return'] as $return => $type) {
+                    //   $thetype = converterMoodleParamIntoWsParam($type);
+                        $documentation .= <<<EOF
+                <span style=color:blue>
+                <i>
+                            {$type}</i>
+EOF;
+                        if (is_array($type)) {
+                            $arraytype = "<pre>".print_r($type, true)."</pre>";
+                            $documentation .= <<<EOF
+                 <b>{$return}</b><br/><br/><b>{$return}</b>  {$arraytype} </span>
+EOF;
+                        }
+                    }
+                }
+
+                $documentation .= <<<EOF
+                    <br/><br/><span style=color:green>
+EOF;
+                foreach($functiondescription['params'] as $param => $type) {
+
+                    if (is_array($type)) {
+                        $arraytype = "<pre>".print_r($type, true)."</pre>";
+                        $documentation .= <<<EOF
+         <b>{$param}</b> : {$arraytype} <br>
+EOF;
+                    }
+                    else {
+                    // $type = converterMoodleParamIntoWsParam($type);
+                        $documentation .= <<<EOF
+         <b>{$param}</b> : {$type} <br>
+EOF;
+                    }
+
+                }
+                $documentation .= <<<EOF
+                    </div><br/><br/>
+EOF;
+
+            }
+        }
+        $documentation .= <<<EOF
+            </ul>
+EOF;
+
+    }
+
+    echo $documentation;
+
+}
+
+function convertDescriptionType(&$description) {
+    foreach ($description as &$type) {
+        if (is_array($type)) { //is it a List ?
+            convertDescriptionType($type);
+        }
+        else {
+            if (is_object($type)) { //is it a object
+               convertObjectTypes($type);
+            }
+            else { //it's a primary type
+            
+            $type = converterMoodleParamIntoWsParam($type);
+            }
+        }
+      
+    }
+}
+
+function convertObjectTypes(&$type) {
+   foreach (get_object_vars($type) as $propertyname => $propertytype) {
+       if (is_array($propertytype)) {
+           convertDescriptionType($propertytype);
+           $type->$propertyname = $propertytype;
+       } else {
+           $type->$propertyname = converterMoodleParamIntoWsParam($propertytype);
+       }
+   }
+}
+
+/**
+ * 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;
+        default:
+            
+            //return get_object_vars($moodleparam);
+            return "object";
+            break;
+    }
+}
+
+/**
+ * Retrieve all external.php from Moodle
+ * @param array $files
+ * @param string $directorypath
+ * @return boolean result true if n
+ */
+function setListApiFiles( &$files, $directorypath ) {
+    if(is_dir($directorypath)) { //check that we are browsing a folder not a file
+
+        if( $dh = opendir($directorypath)) {
+            while( false !== ($file = readdir($dh))) {
+
+                if( $file == '.' || $file == '..') {   // Skip '.' and '..'
+                    continue;
+                }
+                $path = $directorypath . '/' . $file;
+                ///browse the subfolder
+                if( is_dir($path) ) {
+                    setListApiFiles($files, $path);
+                }
+                ///retrieve api.php file
+                else if ($file == "external.php") {
+                        $files[] = $path;
+                    }
+            }
+            closedir($dh);
+
+        }
+    }
+}
+
+
+?>