diff --git a/admin/uploaduser.php b/admin/uploaduser.php index 5ee0e8a15d2..c2be9f1a67a 100755 --- a/admin/uploaduser.php +++ b/admin/uploaduser.php @@ -1,40 +1,46 @@ . -/// Bulk user registration script from a comma separated file -/// Returns list of users with their user ids +/** + * Bulk user registration script from a comma separated file + * + * @package core + * @subpackage admin + * @copyright 2004 onwards Martin Dougiamas (http://dougiamas.com) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ require('../config.php'); require_once($CFG->libdir.'/adminlib.php'); require_once($CFG->libdir.'/csvlib.class.php'); require_once($CFG->dirroot.'/user/profile/lib.php'); require_once($CFG->dirroot.'/group/lib.php'); +require_once('uploaduserlib.php'); require_once('uploaduser_form.php'); $iid = optional_param('iid', '', PARAM_INT); $previewrows = optional_param('previewrows', 10, PARAM_INT); -$readcount = optional_param('readcount', 0, PARAM_INT); -$uploadtype = optional_param('uutype', 0, PARAM_INT); -define('UU_ADDNEW', 0); -define('UU_ADDINC', 1); -define('UU_ADD_UPDATE', 2); -define('UU_UPDATE', 3); - -$choices = array(UU_ADDNEW => get_string('uuoptype_addnew', 'admin'), - UU_ADDINC => get_string('uuoptype_addinc', 'admin'), - UU_ADD_UPDATE => get_string('uuoptype_addupdate', 'admin'), - UU_UPDATE => get_string('uuoptype_update', 'admin')); - -@set_time_limit(3600); // 1 hour should be enough -raise_memory_limit(MEMORY_EXTRA); +@set_time_limit(60*60); // 1 hour should be enough +raise_memory_limit(MEMORY_HUGE); require_login(); admin_externalpage_setup('uploadusers'); require_capability('moodle/site:uploadusers', get_context_instance(CONTEXT_SYSTEM)); -$textlib = textlib_get_instance(); -$systemcontext = get_context_instance(CONTEXT_SYSTEM); - $struserrenamed = get_string('userrenamed', 'admin'); $strusernotrenamedexists = get_string('usernotrenamedexists', 'error'); $strusernotrenamedmissing = get_string('usernotrenamedmissing', 'error'); @@ -46,6 +52,8 @@ $strusernotupdated = get_string('usernotupdatederror', 'error'); $strusernotupdatednotexists = get_string('usernotupdatednotexists', 'error'); $strusernotupdatedadmin = get_string('usernotupdatedadmin', 'error'); +$struseruptodate = get_string('useraccountuptodate', 'admin'); + $struseradded = get_string('newuser'); $strusernotadded = get_string('usernotaddedregistered', 'error'); $strusernotaddederror = get_string('usernotaddederror', 'error'); @@ -57,7 +65,6 @@ $strusernotdeletedoff = get_string('usernotdeletedoff', 'error'); $strusernotdeletedadmin = get_string('usernotdeletedadmin', 'error'); $strcannotassignrole = get_string('cannotassignrole', 'error'); -$strduplicateusername = get_string('duplicateusername', 'error'); $struserauthunsupported = get_string('userauthunsupported', 'error'); $stremailduplicate = get_string('useremailduplicate', 'error'); @@ -65,20 +72,23 @@ $stremailduplicate = get_string('useremailduplicate', 'error'); $strinvalidpasswordpolicy = get_string('invalidpasswordpolicy', 'error'); $errorstr = get_string('error'); -$returnurl = $CFG->wwwroot.'/'.$CFG->admin.'/uploaduser.php'; -$bulknurl = $CFG->wwwroot.'/'.$CFG->admin.'/user/user_bulk.php'; +$returnurl = new moodle_url('/admin/uploaduser.php'); +$bulknurl = new moodle_url('/admin/user/user_bulk.php'); $today = time(); $today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0); // array of all valid fields for validation $STD_FIELDS = array('id', 'firstname', 'lastname', 'username', 'email', - 'city', 'country', 'lang', 'auth', 'timezone', 'mailformat', + 'city', 'country', 'lang', 'timezone', 'mailformat', 'maildisplay', 'maildigest', 'htmleditor', 'ajax', 'autosubscribe', - 'mnethostid', 'institution', 'department', 'idnumber', 'skype', + 'institution', 'department', 'idnumber', 'skype', 'msn', 'aim', 'yahoo', 'icq', 'phone1', 'phone2', 'address', - 'url', 'description', 'descriptionformat', 'oldusername', 'deleted', - 'password'); + 'url', 'description', 'descriptionformat', 'password', + 'auth', // watch out when changing auth type or using external auth plugins! + 'oldusername', // use when renaming users - this is the original username + 'deleted', // 1 means delete user + ); $PRF_FIELDS = array(); @@ -86,27 +96,28 @@ if ($prof_fields = $DB->get_records('user_info_field')) { foreach ($prof_fields as $prof_field) { $PRF_FIELDS[] = 'profile_field_'.$prof_field->shortname; } - unset($prof_fields); } +unset($prof_fields); if (empty($iid)) { - $mform = new admin_uploaduser_form1(); + $mform1 = new admin_uploaduser_form1(); - if ($formdata = $mform->get_data()) { + if ($formdata = $mform1->get_data()) { $iid = csv_import_reader::get_new_iid('uploaduser'); $cir = new csv_import_reader($iid, 'uploaduser'); - $content = $mform->get_file_content('userfile'); - $optype = $formdata->uutype; - $readcount = $cir->load_csv_content($content, $formdata->encoding, $formdata->delimiter_name, 'validate_user_upload_columns'); + $content = $mform1->get_file_content('userfile'); + + $readcount = $cir->load_csv_content($content, $formdata->encoding, $formdata->delimiter_name); unset($content); if ($readcount === false) { - //TODO: need more detailed error info print_error('csvloaderror', '', $returnurl); } else if ($readcount == 0) { print_error('csvemptyfile', 'error', $returnurl); } + // test if columns ok + $filecolumns = uu_validate_user_upload_columns($cir, $STD_FIELDS, $PRF_FIELDS, $returnurl); // continue to form2 } else { @@ -114,61 +125,56 @@ if (empty($iid)) { echo $OUTPUT->heading_with_help(get_string('uploadusers', 'admin'), 'uploadusers', 'admin'); - $mform->display(); + $mform1->display(); echo $OUTPUT->footer(); die; } } else { $cir = new csv_import_reader($iid, 'uploaduser'); + $filecolumns = uu_validate_user_upload_columns($cir, $STD_FIELDS, $PRF_FIELDS, $returnurl); } -if (!$columns = $cir->get_columns()) { - print_error('cannotreadtmpfile', 'error', $returnurl); -} -$mform = new admin_uploaduser_form2(null, $columns); -// get initial date from form1 -$mform->set_data(array('iid'=>$iid, 'previewrows'=>$previewrows, 'readcount'=>$readcount, 'uutypelabel'=>$choices[$uploadtype], 'uutype'=>$uploadtype)); +$mform2 = new admin_uploaduser_form2(null, array('columns'=>$filecolumns, 'data'=>array('iid'=>$iid, 'previewrows'=>$previewrows))); // If a file has been uploaded, then process it -if ($formdata = $mform->is_cancelled()) { +if ($formdata = $mform2->is_cancelled()) { $cir->cleanup(true); redirect($returnurl); -} else if ($formdata = $mform->get_data()) { +} else if ($formdata = $mform2->get_data()) { // Print the header echo $OUTPUT->header(); echo $OUTPUT->heading(get_string('uploadusersresult', 'admin')); $optype = $formdata->uutype; - $createpasswords = (!empty($formdata->uupasswordnew) and $optype != UU_UPDATE); - $updatepasswords = (!empty($formdata->uupasswordold) and $optype != UU_ADDNEW and $optype != UU_ADDINC); - $allowrenames = (!empty($formdata->uuallowrenames) and $optype != UU_ADDNEW and $optype != UU_ADDINC); - $allowdeletes = (!empty($formdata->uuallowdeletes) and $optype != UU_ADDNEW and $optype != UU_ADDINC); $updatetype = isset($formdata->uuupdatetype) ? $formdata->uuupdatetype : 0; + $createpasswords = (!empty($formdata->uupasswordnew) and $optype != UU_USER_UPDATE); + $updatepasswords = (!empty($formdata->uupasswordold) and $optype != UU_USER_ADDNEW and $optype != UU_USER_ADDINC and ($updatetype == UU_UPDATE_FILEOVERRIDE or $updatetype == UU_UPDATE_ALLOVERRIDE)); + $allowrenames = (!empty($formdata->uuallowrenames) and $optype != UU_USER_ADDNEW and $optype != UU_USER_ADDINC); + $allowdeletes = (!empty($formdata->uuallowdeletes) and $optype != UU_USER_ADDNEW and $optype != UU_USER_ADDINC); $bulk = $formdata->uubulk; $noemailduplicates = $formdata->uunoemailduplicates; + $standardusernames = $formdata->uustandardusernames; + $resetpasswords = isset($formdata->uuforcepasswordchange) ? $formdata->uuforcepasswordchange : UU_PWRESET_NONE; // verification moved to two places: after upload and into form2 - $usersnew = 0; - $usersupdated = 0; - $userserrors = 0; - $deletes = 0; - $deleteerrors = 0; - $renames = 0; - $renameerrors = 0; - $usersskipped = 0; + $usersnew = 0; + $usersupdated = 0; + $usersuptodate = 0; //not printed yet anywhere + $userserrors = 0; + $deletes = 0; + $deleteerrors = 0; + $renames = 0; + $renameerrors = 0; + $usersskipped = 0; $weakpasswords = 0; // caches - $ccache = array(); // course cache - do not fetch all courses here, we will not probably use them all anyway! - $rolecache = uu_allowed_roles_cache(); // roles lookup cache - $manualcache = array(); // cache of used manual enrol plugins in each course - - $allowedauths = uu_allowed_auths(); - $allowedauths = array_keys($allowedauths); - $availableauths = get_plugin_list('auth'); - $availableauths = array_keys($availableauths); + $ccache = array(); // course cache - do not fetch all courses here, we will not probably use them all anyway! + $rolecache = uu_allowed_roles_cache(); // roles lookup cache + $manualcache = array(); // cache of used manual enrol plugins in each course + $supportedauths = uu_supported_auths(); // officially supported plugins that are enabled // we use only manual enrol plugin here, if it is disabled no enrol is done if (enrol_is_enabled('manual')) { @@ -188,7 +194,7 @@ if ($formdata = $mform->is_cancelled()) { // init upload progress tracker $upt = new uu_progress_tracker(); - $upt->init(); // start table + $upt->start(); // start table while ($line = $cir->next()) { $upt->flush(); @@ -196,37 +202,43 @@ if ($formdata = $mform->is_cancelled()) { $upt->track('line', $linenum); - $forcechangepassword = false; - $user = new stdClass(); - // by default, use the local mnet id (this may be changed in the file) - $user->mnethostid = $CFG->mnet_localhost_id; - // add fields to user object - foreach ($line as $key => $value) { - if ($value !== '') { - $key = $columns[$key]; - $user->$key = $value; - if (in_array($key, $upt->columns)) { - $upt->track($key, $value); - } - } else { - $user->$columns[$key] = ''; - } - } - // get username, first/last name now - we need them in templates!! - if ($optype == UU_UPDATE) { - // when updating only username is required - if (!isset($user->username)) { - $upt->track('status', get_string('missingfield', 'error', 'username'), 'error'); - $upt->track('username', $errorstr, 'error'); - $userserrors++; + // add fields to user object + foreach ($line as $keynum => $value) { + if (!isset($filecolumns[$keynum])) { + // this should not happen continue; } + $key = $filecolumns[$keynum]; + if (strpos($key, 'profile_field_') === 0) { + //NOTE: bloody mega hack alert!! + if (isset($USER->$key) and is_array($USER->$key)) { + // this must be some hacky field that is abusing arrays to store content and format + $user->$key = array(); + $user->$key['text'] = $value; + $user->$key['format'] = FORMAT_MOODLE; + } else { + $user->$key = $value; + } + } else { + $user->$key = $value; + } - } else { + if (in_array($key, $upt->columns)) { + // default value in progress tracking table, can be changed later + $upt->track($key, s($value), 'normal'); + } + } + if (!isset($user->username)) { + // prevent warnings bellow + $user->username = ''; + } + + if ($optype == UU_USER_ADDNEW or $optype == UU_USER_ADDINC) { + // user creation is a special case - the username may be constructed from templates using firstname and lastname + // better never try this in mixed update types $error = false; - // when all other ops need firstname and lastname if (!isset($user->firstname) or $user->firstname === '') { $upt->track('status', get_string('missingfield', 'error', 'firstname'), 'error'); $upt->track('firstname', $errorstr, 'error'); @@ -242,43 +254,50 @@ if ($formdata = $mform->is_cancelled()) { continue; } // we require username too - we might use template for it though - if (!isset($user->username)) { - if (!isset($formdata->username) or $formdata->username === '') { - $upt->track('status', get_string('missingfield', 'error', 'username'), 'error'); - $upt->track('username', $errorstr, 'error'); - $userserrors++; - continue; - } else { - $user->username = process_template($formdata->username, $user); - $upt->track('username', $user->username); - } + if (empty($user->username) and !empty($formdata->username)) { + $user->username = uu_process_template($formdata->username, $user); + $upt->track('username', s($user->username)); } } // normalize username - $user->username = clean_param($user->username, PARAM_USERNAME); + $originalusername = $user->username; + if ($standardusernames) { + $user->username = clean_param($user->username, PARAM_USERNAME); + } + // make sure we really have username if (empty($user->username)) { $upt->track('status', get_string('missingfield', 'error', 'username'), 'error'); $upt->track('username', $errorstr, 'error'); $userserrors++; continue; + } else if ($user->username === 'guest') { + $upt->track('status', get_string('guestnoeditprofileother', 'error'), 'error'); + $userserrors++; + continue; } - if ($existinguser = $DB->get_record('user', array('username'=>$user->username, 'mnethostid'=>$user->mnethostid))) { + if ($existinguser = $DB->get_record('user', array('username'=>$user->username, 'mnethostid'=>$CFG->mnet_localhost_id))) { $upt->track('id', $existinguser->id, 'normal', false); } // find out in username incrementing required - if ($existinguser and $optype == UU_ADDINC) { - $oldusername = $user->username; - $user->username = increment_username($user->username, $user->mnethostid); - $upt->track('username', '', 'normal', false); // clear previous - $upt->track('username', $oldusername.'-->'.$user->username, 'info'); + if ($existinguser and $optype == UU_USER_ADDINC) { + $user->username = uu_increment_username($user->username); $existinguser = false; } + // notify about nay username changes + if ($originalusername !== $user->username) { + $upt->track('username', '', 'normal', false); // clear previous + $upt->track('username', s($originalusername).'-->'.s($user->username), 'info'); + } else { + $upt->track('username', s($user->username), 'normal', false); + } + // add default values for remaining fields + $formdefaults = array(); foreach ($STD_FIELDS as $field) { if (isset($user->$field)) { continue; @@ -286,7 +305,8 @@ if ($formdata = $mform->is_cancelled()) { // all validation moved to form2 if (isset($formdata->$field)) { // process templates - $user->$field = process_template($formdata->$field, $user); + $user->$field = uu_process_template($formdata->$field, $user); + $formdefaults[$field] = true; } } foreach ($PRF_FIELDS as $field) { @@ -295,13 +315,8 @@ if ($formdata = $mform->is_cancelled()) { } if (isset($formdata->$field)) { // process templates - if (is_array($formdata->$field)) { - foreach ($formdata->$field as $k=>$v) { - $user->$field[$k] = process_template($v, $user); - } - } else { - $user->$field = process_template($formdata->$field, $user); - } + $user->$field = uu_process_template($formdata->$field, $user); + $formdefaults[$field] = true; } } @@ -336,7 +351,6 @@ if ($formdata = $mform->is_cancelled()) { // renaming requested? if (!empty($user->oldusername) ) { - $oldusername = $textlib->strtolower($user->oldusername); if (!$allowrenames) { $usersskipped++; $upt->track('status', $strusernotrenamedoff, 'warning'); @@ -349,7 +363,20 @@ if ($formdata = $mform->is_cancelled()) { continue; } - if ($olduser = $DB->get_record('user', array('username'=>$oldusername, 'mnethostid'=>$user->mnethostid))) { + if ($user->username === 'guest') { + $upt->track('status', get_string('guestnoeditprofileother', 'error'), 'error'); + $renameerrors++; + continue; + } + + if ($standardusernames) { + $oldusername = clean_param($user->oldusername, PARAM_USERNAME); + } else { + $oldusername = $user->oldusername; + } + + // no guessing when looking for old username, it must be exact match + if ($olduser = $DB->get_record('user', array('username'=>$oldusername, 'mnethostid'=>$CFG->mnet_localhost_id))) { $upt->track('id', $olduser->id, 'normal', false); if (is_siteadmin($olduser->id)) { $upt->track('status', $strusernotrenamedadmin, 'error'); @@ -358,7 +385,7 @@ if ($formdata = $mform->is_cancelled()) { } $DB->set_field('user', 'username', $user->username, array('id'=>$olduser->id)); $upt->track('username', '', 'normal', false); // clear previous - $upt->track('username', $oldusername.'-->'.$user->username, 'info'); + $upt->track('username', s($oldusername).'-->'.s($user->username), 'info'); $upt->track('status', $struserrenamed); $renames++; } else { @@ -373,7 +400,7 @@ if ($formdata = $mform->is_cancelled()) { // can we process with update or insert? $skip = false; switch ($optype) { - case UU_ADDNEW: + case UU_USER_ADDNEW: if ($existinguser) { $usersskipped++; $upt->track('status', $strusernotadded, 'warning'); @@ -381,25 +408,29 @@ if ($formdata = $mform->is_cancelled()) { } break; - case UU_ADDINC: + case UU_USER_ADDINC: if ($existinguser) { //this should not happen! $upt->track('status', $strusernotaddederror, 'error'); $userserrors++; - continue; + $skip = true; } break; - case UU_ADD_UPDATE: + case UU_USER_ADD_UPDATE: break; - case UU_UPDATE: + case UU_USER_UPDATE: if (!$existinguser) { $usersskipped++; $upt->track('status', $strusernotupdatednotexists, 'warning'); $skip = true; } break; + + default: + // unknown type + $skip = true; } if ($skip) { @@ -409,201 +440,179 @@ if ($formdata = $mform->is_cancelled()) { if ($existinguser) { $user->id = $existinguser->id; + $upt->track('username', html_writer::link(new moodle_url('/user/profile.php', array('id'=>$existinguser->id)), s($existinguser->username)), 'normal', false); + if (is_siteadmin($user->id)) { $upt->track('status', $strusernotupdatedadmin, 'error'); $userserrors++; continue; } - if (!$updatetype) { - // no updates of existing data at all - } else { - $existinguser->timemodified = time(); - if (empty($existinguser->timecreated)) { - if (empty($existinguser->firstaccess)) { - $existinguser->timecreated = time(); - } else { - $existinguser->timecreated = $existinguser->firstaccess; + $existinguser->timemodified = time(); + // do NOT mess with timecreated or firstaccess here! + + //load existing profile data + profile_load_data($existinguser); + + $upt->track('auth', $existinguser->auth, 'normal', false); + + $doupdate = false; + + if ($updatetype != UU_UPDATE_NOCHANGES) { + if (!empty($user->auth) and $user->auth !== $existinguser->auth) { + $upt->track('auth', s($existinguser->auth).'-->'.s($user->auth), 'info', false); + $existinguser->auth = $user->auth; + if (!isset($supportedauths[$user->auth])) { + $upt->track('auth', $struserauthunsupported, 'warning'); } } - - //load existing profile data - profile_load_data($existinguser); - - $allowed = array(); - if ($updatetype == 1) { - $allowed = $columns; - } else if ($updatetype == 2 or $updatetype == 3) { - $allowed = array_merge($STD_FIELDS, $PRF_FIELDS); - } - foreach ($allowed as $column) { - $temppasswordhandler = ''; - if ($column == 'username') { + $allcolumns = array_merge($STD_FIELDS, $PRF_FIELDS); + foreach ($allcolumns as $column) { + if ($column === 'username' or $column === 'password' or $column === 'auth') { + // these can not be changed here continue; } - if ((property_exists($existinguser, $column) and property_exists($user, $column)) or in_array($column, $PRF_FIELDS)) { - if ($updatetype == 3 && $existinguser->$column !== '') { - //missing == non-empty only + if (!property_exists($user, $column) or !property_exists($existinguser, $column)) { + // this should never happen + continue; + } + if ($updatetype == UU_UPDATE_MISSING) { + if (!is_null($existinguser->$column) and $existinguser->$column !== '') { continue; } - if ($existinguser->$column !== $user->$column) { - if ($column == 'email') { - if ($DB->record_exists('user', array('email'=>$user->email))) { - if ($noemailduplicates) { - $upt->track('email', $stremailduplicate, 'error'); - $upt->track('status', $strusernotupdated, 'error'); - $userserrors++; - continue 2; - } else { - $upt->track('email', $stremailduplicate, 'warning'); - } - } - } + } else if ($updatetype == UU_UPDATE_ALLOVERRIDE) { + // we override everything - if ($column == 'password') { - $temppasswordhandler = $existinguser->password; - } - - if ($column == 'auth') { - if (isset($user->auth) && empty($user->auth)) { - $user->auth = 'manual'; - } - - $existinguserauth = get_auth_plugin($existinguser->auth); - $existingisinternalauth = $existinguserauth->is_internal(); - - $userauth = get_auth_plugin($user->auth); - $isinternalauth = $userauth->is_internal(); - - if ($isinternalauth === $existingisinternalauth) { - if ($updatepasswords) { - if (empty($user->password)) { - $forcechangepassword = true; - } - } - } else if ($isinternalauth) { - $existinguser->password = ''; - $forcechangepassword = true; - } - } - - $upt->track($column, '', 'normal', false); // clear previous - if ($column != 'password' && in_array($column, $upt->columns)) { - $upt->track($column, $existinguser->$column.'-->'.$user->$column, 'info'); - } - $existinguser->$column = $user->$column; - - if (!isset($user->auth) && !$updatepasswords) { - $existinguser->password = $temppasswordhandler; - } + } else if ($updatetype == UU_UPDATE_FILEOVERRIDE) { + if (!empty($formdefaults[$column])) { + // do not override with form defaults + continue; } } - } + if ($existinguser->$column !== $user->$column) { + if ($column === 'email') { + if ($DB->record_exists('user', array('email'=>$user->email))) { + if ($noemailduplicates) { + $upt->track('email', $stremailduplicate, 'error'); + $upt->track('status', $strusernotupdated, 'error'); + $userserrors++; + continue 2; + } else { + $upt->track('email', $stremailduplicate, 'warning'); + } + } + if (!validate_email($user->email)) { + $upt->track('email', get_string('invalidemail'), 'warning'); + } + } - // do not update record if new auth plugin does not exist! - if (!in_array($existinguser->auth, $availableauths)) { - $upt->track('auth', get_string('userautherror', 'error', $existinguser->auth), 'error'); - $upt->track('status', $strusernotupdated, 'error'); - $userserrors++; - continue; - } else if (!in_array($existinguser->auth, $allowedauths)) { - $upt->track('auth', $struserauthunsupported, 'warning'); + if (in_array($column, $upt->columns)) { + $upt->track($column, s($existinguser->$column).'-->'.s($user->$column), 'info', false); + } + $existinguser->$column = $user->$column; + $doupdate = true; + } } + } + try { $auth = get_auth_plugin($existinguser->auth); - $isinternalauth = $auth->is_internal(); + } catch (Exception $e) { + $upt->track('auth', get_string('userautherror', 'error', s($existinguser->auth)), 'error'); + $upt->track('status', $strusernotupdated, 'error'); + $userserrors++; + continue; + } + $isinternalauth = $auth->is_internal(); - if ($isinternalauth && $updatepasswords && !check_password_policy($user->password, $errmsg)) { - $upt->track('password', get_string('internalauthpassworderror', 'error', $existinguser->password), 'error'); - $upt->track('status', $strusernotupdated, 'error'); - $userserrors++; - continue; - } else { - $forcechangepassword = true; - } + // changing of passwords is a special case + // do not force password changes for external auth plugins! + $oldpw = $existinguser->password; + if (!$isinternalauth) { + $existinguser->password = 'not cached'; + $upt->track('password', '-', 'normal', false); + // clean up prefs + unset_user_preference('create_password', $existinguser); + unset_user_preference('auth_forcepasswordchange', $existinguser); - if (!$isinternalauth) { - $existinguser->password = 'not cached'; - $upt->track('password', 'not cached'); - $forcechangepassword = false; - } else if ($updatepasswords){ - $existinguser->password = hash_internal_user_password($existinguser->password); + } else if (!empty($user->password)) { + if ($updatepasswords) { + $errmsg = null; + $weak = check_password_policy($user->password, $errmsg); + if ($resetpasswords == UU_PWRESET_ALL or ($resetpasswords == UU_PWRESET_WEAK and $weak)) { + if ($weak) { + $weakpasswords++; + $upt->track('password', $strinvalidpasswordpolicy, 'warning'); + } + set_user_preference('auth_forcepasswordchange', 1, $existinguser); + } else { + unset_user_preference('auth_forcepasswordchange', $existinguser); + } + unset_user_preference('create_password', $existinguser); // no need to create password any more + $existinguser->password = hash_internal_user_password($user->password); } else { - $existinguser->password = $temppasswordhandler; + // do not print password when not changed + $upt->track('password', '', 'normal', false); } + } + + if ($doupdate or $existinguser->password !== $oldpw) { + // we want only users that were really updated $DB->update_record('user', $existinguser); - //remove user preference - - if (get_user_preferences('create_password', false, $existinguser)) { - unset_user_preference('create_password', $existinguser); - } - if (get_user_preferences('auth_forcepasswordchange', false, $existinguser)) { - unset_user_preference('auth_forcepasswordchange', $existinguser); - } - - if ($isinternalauth && $updatepasswords) { - if (empty($existinguser->password)) { - set_user_preference('create_password', 1, $existinguser->id); - set_user_preference('auth_forcepasswordchange', 1, $existinguser->id); - $upt->track('password', get_string('new')); - } else if ($forcechangepassword) { - set_user_preference('auth_forcepasswordchange', 1, $existinguser->id); - } - } $upt->track('status', $struserupdated); $usersupdated++; // save custom profile fields data from csv file profile_save_data($existinguser); events_trigger('user_updated', $existinguser); - } - if ($bulk == 2 or $bulk == 3) { - if (!in_array($user->id, $SESSION->bulk_users)) { - $SESSION->bulk_users[] = $user->id; + if ($bulk == UU_BULK_UPDATED or $bulk == UU_BULK_ALL) { + if (!in_array($user->id, $SESSION->bulk_users)) { + $SESSION->bulk_users[] = $user->id; + } + } + + } else { + // no user information changed + $upt->track('status', $struseruptodate); + $usersuptodate++; + + if ($bulk == UU_BULK_ALL) { + if (!in_array($user->id, $SESSION->bulk_users)) { + $SESSION->bulk_users[] = $user->id; + } } } } else { - // save the user to the database - $user->confirmed = 1; + // save the new user to the database + $user->confirmed = 1; $user->timemodified = time(); - $user->timecreated = time(); + $user->timecreated = time(); + $user->mnethostid = $CFG->mnet_localhost_id; // we support ONLY local accounts here, sorry - if (isset($user->auth) && empty($user->auth)) { + if (empty($user->auth)) { $user->auth = 'manual'; } - $auth = get_auth_plugin($user->auth); + $upt->track('auth', $user->auth, 'normal', false); + + // do not insert record if new auth plugin does not exist! + try { + $auth = get_auth_plugin($user->auth); + } catch (Exception $e) { + $upt->track('auth', get_string('userautherror', 'error', s($user->auth)), 'error'); + $upt->track('status', $strusernotaddederror, 'error'); + $userserrors++; + continue; + } + if (!isset($supportedauths[$user->auth])) { + $upt->track('auth', $struserauthunsupported, 'warning'); + } + $isinternalauth = $auth->is_internal(); - if (!$createpasswords && $isinternalauth) { - if (empty($user->password)) { - $upt->track('password', get_string('missingfield', 'error', 'password'), 'error'); - $upt->track('status', $strusernotaddederror, 'error'); - $userserrors++; - continue; - } else if ($forcechangepassword) { - $upt->track('password', $strinvalidpasswordpolicy); - $upt->track('status', $strusernotaddederror, 'error'); - $userserrors++; - continue; - } - } - - // do not insert record if new auth plguin does not exist! - if (isset($user->auth)) { - if (!in_array($user->auth, $availableauths)) { - $upt->track('auth', get_string('userautherror', 'error', $user->auth), 'error'); - $upt->track('status', $strusernotaddederror, 'error'); - $userserrors++; - continue; - } else if (!in_array($user->auth, $allowedauths)) { - $upt->track('auth', $struserauthunsupported, 'warning'); - } - } - if ($DB->record_exists('user', array('email'=>$user->email))) { if ($noemailduplicates) { $upt->track('email', $stremailduplicate, 'error'); @@ -614,38 +623,66 @@ if ($formdata = $mform->is_cancelled()) { $upt->track('email', $stremailduplicate, 'warning'); } } - if (!$isinternalauth) { - $user->password = 'not cached'; - $upt->track('password', 'not cached'); - } else { - $user->password = hash_internal_user_password($user->password); + if (!validate_email($user->email)) { + $upt->track('email', get_string('invalidemail'), 'warning'); } - $user->id = $DB->insert_record('user', $user); - $info = ': ' . $user->username .' (ID = ' . $user->id . ')'; - $upt->track('status', $struseradded); - $upt->track('id', $user->id, 'normal', false); - $usersnew++; - if ($createpasswords && $isinternalauth) { - if (empty($user->password) || $forcechangepassword) { - // passwords will be created and sent out on cron - set_user_preference('create_password', 1, $user->id); - set_user_preference('auth_forcepasswordchange', 1, $user->id); - $upt->track('password', get_string('new')); + $forcechangepassword = false; + + if ($isinternalauth) { + if (empty($user->password)) { + if ($createpasswords) { + $user->password = 'to be generated'; + $upt->track('password', '', 'normal', false); + $upt->track('password', get_string('uupasswordcron', 'admin'), 'warning', false); + } else { + $upt->track('password', '', 'normal', false); + $upt->track('password', get_string('missingfield', 'error', 'password'), 'error'); + $upt->track('status', $strusernotaddederror, 'error'); + $userserrors++; + continue; + } } else { - set_user_preference('auth_forcepasswordchange', 1, $user->id); + $errmsg = null; + $weak = check_password_policy($user->password, $errmsg); + if ($resetpasswords == UU_PWRESET_ALL or ($resetpasswords == UU_PWRESET_WEAK and $weak)) { + if ($weak) { + $weakpasswords++; + $upt->track('password', $strinvalidpasswordpolicy, 'warning'); + } + $forcechangepassword = true; + } + $user->password = hash_internal_user_password($user->password); } + } else { + $user->password = 'not cached'; + $upt->track('password', '-', 'normal', false); } + // create user - insert_record ignores any extra properties + $user->id = $DB->insert_record('user', $user); + $upt->track('username', html_writer::link(new moodle_url('/user/profile.php', array('id'=>$user->id)), s($user->username)), 'normal', false); + // save custom profile fields data profile_save_data($user); + if ($forcechangepassword) { + set_user_preference('auth_forcepasswordchange', 1, $user); + } + if ($user->password === 'to be generated') { + set_user_preference('create_password', 1, $user); + } + + $upt->track('status', $struseradded); + $upt->track('id', $user->id, 'normal', false); + $usersnew++; + // make sure user context exists get_context_instance(CONTEXT_USER, $user->id); events_trigger('user_created', $user); - if ($bulk == 1 or $bulk == 3) { + if ($bulk == UU_BULK_NEW or $bulk == UU_BULK_ALL) { if (!in_array($user->id, $SESSION->bulk_users)) { $SESSION->bulk_users[] = $user->id; } @@ -653,7 +690,8 @@ if ($formdata = $mform->is_cancelled()) { } // find course enrolments, groups, roles/types and enrol periods - foreach ($columns as $column) { + // this is again a special case, we always do this for any updated or created users + foreach ($filecolumns as $column) { if (!preg_match('/^course\d+$/', $column)) { continue; } @@ -665,7 +703,7 @@ if ($formdata = $mform->is_cancelled()) { $shortname = $user->{'course'.$i}; if (!array_key_exists($shortname, $ccache)) { if (!$course = $DB->get_record('course', array('shortname'=>$shortname), 'id, shortname')) { - $upt->track('enrolments', get_string('unknowncourse', 'error', $shortname), 'error'); + $upt->track('enrolments', get_string('unknowncourse', 'error', s($shortname)), 'error'); continue; } $ccache[$shortname] = $course; @@ -696,7 +734,7 @@ if ($formdata = $mform->is_cancelled()) { if (array_key_exists($addrole, $rolecache)) { $rid = $rolecache[$addrole]->id; } else { - $upt->track('enrolments', get_string('unknownrole', 'error', $addrole), 'error'); + $upt->track('enrolments', get_string('unknownrole', 'error', s($addrole)), 'error'); continue; } @@ -720,9 +758,9 @@ if ($formdata = $mform->is_cancelled()) { // find duration $timeend = 0; if (!empty($user->{'enrolperiod'.$i})) { - $duration = (int)$user->{'enrolperiod'.$i} * 86400; // convert days to seconds + $duration = (int)$user->{'enrolperiod'.$i} * 60*60*24; // convert days to seconds if ($duration > 0) { // sanity check - $timeend = $today + $duration; + $timeend = $today + $duration; } } @@ -751,9 +789,9 @@ if ($formdata = $mform->is_cancelled()) { $ccache[$shortname]->groups[$gid]->id = $gid; $ccache[$shortname]->groups[$gid]->name = $group->name; if (!is_numeric($group->name)) { // only non-numeric names are supported!!! - $ccache[$shortname]->groups[$group->name] = new stdClass(); - $ccache[$shortname]->groups[$group->name]->id = $gid; - $ccache[$shortname]->groups[$group->name]->name = $group->name; + $ccache[$shortname]->groups[$group->name] = new stdClass(); + $ccache[$shortname]->groups[$group->name]->id = $gid; + $ccache[$shortname]->groups[$group->name]->name = $group->name; } } } @@ -768,7 +806,7 @@ if ($formdata = $mform->is_cancelled()) { if ($ccache[$shortname]->groups[$addgroup]->id = groups_create_group($newgroupdata)){ $ccache[$shortname]->groups[$addgroup]->name = $newgroupdata->name; } else { - $upt->track('enrolments', get_string('unknowngroup', 'error', $addgroup), 'error'); + $upt->track('enrolments', get_string('unknowngroup', 'error', s($addgroup)), 'error'); continue; } } @@ -777,18 +815,17 @@ if ($formdata = $mform->is_cancelled()) { try { if (groups_add_member($gid, $user->id)) { - $upt->track('enrolments', get_string('addedtogroup', '', $gname)); + $upt->track('enrolments', get_string('addedtogroup', '', s($gname))); } else { - $upt->track('enrolments', get_string('addedtogroupnot', '', $gname), 'error'); + $upt->track('enrolments', get_string('addedtogroupnot', '', s($gname)), 'error'); } } catch (moodle_exception $e) { - $upt->track('enrolments', get_string('addedtogroupnot', '', $gname), 'error'); + $upt->track('enrolments', get_string('addedtogroupnot', '', s($gname)), 'error'); continue; } } } } - $upt->flush(); $upt->close(); // close table $cir->close(); @@ -796,10 +833,10 @@ if ($formdata = $mform->is_cancelled()) { echo $OUTPUT->box_start('boxwidthnarrow boxaligncenter generalbox', 'uploadresults'); echo '

