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