MDL-10181, user management improvements, adding improvements to bulk user upload (with minor bugs) and other changes

This commit is contained in:
toyomoyo 2007-08-20 08:51:35 +00:00
parent 2619224c8a
commit 066bfbfe77
11 changed files with 564 additions and 381 deletions

View File

@ -1,391 +1,363 @@
<?php // $Id$
<?php
/// Bulk user registration script from a comma separated file
/// Returns list of users with their user ids
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->dirroot.'/group/lib.php');
require_once($CFG->libdir.'/textlib.class.php');
require_once('uploaduser_form.php');
define('LINE_MAX_SIZE', 1024);
//Note: commas within a field should be encoded as &#44 (for comma separated csv files)
//Note: semicolon within a field should be encoded as &#59 (for semicolon separated csv files)
$csv_delimiter = isset($CFG->CSV_DELIMITER) ? $CFG->CSV_DELIMITER : ',';
$csv_encode = '&#' . (isset($CFG->CSV_ENCODE) ? $CFG->CSV_ENCODE : ord($csv_delimiter));
@set_time_limit(0);
@raise_memory_limit('192M');
admin_externalpage_setup('uploadusers');
require_capability('moodle/site:uploadusers', get_context_instance(CONTEXT_SYSTEM));
if (! $site = get_site()) {
error("Could not find site-level course");
error('Could not find site-level course');
}
if (!$adminuser = get_admin()) {
error("Could not find site admin");
}
$textlib =& textlib_get_instance();
$struser = get_string('user');
$strusersnew = get_string('usersnew');
$struserrenamed = get_string('userrenamed', 'admin');
$strusernotrenamedexists = get_string('usernotrenamedexists', 'error');
$strusernotrenamedmissing = get_string('usernotrenamedmissing', 'error');
$csv_encode = '/\&\#44/';
if (isset($CFG->CSV_DELIMITER)) {
$csv_delimiter = '\\' . $CFG->CSV_DELIMITER;
$csv_delimiter2 = $CFG->CSV_DELIMITER;
$struserupdated = get_string('useraccountupdated', 'admin');
$strusernotupdated = get_string('usernotupdatederror', 'error');
$strusernotadded = get_string('usernotaddedregistered', 'error');
if (isset($CFG->CSV_ENCODE)) {
$csv_encode = '/\&\#' . $CFG->CSV_ENCODE . '/';
}
} else {
$csv_delimiter = "\,";
$csv_delimiter2 = ",";
}
/// Print the header
admin_externalpage_print_header();
$struseradded = get_string('newuser');
$strusernotaddederror = get_string('usernotaddederror', 'error');
$strcannotassignrole = get_string('cannotassignrole', 'error');
$strduplicateusername = get_string('duplicateusername', 'error');
$strindent = '-->';
$mform = new admin_uploaduser_form();
/// If a file has been uploaded, then process it
// Print the header
admin_externalpage_print_header();
// If a file has been uploaded, then process it
if ( $formdata = $mform->get_data() ) {
$createpassword = $formdata->createpassword;
$updateaccounts = $formdata->updateaccounts;
$allowrenames = $formdata->allowrenames;
$filename = $mform->get_userfile_name();
$skipduplicates = $formdata->duplicatehandling;
// Large files are likely to take their time and memory. Let PHP know
// that we'll take longer, and that the process should be recycled soon
// to free up memory.
@set_time_limit(0);
@raise_memory_limit("192M");
if (function_exists('apache_child_terminate')) {
@apache_child_terminate();
// 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' => 1,
'autosubscribe' => 1,
'mnethostid' => 1,
'institution' => 0,
'department' => 0,
'idnumber' => 0,
'icq' => 0,
'phone1' => 0,
'phone2' => 0,
'address' => 0,
'url' => 0,
'description' => 0,
'icq' => 0,
'oldusername' => 0,
'emailstop' => 1,
'password' => !$createpassword,
);
$fp = fopen($mform->get_userfile_name(), 'r');
$linenum = 1; // since header is line 1
// get header (field names) and remove Unicode BOM from first line, if any
$line = explode($csv_delimiter, $textlib->trim_utf8_bom(fgets($fp,LINE_MAX_SIZE)));
// check for valid field names
$headers = array();
foreach ($line as $key => $value) {
$value = trim($value); // remove whitespace
if (!in_array($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), 'uploaduser.php?sesskey='.$USER->sesskey);
}
$headers[$key] = $value;
}
$text = my_file_get_contents($filename);
//trim utf-8 bom
$textlib = new textlib();
$text = $textlib->trim_utf8_bom($text);
//Fix mac/dos newlines
$text = preg_replace('!\r\n?!',"\n",$text);
$fp = fopen($filename, "w");
fwrite($fp,$text);
$usersnew = 0;
$usersupdated = 0;
$userserrors = 0;
$renames = 0;
$renameerrors = 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;
}
unset($tmp);
echo '<p id="results">';
while (!feof ($fp)) {
$user = new object();
// by default, use the local mnet id (this may be changed in the file)
$user->mnethostid = $CFG->mnet_localhost_id;
$line = explode($csv_delimiter, fgets($fp,LINE_MAX_SIZE));
++$linenum;
$ok = true;
// 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') {
$user->$key = addslashes($textlib->strtolower($value));
} else {
$user->$key = addslashes($value);
}
}
}
// add default values for remaining fields
foreach ($fields as $key => $value) {
if(isset($user->$key)) {
continue;
}
if(!isset($formdata->$key) || $formdata->$key==='') { // no default value was submited
if($value) { // the field is required
notify(get_string('erroronline', 'error', $linenum). ': ' .get_string('missingfield', 'error', $key));
$ok = false;
}
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
continue;
}
$i = $j - 1;
// change case
if($case == 1) {
$info = $textlib->strtolower($info);
} else if($case == 2) {
$info = $textlib->strtoupper($info);
}
if($len) { // truncate data
$info = $textlib->substr($info, 0, $len);
}
$value .= $info;
} else {
$value .= $template[$i];
}
}
if($key == 'username') {
$value = $textlib->strtolower($value);
if(empty($CFG->extendedusernamechars)) {
$value = eregi_replace('[^(-\.[:alnum:])]', '', $value);
}
// check for new username duplicates
if(empty($newusernames[$value])) {
$newusernames[$value] = 1;
} else {
if($skipduplicates) {
notify($strduplicateusername . ': ' . $value);
$ok = false;
continue;
} else {
++$newusernames[$value];
$value .= $newusernames[$value];
}
}
}
$user->$key = $value;
}
if(!$ok) {
++$userserrors;
continue;
}
$user->confirmed = 1;
$user->timemodified = time();
// save the user to the database
$username = $user->username;
// 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 = ': ' . $user->oldusername . '-->' . $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($strusernotrenamedexists . $info);
$renameerrors++;
continue;
}
} else {
notify($strusernotrenamedmissing . $info);
$renameerrors++;
continue;
}
}
// save the information
if ($olduser = get_record('user', 'username', $username, 'mnethostid', $user->mnethostid)) {
$user->id = $olduser->id;
$info = ': ' . $username .' (ID = ' . $user->id . ')';
if ($updateaccounts) {
// Record is being updated
if (update_record('user', $user)) {
echo $struserupdated . $info . '<br />';
$usersupdated++;
} else {
notify($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++;
}
} else { // new user
if ($user->id = insert_record('user', $user)) {
$info = ': ' . $username .' (ID = ' . $user->id . ')';
echo $struseradded . $info . '<br />';
$usersnew++;
if (empty($user->password) && $createpassword) {
// passwords will be created and sent out on cron
insert_record('user_preferences', array( 'userid' => $user->id, 'name' => 'create_password', 'value' => 1));
insert_record('user_preferences', array( 'userid' => $user->id, 'name' => 'auth_forcepasswordchange', 'value' => 1));
}
} else {
// Record not added -- possibly some other error
notify($strusernotaddederror . ': ' . $username);
$userserrors++;
continue;
}
}
// find course enrolments, groups and roles/types
for($ncourses = 1; $addcourse = @$user->{'course' . $ncourses}; ++$ncourses) {
// find course
if(!$course = @$courses[$addcourse]) {
notify(get_string('unknowncourse', 'error', $addcourse));
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 >';
}
} 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;
}
}
if ($ok) { // OK
echo $strindent . get_string('enrolledincourse', '', $addcourse) . '<br />';
} else {
notify(get_string('enrolledincoursenot', '', $addcourse));
}
// 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('addedtogroupnot','',$addgroup));
}
} else {
notify(get_string('addedtogroupnotenrolled','',$addgroup));
}
} else {
notify(get_string('groupunknown','error',$addgroup));
}
}
}
}
echo '</p>';
fclose($fp);
$fp = fopen($filename, "r");
// make arrays of valid fields for error checking
$required = array("username" => 1,
"password" => !$createpassword,
"firstname" => 1,
"lastname" => 1,
"email" => 1);
$optionalDefaults = array("mnethostid" => 1,
"institution" => 1,
"department" => 1,
"city" => 1,
"country" => 1,
"lang" => 1,
"auth" => 1,
"timezone" => 1);
$optional = array("idnumber" => 1,
"icq" => 1,
"phone1" => 1,
"phone2" => 1,
"address" => 1,
"url" => 1,
"description" => 1,
"mailformat" => 1,
"maildisplay" => 1,
"htmleditor" => 1,
"autosubscribe" => 1,
"idnumber" => 1,
"icq" => 1,
"course1" => 1,
"course2" => 1,
"course3" => 1,
"course4" => 1,
"course5" => 1,
"group1" => 1,
"group2" => 1,
"group3" => 1,
"group4" => 1,
"group5" => 1,
"type1" => 1,
"type2" => 1,
"type3" => 1,
"type4" => 1,
"type5" => 1,
"role1" => 1,
"role2" => 1,
"role3" => 1,
"role4" => 1,
"role5" => 1,
"password" => $createpassword,
"oldusername" => $allowrenames,
"emailstop" => 1);
// --- get header (field names) ---
$header = split($csv_delimiter, fgets($fp,1024));
// check for valid field names
foreach ($header as $i => $h) {
$h = trim($h); $header[$i] = $h; // remove whitespace
if (!(isset($required[$h]) or isset($optionalDefaults[$h]) or isset($optional[$h]))) {
error(get_string('invalidfieldname', 'error', $h), 'uploaduser.php?sesskey='.$USER->sesskey);
}
if (isset($required[$h])) {
$required[$h] = 0;
}
}
// check for required fields
foreach ($required as $key => $value) {
if ($value) { //required field missing
error(get_string('fieldrequired', 'error', $key), 'uploaduser.php?sesskey='.$USER->sesskey);
}
}
$linenum = 2; // since header is line 1
$usersnew = 0;
$usersupdated = 0;
$userserrors = 0;
$renames = 0;
$renameerrors = 0;
// Will use this course array a lot
// so fetch it early and keep it in memory
$courses = get_courses('all','c.sortorder','c.id,c.shortname,c.fullname,c.sortorder,c.teacher,c.visible');
while (!feof ($fp)) {
foreach ($optionalDefaults as $key => $value) {
$user->$key = addslashes($adminuser->$key);
}
//Note: commas within a field should be encoded as &#44 (for comma separated csv files)
//Note: semicolon within a field should be encoded as &#59 (for semicolon separated csv files)
$line = split($csv_delimiter, fgets($fp,1024));
foreach ($line as $key => $value) {
//decode encoded commas
$record[$header[$key]] = preg_replace($csv_encode,$csv_delimiter2,trim($value));
}
if ($record[$header[0]]) {
// add a new user to the database
// add fields to object $user
foreach ($record as $name => $value) {
// check for required values
if (isset($required[$name]) and !$value) {
error(get_string('missingfield', 'error', $name). " ".
get_string('erroronline', 'error', $linenum) .". ".
get_string('processingstops', 'error'),
'uploaduser.php?sesskey='.$USER->sesskey);
}
// password needs to be encrypted
else if ($name == "password" && !empty($value)) {
$user->password = hash_internal_user_password($value);
}
else if ($name == "username") {
$user->username = addslashes(moodle_strtolower($value));
}
// normal entry
else {
$user->{$name} = addslashes($value);
}
}
$user->confirmed = 1;
$user->timemodified = time();
$linenum++;
$username = $user->username;
$addcourse[0] = isset($user->course1) ? $user->course1 : NULL;
$addcourse[1] = isset($user->course2) ? $user->course2 : NULL;
$addcourse[2] = isset($user->course3) ? $user->course3 : NULL;
$addcourse[3] = isset($user->course4) ? $user->course4 : NULL;
$addcourse[4] = isset($user->course5) ? $user->course5 : NULL;
$addgroup[0] = isset($user->group1) ? $user->group1 : NULL;
$addgroup[1] = isset($user->group2) ? $user->group2 : NULL;
$addgroup[2] = isset($user->group3) ? $user->group3 : NULL;
$addgroup[3] = isset($user->group4) ? $user->group4 : NULL;
$addgroup[4] = isset($user->group5) ? $user->group5 : NULL;
$addtype[0] = isset($user->type1) ? $user->type1 : NULL;
$addtype[1] = isset($user->type2) ? $user->type2 : NULL;
$addtype[2] = isset($user->type3) ? $user->type3 : NULL;
$addtype[3] = isset($user->type4) ? $user->type4 : NULL;
$addtype[4] = isset($user->type5) ? $user->type5 : NULL;
$addrole[0] = isset($user->role1) ? $user->role1 : NULL;
$addrole[1] = isset($user->role2) ? $user->role2 : NULL;
$addrole[2] = isset($user->role3) ? $user->role3 : NULL;
$addrole[3] = isset($user->role4) ? $user->role4 : NULL;
$addrole[4] = isset($user->role5) ? $user->role5 : NULL;
for ($i=0; $i<5; $i++) {
$course[$i]=NULL;
}
foreach ($courses as $eachcourse) {
for ($i=0; $i<5; $i++) {
if ($eachcourse->shortname == $addcourse[$i]) {
$course[$i] = $eachcourse;
}
}
}
// before insert/update, check whether we should be updating
// an old record instead
if ($allowrenames && !empty($user->oldusername) ) {
$user->oldusername = moodle_strtolower($user->oldusername);
if ($olduser = get_record('user', 'username', $user->oldusername, 'mnethostid', $user->mnethostid)) {
if (set_field('user', 'username', $user->username, 'username', $user->oldusername)) {
notify(get_string('userrenamed', 'admin') . " : $user->oldusername $user->username");
$renames++;
} else {
notify(get_string('usernotrenamedexists', 'error') . " : $user->oldusername $user->username");
$renameerrors++;
continue;
}
} else {
notify(get_string('usernotrenamedmissing', 'error') . " : $user->oldusername $user->username");
$renameerrors++;
continue;
}
}
if ($olduser = get_record("user", "username", $username, "mnethostid", $user->mnethostid)) {
if ($updateaccounts) {
// Record is being updated
$user->id = $olduser->id;
if (update_record('user', $user)) {
notify("$user->id , $user->username ".get_string('useraccountupdated', 'admin'));
$usersupdated++;
} else {
notify(get_string('usernotupdatederror', 'error', $username));
$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
notify("$olduser->id ".get_string('usernotaddedregistered', 'error', $username));
$userserrors++;
}
} else { // new user
if ($user->id = insert_record("user", $user)) {
notify("$struser: $user->id = $user->username");
$usersnew++;
if (empty($user->password) && $createpassword) {
// passwords will be created and sent out on cron
insert_record('user_preferences', array( 'userid' => $user->id,
'name' => 'create_password',
'value' => 1));
insert_record('user_preferences', array( 'userid' => $user->id,
'name' => 'auth_forcepasswordchange',
'value' => 1));
}
} else {
// Record not added -- possibly some other error
notify(get_string('usernotaddederror', 'error', $username));
$userserrors++;
continue;
}
}
for ($i=0; $i<5; $i++) {
if ($addcourse[$i] && !$course[$i]) {
notify(get_string('unknowncourse', 'error', $addcourse[$i]));
}
}
for ($i=0; $i<5; $i++) {
$groupid[$i] = 0;
if ($addgroup[$i]) {
if (!$course[$i]) {
notify(get_string('coursegroupunknown','error',$addgroup[$i]));
} else {
if ($gid = groups_get_group_by_name($course[$i]->id, $addgroup[$i])) {
$groupid[$i] = $gid;
} else {
notify(get_string('groupunknown','error',$addgroup[$i]));
}
}
}
}
for ($i=0; $i<5; $i++) { /// Enrol into courses if necessary
if ($course[$i]) {
if (isset($addrole[$i])) {
$coursecontext = get_context_instance(CONTEXT_COURSE, $course[$i]->id);
if (!user_can_assign($coursecontext, $addrole[$i])) {
notify('--> Can not assign role in course'); //TODO: localize
}
$ret = role_assign($addrole[$i], $user->id, 0, $coursecontext->id);
} else if (isset($addtype[$i])) {
switch ($addtype[$i]) {
case 2: // teacher
$ret = add_teacher($user->id, $course[$i]->id, 1);
break;
case 3: // non-editing teacher
$ret = add_teacher($user->id, $course[$i]->id, 0);
break;
default: // student
$ret = enrol_student($user->id, $course[$i]->id);
break;
}
} else {
$ret = enrol_student($user->id, $course[$i]->id);
}
if ($ret) { // OK
notify('-->'. get_string('enrolledincourse', '', $addcourse[$i]));
} else {
notify('-->'.get_string('enrolledincoursenot', '', $addcourse[$i]));
}
}
}
for ($i=0; $i<5; $i++) { // Add user to groups if necessary
if ($course[$i] && $groupid[$i]) {
$coursecontext = get_context_instance(CONTEXT_COURSE, $course[$i]->id);
if (count(get_user_roles($coursecontext, $user->id))) {
if (groups_add_member($groupid[$i], $user->id)) {
notify('-->' . get_string('addedtogroup','',$addgroup[$i]));
} else {
notify('-->' . get_string('addedtogroupnot','',$addgroup[$i]));
}
} else {
notify('-->' . get_string('addedtogroupnotenrolled','',$addgroup[$i]));
}
}
}
unset ($user);
}
}
fclose($fp);
notify("$strusersnew: $usersnew");
notify(get_string('usersupdated', 'admin') . ": $usersupdated");
notify(get_string('errors', 'admin') . ": $userserrors");
if ($allowrenames) {
notify(get_string('usersrenamed', 'admin') . ": $renames");
notify(get_string('renameerrors', 'admin') . ": $renameerrors");
}
echo '<hr />';
notify(get_string('userscreated', 'admin') . ': ' . $usersnew);
notify(get_string('usersupdated', 'admin') . ': ' . $usersupdated);
notify(get_string('errors', 'admin') . ': ' . $userserrors);
if ($allowrenames) {
notify(get_string('usersrenamed', 'admin') . ': ' . $renames);
notify(get_string('renameerrors', 'admin') . ': ' . $renameerrors);
}
echo '<hr />';
}
/// Print the form
print_heading_with_help(get_string('uploadusers'), 'uploadusers');
$mform->display();
admin_externalpage_print_footer();
function my_file_get_contents($filename, $use_include_path = 0) {
/// Returns the file as one big long string
$data = "";
$file = @fopen($filename, "rb", $use_include_path);
if ($file) {
while (!feof($file)) {
$data .= fread($file, 1024);
}
fclose($file);
}
return $data;
}
?>

