From ef22c1b6645b5ba6cee79ace5217529fba75395a Mon Sep 17 00:00:00 2001 From: skodak Date: Tue, 15 Sep 2009 22:52:49 +0000 Subject: [PATCH] MDL-12886 converting user/external.php to externallib.php - work in progress --- lang/en_utf8/error.php | 2 - lib/db/services.php | 37 +++++++++ lib/moodleexternal.php | 116 ---------------------------- user/external.php | 105 ++----------------------- user/externallib.php | 145 ++++++++++++++++++++++++++++++++++ user/lib.php | 171 ----------------------------------------- 6 files changed, 187 insertions(+), 389 deletions(-) delete mode 100644 lib/moodleexternal.php create mode 100644 user/externallib.php delete mode 100644 user/lib.php diff --git a/lang/en_utf8/error.php b/lang/en_utf8/error.php index c359ea2f15..fb03b892a0 100644 --- a/lang/en_utf8/error.php +++ b/lang/en_utf8/error.php @@ -454,7 +454,6 @@ $string['usernotaddedadmin'] = 'Cannot delete admin accounts'; $string['usernotaddederror'] = 'User not added - error'; $string['usernotaddedregistered'] = 'User not added - already registered'; $string['usernotavailable'] = 'The details of this user are not available to you'; -$string['usernotcreated'] = 'The user could not be created'; $string['usernotdeletederror'] = 'User not deleted - error'; $string['usernotdeletedmissing'] = 'User not deleted - could not find the username'; $string['usernotdeletedoff'] = 'User not deleted - deleting not allowed'; @@ -477,7 +476,6 @@ $string['wrongsourcebase'] = 'Wrong source URL base'; $string['wrongusernamepassword'] = 'Wrong user/password'; $string['wrongzipfilename'] = 'Wrong ZIP file name'; $string['wscouldnotcreateecoursenopermission'] = 'WS - Could not create course - No permission'; -$string['wscouldnotcreateeuserindb'] = 'WS - Could not create a user'; $string['wscouldnotcreateeusernopermission'] = 'WS - Could not create a user - No permission'; $string['wscouldnotdeletenoexistinguser'] = 'WS - Could not delete a user - User doesn\'t exist'; $string['wscouldnotdeleteusernopermission'] = 'WS - Could not delete a user - No permission'; diff --git a/lib/db/services.php b/lib/db/services.php index b808156584..a1ac97a2ac 100644 --- a/lib/db/services.php +++ b/lib/db/services.php @@ -25,6 +25,9 @@ */ $functions = array( + + // === group related functions === + 'moodle_group_create_groups' => array( 'classname' => 'moodle_group_external', 'methodname' => 'create_groups', @@ -73,4 +76,38 @@ $functions = array( 'returns' => null, //TODO ), + // === user related functions === + + 'moodle_user_create_users' => array( + 'classname' => 'moodle_user_external', + 'methodname' => 'create_users', + 'classpath' => 'user/externallib.php', + 'params' => null, //TODO + 'returns' => null, //TODO + ), + + 'moodle_user_get_users' => array( + 'classname' => 'moodle_user_external', + 'methodname' => 'get_users', + 'classpath' => 'user/externallib.php', + 'params' => null, //TODO + 'returns' => null, //TODO + ), + + 'moodle_user_delete_users' => array( + 'classname' => 'moodle_user_external', + 'methodname' => 'delete_users', + 'classpath' => 'user/externallib.php', + 'params' => null, //TODO + 'returns' => null, //TODO + ), + + 'moodle_user_update_users' => array( + 'classname' => 'moodle_user_external', + 'methodname' => 'update_users', + 'classpath' => 'user/externallib.php', + 'params' => null, //TODO + 'returns' => null, //TODO + ), + ); diff --git a/lib/moodleexternal.php b/lib/moodleexternal.php deleted file mode 100644 index c593b9613c..0000000000 --- a/lib/moodleexternal.php +++ /dev/null @@ -1,116 +0,0 @@ -. - -/** - * moodleexternal.php - parent class of any external.php file into Moodle - * - * @package moodlecore - * @copyright 1999 onwards Martin Dougiamas http://dougiamas.com - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -abstract class moodle_external { - - protected $descriptions; //the web service description of the external.php functions - - function __construct () { - $this->descriptions = array(); - } - - /** - * Return web service description for a specific function - * @param string $functionname - * @return array the web service description of the function, return false if the function name doesn't exist - */ - public function get_function_webservice_description($functionname) { - if (key_exists($functionname, $this->descriptions)) { - return $this->descriptions[$functionname]; - } - else { - return false; - } - } - - /** - * Return web service description for all web service functions of the external class - * @return array - */ - public function get_descriptions() { - return $this->descriptions; - } - - /** - * This function clean params, - * It's protected because we should only clean the params into external files (not server layer) - * @param array $params - */ - protected function clean_function_params($functionname, &$params) { - $description = $this->get_function_webservice_description($functionname); - $this->clean_object($description['params'], $params); - } - - - /** - * Clean an array param - * @param array $description - an array with only one element ! - * @param array $params - an array with one or several elements - */ - protected function clean_params($description, &$params) { - foreach ($params as &$param) { - if (is_array($param) ) { //it's a list - $this->clean_params($description[0], $param); - } - else { - if (is_object($param)) { //it's an object - $this->clean_object($description[0], $param); - } - else { //it's a primary type - $param = clean_param($param, $description[0]); - } - } - } - } - - /** - * Clean an object param - * @param object $objectdescription - * @param object $paramobject - */ - protected function clean_object($objectdescription, &$paramobject) { - foreach (get_object_vars($paramobject) as $propertyname => $propertyvalue) { - if (!isset($objectdescription->$propertyname)) { //if the param is not defined into the web service description - throw new moodle_exception('wswrongparams'); //throw exception - } - if (is_array($propertyvalue)) { //the object property is a list - $this->clean_params($objectdescription->$propertyname, $propertyvalue); - $paramobject->$propertyname = $propertyvalue; - - } - else { - if (is_object($propertyvalue)) { //the object property is an object - $this->clean_object($objectdescription->$propertyname, $propertyvalue); - $paramobject->$propertyname = $propertyvalue; - } - else { //the object property is a primary type - $paramobject->$propertyname = clean_param($propertyvalue, $objectdescription->$propertyname); - - } - } - } - } - -} - diff --git a/user/external.php b/user/external.php index 24cd49c981..ab3214579e 100644 --- a/user/external.php +++ b/user/external.php @@ -22,6 +22,10 @@ * @copyright Copyright (c) 1999 onwards Martin Dougiamas http://dougiamas.com * @license http://www.gnu.org/copyleft/gpl.html GNU GPL License */ + + +die('this file is being migrated to exxternallib.php right now...'); + require_once(dirname(dirname(__FILE__)) . '/lib/moodleexternal.php'); require_once(dirname(dirname(__FILE__)) . '/user/lib.php'); @@ -38,60 +42,6 @@ final class user_external extends moodle_external { function __construct () { $this->descriptions = array(); - $user = new object(); - $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; - $params = new object(); - $params->users = array($user); - $return = new object(); - $return->userids = array(PARAM_NUMBER); - $this->descriptions['create_users'] = array( 'params' => $params, - 'optionalinformation' => 'Username, password, firstname, and username are the only mandatory', - 'return' => $return, - 'service' => 'user', - 'requiredlogin' => 0); - - $user = new object(); - $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; - $params = new object(); - $params->search = PARAM_ALPHANUM; - $return = new object(); - $return->users = array($user); - $this->descriptions['get_users'] = array( 'params' => $params, - 'optionalparams' => 'All params are not mandatory', - 'return' => $return, - 'service' => 'user', - 'requiredlogin' => 0); - $params = new object(); $params->usernames = array(PARAM_ALPHANUMEXT); $return = new object(); @@ -112,49 +62,6 @@ final class user_external extends moodle_external { 'requiredlogin' => 0); } - /** - * Retrieve all user - * @param object|struct $params - need to be define as struct for XMLRPC - * @return object $return - */ - public function get_users($params) { - global $USER; - - $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'); - } - else { - throw new moodle_exception('wscouldnotvieweusernopermission'); - } - } - - /** - * Create multiple users - * @param object|struct $params - need to be define as struct for XMLRPC - * @return object $return - */ - public function create_users($params) { - global $USER; - if (has_capability('moodle/user:create', get_context_instance(CONTEXT_SYSTEM))) { - $userids = array(); - $this->clean_function_params('create_users', $params); - foreach ($params->users as $user) { - try { - $userids[$user->username] = create_user($user); - } - catch (dml_write_exception $e) { - throw new moodle_exception('wscouldnotcreateeuserindb'); - } - } - return $userids; - } - else { - throw new moodle_exception('wscouldnotcreateeusernopermission'); - } - } - /** * Delete multiple users * @global object $DB @@ -208,9 +115,7 @@ final class user_external extends moodle_external { } $user->username = $paramuser->newusername; try { - if( !update_user($user)) { - $updatesuccessfull = false; - } + $DB->update_record('user', $user); } catch (dml_write_exception $e) { throw new moodle_exception('wscouldnotupdateuserindb'); diff --git a/user/externallib.php b/user/externallib.php new file mode 100644 index 0000000000..9a8e4277c5 --- /dev/null +++ b/user/externallib.php @@ -0,0 +1,145 @@ +. + +/** + * External user API + * + * @package moodlecore + * @subpackage webservice + * @copyright 2009 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once("$CFG->libdir/externallib.php"); + +class moodle_user_external extends external_api { + + public static function get_users($params) { + $context = get_context_instance(CONTEXT_SYSTEM); + requier_capability('moodle/user:viewdetails', $context); + self::validate_context($context); + + $search = validate_param($params['search'], PARAM_RAW); + + //TODO: this search is probably useless for external systems because it is not exact + // 1/ we should specify multiple search parameters including the mnet host id + // 2/ custom profile fileds not inlcuded + + return get_users(true, $search, false, null, 'firstname ASC','', '', '', 1000, 'id, mnethostid, auth, confirmed, username, idnumber, firstname, lastname, email, emailstop, lang, theme, timezone, mailformat, city, description, country'); + } + + public static function create_users($params) { + global $CFG, $DB; + + $context = get_context_instance(CONTEXT_SYSTEM); + requier_capability('moodle/user:create', $context); + self::validate_context($context); + + //TODO: this list is incomplete - we have preferences and custom fields too + $accepted = array( + 'password' => PARAM_RAW, + 'auth' => PARAM_SAFEDIR, + 'username' => PARAM_RAW, + 'idnumber' => PARAM_RAW, + 'firstname' => PARAM_CLEAN, + 'lastname' => PARAM_CLEAN, + 'email' => PARAM_EMAIL, + 'emailstop' => PARAM_BOOL, + 'lang' => PARAM_SAFEDIR, // validate using list of available langs - ignored if wrong + 'theme' => PARAM_SAFEDIR, + 'timezone' => PARAM_ALPHANUMEXT, + 'mailformat' => PARAM_ALPHA, + 'description' => PARAM_RAW, + 'city' => PARAM_CLEAN, + 'country' => PARAM_ALPHANUMEXT, + ); + + $required = array('username', 'firstname', 'lastname', 'email', 'password'); //TODO: password may not be required in some cases + $langs = get_list_of_languages(); + + // verify data first, only then start creating records + $users = array(); + foreach ($params as $data) { + $user = array(); + foreach ($accepted as $key=>$type) { + if (array_key_exists($key, $data)) { + $user[$key] = validate_param($data[$key], $type); + unset($data[$key]); + } + } + if (!empty($data)) { + throw new invalid_parameter_exception('Unsupported parameters in user array'); + } + foreach ($required as $req) { + if (!array_key_exists($req, $user) or empty($user[$req])) { + throw new invalid_parameter_exception("$req is required in user array"); + } + } + if (!isset($user['auth'])) { + $user['auth'] = 'manual'; + } + if (!exists_auth_plugin($user['auth'])) { + throw new invalid_parameter_exception($user['auth']." is not valid authentication plugin"); + } + + if (isset($user['lang']) and !isset($langs[$user['lang']])) { + unset($user['lang']); + } + + //TODO: add more param validations here: username, etc. + + if ($DB->get_record('user', array('username'=>$user['username'], 'mnethostid'=>$CFG->mnet_localhost_id))) { + throw new invalid_parameter_exception($user['username']." username is already taken, sorry"); + } + + if (isset($users[$user['username']])) { + throw new invalid_parameter_exception("multiple users with the same username requested"); + } + $users[$user['username']] = $user; + } + + $result = array(); + + foreach ($users as $user) { + $record = create_user_record($user['username'], $user['password'], $user['auth']); + unset($user['username']); + unset($user['password']); + unset($user['auth']); + + // now override the default (or external) values + foreach ($user as $key=>$value) { + $record->$key = $value; + } + $DB->update_record('user', $record); + + unset($record->password); // lets keep this as a secret ;-) + $result[$record->id] = $record; + } + + return $result; + } + + + public static function delete_users($params) { + //TODO + } + + + public static function update_users($params) { + //TODO + } +} \ No newline at end of file diff --git a/user/lib.php b/user/lib.php deleted file mode 100644 index df34ec04a4..0000000000 --- a/user/lib.php +++ /dev/null @@ -1,171 +0,0 @@ -search string A simple string to search for - * ->confirmed bool A switch to allow/disallow unconfirmed users - * ->exceptions array(int) A list of IDs to ignore, eg 2,4,5,8,9,10 - * ->firstinitial string ? - * ->lastinitial string ? - * @return array|false Array of {@link $USER} objects. False is returned if an error is encountered. - */ -function get_users_2($sort='firstname ASC', $recordsperpage=999999, $page=0, $fields='*', $selectioncriteria=NULL) { - global $DB; - - ///WS: convert array into an object - if (!empty($selectioncriteria) && is_array($selectioncriteria)) { - $selectioncriteria = (object) $selectioncriteria; - } - - $LIKE = $DB->sql_ilike(); - $fullname = $DB->sql_fullname(); - - $select = " username <> :guest AND deleted = 0"; - $params = array('guest'=>'guest'); - - if (!empty($selectioncriteria->search)){ - $selectioncriteria->search = trim($selectioncriteria->search); - $select .= " AND ($fullname $LIKE :search1 OR email $LIKE :search2 OR username = :search3)"; - $params['search1'] = "%".$selectioncriteria->search."%"; - $params['search2'] = "%".$selectioncriteria->search."%"; - $params['search3'] = $selectioncriteria->search; - } - - if (!empty($selectioncriteria->confirmed)) { - $select .= " AND confirmed = 1"; - } - - if (!empty($selectioncriteria->exceptions)) { - list($selectioncriteria->exceptions, $eparams) = $DB->get_in_or_equal($selectioncriteria->exceptions, SQL_PARAMS_NAMED, 'ex0000', false); - $params = $params + $eparams; - $except = " AND id ".$selectioncriteria->exceptions; - } - - if (!empty($selectioncriteria->firstinitial)) { - $select .= " AND firstname $LIKE :fni"; - $params['fni'] = $selectioncriteria->firstinitial."%"; - } - if (!empty($selectioncriteria->lastinitial)) { - $select .= " AND lastname $LIKE :lni"; - $params['lni'] = $selectioncriteria->lastinitial."%"; - } - - if (!empty($selectioncriteria->extraselect)) { - $select .= " AND ".$selectioncriteria->extraselect; - if (empty($selectioncriteria->extraparams)){ - $params = $params + (array)$selectioncriteria->extraparams; - } - } - - return $DB->get_records_select('user', $select, $params, $sort, $fields, $page, $recordsperpage); -} - - -/** - * Creates an User with given information. Required fields are: - * -username - * -idnumber - * -firstname - * -lastname - * -email - * - * And there's some interesting fields: - * -password - * -auth - * -confirmed - * -timezone - * -country - * -emailstop - * -theme - * -lang - * -mailformat - * - * @param assoc array or object $user - * - * @return string or thrown exceptions - */ -function create_user($user) { - global $CFG, $DB; - /// WS: convert user array into an user object - if (is_array($user)) { - $user = (object) $user; - } - - /// check auth fields - if (!isset($user->auth)) { - $user->auth = 'manual'; - } else { - /// check that the auth value exists - $authplugin = get_directory_list($CFG->dirroot."/auth", '', false, true, false); - if (array_search($user->auth, $authplugin)===false) { - throw new moodle_exception('authnotexisting'); - } - } - - $required = array('username','firstname','lastname','email', 'password'); - foreach ($required as $req) { - if (!isset($user->{$req})) { - throw new moodle_exception('missingrequiredfield'); - } - } - $password = hash_internal_user_password($user->password); - $record = create_user_record($user->username, $password, $user->auth); - if ($record) { - $user->id = $record->id; - if ($DB->update_record('user',$user)) { - return $record->id; - } else { - //we could not update properly the newly created user, we need to delete it - $DB->delete_record('user',array('id' => $record->id)); - throw new moodle_exception('usernotcreated'); - } - } - throw new moodle_exception('usernotcreated'); -} - - - -/** -* Update a user record from its id -* Warning: no checks are done on the data!!! -* @param object $user -* @return boolean -*/ -function update_user($user) { - global $DB; - - //check that the user exist - $existinguser = $DB->get_record('user', array('id'=>$user->id)); - if (empty($existinguser)) { - throw new moodle_exception('couldnotupdatenoexistinguser'); - } - - if ($DB->update_record('user', $user)) { - //TODO check the php warning that this line produce - events_trigger('user_updated', $user); - return true; - } else { - return false; - } -} - - - -?> -- 2.39.5