weekly release
[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;
e4e38544 310 }
311 }
312 foreach ($PRF_FIELDS as $field) {
313 if (isset($user->$field)) {
314 continue;
315 }
316 if (isset($formdata->$field)) {
317 // process templates
8bdb31ed
PS
318 $user->$field = uu_process_template($formdata->$field, $user);
319 $formdefaults[$field] = true;
e4e38544 320 }
321 }
322
323 // delete user
324 if (!empty($user->deleted)) {
325 if (!$allowdeletes) {
326 $usersskipped++;
327 $upt->track('status', $strusernotdeletedoff, 'warning');
328 continue;
329 }
330 if ($existinguser) {
4f0c2d00 331 if (is_siteadmin($existinguser->id)) {
e4e38544 332 $upt->track('status', $strusernotdeletedadmin, 'error');
333 $deleteerrors++;
334 continue;
335 }
336 if (delete_user($existinguser)) {
337 $upt->track('status', $struserdeleted);
338 $deletes++;
339 } else {
340 $upt->track('status', $strusernotdeletederror, 'error');
341 $deleteerrors++;
6b09974b 342 }
e4e38544 343 } else {
344 $upt->track('status', $strusernotdeletedmissing, 'error');
345 $deleteerrors++;
346 }
347 continue;
348 }
349 // we do not need the deleted flag anymore
350 unset($user->deleted);
351
352 // renaming requested?
353 if (!empty($user->oldusername) ) {
e4e38544 354 if (!$allowrenames) {
355 $usersskipped++;
356 $upt->track('status', $strusernotrenamedoff, 'warning');
357 continue;
358 }
359
360 if ($existinguser) {
361 $upt->track('status', $strusernotrenamedexists, 'error');
362 $renameerrors++;
363 continue;
16a1fed4 364 }
ed22a01b 365
8bdb31ed
PS
366 if ($user->username === 'guest') {
367 $upt->track('status', get_string('guestnoeditprofileother', 'error'), 'error');
368 $renameerrors++;
369 continue;
370 }
371
372 if ($standardusernames) {
373 $oldusername = clean_param($user->oldusername, PARAM_USERNAME);
374 } else {
375 $oldusername = $user->oldusername;
376 }
377
378 // no guessing when looking for old username, it must be exact match
379 if ($olduser = $DB->get_record('user', array('username'=>$oldusername, 'mnethostid'=>$CFG->mnet_localhost_id))) {
e4e38544 380 $upt->track('id', $olduser->id, 'normal', false);
4f0c2d00 381 if (is_siteadmin($olduser->id)) {
e4e38544 382 $upt->track('status', $strusernotrenamedadmin, 'error');
383 $renameerrors++;
a7db355a 384 continue;
0063abee 385 }
df997f84
PS
386 $DB->set_field('user', 'username', $user->username, array('id'=>$olduser->id));
387 $upt->track('username', '', 'normal', false); // clear previous
8bdb31ed 388 $upt->track('username', s($oldusername).'-->'.s($user->username), 'info');
df997f84
PS
389 $upt->track('status', $struserrenamed);
390 $renames++;
e4e38544 391 } else {
392 $upt->track('status', $strusernotrenamedmissing, 'error');
393 $renameerrors++;
394 continue;
395 }
396 $existinguser = $olduser;
397 $existinguser->username = $user->username;
398 }
399
400 // can we process with update or insert?
401 $skip = false;
402 switch ($optype) {
8bdb31ed 403 case UU_USER_ADDNEW:
e4e38544 404 if ($existinguser) {
405 $usersskipped++;
406 $upt->track('status', $strusernotadded, 'warning');
3fe2cfb5 407 $skip = true;
e4e38544 408 }
409 break;
410
8bdb31ed 411 case UU_USER_ADDINC:
e4e38544 412 if ($existinguser) {
413 //this should not happen!
414 $upt->track('status', $strusernotaddederror, 'error');
415 $userserrors++;
8bdb31ed 416 $skip = true;
e4e38544 417 }
418 break;
419
8bdb31ed 420 case UU_USER_ADD_UPDATE:
e4e38544 421 break;
422
8bdb31ed 423 case UU_USER_UPDATE:
e4e38544 424 if (!$existinguser) {
425 $usersskipped++;
426 $upt->track('status', $strusernotupdatednotexists, 'warning');
427 $skip = true;
428 }
429 break;
8bdb31ed
PS
430
431 default:
432 // unknown type
433 $skip = true;
e4e38544 434 }
435
436 if ($skip) {
437 continue;
438 }
439
440 if ($existinguser) {
441 $user->id = $existinguser->id;
442
8bdb31ed
PS
443 $upt->track('username', html_writer::link(new moodle_url('/user/profile.php', array('id'=>$existinguser->id)), s($existinguser->username)), 'normal', false);
444
4f0c2d00 445 if (is_siteadmin($user->id)) {
e4e38544 446 $upt->track('status', $strusernotupdatedadmin, 'error');
447 $userserrors++;
448 continue;
449 }
450
8bdb31ed
PS
451 $existinguser->timemodified = time();
452 // do NOT mess with timecreated or firstaccess here!
453
454 //load existing profile data
455 profile_load_data($existinguser);
3fe2cfb5 456
8bdb31ed 457 $upt->track('auth', $existinguser->auth, 'normal', false);
e4e38544 458
8bdb31ed
PS
459 $doupdate = false;
460
461 if ($updatetype != UU_UPDATE_NOCHANGES) {
462 if (!empty($user->auth) and $user->auth !== $existinguser->auth) {
463 $upt->track('auth', s($existinguser->auth).'-->'.s($user->auth), 'info', false);
464 $existinguser->auth = $user->auth;
465 if (!isset($supportedauths[$user->auth])) {
466 $upt->track('auth', $struserauthunsupported, 'warning');
467 }
e4e38544 468 }
8bdb31ed
PS
469 $allcolumns = array_merge($STD_FIELDS, $PRF_FIELDS);
470 foreach ($allcolumns as $column) {
471 if ($column === 'username' or $column === 'password' or $column === 'auth') {
472 // these can not be changed here
e4e38544 473 continue;
474 }
8bdb31ed
PS
475 if (!property_exists($user, $column) or !property_exists($existinguser, $column)) {
476 // this should never happen
477 continue;
478 }
479 if ($updatetype == UU_UPDATE_MISSING) {
480 if (!is_null($existinguser->$column) and $existinguser->$column !== '') {
e4e38544 481 continue;
a7db355a 482 }
8bdb31ed
PS
483 } else if ($updatetype == UU_UPDATE_ALLOVERRIDE) {
484 // we override everything
3f12c146 485
8bdb31ed
PS
486 } else if ($updatetype == UU_UPDATE_FILEOVERRIDE) {
487 if (!empty($formdefaults[$column])) {
488 // do not override with form defaults
489 continue;
490 }
491 }
492 if ($existinguser->$column !== $user->$column) {
493 if ($column === 'email') {
494 if ($DB->record_exists('user', array('email'=>$user->email))) {
495 if ($noemailduplicates) {
496 $upt->track('email', $stremailduplicate, 'error');
497 $upt->track('status', $strusernotupdated, 'error');
498 $userserrors++;
499 continue 2;
500 } else {
501 $upt->track('email', $stremailduplicate, 'warning');
3f12c146
RW
502 }
503 }
8bdb31ed
PS
504 if (!validate_email($user->email)) {
505 $upt->track('email', get_string('invalidemail'), 'warning');
e4e38544 506 }
8bdb31ed 507 }
3f12c146 508
8bdb31ed
PS
509 if (in_array($column, $upt->columns)) {
510 $upt->track($column, s($existinguser->$column).'-->'.s($user->$column), 'info', false);
a7db355a 511 }
8bdb31ed
PS
512 $existinguser->$column = $user->$column;
513 $doupdate = true;
6b09974b 514 }
a7db355a 515 }
8bdb31ed 516 }
ed22a01b 517
8bdb31ed 518 try {
3f12c146 519 $auth = get_auth_plugin($existinguser->auth);
8bdb31ed
PS
520 } catch (Exception $e) {
521 $upt->track('auth', get_string('userautherror', 'error', s($existinguser->auth)), 'error');
522 $upt->track('status', $strusernotupdated, 'error');
523 $userserrors++;
524 continue;
525 }
526 $isinternalauth = $auth->is_internal();
3f12c146 527
8bdb31ed
PS
528 // changing of passwords is a special case
529 // do not force password changes for external auth plugins!
530 $oldpw = $existinguser->password;
531 if (!$isinternalauth) {
532 $existinguser->password = 'not cached';
533 $upt->track('password', '-', 'normal', false);
534 // clean up prefs
535 unset_user_preference('create_password', $existinguser);
536 unset_user_preference('auth_forcepasswordchange', $existinguser);
537
538 } else if (!empty($user->password)) {
539 if ($updatepasswords) {
540 $errmsg = null;
faceca91 541 $weak = !check_password_policy($user->password, $errmsg);
8bdb31ed
PS
542 if ($resetpasswords == UU_PWRESET_ALL or ($resetpasswords == UU_PWRESET_WEAK and $weak)) {
543 if ($weak) {
544 $weakpasswords++;
545 $upt->track('password', $strinvalidpasswordpolicy, 'warning');
546 }
547 set_user_preference('auth_forcepasswordchange', 1, $existinguser);
548 } else {
549 unset_user_preference('auth_forcepasswordchange', $existinguser);
550 }
551 unset_user_preference('create_password', $existinguser); // no need to create password any more
552 $existinguser->password = hash_internal_user_password($user->password);
2197b642 553 $upt->track('password', $user->password, 'normal', false);
3f12c146 554 } else {
8bdb31ed
PS
555 // do not print password when not changed
556 $upt->track('password', '', 'normal', false);
3f12c146 557 }
8bdb31ed 558 }
3f12c146 559
8bdb31ed
PS
560 if ($doupdate or $existinguser->password !== $oldpw) {
561 // we want only users that were really updated
3f12c146 562
df997f84 563 $DB->update_record('user', $existinguser);
3f12c146 564
df997f84
PS
565 $upt->track('status', $struserupdated);
566 $usersupdated++;
e4e38544 567 // save custom profile fields data from csv file
5d910388 568 profile_save_data($existinguser);
e6f74ba3
PS
569
570 events_trigger('user_updated', $existinguser);
e4e38544 571
8bdb31ed
PS
572 if ($bulk == UU_BULK_UPDATED or $bulk == UU_BULK_ALL) {
573 if (!in_array($user->id, $SESSION->bulk_users)) {
574 $SESSION->bulk_users[] = $user->id;
575 }
576 }
577
578 } else {
579 // no user information changed
580 $upt->track('status', $struseruptodate);
581 $usersuptodate++;
582
583 if ($bulk == UU_BULK_ALL) {
584 if (!in_array($user->id, $SESSION->bulk_users)) {
585 $SESSION->bulk_users[] = $user->id;
586 }
ed22a01b 587 }
066bfbfe 588 }
ed22a01b 589
e4e38544 590 } else {
8bdb31ed
PS
591 // save the new user to the database
592 $user->confirmed = 1;
a7db355a 593 $user->timemodified = time();
8bdb31ed
PS
594 $user->timecreated = time();
595 $user->mnethostid = $CFG->mnet_localhost_id; // we support ONLY local accounts here, sorry
066bfbfe 596
8bdb31ed 597 if (empty($user->auth)) {
3f12c146
RW
598 $user->auth = 'manual';
599 }
8bdb31ed 600 $upt->track('auth', $user->auth, 'normal', false);
3f12c146 601
8bdb31ed
PS
602 // do not insert record if new auth plugin does not exist!
603 try {
604 $auth = get_auth_plugin($user->auth);
605 } catch (Exception $e) {
606 $upt->track('auth', get_string('userautherror', 'error', s($user->auth)), 'error');
607 $upt->track('status', $strusernotaddederror, 'error');
608 $userserrors++;
609 continue;
e4e38544 610 }
8bdb31ed
PS
611 if (!isset($supportedauths[$user->auth])) {
612 $upt->track('auth', $struserauthunsupported, 'warning');
066bfbfe 613 }
a2ce7344 614
8bdb31ed
PS
615 $isinternalauth = $auth->is_internal();
616
1d8bf5f0 617 if ($DB->record_exists('user', array('email'=>$user->email))) {
0c4807ab 618 if ($noemailduplicates) {
619 $upt->track('email', $stremailduplicate, 'error');
620 $upt->track('status', $strusernotaddederror, 'error');
621 $userserrors++;
622 continue;
623 } else {
624 $upt->track('email', $stremailduplicate, 'warning');
625 }
626 }
8bdb31ed
PS
627 if (!validate_email($user->email)) {
628 $upt->track('email', get_string('invalidemail'), 'warning');
3f12c146 629 }
0c4807ab 630
8bdb31ed
PS
631 $forcechangepassword = false;
632
633 if ($isinternalauth) {
634 if (empty($user->password)) {
635 if ($createpasswords) {
636 $user->password = 'to be generated';
637 $upt->track('password', '', 'normal', false);
638 $upt->track('password', get_string('uupasswordcron', 'admin'), 'warning', false);
639 } else {
640 $upt->track('password', '', 'normal', false);
641 $upt->track('password', get_string('missingfield', 'error', 'password'), 'error');
642 $upt->track('status', $strusernotaddederror, 'error');
643 $userserrors++;
644 continue;
645 }
3f12c146 646 } else {
8bdb31ed 647 $errmsg = null;
faceca91 648 $weak = !check_password_policy($user->password, $errmsg);
8bdb31ed
PS
649 if ($resetpasswords == UU_PWRESET_ALL or ($resetpasswords == UU_PWRESET_WEAK and $weak)) {
650 if ($weak) {
651 $weakpasswords++;
652 $upt->track('password', $strinvalidpasswordpolicy, 'warning');
653 }
654 $forcechangepassword = true;
655 }
656 $user->password = hash_internal_user_password($user->password);
3f12c146 657 }
8bdb31ed
PS
658 } else {
659 $user->password = 'not cached';
660 $upt->track('password', '-', 'normal', false);
df997f84
PS
661 }
662
8bdb31ed
PS
663 // create user - insert_record ignores any extra properties
664 $user->id = $DB->insert_record('user', $user);
665 $upt->track('username', html_writer::link(new moodle_url('/user/profile.php', array('id'=>$user->id)), s($user->username)), 'normal', false);
666
e4e38544 667 // save custom profile fields data
668 profile_save_data($user);
669
8bdb31ed
PS
670 if ($forcechangepassword) {
671 set_user_preference('auth_forcepasswordchange', 1, $user);
672 }
673 if ($user->password === 'to be generated') {
674 set_user_preference('create_password', 1, $user);
675 }
676
677 $upt->track('status', $struseradded);
678 $upt->track('id', $user->id, 'normal', false);
679 $usersnew++;
680
2304f629 681 // make sure user context exists
a5feb176 682 get_context_instance(CONTEXT_USER, $user->id);
2304f629 683
e6f74ba3
PS
684 events_trigger('user_created', $user);
685
8bdb31ed 686 if ($bulk == UU_BULK_NEW or $bulk == UU_BULK_ALL) {
cd1edf9e 687 if (!in_array($user->id, $SESSION->bulk_users)) {
688 $SESSION->bulk_users[] = $user->id;
066bfbfe 689 }
066bfbfe 690 }
e4e38544 691 }
692
2686b6c3 693 // find course enrolments, groups, roles/types and enrol periods
8bdb31ed
PS
694 // this is again a special case, we always do this for any updated or created users
695 foreach ($filecolumns as $column) {
e4e38544 696 if (!preg_match('/^course\d+$/', $column)) {
697 continue;
698 }
699 $i = substr($column, 6);
6b09974b 700
df997f84
PS
701 if (empty($user->{'course'.$i})) {
702 continue;
703 }
e4e38544 704 $shortname = $user->{'course'.$i};
705 if (!array_key_exists($shortname, $ccache)) {
df997f84 706 if (!$course = $DB->get_record('course', array('shortname'=>$shortname), 'id, shortname')) {
8bdb31ed 707 $upt->track('enrolments', get_string('unknowncourse', 'error', s($shortname)), 'error');
a7db355a 708 continue;
066bfbfe 709 }
e4e38544 710 $ccache[$shortname] = $course;
711 $ccache[$shortname]->groups = null;
712 }
713 $courseid = $ccache[$shortname]->id;
714 $coursecontext = get_context_instance(CONTEXT_COURSE, $courseid);
df997f84 715 if (!isset($manualcache[$courseid])) {
4cb02426
PS
716 $manualcache[$courseid] = false;
717 if ($manual) {
718 if ($instances = enrol_get_instances($courseid, false)) {
719 foreach ($instances as $instance) {
720 if ($instance->enrol === 'manual') {
721 $manualcache[$courseid] = $instance;
722 break;
723 }
724 }
725 }
e4e38544 726 }
df997f84 727 }
e4e38544 728
df997f84
PS
729 if ($manual and $manualcache[$courseid]) {
730
731 // find role
732 $rid = false;
733 if (!empty($user->{'role'.$i})) {
734 $addrole = $user->{'role'.$i};
735 if (array_key_exists($addrole, $rolecache)) {
736 $rid = $rolecache[$addrole]->id;
e4e38544 737 } else {
8bdb31ed 738 $upt->track('enrolments', get_string('unknownrole', 'error', s($addrole)), 'error');
df997f84 739 continue;
a7db355a 740 }
e4e38544 741
df997f84
PS
742 } else if (!empty($user->{'type'.$i})) {
743 // if no role, then find "old" enrolment type
744 $addtype = $user->{'type'.$i};
745 if ($addtype < 1 or $addtype > 3) {
746 $upt->track('enrolments', $strerror.': typeN = 1|2|3', 'error');
747 continue;
748 } else if (empty($formdata->{'uulegacy'.$addtype})) {
749 continue;
750 } else {
751 $rid = $formdata->{'uulegacy'.$addtype};
752 }
e4e38544 753 } else {
df997f84
PS
754 // no role specified, use the default from manual enrol plugin
755 $rid = $manualcache[$courseid]->roleid;
a7db355a 756 }
2686b6c3 757
df997f84
PS
758 if ($rid) {
759 // find duration
df997f84
PS
760 $timeend = 0;
761 if (!empty($user->{'enrolperiod'.$i})) {
8bdb31ed 762 $duration = (int)$user->{'enrolperiod'.$i} * 60*60*24; // convert days to seconds
df997f84 763 if ($duration > 0) { // sanity check
8bdb31ed 764 $timeend = $today + $duration;
df997f84
PS
765 }
766 }
2686b6c3 767
2a6dcb72 768 $manual->enrol_user($manualcache[$courseid], $user->id, $rid, $today, $timeend, true);
df997f84 769
a226a972 770 $a = new stdClass();
df997f84
PS
771 $a->course = $shortname;
772 $a->role = $rolecache[$rid]->name;
773 $upt->track('enrolments', get_string('enrolledincourserole', 'enrol_manual', $a));
066bfbfe 774 }
e4e38544 775 }
6b09974b 776
e4e38544 777 // find group to add to
778 if (!empty($user->{'group'.$i})) {
779 // make sure user is enrolled into course before adding into groups
4f0c2d00 780 if (!is_enrolled($coursecontext, $user->id)) {
d85f2634 781 $upt->track('enrolments', get_string('addedtogroupnotenrolled', '', $user->{'group'.$i}), 'error');
e4e38544 782 continue;
783 }
784 //build group cache
785 if (is_null($ccache[$shortname]->groups)) {
786 $ccache[$shortname]->groups = array();
35987665 787 if ($groups = groups_get_all_groups($courseid)) {
e4e38544 788 foreach ($groups as $gid=>$group) {
a226a972 789 $ccache[$shortname]->groups[$gid] = new stdClass();
e4e38544 790 $ccache[$shortname]->groups[$gid]->id = $gid;
791 $ccache[$shortname]->groups[$gid]->name = $group->name;
792 if (!is_numeric($group->name)) { // only non-numeric names are supported!!!
8bdb31ed
PS
793 $ccache[$shortname]->groups[$group->name] = new stdClass();
794 $ccache[$shortname]->groups[$group->name]->id = $gid;
795 $ccache[$shortname]->groups[$group->name]->name = $group->name;
a7db355a 796 }
a5702569 797 }
0063abee 798 }
6b09974b 799 }
e4e38544 800 // group exists?
801 $addgroup = $user->{'group'.$i};
802 if (!array_key_exists($addgroup, $ccache[$shortname]->groups)) {
b225cf36 803 // if group doesn't exist, create it
a226a972 804 $newgroupdata = new stdClass();
b225cf36 805 $newgroupdata->name = $addgroup;
806 $newgroupdata->courseid = $ccache[$shortname]->id;
807 if ($ccache[$shortname]->groups[$addgroup]->id = groups_create_group($newgroupdata)){
808 $ccache[$shortname]->groups[$addgroup]->name = $newgroupdata->name;
809 } else {
8bdb31ed 810 $upt->track('enrolments', get_string('unknowngroup', 'error', s($addgroup)), 'error');
b225cf36 811 continue;
812 }
e4e38544 813 }
814 $gid = $ccache[$shortname]->groups[$addgroup]->id;
815 $gname = $ccache[$shortname]->groups[$addgroup]->name;
816
9c000a99 817 try {
818 if (groups_add_member($gid, $user->id)) {
8bdb31ed 819 $upt->track('enrolments', get_string('addedtogroup', '', s($gname)));
df997f84 820 } else {
8bdb31ed 821 $upt->track('enrolments', get_string('addedtogroupnot', '', s($gname)), 'error');
9c000a99 822 }
823 } catch (moodle_exception $e) {
8bdb31ed 824 $upt->track('enrolments', get_string('addedtogroupnot', '', s($gname)), 'error');
e4e38544 825 continue;
826 }
a5702569 827 }
066bfbfe 828 }
829 }
e4e38544 830 $upt->close(); // close table
831
832 $cir->close();
833 $cir->cleanup(true);
834
20486a5a 835 echo $OUTPUT->box_start('boxwidthnarrow boxaligncenter generalbox', 'uploadresults');
e4e38544 836 echo '<p>';
8bdb31ed 837 if ($optype != UU_USER_UPDATE) {
e4e38544 838 echo get_string('userscreated', 'admin').': '.$usersnew.'<br />';
839 }
8bdb31ed 840 if ($optype == UU_USER_UPDATE or $optype == UU_USER_ADD_UPDATE) {
e4e38544 841 echo get_string('usersupdated', 'admin').': '.$usersupdated.'<br />';
842 }
843 if ($allowdeletes) {
844 echo get_string('usersdeleted', 'admin').': '.$deletes.'<br />';
845 echo get_string('deleteerrors', 'admin').': '.$deleteerrors.'<br />';
846 }
847 if ($allowrenames) {
848 echo get_string('usersrenamed', 'admin').': '.$renames.'<br />';
849 echo get_string('renameerrors', 'admin').': '.$renameerrors.'<br />';
850 }
851 if ($usersskipped) {
852 echo get_string('usersskipped', 'admin').': '.$usersskipped.'<br />';
853 }
d6bb2d2f 854 echo get_string('usersweakpassword', 'admin').': '.$weakpasswords.'<br />';
e4e38544 855 echo get_string('errors', 'admin').': '.$userserrors.'</p>';
20486a5a 856 echo $OUTPUT->box_end();
e4e38544 857
858 if ($bulk) {
8fbce1c8 859 echo $OUTPUT->continue_button($bulknurl);
e4e38544 860 } else {
8fbce1c8 861 echo $OUTPUT->continue_button($returnurl);
e4e38544 862 }
73d6f52f 863 echo $OUTPUT->footer();
df7ecfe4 864 die;
6b09974b 865}
0a6150ca 866
df7ecfe4 867// Print the header
61ef8f9f 868echo $OUTPUT->header();
df7ecfe4 869
6c7a5df7 870echo $OUTPUT->heading(get_string('uploaduserspreview', 'admin'));
df7ecfe4 871
8bdb31ed
PS
872// NOTE: this is JUST csv processing preview, we must not prevent import from here if there is something in the file!!
873// this was intended for validation of csv formatting and encoding, not filtering the data!!!!
874// we definitely must not process the whole file!
875
876// preview table data
877$data = array();
e4e38544 878$cir->init();
8bdb31ed
PS
879$linenum = 1; //column header is first line
880while ($linenum <= $previewrows and $fields = $cir->next()) {
881 $linenum++;
3fe2cfb5 882 $rowcols = array();
8bdb31ed
PS
883 $rowcols['line'] = $linenum;
884 foreach($fields as $key => $field) {
885 $rowcols[$filecolumns[$key]] = s($field);
3fe2cfb5 886 }
8bdb31ed 887 $rowcols['status'] = array();
3fe2cfb5 888
8bdb31ed
PS
889 if (isset($rowcols['username'])) {
890 $stdusername = clean_param($rowcols['username'], PARAM_USERNAME);
891 if ($rowcols['username'] !== $stdusername) {
892 $rowcols['status'][] = get_string('invalidusernameupload');
3fe2cfb5 893 }
8bdb31ed
PS
894 if ($userid = $DB->get_field('user', 'id', array('username'=>$stdusername, 'mnethostid'=>$CFG->mnet_localhost_id))) {
895 $rowcols['username'] = html_writer::link(new moodle_url('/user/profile.php', array('id'=>$userid)), $rowcols['username']);
e4e38544 896 }
8bdb31ed
PS
897 } else {
898 $rowcols['status'][] = get_string('missingusername');
df7ecfe4 899 }
07ed083e 900
8bdb31ed
PS
901 if (!validate_email($rowcols['email'])) {
902 $rowcols['status'][] = get_string('invalidemail');
3fe2cfb5 903 }
8bdb31ed
PS
904 if ($DB->record_exists('user', array('email'=>$rowcols['email']))) {
905 $rowcols['status'][] = $stremailduplicate;
07ed083e 906 }
8bdb31ed
PS
907 $rowcols['status'] = implode('<br />', $rowcols['status']);
908 $data[] = $rowcols;
07ed083e 909}
8bdb31ed
PS
910if ($fields = $cir->next()) {
911 $data[] = array_fill(0, count($fields) + 2, '...');
07ed083e 912}
8bdb31ed 913$cir->close();
3fe2cfb5
RW
914
915$table = new html_table();
916$table->id = "uupreview";
16be8974 917$table->attributes['class'] = 'generaltable';
3fe2cfb5
RW
918$table->tablealign = 'center';
919$table->summary = get_string('uploaduserspreview', 'admin');
920$table->head = array();
8bdb31ed 921$table->data = $data;
3fe2cfb5 922
8bdb31ed
PS
923$table->head[] = get_string('uucsvline', 'admin');
924foreach ($filecolumns as $column) {
925 $table->head[] = $column;
07ed083e 926}
8bdb31ed 927$table->head[] = get_string('status');
07ed083e 928
3f12c146 929echo html_writer::tag('div', html_writer::table($table), array('class'=>'flexible-wrap'));
3fe2cfb5 930
8bdb31ed 931/// Print the form
07ed083e 932
8bdb31ed 933$mform2->display();
73d6f52f 934echo $OUTPUT->footer();
df7ecfe4 935die;
936