weekly release 2.2dev
[moodle.git] / admin / uploaduser.php
CommitLineData
9e492db0 1<?php
8bdb31ed
PS
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
0a6150ca 16
8bdb31ed
PS
17/**
18 * Bulk user registration script from a comma separated file
19 *
20 * @package core
21 * @subpackage admin
22 * @copyright 2004 onwards Martin Dougiamas (http://dougiamas.com)
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
0a6150ca 25
e4e38544 26require('../config.php');
cc891abe 27require_once($CFG->libdir.'/adminlib.php');
e4e38544 28require_once($CFG->libdir.'/csvlib.class.php');
29require_once($CFG->dirroot.'/user/profile/lib.php');
59186c92 30require_once($CFG->dirroot.'/group/lib.php');
8bdb31ed 31require_once('uploaduserlib.php');
0a5dffcc 32require_once('uploaduser_form.php');
1ae083e4 33
e4e38544 34$iid = optional_param('iid', '', PARAM_INT);
df7ecfe4 35$previewrows = optional_param('previewrows', 10, PARAM_INT);
066bfbfe 36
8bdb31ed
PS
37@set_time_limit(60*60); // 1 hour should be enough
38raise_memory_limit(MEMORY_HUGE);
0a6150ca 39
ebff4779 40require_login();
066bfbfe 41admin_externalpage_setup('uploadusers');
1ae083e4 42require_capability('moodle/site:uploadusers', get_context_instance(CONTEXT_SYSTEM));
0a6150ca 43
e4e38544 44$struserrenamed = get_string('userrenamed', 'admin');
45$strusernotrenamedexists = get_string('usernotrenamedexists', 'error');
46$strusernotrenamedmissing = get_string('usernotrenamedmissing', 'error');
47$strusernotrenamedoff = get_string('usernotrenamedoff', 'error');
48$strusernotrenamedadmin = get_string('usernotrenamedadmin', 'error');
49
50$struserupdated = get_string('useraccountupdated', 'admin');
51$strusernotupdated = get_string('usernotupdatederror', 'error');
52$strusernotupdatednotexists = get_string('usernotupdatednotexists', 'error');
53$strusernotupdatedadmin = get_string('usernotupdatedadmin', 'error');
54
8bdb31ed
PS
55$struseruptodate = get_string('useraccountuptodate', 'admin');
56
e4e38544 57$struseradded = get_string('newuser');
58$strusernotadded = get_string('usernotaddedregistered', 'error');
59$strusernotaddederror = get_string('usernotaddederror', 'error');
60
61$struserdeleted = get_string('userdeleted', 'admin');
62$strusernotdeletederror = get_string('usernotdeletederror', 'error');
63$strusernotdeletedmissing = get_string('usernotdeletedmissing', 'error');
64$strusernotdeletedoff = get_string('usernotdeletedoff', 'error');
65$strusernotdeletedadmin = get_string('usernotdeletedadmin', 'error');
66
67$strcannotassignrole = get_string('cannotassignrole', 'error');
e4e38544 68
69$struserauthunsupported = get_string('userauthunsupported', 'error');
3fe2cfb5 70$stremailduplicate = get_string('useremailduplicate', 'error');
e4e38544 71
3f12c146 72$strinvalidpasswordpolicy = get_string('invalidpasswordpolicy', 'error');
e4e38544 73$errorstr = get_string('error');
ca23a9c9 74
8bdb31ed
PS
75$returnurl = new moodle_url('/admin/uploaduser.php');
76$bulknurl = new moodle_url('/admin/user/user_bulk.php');
e4e38544 77
2a6dcb72
PS
78$today = time();
79$today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0);
80
e4e38544 81// array of all valid fields for validation
6dbcacee 82$STD_FIELDS = array('id', 'firstname', 'lastname', 'username', 'email',
8bdb31ed 83 'city', 'country', 'lang', 'timezone', 'mailformat',
6dbcacee 84 'maildisplay', 'maildigest', 'htmleditor', 'ajax', 'autosubscribe',
8bdb31ed 85 'institution', 'department', 'idnumber', 'skype',
6dbcacee 86 'msn', 'aim', 'yahoo', 'icq', 'phone1', 'phone2', 'address',
8bdb31ed
PS
87 'url', 'description', 'descriptionformat', 'password',
88 'auth', // watch out when changing auth type or using external auth plugins!
89 'oldusername', // use when renaming users - this is the original username
90 'deleted', // 1 means delete user
91 );
e4e38544 92
93$PRF_FIELDS = array();
94
1d8bf5f0 95if ($prof_fields = $DB->get_records('user_info_field')) {
e4e38544 96 foreach ($prof_fields as $prof_field) {
97 $PRF_FIELDS[] = 'profile_field_'.$prof_field->shortname;
98 }
e4e38544 99}
8bdb31ed 100unset($prof_fields);
e4e38544 101
102if (empty($iid)) {
8bdb31ed 103 $mform1 = new admin_uploaduser_form1();
0a6150ca 104
8bdb31ed 105 if ($formdata = $mform1->get_data()) {
e4e38544 106 $iid = csv_import_reader::get_new_iid('uploaduser');
107 $cir = new csv_import_reader($iid, 'uploaduser');
df7ecfe4 108
8bdb31ed
PS
109 $content = $mform1->get_file_content('userfile');
110
111 $readcount = $cir->load_csv_content($content, $formdata->encoding, $formdata->delimiter_name);
e4e38544 112 unset($content);
df7ecfe4 113
e4e38544 114 if ($readcount === false) {
bd8ee7c1 115 print_error('csvloaderror', '', $returnurl);
e4e38544 116 } else if ($readcount == 0) {
5a2a5331 117 print_error('csvemptyfile', 'error', $returnurl);
ed22a01b 118 }
8bdb31ed
PS
119 // test if columns ok
120 $filecolumns = uu_validate_user_upload_columns($cir, $STD_FIELDS, $PRF_FIELDS, $returnurl);
e4e38544 121 // continue to form2
df7ecfe4 122
123 } else {
61ef8f9f 124 echo $OUTPUT->header();
9e492db0 125
6c7a5df7 126 echo $OUTPUT->heading_with_help(get_string('uploadusers', 'admin'), 'uploadusers', 'admin');
9e492db0 127
8bdb31ed 128 $mform1->display();
73d6f52f 129 echo $OUTPUT->footer();
df7ecfe4 130 die;
131 }
e4e38544 132} else {
133 $cir = new csv_import_reader($iid, 'uploaduser');
8bdb31ed 134 $filecolumns = uu_validate_user_upload_columns($cir, $STD_FIELDS, $PRF_FIELDS, $returnurl);
df7ecfe4 135}
136
8bdb31ed 137$mform2 = new admin_uploaduser_form2(null, array('columns'=>$filecolumns, 'data'=>array('iid'=>$iid, 'previewrows'=>$previewrows)));
df7ecfe4 138
139// If a file has been uploaded, then process it
8bdb31ed 140if ($formdata = $mform2->is_cancelled()) {
e4e38544 141 $cir->cleanup(true);
142 redirect($returnurl);
df7ecfe4 143
8bdb31ed 144} else if ($formdata = $mform2->get_data()) {
df7ecfe4 145 // Print the header
61ef8f9f 146 echo $OUTPUT->header();
2fff8846 147 echo $OUTPUT->heading(get_string('uploadusersresult', 'admin'));
e4e38544 148
149 $optype = $formdata->uutype;
150
0c4807ab 151 $updatetype = isset($formdata->uuupdatetype) ? $formdata->uuupdatetype : 0;
8bdb31ed
PS
152 $createpasswords = (!empty($formdata->uupasswordnew) and $optype != UU_USER_UPDATE);
153 $updatepasswords = (!empty($formdata->uupasswordold) and $optype != UU_USER_ADDNEW and $optype != UU_USER_ADDINC and ($updatetype == UU_UPDATE_FILEOVERRIDE or $updatetype == UU_UPDATE_ALLOVERRIDE));
154 $allowrenames = (!empty($formdata->uuallowrenames) and $optype != UU_USER_ADDNEW and $optype != UU_USER_ADDINC);
155 $allowdeletes = (!empty($formdata->uuallowdeletes) and $optype != UU_USER_ADDNEW and $optype != UU_USER_ADDINC);
0c4807ab 156 $bulk = $formdata->uubulk;
157 $noemailduplicates = $formdata->uunoemailduplicates;
8bdb31ed
PS
158 $standardusernames = $formdata->uustandardusernames;
159 $resetpasswords = isset($formdata->uuforcepasswordchange) ? $formdata->uuforcepasswordchange : UU_PWRESET_NONE;
e4e38544 160
161 // verification moved to two places: after upload and into form2
8bdb31ed
PS
162 $usersnew = 0;
163 $usersupdated = 0;
164 $usersuptodate = 0; //not printed yet anywhere
165 $userserrors = 0;
166 $deletes = 0;
167 $deleteerrors = 0;
168 $renames = 0;
169 $renameerrors = 0;
170 $usersskipped = 0;
d6bb2d2f 171 $weakpasswords = 0;
feecd4d6 172
e4e38544 173 // caches
8bdb31ed
PS
174 $ccache = array(); // course cache - do not fetch all courses here, we will not probably use them all anyway!
175 $rolecache = uu_allowed_roles_cache(); // roles lookup cache
176 $manualcache = array(); // cache of used manual enrol plugins in each course
177 $supportedauths = uu_supported_auths(); // officially supported plugins that are enabled
e4e38544 178
df997f84
PS
179 // we use only manual enrol plugin here, if it is disabled no enrol is done
180 if (enrol_is_enabled('manual')) {
181 $manual = enrol_get_plugin('manual');
182 } else {
183 $manual = NULL;
e4e38544 184 }
df7ecfe4 185
b4bd91ce 186 // clear bulk selection
e4e38544 187 if ($bulk) {
cd1edf9e 188 $SESSION->bulk_users = array();
e4e38544 189 }
df7ecfe4 190
e4e38544 191 // init csv import helper
192 $cir->init();
193 $linenum = 1; //column header is first line
df7ecfe4 194
e4e38544 195 // init upload progress tracker
196 $upt = new uu_progress_tracker();
8bdb31ed 197 $upt->start(); // start table
a2ce7344 198
e4e38544 199 while ($line = $cir->next()) {
200 $upt->flush();
201 $linenum++;
202
203 $upt->track('line', $linenum);
204
a226a972 205 $user = new stdClass();
8bdb31ed 206
e4e38544 207 // add fields to user object
8bdb31ed
PS
208 foreach ($line as $keynum => $value) {
209 if (!isset($filecolumns[$keynum])) {
210 // this should not happen
211 continue;
212 }
213 $key = $filecolumns[$keynum];
214 if (strpos($key, 'profile_field_') === 0) {
215 //NOTE: bloody mega hack alert!!
216 if (isset($USER->$key) and is_array($USER->$key)) {
217 // this must be some hacky field that is abusing arrays to store content and format
218 $user->$key = array();
219 $user->$key['text'] = $value;
220 $user->$key['format'] = FORMAT_MOODLE;
221 } else {
222 $user->$key = $value;
e4e38544 223 }
c3231d1d 224 } else {
8bdb31ed 225 $user->$key = $value;
a7db355a 226 }
e4e38544 227
8bdb31ed
PS
228 if (in_array($key, $upt->columns)) {
229 // default value in progress tracking table, can be changed later
230 $upt->track($key, s($value), 'normal');
e4e38544 231 }
8bdb31ed
PS
232 }
233 if (!isset($user->username)) {
234 // prevent warnings bellow
235 $user->username = '';
236 }
e4e38544 237
8bdb31ed
PS
238 if ($optype == UU_USER_ADDNEW or $optype == UU_USER_ADDINC) {
239 // user creation is a special case - the username may be constructed from templates using firstname and lastname
240 // better never try this in mixed update types
e4e38544 241 $error = false;
e4e38544 242 if (!isset($user->firstname) or $user->firstname === '') {
243 $upt->track('status', get_string('missingfield', 'error', 'firstname'), 'error');
244 $upt->track('firstname', $errorstr, 'error');
245 $error = true;
246 }
247 if (!isset($user->lastname) or $user->lastname === '') {
248 $upt->track('status', get_string('missingfield', 'error', 'lastname'), 'error');
249 $upt->track('lastname', $errorstr, 'error');
250 $error = true;
251 }
252 if ($error) {
253 $userserrors++;
254 continue;
255 }
256 // we require username too - we might use template for it though
8bdb31ed
PS
257 if (empty($user->username) and !empty($formdata->username)) {
258 $user->username = uu_process_template($formdata->username, $user);
259 $upt->track('username', s($user->username));
e4e38544 260 }
a7db355a 261 }
e4e38544 262
263 // normalize username
8bdb31ed
PS
264 $originalusername = $user->username;
265 if ($standardusernames) {
266 $user->username = clean_param($user->username, PARAM_USERNAME);
267 }
07ed083e 268
8bdb31ed 269 // make sure we really have username
e4e38544 270 if (empty($user->username)) {
271 $upt->track('status', get_string('missingfield', 'error', 'username'), 'error');
272 $upt->track('username', $errorstr, 'error');
273 $userserrors++;
274 continue;
8bdb31ed
PS
275 } else if ($user->username === 'guest') {
276 $upt->track('status', get_string('guestnoeditprofileother', 'error'), 'error');
277 $userserrors++;
278 continue;
e4e38544 279 }
280
8bdb31ed 281 if ($existinguser = $DB->get_record('user', array('username'=>$user->username, 'mnethostid'=>$CFG->mnet_localhost_id))) {
e4e38544 282 $upt->track('id', $existinguser->id, 'normal', false);
283 }
284
285 // find out in username incrementing required
8bdb31ed
PS
286 if ($existinguser and $optype == UU_USER_ADDINC) {
287 $user->username = uu_increment_username($user->username);
e4e38544 288 $existinguser = false;
289 }
290
8bdb31ed
PS
291 // notify about nay username changes
292 if ($originalusername !== $user->username) {
293 $upt->track('username', '', 'normal', false); // clear previous
294 $upt->track('username', s($originalusername).'-->'.s($user->username), 'info');
295 } else {
296 $upt->track('username', s($user->username), 'normal', false);
297 }
298
e4e38544 299 // add default values for remaining fields
8bdb31ed 300 $formdefaults = array();
e4e38544 301 foreach ($STD_FIELDS as $field) {
302 if (isset($user->$field)) {
303 continue;
304 }
305 // all validation moved to form2
306 if (isset($formdata->$field)) {
307 // process templates
8bdb31ed
PS
308 $user->$field = uu_process_template($formdata->$field, $user);
309 $formdefaults[$field] = true;
43070e61
PS
310 if (in_array($field, $upt->columns)) {
311 $upt->track($field, s($user->$field), 'normal');
312 }
e4e38544 313 }
314 }
315 foreach ($PRF_FIELDS as $field) {
316 if (isset($user->$field)) {
317 continue;
318 }
319 if (isset($formdata->$field)) {
320 // process templates
8bdb31ed
PS
321 $user->$field = uu_process_template($formdata->$field, $user);
322 $formdefaults[$field] = true;
e4e38544 323 }
324 }
325
326 // delete user
327 if (!empty($user->deleted)) {
328 if (!$allowdeletes) {
329 $usersskipped++;
330 $upt->track('status', $strusernotdeletedoff, 'warning');
331 continue;
332 }
333 if ($existinguser) {
4f0c2d00 334 if (is_siteadmin($existinguser->id)) {
e4e38544 335 $upt->track('status', $strusernotdeletedadmin, 'error');
336 $deleteerrors++;
337 continue;
338 }
339 if (delete_user($existinguser)) {
340 $upt->track('status', $struserdeleted);
341 $deletes++;
342 } else {
343 $upt->track('status', $strusernotdeletederror, 'error');
344 $deleteerrors++;
6b09974b 345 }
e4e38544 346 } else {
347 $upt->track('status', $strusernotdeletedmissing, 'error');
348 $deleteerrors++;
349 }
350 continue;
351 }
352 // we do not need the deleted flag anymore
353 unset($user->deleted);
354
355 // renaming requested?
356 if (!empty($user->oldusername) ) {
e4e38544 357 if (!$allowrenames) {
358 $usersskipped++;
359 $upt->track('status', $strusernotrenamedoff, 'warning');
360 continue;
361 }
362
363 if ($existinguser) {
364 $upt->track('status', $strusernotrenamedexists, 'error');
365 $renameerrors++;
366 continue;
16a1fed4 367 }
ed22a01b 368
8bdb31ed
PS
369 if ($user->username === 'guest') {
370 $upt->track('status', get_string('guestnoeditprofileother', 'error'), 'error');
371 $renameerrors++;
372 continue;
373 }
374
375 if ($standardusernames) {
376 $oldusername = clean_param($user->oldusername, PARAM_USERNAME);
377 } else {
378 $oldusername = $user->oldusername;
379 }
380
381 // no guessing when looking for old username, it must be exact match
382 if ($olduser = $DB->get_record('user', array('username'=>$oldusername, 'mnethostid'=>$CFG->mnet_localhost_id))) {
e4e38544 383 $upt->track('id', $olduser->id, 'normal', false);
4f0c2d00 384 if (is_siteadmin($olduser->id)) {
e4e38544 385 $upt->track('status', $strusernotrenamedadmin, 'error');
386 $renameerrors++;
a7db355a 387 continue;
0063abee 388 }
df997f84
PS
389 $DB->set_field('user', 'username', $user->username, array('id'=>$olduser->id));
390 $upt->track('username', '', 'normal', false); // clear previous
8bdb31ed 391 $upt->track('username', s($oldusername).'-->'.s($user->username), 'info');
df997f84
PS
392 $upt->track('status', $struserrenamed);
393 $renames++;
e4e38544 394 } else {
395 $upt->track('status', $strusernotrenamedmissing, 'error');
396 $renameerrors++;
397 continue;
398 }
399 $existinguser = $olduser;
400 $existinguser->username = $user->username;
401 }
402
403 // can we process with update or insert?
404 $skip = false;
405 switch ($optype) {
8bdb31ed 406 case UU_USER_ADDNEW:
e4e38544 407 if ($existinguser) {
408 $usersskipped++;
409 $upt->track('status', $strusernotadded, 'warning');
3fe2cfb5 410 $skip = true;
e4e38544 411 }
412 break;
413
8bdb31ed 414 case UU_USER_ADDINC:
e4e38544 415 if ($existinguser) {
416 //this should not happen!
417 $upt->track('status', $strusernotaddederror, 'error');
418 $userserrors++;
8bdb31ed 419 $skip = true;
e4e38544 420 }
421 break;
422
8bdb31ed 423 case UU_USER_ADD_UPDATE:
e4e38544 424 break;
425
8bdb31ed 426 case UU_USER_UPDATE:
e4e38544 427 if (!$existinguser) {
428 $usersskipped++;
429 $upt->track('status', $strusernotupdatednotexists, 'warning');
430 $skip = true;
431 }
432 break;
8bdb31ed
PS
433
434 default:
435 // unknown type
436 $skip = true;
e4e38544 437 }
438
439 if ($skip) {
440 continue;
441 }
442
443 if ($existinguser) {
444 $user->id = $existinguser->id;
445
8bdb31ed
PS
446 $upt->track('username', html_writer::link(new moodle_url('/user/profile.php', array('id'=>$existinguser->id)), s($existinguser->username)), 'normal', false);
447
4f0c2d00 448 if (is_siteadmin($user->id)) {
e4e38544 449 $upt->track('status', $strusernotupdatedadmin, 'error');
450 $userserrors++;
451 continue;
452 }
453
8bdb31ed
PS
454 $existinguser->timemodified = time();
455 // do NOT mess with timecreated or firstaccess here!
456
457 //load existing profile data
458 profile_load_data($existinguser);
3fe2cfb5 459
8bdb31ed 460 $upt->track('auth', $existinguser->auth, 'normal', false);
e4e38544 461
8bdb31ed
PS
462 $doupdate = false;
463
464 if ($updatetype != UU_UPDATE_NOCHANGES) {
465 if (!empty($user->auth) and $user->auth !== $existinguser->auth) {
466 $upt->track('auth', s($existinguser->auth).'-->'.s($user->auth), 'info', false);
467 $existinguser->auth = $user->auth;
468 if (!isset($supportedauths[$user->auth])) {
469 $upt->track('auth', $struserauthunsupported, 'warning');
470 }
e4e38544 471 }
8bdb31ed
PS
472 $allcolumns = array_merge($STD_FIELDS, $PRF_FIELDS);
473 foreach ($allcolumns as $column) {
474 if ($column === 'username' or $column === 'password' or $column === 'auth') {
475 // these can not be changed here
e4e38544 476 continue;
477 }
8bdb31ed
PS
478 if (!property_exists($user, $column) or !property_exists($existinguser, $column)) {
479 // this should never happen
480 continue;
481 }
482 if ($updatetype == UU_UPDATE_MISSING) {
483 if (!is_null($existinguser->$column) and $existinguser->$column !== '') {
e4e38544 484 continue;
a7db355a 485 }
8bdb31ed
PS
486 } else if ($updatetype == UU_UPDATE_ALLOVERRIDE) {
487 // we override everything
3f12c146 488
8bdb31ed
PS
489 } else if ($updatetype == UU_UPDATE_FILEOVERRIDE) {
490 if (!empty($formdefaults[$column])) {
491 // do not override with form defaults
492 continue;
493 }
494 }
495 if ($existinguser->$column !== $user->$column) {
496 if ($column === 'email') {
497 if ($DB->record_exists('user', array('email'=>$user->email))) {
498 if ($noemailduplicates) {
499 $upt->track('email', $stremailduplicate, 'error');
500 $upt->track('status', $strusernotupdated, 'error');
501 $userserrors++;
502 continue 2;
503 } else {
504 $upt->track('email', $stremailduplicate, 'warning');
3f12c146
RW
505 }
506 }
8bdb31ed
PS
507 if (!validate_email($user->email)) {
508 $upt->track('email', get_string('invalidemail'), 'warning');
e4e38544 509 }
8bdb31ed 510 }
3f12c146 511
8bdb31ed
PS
512 if (in_array($column, $upt->columns)) {
513 $upt->track($column, s($existinguser->$column).'-->'.s($user->$column), 'info', false);
a7db355a 514 }
8bdb31ed
PS
515 $existinguser->$column = $user->$column;
516 $doupdate = true;
6b09974b 517 }
a7db355a 518 }
8bdb31ed 519 }
ed22a01b 520
8bdb31ed 521 try {
3f12c146 522 $auth = get_auth_plugin($existinguser->auth);
8bdb31ed
PS
523 } catch (Exception $e) {
524 $upt->track('auth', get_string('userautherror', 'error', s($existinguser->auth)), 'error');
525 $upt->track('status', $strusernotupdated, 'error');
526 $userserrors++;
527 continue;
528 }
529 $isinternalauth = $auth->is_internal();
3f12c146 530
8bdb31ed
PS
531 // changing of passwords is a special case
532 // do not force password changes for external auth plugins!
533 $oldpw = $existinguser->password;
534 if (!$isinternalauth) {
535 $existinguser->password = 'not cached';
536 $upt->track('password', '-', 'normal', false);
537 // clean up prefs
538 unset_user_preference('create_password', $existinguser);
539 unset_user_preference('auth_forcepasswordchange', $existinguser);
540
541 } else if (!empty($user->password)) {
542 if ($updatepasswords) {
543 $errmsg = null;
faceca91 544 $weak = !check_password_policy($user->password, $errmsg);
8bdb31ed
PS
545 if ($resetpasswords == UU_PWRESET_ALL or ($resetpasswords == UU_PWRESET_WEAK and $weak)) {
546 if ($weak) {
547 $weakpasswords++;
548 $upt->track('password', $strinvalidpasswordpolicy, 'warning');
549 }
550 set_user_preference('auth_forcepasswordchange', 1, $existinguser);
551 } else {
552 unset_user_preference('auth_forcepasswordchange', $existinguser);
553 }
554 unset_user_preference('create_password', $existinguser); // no need to create password any more
555 $existinguser->password = hash_internal_user_password($user->password);
2197b642 556 $upt->track('password', $user->password, 'normal', false);
3f12c146 557 } else {
8bdb31ed
PS
558 // do not print password when not changed
559 $upt->track('password', '', 'normal', false);
3f12c146 560 }
8bdb31ed 561 }
3f12c146 562
8bdb31ed
PS
563 if ($doupdate or $existinguser->password !== $oldpw) {
564 // we want only users that were really updated
3f12c146 565
df997f84 566 $DB->update_record('user', $existinguser);
3f12c146 567
df997f84
PS
568 $upt->track('status', $struserupdated);
569 $usersupdated++;
e4e38544 570 // save custom profile fields data from csv file
5d910388 571 profile_save_data($existinguser);
e6f74ba3
PS
572
573 events_trigger('user_updated', $existinguser);
e4e38544 574
8bdb31ed
PS
575 if ($bulk == UU_BULK_UPDATED or $bulk == UU_BULK_ALL) {
576 if (!in_array($user->id, $SESSION->bulk_users)) {
577 $SESSION->bulk_users[] = $user->id;
578 }
579 }
580
581 } else {
582 // no user information changed
583 $upt->track('status', $struseruptodate);
584 $usersuptodate++;
585
586 if ($bulk == UU_BULK_ALL) {
587 if (!in_array($user->id, $SESSION->bulk_users)) {
588 $SESSION->bulk_users[] = $user->id;
589 }
ed22a01b 590 }
066bfbfe 591 }
ed22a01b 592
e4e38544 593 } else {
8bdb31ed
PS
594 // save the new user to the database
595 $user->confirmed = 1;
a7db355a 596 $user->timemodified = time();
8bdb31ed
PS
597 $user->timecreated = time();
598 $user->mnethostid = $CFG->mnet_localhost_id; // we support ONLY local accounts here, sorry
066bfbfe 599
8bdb31ed 600 if (empty($user->auth)) {
3f12c146
RW
601 $user->auth = 'manual';
602 }
8bdb31ed 603 $upt->track('auth', $user->auth, 'normal', false);
3f12c146 604
8bdb31ed
PS
605 // do not insert record if new auth plugin does not exist!
606 try {
607 $auth = get_auth_plugin($user->auth);
608 } catch (Exception $e) {
609 $upt->track('auth', get_string('userautherror', 'error', s($user->auth)), 'error');
610 $upt->track('status', $strusernotaddederror, 'error');
611 $userserrors++;
612 continue;
e4e38544 613 }
8bdb31ed
PS
614 if (!isset($supportedauths[$user->auth])) {
615 $upt->track('auth', $struserauthunsupported, 'warning');
066bfbfe 616 }
a2ce7344 617
8bdb31ed
PS
618 $isinternalauth = $auth->is_internal();
619
43070e61
PS
620 if (empty($user->email)) {
621 $upt->track('email', get_string('invalidemail'), 'error');
622 $upt->track('status', $strusernotaddederror, 'error');
623 $userserrors++;
624 continue;
625
626 } else if ($DB->record_exists('user', array('email'=>$user->email))) {
0c4807ab 627 if ($noemailduplicates) {
628 $upt->track('email', $stremailduplicate, 'error');
629 $upt->track('status', $strusernotaddederror, 'error');
630 $userserrors++;
631 continue;
632 } else {
633 $upt->track('email', $stremailduplicate, 'warning');
634 }
635 }
8bdb31ed
PS
636 if (!validate_email($user->email)) {
637 $upt->track('email', get_string('invalidemail'), 'warning');
3f12c146 638 }
0c4807ab 639
8bdb31ed
PS
640 $forcechangepassword = false;
641
642 if ($isinternalauth) {
643 if (empty($user->password)) {
644 if ($createpasswords) {
645 $user->password = 'to be generated';
646 $upt->track('password', '', 'normal', false);
647 $upt->track('password', get_string('uupasswordcron', 'admin'), 'warning', false);
648 } else {
649 $upt->track('password', '', 'normal', false);
650 $upt->track('password', get_string('missingfield', 'error', 'password'), 'error');
651 $upt->track('status', $strusernotaddederror, 'error');
652 $userserrors++;
653 continue;
654 }
3f12c146 655 } else {
8bdb31ed 656 $errmsg = null;
faceca91 657 $weak = !check_password_policy($user->password, $errmsg);
8bdb31ed
PS
658 if ($resetpasswords == UU_PWRESET_ALL or ($resetpasswords == UU_PWRESET_WEAK and $weak)) {
659 if ($weak) {
660 $weakpasswords++;
661 $upt->track('password', $strinvalidpasswordpolicy, 'warning');
662 }
663 $forcechangepassword = true;
664 }
665 $user->password = hash_internal_user_password($user->password);
3f12c146 666 }
8bdb31ed
PS
667 } else {
668 $user->password = 'not cached';
669 $upt->track('password', '-', 'normal', false);
df997f84
PS
670 }
671
8bdb31ed
PS
672 // create user - insert_record ignores any extra properties
673 $user->id = $DB->insert_record('user', $user);
674 $upt->track('username', html_writer::link(new moodle_url('/user/profile.php', array('id'=>$user->id)), s($user->username)), 'normal', false);
675
e4e38544 676 // save custom profile fields data
677 profile_save_data($user);
678
8bdb31ed
PS
679 if ($forcechangepassword) {
680 set_user_preference('auth_forcepasswordchange', 1, $user);
681 }
682 if ($user->password === 'to be generated') {
683 set_user_preference('create_password', 1, $user);
684 }
685
686 $upt->track('status', $struseradded);
687 $upt->track('id', $user->id, 'normal', false);
688 $usersnew++;
689
2304f629 690 // make sure user context exists
a5feb176 691 get_context_instance(CONTEXT_USER, $user->id);
2304f629 692
e6f74ba3
PS
693 events_trigger('user_created', $user);
694
8bdb31ed 695 if ($bulk == UU_BULK_NEW or $bulk == UU_BULK_ALL) {
cd1edf9e 696 if (!in_array($user->id, $SESSION->bulk_users)) {
697 $SESSION->bulk_users[] = $user->id;
066bfbfe 698 }
066bfbfe 699 }
e4e38544 700 }
701
2686b6c3 702 // find course enrolments, groups, roles/types and enrol periods
8bdb31ed
PS
703 // this is again a special case, we always do this for any updated or created users
704 foreach ($filecolumns as $column) {
e4e38544 705 if (!preg_match('/^course\d+$/', $column)) {
706 continue;
707 }
708 $i = substr($column, 6);
6b09974b 709
df997f84
PS
710 if (empty($user->{'course'.$i})) {
711 continue;
712 }
e4e38544 713 $shortname = $user->{'course'.$i};
714 if (!array_key_exists($shortname, $ccache)) {
df997f84 715 if (!$course = $DB->get_record('course', array('shortname'=>$shortname), 'id, shortname')) {
8bdb31ed 716 $upt->track('enrolments', get_string('unknowncourse', 'error', s($shortname)), 'error');
a7db355a 717 continue;
066bfbfe 718 }
e4e38544 719 $ccache[$shortname] = $course;
720 $ccache[$shortname]->groups = null;
721 }
722 $courseid = $ccache[$shortname]->id;
723 $coursecontext = get_context_instance(CONTEXT_COURSE, $courseid);
df997f84 724 if (!isset($manualcache[$courseid])) {
4cb02426
PS
725 $manualcache[$courseid] = false;
726 if ($manual) {
727 if ($instances = enrol_get_instances($courseid, false)) {
728 foreach ($instances as $instance) {
729 if ($instance->enrol === 'manual') {
730 $manualcache[$courseid] = $instance;
731 break;
732 }
733 }
734 }
e4e38544 735 }
df997f84 736 }
e4e38544 737
df997f84
PS
738 if ($manual and $manualcache[$courseid]) {
739
740 // find role
741 $rid = false;
742 if (!empty($user->{'role'.$i})) {
743 $addrole = $user->{'role'.$i};
744 if (array_key_exists($addrole, $rolecache)) {
745 $rid = $rolecache[$addrole]->id;
e4e38544 746 } else {
8bdb31ed 747 $upt->track('enrolments', get_string('unknownrole', 'error', s($addrole)), 'error');
df997f84 748 continue;
a7db355a 749 }
e4e38544 750
df997f84
PS
751 } else if (!empty($user->{'type'.$i})) {
752 // if no role, then find "old" enrolment type
753 $addtype = $user->{'type'.$i};
754 if ($addtype < 1 or $addtype > 3) {
755 $upt->track('enrolments', $strerror.': typeN = 1|2|3', 'error');
756 continue;
757 } else if (empty($formdata->{'uulegacy'.$addtype})) {
758 continue;
759 } else {
760 $rid = $formdata->{'uulegacy'.$addtype};
761 }
e4e38544 762 } else {
df997f84
PS
763 // no role specified, use the default from manual enrol plugin
764 $rid = $manualcache[$courseid]->roleid;
a7db355a 765 }
2686b6c3 766
df997f84
PS
767 if ($rid) {
768 // find duration
df997f84
PS
769 $timeend = 0;
770 if (!empty($user->{'enrolperiod'.$i})) {
8bdb31ed 771 $duration = (int)$user->{'enrolperiod'.$i} * 60*60*24; // convert days to seconds
df997f84 772 if ($duration > 0) { // sanity check
8bdb31ed 773 $timeend = $today + $duration;
df997f84
PS
774 }
775 }
2686b6c3 776
02c97e65 777 $manual->enrol_user($manualcache[$courseid], $user->id, $rid, $today, $timeend);
df997f84 778
a226a972 779 $a = new stdClass();
df997f84
PS
780 $a->course = $shortname;
781 $a->role = $rolecache[$rid]->name;
782 $upt->track('enrolments', get_string('enrolledincourserole', 'enrol_manual', $a));
066bfbfe 783 }
e4e38544 784 }
6b09974b 785
e4e38544 786 // find group to add to
787 if (!empty($user->{'group'.$i})) {
788 // make sure user is enrolled into course before adding into groups
4f0c2d00 789 if (!is_enrolled($coursecontext, $user->id)) {
d85f2634 790 $upt->track('enrolments', get_string('addedtogroupnotenrolled', '', $user->{'group'.$i}), 'error');
e4e38544 791 continue;
792 }
793 //build group cache
794 if (is_null($ccache[$shortname]->groups)) {
795 $ccache[$shortname]->groups = array();
35987665 796 if ($groups = groups_get_all_groups($courseid)) {
e4e38544 797 foreach ($groups as $gid=>$group) {
a226a972 798 $ccache[$shortname]->groups[$gid] = new stdClass();
e4e38544 799 $ccache[$shortname]->groups[$gid]->id = $gid;
800 $ccache[$shortname]->groups[$gid]->name = $group->name;
801 if (!is_numeric($group->name)) { // only non-numeric names are supported!!!
8bdb31ed
PS
802 $ccache[$shortname]->groups[$group->name] = new stdClass();
803 $ccache[$shortname]->groups[$group->name]->id = $gid;
804 $ccache[$shortname]->groups[$group->name]->name = $group->name;
a7db355a 805 }
a5702569 806 }
0063abee 807 }
6b09974b 808 }
e4e38544 809 // group exists?
810 $addgroup = $user->{'group'.$i};
811 if (!array_key_exists($addgroup, $ccache[$shortname]->groups)) {
b225cf36 812 // if group doesn't exist, create it
a226a972 813 $newgroupdata = new stdClass();
b225cf36 814 $newgroupdata->name = $addgroup;
815 $newgroupdata->courseid = $ccache[$shortname]->id;
816 if ($ccache[$shortname]->groups[$addgroup]->id = groups_create_group($newgroupdata)){
817 $ccache[$shortname]->groups[$addgroup]->name = $newgroupdata->name;
818 } else {
8bdb31ed 819 $upt->track('enrolments', get_string('unknowngroup', 'error', s($addgroup)), 'error');
b225cf36 820 continue;
821 }
e4e38544 822 }
823 $gid = $ccache[$shortname]->groups[$addgroup]->id;
824 $gname = $ccache[$shortname]->groups[$addgroup]->name;
825
9c000a99 826 try {
827 if (groups_add_member($gid, $user->id)) {
8bdb31ed 828 $upt->track('enrolments', get_string('addedtogroup', '', s($gname)));
df997f84 829 } else {
8bdb31ed 830 $upt->track('enrolments', get_string('addedtogroupnot', '', s($gname)), 'error');
9c000a99 831 }
832 } catch (moodle_exception $e) {
8bdb31ed 833 $upt->track('enrolments', get_string('addedtogroupnot', '', s($gname)), 'error');
e4e38544 834 continue;
835 }
a5702569 836 }
066bfbfe 837 }
838 }
e4e38544 839 $upt->close(); // close table
840
841 $cir->close();
842 $cir->cleanup(true);
843
20486a5a 844 echo $OUTPUT->box_start('boxwidthnarrow boxaligncenter generalbox', 'uploadresults');
e4e38544 845 echo '<p>';
8bdb31ed 846 if ($optype != UU_USER_UPDATE) {
e4e38544 847 echo get_string('userscreated', 'admin').': '.$usersnew.'<br />';
848 }
8bdb31ed 849 if ($optype == UU_USER_UPDATE or $optype == UU_USER_ADD_UPDATE) {
e4e38544 850 echo get_string('usersupdated', 'admin').': '.$usersupdated.'<br />';
851 }
852 if ($allowdeletes) {
853 echo get_string('usersdeleted', 'admin').': '.$deletes.'<br />';
854 echo get_string('deleteerrors', 'admin').': '.$deleteerrors.'<br />';
855 }
856 if ($allowrenames) {
857 echo get_string('usersrenamed', 'admin').': '.$renames.'<br />';
858 echo get_string('renameerrors', 'admin').': '.$renameerrors.'<br />';
859 }
860 if ($usersskipped) {
861 echo get_string('usersskipped', 'admin').': '.$usersskipped.'<br />';
862 }
d6bb2d2f 863 echo get_string('usersweakpassword', 'admin').': '.$weakpasswords.'<br />';
e4e38544 864 echo get_string('errors', 'admin').': '.$userserrors.'</p>';
20486a5a 865 echo $OUTPUT->box_end();
e4e38544 866
867 if ($bulk) {
8fbce1c8 868 echo $OUTPUT->continue_button($bulknurl);
e4e38544 869 } else {
8fbce1c8 870 echo $OUTPUT->continue_button($returnurl);
e4e38544 871 }
73d6f52f 872 echo $OUTPUT->footer();
df7ecfe4 873 die;
6b09974b 874}
0a6150ca 875
df7ecfe4 876// Print the header
61ef8f9f 877echo $OUTPUT->header();
df7ecfe4 878
6c7a5df7 879echo $OUTPUT->heading(get_string('uploaduserspreview', 'admin'));
df7ecfe4 880
8bdb31ed
PS
881// NOTE: this is JUST csv processing preview, we must not prevent import from here if there is something in the file!!
882// this was intended for validation of csv formatting and encoding, not filtering the data!!!!
883// we definitely must not process the whole file!
884
885// preview table data
886$data = array();
e4e38544 887$cir->init();
8bdb31ed
PS
888$linenum = 1; //column header is first line
889while ($linenum <= $previewrows and $fields = $cir->next()) {
890 $linenum++;
3fe2cfb5 891 $rowcols = array();
8bdb31ed
PS
892 $rowcols['line'] = $linenum;
893 foreach($fields as $key => $field) {
894 $rowcols[$filecolumns[$key]] = s($field);
3fe2cfb5 895 }
8bdb31ed 896 $rowcols['status'] = array();
3fe2cfb5 897
8bdb31ed
PS
898 if (isset($rowcols['username'])) {
899 $stdusername = clean_param($rowcols['username'], PARAM_USERNAME);
900 if ($rowcols['username'] !== $stdusername) {
901 $rowcols['status'][] = get_string('invalidusernameupload');
3fe2cfb5 902 }
8bdb31ed
PS
903 if ($userid = $DB->get_field('user', 'id', array('username'=>$stdusername, 'mnethostid'=>$CFG->mnet_localhost_id))) {
904 $rowcols['username'] = html_writer::link(new moodle_url('/user/profile.php', array('id'=>$userid)), $rowcols['username']);
e4e38544 905 }
8bdb31ed
PS
906 } else {
907 $rowcols['status'][] = get_string('missingusername');
df7ecfe4 908 }
07ed083e 909
43070e61
PS
910 if (isset($rowcols['email'])) {
911 if (!validate_email($rowcols['email'])) {
912 $rowcols['status'][] = get_string('invalidemail');
913 }
914 if ($DB->record_exists('user', array('email'=>$rowcols['email']))) {
915 $rowcols['status'][] = $stremailduplicate;
916 }
07ed083e 917 }
8bdb31ed
PS
918 $rowcols['status'] = implode('<br />', $rowcols['status']);
919 $data[] = $rowcols;
07ed083e 920}
8bdb31ed
PS
921if ($fields = $cir->next()) {
922 $data[] = array_fill(0, count($fields) + 2, '...');
07ed083e 923}
8bdb31ed 924$cir->close();
3fe2cfb5
RW
925
926$table = new html_table();
927$table->id = "uupreview";
16be8974 928$table->attributes['class'] = 'generaltable';
3fe2cfb5
RW
929$table->tablealign = 'center';
930$table->summary = get_string('uploaduserspreview', 'admin');
931$table->head = array();
8bdb31ed 932$table->data = $data;
3fe2cfb5 933
8bdb31ed
PS
934$table->head[] = get_string('uucsvline', 'admin');
935foreach ($filecolumns as $column) {
936 $table->head[] = $column;
07ed083e 937}
8bdb31ed 938$table->head[] = get_string('status');
07ed083e 939
3f12c146 940echo html_writer::tag('div', html_writer::table($table), array('class'=>'flexible-wrap'));
3fe2cfb5 941
8bdb31ed 942/// Print the form
07ed083e 943
8bdb31ed 944$mform2->display();
73d6f52f 945echo $OUTPUT->footer();
df7ecfe4 946die;
947