fixing a broken get_context_instance() call
[moodle.git] / admin / uploaduser.php
CommitLineData
066bfbfe 1<?php
0a6150ca 2
3/// Bulk user registration script from a comma separated file
4/// Returns list of users with their user ids
5
6b09974b 6require_once('../config.php');
cc891abe 7require_once($CFG->libdir.'/adminlib.php');
066bfbfe 8require_once($CFG->libdir.'/textlib.class.php');
0a5dffcc 9require_once('uploaduser_form.php');
066bfbfe 10define('LINE_MAX_SIZE', 1024);
1ae083e4 11
066bfbfe 12//Note: commas within a field should be encoded as &#44 (for comma separated csv files)
13//Note: semicolon within a field should be encoded as &#59 (for semicolon separated csv files)
14$csv_delimiter = isset($CFG->CSV_DELIMITER) ? $CFG->CSV_DELIMITER : ',';
15$csv_encode = '&#' . (isset($CFG->CSV_ENCODE) ? $CFG->CSV_ENCODE : ord($csv_delimiter));
16
17@set_time_limit(0);
18@raise_memory_limit('192M');
0a6150ca 19
066bfbfe 20admin_externalpage_setup('uploadusers');
1ae083e4 21require_capability('moodle/site:uploadusers', get_context_instance(CONTEXT_SYSTEM));
0a6150ca 22
6b09974b 23if (! $site = get_site()) {
066bfbfe 24 error('Could not find site-level course');
6b09974b 25}
0a6150ca 26
066bfbfe 27$textlib =& textlib_get_instance();
ca23a9c9 28
066bfbfe 29$struserrenamed = get_string('userrenamed', 'admin');
30$strusernotrenamedexists = get_string('usernotrenamedexists', 'error');
31$strusernotrenamedmissing = get_string('usernotrenamedmissing', 'error');
6b09974b 32
066bfbfe 33$struserupdated = get_string('useraccountupdated', 'admin');
34$strusernotupdated = get_string('usernotupdatederror', 'error');
35$strusernotadded = get_string('usernotaddedregistered', 'error');
6b09974b 36
066bfbfe 37$struseradded = get_string('newuser');
38$strusernotaddederror = get_string('usernotaddederror', 'error');
39$strcannotassignrole = get_string('cannotassignrole', 'error');
40$strduplicateusername = get_string('duplicateusername', 'error');
41$strindent = '-->';
a5702569 42
0a5dffcc 43$mform = new admin_uploaduser_form();
a5702569 44
066bfbfe 45// Print the header
0a6150ca 46
066bfbfe 47admin_externalpage_print_header();
0a6150ca 48
066bfbfe 49// If a file has been uploaded, then process it
50if ( $formdata = $mform->get_data() ) {
0a5dffcc 51 $createpassword = $formdata->createpassword;
52 $updateaccounts = $formdata->updateaccounts;
53 $allowrenames = $formdata->allowrenames;
066bfbfe 54 $skipduplicates = $formdata->duplicatehandling;
0a5dffcc 55
066bfbfe 56 // make arrays of valid fields for error checking
57 // the value associated to each field is: 0 = optional field, 1 = field required either in default values or in data file
58 $fields = array(
59 'firstname' => 1,
60 'lastname' => 1,
61 'username' => 1,
62 'email' => 1,
63 'city' => 1,
64 'country' => 1,
65 'lang' => 1,
66 'auth' => 1,
67 'timezone' => 1,
68 'mailformat' => 1,
69 'maildisplay' => 1,
70 'htmleditor' => 1,
71 'autosubscribe' => 1,
72 'mnethostid' => 1,
73 'institution' => 0,
74 'department' => 0,
75 'idnumber' => 0,
76 'icq' => 0,
77 'phone1' => 0,
78 'phone2' => 0,
79 'address' => 0,
80 'url' => 0,
81 'description' => 0,
82 'icq' => 0,
83 'oldusername' => 0,
84 'emailstop' => 1,
85 'password' => !$createpassword,
86 );
87
88 $fp = fopen($mform->get_userfile_name(), 'r');
89 $linenum = 1; // since header is line 1
90 // get header (field names) and remove Unicode BOM from first line, if any
91 $line = explode($csv_delimiter, $textlib->trim_utf8_bom(fgets($fp,LINE_MAX_SIZE)));
92 // check for valid field names
93 $headers = array();
94 foreach ($line as $key => $value) {
95 $value = trim($value); // remove whitespace
96 if (!in_array($value, $fields) && // if not a standard field and not an enrolment field, then we have an error
97 !preg_match('/^course\d+$/', $value) && !preg_match('/^group\d+$/', $value) &&
98 !preg_match('/^type\d+$/', $value) && !preg_match('/^role\d+$/', $value)) {
99 error(get_string('invalidfieldname', 'error', $value), 'uploaduser.php?sesskey='.$USER->sesskey);
100 }
101 $headers[$key] = $value;
6b09974b 102 }
a2ce7344 103
066bfbfe 104 $usersnew = 0;
105 $usersupdated = 0;
106 $userserrors = 0;
107 $renames = 0;
108 $renameerrors = 0;
109 $newusernames = array();
110 // We'll need courses a lot, so fetch it early and keep it in memory, indexed by their shortname
111 $tmp =& get_courses('all','','id,shortname,visible');
112 $courses = array();
113 foreach ($tmp as $c) {
114 $courses[$c->shortname] = $c;
115 }
116 unset($tmp);
117
118 echo '<p id="results">';
119 while (!feof ($fp)) {
120 $user = new object();
121 // by default, use the local mnet id (this may be changed in the file)
122 $user->mnethostid = $CFG->mnet_localhost_id;
123 $line = explode($csv_delimiter, fgets($fp,LINE_MAX_SIZE));
124 ++$linenum;
125 $ok = true;
126 // add fields to user object
127 foreach ($line as $key => $value) {
128 if($value !== '') {
129 $key = $headers[$key];
130 //decode encoded commas
131 $value = str_replace($csv_encode,$csv_delimiter,trim($value));
132 // special fields: password and username
133 if ($key == 'password' && !empty($value)) {
134 $user->$key = hash_internal_user_password($value);
135 } else if($key == 'username') {
136 $user->$key = addslashes($textlib->strtolower($value));
137 } else {
138 $user->$key = addslashes($value);
6b09974b 139 }
16a1fed4 140 }
066bfbfe 141 }
142 // add default values for remaining fields
143 foreach ($fields as $key => $value) {
144 if(isset($user->$key)) {
145 continue;
16a1fed4 146 }
066bfbfe 147 if(!isset($formdata->$key) || $formdata->$key==='') { // no default value was submited
148 if($value) { // the field is required
149 notify(get_string('erroronline', 'error', $linenum). ': ' .get_string('missingfield', 'error', $key));
150 $ok = false;
0063abee 151 }
066bfbfe 152 continue;
153 }
154 // process templates
155 $template = $formdata->$key;
156 $templatelen = strlen($template);
157 $value = '';
158 for ($i = 0 ; $i < $templatelen; ++$i) {
159 if($template[$i] == '%') {
160 $case = 0; // 1=lowercase, 2=uppercase
161 $len = 0; // number of characters to keep
162 $info = null; // data to process
163 for($j = $i + 1; is_null($info) && $j < $templatelen; ++$j) {
164 $car = $template[$j];
165 if ($car >= '0' && $car <= '9') {
166 $len = $len * 10 + (int)$car;
167 } else if($car == '-') {
168 $case = 1;
169 } else if($car == '+') {
170 $case = 2;
171 } else if($car == 'f') { // first name
172 $info = @$user->firstname;
173 } else if($car == 'l') { // last name
174 $info = @$user->lastname;
175 } else if($car == 'u') { // username
176 $info = @$user->username;
177 } else if($car == '%' && $j == $i+1) {
178 $info = '%';
179 } else { // invalid character
180 $info = '';
6b09974b 181 }
182 }
066bfbfe 183 if($info==='' || is_null($info)) { // invalid template
184 continue;
6b09974b 185 }
066bfbfe 186 $i = $j - 1;
187 // change case
188 if($case == 1) {
189 $info = $textlib->strtolower($info);
190 } else if($case == 2) {
191 $info = $textlib->strtoupper($info);
6740dd64 192 }
066bfbfe 193 if($len) { // truncate data
194 $info = $textlib->substr($info, 0, $len);
195 }
196 $value .= $info;
197 } else {
198 $value .= $template[$i];
199 }
200 }
201
202 if($key == 'username') {
203 $value = $textlib->strtolower($value);
204 if(empty($CFG->extendedusernamechars)) {
205 $value = eregi_replace('[^(-\.[:alnum:])]', '', $value);
206 }
207 // check for new username duplicates
208 if(empty($newusernames[$value])) {
209 $newusernames[$value] = 1;
210 } else {
211 if($skipduplicates) {
212 notify($strduplicateusername . ': ' . $value);
213 $ok = false;
214 continue;
215 } else {
216 ++$newusernames[$value];
217 $value .= $newusernames[$value];
a2ce7344 218 }
066bfbfe 219 }
220 }
221 $user->$key = $value;
222 }
223 if(!$ok) {
224 ++$userserrors;
225 continue;
226 }
a2ce7344 227
066bfbfe 228 $user->confirmed = 1;
229 $user->timemodified = time();
230
231 // save the user to the database
232 $username = $user->username;
233
234 // before insert/update, check whether we should be updating an old record instead
235 if ($allowrenames && !empty($user->oldusername) ) {
236 $user->oldusername = $textlib->strtolower($user->oldusername);
237 $info = ': ' . $user->oldusername . '-->' . $user->username . '. ';
238 if ($olduser = get_record('user', 'username', $user->oldusername, 'mnethostid', $user->mnethostid)) {
239 if (set_field('user', 'username', $user->username, 'id', $olduser->id)) {
240 echo $struserrenamed . $info;
241 $renames++;
242 } else {
243 notify($strusernotrenamedexists . $info);
244 $renameerrors++;
245 continue;
246 }
247 } else {
248 notify($strusernotrenamedmissing . $info);
249 $renameerrors++;
250 continue;
251 }
252 }
a2ce7344 253
066bfbfe 254 // save the information
255 if ($olduser = get_record('user', 'username', $username, 'mnethostid', $user->mnethostid)) {
256 $user->id = $olduser->id;
257 $info = ': ' . $username .' (ID = ' . $user->id . ')';
258 if ($updateaccounts) {
259 // Record is being updated
260 if (update_record('user', $user)) {
261 echo $struserupdated . $info . '<br />';
262 $usersupdated++;
263 } else {
264 notify($strusernotupdated . $info);
265 $userserrors++;
266 continue;
267 }
268 } else {
269 //Record not added - user is already registered
270 //In this case, output userid from previous registration
271 //This can be used to obtain a list of userids for existing users
272 echo $strusernotadded . $info . '<br />';
273 $userserrors++;
274 }
275 } else { // new user
276 if ($user->id = insert_record('user', $user)) {
277 $info = ': ' . $username .' (ID = ' . $user->id . ')';
278 echo $struseradded . $info . '<br />';
279 $usersnew++;
280 if (empty($user->password) && $createpassword) {
281 // passwords will be created and sent out on cron
282 insert_record('user_preferences', array( 'userid' => $user->id, 'name' => 'create_password', 'value' => 1));
283 insert_record('user_preferences', array( 'userid' => $user->id, 'name' => 'auth_forcepasswordchange', 'value' => 1));
284 }
285 } else {
286 // Record not added -- possibly some other error
287 notify($strusernotaddederror . ': ' . $username);
288 $userserrors++;
289 continue;
290 }
291 }
6b09974b 292
066bfbfe 293 // find course enrolments, groups and roles/types
294 for($ncourses = 1; $addcourse = @$user->{'course' . $ncourses}; ++$ncourses) {
295 // find course
296 if(!$course = @$courses[$addcourse]) {
297 notify(get_string('unknowncourse', 'error', $addcourse));
298 continue;
299 }
300 // find role
301 if ($addrole = @$user->{'role' . $ncourses}) {
302 $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
303 if (!$ok = role_assign($addrole, $user->id, 0, $coursecontext->id)) {
304 echo $strindent . $strcannotassignrole . '<br >';
305 }
306 } else {
307 // if no role, then find "old" enrolment type
308 switch ($addtype = @$user->{'type' . $ncourses}) {
309 case 2: // teacher
310 $ok = add_teacher($user->id, $course->id, 1);
311 break;
312 case 3: // non-editing teacher
313 $ok = add_teacher($user->id, $course->id, 0);
314 break;
315 case 1: // student
316 default:
317 $ok = enrol_student($user->id, $course->id);
318 break;
319 }
320 }
321 if ($ok) { // OK
322 echo $strindent . get_string('enrolledincourse', '', $addcourse) . '<br />';
323 } else {
324 notify(get_string('enrolledincoursenot', '', $addcourse));
325 }
6b09974b 326
066bfbfe 327 // find group to add to
328 if ($addgroup = @$user->{'group' . $ncourses}) {
329 if ($gid = groups_get_group_by_name($course->id, $addgroup)) {
330 $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
331 if (count(get_user_roles($coursecontext, $user->id))) {
332 if (groups_add_member($gid, $user->id)) {
333 echo $strindent . get_string('addedtogroup','',$addgroup) . '<br />';
334 } else {
335 notify(get_string('addedtogroupnot','',$addgroup));
a5702569 336 }
066bfbfe 337 } else {
338 notify(get_string('addedtogroupnotenrolled','',$addgroup));
0063abee 339 }
066bfbfe 340 } else {
341 notify(get_string('groupunknown','error',$addgroup));
6b09974b 342 }
a5702569 343 }
066bfbfe 344 }
345 }
346 echo '</p>';
347
348 fclose($fp);
349 notify(get_string('userscreated', 'admin') . ': ' . $usersnew);
350 notify(get_string('usersupdated', 'admin') . ': ' . $usersupdated);
351 notify(get_string('errors', 'admin') . ': ' . $userserrors);
352 if ($allowrenames) {
353 notify(get_string('usersrenamed', 'admin') . ': ' . $renames);
354 notify(get_string('renameerrors', 'admin') . ': ' . $renameerrors);
355 }
356 echo '<hr />';
6b09974b 357}
0a6150ca 358
a5702569 359/// Print the form
0a5dffcc 360print_heading_with_help(get_string('uploadusers'), 'uploadusers');
0a5dffcc 361$mform->display();
1ae083e4 362admin_externalpage_print_footer();
0a6150ca 363?>