/// Bulk user registration script from a comma separated file
/// Returns list of users with their user ids
-require_once('../config.php');
+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('uploaduser_form.php');
-$uplid = optional_param('uplid', '', PARAM_FILE);
+$iid = optional_param('iid', '', PARAM_INT);
$previewrows = optional_param('previewrows', 10, PARAM_INT);
-$separator = optional_param('separator', 'comma', PARAM_ALPHA);
+$readcount = optional_param('readcount', 0, PARAM_INT);
-if (!defined('UP_LINE_MAX_SIZE')) {
- define('UP_LINE_MAX_SIZE', 4096);
-}
+define('UU_ADDNEW', 0);
+define('UU_ADDINC', 1);
+define('UU_ADD_UPDATE', 2);
+define('UU_UPDATE', 3);
@set_time_limit(3600); // 1 hour should be enough
@raise_memory_limit('256M');
if (function_exists('apache_child_terminate')) {
- // if we are running from Apache, give httpd a hint that
- // it can recycle the process after it's done. Apache's
+ // if we are running from Apache, give httpd a hint that
+ // it can recycle the process after it's done. Apache's
// memory management is truly awful but we can help it.
@apache_child_terminate();
}
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');
+$strusernotrenamedoff = get_string('usernotrenamedoff', 'error');
+$strusernotrenamedadmin = get_string('usernotrenamedadmin', 'error');
+
+$struserupdated = get_string('useraccountupdated', 'admin');
+$strusernotupdated = get_string('usernotupdatederror', 'error');
+$strusernotupdatednotexists = get_string('usernotupdatednotexists', 'error');
+$strusernotupdatedadmin = get_string('usernotupdatedadmin', 'error');
+
+$struseradded = get_string('newuser');
+$strusernotadded = get_string('usernotaddedregistered', 'error');
+$strusernotaddederror = get_string('usernotaddederror', 'error');
+
+$struserdeleted = get_string('userdeleted', 'admin');
+$strusernotdeletederror = get_string('usernotdeletederror', 'error');
+$strusernotdeletedmissing = get_string('usernotdeletedmissing', 'error');
+$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');
+
+
+$errorstr = get_string('error');
-$struserrenamed = get_string('userrenamed', 'admin');
-$strusernotrenamedexists = get_string('usernotrenamedexists', 'error');
-$strusernotrenamedmissing = get_string('usernotrenamedmissing', 'error');
-
-$struserupdated = get_string('useraccountupdated', 'admin');
-$strusernotupdated = get_string('usernotupdatederror', 'error');
-
-$struseradded = get_string('newuser');
-$strusernotadded = get_string('usernotaddedregistered', 'error');
-$strusernotaddederror = get_string('usernotaddederror', 'error');
-
-$struserdeleted = get_string('userdeleted', 'admin');
-$strusernotdeletederror = get_string('usernotdeletederror', 'error');
-$strusernotdeletedmissing = get_string('usernotdeletedmissing', 'error');
-
-$strcannotassignrole = get_string('cannotassignrole', 'error');
-$strduplicateusername = get_string('duplicateusername', 'error');
-$strindent = '-->';
-
-$return = $CFG->wwwroot.'/'.$CFG->admin.'/uploaduser.php';
-
-// make arrays of valid fields for error checking
-// the value associated to each field is: 0 = optional field, 1 = field required either in default values or in data file
-$fields = array(
- 'firstname' => 1,
- 'lastname' => 1,
- 'username' => 1,
- 'email' => 1,
- 'city' => 1,
- 'country' => 1,
- 'lang' => 1,
- 'auth' => 1,
- 'timezone' => 1,
- 'mailformat' => 1,
- 'maildisplay' => 1,
- 'htmleditor' => 0,
- 'ajax' => 0,
- 'autosubscribe' => 1,
- 'mnethostid' => 0,
- 'institution' => 0,
- 'department' => 0,
- 'idnumber' => 0,
- 'icq' => 0,
- 'phone1' => 0,
- 'phone2' => 0,
- 'address' => 0,
- 'url' => 0,
- 'description' => 0,
- 'icq' => 0,
- 'oldusername' => 0,
- 'emailstop' => 1,
- 'deleted' => 0,
- 'password' => 0, // changed later
-);
-
-if (empty($uplid)) {
+$returnurl = $CFG->wwwroot.'/'.$CFG->admin.'/uploaduser.php';
+$bulknurl = $CFG->wwwroot.'/'.$CFG->admin.'/user/user_bulk.php';
+
+// array of all valid fields for validation
+$STD_FIELDS = array('firstname', 'lastname', 'username', 'email', 'city', 'country', 'lang', 'auth', 'timezone', 'mailformat', 'maildisplay', 'htmleditor',
+ 'ajax', 'autosubscribe', 'mnethostid', 'institution', 'department', 'idnumber', 'icq', 'phone1', 'phone2', 'address', 'url', 'description',
+ 'icq', 'oldusername', 'emailstop', 'deleted', 'password');
+
+$PRF_FIELDS = array();
+
+if ($prof_fields = $fields = get_records_select('user_info_field')) {
+ foreach ($prof_fields as $prof_field) {
+ $PRF_FIELDS[] = 'profile_field_'.$prof_field->shortname;
+ }
+ unset($prof_fields);
+}
+
+if (empty($iid)) {
$mform = new admin_uploaduser_form1();
if ($formdata = $mform->get_data()) {
- if (!$filename = make_upload_directory('temp/uploaduser/'.$USER->id, true)) {
- error('Can not create temporary upload directory!', $return);
- }
- // use current (non-conflicting) time stamp
- $uplid = time();
- while (file_exists($filename.'/'.$uplid)) {
- $uplid--;
- }
- $filename = $filename.'/'.$uplid;
-
- $text = $mform->get_file_content('userfile');
- // convert to utf-8 encoding
- $text = $textlib->convert($text, $formdata->encoding, 'utf-8');
- // remove Unicode BOM from first line
- $text = $textlib->trim_utf8_bom($text);
- // Fix mac/dos newlines
- $text = preg_replace('!\r\n?!', "\n", $text);
- //remove empty lines at the beginning and end
- $text = trim($text);
-
- // verify each line has the same number of separators - this detects major breakage in files
- $line = strtok($text, "\n");
- if ($line === false) {
- error('Empty file', $return); //TODO: localize
- }
-
- // test headers
- $csv_delimiter = get_upload_csv_delimiter($separator);
- $col_count = substr_count($line, $csv_delimiter);
- if ($col_count < 2) {
- error('Not enough columns, please verify the separator setting!', $return); //TODO: localize
- }
+ $iid = csv_import_reader::get_new_iid('uploaduser');
+ $cir = new csv_import_reader($iid, 'uploaduser');
- $line = explode($csv_delimiter, $line);
- foreach ($line as $key => $value) {
- $value = trim($value); // remove whitespace
- if (!array_key_exists($value, $fields) && // if not a standard field and not an enrolment field, then we have an error
- !preg_match('/^course\d+$/', $value) && !preg_match('/^group\d+$/', $value) &&
- !preg_match('/^type\d+$/', $value) && !preg_match('/^role\d+$/', $value)) {
- error(get_string('invalidfieldname', 'error', $value), $return);
- }
- }
+ $content = $mform->get_file_content('userfile');
- $line = strtok("\n");
- if ($line === false) {
- error('Only one row present, can not continue!', $return); //TODO: localize
- }
+ $readcount = $cir->load_csv_content($content, $formdata->encoding, $formdata->delimiter_name, 'validate_user_upload_columns');
+ unset($content);
- while ($line !== false) {
- if (substr_count($line, $csv_delimiter) !== $col_count) {
- error('Incorrect file format - number of columns is not constant!', $return); //TODO: localize
- }
- $line = strtok("\n");
+ if ($readcount === false) {
+ error($cir->get_error(), $returnurl);
+ } else if ($readcount == 0) {
+ error(get_string('csvemptyfile', 'error'), $returnurl);
}
-
- // store file
- $fp = fopen($filename, "w");
- fwrite($fp,$text);
- fclose($fp);
- // continue to second form
+ // continue to form2
} else {
admin_externalpage_print_header();
admin_externalpage_print_footer();
die;
}
+} else {
+ $cir = new csv_import_reader($iid, 'uploaduser');
}
-$mform = new admin_uploaduser_form2();
-// set initial date from form1
-$mform->set_data(array('separator'=>$separator, 'uplid'=>$uplid, 'previewrows'=>$previewrows));
+if (!$columns = $cir->get_columns()) {
+ error('Error reading temporary file', $returnurl);
+}
+$mform = new admin_uploaduser_form2(null, $columns);
+// get initial date from form1
+$mform->set_data(array('iid'=>$iid, 'previewrows'=>$previewrows, 'readcount'=>$readcount));
// If a file has been uploaded, then process it
if ($formdata = $mform->is_cancelled()) {
- user_upload_cleanup($uplid);
- redirect($return);
+ $cir->cleanup(true);
+ redirect($returnurl);
-} else if ($formdata = $mform->get_data()) {
+} else if ($formdata = $mform->get_data(false)) { // no magic quotes here!!!
// Print the header
admin_externalpage_print_header();
- print_heading(get_string('uploadusers'));
+ print_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;
+ $bulk = $formdata->uubulk;
+
+ // 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;
+
+ // caches
+ $ccache = array(); // course cache - do not fetch all courses here, we will not probably use them all anyway!
+ $rolecache = array(); // roles lookup cache
+
+ $allowedauths = uu_allowed_auths();
+ $allowedauths = array_keys($allowedauths);
+ $availableauths = get_list_of_plugins('auth');
+
+ $allowedroles = uu_allowed_roles(true);
+ foreach ($allowedroles as $rid=>$rname) {
+ $rolecache[$rid] = new object();
+ $rolecache[$rid]->id = $rid;
+ $rolecache[$rid]->name = $rname;
+ if (!is_numeric($rname)) { // only non-numeric shornames are supported!!!
+ $rolecache[$rname] = new object();
+ $rolecache[$rname]->id = $rid;
+ $rolecache[$rname]->name = $rname;
+ }
+ }
+ unset($allowedroles);
- $createpassword = $formdata->createpassword;
- $updateaccounts = $formdata->updateaccounts;
- $allowrenames = $formdata->allowrenames;
- $skipduplicates = $formdata->duplicatehandling;
+ // clear bilk selection
+ if ($bulk) {
+ $SESSION->bulk_susers = array();
+ }
- $fields['password'] = !$createpassword;
+ // init csv import helper
+ $cir->init();
+ $linenum = 1; //column header is first line
- $filename = $CFG->dataroot.'/temp/uploaduser/'.$USER->id.'/'.$uplid;
- if (!file_exists($filename)) {
- user_upload_cleanup($uplid);
- error('Error reading temporary file!', $return); //TODO: localize
- }
- if (!$fp = fopen($filename, "r")) {
- user_upload_cleanup($uplid);
- error('Error reading temporary file!', $return); //TODO: localize
- }
-
- $csv_delimiter = get_upload_csv_delimiter($separator);
- $csv_encode = get_upload_csv_encode($csv_delimiter);
-
- // find header row
- $headers = array();
- $linenum = 1;
- $line = explode($csv_delimiter, fgets($fp, UP_LINE_MAX_SIZE));
-
- // prepare headers
- foreach ($line as $key => $value) {
- $headers[$key] = trim($value);
- }
+ // init upload progress tracker
+ $upt = new uu_progress_tracker();
+ $upt->init(); // start table
- // check that required fields are present or a default value for them exists
- $headersOk = true;
- // disable the check if we also have deleting information (ie. deleted column)
- if (!in_array('deleted', $headers)) {
- foreach ($fields as $key => $required) {
- if($required && !in_array($key, $headers) && (!isset($formdata->$key) || $formdata->$key==='')) {
- notify(get_string('missingfield', 'error', $key));
- $headersOk = false;
+ while ($line = $cir->next()) {
+ $upt->flush();
+ $linenum++;
+
+ $upt->track('line', $linenum);
+
+ $user = new object();
+ // 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];
+ // password is special field
+ if ($key == 'password') {
+ if ($value !== '') {
+ $user->password = hash_internal_user_password($value);
+ }
+ } else {
+ $user->$key = $value;
+ if (in_array($key, $upt->columns)) {
+ $upt->track($key, $value);
+ }
+ }
}
}
- }
- if ($headersOk) {
- $usersnew = 0;
- $usersupdated = 0;
- $userserrors = 0;
- $usersdeleted = 0;
- $renames = 0;
- $renameerrors = 0;
- $deleteerrors = 0;
- $newusernames = array();
- // We'll need courses a lot, so fetch it early and keep it in memory, indexed by their shortname
- $tmp =& get_courses('all','','id,shortname,visible');
- $courses = array();
- foreach ($tmp as $c) {
- $courses[$c->shortname] = $c;
+
+ // 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++;
+ continue;
+ }
+
+ } else {
+ $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');
+ $error = true;
+ }
+ if (!isset($user->lastname) or $user->lastname === '') {
+ $upt->track('status', get_string('missingfield', 'error', 'lastname'), 'error');
+ $upt->track('lastname', $errorstr, 'error');
+ $error = true;
+ }
+ if ($error) {
+ $userserrors++;
+ 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);
+ }
+ }
}
- unset($tmp);
-
- echo '<p id="results">';
- while (!feof($fp)) {
- $linenum++;
- $line = explode($csv_delimiter, fgets($fp, UP_LINE_MAX_SIZE));
- $errors = '';
- $user = new object();
- // 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 = $headers[$key];
- //decode encoded commas
- $value = str_replace($csv_encode,$csv_delimiter,trim($value));
- // special fields: password and username
- if ($key == 'password' && !empty($value)) {
- $user->$key = hash_internal_user_password($value);
- } else if($key == 'username') {
- $value = $textlib->strtolower(addslashes($value));
- if(empty($CFG->extendedusernamechars)) {
- $value = eregi_replace('[^(-\.[:alnum:])]', '', $value);
- }
- @$newusernames[$value]++;
- $user->$key = $value;
- } else {
- $user->$key = addslashes($value);
- }
+
+ // normalize username
+ $user->username = $textlib->strtolower($user->username);
+ if (empty($CFG->extendedusernamechars)) {
+ $user->username = eregi_replace('[^(-\.[:alnum:])]', '', $user->username);
+ }
+ if (empty($user->username)) {
+ $upt->track('status', get_string('missingfield', 'error', 'username'), 'error');
+ $upt->track('username', $errorstr, 'error');
+ $userserrors++;
+ continue;
+ }
+
+ if ($existinguser = get_record('user', 'username', addslashes($user->username), 'mnethostid', $user->mnethostid)) {
+ $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');
+ $existinguser = false;
+ }
+
+ // add default values for remaining fields
+ foreach ($STD_FIELDS as $field) {
+ if (isset($user->$field)) {
+ continue;
+ }
+ // all validation moved to form2
+ if (isset($formdata->$field)) {
+ // process templates
+ $user->$field = process_template($formdata->$field, $user);
+ }
+ }
+ foreach ($PRF_FIELDS as $field) {
+ if (isset($user->$field)) {
+ continue;
+ }
+ if (isset($formdata->$field)) {
+ // process templates
+ $user->$field = process_template($formdata->$field, $user);
+ }
+ }
+
+ // delete user
+ if (!empty($user->deleted)) {
+ if (!$allowdeletes) {
+ $usersskipped++;
+ $upt->track('status', $strusernotdeletedoff, 'warning');
+ continue;
+ }
+ if ($existinguser) {
+ if (has_capability('moodle/site:doanything', $systemcontext, $existinguser->id)) {
+ $upt->track('status', $strusernotdeletedadmin, 'error');
+ $deleteerrors++;
+ continue;
+ }
+ if (delete_user($existinguser)) {
+ $upt->track('status', $struserdeleted);
+ $deletes++;
+ } else {
+ $upt->track('status', $strusernotdeletederror, 'error');
+ $deleteerrors++;
}
+ } else {
+ $upt->track('status', $strusernotdeletedmissing, 'error');
+ $deleteerrors++;
+ }
+ continue;
+ }
+ // we do not need the deleted flag anymore
+ unset($user->deleted);
+
+ // renaming requested?
+ if (!empty($user->oldusername) ) {
+ $oldusername = $textlib->strtolower($user->oldusername);
+ if (!$allowrenames) {
+ $usersskipped++;
+ $upt->track('status', $strusernotrenamedoff, 'warning');
+ continue;
+ }
+
+ if ($existinguser) {
+ $upt->track('status', $strusernotrenamedexists, 'error');
+ $renameerrors++;
+ continue;
}
- // add default values for remaining fields
- foreach ($fields as $key => $required) {
- if(isset($user->$key)) {
+ if ($olduser = get_record('user', 'username', addslashes($oldusername), 'mnethostid', $user->mnethostid)) {
+ $upt->track('id', $olduser->id, 'normal', false);
+ if (has_capability('moodle/site:doanything', $systemcontext, $olduser->id)) {
+ $upt->track('status', $strusernotrenamedadmin, 'error');
+ $renameerrors++;
continue;
}
- if(!isset($formdata->$key) || $formdata->$key==='') { // no default value was submited
- // if the field is required, give an error only if we are adding the user or deleting a user with unkown username
- if($required && (empty($user->deleted) || $key == 'username')) {
- $errors .= get_string('missingfield', 'error', $key) . ' ';
- }
+ if (set_field('user', 'username', addslashes($user->username), 'id', $olduser->id)) {
+ $upt->track('username', '', 'normal', false); // clear previous
+ $upt->track('username', $oldusername.'-->'.$user->username, 'info');
+ $upt->track('status', $struserrenamed);
+ $renames++;
+ } else {
+ $upt->track('status', $strusernotrenamedexists, 'error');
+ $renameerrors++;
continue;
}
- // process templates
- $template = $formdata->$key;
- $templatelen = strlen($template);
- $value = '';
- for ($i = 0 ; $i < $templatelen; ++$i) {
- if($template[$i] == '%') {
- $case = 0; // 1=lowercase, 2=uppercase
- $len = 0; // number of characters to keep
- $info = null; // data to process
- for($j = $i + 1; is_null($info) && $j < $templatelen; ++$j) {
- $car = $template[$j];
- if ($car >= '0' && $car <= '9') {
- $len = $len * 10 + (int)$car;
- } else if($car == '-') {
- $case = 1;
- } else if($car == '+') {
- $case = 2;
- } else if($car == 'f') { // first name
- $info = @$user->firstname;
- } else if($car == 'l') { // last name
- $info = @$user->lastname;
- } else if($car == 'u') { // username
- $info = @$user->username;
- } else if($car == '%' && $j == $i+1) {
- $info = '%';
- } else { // invalid character
- $info = '';
- }
- }
- if($info==='' || is_null($info)) { // invalid template
+ } else {
+ $upt->track('status', $strusernotrenamedmissing, 'error');
+ $renameerrors++;
+ continue;
+ }
+ $existinguser = $olduser;
+ $existinguser->username = $user->username;
+ }
+
+ // can we process with update or insert?
+ $skip = false;
+ switch ($optype) {
+ case UU_ADDNEW:
+ if ($existinguser) {
+ $usersskipped++;
+ $upt->track('status', $strusernotadded, 'warning');
+ $skip = true;;
+ }
+ break;
+
+ case UU_ADDINC:
+ if ($existinguser) {
+ //this should not happen!
+ $upt->track('status', $strusernotaddederror, 'error');
+ $userserrors++;
+ continue;
+ }
+ break;
+
+ case UU_ADD_UPDATE:
+ break;
+
+ case UU_UPDATE:
+ if (!$existinguser) {
+ $usersskipped++;
+ $upt->track('status', $strusernotupdatednotexists, 'warning');
+ $skip = true;
+ }
+ break;
+ }
+
+ if ($skip) {
+ continue;
+ }
+
+ if ($existinguser) {
+ $user->id = $existinguser->id;
+
+ if (has_capability('moodle/site:doanything', $systemcontext, $user->id)) {
+ $upt->track('status', $strusernotupdatedadmin, 'error');
+ $userserrors++;
+ continue;
+ }
+
+ if (!$updatetype) {
+ // no updates of existing data at all
+ } else {
+ $existinguser->timemodified = time();
+ //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) {
+ if ($column == 'username') {
+ continue;
+ }
+ if ($column == 'password') {
+ if (!$updatepasswords or $updatetype == 3) {
continue;
+ } else if (!empty($user->password)) {
+ $upt->track('password', get_string('updated'));
}
- $i = $j - 1;
- // change case
- if($case == 1) {
- $info = $textlib->strtolower($info);
- } else if($case == 2) {
- $info = $textlib->strtoupper($info);
+ }
+ if ((array_key_exists($column, $existinguser) and array_key_exists($column, $user)) or in_array($column, $PRF_FIELDS)) {
+ if ($updatetype == 3 and $existinguser->$column !== '') {
+ //missing == non-empty only
+ continue;
}
- if($len) { // truncate data
- $info = $textlib->substr($info, 0, $len);
+ if ($existinguser->$column !== $user->$column) {
+ if ($column != 'password' and in_array($column, $upt->columns)) {
+ $upt->track($column, '', 'normal', false); // clear previous
+ $upt->track($column, $existinguser->$column.'-->'.$user->$column, 'info');
+ }
+ $existinguser->$column = $user->$column;
}
- $value .= $info;
- } else {
- $value .= $template[$i];
}
}
- if($key == 'username') {
- $value = $textlib->strtolower($value);
- if(empty($CFG->extendedusernamechars)) {
- $value = eregi_replace('[^(-\.[:alnum:])]', '', $value);
- }
- @$newusernames[$value]++;
- // check for new username duplicates
- if($newusernames[$value] > 1) {
- if($skipduplicates) {
- $errors .= $strduplicateusername . ' (' . stripslashes($value) . '). ';
- continue;
- } else {
- $value .= $newusernames[$value];
- }
- }
+ // do not update record if new auth plguin 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');
}
- $user->$key = $value;
- }
- if($errors) {
- notify(get_string('erroronline', 'error', $linenum). ': ' . $errors);
- ++$userserrors;
- continue;
- }
- // delete user
- if(@$user->deleted) {
- $info = ': ' . stripslashes($user->username) . '. ';
- if($user =& get_record('user', 'username', $user->username, 'mnethostid', $user->mnethostid)) {
- $user->timemodified = time();
- $user->username = addslashes($user->email . $user->timemodified); // Remember it just in case
- $user->deleted = 1;
- $user->email = ''; // Clear this field to free it up
- $user->idnumber = ''; // Clear this field to free it up
- if (update_record('user', $user)) {
- // not sure if this is needed. unenrol_student($user->id); // From all courses
- delete_records('role_assignments', 'userid', $user->id); // unassign all roles
- // remove all context assigned on this user?
- echo $struserdeleted . $info . '<br />';
- ++$usersdeleted;
- } else {
- notify(get_string('erroronline', 'error', $linenum). ': ' . $strusernotdeletederror . $info);
- ++$deleteerrors;
- }
+ if (update_record('user', addslashes_recursive($existinguser))) {
+ $upt->track('status', $struserupdated);
+ $usersupdated++;
} else {
- notify(get_string('erroronline', 'error', $linenum). ': ' . $strusernotdeletedmissing . $info);
- ++$deleteerrors;
+ $upt->track('status', $strusernotupdated, 'error');
+ $userserrors++;
+ continue;
+ }
+ // save custom profile fields data from csv file
+ profile_save_data(addslashes_recursive($existinguser));
+ }
+
+ if ($bulk == 2 or $bulk == 3) {
+ if (!in_array($user->id, $SESSION->bulk_susers)) {
+ $SESSION->bulk_susers[] = $user->id;
}
- continue;
}
+ } else {
// save the user to the database
$user->confirmed = 1;
$user->timemodified = time();
- // before insert/update, check whether we should be updating an old record instead
- if ($allowrenames && !empty($user->oldusername) ) {
- $user->oldusername = $textlib->strtolower($user->oldusername);
- $info = ': ' . stripslashes($user->oldusername) . '-->' . stripslashes($user->username) . '. ';
- if ($olduser =& get_record('user', 'username', $user->oldusername, 'mnethostid', $user->mnethostid)) {
- if (set_field('user', 'username', $user->username, 'id', $olduser->id)) {
- echo $struserrenamed . $info;
- $renames++;
- } else {
- notify(get_string('erroronline', 'error', $linenum). ': ' . $strusernotrenamedexists . $info);
- $renameerrors++;
- continue;
- }
- } else {
- notify(get_string('erroronline', 'error', $linenum). ': ' . $strusernotrenamedmissing . $info);
- $renameerrors++;
+ if (!$createpasswords and empty($user->password)) {
+ $upt->track('password', get_string('missingfield', 'error', 'password'), 'error');
+ $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');
}
}
- // save the information
- if ($olduser =& get_record('user', 'username', $user->username, 'mnethostid', $user->mnethostid)) {
- $user->id = $olduser->id;
- $info = ': ' . stripslashes($user->username) .' (ID = ' . $user->id . ')';
- if ($updateaccounts) {
- // Record is being updated
- if (update_record('user', $user)) {
- echo $struserupdated . $info . '<br />';
- $usersupdated++;
- } else {
- notify(get_string('erroronline', 'error', $linenum). ': ' . $strusernotupdated . $info);
- $userserrors++;
- continue;
- }
- } else {
- //Record not added - user is already registered
- //In this case, output userid from previous registration
- //This can be used to obtain a list of userids for existing users
- echo $strusernotadded . $info . '<br />';
- $userserrors++;
+ if ($user->id = insert_record('user', addslashes_recursive($user))) {
+ $info = ': ' . $user->username .' (ID = ' . $user->id . ')';
+ $upt->track('status', $struseradded);
+ $upt->track('id', $user->id, 'normal', false);
+ $usersnew++;
+ if ($createpasswords and empty($user->password)) {
+ // 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'));
}
- } else { // new user
- if ($user->id = insert_record('user', $user)) {
- $info = ': ' . stripslashes($user->username) .' (ID = ' . $user->id . ')';
- echo $struseradded . $info . '<br />';
- $usersnew++;
- if (empty($user->password) && $createpassword) {
- // 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);
- }
- } else {
- // Record not added -- possibly some other error
- notify(get_string('erroronline', 'error', $linenum). ': ' . $strusernotaddederror . ': ' . stripslashes($user->username));
- $userserrors++;
- continue;
+ } else {
+ // Record not added -- possibly some other error
+ $upt->track('status', $strusernotaddederror, 'error');
+ $userserrors++;
+ continue;
+ }
+ // save custom profile fields data
+ profile_save_data($user);
+
+ if ($bulk == 1 or $bulk == 3) {
+ if (!in_array($user->id, $SESSION->bulk_susers)) {
+ $SESSION->bulk_susers[] = $user->id;
}
}
+ }
+
+ // find course enrolments, groups and roles/types
+ foreach ($columns as $column) {
+ if (!preg_match('/^course\d+$/', $column)) {
+ continue;
+ }
+ $i = substr($column, 6);
- // find course enrolments, groups and roles/types
- for($ncourses = 1; $addcourse = @$user->{'course' . $ncourses}; ++$ncourses) {
- // find course
- if(!$course = @$courses[$addcourse]) {
- notify(get_string('erroronline', 'error', $linenum). ': ' . get_string('unknowncourse', 'error', $addcourse));
+ $shortname = $user->{'course'.$i};
+ if (!array_key_exists($shortname, $ccache)) {
+ if (!$course = get_record('course', 'shortname', $shortname, '', '', '', '', 'id, shortname, defaultrole')) {
+ $upt->track('enrolments', get_string('unknowncourse', 'error', $shortname), 'error');
continue;
}
- // find role
- if ($addrole = @$user->{'role' . $ncourses}) {
- $coursecontext =& get_context_instance(CONTEXT_COURSE, $course->id);
- if (!$ok = role_assign($addrole, $user->id, 0, $coursecontext->id)) {
- echo $strindent . $strcannotassignrole . '<br >';
- }
+ $ccache[$shortname] = $course;
+ $ccache[$shortname]->groups = null;
+ }
+ $courseid = $ccache[$shortname]->id;
+ $coursecontext = get_context_instance(CONTEXT_COURSE, $courseid);
+
+ // find role
+ $rid = false;
+ if (!empty($user->{'role'.$i})) {
+ $addrole = $user->{'role'.$i};
+ if (array_key_exists($addrole, $rolecache)) {
+ $rid = $rolecache[$addrole]->id;
} else {
- // if no role, then find "old" enrolment type
- switch ($addtype = @$user->{'type' . $ncourses}) {
- case 2: // teacher
- $ok = add_teacher($user->id, $course->id, 1);
- break;
- case 3: // non-editing teacher
- $ok = add_teacher($user->id, $course->id, 0);
- break;
- case 1: // student
- default:
- $ok = enrol_student($user->id, $course->id);
- break;
+ $upt->track('enrolments', get_string('unknownrole', 'error', $addrole), 'error');
+ continue;
+ }
+
+ } else if (!empty($user->{'type'.$i})) {
+ // if no role, then find "old" enrolment type
+ $addtype = $user->{'type'.$i};
+ if ($addtype < 1 or $addtype > 3) {
+ $upt->track('enrolments', $strerror.': typeN = 1|2|3', 'error');
+ continue;
+ } else if ($addtype == 1 and empty($formdata->uulegacy1)) {
+ if (empty($ccache[$shortname]->defaultrole)) {
+ $rid = $CFG->defaultcourseroleid;
+ } else {
+ $rid = $ccache[$shortname]->defaultrole;
}
+ } else {
+ $rid = $formdata->{'uulegacy'.$addtype};
+ }
+
+ } else {
+ // no role specified, use the default
+ if (empty($ccache[$shortname]->defaultrole)) {
+ $rid = $CFG->defaultcourseroleid;
+ } else {
+ $rid = $ccache[$shortname]->defaultrole;
}
- if ($ok) { // OK
- echo $strindent . get_string('enrolledincourse', '', $addcourse) . '<br />';
+ }
+ if ($rid) {
+ $a = new object();
+ $a->course = $shortname;
+ $a->role = $rolecache[$rid]->name;
+ if (role_assign($rid, $user->id, 0, $coursecontext->id)) {
+ $upt->track('enrolments', get_string('enrolledincourserole', '', $a));
} else {
- notify(get_string('erroronline', 'error', $linenum). ': ' . get_string('enrolledincoursenot', '', $addcourse));
+ $upt->track('enrolments', get_string('enrolledincoursenotrole', '', $a), 'error');
}
+ }
- // find group to add to
- if ($addgroup = @$user->{'group' . $ncourses}) {
- if ($gid =& groups_get_group_by_name($course->id, $addgroup)) {
- $coursecontext =& get_context_instance(CONTEXT_COURSE, $course->id);
- if (count(get_user_roles($coursecontext, $user->id))) {
- if (groups_add_member($gid, $user->id)) {
- echo $strindent . get_string('addedtogroup','',$addgroup) . '<br />';
- } else {
- notify(get_string('erroronline', 'error', $linenum). ': ' . get_string('addedtogroupnot','',$addgroup));
+ // find group to add to
+ if (!empty($user->{'group'.$i})) {
+ // make sure user is enrolled into course before adding into groups
+ if (!has_capability('moodle/course:view', $coursecontext, $user->id, false)) {
+ $upt->track('enrolments', get_string('addedtogroupnotenrolled', '', $gname), 'error');
+ continue;
+ }
+ //build group cache
+ if (is_null($ccache[$shortname]->groups)) {
+ $ccache[$shortname]->groups = array();
+ if ($groups = get_groups($courseid)) {
+ foreach ($groups as $gid=>$group) {
+ $ccache[$shortname]->groups[$gid] = new object();
+ $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 object();
+ $ccache[$shortname]->groups[$group->name]->id = $gid;
+ $ccache[$shortname]->groups[$group->name]->name = $group->name;
}
- } else {
- notify(get_string('erroronline', 'error', $linenum). ': ' . get_string('addedtogroupnotenrolled','',$addgroup));
}
- } else {
- notify(get_string('erroronline', 'error', $linenum). ': ' . get_string('groupunknown','error',$addgroup));
}
}
+ // group exists?
+ $addgroup = $user->{'group'.$i};
+ if (!array_key_exists($addgroup, $ccache[$shortname]->groups)) {
+ $upt->track('enrolments', get_string('unknowgroup', 'error', $addgroup), 'error');
+ continue;
+ }
+ $gid = $ccache[$shortname]->groups[$addgroup]->id;
+ $gname = $ccache[$shortname]->groups[$addgroup]->name;
+
+ if (groups_add_member($gid, $user->id)) {
+ $upt->track('enrolments', get_string('addedtogroup', '', $gname));
+ } else {
+ $upt->track('enrolments', get_string('addedtogroupnot', '', $gname), 'error');
+ continue;
+ }
}
}
- echo '</p>';
- notify(get_string('userscreated', 'admin') . ': ' . $usersnew);
- notify(get_string('usersupdated', 'admin') . ': ' . $usersupdated);
- notify(get_string('usersdeleted', 'admin') . ': ' . $usersdeleted);
- notify(get_string('deleteerrors', 'admin') . ': ' . $deleteerrors);
- if ($allowrenames) {
- notify(get_string('usersrenamed', 'admin') . ': ' . $renames);
- notify(get_string('renameerrors', 'admin') . ': ' . $renameerrors);
- }
- notify(get_string('errors', 'admin') . ': ' . $userserrors);
}
- fclose($fp);
- user_upload_cleanup($uplid);
- echo '<hr />';
- print_continue($return);
+ $upt->flush();
+ $upt->close(); // close table
+
+ $cir->close();
+ $cir->cleanup(true);
+
+ print_box_start('boxwidthnarrow boxaligncenter generalbox', 'uploadresults');
+ echo '<p>';
+ if ($optype != UU_UPDATE) {
+ echo get_string('userscreated', 'admin').': '.$usersnew.'<br />';
+ }
+ if ($optype == UU_UPDATE or $optype == UU_ADD_UPDATE) {
+ echo get_string('usersupdated', 'admin').': '.$usersupdated.'<br />';
+ }
+ if ($allowdeletes) {
+ echo get_string('usersdeleted', 'admin').': '.$deletes.'<br />';
+ echo get_string('deleteerrors', 'admin').': '.$deleteerrors.'<br />';
+ }
+ if ($allowrenames) {
+ echo get_string('usersrenamed', 'admin').': '.$renames.'<br />';
+ echo get_string('renameerrors', 'admin').': '.$renameerrors.'<br />';
+ }
+ if ($usersskipped) {
+ echo get_string('usersskipped', 'admin').': '.$usersskipped.'<br />';
+ }
+ echo get_string('errors', 'admin').': '.$userserrors.'</p>';
+ print_box_end();
+
+ if ($bulk) {
+ print_continue($bulknurl);
+ } else {
+ print_continue($returnurl);
+ }
admin_externalpage_print_footer();
die;
}
admin_externalpage_print_header();
/// Print the form
-print_heading_with_help(get_string('uploadusers'), 'uploadusers2');
-
-/// Print csv file preview
-$filename = $CFG->dataroot.'/temp/uploaduser/'.$USER->id.'/'.$uplid;
-if (!file_exists($filename)) {
- error('Error reading temporary file!', $return); //TODO: localize
-}
-if (!$fp = fopen($filename, "r")) {
- error('Error reading temporary file!', $return); //TODO: localize
-}
+print_heading_with_help(get_string('uploaduserspreview', 'admin'), 'uploadusers2');
-$csv_delimiter = get_upload_csv_delimiter($separator);
-$csv_encode = get_upload_csv_encode($csv_delimiter);
+$ci = 0;
+$ri = 0;
-$header = explode($csv_delimiter, fgets($fp, UP_LINE_MAX_SIZE));
-
-$width = count($header);
-$columncount = 0;
-$rowcount = 0;
-echo '<table class="flexible boxaligncenter generaltable">';
-echo '<tr class="heading r'.$rowcount++.'">';
-foreach ($header as $h) {
- echo '<th class="header c'.$columncount++.'">'.trim($h).'</th>';
+echo '<table id="uupreview" class="generaltable boxaligncenter" summary="'.get_string('uploaduserspreview', 'admin').'">';
+echo '<tr class="heading r'.$ri++.'">';
+foreach ($columns as $col) {
+ echo '<th class="header c'.$ci++.'" scope="col">'.s($col).'</th>';
}
echo '</tr>';
-while (!feof($fp) and $rowcount <= $previewrows+1) {
- $columncount = 0;
- $fields = explode($csv_delimiter, fgets($fp, UP_LINE_MAX_SIZE));
- echo '<tr class="r'.$rowcount++.'">';
- foreach ($fields as $field) {
- echo '<td class=" c'.$columncount++.'">'.trim(str_replace($csv_encode, $csv_delimiter, $field)).'</td>';;
+$cir->init();
+while ($fields = $cir->next()) {
+ if ($ri > $previewrows) {
+ echo '<tr class="r'.$ri++.'">';
+ foreach ($fields as $field) {
+ echo '<td class="cell c'.$ci++.'">...</td>';;
+ }
+ break;
}
- echo '</tr>';
-}
-if ($rowcount > $previewrows+1) {
- echo '<tr class="r'.$rowcount++.'">';
+ $ci = 0;
+ echo '<tr class="r'.$ri++.'">';
foreach ($fields as $field) {
- echo '<td class=" c'.$columncount++.'">...</td>';;
+ echo '<td class="cell c'.$ci++.'">'.s($field).'</td>';;
}
+ echo '</tr>';
}
-echo '</table>';
-fclose($fp);
+$cir->close();
+echo '</table>';
+echo '<div class="centerpara">'.get_string('uupreprocessedcount', 'admin', $readcount).'</div>';
$mform->display();
admin_externalpage_print_footer();
die;
-/////////////////////////
-/// Utility functions ///
-/////////////////////////
+/////////////////////////////////////
+/// 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 '<table id="uuresults" class="generaltable boxaligncenter" summary="'.get_string('uploadusersresult', 'admin').'">';
+ echo '<tr class="heading r0">';
+ echo '<th class="header c'.$ci++.'" scope="col">'.get_string('status').'</th>';
+ echo '<th class="header c'.$ci++.'" scope="col">'.get_string('uucsvline', 'admin').'</th>';
+ echo '<th class="header c'.$ci++.'" scope="col">ID</th>';
+ echo '<th class="header c'.$ci++.'" scope="col">'.get_string('username').'</th>';
+ echo '<th class="header c'.$ci++.'" scope="col">'.get_string('firstname').'</th>';
+ echo '<th class="header c'.$ci++.'" scope="col">'.get_string('lastname').'</th>';
+ echo '<th class="header c'.$ci++.'" scope="col">'.get_string('email').'</th>';
+ echo '<th class="header c'.$ci++.'" scope="col">'.get_string('password').'</th>';
+ echo '<th class="header c'.$ci++.'" scope="col">'.get_string('authentication').'</th>';
+ echo '<th class="header c'.$ci++.'" scope="col">'.get_string('enrolments').'</th>';
+ echo '<th class="header c'.$ci++.'" scope="col">'.get_string('delete').'</th>';
+ echo '</tr>';
+ $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 '<tr class="r'.$ri++.'">';
+ foreach ($this->_row as $field) {
+ foreach ($field as $type=>$content) {
+ if ($field[$type] !== '') {
+ $field[$type] = '<span class="uu'.$type.'">'.$field[$type].'</span>';
+ } else {
+ unset($field[$type]);
+ }
+ }
+ echo '<td class="cell c'.$ci++.'">';
+ if (!empty($field)) {
+ echo implode('<br />', $field);
+ } else {
+ echo ' ';
+ }
+ echo '</td>';
+ }
+ echo '</tr>';
+ 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] .='<br />';
+ }
+ $this->_row[$col][$level] .= s($msg);
+ } else {
+ $this->_row[$col][$level] = s($msg);
+ }
+ }
+
+ function close() {
+ echo '</table>';
+ }
+}
-function user_upload_cleanup($uplid) {
- global $USER, $CFG;
- if (empty($uplid)) {
- return;
+/**
+ * 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');
}
- $filename = $CFG->dataroot.'/temp/uploaduser/'.$USER->id.'/'.$uplid;
- if (file_exists($filename)) {
- @unlink($filename);
+
+ // 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)) {
+ return get_string('invalidfieldname', 'error', $field);
+ }
+ if (in_array($field, $processed)) {
+ return get_string('csvcolumnduplicates', 'error');
+ }
+ $processed[] = $field;
}
+ return true;
}
-function get_uf_headers($uplid, $separator) {
- global $USER, $CFG;
+/**
+ * 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) {
+ if (!preg_match_all('/(.*?)([0-9]+)$/', $username, $matches)) {
+ $username = $username.'2';
+ } else {
+ $username = $matches[1][0].($matches[2][0]+1);
+ }
+
+ if (record_exists('user', 'username', addslashes($username), 'mnethostid', $mnethostid)) {
+ return increment_username($username, $mnethostid);
+ } else {
+ return $username;
+ }
+}
- $filename = $CFG->dataroot.'/temp/uploaduser/'.$USER->id.'/'.$uplid;
- if (!file_exists($filename)) {
- return false;
+/**
+ * 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;
}
- $fp = fopen($filename, "r");
- $line = fgets($fp, 2048);
- fclose($fp);
- if ($line === false) {
- return false;
+
+ // very very ugly hack!
+ global $template_globals;
+ $template_globals = new object();
+ $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('/(?<!%)%([+-~])?(\d)*([flu])/', 'process_template_callback', $template);
+
+ $template_globals = null;
+
+ if (is_null($result)) {
+ return $template; //error during regex processing??
+ } else {
+ return $result;
}
+}
- $csv_delimiter = get_upload_csv_delimiter($separator);
- $headers = explode($csv_delimiter, $line);
- foreach($headers as $key=>$val) {
- $headers[$key] = trim($val);
+/**
+ * Internal callback function.
+ */
+function process_template_callback($block) {
+ global $template_globals;
+ $textlib = textlib_get_instance();
+ $repl = $block[0];
+
+ switch ($block[3]) {
+ case 'u': $repl = $template_globals->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 $headers;
+
+ return $repl;
}
-function get_upload_csv_delimiter($separator) {
+/**
+ * Returns list of auth plugins that are enabled and known to work.
+ */
+function uu_allowed_auths() {
global $CFG;
- switch ($separator) {
- case 'semicolon' : return ';';
- case 'colon' : return ':';
- case 'tab' : return "\t";
- case 'cfg' : return isset($CFG->CSV_DELIMITER) ? $CFG->CSV_DELIMITER : ',';
- default : return ',';
+ // only following plugins are guaranteed to work properly
+ // TODO: add support for more plguins in 2.0
+ $whitelist = array('manual', 'nologin', 'none', 'email');
+ $plugins = get_enabled_auth_plugins();
+ $choices = array();
+ foreach ($plugins as $plugin) {
+ $choices[$plugin] = get_string('auth_'.$plugin.'title', 'auth');
}
+
+ return $choices;
}
-function get_upload_csv_encode($delimiter) {
-//Note: commas within a field should be encoded as , (for comma separated csv files)
-//Note: semicolon within a field should be encoded as ; (for semicolon separated csv files)
+/**
+ * Returns list of non administrator roles
+ */
+function uu_allowed_roles($shortname=false) {
global $CFG;
- return '&#' . (isset($CFG->CSV_ENCODE) ? $CFG->CSV_ENCODE : ord($delimiter));
+
+ $roles = get_all_roles();
+ $choices = array();
+ foreach($roles as $role) {
+ if ($shortname) {
+ $choices[$role->id] = $role->shortname;
+ } else {
+ $choices[$role->id] = format_string($role->name);
+ }
+ }
+ // get rid of all admin roles
+ if ($adminroles = get_roles_with_capability('moodle/site:doanything', CAP_ALLOW)) {
+ foreach($adminroles as $adminrole) {
+ unset($choices[$adminrole->id]);
+ }
+ }
+
+ return $choices;
}
?>
function definition (){
global $CFG, $USER;
- $this->set_upload_manager(new upload_manager('userfile', false, false, null, false, 0, true, true, false));
-
$mform =& $this->_form;
+ $this->set_upload_manager(new upload_manager('userfile', false, false, null, false, 0, true, true, false));
+
$mform->addElement('header', 'settingsheader', get_string('upload'));
- $mform->addElement('file', 'userfile', get_string('file'));
+ $mform->addElement('file', 'userfile', get_string('file'), 'size="40"');
$mform->addRule('userfile', null, 'required');
- $choices = array('comma'=>',', 'semicolon'=>';', 'colon'=>':', 'tab'=>'\\t');
- if (isset($CFG->CSV_DELIMITER) and !in_array($CFG->CSV_DELIMITER, $choices)) {
- $choices['cfg'] = $CFG->CSV_DELIMITER;
- }
- $mform->addElement('select', 'separator', get_string('csvseparator', 'admin'), $choices);
+ $choices = csv_import_reader::get_delimiter_list();
+ $mform->addElement('select', 'delimiter_name', get_string('csvdelimiter', 'admin'), $choices);
if (array_key_exists('cfg', $choices)) {
- $mform->setDefault('separator', 'cfg');
+ $mform->setDefault('delimiter_name', 'cfg');
} else if (get_string('listsep') == ';') {
- $mform->setDefault('separator', 'semicolon');
+ $mform->setDefault('delimiter_name', 'semicolon');
} else {
- $mform->setDefault('separator', 'comma');
+ $mform->setDefault('delimiter_name', 'comma');
}
$textlib = textlib_get_instance();
function definition (){
global $CFG, $USER;
- $mform =& $this->_form;
+ //no editors here - we need proper empty fields
+ $CFG->htmleditor = null;
+
+ $mform =& $this->_form;
+ $columns =& $this->_customdata;
- // I am the tamplate user
+ // 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'));
- $choices = array(0 => get_string('infilefield', 'auth'), 1 => get_string('createpasswordifneeded', 'auth'));
- $mform->addElement('select', 'createpassword', get_string('passwordhandling', 'auth'), $choices);
+ $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);
- $mform->addElement('selectyesno', 'updateaccounts', get_string('updateaccounts', 'admin'));
- $mform->addElement('selectyesno', 'allowrenames', get_string('allowrenames', 'admin'));
+ $choices = array(0 => get_string('infilefield', 'auth'), 1 => get_string('createpasswordifneeded', 'auth'));
+ $mform->addElement('select', 'uupasswordnew', get_string('uupasswordnew', 'admin'), $choices);
+ $mform->disabledIf('uupasswordnew', 'uutype', 'eq', UU_UPDATE);
+
+ $choices = array(0 => get_string('nochanges', 'admin'),
+ 1 => get_string('uuupdatefromfile', 'admin'),
+ 2 => get_string('uuupdateall', 'admin'),
+ 3 => get_string('uuupdatemissing', 'admin'));
+ $mform->addElement('select', 'uuupdatetype', get_string('uuupdatetype', 'admin'), $choices);
+ $mform->disabledIf('uuupdatetype', 'uutype', 'eq', UU_ADDNEW);
+ $mform->disabledIf('uuupdatetype', 'uutype', 'eq', UU_ADDINC);
+
+ $choices = array(0 => get_string('nochanges', 'admin'), 1 => get_string('update'));
+ $mform->addElement('select', 'uupasswordold', get_string('uupasswordold', 'admin'), $choices);
+ $mform->disabledIf('uupasswordold', 'uutype', 'eq', UU_ADDNEW);
+ $mform->disabledIf('uupasswordold', 'uutype', 'eq', UU_ADDINC);
+ $mform->disabledIf('uupasswordold', 'uuupdatetype', 'eq', 0);
+ $mform->disabledIf('uupasswordold', 'uuupdatetype', 'eq', 3);
+
+ $mform->addElement('selectyesno', 'uuallowrenames', get_string('allowrenames', 'admin'));
+ $mform->disabledIf('uuallowrenames', 'uutype', 'eq', UU_ADDNEW);
+ $mform->disabledIf('uuallowrenames', 'uutype', 'eq', UU_ADDINC);
+
+ $mform->addElement('selectyesno', 'uuallowdeletes', get_string('allowdeletes', 'admin'));
+ $mform->disabledIf('uuallowdeletes', 'uutype', 'eq', UU_ADDNEW);
+ $mform->disabledIf('uuallowdeletes', 'uutype', 'eq', UU_ADDINC);
+
+ $choices = array(0 => get_string('no'),
+ 1 => get_string('uubulknew', 'admin'),
+ 2 => get_string('uubulkupdated', 'admin'),
+ 3 => get_string('uubulkall', 'admin'));
+ $mform->addElement('select', 'uubulk', get_string('uubulk', 'admin'), $choices);
+
+// roles selection
+ $showroles = false;
+ foreach ($columns as $column) {
+ if (preg_match('/^type\d+$/', $column)) {
+ $showroles = true;
+ break;
+ }
+ }
+ if ($showroles) {
+ $mform->addElement('header', 'rolesheader', get_string('roles'));
+
+ $choices = uu_allowed_roles(true);
+
+ $choices[0] = get_string('uucoursedefaultrole', 'admin');
+ $mform->addElement('select', 'uulegacy1', get_string('uulegacy1role', 'admin'), $choices);
+ $mform->setDefault('uulegacy1', 0);
+ unset($choices[0]);
+
+ $mform->addElement('select', 'uulegacy2', get_string('uulegacy2role', 'admin'), $choices);
+ if ($editteacherroles = get_roles_with_capability('moodle/legacy:editingteacher', CAP_ALLOW)) {
+ $editteacherrole = array_shift($editteacherroles); /// Take the first one
+ $mform->setDefault('uulegacy2', $editteacherrole->id);
+ unset($editteacherroles);
+ } else {
+ $mform->setDefault('uulegacy2', $CFG->defaultcourseroleid);
+ }
- $choices = array(0 => get_string('addcounter', 'admin'), 1 => get_string('skipuser', 'admin'));
- $mform->addElement('select', 'duplicatehandling', get_string('newusernamehandling', 'admin'), $choices);
- $mform->setDefault('duplicatehandling', 1); // better skip, bc and safer
+ $mform->addElement('select', 'uulegacy3', get_string('uulegacy3role', 'admin'), $choices);
+ if ($teacherroles = get_roles_with_capability('moodle/legacy:teacher', CAP_ALLOW)) {
+ $teacherrole = array_shift($teacherroles); /// Take the first one
+ $mform->setDefault('uulegacy3', $teacherrole->id);
+ unset($teacherroles);
+ } else {
+ $mform->setDefault('uulegacy3', $CFG->defaultcourseroleid);
+ }
+ }
// default values
$mform->addElement('header', 'defaultheader', get_string('defaultvalues', 'admin'));
+
$mform->addElement('text', 'username', get_string('username'), 'size="20"');
+ $mform->addRule('username', get_string('requiredtemplate', 'admin'), 'required', null, 'client');
- // only enabled plugins
- $aplugins = get_enabled_auth_plugins();
- $auth_options = array();
- foreach ($aplugins as $module) {
- $auth_options[$module] = get_string('auth_'.$module.'title', 'auth');
- }
- $mform->addElement('select', 'auth', get_string('chooseauthmethod','auth'), $auth_options);
+ // only enabled and known to work plugins
+ $choices = uu_allowed_auths();
+ $mform->addElement('select', 'auth', get_string('chooseauthmethod','auth'), $choices);
$mform->setDefault('auth', 'manual'); // manual is a sensible backwards compatible default
$mform->setHelpButton('auth', array('authchange', get_string('chooseauthmethod','auth')));
$mform->setAdvanced('auth');
$mform->setType('address', PARAM_MULTILANG);
$mform->setAdvanced('address');
-// hidden fields
- $mform->addElement('hidden', 'uplid');
- $mform->setType('uplid', PARAM_FILE);
+ /// Next the profile defaults
+ profile_definition($mform);
- $mform->addElement('hidden', 'separator');
- $mform->setType('separator', PARAM_ALPHA);
+// hidden fields
+ $mform->addElement('hidden', 'iid');
+ $mform->setType('iid', PARAM_INT);
$mform->addElement('hidden', 'previewrows');
- $mform->setType('previewrows', PARAM_ALPHA);
+ $mform->setType('previewrows', PARAM_INT);
+
+ $mform->addElement('hidden', 'readcount');
+ $mform->setType('readcount', PARAM_INT);
$this->add_action_buttons(true, get_string('uploadusers'));
}
+ /**
+ * Form tweaks that depend on current data.
+ */
function definition_after_data() {
- $mform =& $this->_form;
+ $mform =& $this->_form;
+ $columns =& $this->_customdata;
+
+ foreach ($columns as $column) {
+ if ($mform->elementExists($column)) {
+ $mform->removeElement($column);
+ }
+ }
+ }
+
+ /**
+ * Server side validation.
+ */
+ function validation($data) {
+ $errors = array();
+ $columns =& $this->_customdata;
+ $optype = $data['uutype'];
+
+ // detect if password column needed in file
+ if (!in_array('password', $columns)) {
+ switch ($optype) {
+ case UU_UPDATE:
+ if (!empty($data['uupasswordold'])) {
+ $errors['uupasswordold'] = get_string('missingfield', 'error', 'password');
+ }
+ break;
+
+ case UU_ADD_UPDATE:
+ if (empty($data['uupasswordnew'])) {
+ $errors['uupasswordnew'] = get_string('missingfield', 'error', 'password');
+ }
+ if (!empty($data['uupasswordold'])) {
+ $errors['uupasswordold'] = get_string('missingfield', 'error', 'password');
+ }
+ break;
+
+ case UU_ADDNEW:
+ case UU_ADDINC:
+ if (empty($data['uupasswordnew'])) {
+ $errors['uupasswordnew'] = get_string('missingfield', 'error', 'password');
+ }
+ break;
+ }
+ }
- $separator = $mform->getElementValue('separator');
- $uplid = $mform->getElementValue('uplid');
-
- if ($headers = get_uf_headers($uplid, $separator)) {
- foreach ($headers as $header) {
- if ($mform->elementExists($header)) {
- $mform->removeElement($header);
+ // look for other required data
+ if ($optype != UU_UPDATE) {
+ if (!in_array('firstname', $columns)) {
+ $errors['uutype'] = get_string('missingfield', 'error', 'firstname');
+ }
+
+ if (!in_array('lastname', $columns)) {
+ if (isset($errors['uutype'])) {
+ $errors['uutype'] = '';
+ } else {
+ $errors['uutype'] = ' ';
}
+ $errors['uutype'] .= get_string('missingfield', 'error', 'lastname');
}
+
+ if (!in_array('email', $columns) and empty($data['email'])) {
+ $errors['email'] = get_string('requiredtemplate', 'admin');
+ }
+
+ if (!in_array('city', $columns) and empty($data['city'])) {
+ $errors['city'] = get_string('required');
+ }
+ }
+
+ if (0 == count($errors)){
+ return true;
+ } else {
+ return $errors;
}
}
}