'; - if ($optype != UU_UPDATE) { + if ($optype != UU_USER_UPDATE) { echo get_string('userscreated', 'admin').': '.$usersnew.'
'; } - if ($optype == UU_UPDATE or $optype == UU_ADD_UPDATE) { + if ($optype == UU_USER_UPDATE or $optype == UU_USER_ADD_UPDATE) { echo get_string('usersupdated', 'admin').': '.$usersupdated.'
'; } if ($allowdeletes) { @@ -829,451 +866,70 @@ if ($formdata = $mform->is_cancelled()) { // Print the header echo $OUTPUT->header(); -/// Print the form - echo $OUTPUT->heading(get_string('uploaduserspreview', 'admin')); +// NOTE: this is JUST csv processing preview, we must not prevent import from here if there is something in the file!! +// this was intended for validation of csv formatting and encoding, not filtering the data!!!! +// we definitely must not process the whole file! + +// preview table data +$data = array(); $cir->init(); -$availableauths = get_plugin_list('auth'); -$availableauths = array_keys($availableauths); -$contents = array(); -while ($fields = $cir->next()) { - $errormsg = array(); +$linenum = 1; //column header is first line +while ($linenum <= $previewrows and $fields = $cir->next()) { + $linenum++; $rowcols = array(); - foreach($fields as $key =>$field) { - $rowcols[$columns[$key]] = $field; + $rowcols['line'] = $linenum; + foreach($fields as $key => $field) { + $rowcols[$filecolumns[$key]] = s($field); } + $rowcols['status'] = array(); - $usernameexist = $DB->record_exists('user', array('username'=>$rowcols['username'])); - $emailexist = $DB->record_exists('user', array('email'=>$rowcols['email'])); - $cleanusername = clean_param($rowcols['username'], PARAM_USERNAME); - $validusername = strcmp($rowcols['username'], $cleanusername); - $validemail = validate_email($rowcols['email']); - - if ($validusername != 0 || !$validemail) { - if ($validusername != 0) { - $errormsg['username'] = get_string('invalidusernameupload'); + if (isset($rowcols['username'])) { + $stdusername = clean_param($rowcols['username'], PARAM_USERNAME); + if ($rowcols['username'] !== $stdusername) { + $rowcols['status'][] = get_string('invalidusernameupload'); } - if (!$validemail) { - $errormsg['email'] = get_string('invalidemail'); + if ($userid = $DB->get_field('user', 'id', array('username'=>$stdusername, 'mnethostid'=>$CFG->mnet_localhost_id))) { + $rowcols['username'] = html_writer::link(new moodle_url('/user/profile.php', array('id'=>$userid)), $rowcols['username']); } + } else { + $rowcols['status'][] = get_string('missingusername'); } - //check password column - if (array_key_exists('auth', $rowcols)) { - if (isset($rowcols['auth']) && empty($rowcols['auth'])) { - $rowcols['auth'] = 'manual'; - } - $rowauth = get_auth_plugin($rowcols['auth']); - $rowisinternalauth = $rowauth->is_internal(); - if (!$rowisinternalauth) { - if (array_key_exists('password', $rowcols) && !empty($rowcols['password'])) { - $errormsg['password'] = get_string('externalauthpassworderror', 'error'); - } - } - - if (!in_array($rowcols['auth'], $availableauths)) { - $errormsg['auth'] = get_string('userautherror', 'error'); - } + if (!validate_email($rowcols['email'])) { + $rowcols['status'][] = get_string('invalidemail'); } - - if (empty($optype) ) { - $optype = $uploadtype; - } - - switch($optype) { - case UU_ADDNEW: - if ($usernameexist || $emailexist ) { - $rowcols['action'] = 'skipped'; - } else { - $rowcols['action'] = 'create'; - } - break; - - case UU_ADDINC: - if (!$usernameexist && !$emailexist) { - $rowcols['action'] = 'create'; - } else if ($usernameexist && !$emailexist) { - $rowcols['action'] = 'addcountertousername'; - $rowcols['username'] = increment_username($rowcols['username'], $CFG->mnet_localhost_id); - } else { - $rowcols['action'] = 'skipped'; - } - break; - - case UU_ADD_UPDATE: - $oldusernameexist = ''; - if (isset($rowcols['oldusername'])) { - $oldusernameexist = $DB->record_exists('user', array('username'=>$rowcols['oldusername'])); - } - if ($usernameexist || $emailexist || $oldusernameexist ) { - $rowcols['action'] = 'update'; - } else { - $rowcols['action'] = 'create'; - } - break; - - case UU_UPDATE: - $oldusernameexist = ''; - if (isset($rowcols['oldusername'])) { - $oldusernameexist = $DB->record_exists('user', array('username'=>$rowcols['oldusername'])); - } - - if ($usernameexist || $emailexist || !empty($oldusernameexist)) { - $rowcols['action'] = 'update'; - } else { - $rowcols['action'] = "skipped"; - } - break; - } - - if (!empty($errormsg)){ - $rowcols['error'] = array(); - $rowcols['error'] = $errormsg; - } - if ($rowcols['action'] != 'skipped') { - $contents[] = $rowcols; + if ($DB->record_exists('user', array('email'=>$rowcols['email']))) { + $rowcols['status'][] = $stremailduplicate; } + $rowcols['status'] = implode('
', $rowcols['status']); + $data[] = $rowcols; +} +if ($fields = $cir->next()) { + $data[] = array_fill(0, count($fields) + 2, '...'); } $cir->close(); -//get heading -$headings = array(); -foreach ($contents as $content) { - foreach($content as $key => $value) { - if (!in_array($key, $headings)) { - $headings[] = $key; - } - } -} - $table = new html_table(); $table->id = "uupreview"; $table->attributes['class'] = 'generaltable'; $table->tablealign = 'center'; $table->summary = get_string('uploaduserspreview', 'admin'); $table->head = array(); -$table->data = array(); +$table->data = $data; -//print heading -foreach ($headings as $heading) { - $table->head[] = s($heading); +$table->head[] = get_string('uucsvline', 'admin'); +foreach ($filecolumns as $column) { + $table->head[] = $column; } +$table->head[] = get_string('status'); -$haserror = false; -$countcontent = 0; -if (in_array('error', $headings)) { - //print error - $haserror = true; - - foreach ($contents as $content) { - if (array_key_exists('error', $content)) { - $rows = new html_table_row(); - foreach ($content as $key => $value) { - $cells = new html_table_cell(); - $errclass = ''; - if (array_key_exists($key, $content['error'])) { - $errclass = 'uuerror'; - } - if ($key == 'error') { - $value = join('
', $content['error']); - } - if ($key == 'action') { - $value = get_string($content[$key]); - } - $cells->text = $value; - $cells->attributes['class'] = $errclass; - $rows->cells[] = $cells; - } - $countcontent++; - $table->data[] = $rows; - } - } - $mform = new admin_uploaduser_form3(); - $mform->set_data(array('uutype'=>$uploadtype)); -} else if (empty($contents)) { - $mform = new admin_uploaduser_form3(); - $mform->set_data(array('uutype'=>$uploadtype)); -} else { - //print content - foreach ($contents as $content) { - $rows = new html_table_row(); - if ($countcontent >= $previewrows) { - foreach ($content as $con) { - $cells = new html_table_cell(); - $cells->text = '...'; - } - $rows->cells[] = $cells; - $table->data[] = $rows; - break; - } - foreach ($headings as $heading) { - $cells = new html_table_cell(); - if(array_key_exists($heading, $content)) { - if ($heading == 'action') { - $content[$heading] = get_string($content[$heading]); - } - $cells->text = $content[$heading]; - } else { - $cells->text = ''; - } - $rows->cells[] = $cells; - } - $table->data[] = $rows; - $countcontent++; - } -} echo html_writer::tag('div', html_writer::table($table), array('class'=>'flexible-wrap')); -if ($haserror) { - echo $OUTPUT->container(get_string('useruploadtype', 'moodle', $choices[$uploadtype]), 'centerpara'); - echo $OUTPUT->container(get_string('uploadinvalidpreprocessedcount', 'moodle', $countcontent), 'centerpara'); - echo $OUTPUT->container(get_string('invalidusername', 'moodle'), 'centerpara'); - echo $OUTPUT->container(get_string('uploadfilecontainerror', 'moodle'), 'centerpara'); -} else if (empty($contents)) { - echo $OUTPUT->container(get_string('uupreprocessedcount', 'admin', $countcontent), 'centerpara'); - echo $OUTPUT->container(get_string('uploadfilecontentsnovaliddata'), 'centerpara'); -} else { - echo $OUTPUT->container(get_string('uupreprocessedcount', 'admin', $countcontent), 'centerpara'); -} +/// Print the form -$mform->display(); +$mform2->display(); echo $OUTPUT->footer(); die; -///////////////////////////////////// -/// Utility functions and classes /// -///////////////////////////////////// - -class uu_progress_tracker { - var $_row; - var $columns = array('status', 'line', 'id', 'username', 'firstname', 'lastname', 'email', 'password', 'auth', 'enrolments', 'deleted'); - - function uu_progress_tracker() { - } - - function init() { - $ci = 0; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - $this->_row = null; - } - - function flush() { - if (empty($this->_row) or empty($this->_row['line']['normal'])) { - $this->_row = array(); - foreach ($this->columns as $col) { - $this->_row[$col] = array('normal'=>'', 'info'=>'', 'warning'=>'', 'error'=>''); - } - return; - } - $ci = 0; - $ri = 1; - echo ''; - foreach ($this->_row as $key=>$field) { - foreach ($field as $type=>$content) { - if ($field[$type] !== '') { - if ($key == 'username' && $type == 'normal') { - $field[$type] = clean_param($field[$type], PARAM_USERNAME); - } - $field[$type] = ''.$field[$type].''; - } else { - unset($field[$type]); - } - } - echo ''; - } - echo ''; - foreach ($this->columns as $col) { - $this->_row[$col] = array('normal'=>'', 'info'=>'', 'warning'=>'', 'error'=>''); - } - } - - function track($col, $msg, $level='normal', $merge=true) { - if (empty($this->_row)) { - $this->flush(); //init arrays - } - if (!in_array($col, $this->columns)) { - debugging('Incorrect column:'.$col); - return; - } - if ($merge) { - if ($this->_row[$col][$level] != '') { - $this->_row[$col][$level] .='
'; - } - $this->_row[$col][$level] .= s($msg); - } else { - $this->_row[$col][$level] = s($msg); - } - } - - function close() { - echo '
'.get_string('status').''.get_string('uucsvline', 'admin').'ID'.get_string('username').''.get_string('firstname').''.get_string('lastname').''.get_string('email').''.get_string('password').''.get_string('authentication').''.get_string('enrolments', 'enrol').''.get_string('delete').'
'; - if (!empty($field)) { - echo implode('
', $field); - } else { - echo ' '; - } - echo '
'; - } -} - -/** - * Validation callback function - verified the column line of csv file. - * Converts column names to lowercase too. - */ -function validate_user_upload_columns(&$columns) { - global $STD_FIELDS, $PRF_FIELDS; - - if (count($columns) < 2) { - return get_string('csvfewcolumns', 'error'); - } - - // test columns - $processed = array(); - foreach ($columns as $key=>$unused) { - $columns[$key] = strtolower($columns[$key]); // no unicode expected here, ignore case - $field = $columns[$key]; - if (!in_array($field, $STD_FIELDS) && !in_array($field, $PRF_FIELDS) &&// if not a standard field and not an enrolment field, then we have an error - !preg_match('/^course\d+$/', $field) && !preg_match('/^group\d+$/', $field) && - !preg_match('/^type\d+$/', $field) && !preg_match('/^role\d+$/', $field) && - !preg_match('/^enrolperiod\d+$/', $field)) { - return get_string('invalidfieldname', 'error', $field); - } - if (in_array($field, $processed)) { - return get_string('csvcolumnduplicates', 'error'); - } - $processed[] = $field; - } - return true; -} - -/** - * Increments username - increments trailing number or adds it if not present. - * Varifies that the new username does not exist yet - * @param string $username - * @return incremented username which does not exist yet - */ -function increment_username($username, $mnethostid) { - global $DB; - - if (!preg_match_all('/(.*?)([0-9]+)$/', $username, $matches)) { - $username = $username.'2'; - } else { - $username = $matches[1][0].($matches[2][0]+1); - } - - if ($DB->record_exists('user', array('username'=>$username, 'mnethostid'=>$mnethostid))) { - return increment_username($username, $mnethostid); - } else { - return $username; - } -} - -/** - * Check if default field contains templates and apply them. - * @param string template - potential tempalte string - * @param object user object- we need username, firstname and lastname - * @return string field value - */ -function process_template($template, $user) { - if (strpos($template, '%') === false) { - return $template; - } - - // very very ugly hack! - global $template_globals; - $template_globals = new stdClass(); - $template_globals->username = isset($user->username) ? $user->username : ''; - $template_globals->firstname = isset($user->firstname) ? $user->firstname : ''; - $template_globals->lastname = isset($user->lastname) ? $user->lastname : ''; - - $result = preg_replace_callback('/(?username; break; - case 'f': $repl = $template_globals->firstname; break; - case 'l': $repl = $template_globals->lastname; break; - } - switch ($block[1]) { - case '+': $repl = $textlib->strtoupper($repl); break; - case '-': $repl = $textlib->strtolower($repl); break; - case '~': $repl = $textlib->strtotitle($repl); break; - } - if (!empty($block[2])) { - $repl = $textlib->substr($repl, 0 , $block[2]); - } - - return $repl; -} - -/** - * Returns list of auth plugins that are enabled and known to work. - */ -function uu_allowed_auths() { - global $CFG; - - // only following plugins are guaranteed to work properly - // TODO: add support for more plugins in 2.0 - $whitelist = array('manual', 'nologin', 'none', 'email'); - $plugins = get_enabled_auth_plugins(); - $choices = array(); - foreach ($plugins as $plugin) { - $choices[$plugin] = get_string('pluginname', "auth_{$plugin}"); - } - - return $choices; -} - -/** - * Returns list of roles that are assignable in courses - */ -function uu_allowed_roles() { - // let's cheat a bit, frontpage is guaranteed to exist and has the same list of roles ;-) - $roles = get_assignable_roles(get_context_instance(CONTEXT_COURSE, SITEID), ROLENAME_ORIGINALANDSHORT); - return array_reverse($roles, true); -} - -function uu_allowed_roles_cache() { - $allowedroles = get_assignable_roles(get_context_instance(CONTEXT_COURSE, SITEID), ROLENAME_SHORT); - foreach ($allowedroles as $rid=>$rname) { - $rolecache[$rid] = new stdClass(); - $rolecache[$rid]->id = $rid; - $rolecache[$rid]->name = $rname; - if (!is_numeric($rname)) { // only non-numeric shortnames are supported!!! - $rolecache[$rname] = new stdClass(); - $rolecache[$rname]->id = $rid; - $rolecache[$rname]->name = $rname; - } - } - return $rolecache; -} diff --git a/admin/uploaduser_form.php b/admin/uploaduser_form.php index 956ecdb6ade..fe5311698ab 100644 --- a/admin/uploaduser_form.php +++ b/admin/uploaduser_form.php @@ -1,16 +1,44 @@ . -if (!defined('MOODLE_INTERNAL')) { - die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page -} +/** + * Bulk user upload forms + * + * @package core + * @subpackage admin + * @copyright 2007 Dan Poltawski + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); require_once $CFG->libdir.'/formslib.php'; -class admin_uploaduser_form1 extends moodleform { - function definition (){ - global $CFG, $USER; - $mform =& $this->_form; +/** + * Upload a file CVS file with user information. + * + * @package core + * @subpackage admin + * @copyright 2007 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class admin_uploaduser_form1 extends moodleform { + function definition () { + $mform = $this->_form; $mform->addElement('header', 'settingsheader', get_string('upload')); @@ -36,69 +64,90 @@ class admin_uploaduser_form1 extends moodleform { $mform->addElement('select', 'previewrows', get_string('rowpreviewnum', 'admin'), $choices); $mform->setType('previewrows', PARAM_INT); - $choices = array(UU_ADDNEW => get_string('uuoptype_addnew', 'admin'), - UU_ADDINC => get_string('uuoptype_addinc', 'admin'), - UU_ADD_UPDATE => get_string('uuoptype_addupdate', 'admin'), - UU_UPDATE => get_string('uuoptype_update', 'admin')); - $mform->addElement('select', 'uutype', get_string('uuoptype', 'admin'), $choices); - $this->add_action_buttons(false, get_string('uploadusers', 'admin')); } } + +/** + * Specify user upload details + * + * @package core + * @subpackage admin + * @copyright 2007 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ class admin_uploaduser_form2 extends moodleform { - function definition (){ + function definition () { global $CFG, $USER; - $mform =& $this->_form; - $columns =& $this->_customdata; + $mform = $this->_form; + $columns = $this->_customdata['columns']; + $data = $this->_customdata['data']; // I am the template user, why should it be the administrator? we have roles now, other ppl may use this script ;-) $templateuser = $USER; // upload settings and file $mform->addElement('header', 'settingsheader', get_string('settings')); - $mform->addElement('static', 'uutypelabel', get_string('uuoptype', 'admin') ); + + $choices = array(UU_USER_ADDNEW => get_string('uuoptype_addnew', 'admin'), + UU_USER_ADDINC => get_string('uuoptype_addinc', 'admin'), + UU_USER_ADD_UPDATE => get_string('uuoptype_addupdate', 'admin'), + UU_USER_UPDATE => get_string('uuoptype_update', 'admin')); + $mform->addElement('select', 'uutype', get_string('uuoptype', 'admin'), $choices); $choices = array(0 => get_string('infilefield', 'auth'), 1 => get_string('createpasswordifneeded', 'auth')); $mform->addElement('select', 'uupasswordnew', get_string('uupasswordnew', 'admin'), $choices); $mform->setDefault('uupasswordnew', 1); - $mform->disabledIf('uupasswordnew', 'uutype', 'eq', UU_UPDATE); + $mform->disabledIf('uupasswordnew', 'uutype', 'eq', UU_USER_UPDATE); - $choices = array(0 => get_string('nochanges', 'admin'), - 1 => get_string('uuupdatefromfile', 'admin'), - 2 => get_string('uuupdateall', 'admin'), - 3 => get_string('uuupdatemissing', 'admin')); + $choices = array(UU_UPDATE_NOCHANGES => get_string('nochanges', 'admin'), + UU_UPDATE_FILEOVERRIDE => get_string('uuupdatefromfile', 'admin'), + UU_UPDATE_ALLOVERRIDE => get_string('uuupdateall', 'admin'), + UU_UPDATE_MISSING => get_string('uuupdatemissing', 'admin')); $mform->addElement('select', 'uuupdatetype', get_string('uuupdatetype', 'admin'), $choices); - $mform->setDefault('uuupdatetype', 0); - $mform->disabledIf('uuupdatetype', 'uutype', 'eq', UU_ADDNEW); - $mform->disabledIf('uuupdatetype', 'uutype', 'eq', UU_ADDINC); + $mform->setDefault('uuupdatetype', UU_UPDATE_NOCHANGES); + $mform->disabledIf('uuupdatetype', 'uutype', 'eq', UU_USER_ADDNEW); + $mform->disabledIf('uuupdatetype', 'uutype', 'eq', UU_USER_ADDINC); $choices = array(0 => get_string('nochanges', 'admin'), 1 => get_string('update')); $mform->addElement('select', 'uupasswordold', get_string('uupasswordold', 'admin'), $choices); $mform->setDefault('uupasswordold', 0); - $mform->disabledIf('uupasswordold', 'uutype', 'eq', UU_ADDNEW); - $mform->disabledIf('uupasswordold', 'uutype', 'eq', UU_ADDINC); + $mform->disabledIf('uupasswordold', 'uutype', 'eq', UU_USER_ADDNEW); + $mform->disabledIf('uupasswordold', 'uutype', 'eq', UU_USER_ADDINC); $mform->disabledIf('uupasswordold', 'uuupdatetype', 'eq', 0); $mform->disabledIf('uupasswordold', 'uuupdatetype', 'eq', 3); + $choices = array(UU_PWRESET_WEAK => get_string('usersweakpassword', 'admin'), + UU_PWRESET_NONE => get_string('none'), + UU_PWRESET_ALL => get_string('all')); + if (empty($CFG->passwordpolicy)) { + unset($choices[UU_PWRESET_WEAK]); + } + $mform->addElement('select', 'uuforcepasswordchange', get_string('forcepasswordchange', 'core'), $choices); + + $mform->addElement('selectyesno', 'uuallowrenames', get_string('allowrenames', 'admin')); $mform->setDefault('uuallowrenames', 0); - $mform->disabledIf('uuallowrenames', 'uutype', 'eq', UU_ADDNEW); - $mform->disabledIf('uuallowrenames', 'uutype', 'eq', UU_ADDINC); + $mform->disabledIf('uuallowrenames', 'uutype', 'eq', UU_USER_ADDNEW); + $mform->disabledIf('uuallowrenames', 'uutype', 'eq', UU_USER_ADDINC); $mform->addElement('selectyesno', 'uuallowdeletes', get_string('allowdeletes', 'admin')); $mform->setDefault('uuallowdeletes', 0); - $mform->disabledIf('uuallowdeletes', 'uutype', 'eq', UU_ADDNEW); - $mform->disabledIf('uuallowdeletes', 'uutype', 'eq', UU_ADDINC); + $mform->disabledIf('uuallowdeletes', 'uutype', 'eq', UU_USER_ADDNEW); + $mform->disabledIf('uuallowdeletes', 'uutype', 'eq', UU_USER_ADDINC); $mform->addElement('selectyesno', 'uunoemailduplicates', get_string('uunoemailduplicates', 'admin')); $mform->setDefault('uunoemailduplicates', 1); - $choices = array(0 => get_string('no'), - 1 => get_string('uubulknew', 'admin'), - 2 => get_string('uubulkupdated', 'admin'), - 3 => get_string('uubulkall', 'admin')); + $mform->addElement('selectyesno', 'uustandardusernames', get_string('uustandardusernames', 'admin')); + $mform->setDefault('uustandardusernames', 1); + + $choices = array(UU_BULK_NONE => get_string('no'), + UU_BULK_NEW => get_string('uubulknew', 'admin'), + UU_BULK_UPDATED => get_string('uubulkupdated', 'admin'), + UU_BULK_ALL => get_string('uubulkall', 'admin')); $mform->addElement('select', 'uubulk', get_string('uubulk', 'admin'), $choices); $mform->setDefault('uubulk', 0); @@ -152,18 +201,22 @@ class admin_uploaduser_form2 extends moodleform { // default values $mform->addElement('header', 'defaultheader', get_string('defaultvalues', 'admin')); - $mform->addElement('text', 'username', get_string('username'), 'size="20"'); + $mform->addElement('text', 'username', get_string('uuusernametemplate', 'admin'), 'size="20"'); $mform->addRule('username', get_string('requiredtemplate', 'admin'), 'required', null, 'client'); + $mform->disabledIf('username', 'uutype', 'eq', UU_USER_ADD_UPDATE); + $mform->disabledIf('username', 'uutype', 'eq', UU_USER_UPDATE); + + $mform->addElement('text', 'email', get_string('email'), 'maxlength="100" size="30"'); + $mform->disabledIf('email', 'uutype', 'eq', UU_USER_ADD_UPDATE); + $mform->disabledIf('email', 'uutype', 'eq', UU_USER_UPDATE); // only enabled and known to work plugins - $choices = uu_allowed_auths(); + $choices = uu_supported_auths(); $mform->addElement('select', 'auth', get_string('chooseauthmethod','auth'), $choices); $mform->setDefault('auth', 'manual'); // manual is a sensible backwards compatible default $mform->addHelpButton('auth', 'chooseauthmethod', 'auth'); $mform->setAdvanced('auth'); - $mform->addElement('text', 'email', get_string('email'), 'maxlength="100" size="30"'); - $choices = array(0 => get_string('emaildisplayno'), 1 => get_string('emaildisplayyes'), 2 => get_string('emaildisplaycourse')); $mform->addElement('select', 'maildisplay', get_string('emaildisplay'), $choices); $mform->setDefault('maildisplay', 2); @@ -272,27 +325,30 @@ class admin_uploaduser_form2 extends moodleform { $mform->addElement('hidden', 'previewrows'); $mform->setType('previewrows', PARAM_INT); - $mform->addElement('hidden', 'readcount'); - $mform->setType('readcount', PARAM_INT); - - $mform->addElement('hidden', 'uutype'); - $mform->setType('uutype', PARAM_INT); - $this->add_action_buttons(true, get_string('uploadusers', 'admin')); + + $this->set_data($data); } /** * Form tweaks that depend on current data. */ function definition_after_data() { - $mform =& $this->_form; - $columns =& $this->_customdata; + $mform = $this->_form; + $columns = $this->_customdata['columns']; foreach ($columns as $column) { if ($mform->elementExists($column)) { $mform->removeElement($column); } } + + if (!in_array('password', $columns)) { + // password resetting makes sense only if password specified in csv file + if ($mform->elementExists('uuforcepasswordchange')) { + $mform->removeElement('uuforcepasswordchange'); + } + } } /** @@ -300,19 +356,19 @@ class admin_uploaduser_form2 extends moodleform { */ function validation($data, $files) { $errors = parent::validation($data, $files); - $columns =& $this->_customdata; + $columns = $this->_customdata['columns']; $optype = $data['uutype']; // detect if password column needed in file if (!in_array('password', $columns)) { switch ($optype) { - case UU_UPDATE: + case UU_USER_UPDATE: if (!empty($data['uupasswordold'])) { $errors['uupasswordold'] = get_string('missingfield', 'error', 'password'); } break; - case UU_ADD_UPDATE: + case UU_USER_ADD_UPDATE: if (empty($data['uupasswordnew'])) { $errors['uupasswordnew'] = get_string('missingfield', 'error', 'password'); } @@ -321,12 +377,12 @@ class admin_uploaduser_form2 extends moodleform { } break; - case UU_ADDNEW: + case UU_USER_ADDNEW: if (empty($data['uupasswordnew'])) { $errors['uupasswordnew'] = get_string('missingfield', 'error', 'password'); } break; - case UU_ADDINC: + case UU_USER_ADDINC: if (empty($data['uupasswordnew'])) { $errors['uupasswordnew'] = get_string('missingfield', 'error', 'password'); } @@ -335,7 +391,7 @@ class admin_uploaduser_form2 extends moodleform { } // look for other required data - if ($optype != UU_UPDATE) { + if ($optype != UU_USER_UPDATE) { if (!in_array('firstname', $columns)) { $errors['uutype'] = get_string('missingfield', 'error', 'firstname'); } @@ -369,7 +425,7 @@ class admin_uploaduser_form2 extends moodleform { function get_data() { $data = parent::get_data(); - if ($data !== null) { + if ($data !== null and isset($data->description)) { $data->descriptionformat = $data->description['format']; $data->description = $data->description['text']; } @@ -377,11 +433,3 @@ class admin_uploaduser_form2 extends moodleform { return $data; } } - -class admin_uploaduser_form3 extends moodleform { - function definition (){ - global $CFG, $USER; - $mform =& $this->_form; - $this->add_action_buttons(false, get_string('uploadnewfile')); - } -} diff --git a/admin/uploaduserlib.php b/admin/uploaduserlib.php new file mode 100644 index 00000000000..7df9290268f --- /dev/null +++ b/admin/uploaduserlib.php @@ -0,0 +1,335 @@ +. + +/** + * Bulk user registration functions + * + * @package core + * @subpackage admin + * @copyright 2004 onwards Martin Dougiamas (http://dougiamas.com) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +define('UU_USER_ADDNEW', 0); +define('UU_USER_ADDINC', 1); +define('UU_USER_ADD_UPDATE', 2); +define('UU_USER_UPDATE', 3); + +define('UU_UPDATE_NOCHANGES', 0); +define('UU_UPDATE_FILEOVERRIDE', 1); +define('UU_UPDATE_ALLOVERRIDE', 2); +define('UU_UPDATE_MISSING', 3); + +define('UU_BULK_NONE', 0); +define('UU_BULK_NEW', 1); +define('UU_BULK_UPDATED', 2); +define('UU_BULK_ALL', 3); + +define('UU_PWRESET_NONE', 0); +define('UU_PWRESET_WEAK', 1); +define('UU_PWRESET_ALL', 2); + +/** + * Tracking of processed users. + * + * This class prints user information into a html table. + * + * @package core + * @subpackage admin + * @copyright 2007 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class uu_progress_tracker { + private $_row; + public $columns = array('status', 'line', 'id', 'username', 'firstname', 'lastname', 'email', 'password', 'auth', 'enrolments', 'deleted'); + + /** + * Print table header. + * @return void + */ + public function start() { + $ci = 0; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + $this->_row = null; + } + + /** + * Flush previous line and start a new one. + * @return void + */ + public function flush() { + if (empty($this->_row) or empty($this->_row['line']['normal'])) { + // Nothing to print - each line has to have at least number + $this->_row = array(); + foreach ($this->columns as $col) { + $this->_row[$col] = array('normal'=>'', 'info'=>'', 'warning'=>'', 'error'=>''); + } + return; + } + $ci = 0; + $ri = 1; + echo ''; + foreach ($this->_row as $key=>$field) { + foreach ($field as $type=>$content) { + if ($field[$type] !== '') { + $field[$type] = ''.$field[$type].''; + } else { + unset($field[$type]); + } + } + echo ''; + } + echo ''; + foreach ($this->columns as $col) { + $this->_row[$col] = array('normal'=>'', 'info'=>'', 'warning'=>'', 'error'=>''); + } + } + + /** + * Add tracking info + * @param string $col name of column + * @param string $msg message + * @param string $level 'normal', 'warning' or 'error' + * @param bool $merge true means add as new line, false means override all previous text of the same type + * @return void + */ + public function track($col, $msg, $level = 'normal', $merge = true) { + if (empty($this->_row)) { + $this->flush(); //init arrays + } + if (!in_array($col, $this->columns)) { + debugging('Incorrect column:'.$col); + return; + } + if ($merge) { + if ($this->_row[$col][$level] != '') { + $this->_row[$col][$level] .='
'; + } + $this->_row[$col][$level] .= $msg; + } else { + $this->_row[$col][$level] = $msg; + } + } + + /** + * Print the table end + * @return void + */ + public function close() { + $this->flush(); + echo '
'.get_string('status').''.get_string('uucsvline', 'admin').'ID'.get_string('username').''.get_string('firstname').''.get_string('lastname').''.get_string('email').''.get_string('password').''.get_string('authentication').''.get_string('enrolments', 'enrol').''.get_string('delete').'
'; + if (!empty($field)) { + echo implode('
', $field); + } else { + echo ' '; + } + echo '
'; + } +} + +/** + * Validation callback function - verified the column line of csv file. + * Converts column names to lowercase too. + * @param csv_import_reader $cir + * @param array standard user fields + * @param array custom profile fields + * @param moodle_url $returnurl return url in case of any error + * @return array list of fields + */ +function uu_validate_user_upload_columns(csv_import_reader $cir, $stdfields, $frofilefields, moodle_url $returnurl) { + $columns = $cir->get_columns(); + + if (empty($columns)) { + $cir->close(); + $cir->cleanup(); + print_error('cannotreadtmpfile', 'error', $returnurl); + } + if (count($columns) < 2) { + $cir->close(); + $cir->cleanup(); + print_error('csvfewcolumns', 'error', $returnurl); + } + + // test columns + $processed = array(); + foreach ($columns as $key=>$unused) { + $field = strtolower($columns[$key]); // no unicode expected here, ignore case + if (!in_array($field, $stdfields) && !in_array($field, $frofilefields) &&// if not a standard field and not an enrolment field, then we have an error + !preg_match('/^course\d+$/', $field) && !preg_match('/^group\d+$/', $field) && + !preg_match('/^type\d+$/', $field) && !preg_match('/^role\d+$/', $field) && + !preg_match('/^enrolperiod\d+$/', $field)) { + print_error('invalidfieldname', 'error', $returnurl, $field); + } + if (in_array($field, $processed)) { + $cir->close(); + $cir->cleanup(); + print_error('duplicatefieldname', 'error', $returnurl, $field); + } + $processed[$key] = $field; + } + + return $processed; +} + +/** + * Increments username - increments trailing number or adds it if not present. + * Varifies that the new username does not exist yet + * @param string $username + * @return incremented username which does not exist yet + */ +function uu_increment_username($username) { + global $DB, $CFG; + + if (!preg_match_all('/(.*?)([0-9]+)$/', $username, $matches)) { + $username = $username.'2'; + } else { + $username = $matches[1][0].($matches[2][0]+1); + } + + if ($DB->record_exists('user', array('username'=>$username, 'mnethostid'=>$CFG->mnet_localhost_id))) { + return uu_increment_username($username); + } else { + return $username; + } +} + +/** + * Check if default field contains templates and apply them. + * @param string template - potential tempalte string + * @param object user object- we need username, firstname and lastname + * @return string field value + */ +function uu_process_template($template, $user) { + if (is_array($template)) { + // hack for for support of text editors with format + $t = $template['text']; + } else { + $t = $template; + } + if (strpos($t, '%') === false) { + return $template; + } + + $username = isset($user->username) ? $user->username : ''; + $firstname = isset($user->firstname) ? $user->firstname : ''; + $lastname = isset($user->lastname) ? $user->lastname : ''; + + $callback = partial('uu_process_template_callback', $username, $firstname, $lastname); + + $result = preg_replace_callback('/(?strtoupper($repl); break; + case '-': $repl = $textlib->strtolower($repl); break; + case '~': $repl = $textlib->strtotitle($repl); break; + } + if (!empty($block[2])) { + $repl = $textlib->substr($repl, 0 , $block[2]); + } + + return $repl; +} + +/** + * Returns list of auth plugins that are enabled and known to work. + * + * If ppl want to use some other auth type they have to include it + * in the CSV file next on each line. + * + * @return array type=>name + */ +function uu_supported_auths() { + // only following plugins are guaranteed to work properly + $whitelist = array('manual', 'nologin', 'none', 'email'); + $plugins = get_enabled_auth_plugins(); + $choices = array(); + foreach ($plugins as $plugin) { + if (!in_array($plugin, $whitelist)) { + continue; + } + $choices[$plugin] = get_string('pluginname', "auth_{$plugin}"); + } + + return $choices; +} + +/** + * Returns list of roles that are assignable in courses + * @return array + */ +function uu_allowed_roles() { + // let's cheat a bit, frontpage is guaranteed to exist and has the same list of roles ;-) + $roles = get_assignable_roles(get_context_instance(CONTEXT_COURSE, SITEID), ROLENAME_ORIGINALANDSHORT); + return array_reverse($roles, true); +} + +/** + * Returns mapping of all roles using short role name as index. + * @return array + */ +function uu_allowed_roles_cache() { + $allowedroles = get_assignable_roles(get_context_instance(CONTEXT_COURSE, SITEID), ROLENAME_SHORT); + foreach ($allowedroles as $rid=>$rname) { + $rolecache[$rid] = new stdClass(); + $rolecache[$rid]->id = $rid; + $rolecache[$rid]->name = $rname; + if (!is_numeric($rname)) { // only non-numeric shortnames are supported!!! + $rolecache[$rname] = new stdClass(); + $rolecache[$rname]->id = $rid; + $rolecache[$rname]->name = $rname; + } + } + return $rolecache; +} diff --git a/auth/manual/db/upgrade.php b/auth/manual/db/upgrade.php new file mode 100644 index 00000000000..dcfe7bd21ff --- /dev/null +++ b/auth/manual/db/upgrade.php @@ -0,0 +1,49 @@ +. + +/** + * Manual authentication plugin upgrade code + * + * @package auth + * @subpackage manual + * @copyright 2011 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * @param int $oldversion the version we are upgrading from + * @return bool result + */ +function xmldb_auth_manual_upgrade($oldversion) { + global $CFG, $DB, $OUTPUT; + + if ($oldversion < 2011022700) { + // force creation of missing passwords + $createpassword = hash_internal_user_password(''); + $rs = $DB->get_recordset('user', array('password'=>$createpassword, 'auth'=>'manual')); + foreach ($rs as $user) { + if (validate_email($user->email)) { + $DB->set_field('user', 'password', 'to be created', array('id'=>$user->id)); + unset_user_preference('auth_forcepasswordchange', $user); + set_user_preference('create_password', 1, $user); + } + } + $rs->close(); + upgrade_plugin_savepoint(true, 2011022700, 'auth', 'manual'); + } + + return true; +} diff --git a/auth/manual/version.php b/auth/manual/version.php new file mode 100644 index 00000000000..a8edb8e94cf --- /dev/null +++ b/auth/manual/version.php @@ -0,0 +1,29 @@ +. + +/** + * Manual authentication plugin version information + * + * @package auth + * @subpackage manual + * @copyright 2011 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->version = 2011022700; +$plugin->component = 'auth_manual'; \ No newline at end of file diff --git a/lang/en/admin.php b/lang/en/admin.php index 02fde935601..d11e5ff52d9 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -1053,6 +1053,7 @@ $string['useexternalyui'] = 'Use online YUI libraries'; $string['usehtmleditor'] = 'Use HTML editor'; $string['user'] = 'User'; $string['useraccountupdated'] = 'User updated'; +$string['useraccountuptodate'] = 'User up-to-date'; $string['userbulk'] = 'Bulk user actions'; $string['userdeleted'] = 'User deleted'; $string['userlist'] = 'Browse list of users'; @@ -1082,13 +1083,15 @@ $string['uuoptype_addinc'] = 'Add all, append number to usernames if needed'; $string['uuoptype_addnew'] = 'Add new only, skip existing users'; $string['uuoptype_addupdate'] = 'Add new and update existing users'; $string['uuoptype_update'] = 'Update existing users only'; +$string['uupasswordcron'] = 'Generated in cron'; $string['uupasswordnew'] = 'New user password'; $string['uupasswordold'] = 'Existing user password'; -$string['uupreprocessedcount'] = 'Number of preprocessed records: {$a}'; +$string['uustandardusernames'] = 'Standardise usernames'; $string['uuupdateall'] = 'Override with file and defaults'; $string['uuupdatefromfile'] = 'Override with file'; $string['uuupdatemissing'] = 'Fill in missing from file and defaults'; $string['uuupdatetype'] = 'Existing user details'; +$string['uuusernametemplate'] = 'Username template'; $string['validateerror'] = 'This value was not valid:'; $string['verifychangedemail'] = 'Restrict domains when changing email'; $string['warningcurrentsetting'] = 'Invalid current value: {$a}'; diff --git a/lang/en/error.php b/lang/en/error.php index 2a8df114210..cc945cff311 100755 --- a/lang/en/error.php +++ b/lang/en/error.php @@ -200,6 +200,7 @@ $string['dmltransactionexception'] = 'Database transaction error'; $string['dmlwriteexception'] = 'Error writing to database'; $string['downgradedcore'] = 'ERROR!!! The code you are using is OLDER than the version that made these databases!'; $string['downloadedfilecheckfailed'] = 'Downloaded file check failed'; +$string['duplicatefieldname'] = 'Duplicate field name "{$a}" detected'; $string['duplicateparaminsql'] = 'ERROR: duplicate parameter name in query'; $string['duplicaterolename'] = 'There is already a role with this name!'; $string['duplicateroleshortname'] = 'There is already a role with this short name!'; diff --git a/lang/en/moodle.php b/lang/en/moodle.php index 9e38f1c9f5c..7c9d27dff65 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -1672,11 +1672,8 @@ $string['uploadedfileto'] = 'Uploaded {$a->file} to {$a->directory}'; $string['uploadedfiletoobig'] = 'Sorry, but that file is too big (limit is {$a} bytes)'; $string['uploadextension'] = 'File upload stopped by extension'; $string['uploadfailednotrecovering'] = 'Your file upload has failed because there was a problem with one of the files, {$a->name}.
Here is a log of the problems:
{$a->problem}
Not recovering.'; -$string['uploadfilecontainerror'] = 'The uploaded file has not been processed due to the error(s) specified. Please amend the file before uploading it again.'; -$string['uploadfilecontentsnovaliddata'] = 'The uploaded file contains no valid data.'; $string['uploadfilelog'] = 'Upload log for file {$a}'; $string['uploadformlimit'] = 'Uploaded file exceeded the maximum size limit set by the form'; -$string['uploadinvalidpreprocessedcount'] = 'Number of invalid preprocessed records: {$a}'; $string['uploadlabel'] = 'Title:'; $string['uploadnewfile'] = 'Upload new file'; $string['uploadnofilefound'] = 'No file was found - are you sure you selected one to upload?'; diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 4fe7651c05c..abdb8153912 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -6043,6 +6043,14 @@ WHERE gradeitemid IS NOT NULL AND grademax IS NOT NULL"); upgrade_main_savepoint(true, 2011020900.08); } + if ($oldversion < 2011022100.01) { + // hack alert: inject missing version of manual auth_plugin, + // we need to do it so that we may use upgrade.php there + + set_config('version', 2011022100, 'auth_manual'); + upgrade_main_savepoint(true, 2011022100.01); + } + return true; } diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 41d32983127..e1d5a6e3f9d 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -4831,8 +4831,7 @@ function setnew_password_and_mail($user) { /** * Resets specified user's password and send the new password to the user via email. * - * @global object - * @param user $user A {@link $USER} object + * @param stdClass $user A {@link $USER} object * @return bool Returns true if mail was sent OK and false if there was an error. */ function reset_password_and_mail($user) { @@ -4866,6 +4865,8 @@ function reset_password_and_mail($user) { $subject = format_string($site->fullname) .': '. get_string('changedpassword'); + unset_user_preference('create_password', $user); // prevent cron from generating the password + //directly email rather than using the messaging system to ensure its not routed to a popup or jabber return email_to_user($user, $supportuser, $subject, $message); diff --git a/login/change_password.php b/login/change_password.php index 2bdb401320e..2608079a004 100644 --- a/login/change_password.php +++ b/login/change_password.php @@ -111,7 +111,8 @@ if ($mform->is_cancelled()) { } // register success changing password - unset_user_preference('auth_forcepasswordchange', $USER->id); + unset_user_preference('auth_forcepasswordchange', $USER); + unset_user_preference('create_password', $USER); $strpasswordchanged = get_string('passwordchanged'); diff --git a/user/editadvanced.php b/user/editadvanced.php index bc99881a2b5..4a1f4ecd8d5 100644 --- a/user/editadvanced.php +++ b/user/editadvanced.php @@ -165,6 +165,7 @@ if ($usernew = $userform->get_data()) { if (!$authplugin->user_update_password($usernew, $usernew->newpassword)){ print_error('cannotupdatepasswordonextauth', '', '', $usernew->auth); } + unset_user_preference('create_password', $usernew); // prevent cron from generating the password } } $usercreated = false; diff --git a/version.php b/version.php index 0b05d606446..7287adaf4fe 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2011022100.00; // YYYYMMDD = date of the last version bump +$version = 2011022100.01; // YYYYMMDD = date of the last version bump // XX = daily increments $release = '2.0.2+ (Build: 20110223)'; // Human-friendly version name