View File

@ -3,22 +3,124 @@ require_once $CFG->libdir.'/formslib.php';
class admin_uploaduser_form extends moodleform {
function definition (){
global $CFG;
$templateuser = $this->_customdata;
if(empty($templateuser)) {
if (!$templateuser = get_admin()) {
error('Could not find site admin');
}
}
$mform =& $this->_form;
$mform->addElement('file', 'userfile', get_string('file'));
$mform->addRule('userfile', null, 'required');
$mform->addElement('header', 'defaultheader', get_string('defaultvalues', 'admin'));
$mform->addElement('text', 'username', get_string('username'), 'size="20"');
$modules = get_list_of_plugins('auth');
$auth_options = array();
foreach ($modules as $module) {
$auth_options[$module] = get_string("auth_$module"."title", "auth");
}
$mform->addElement('select', 'auth', get_string('chooseauthmethod','auth'), $auth_options);
$mform->setDefault('auth', $templateuser->auth);
$mform->setHelpButton('auth', array('authchange', get_string('chooseauthmethod','auth')));
$mform->addElement('text', 'email', get_string('email'), 'maxlength="100" size="30"');
$choices = array(
get_string('emaildisplayno'),
get_string('emaildisplayyes'),
get_string('emaildisplaycourse'),
);
$mform->addElement('select', 'maildisplay', get_string('emaildisplay'), $choices);
$mform->setDefault('maildisplay', 2);
$choices = array(
get_string('emailenable'),
get_string('emaildisable'),
);
$mform->addElement('select', 'emailstop', get_string('emailactive'), $choices);
$choices = array(
get_string('textformat'),
get_string('htmlformat'),
);
$mform->addElement('select', 'mailformat', get_string('emailformat'), $choices);
$mform->setDefault('mailformat', 1);
$choices = array(
get_string('autosubscribeyes'),
get_string('autosubscribeno'),
);
$mform->addElement('select', 'autosubscribe', get_string('autosubscribe'), $choices);
$mform->setDefault('autosubscribe', 1);
if ($CFG->htmleditor) {
$choices = array(
get_string('texteditor'),
get_string('htmleditor'),
);
$mform->addElement('select', 'htmleditor', get_string('textediting'), $choices);
$mform->setDefault('htmleditor', 1);
}
$mform->addElement('text', 'city', get_string('city'), 'maxlength="100" size="25"');
$mform->setType('city', PARAM_MULTILANG);
$mform->setDefault('city', $templateuser->city);
$mform->addElement('select', 'country', get_string('selectacountry'), get_list_of_countries());
$mform->setDefault('country', $templateuser->country);
$choices = get_list_of_timezones();
$choices['99'] = get_string('serverlocaltime');
$mform->addElement('select', 'timezone', get_string('timezone'), $choices);
$mform->setDefault('timezone', $templateuser->timezone);
$mform->addElement('select', 'lang', get_string('preferredlanguage'), get_list_of_languages());
$mform->setDefault('lang', $templateuser->lang);
$mform->addElement('htmleditor', 'description', get_string('userdescription'));
$mform->setType('description', PARAM_CLEAN);
$mform->setHelpButton('description', array('text', get_string('helptext')));
$mform->addElement('text', 'url', get_string('webpage'), 'maxlength="255" size="50"');
$mform->addElement('text', 'institution', get_string('institution'), 'maxlength="40" size="25"');
$mform->setType('institution', PARAM_MULTILANG);
$mform->setDefault('institution', $templateuser->institution);
$mform->addElement('text', 'department', get_string('department'), 'maxlength="30" size="25"');
$mform->setType('department', PARAM_MULTILANG);
$mform->setDefault('department', $templateuser->department);
$mform->addElement('text', 'phone1', get_string('phone'), 'maxlength="20" size="25"');
$mform->setType('phone1', PARAM_CLEAN);
$mform->addElement('text', 'phone2', get_string('phone'), 'maxlength="20" size="25"');
$mform->setType('phone2', PARAM_CLEAN);
$mform->addElement('text', 'address', get_string('address'), 'maxlength="70" size="25"');
$mform->setType('address', PARAM_MULTILANG);
$mform->addElement('header', 'settingsheader', get_string('settings'));
$passwordopts = array( 0 => get_string('infilefield', 'auth'),
1 => get_string('createpasswordifneeded', 'auth'),
$choices = array(
get_string('infilefield', 'auth'),
get_string('createpasswordifneeded', 'auth'),
);
$mform->addElement('select', 'createpassword', get_string('passwordhandling', 'auth'), $passwordopts);
$mform->addElement('select', 'createpassword', get_string('passwordhandling', 'auth'), $choices);
$mform->addElement('selectyesno', 'updateaccounts', get_string('updateaccounts', 'admin'));
$mform->addElement('selectyesno', 'allowrenames', get_string('allowrenames', 'admin'));
$choices = array(
get_string('addcounter', 'admin'),
get_string('skipuser', 'admin'),
);
$mform->addElement('select', 'duplicatehandling', get_string('newusernamehandling', 'admin'), $choices);
$this->add_action_buttons(false, get_string('uploadusers'));
}

View File

@ -22,20 +22,19 @@
$actions[2] = get_string('messageselectadd');
}
$actions[3] = get_string('delete');
$actions[4] = get_string('displayonpage');
// create the bulk operations form
$user_bulk_form =& new user_bulk_form(null, $actions);
// check if an action should be performed and do so
switch ($user_bulk_form->getAction()) {
case 1:
include($CFG->dirroot . '/admin/user/user_bulk_confirm.php');
return;
redirect($CFG->wwwroot . '/admin/user/user_bulk_confirm.php');
case 2:
include($CFG->dirroot . '/admin/user/user_bulk_message.php');
return;
redirect($CFG->wwwroot . '/admin/user/user_bulk_message.php');
case 3:
include($CFG->dirroot . '/admin/user/user_bulk_delete.php');
return;
redirect($CFG->wwwroot . '/admin/user/user_bulk_delete.php');
case 4:
redirect($CFG->wwwroot . '/admin/user/user_bulk_display.php');
}
// prepare user filter types

View File

@ -21,7 +21,7 @@ foreach ($SESSION->bulk_susers as $k => $v) {
}
if (empty($userlist)) {
redirect($CFG->wwwroot . '/admin/user_bulk.php');
redirect($CFG->wwwroot . '/admin/user/user_bulk.php');
}
admin_externalpage_setup('userbulk');

View File

@ -22,7 +22,7 @@ foreach ($SESSION->bulk_susers as $k => $v) {
}
if (empty($userlist)) {
redirect($CFG->wwwroot . '/admin/user_bulk.php');
redirect($CFG->wwwroot . '/admin/user/user_bulk.php');
}
admin_externalpage_setup('userbulk');

View File

@ -0,0 +1,76 @@
<?php // $Id$
require_once('../../config.php');
require_once($CFG->libdir.'/adminlib.php');
if(empty($SESSION->bulk_susers)) {
redirect($CFG->wwwroot . '/admin/user/user_bulk.php');
}
$users = $SESSION->bulk_susers;
$usertotal = get_users(false);
$usercount = count($users);
$sort = optional_param('sort', 'fullname', PARAM_ALPHA);
$dir = optional_param('dir', 'asc', PARAM_ALPHA);
$strnever = get_string('never');
$sitecontext = get_context_instance(CONTEXT_SYSTEM, SITEID);
$site = get_site();
admin_externalpage_setup('userbulk');
admin_externalpage_print_header();
$countries =& get_list_of_countries();
foreach ($users as $key => $id) {
$user =& get_record('user', 'id', $id, null, null, null, null, 'id,firstname,lastname,username,email,country,lastaccess,city');
$user->fullname = fullname($user, true);
$user->country = @$countries[$user->country];
unset($user->firstname);
unset($user->lastname);
$users[$key] = $user;
}
unset($countries);
// Need to sort by data
function sort_compare($a, $b) {
global $sort, $dir;
if($sort == 'lastaccess') {
$rez = $b->lastaccess - $a->lastaccess;
} else {
$rez = strcasecmp(@$a->$sort, @$b->$sort);
}
return $dir == 'desc' ? -$rez : $rez;
}
usort($users, 'sort_compare');
$table->width = "95%";
$columns = array('fullname', 'username', 'email', 'city', 'country', 'lastaccess');
foreach ($columns as $column) {
$strtitle = get_string($column);
if ($sort != $column) {
$columnicon = '';
$columndir = 'asc';
} else {
$columndir = $dir == 'asc' ? 'desc' : 'asc';
$columnicon = ' <img src="' . $CFG->pixpath . '/t/' . ($dir == 'asc' ? 'down' : 'up' ). '.gif" alt="" />';
}
$table->head[] = '<a href="user_bulk_display.php?sort=' . $column . '&amp;dir=' . $columndir .'">' .$strtitle . '</a>' . $columnicon;
$table->align[] = 'left';
}
foreach($users as $user) {
$table->data[] = array (
'<a href="' . $CFG->wwwroot . '/user/view.php?id=' . $user->id . '&amp;course=' . $site->id .'">' . $user->fullname .'</a>',
$user->username,
$user->email,
$user->city,
$user->country,
$user->lastaccess ? format_time(time() - $user->lastaccess) : $strnever
);
}
print_heading("$usercount / $usertotal ".get_string('users'));
print_table($table);
admin_externalpage_print_footer();
?>

View File

@ -53,7 +53,7 @@ class user_bulk_form extends moodleform {
}
$obj =& $this->_form->getElement('comment');
$obj->setLabel($comment);
$obj->setText(get_string('usersfound', 'bulkusers', $count));
$obj->setText(get_string('usersfound', 'bulkusers', $count) . ' ' .get_string('usersselected', 'bulkusers', count($SESSION->bulk_susers)));
}
function definition_after_data() {

View File

@ -1,6 +1,7 @@
<?php
$string['accessdenied'] = 'Access denied';
$string['accounts'] = 'Accounts';
$string['addcounter'] = 'Append counter';
$string['adminseesall'] = 'Admins See All';
$string['adminseesallevents'] = 'Administrators see all events';
$string['adminseesownevents'] = 'Administrators are just like other users';
@ -252,6 +253,7 @@ $string['defaultallowedmodules'] = 'Default allowed modules';
$string['defaultcourseroleid'] = 'Default role for users in a course';
$string['defaultrequestcategory'] = 'Default category for course requests';
$string['defaultuserroleid'] = 'Default role for all users';
$string['defaultvalues'] = 'Default values';
$string['deleteunconfirmed'] = 'Delete unconfirmed users after';
$string['deleteuser'] = 'Delete user';
$string['density'] = 'Density';
@ -423,6 +425,7 @@ $string['mymoodle'] = 'My Moodle';
$string['mymoodleredirect'] = 'Force users to use My Moodle';
$string['mysql416bypassed'] = 'However, if your site is using iso-8859-1 (latin) languages ONLY, you may continue using your currently installed MySQL 4.1.12 (or higher).';
$string['mysql416required'] = 'MySQL 4.1.16 is the minimum version required for Moodle 1.6 in order to guarantee that all data can be converted to UTF-8 in the future.';
$string['newusernamehandling'] = 'New username duplicate handling';
$string['nobookmarksforuser'] = 'You do not have any bookmarks.';
$string['nodefaultuserrolelists'] = 'Don\'t return all default role users';
$string['nolangupdateneeded'] = 'All your language packs are up to date, no update is needed';
@ -561,6 +564,7 @@ $string['sitemaintenancewarning'] = 'Your site is currently in maintenance mode
$string['sitepolicies'] = 'Site policies';
$string['sitepolicy'] = 'Site policy URL';
$string['sitesectionhelp'] = 'If selected, a topic section will be displayed on the site\'s front page.';
$string['skipuser'] = 'Skip user';
$string['slasharguments'] = 'Use slash arguments';
$string['smartpix'] ='Smart pix search';
$string['smtphosts'] = 'SMTP hosts';

View File

@ -6,4 +6,5 @@ $string['removeall'] = 'Clear selection';
$string['removesel'] = 'Remove from selection';
$string['available'] = 'Available';
$string['selected'] = 'Selected';
$string['usersfound'] = '$a user(s) found';
$string['usersfound'] = '$a user(s) found.';
$string['usersselected'] = '$a user(s) selected.';

View File

@ -3,6 +3,7 @@
$string['adminprimarynoedit'] = 'The primary admin cannot be edited by others';
$string['cannotassignrole'] = 'Cannot assign role in course';
$string['cannotcreatelangdir'] = 'Cannot create lang dir.';
$string['cannotcreatetempdir'] = 'Cannot create temp dir.';
$string['cannotcustomizelocallang'] = 'You do not have permission to customize the strings translation. This permission is controlled by the capability "moodle/site:langeditlocal". Set this capability to allow you to edit local language packages in case you want to modify translations for your site.';
@ -21,6 +22,7 @@ $string['confirmsesskeybad'] = 'Sorry, but your session key could not be confirm
$string['couldnotassignrole'] = 'A serious but unspecified error occurred while trying to assign a role to you';
$string['coursegroupunknown'] = 'Course corresponding to group $a not specified';
$string['downloadedfilecheckfailed'] = 'Downloaded file check failed.';
$string['duplicateusername'] = 'Duplicate username - skiping record';
$string['errorcleaningdirectory'] = 'Error cleaning directory \"$a\"';
$string['errorcopyingfiles'] = 'Error copying files';
$string['errorcreatingdirectory'] = 'Error creating directory \"$a\"';
@ -85,11 +87,12 @@ $string['unicodeupgradeerror'] = 'Sorry, but your database is not already in Uni
$string['unknowncourse'] = 'Unknown course named \"$a\"';
$string['unknowncourseidnumber'] = 'Unknown Course ID \"$a\"';
$string['unknownuseraction'] = 'Sorry, I do not understand this user action.';
$string['usernotaddederror'] = 'User \"$a\" not added - unknown error';
$string['usernotaddedregistered'] = 'User \"$a\" not added - already registered';
$string['usernotaddederror'] = 'User not added - unknown error';
$string['usernotaddedregistered'] = 'User not added - already registered';
$string['usernotavailable'] = 'The details of this user are not available to you.';
$string['usernotrenamedexists'] = 'User not renamed -- the new username is already in use.';
$string['usernotrenamedmissing'] = 'User not renamed -- could not find the old username.';
$string['usernotupdatederror'] = 'User not updated - unknown error';
$string['wrongdestpath'] = 'Wrong destination path.';
$string['wrongsourcebase'] = 'Wrong source URL base.';
$string['wrongzipfilename'] = 'Wrong ZIP filename.';

View File

@ -9,30 +9,56 @@
<li>The first record of the file is special, and contains a list of fieldnames. This defines the format of the rest of the file.
<blockquote>
<p><strong>Required fieldnames:</strong> these fields must be included in the first record, and defined for each user</p>
<p><code class="example1">username, password, firstname, lastname, email</code></p>
<p><strong>Default fieldnames:</strong> these are optional - if they are not included then the values are taken from the primary admin</p>
<p><code class="example1">institution, department, city, country, lang, auth, timezone</code> </p>
<p><strong>Optional fieldnames: </strong>all of these are completely optional. The course names are the &quot;shortnames&quot; of the courses - if present then the user will be enrolled as students in those courses. Group names must be associated to the corresponding courses, i.e. group1 to course1, etc.</p>
<p> <code class="example1">idnumber, icq, phone1, phone2, address, url, description, mailformat, maildisplay, htmleditor, autosubscribe, course1, course2, course3, course4, course5, group1, group2, group3, group4, group5, type1, type2, type3, type4, type5, role1, role2, role3, role4, role5, emailstop</code></p>
<p><code class="example1">firstname, lastname</code></p>
<p><strong>Optional fieldnames: </strong>all of these are completely optional. If a values is present for the field in the file, then that value is used; else, the default value for that field is used.</p>
<p> <code class="example1">institution, department, city, country, lang, auth, timezone, idnumber, icq, phone1, phone2, address, url, description, mailformat, maildisplay, htmleditor, autosubscribe, emailstop</code></p>
<p><strong>Enrolment fieldnames (optional): </strong>The course names are the &quot;shortnames&quot; of the courses - if present then the user will be enrolled in those courses. For groups use group name; for roles use id. Group names must be associated to the corresponding courses, i.e. group1 to course1, etc.</p>
<p><code class="example1">course1, group1, type1, role1, course2, group2, type2, role2, etc.</code></p>
</blockquote>
</li>
<li>Commas within the data should be encoded as &amp;#44 - the script will automatically decode these back to commas. </li>
<li>For Boolean fields, use 0 for false and 1 for true. </li>
<li>Types are used to tell Moodle whether the user is a student or a teacher if a corresponding course exists (e.g. type2 corresponds to course2). 1 = Student, 2 = Editing Teacher, and 3 = Non-editing Teacher. If type is left blank, or if no course is specified, the user is default to student. </li>
<li>For courses use the short name; for groups use group name; for roles use id.</li>
<li>Note: If a user is already registered in the Moodle user database, this script will return the
userid number (database index) for that user, and will enrol the user as a student in any of the
specified courses WITHOUT updating the other specified data.</li>
</ul>
<p>Here is an example of a valid import file:</p>
<p><code>username, password, firstname, lastname, email, lang, idnumber, maildisplay, course1, group1, type1<br />
jonest, verysecret, Tom, Jones, jonest@someplace.edu, en, 3663737, 1, Intro101, Section 1, 1<br />
reznort, somesecret, Trent, Reznor, reznort@someplace.edu, en_us, 6736733, 0, Advanced202, Section 3, 3
</code></p>
<h2>Templates</h2>
<p>The default values are processed as templates in which the following codes are allowed:</p>
<ul>
<li><code>%l</code> - will be replaced by the lastname</li>
<li><code>%f</code> - will be replaced by the firstname</li>
<li><code>%u</code> - will be replaced by the username</li>
<li><code>%%</code> - will be replaced by the %</li>
</ul>
<p>Between the percent sign (%) and any code letter (l, f or u) the following modifiers are allowed:</p>
<ul>
<li>minus sign (-) - the information specified by the code letter will be converted to lowercase</li>
<li>plus sign (+) - the information specified by the code letter will be converted to uppercase</li>
<li>a decimal number - the information specified by the code letter will be truncated to that many characters</li>
</ul>
<p>For example, if the firstname is John and the lastname is Doe, the following values will be obtained with the specified templates:</p>
<ul>
<li>%l%f = DoeJohn</li>
<li>%l%1f = DoeJ</li>
<li>%-l%+f = doeJOHN</li>
<li>%-f_%-l = john_doe</li>
<li>http://www.example.com/~%u/ = http://www.example.com/~jdoe/ (if the username is jdoe or %-1f%-l)</li>
</ul>
<p>Template processing is done only on default values, and not on the values retrieved from the CSV file.</p>
<p>In order to create corect Moodle usernames, the username is always converted to lowercase. Moreover, if the &quot;Allow extended characters in usernames&quot; option in the Site policies page is off, characters different to letters, digits, dash (-) and dot (.) are removed.
For example if the firstname is John Jr. and the lastname is Doe, the username %-f%-l will produce john jr.doe when Allow extended characters in usernames is on, and johnjr.doe when off (notice the extra space).</p>
<p>When the &quot;New username duplicate handling&quot; setting is set to Append counter, an auto-increment counter will be append to duplicate usernames produced by the template.
For example, if the CSV file contains the users named John Doe, Jane Doe and Jenny Doe without explicit usernames, the default username is %-1f%-l and New username duplicate handling is set to Append counter, then the usernames produced will be jdoe, jdoe2 and jdoe3.
</p>
<h2>Updating existing accounts</h2>
<p>By default Moodle assumes that you will be creating new user accounts, and skips records where the username matches an existing account. However, if you set "Update existing accounts" to <b>Yes</b>, the existing user account will be updated. </p>