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