From: jerome Date: Thu, 15 Jan 2009 06:12:57 +0000 (+0000) Subject: web service MDL-12886 add delete + update user core function and REST ws functions X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=74f3622699155b05bcd9c61ec357161100b44535;p=moodle.git web service MDL-12886 add delete + update user core function and REST ws functions --- diff --git a/user/api.php b/user/api.php index bf10b2a5f6..96a7929d58 100644 --- a/user/api.php +++ b/user/api.php @@ -12,207 +12,280 @@ */ final class user_api { + /** + * Returns a subset of users (DO NOT COUNT) + * @global object $DB + * @param string $sort A SQL snippet for the sorting criteria to use + * @param string $recordsperpage how many records do pages have + * @param string $page which page to return (starts from 0) + * @param string $fields A comma separated list of fields to be returned from the chosen table. + * @param object $selectioncriteria: + * ->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. + */ + static function tmp_namedparams_get_users($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(); -/** - * Returns a subset of users (DO NOT COUNT) - * @global object $DB - * @param string $sort A SQL snippet for the sorting criteria to use - * @param string $recordsperpage how many records do pages have - * @param string $page which page to return (starts from 0) - * @param string $fields A comma separated list of fields to be returned from the chosen table. - * @param object $selectioncriteria: - * ->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. - */ -static function tmp_namedparams_get_users($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; - } + $select = " username <> :guest AND deleted = 0"; + $params = array('guest'=>'guest'); - $LIKE = $DB->sql_ilike(); - $fullname = $DB->sql_fullname(); + 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; + } - $select = " username <> :guest AND deleted = 0"; - $params = array('guest'=>'guest'); + if (!empty($selectioncriteria->confirmed)) { + $select .= " AND confirmed = 1"; + } - 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->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->confirmed)) { - $select .= " AND confirmed = 1"; - } + 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->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->extraselect)) { + $select .= " AND ".$selectioncriteria->extraselect; + if (empty($selectioncriteria->extraparams)){ + $params = $params + (array)$selectioncriteria->extraparams; + } + } - 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."%"; + return $DB->get_records_select('user', $select, $params, $sort, $fields, $page, $recordsperpage); } - if (!empty($selectioncriteria->extraselect)) { - $select .= " AND ".$selectioncriteria->extraselect; - if (empty($selectioncriteria->extraparams)){ - $params = $params + (array)$selectioncriteria->extraparams; + /** + * Returns a subset of users + * + * @uses $CFG + * @param bool $get If false then only a count of the records is returned + * @param string $search A simple string to search for + * @param bool $confirmed A switch to allow/disallow unconfirmed users + * @param array(int) $exceptions A list of IDs to ignore, eg 2,4,5,8,9,10 + * @param string $sort A SQL snippet for the sorting criteria to use + * @param string $firstinitial ? + * @param string $lastinitial ? + * @param string $page ? + * @param string $recordsperpage ? + * @param string $fields A comma separated list of fields to be returned from the chosen table. + * @return object|false|int {@link $USER} records unless get is false in which case the integer count of the records found is returned. False is returned if an error is encountered. + */ + static function tmp_get_users($get=true, $search='', $confirmed=false, array $exceptions=null, $sort='firstname ASC', + $firstinitial='', $lastinitial='', $page='', $recordsperpage='', $fields='*', $extraselect='', array $extraparams=null) { + global $DB; + + if ($get && !$recordsperpage) { + debugging('Call to get_users with $get = true no $recordsperpage limit. ' . + 'On large installations, this will probably cause an out of memory error. ' . + 'Please think again and change your code so that it does not try to ' . + 'load so much data into memory.', DEBUG_DEVELOPER); } - } - return $DB->get_records_select('user', $select, $params, $sort, $fields, $page, $recordsperpage); -} + $LIKE = $DB->sql_ilike(); + $fullname = $DB->sql_fullname(); -/** - * Returns a subset of users - * - * @uses $CFG - * @param bool $get If false then only a count of the records is returned - * @param string $search A simple string to search for - * @param bool $confirmed A switch to allow/disallow unconfirmed users - * @param array(int) $exceptions A list of IDs to ignore, eg 2,4,5,8,9,10 - * @param string $sort A SQL snippet for the sorting criteria to use - * @param string $firstinitial ? - * @param string $lastinitial ? - * @param string $page ? - * @param string $recordsperpage ? - * @param string $fields A comma separated list of fields to be returned from the chosen table. - * @return object|false|int {@link $USER} records unless get is false in which case the integer count of the records found is returned. False is returned if an error is encountered. - */ -static function tmp_get_users($get=true, $search='', $confirmed=false, array $exceptions=null, $sort='firstname ASC', - $firstinitial='', $lastinitial='', $page='', $recordsperpage='', $fields='*', $extraselect='', array $extraparams=null) { - global $DB; - - if ($get && !$recordsperpage) { - debugging('Call to get_users with $get = true no $recordsperpage limit. ' . - 'On large installations, this will probably cause an out of memory error. ' . - 'Please think again and change your code so that it does not try to ' . - 'load so much data into memory.', DEBUG_DEVELOPER); - } + $select = " username <> :guest AND deleted = 0"; + $params = array('guest'=>'guest'); - $LIKE = $DB->sql_ilike(); - $fullname = $DB->sql_fullname(); + if (!empty($search)){ + $search = trim($search); + $select .= " AND ($fullname $LIKE :search1 OR email $LIKE :search2 OR username = :search3)"; + $params['search1'] = "%$search%"; + $params['search2'] = "%$search%"; + $params['search3'] = "$search"; + } - $select = " username <> :guest AND deleted = 0"; - $params = array('guest'=>'guest'); + if ($confirmed) { + $select .= " AND confirmed = 1"; + } - if (!empty($search)){ - $search = trim($search); - $select .= " AND ($fullname $LIKE :search1 OR email $LIKE :search2 OR username = :search3)"; - $params['search1'] = "%$search%"; - $params['search2'] = "%$search%"; - $params['search3'] = "$search"; - } + if ($exceptions) { + list($exceptions, $eparams) = $DB->get_in_or_equal($exceptions, SQL_PARAMS_NAMED, 'ex0000', false); + $params = $params + $eparams; + $except = " AND id $exceptions"; + } - if ($confirmed) { - $select .= " AND confirmed = 1"; - } + if ($firstinitial) { + $select .= " AND firstname $LIKE :fni"; + $params['fni'] = "$firstinitial%"; + } + if ($lastinitial) { + $select .= " AND lastname $LIKE :lni"; + $params['lni'] = "$lastinitial%"; + } - if ($exceptions) { - list($exceptions, $eparams) = $DB->get_in_or_equal($exceptions, SQL_PARAMS_NAMED, 'ex0000', false); - $params = $params + $eparams; - $except = " AND id $exceptions"; - } + if ($extraselect) { + $select .= " AND $extraselect"; + $params = $params + (array)$extraparams; + } - if ($firstinitial) { - $select .= " AND firstname $LIKE :fni"; - $params['fni'] = "$firstinitial%"; - } - if ($lastinitial) { - $select .= " AND lastname $LIKE :lni"; - $params['lni'] = "$lastinitial%"; + if ($get) { + return $DB->get_records_select('user', $select, $params, $sort, $fields, $page, $recordsperpage); + } else { + return $DB->count_records_select('user', $select, $params); + } } - if ($extraselect) { - $select .= " AND $extraselect"; - $params = $params + (array)$extraparams; - } + /** + * 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 userid or thrown exceptions + */ + static function tmp_create_user($user) { + global $CFG, $DB; + ///WS: convert user array into an user object + if (is_array($user)) { + $user = (object) $user; + } - if ($get) { - return $DB->get_records_select('user', $select, $params, $sort, $fields, $page, $recordsperpage); - } else { - return $DB->count_records_select('user', $select, $params); - } -} + ///check password and auth fields + if (!isset($user->password)) { + $user->password = ''; + } + if (!isset($user->auth)) { + $user->auth = 'manual'; + } -/** - * 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 userid or thrown exceptions - */ -static function tmp_create_user($user) { - global $CFG, $DB; - ///WS: convert user array into an user object - if (is_array($user)) { - $user = (object) $user; - } - - ///check password and auth fields - if (!isset($user->password)) { - $user->password = ''; - } - if (!isset($user->auth)) { - $user->auth = 'manual'; + $required = array('username','firstname','lastname','email'); + foreach ($required as $req) { + if (!isset($user->{$req})) { + throw new moodle_exception('missingerequiredfield'); + } + } + + $record = create_user_record($user->username, $user->password, $user->auth); + if ($record) { + $user->id = $record->id; + if ($DB->update_record('user',$user)) { + return $record->id; + } else { + $DB->delete_record('user',array('id' => $record->id)); + } + } + throw new moodle_exception('couldnotcreateuser'); } - $required = array('username','firstname','lastname','email'); - foreach ($required as $req) { - if (!isset($user->{$req})) { - throw new moodle_exception('missingerequiredfield'); + /** + * Marks user deleted in internal user database and notifies the auth plugin. + * Also unenrols user from all roles and does other cleanup. + * @param object $user Userobject before delete (without system magic quotes) + * @return boolean success + */ + static function tmp_delete_user($user) { + global $CFG, $DB; + require_once($CFG->libdir.'/grouplib.php'); + require_once($CFG->libdir.'/gradelib.php'); + + $DB->begin_sql(); + + // delete all grades - backup is kept in grade_grades_history table + if ($grades = grade_grade::fetch_all(array('userid'=>$user->id))) { + foreach ($grades as $grade) { + $grade->delete('userdelete'); + } } - } - $record = create_user_record($user->username, $user->password, $user->auth); - if ($record) { - $user->id = $record->id; - if ($DB->update_record('user',$user)) { - return $record->id; - } else { - $DB->delete_record('user',array('id' => $record->id)); + // remove from all groups + $DB->delete_records('groups_members', array('userid'=>$user->id)); + + // unenrol from all roles in all contexts + role_unassign(0, $user->id); // this might be slow but it is really needed - modules might do some extra cleanup! + + // now do a final accesslib cleanup - removes all role assingments in user context and context itself + delete_context(CONTEXT_USER, $user->id); + + require_once($CFG->dirroot.'/tag/lib.php'); + tag_set('user', $user->id, array()); + + // workaround for bulk deletes of users with the same email address + $delname = "$user->email.".time(); + while ($DB->record_exists('user', array('username'=>$delname))) { // no need to use mnethostid here + $delname++; } - } - throw new moodle_exception('couldnotcreateuser'); -} -} + // mark internal user record as "deleted" + $updateuser = new object(); + $updateuser->id = $user->id; + $updateuser->deleted = 1; + $updateuser->username = $delname; // Remember it just in case + $updateuser->email = ''; // Clear this field to free it up + $updateuser->idnumber = ''; // Clear this field to free it up + $updateuser->timemodified = time(); + if ($DB->update_record('user', $updateuser)) { + $DB->commit_sql(); + // notify auth plugin - do not block the delete even when plugin fails + $authplugin = get_auth_plugin($user->auth); + $authplugin->user_delete($user); + events_trigger('user_deleted', $user); + return true; + } else { + $DB->rollback_sql(); + return false; + } + } + + /** + * Update a user record from its id + * Warning: no checks are done on the data!!! + * @param object $user + */ + static function tmp_update_user($user) { + global $DB; + if ($DB->update_record('user', $user)) { + $DB->commit_sql(); + events_trigger('user_updated', $user); + return true; + } else { + $DB->rollback_sql(); + return false; + } + } +} ?> diff --git a/user/wsapi.php b/user/wsapi.php index 358e79bbda..b8a547b805 100644 --- a/user/wsapi.php +++ b/user/wsapi.php @@ -32,7 +32,7 @@ final class user_ws_api extends moodle_ws_api { /// Then 'paramorder'=> array('anyobjectname' => array('username' => ...)); /// ///TODO: manage object->object parameter - $this->descriptions['tmp_get_users'] = array( 'wsparams' => array('search'=> PARAM_ALPHA), + $this->descriptions['tmp_get_users'] = array( 'wsparams' => array('search'=> PARAM_ALPHANUM), '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))); @@ -45,12 +45,18 @@ final class user_ws_api extends moodle_ws_api { '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( 'wsparams' => array('username'=> PARAM_ALPHANUM, 'mnethostid'=> PARAM_NUMBER), + 'return' => array('result', PARAM_BOOL)); + + $this->descriptions['tmp_update_user'] = array( 'wsparams' => array('username'=> PARAM_ALPHANUM, 'mnethostid'=> PARAM_NUMBER, 'newusername' => PARAM_ALPHANUM, 'firstname' => PARAM_ALPHANUM), + 'return' => array('result', PARAM_BOOL)); } /** - * - * @param $search - * @return + * Retrieve all user + * @param string $search + * @return object user */ static function tmp_get_users($search) { return user_api::tmp_get_users( true, $search, false, null, 'firstname ASC','', '', '', '', @@ -58,13 +64,13 @@ final class user_ws_api extends moodle_ws_api { } /** - * - * @param $username - * @param $firstname - * @param $lastname - * @param $email - * @param $password - * @return + * Create a user + * @param string $username + * @param string $firstname + * @param string $lastname + * @param string $email + * @param string $password + * @return integer id of new user */ static function tmp_create_user($username, $firstname, $lastname, $email, $password) { $user = array(); @@ -73,8 +79,38 @@ final class user_ws_api extends moodle_ws_api { $user['lastname'] = $lastname; $user['email'] = $email; $user['password'] = $password; - return user_api::tmp_create_user($user); - + return user_api::tmp_create_user($user); + } + + /** + * Delete a user + * @global object $DB + * @param string $username + * @param integer $mnethostid + * @return boolean true if success + */ + static function tmp_delete_user($username, $mnethostid) { + global $DB; + $user = $DB->get_record('user', array('username'=>$username, 'mnethostid'=>$mnethostid)); + return user_api::tmp_delete_user($user); + } + + /** + * Update some user information + * @global object $DB + * @param string $username + * @param integer $mnethostid + * @param string $newusername + * @param string $firstname + * @return boolean true if success + */ + static function tmp_update_user($username, $mnethostid, $newusername, $firstname) { + global $DB; + $user = $DB->get_record('user', array('username'=>$username, 'mnethostid'=>$mnethostid)); + $user->username = $newusername; + $user->firstname = $firstname; + + return user_api::tmp_update_user($user); } } diff --git a/webservice/rest/lib.php b/webservice/rest/lib.php index 4e162ade17..e81035cfa2 100644 --- a/webservice/rest/lib.php +++ b/webservice/rest/lib.php @@ -54,8 +54,8 @@ function call_moodle_function ($rest_arguments) { * @return */ function retrieve_params ($description) { - $params = $description['wsparam']; - //retrieve REST param matching the description +// $params = $description['wsparams']; + //retrieve REST param matching the description (warning: PHP assign the first instanciation as the first position in the table) foreach ($description['wsparams'] as $paramname => $paramtype) { $value = optional_param($paramname,null,$paramtype); diff --git a/webservice/rest/server.php b/webservice/rest/server.php index 20eb8afbff..5f84d7a7ae 100644 --- a/webservice/rest/server.php +++ b/webservice/rest/server.php @@ -15,10 +15,6 @@ require_once(dirname(dirname(dirname(__FILE__))) . '/config.php'); require_once('lib.php'); -if (empty($CFG->enablewebservices)) { - die; -} - //retrieve path and function name from the URL $rest_arguments = get_file_argument('server.php'); diff --git a/webservice/rest/testclient/config_rest.php b/webservice/rest/testclient/config_rest.php index 8f9e94415b..f0f571196e 100644 --- a/webservice/rest/testclient/config_rest.php +++ b/webservice/rest/testclient/config_rest.php @@ -13,10 +13,6 @@ require_once("../../../config.php"); require_once ('lib.php'); -if (empty($CFG->enablewebservices)) { - die; -} - $CFG->serverurl = $CFG->wwwroot.'/webservice/rest/server.php'; if (!function_exists('curl_init')) die ('CURL library was not found!'); diff --git a/webservice/rest/testclient/deleteuser.php b/webservice/rest/testclient/deleteuser.php new file mode 100644 index 0000000000..b8ee31b5d8 --- /dev/null +++ b/webservice/rest/testclient/deleteuser.php @@ -0,0 +1,54 @@ + + +
+ + + +
Search:
+
+ +serverurl.'/user/tmp_delete_user'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($data)); + $out = curl_exec($ch); + + $res = basicxml_xml_to_object($out); + + //show_object($res->user,2,'auth'); + var_dump($res); + show_xml ($out); +} else { + echo "

Fill the form first

"; +} + +end_interface(); + +?> diff --git a/webservice/rest/testclient/index.php b/webservice/rest/testclient/index.php index 42e22c21eb..7a3a767e92 100644 --- a/webservice/rest/testclient/index.php +++ b/webservice/rest/testclient/index.php @@ -13,9 +13,10 @@ require_once ('config_rest.php'); start_interface (false); -$links = array( array('getusers.php','getusers()'), - array('createuser.php','createuser()'), - array('namedparams_get_users.php','namedparams_get_users()')); +$links = array( array('getusers.php','get_users()'), + array('createuser.php','create_user()'), + array('deleteuser.php','delete_user()'), + array('updateuser.php','update_user()')); echo '
    '; foreach ($links as $link) { diff --git a/webservice/rest/testclient/updateuser.php b/webservice/rest/testclient/updateuser.php new file mode 100644 index 0000000000..f086c0f32e --- /dev/null +++ b/webservice/rest/testclient/updateuser.php @@ -0,0 +1,58 @@ + + +
    + + + + + +
    Old username:
    New username:
    New firstname:
    +
    + +serverurl.'/user/tmp_update_user'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($data)); + $out = curl_exec($ch); + + $res = basicxml_xml_to_object($out); + + //show_object($res->user,2,'auth'); + var_dump($res); + show_xml ($out); +} else { + echo "

    Fill the form first

    "; +} + +end_interface(); + +?>