From: jerome Date: Tue, 24 Feb 2009 05:11:04 +0000 (+0000) Subject: web service MDL-12886 X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=40f024c9f31ac72a64a6ed9d7542a9060fad5999;p=moodle.git web service MDL-12886 * Remove description array => all these information are now into the phpdoc. Remove all call/reference to moodleexternal.php * Adapt our own REST server to these changes * Remove Zend REST server as it's going to be deprecated in Zend Framework 1.8 * Remove our own SOAP server as we use the Zend SOAP server --- diff --git a/group/external.php b/group/external.php index 09a5b430e7..358e56648f 100644 --- a/group/external.php +++ b/group/external.php @@ -8,7 +8,6 @@ * @author Ferran Recio */ -require_once(dirname(dirname(__FILE__)) . '/lib/moodleexternal.php'); require_once(dirname(dirname(__FILE__)) . '/group/lib.php'); require_once(dirname(dirname(__FILE__)) . '/lib/grouplib.php'); @@ -18,11 +17,12 @@ require_once(dirname(dirname(__FILE__)) . '/lib/grouplib.php'); * * WORK IN PROGRESS, DO NOT USE IT */ -final class group_external extends moodle_external { +final class group_external { /** * Constructor - We set the description of this API in order to be access by Web service */ + /* function __construct () { $this->descriptions = array(); @@ -47,7 +47,7 @@ final class group_external extends moodle_external { 'optionalparams' => array( ), 'return' => array('result' => PARAM_BOOL)); - } + }*/ /** * Creates a group @@ -72,6 +72,13 @@ final class group_external extends moodle_external { } } + /** + * add a group member + * @param array $params + * ->groupid int + * ->userid int + * @return boolean success + */ static function tmp_get_group($params){ // @TODO: any capability to check? diff --git a/user/external.php b/user/external.php index e8bf4bc9f3..8f2db86772 100644 --- a/user/external.php +++ b/user/external.php @@ -6,59 +6,38 @@ * * @author Jerome Mouneyrac */ -require_once(dirname(dirname(__FILE__)) . '/lib/moodleexternal.php'); require_once(dirname(dirname(__FILE__)) . '/user/lib.php'); /** * WORK IN PROGRESS, DO NOT USE IT */ -final class user_external extends moodle_external { +final class user_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 - /// - ///'wsparams' and 'return' are used to described the web services to the end user (can build WSDL file from these information) - /// - ///Note: web services param names have not importance. However 'paramorder' must match the function params order. - ///And all web services param names defined into 'wsparams' should be included into 'paramorder' (otherwise they will not be used) - $this->descriptions['tmp_create_user'] = array( 'params' => array('username'=> PARAM_RAW, 'firstname'=> PARAM_RAW, 'lastname'=> PARAM_RAW, 'email'=> PARAM_RAW, 'password'=> PARAM_RAW), - 'optionalparams' => array( ), - 'return' => array('userid' => PARAM_RAW)); - - $this->descriptions['tmp_get_users'] = array( 'params' => array('search'=> PARAM_ALPHANUM), - 'optionalparams' => array( ), - 'return' => array('user' => array('id' => PARAM_RAW, 'auth' => PARAM_RAW, 'confirmed' => PARAM_RAW, 'username' => PARAM_RAW, 'idnumber' => PARAM_RAW, - 'firstname' => PARAM_RAW, 'lastname' => PARAM_RAW, 'email' => PARAM_RAW, 'emailstop' => PARAM_RAW, - 'lang' => PARAM_RAW, 'theme' => PARAM_RAW, 'timezone' => PARAM_RAW, 'mailformat' => PARAM_RAW))); - - $this->descriptions['tmp_delete_user'] = array( 'params' => array('username'=> PARAM_ALPHANUM, 'mnethostid'=> PARAM_NUMBER), - 'optionalparams' => array( ), - 'return' => array('result' => PARAM_BOOL)); - - $this->descriptions['tmp_update_user'] = array( 'params' => array('username'=> PARAM_ALPHANUM, 'mnethostid'=> PARAM_NUMBER), - 'optionalparams' => array( 'newusername' => PARAM_ALPHANUM, 'firstname' => PARAM_ALPHANUM), - 'return' => array('result' => PARAM_BOOL)); - - $this->descriptions['tmp_do_multiple_user_searches'] = array( 'params' => array(array('search'=> PARAM_RAW)), - 'optionalparams' => array( ), - 'return' => array('user' => array('id' => PARAM_RAW, 'auth' => PARAM_RAW, 'confirmed' => PARAM_RAW, 'username' => PARAM_RAW, 'idnumber' => PARAM_RAW, - 'firstname' => PARAM_RAW, 'lastname' => PARAM_RAW, 'email' => PARAM_RAW, 'emailstop' => PARAM_RAW, - 'lang' => PARAM_RAW, 'theme' => PARAM_RAW, 'timezone' => PARAM_RAW, 'mailformat' => PARAM_RAW))); - - - } - - /** - * + * This docblock has a right syntax but it does not match the real function parameters - except @ param and @ return + * I just keep it for a while till we implement a real ws function using complex blockdoc syntax as this one + * Understand, this dockblock is a example... * @global object $USER * @param array|struct $params - * @return array + * @subparam string $params:searches->search - the string to search + * @subparam string $params:searches->search2 optional - the string to search + * @subparam string $params:searches->search3 - the string to search + * @subparam string $params:airport->planes:plane->company->employees:employee->name - name of a employee of a company of a plane of an airport + * @return array users + * @subreturn integer $users:user->id + * @subreturn integer $users:user->auth + * @subreturn integer $users:user->confirmed + * @subreturn string $users:user->username + * @subreturn string $users:user->idnumber + * @subreturn string $users:user->firstname + * @subreturn string $users:user->lastname + * @subreturn string $users:user->email + * @subreturn string $users:user->emailstop + * @subreturn string $users:user->lang + * @subreturn string $users:user->theme + * @subreturn string $users:user->timezone + * @subreturn string $users:user->mailformat */ - static function tmp_do_multiple_user_searches($params) { global $USER; if (has_capability('moodle/user:viewdetails', get_context_instance(CONTEXT_SYSTEM))) { @@ -79,11 +58,27 @@ final class user_external extends moodle_external { /** * Retrieve all user * @param array|struct $params - need to be define as struct for XMLRPC - * ->search string - * @return object user + * @subparam string $params->search - the string to search + * @return object users + * @subreturn integer $users:user->id + * @subreturn integer $users:user->auth + * @subreturn integer $users:user->confirmed + * @subreturn string $users:user->username + * @subreturn string $users:user->idnumber + * @subreturn string $users:user->firstname + * @subreturn string $users:user->lastname + * @subreturn string $users:user->email + * @subreturn string $users:user->emailstop + * @subreturn string $users:user->lang + * @subreturn string $users:user->theme + * @subreturn string $users:user->timezone + * @subreturn string $users:user->mailformat */ static function tmp_get_users($params) { global $USER; + + $params['search'] = clean_param($params['search'], PARAM_ALPHANUM); + if (has_capability('moodle/user:viewdetails', get_context_instance(CONTEXT_SYSTEM))) { // return "toto"; return get_users(true, $params['search'], false, null, 'firstname ASC','', '', '', 1000, 'id, auth, confirmed, username, idnumber, firstname, lastname, email, emailstop, lang, theme, timezone, mailformat'); @@ -96,10 +91,11 @@ final class user_external extends moodle_external { /** * Create a user * @param array|struct $params - need to be define as struct for XMLRPC - * ->firstname string - * ->lastname string - * ->email string - * ->password string + * @subparam string $params->username + * @subparam string $params->firstname + * @subparam string $params->lastname + * @subparam string $params->email + * @subparam string $params->password * @return integer id of new user */ static function tmp_create_user($params) { @@ -122,9 +118,9 @@ final class user_external extends moodle_external { * Delete a user * @global object $DB * @param array|struct $params - need to be define as struct for XMLRPC - * ->username string - * ->mnethostid integer - * @return boolean true if success + * @subparam string $params->username + * @subparam integer $params->mnethostid + * @return boolean result true if success */ static function tmp_delete_user($params) { global $DB,$USER; @@ -142,11 +138,11 @@ final class user_external extends moodle_external { * Update some user information * @global object $DB * @param array|struct $params - need to be define as struct for XMLRPC - * ->username string - * ->mnethostid integer - * ->newusername string - * ->firstname string - * @return string true if success + * @subparam string $params->username + * @subparam integer $params->mnethostid + * @subparam string $params->newusername + * @subparam string $params->firstname + * @return boolean result true if success */ static function tmp_update_user($params) { global $DB,$USER; diff --git a/webservice/documentation.php b/webservice/documentation.php index 00cb88f734..10186568c2 100644 --- a/webservice/documentation.php +++ b/webservice/documentation.php @@ -28,10 +28,16 @@ * This documentation describe how to call Moodle SOAP Web Service */ require_once('../config.php'); +require_once('lib.php'); $protocol = optional_param('protocol',"soap",PARAM_ALPHA); generate_documentation($protocol); generate_functionlist(); + +/** + * + * @param $protocol + */ function generate_documentation($protocol) { switch ($protocol) { case "soap": @@ -49,7 +55,7 @@ function generate_documentation($protocol) { tmp_delete_user( string username, integer mnethostid, )
You will call something like:
your_client->tmp_delete_user(array('username' => "username_to_delete",'mnethostid' => 1))
- + EOF; break; case "xmlrpc": @@ -77,20 +83,24 @@ EOF; } +/** + * + * @global $CFG + */ function generate_functionlist () { global $CFG; $documentation = <<list of web services functions +

list of web service functions

EOF; //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 _ @@ -99,107 +109,75 @@ EOF; $documentation .= <<Moodle path: {$classpath} EOF; - - foreach($api->get_descriptions() as $functionname => $description) { - $documentation .= <<{$functionname}( + $description = webservice_lib::generate_webservice_description($file, $classname); + foreach ($description as $functionname => $functiondescription) { + $documentation .= <<{$functionname}( EOF; - - foreach ($description['params'] as $param => $paramtype) { - $wsparamtype = converterMoodleParamIntoWsParam($paramtype); + $arrayparams = array(); + foreach($functiondescription['params'] as $param => $type) { $documentation .= << -EOF; - foreach ($description['optionalparams'] as $param => $paramtype) { - $wsparamtype = converterMoodleParamIntoWsParam($paramtype); $documentation .= <<)
+EOF; + foreach($functiondescription['params'] as $param => $type) { + if (is_array($type)) { + $arraytype = "
".print_r($type, true)."
"; + $documentation .= <<{$param} : {$arraytype}
EOF; - + } + + } + } - $documentation .= << -EOF; - $documentation .= << -EOF; - } - - } - echo $documentation; + } -} + echo $documentation; - /** - * 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_RAW: - return "string"; - break; - default: - return "object"; - break; } -} + /** * Retrieve all external.php from Moodle * @param $ * @param $directorypath - * @return boolean true if n + * @return boolean result true if n */ -function setListApiFiles( &$files, $directorypath ) -{ - if(is_dir($directorypath)){ //check that we are browsing a folder not a file + 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( $dh = opendir($directorypath)) { - - if( $file == '.' || $file == '..') { // Skip '.' and '..' - continue; - } - $path = $directorypath . '/' . $file; - ///browse the subfolder - if( is_dir($path) ) { - setListApiFiles($files, $path); + 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; + } } - ///retrieve api.php file - else if ($file == "external.php") { - $files[] = $path; - } - } - closedir($dh); + closedir($dh); + } } } -} -?> + ?> diff --git a/webservice/lib.php b/webservice/lib.php index 80a37ffccb..33794ad939 100644 --- a/webservice/lib.php +++ b/webservice/lib.php @@ -46,13 +46,13 @@ final class webservice_lib { continue; } $path = $directorypath . '/' . $file; - ///browse the subfolder + ///browse the subfolder if( is_dir($path) ) { - require_once($path."/lib.php"); - $classname = $file."_server"; - $protocols[] = new $classname; + require_once($path."/lib.php"); + $classname = $file."_server"; + $protocols[] = new $classname; } - ///retrieve api.php file + ///retrieve api.php file else { continue; } @@ -106,11 +106,11 @@ final class webservice_lib { continue; } $path = $directorypath . '/' . $file; - ///browse the subfolder + ///browse the subfolder if( is_dir($path) ) { - webservice_lib::setListApiFiles($files, $path); + webservice_lib::setListApiFiles($files, $path); } - ///retrieve api.php file + ///retrieve api.php file else if ($file == "external.php") { $files[] = $path; } @@ -122,6 +122,278 @@ final class webservice_lib { } + /** + * Generate description array from the phpdoc + * TODO: works but it need serious refactoring + * @param $file + * @param $class + * @return + */ + public static function generate_webservice_description($file, $class){ + require_once($file); + require_once "Zend/Loader.php"; + Zend_Loader::registerAutoload(); + $reflection = Zend_Server_Reflection::reflectClass($class); + $description = array(); + + foreach($reflection->getMethods() as $method){ + + if ($method->getName()!="get_function_webservice_description" + && $method->getName()!="get_descriptions" ) { + $docBlock = $method->getDocComment(); + + + //retrieve the return and add it into the description if not array|object + preg_match_all('/@return\s+(\w+)\s+((?:\$)?\w+)/', $docBlock, $returnmatches); + + //retrieve the subparam and subreturn + preg_match_all('/\s*\*\s*@(subparam|subreturn)\s+(\w+)\s+(\$\w+(?::\w+|->\w+)+)((?:\s+(?:optional|required|multiple))*)/', $docBlock, $matches); + + for($i=0;$igetName()] = array(); + } + + if (strpos($returnmatches[1][0] ,"object")===false && strpos($returnmatches[1][0],"array")===false) { + $description[$method->getName()]['return'] = array($returnmatches[2][0] => $returnmatches[1][0]); + } + + if ($matches[1][$i] == "subparam" || $matches[1][$i] == "subreturn") { + + + ///algorythm parts + ///1. We compare the string to the description array + /// When we find a attribut that is not in the description, we retrieve all the rest of the string + ///2. We create the missing part of the description array, starting from the end of the rest of the string + ///3. We add the missing part to the description array + + ///Part 1. + + + ///construct the description array + if (strpos($matches[3][$i], "->")===false && strpos($matches[3][$i], ":")===false) { + //no separator + $otherparam = $matches[3][$i]; + } + else if (strpos($matches[3][$i], "->")===false || (strpos($matches[3][$i], ":")!==false && (strpos($matches[3][$i], ":") < strpos($matches[3][$i], "->")))) { + $separator = ":"; + $separatorsize=1; + + } else { + $separator = "->"; + $separatorsize=2; + } + + $param = substr($matches[3][$i],1,strpos($matches[3][$i], $separator)-1); + + $otherparam = substr($matches[3][$i],strpos($matches[3][$i], $separator)+$separatorsize); + $parsingdesc = $description[$method->getName()]; + + if (!empty($parsingdesc) && array_key_exists($descriptiontype, $parsingdesc)){ + $parsingdesc = $parsingdesc[$descriptiontype]; + } + $descriptionpath=array(); + + $creationfinished = false; + unset($type); + + while(!$creationfinished && (strpos($otherparam, ":") || strpos($otherparam, "->"))) { + if (strpos($otherparam, "->")===false || (strpos($otherparam, ":")!==false && (strpos($otherparam, ":") < strpos($otherparam, "->")))) { + $type = $separator; + + $separator = ":"; + $separatorsize=1; + } else { + $type = $separator; + $separator = "->"; + $separatorsize=2; + } + + $param = substr($otherparam,0,strpos($otherparam, $separator)); + + $otherparam = substr($otherparam,strpos($otherparam, $separator)+$separatorsize); + + + if ($type==":") { + if (!array_key_exists('multiple:'.$param, $parsingdesc)){ + + $desctoadd = webservice_lib::create_end_of_description(":".$param.$separator.$otherparam, $matches[2][$i]); + + if(empty($descriptionpath) ) { + if (empty($description[$method->getName()]) || !array_key_exists($descriptiontype, $description[$method->getName()])) { + $desctoadd = array($descriptiontype => $desctoadd); + } + $paramtoadd = $descriptiontype; + } else { + $paramtoadd = 'multiple:'.$param; + } + webservice_lib::add_end_of_description($paramtoadd, $desctoadd, $description[$method->getName()], $descriptionpath); + $creationfinished = true; + } else { + if(empty($descriptionpath)) { + $descriptionpath[] = $descriptiontype; + } + $descriptionpath[] = 'multiple:'.$param; + $parsingdesc = $parsingdesc['multiple:'.$param]; + } + } else { + if (!array_key_exists($param, $parsingdesc)){ + + $desctoadd = webservice_lib::create_end_of_description("->".$param.$separator.$otherparam, $matches[2][$i]); + + if(empty($descriptionpath)) { + + if (empty($description[$method->getName()]) || !array_key_exists($descriptiontype, $description[$method->getName()])) { + $desctoadd = array($descriptiontype => $desctoadd); + } + $paramtoadd = $descriptiontype; + + } else { + $paramtoadd = $param; + } + webservice_lib::add_end_of_description($paramtoadd, $desctoadd, $description[$method->getName()], $descriptionpath); + + $creationfinished = true; + } else { + if(empty($descriptionpath)) { + $descriptionpath[] = $descriptiontype; + } + $descriptionpath[] = $param; + $parsingdesc = $parsingdesc[$param]; + } + } + + } + + if (!$creationfinished) { + + if (!empty($type) && $type==":") { + + $desctoadd = webservice_lib::create_end_of_description($separator.$otherparam, $matches[2][$i]); + + if(empty($descriptionpath)) { + if (empty($description[$method->getName()]) || !array_key_exists($descriptiontype, $description[$method->getName()])) { + $desctoadd = array($descriptiontype => $desctoadd); + } + $paramtoadd = $descriptiontype; + } else { + $paramtoadd = 'multiple:'.$param; + } + + webservice_lib::add_end_of_description($paramtoadd, $desctoadd, $description[$method->getName()], $descriptionpath); + + } else { + $desctoadd = webservice_lib::create_end_of_description($separator.$otherparam, $matches[2][$i]); + if(empty($descriptionpath)) { + + if (empty($description[$method->getName()]) || !array_key_exists($descriptiontype, $description[$method->getName()])) { + $desctoadd = array($descriptiontype => $desctoadd); + } + $paramtoadd = $descriptiontype; + + } else { + $paramtoadd = $param; + + } + webservice_lib::add_end_of_description($paramtoadd, $desctoadd, $description[$method->getName()], $descriptionpath); + + } + } + } + } + } + } + + return $description; + } + + /** + * TODO: works but it needs refactoring + * @param $param + * @param $desctoadd + * @param $descriptionlevel + * @param $descriptionpath + * @param $level + */ + public static function add_end_of_description($param, $desctoadd, &$descriptionlevel, $descriptionpath, $level= 0){ + if (sizeof($descriptionpath)==0 || sizeof($descriptionpath)==$level+1) { + + if (is_array($descriptionlevel) && !empty($descriptionlevel)) { + foreach($desctoadd as $key=>$value) { + if ($key!="params" && $key!="optional" && $key!="return") { //TODO + $descriptionlevel[$param][$key] = $value; + } else { + $descriptionlevel[$param] = $value; + } + } + } else { + $descriptionlevel = $desctoadd; + } + } else { + webservice_lib::add_end_of_description($param, $desctoadd, &$descriptionlevel[$descriptionpath[$level]], $descriptionpath, $level+1); + } + + } + + + /** + * TODO: works but it needs refactoring + * @param $stringtoadd + * @param $type + * @return + */ + public static function create_end_of_description($stringtoadd, $type) { + + if (strrpos($stringtoadd, "->")===false || (strrpos($stringtoadd, ":")!==false && (strrpos($stringtoadd, ":") > strrpos($stringtoadd, "->")))) { + $separator = ":"; + $separatorsize=1; + } else { + $separator = "->"; + $separatorsize=2; + } + + $param = substr($stringtoadd,strrpos($stringtoadd, $separator)+$separatorsize); + $result = array( $param => $type); + + $otherparam = substr($stringtoadd,0,strlen($stringtoadd)-strlen($param)-$separatorsize); + + while(strrpos($otherparam, ":")!==false || strrpos($otherparam, "->")!==false) { + if (strrpos($otherparam, "->")===false || (strrpos($otherparam, ":")!==false && (strrpos($otherparam, ":") > strrpos($otherparam, "->")))) { + $separator = ":"; + $separatorsize=1; + } else { + $separator = "->"; + $separatorsize=2; + } + $param = substr($otherparam,strrpos($otherparam, $separator)+$separatorsize); + $otherparam = substr($otherparam,0,strrpos($otherparam, $separator)); + + if ($separator==":") { + $result = array('multiple:'.$param => $result); + } else { + $result = array($param => $result); + } + + } + + return $result; + + } + } /** @@ -189,7 +461,7 @@ final class wsuser_form extends moodleform { global $DB; $this->username = $this->_customdata['username']; $mform =& $this->_form; - + $strrequired = get_string('required'); $mform->addElement('hidden', 'username', $this->username); diff --git a/webservice/rest/lib.php b/webservice/rest/lib.php index 4c369b1752..0d49a124a5 100644 --- a/webservice/rest/lib.php +++ b/webservice/rest/lib.php @@ -39,7 +39,7 @@ final class rest_server extends webservice_server { * Run REST server */ public function run() { - $enable = $this->get_enable(); + $enable = $this->get_enable(); if (empty($enable)) { die; } @@ -49,47 +49,7 @@ final class rest_server extends webservice_server { $rest_arguments = get_file_argument('server.php'); header ("Content-type: text/xml"); echo call_moodle_function($rest_arguments); - } - - /** - * Run Zend REST server - * @global object $USER . - */ - public function zend_run() { - $enable = $this->get_enable(); - if (empty($enable)) { - die; - } - include "Zend/Loader.php"; - Zend_Loader::registerAutoload(); - - // retrieve the token from the url - // if the token doesn't exist, set a class containing only get_token() - $token = optional_param('token',null,PARAM_ALPHANUM); - if (empty($token)) { - $server = new Zend_Rest_Server(); - $server->setClass("ws_authentication"); - $server->handle(); - } else { // if token exist, do the authentication here - /// TODO: following function will need to be modified - $user = webservice_lib::mock_check_token($token); - if (empty($user)) { - throw new moodle_exception('wrongidentification'); - } else { - global $USER; - $USER = $user; - } - - //retrieve the api name - $classpath = optional_param(classpath,null,PARAM_ALPHA); - require_once(dirname(__FILE__) . '/../../'.$classpath.'/external.php'); - - /// run the server - $server = new Zend_Rest_Server(); - $server->setClass($classpath."_external"); - $server->handle(); - } - } + } } diff --git a/webservice/rest/locallib.php b/webservice/rest/locallib.php index 2294de35b9..a19ff3aeb7 100644 --- a/webservice/rest/locallib.php +++ b/webservice/rest/locallib.php @@ -38,7 +38,7 @@ */ function call_moodle_function ($rest_arguments) { global $CFG, $USER; - + ///REST params conversion $functionname = substr($rest_arguments,strrpos($rest_arguments,"/")+1); //retrieve the function name (it's located after the last '/') in $rest_arguments //$rest_argument @@ -75,12 +75,11 @@ function call_moodle_function ($rest_arguments) { } /// load the external class - require_once($CFG->dirroot.$apipath.'external.php'); - $wsapi = new $classname(); - $description = $wsapi->get_function_webservice_description($functionname); //retrieve the web service description for this function + $file = $CFG->dirroot.$apipath.'external.php'; + $description = webservice_lib::generate_webservice_description($file, $classname); /// This following line is only REST protocol - $params = retrieve_params ($description); //retrieve the REST params + $params = retrieve_params ($description[$functionname]); //retrieve the REST params /// Generic part to any protocols if ($params === false) { @@ -94,7 +93,7 @@ function call_moodle_function ($rest_arguments) { } ///Transform result into xml in order to send the REST response - $return = mdl_conn_rest_object_to_xml ($res,key($description['return'])); + $return = mdl_conn_rest_object_to_xml ($res,key($description[$functionname]['return'])); return "$return"; } @@ -122,6 +121,34 @@ function mock_check_token($token) { } } + /** + * Convert into a Moodle type + * @param integer $param + * @return string + */ + function convert_paramtype($param) { + switch ($param) { + case "integer": + return PARAM_NUMBER; + break; + case "integer": + return PARAM_INT; + break; + case "boolean": + return PARAM_BOOL; + break; + case "string": + return PARAM_ALPHANUM; + break; + case "object": + return PARAM_RAW; + break; + default: + return PARAM_RAW; + break; + } + } + /** * * @author Jerome Mouneyrac @@ -132,19 +159,20 @@ function retrieve_params ($description) { $params = array(); //retrieve REST param matching the description (warning: PHP assign the first instanciation as the first position in the table) foreach ($description['params'] as $paramname => $paramtype) { + $paramtype = convert_paramtype($paramtype); $value = optional_param($paramname,null,$paramtype); if (!empty($value)) { $params[$paramname] = $value; } } //retrieve REST optional params - foreach ($description['optionalparams'] as $paramname => $paramtype) { + foreach ($description['optional'] as $paramname => $paramtype) { + $paramtype = convert_paramtype($paramtype); $value = optional_param($paramname,null,$paramtype); if (!empty($value)) { $params[$paramname] = $value; } } - return $params; } diff --git a/webservice/rest/server.php b/webservice/rest/server.php index e4a5a0a49d..585159662d 100644 --- a/webservice/rest/server.php +++ b/webservice/rest/server.php @@ -41,7 +41,6 @@ if (empty($CFG->enablewebservices)) { die; } - $server = new rest_server(); $server->run(); diff --git a/webservice/rest/testclient/getusers.php b/webservice/rest/testclient/getusers.php index f736b8d40e..cb4c35e4d5 100644 --- a/webservice/rest/testclient/getusers.php +++ b/webservice/rest/testclient/getusers.php @@ -1,7 +1,7 @@
- - - -
Search:
+ + + +
Search:
serverurl.'/user/tmp_get_users'); - + //we are asking for a token $connectiondata['username'] = 'wsuser'; $connectiondata['password'] = 'wspassword'; @@ -45,7 +45,7 @@ if ($search) { curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($connectiondata)); $token = curl_exec($ch); $data['token'] = $token; - + $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/tmp_get_users'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); diff --git a/webservice/rest/testclient/zend_rest_client.php b/webservice/rest/testclient/zend_rest_client.php deleted file mode 100644 index 681dc0b52a..0000000000 --- a/webservice/rest/testclient/zend_rest_client.php +++ /dev/null @@ -1,54 +0,0 @@ -wwwroot."/webservice/rest/zend_rest_server.php"); -$token = $client->tmp_get_token(array('username' => "wsuser", 'password' => "wspassword"))->get(); -echo $token->response(); -$token = $token->response(); -print "
\n
"; - -//2. test functions -$client = new Zend_Rest_Client($CFG->wwwroot."/webservice/rest/zend_rest_server.php/?classpath=user&token=".$token); -var_dump($client->tmp_get_users(array('search' => "admin"))->get()); -print "
\n
"; -var_dump($client->tmp_create_user(array('username' => "mockuser66",'firstname' => "firstname6",'lastname' => "lastname6",'email' => "mockuser6@mockuser6.com",'password' => "password6"))->get()); -print "
\n
"; -var_dump($client->tmp_update_user(array('username' => "mockuser66",'mnethostid' => 1,'newusername' => "mockuser6b",'firstname' => "firstname6b"))->get()); -print "
\n
"; -var_dump($client->tmp_delete_user(array('username' => "mockuser6b",'mnethostid' => 1))->get()); -print "
\n
"; -var_dump($client->tmp_do_multiple_user_searches(array(array('search' => "admin"),array('search' => 'mock')))->get()); -print "
\n
"; - -?> \ No newline at end of file diff --git a/webservice/rest/zend_rest_server.php b/webservice/rest/zend_rest_server.php deleted file mode 100644 index a37c8e7625..0000000000 --- a/webservice/rest/zend_rest_server.php +++ /dev/null @@ -1,41 +0,0 @@ -enablewebservices)) { - die; -} - -$server = new rest_server(); -$server->zend_run(); - -?> \ No newline at end of file diff --git a/webservice/soap/generatewsdl.php b/webservice/soap/generatewsdl.php deleted file mode 100644 index 0756c51692..0000000000 --- a/webservice/soap/generatewsdl.php +++ /dev/null @@ -1,371 +0,0 @@ -generate_wsdl($token); -echo $wsdl; - -/** - * WORK IN PROGRESS - */ -class wsdl_generator { - - private $exceptionlist; - - //private $wsdl; - - function __construct () { - // The exception list - // if ever there is some external.php file that are not a web service class, they need to be declared here - // example: $this->exceptionlist['/home/jerome/Projects/Moodle_HEAD/moodle/mod/scorm/external.php'] = true; - $this->exceptionlist = array(); - } - - /** - * Generate the WSDL for Moodle API - * @global $CFG - * @param $token - * @return string wsdl xml - */ - public function generate_wsdl ($token = null) { - global $CFG; - - if (empty($token)) { - - return $this->generate_authentication_wsdl(); - } - - ///initialize different wsdl part - $wsdlmessage = ""; - $wsdlporttype = ""; - $wsdlbinding = ""; - $wsdlservice = ""; - - ///retrieve al api.php file - $listfiles = array(); - $this->setListApiFiles( $listfiles, $CFG->dirroot); - - ///WSDL header - $wsdl = << - - -EOF; - - $wsdltypes = << - - - - - - - -EOF; - - foreach ($listfiles as $fileapipath) { - require_once($fileapipath); - - ///load the class - $classpath = substr($fileapipath,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(); - - $wsdlporttype .= << -EOF; - $wsdlbinding .= << - - -EOF; - $wsdlservice .= << - - - - - -EOF; - foreach($api->get_descriptions() as $functionname => $description) { - - - $wsdlmessage .= << - -EOF; - /* - foreach ($description['params'] as $param => $paramtype) { - $wsparamtype = $this->converterMoodleParamIntoWsParam($paramtype); - $wsdlmessage .= << - -EOF; - } - foreach ($description['optionalparams'] as $param => $paramtype) { - $wsparamtype = $this->converterMoodleParamIntoWsParam($paramtype); - $wsdlmessage .= << - -EOF; - } * */ - $wsdlmessage .= << - -EOF; - - $wsdlmessage .= << - - -EOF; - foreach ($description['return'] as $param => $paramtype) { - $wsparamtype = $this->converterMoodleParamIntoWsParam($paramtype); - $wsdlmessage .= << - -EOF; - } - $wsdlmessage .= << - -EOF; - - $wsdlporttype .= << - - - - -EOF; - $wsdlbinding .= << - - - - - - - - - -EOF; - } - $wsdlporttype .= << - - -EOF; - $wsdlbinding .= << - - -EOF; - } - - ///write WSDL - $wsdl .= $wsdltypes; - $wsdl .= $wsdlmessage; - $wsdl .= $wsdlporttype; - $wsdl .= $wsdlbinding; - $wsdl .= $wsdlservice; - - ///WSDL footer - $wsdl .= << - -EOF; - - return $wsdl; - } - - private function generate_authentication_wsdl() { - global $CFG; - $wsdl = << - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -EOF; - return $wsdl; - } - - /** - * Retrieve all api.php from Moodle (except the one of the exception list) - * @param $ - * @param $directorypath - * @return boolean true if n - */ - private function setListApiFiles( &$files, $directorypath ) - { - $generatewsdl = true; - 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) ) { - $this->setListApiFiles($files, $path); - } - ///retrieve api.php file - else if ($file == "external.php" && ! $this->inExceptionList($path)) { - $files[] = $path; - } - } - closedir($dh); - - } - } - - return $generatewsdl; - - } - - /** - * Hacky function - * We need to define if we remove all external.php file from Moodle when they do not really - * are ws api file for Moodle ws API - * @param string $path - * @return boolean true if the path if in the exception list - */ - private function inExceptionList($path) { - return (!empty( $this->exceptionlist[$path])); - } - - /** - * Convert a Moodle type (PARAM_ALPHA, PARAM_NUMBER,...) as a SOAP type (string, interger,...) - * @param integer $moodleparam - * @return string SOAP type - */ - private 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_RAW: - return "string"; - break; - default: - return "object"; - break; - } - } - -} - -?> diff --git a/webservice/soap/lib.php b/webservice/soap/lib.php index f6eafeb692..4f13d9a137 100644 --- a/webservice/soap/lib.php +++ b/webservice/soap/lib.php @@ -36,54 +36,14 @@ final class soap_server extends webservice_server { $this->set_protocolname("Soap"); } - /** - * Run SOAP server - * @global $CFG - * @global $USER - */ - public function run() { - $enable = $this->get_enable(); - if (empty($enable)) { - die; - } - global $CFG; - // retrieve the token from the url - // if the token doesn't exist, set a class containing only get_token() - $token = optional_param('token',null,PARAM_ALPHANUM); - if (empty($token)) { - $server = new SoapServer($CFG->wwwroot."/webservice/soap/generatewsdl.php"); - $server->setClass("ws_authentication"); - $server->handle(); - } else { // if token exist, do the authentication here - /// TODO: following function will need to be modified - $user = webservice_lib::mock_check_token($token); - if (empty($user)) { - throw new moodle_exception('wrongidentification'); - } else { - /// TODO: probably change this - global $USER; - $USER = $user; - } - - //retrieve the api name - $classpath = optional_param(classpath,null,PARAM_ALPHA); - require_once(dirname(__FILE__) . '/../../'.$classpath.'/external.php'); - - /// run the server - $server = new SoapServer($CFG->wwwroot."/webservice/soap/generatewsdl.php?token=".$token); - $server->setClass($classpath."_external"); //TODO: pass $user as parameter - $server->handle(); - } - } - /** * Run Zend SOAP server * @global $CFG * @global $USER */ - public function zend_run() { - $enable = $this->get_enable(); + public function run() { + $enable = $this->get_enable(); if (empty($enable)) { die; } @@ -114,7 +74,7 @@ final class soap_server extends webservice_server { $autodiscover->handle(); } else { - $soap = new Zend_Soap_Server($CFG->wwwroot."/webservice/soap/zend_soap_server.php?wsdl"); // this current file here + $soap = new Zend_Soap_Server($CFG->wwwroot."/webservice/soap/server.php?wsdl"); // this current file here $soap->setClass('ws_authentication'); $soap->handle(); } @@ -139,11 +99,11 @@ final class soap_server extends webservice_server { $autodiscover = new Zend_Soap_AutoDiscover(); //this is a hack, because there is a bug in Zend framework (http://framework.zend.com/issues/browse/ZF-5736) - $autodiscover->setUri($CFG->wwwroot."/webservice/soap/zend_soap_server.php/".$token."/".$classpath); + $autodiscover->setUri($CFG->wwwroot."/webservice/soap/server.php/".$token."/".$classpath); $autodiscover->setClass($classpath."_external"); $autodiscover->handle(); } else { - $soap = new Zend_Soap_Server($CFG->wwwroot."/webservice/soap/zend_soap_server.php?token=".$token."&classpath=".$classpath."&wsdl"); // this current file here + $soap = new Zend_Soap_Server($CFG->wwwroot."/webservice/soap/server.php?token=".$token."&classpath=".$classpath."&wsdl"); // this current file here $soap->setClass($classpath."_external"); $soap->handle(); } diff --git a/webservice/soap/testclient/php_soap_client.php b/webservice/soap/testclient/php_soap_client.php deleted file mode 100644 index 1b62a64089..0000000000 --- a/webservice/soap/testclient/php_soap_client.php +++ /dev/null @@ -1,71 +0,0 @@ -wwwroot."/webservice/soap/generatewsdl.php",array( - "trace" => 1, - "exceptions" => 0)); - -try { - $token = $client->tmp_get_token(array('username' => "wsuser", 'password' => "wspassword")); - printLastRequestResponse($client); - -} catch (SoapFault $exception) { - echo $exception; -} - - -//2. test functions -$client = new SoapClient($CFG->wwwroot."/webservice/soap/generatewsdl.php?token=".$token,array( - "trace" => 1, - "exceptions" => 0)); - -try { - var_dump($client->tmp_get_users(array('search' => "admin"))); - printLastRequestResponse($client); - var_dump($client->tmp_create_user(array('username' => "mockuser66",'firstname' => "firstname6",'lastname' => "lastname6",'email' => "mockuser6@mockuser6.com",'password' => "password6"))); - printLastRequestResponse($client); - var_dump($client->tmp_update_user(array('username' => "mockuser66",'mnethostid' => 1,'newusername' => "mockuser6b",'firstname' => "firstname6b"))); - printLastRequestResponse($client); - var_dump($client->tmp_delete_user(array('username' => "mockuser6b",'mnethostid' => 1))); - printLastRequestResponse($client); -} catch (SoapFault $exception) { - echo $exception; -} - - -function printLastRequestResponse($client) { - print "
\n";
-    print "Request :\n".htmlspecialchars($client->__getLastRequest()) ."\n";
-    print "Response:\n".htmlspecialchars($client->__getLastResponse())."\n";
-    print "
"; -} - -?> \ No newline at end of file diff --git a/webservice/soap/testclient/zend_soap_client.php b/webservice/soap/testclient/zend_soap_client.php index 219efbd64c..17536c84df 100644 --- a/webservice/soap/testclient/zend_soap_client.php +++ b/webservice/soap/testclient/zend_soap_client.php @@ -34,7 +34,7 @@ Zend_Loader::registerAutoload(); //1. authentication -$client = new Zend_Soap_Client($CFG->wwwroot."/webservice/soap/zend_soap_server.php?wsdl"); +$client = new Zend_Soap_Client($CFG->wwwroot."/webservice/soap/server.php?wsdl"); try { $token = $client->tmp_get_token(array('username' => "wsuser", 'password' => "wspassword")); printLastRequestResponse($client); @@ -43,7 +43,7 @@ try { } //2. test functions -$client = new Zend_Soap_Client($CFG->wwwroot."/webservice/soap/zend_soap_server.php?token=".$token."&classpath=user&wsdl"); +$client = new Zend_Soap_Client($CFG->wwwroot."/webservice/soap/server.php?token=".$token."&classpath=user&wsdl"); var_dump($client->tmp_get_users(array('search' => "admin"))); printLastRequestResponse($client); var_dump($client->tmp_create_user(array('username' => "mockuser66",'firstname' => "firstname6",'lastname' => "lastname6",'email' => "mockuser6@mockuser6.com",'password' => "password6"))); diff --git a/webservice/soap/zend_soap_server.php b/webservice/soap/zend_soap_server.php deleted file mode 100644 index 29094c7e57..0000000000 --- a/webservice/soap/zend_soap_server.php +++ /dev/null @@ -1,41 +0,0 @@ -enablewebservices)) { - die; -} - -$server = new soap_server(); -$server->zend_run(); - -?> \ No newline at end of file diff --git a/webservice/xmlrpc/zend_xmlrpc_server.php b/webservice/xmlrpc/server.php similarity index 100% rename from webservice/xmlrpc/zend_xmlrpc_server.php rename to webservice/xmlrpc/server.php diff --git a/webservice/xmlrpc/testclient/zend_xmlrpc_client.php b/webservice/xmlrpc/testclient/zend_xmlrpc_client.php index 8c88f06914..261dd025f5 100644 --- a/webservice/xmlrpc/testclient/zend_xmlrpc_client.php +++ b/webservice/xmlrpc/testclient/zend_xmlrpc_client.php @@ -33,12 +33,12 @@ Zend_Loader::registerAutoload(); //1. authentication -$client = new Zend_XmlRpc_Client($CFG->wwwroot."/webservice/xmlrpc/zend_xmlrpc_server.php"); +$client = new Zend_XmlRpc_Client($CFG->wwwroot."/webservice/xmlrpc/server.php"); $token = $client->call('authentication.tmp_get_token', array(array('username' => "wsuser", 'password' => "wspassword"))); var_dump($token); //2. test functions -$client = new Zend_XmlRpc_Client($CFG->wwwroot."/webservice/xmlrpc/zend_xmlrpc_server.php?classpath=user&token=".$token); +$client = new Zend_XmlRpc_Client($CFG->wwwroot."/webservice/xmlrpc/server.php?classpath=user&token=".$token); var_dump($users = $client->call('user.tmp_get_users', array(array('search' => "admin")))); print "

\n"; var_dump($users = $client->call('user.tmp_create_user', array(array('username' => "mockuser66",'firstname' => "firstname6",'lastname' => "lastname6",'email' => "mockuser6@mockuser6.com",'password' => "password6"))));