Minor fixes for XHTML compliance
[pfb-moodle.git] / admin / uploaduser.php
blob5a5ecfe6c676d7e1e7adff2d1b00468a13281a2a
1 <?php // $Id$
3 /// Bulk user registration script from a comma separated file
4 /// Returns list of users with their user ids
6 require_once('../config.php');
7 require_once($CFG->libdir.'/uploadlib.php');
8 require_once($CFG->libdir.'/adminlib.php');
9 $adminroot = admin_get_root();
10 admin_externalpage_setup('uploadusers', $adminroot);
12 $createpassword = optional_param('createpassword', 0, PARAM_BOOL);
13 $updateaccounts = optional_param('updateaccounts', 0, PARAM_BOOL);
14 $allowrenames = optional_param('allowrenames', 0, PARAM_BOOL);
16 require_login();
18 require_capability('moodle/site:uploadusers', get_context_instance(CONTEXT_SYSTEM, SITEID));
20 if (! $site = get_site()) {
21 error("Could not find site-level course");
24 if (!$adminuser = get_admin()) {
25 error("Could not find site admin");
28 $strfile = get_string('file');
29 $struser = get_string('user');
30 $strusersnew = get_string('usersnew');
31 $strusersupdated = get_string('usersupdated');
32 $struploadusers = get_string('uploadusers');
33 $straddnewuser = get_string('importuser');
35 $csv_encode = '/\&\#44/';
36 if (isset($CFG->CSV_DELIMITER)) {
37 $csv_delimiter = '\\' . $CFG->CSV_DELIMITER;
38 $csv_delimiter2 = $CFG->CSV_DELIMITER;
40 if (isset($CFG->CSV_ENCODE)) {
41 $csv_encode = '/\&\#' . $CFG->CSV_ENCODE . '/';
43 } else {
44 $csv_delimiter = "\,";
45 $csv_delimiter2 = ",";
48 /// Print the header
50 admin_externalpage_print_header($adminroot);
53 /// If a file has been uploaded, then process it
56 $um = new upload_manager('userfile',false,false,null,false,0);
58 if ($um->preprocess_files() && confirm_sesskey()) {
59 $filename = $um->files['userfile']['tmp_name'];
61 // Large files are likely to take their time and memory. Let PHP know
62 // that we'll take longer, and that the process should be recycled soon
63 // to free up memory.
64 @set_time_limit(0);
65 @raise_memory_limit("192M");
66 if (function_exists('apache_child_terminate')) {
67 @apache_child_terminate();
70 //Fix mac/dos newlines
71 $text = my_file_get_contents($filename);
72 $text = preg_replace('!\r\n?!',"\n",$text);
73 $fp = fopen($filename, "w");
74 fwrite($fp,$text);
75 fclose($fp);
77 $fp = fopen($filename, "r");
79 // make arrays of valid fields for error checking
80 $required = array("username" => 1,
81 "password" => !$createpassword,
82 "firstname" => 1,
83 "lastname" => 1,
84 "email" => 1);
85 $optionalDefaults = array("mnethostid" => 1,
86 "institution" => 1,
87 "department" => 1,
88 "city" => 1,
89 "country" => 1,
90 "lang" => 1,
91 "auth" => 1,
92 "timezone" => 1);
93 $optional = array("idnumber" => 1,
94 "icq" => 1,
95 "phone1" => 1,
96 "phone2" => 1,
97 "address" => 1,
98 "url" => 1,
99 "description" => 1,
100 "mailformat" => 1,
101 "maildisplay" => 1,
102 "htmleditor" => 1,
103 "autosubscribe" => 1,
104 "idnumber" => 1,
105 "icq" => 1,
106 "course1" => 1,
107 "course2" => 1,
108 "course3" => 1,
109 "course4" => 1,
110 "course5" => 1,
111 "group1" => 1,
112 "group2" => 1,
113 "group3" => 1,
114 "group4" => 1,
115 "group5" => 1,
116 "type1" => 1,
117 "type2" => 1,
118 "type3" => 1,
119 "type4" => 1,
120 "type5" => 1,
121 "role1" => 1,
122 "role2" => 1,
123 "role3" => 1,
124 "role4" => 1,
125 "role5" => 1,
126 "password" => $createpassword,
127 "oldusername" => $allowrenames);
129 // --- get header (field names) ---
130 $header = split($csv_delimiter, fgets($fp,1024));
131 // check for valid field names
132 foreach ($header as $i => $h) {
133 $h = trim($h); $header[$i] = $h; // remove whitespace
134 if (!(isset($required[$h]) or isset($optionalDefaults[$h]) or isset($optional[$h]))) {
135 error(get_string('invalidfieldname', 'error', $h), 'uploaduser.php?sesskey='.$USER->sesskey);
137 if (isset($required[$h])) {
138 $required[$h] = 0;
141 // check for required fields
142 foreach ($required as $key => $value) {
143 if ($value) { //required field missing
144 error(get_string('fieldrequired', 'error', $key), 'uploaduser.php?sesskey='.$USER->sesskey);
147 $linenum = 2; // since header is line 1
149 $usersnew = 0;
150 $usersupdated = 0;
151 $userserrors = 0;
152 $renames = 0;
153 $renameerrors = 0;
155 // Will use this course array a lot
156 // so fetch it early and keep it in memory
157 $courses = get_courses('all','c.sortorder','c.id,c.shortname,c.fullname,c.sortorder,c.teacher,c.visible');
159 while (!feof ($fp)) {
160 foreach ($optionalDefaults as $key => $value) {
161 $user->$key = addslashes($adminuser->$key);
163 //Note: commas within a field should be encoded as &#44 (for comma separated csv files)
164 //Note: semicolon within a field should be encoded as &#59 (for semicolon separated csv files)
165 $line = split($csv_delimiter, fgets($fp,1024));
166 foreach ($line as $key => $value) {
167 //decode encoded commas
168 $record[$header[$key]] = preg_replace($csv_encode,$csv_delimiter2,trim($value));
170 if ($record[$header[0]]) {
171 // add a new user to the database
173 // add fields to object $user
174 foreach ($record as $name => $value) {
175 // check for required values
176 if (isset($required[$name]) and !$value) {
177 error(get_string('missingfield', 'error', $name). " ".
178 get_string('erroronline', 'error', $linenum) .". ".
179 get_string('processingstops', 'error'),
180 'uploaduser.php?sesskey='.$USER->sesskey);
182 // password needs to be encrypted
183 else if ($name == "password" && !empty($value)) {
184 $user->password = hash_internal_user_password($value);
186 else if ($name == "username") {
187 $user->username = addslashes(moodle_strtolower($value));
189 // normal entry
190 else {
191 $user->{$name} = addslashes($value);
194 $user->confirmed = 1;
195 $user->timemodified = time();
196 $linenum++;
197 $username = $user->username;
198 $addcourse[0] = isset($user->course1) ? $user->course1 : NULL;
199 $addcourse[1] = isset($user->course2) ? $user->course2 : NULL;
200 $addcourse[2] = isset($user->course3) ? $user->course3 : NULL;
201 $addcourse[3] = isset($user->course4) ? $user->course4 : NULL;
202 $addcourse[4] = isset($user->course5) ? $user->course5 : NULL;
203 $addgroup[0] = isset($user->group1) ? $user->group1 : NULL;
204 $addgroup[1] = isset($user->group2) ? $user->group2 : NULL;
205 $addgroup[2] = isset($user->group3) ? $user->group3 : NULL;
206 $addgroup[3] = isset($user->group4) ? $user->group4 : NULL;
207 $addgroup[4] = isset($user->group5) ? $user->group5 : NULL;
208 $addtype[0] = isset($user->type1) ? $user->type1 : NULL;
209 $addtype[1] = isset($user->type2) ? $user->type2 : NULL;
210 $addtype[2] = isset($user->type3) ? $user->type3 : NULL;
211 $addtype[3] = isset($user->type4) ? $user->type4 : NULL;
212 $addtype[4] = isset($user->type5) ? $user->type5 : NULL;
213 $addrole[0] = isset($user->role1) ? $user->role1 : NULL;
214 $addrole[1] = isset($user->role2) ? $user->role2 : NULL;
215 $addrole[2] = isset($user->role3) ? $user->role3 : NULL;
216 $addrole[3] = isset($user->role4) ? $user->role4 : NULL;
217 $addrole[4] = isset($user->role5) ? $user->role5 : NULL;
219 for ($i=0; $i<5; $i++) {
220 $course[$i]=NULL;
222 foreach ($courses as $eachcourse) {
223 for ($i=0; $i<5; $i++) {
224 if ($eachcourse->shortname == $addcourse[$i]) {
225 $course[$i] = $eachcourse;
230 // before insert/update, check whether we should be updating
231 // an old record instead
232 if ($allowrenames && !empty($user->oldusername) ) {
233 $user->oldusername = moodle_strtolower($user->oldusername);
234 if ($olduser = get_record('user', 'username', $user->oldusername, 'mnethostid', $user->mnethostid)) {
235 if (set_field('user', 'username', $user->username, 'username', $user->oldusername)) {
236 notify(get_string('userrenamed', 'admin') . " : $user->oldusername $user->username");
237 $renames++;
238 } else {
239 notify(get_string('usernotrenamedexists', 'error') . " : $user->oldusername $user->username");
240 $renameerrors++;
241 continue;
243 } else {
244 notify(get_string('usernotrenamedmissing', 'error') . " : $user->oldusername $user->username");
245 $renameerrors++;
246 continue;
250 if ($olduser = get_record("user", "username", $username, "mnethostid", $user->mnethostid)) {
251 if ($updateaccounts) {
252 // Record is being updated
253 $user->id = $olduser->id;
254 if (update_record('user', $user)) {
255 notify("$user->id , $user->username ".get_string('useraccountupdated', 'admin'));
256 $usersupdated++;
257 } else {
258 notify(get_string('usernotupdatederror', 'error', $username));
259 $userserrors++;
260 continue;
262 } else {
263 //Record not added - user is already registered
264 //In this case, output userid from previous registration
265 //This can be used to obtain a list of userids for existing users
266 notify("$olduser->id ".get_string('usernotaddedregistered', 'error', $username));
267 $userserrors++;
268 continue;
271 } else { // new user
272 if ($user->id = insert_record("user", $user)) {
273 notify("$struser: $user->id = $user->username");
274 $usersnew++;
275 if (empty($user->password) && $createpassword) {
276 // passwords will be created and sent out on cron
277 insert_record('user_preferences', array( userid => $user->id,
278 name => 'create_password',
279 value => 1));
280 insert_record('user_preferences', array( userid => $user->id,
281 name => 'auth_forcepasswordchange',
282 value => 1));
284 } else {
285 // Record not added -- possibly some other error
286 notify(get_string('usernotaddederror', 'error', $username));
287 $userserrors++;
288 continue;
291 for ($i=0; $i<5; $i++) {
292 if ($addcourse[$i] && !$course[$i]) {
293 notify(get_string('unknowncourse', 'error', $addcourse[$i]));
296 for ($i=0; $i<5; $i++) {
297 $groupid[$i] = 0;
298 if ($addgroup[$i]) {
299 if (!$course[$i]) {
300 notify(get_string('coursegroupunknown','error',$addgroup[$i]));
301 } else {
302 if ($groupid = groups_get_group_by_name($course[$i]->id, $addgroup[$i])) { //TODO:check.
303 $groupid[$i] = $groupid;
304 } else {
305 notify(get_string('groupunknown','error',$addgroup[$i]));
310 for ($i=0; $i<5; $i++) { /// Enrol into courses if necessary
311 if ($course[$i]) {
312 if (isset($addrole[$i])) {
313 $coursecontext = get_context_instance(CONTEXT_COURSE, $course[$i]->id);
314 if (!user_can_assign($coursecontext, $addrole[$i])) {
315 notify('--> Can not assign role in course'); //TODO: localize
317 $ret = role_assign($addrole[$i], $user->id, 0, $coursecontext->id);
318 } else if (isset($addtype[$i])) {
319 switch ($addtype[$i]) {
320 case 2: // teacher
321 $ret = add_teacher($user->id, $course[$i]->id, 1);
322 break;
324 case 3: // non-editing teacher
325 $ret = add_teacher($user->id, $course[$i]->id, 0);
326 break;
328 default: // student
329 $ret = enrol_student($user->id, $course[$i]->id);
330 break;
332 } else {
333 $ret = enrol_student($user->id, $course[$i]->id);
335 if ($ret) { // OK
336 notify('-->'. get_string('enrolledincourse', '', $addcourse[$i]));
337 } else {
338 notify('-->'.get_string('enrolledincoursenot', '', $addcourse[$i]));
342 for ($i=0; $i<5; $i++) { // Add user to groups if necessary
343 if ($course[$i] && $groupid[$i]) {
344 $coursecontext = get_context_instance(CONTEXT_COURSE, $course[$i]->id);
345 if (count(get_user_roles($coursecontext, $user->id))) {
346 if (add_user_to_group($groupid[$i], $user->id)) {
347 notify('-->' . get_string('addedtogroup','',$addgroup[$i]));
348 } else {
349 notify('-->' . get_string('addedtogroupnot','',$addgroup[$i]));
351 } else {
352 notify('-->' . get_string('addedtogroupnotenrolled','',$addgroup[$i]));
357 unset ($user);
360 fclose($fp);
361 notify("$strusersnew: $usersnew");
362 notify(get_string('usersupdated', 'admin') . ": $usersupdated");
363 notify(get_string('errors', 'admin') . ": $userserrors");
364 if ($allowrenames) {
365 notify(get_string('usersrenamed', 'admin') . ": $renames");
366 notify(get_string('renameerrors', 'admin') . ": $renameerrors");
368 echo '<hr />';
371 /// Print the form
372 print_heading_with_help($struploadusers, 'uploadusers');
374 $noyesoptions = array( get_string('no'), get_string('yes') );
376 $maxuploadsize = get_max_upload_file_size();
377 echo '<div style="text-align:center">';
378 echo '<form method="post" enctype="multipart/form-data" action="uploaduser.php"><div>'.
379 $strfile.'&nbsp;<input type="hidden" name="MAX_FILE_SIZE" value="'.$maxuploadsize.'" />'.
380 '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />'.
381 '<input type="file" name="userfile" size="30" />';
382 print_heading(get_string('settings'));
383 echo '<table style="margin-left:auto;margin-right:auto">';
384 echo '<tr><td>' . get_string('passwordhandling', 'auth') . '</td><td>';
385 $passwordopts = array( 0 => get_string('infilefield', 'auth'),
386 1 => get_string('createpasswordifneeded', 'auth'),
388 choose_from_menu($passwordopts, 'createpassword', $createpassword);
389 echo '</td></tr>';
391 echo '<tr><td>' . get_string('updateaccounts', 'admin') . '</td><td>';
392 choose_from_menu($noyesoptions, 'updateaccounts', $updateaccounts);
393 echo '</td></tr>';
395 echo '<tr><td>' . get_string('allowrenames', 'admin') . '</td><td>';
396 choose_from_menu($noyesoptions, 'allowrenames', $allowrenames);
397 echo '</td></tr>';
398 echo '</table><br />';
399 echo '<input type="submit" value="'.$struploadusers.'" />';
400 echo '</div></form><br />';
401 echo '</div>';
403 admin_externalpage_print_footer($adminroot);
407 function my_file_get_contents($filename, $use_include_path = 0) {
408 /// Returns the file as one big long string
410 $data = "";
411 $file = @fopen($filename, "rb", $use_include_path);
412 if ($file) {
413 while (!feof($file)) {
414 $data .= fread($file, 1024);
416 fclose($file);
418 return $data;