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