weekly release 3.1dev
[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') {
571 if ($DB->record_exists('user', array('email'=>$user->email))) {
572 if ($noemailduplicates) {
573 $upt->track('email', $stremailduplicate, 'error');
574 $upt->track('status', $strusernotupdated, 'error');
575 $userserrors++;
576 continue 2;
577 } else {
578 $upt->track('email', $stremailduplicate, 'warning');
3f12c146
RW
579 }
580 }
8bdb31ed
PS
581 if (!validate_email($user->email)) {
582 $upt->track('email', get_string('invalidemail'), 'warning');
e4e38544 583 }
8bdb31ed 584 }
3f12c146 585
4d3cd148
PS
586 if ($column === 'lang') {
587 if (empty($user->lang)) {
588 // Do not change to not-set value.
589 continue;
590 } else if (clean_param($user->lang, PARAM_LANG) === '') {
591 $upt->track('status', get_string('cannotfindlang', 'error', $user->lang), 'warning');
592 continue;
593 }
594 }
595
8bdb31ed
PS
596 if (in_array($column, $upt->columns)) {
597 $upt->track($column, s($existinguser->$column).'-->'.s($user->$column), 'info', false);
a7db355a 598 }
8bdb31ed
PS
599 $existinguser->$column = $user->$column;
600 $doupdate = true;
6b09974b 601 }
a7db355a 602 }
8bdb31ed 603 }
ed22a01b 604
8bdb31ed 605 try {
3f12c146 606 $auth = get_auth_plugin($existinguser->auth);
8bdb31ed
PS
607 } catch (Exception $e) {
608 $upt->track('auth', get_string('userautherror', 'error', s($existinguser->auth)), 'error');
609 $upt->track('status', $strusernotupdated, 'error');
610 $userserrors++;
611 continue;
612 }
613 $isinternalauth = $auth->is_internal();
3f12c146 614
08157bfe
PS
615 // deal with suspending and activating of accounts
616 if ($allowsuspends and isset($user->suspended) and $user->suspended !== '') {
617 $user->suspended = $user->suspended ? 1 : 0;
618 if ($existinguser->suspended != $user->suspended) {
619 $upt->track('suspended', '', 'normal', false);
620 $upt->track('suspended', $stryesnooptions[$existinguser->suspended].'-->'.$stryesnooptions[$user->suspended], 'info', false);
621 $existinguser->suspended = $user->suspended;
622 $doupdate = true;
623 if ($existinguser->suspended) {
624 $dologout = true;
625 }
626 }
627 }
628
8bdb31ed
PS
629 // changing of passwords is a special case
630 // do not force password changes for external auth plugins!
631 $oldpw = $existinguser->password;
9dcae46d
PS
632
633 if ($remoteuser) {
634 // Do not mess with passwords of remote users.
635
636 } else if (!$isinternalauth) {
ec2d8ceb 637 $existinguser->password = AUTH_PASSWORD_NOT_CACHED;
8bdb31ed
PS
638 $upt->track('password', '-', 'normal', false);
639 // clean up prefs
640 unset_user_preference('create_password', $existinguser);
641 unset_user_preference('auth_forcepasswordchange', $existinguser);
642
643 } else if (!empty($user->password)) {
644 if ($updatepasswords) {
ec2d8ceb
SC
645 // Check for passwords that we want to force users to reset next
646 // time they log in.
8bdb31ed 647 $errmsg = null;
faceca91 648 $weak = !check_password_policy($user->password, $errmsg);
8bdb31ed
PS
649 if ($resetpasswords == UU_PWRESET_ALL or ($resetpasswords == UU_PWRESET_WEAK and $weak)) {
650 if ($weak) {
651 $weakpasswords++;
652 $upt->track('password', $strinvalidpasswordpolicy, 'warning');
653 }
654 set_user_preference('auth_forcepasswordchange', 1, $existinguser);
655 } else {
656 unset_user_preference('auth_forcepasswordchange', $existinguser);
657 }
658 unset_user_preference('create_password', $existinguser); // no need to create password any more
ec2d8ceb
SC
659
660 // Use a low cost factor when generating bcrypt hash otherwise
661 // hashing would be slow when uploading lots of users. Hashes
662 // will be automatically updated to a higher cost factor the first
663 // time the user logs in.
664 $existinguser->password = hash_internal_user_password($user->password, true);
2197b642 665 $upt->track('password', $user->password, 'normal', false);
3f12c146 666 } else {
8bdb31ed
PS
667 // do not print password when not changed
668 $upt->track('password', '', 'normal', false);
3f12c146 669 }
8bdb31ed 670 }
3f12c146 671
8bdb31ed 672 if ($doupdate or $existinguser->password !== $oldpw) {
bb78e249 673 // We want only users that were really updated.
9363073b 674 user_update_user($existinguser, false, false);
3f12c146 675
df997f84
PS
676 $upt->track('status', $struserupdated);
677 $usersupdated++;
9dcae46d
PS
678
679 if (!$remoteuser) {
680 // pre-process custom profile menu fields data from csv file
681 $existinguser = uu_pre_process_custom_profile_data($existinguser);
682 // save custom profile fields data from csv file
683 profile_save_data($existinguser);
684 }
e6f74ba3 685
8bdb31ed
PS
686 if ($bulk == UU_BULK_UPDATED or $bulk == UU_BULK_ALL) {
687 if (!in_array($user->id, $SESSION->bulk_users)) {
688 $SESSION->bulk_users[] = $user->id;
689 }
690 }
691
9363073b
RT
692 // Trigger event.
693 \core\event\user_updated::create_from_userid($existinguser->id)->trigger();
694
8bdb31ed
PS
695 } else {
696 // no user information changed
697 $upt->track('status', $struseruptodate);
698 $usersuptodate++;
699
700 if ($bulk == UU_BULK_ALL) {
701 if (!in_array($user->id, $SESSION->bulk_users)) {
702 $SESSION->bulk_users[] = $user->id;
703 }
ed22a01b 704 }
066bfbfe 705 }
ed22a01b 706
08157bfe 707 if ($dologout) {
d79d5ac2 708 \core\session\manager::kill_user_sessions($existinguser->id);
08157bfe
PS
709 }
710
e4e38544 711 } else {
8bdb31ed
PS
712 // save the new user to the database
713 $user->confirmed = 1;
a7db355a 714 $user->timemodified = time();
8bdb31ed
PS
715 $user->timecreated = time();
716 $user->mnethostid = $CFG->mnet_localhost_id; // we support ONLY local accounts here, sorry
066bfbfe 717
08157bfe
PS
718 if (!isset($user->suspended) or $user->suspended === '') {
719 $user->suspended = 0;
720 } else {
721 $user->suspended = $user->suspended ? 1 : 0;
722 }
723 $upt->track('suspended', $stryesnooptions[$user->suspended], 'normal', false);
724
8bdb31ed 725 if (empty($user->auth)) {
3f12c146
RW
726 $user->auth = 'manual';
727 }
8bdb31ed 728 $upt->track('auth', $user->auth, 'normal', false);
3f12c146 729
8bdb31ed
PS
730 // do not insert record if new auth plugin does not exist!
731 try {
732 $auth = get_auth_plugin($user->auth);
733 } catch (Exception $e) {
734 $upt->track('auth', get_string('userautherror', 'error', s($user->auth)), 'error');
735 $upt->track('status', $strusernotaddederror, 'error');
736 $userserrors++;
737 continue;
e4e38544 738 }
8bdb31ed
PS
739 if (!isset($supportedauths[$user->auth])) {
740 $upt->track('auth', $struserauthunsupported, 'warning');
066bfbfe 741 }
a2ce7344 742
8bdb31ed
PS
743 $isinternalauth = $auth->is_internal();
744
43070e61
PS
745 if (empty($user->email)) {
746 $upt->track('email', get_string('invalidemail'), 'error');
747 $upt->track('status', $strusernotaddederror, 'error');
748 $userserrors++;
749 continue;
750
751 } else if ($DB->record_exists('user', array('email'=>$user->email))) {
0c4807ab 752 if ($noemailduplicates) {
753 $upt->track('email', $stremailduplicate, 'error');
754 $upt->track('status', $strusernotaddederror, 'error');
755 $userserrors++;
756 continue;
757 } else {
758 $upt->track('email', $stremailduplicate, 'warning');
759 }
760 }
8bdb31ed
PS
761 if (!validate_email($user->email)) {
762 $upt->track('email', get_string('invalidemail'), 'warning');
3f12c146 763 }
0c4807ab 764
4d3cd148
PS
765 if (empty($user->lang)) {
766 $user->lang = '';
767 } else if (clean_param($user->lang, PARAM_LANG) === '') {
768 $upt->track('status', get_string('cannotfindlang', 'error', $user->lang), 'warning');
769 $user->lang = '';
770 }
771
8bdb31ed
PS
772 $forcechangepassword = false;
773
774 if ($isinternalauth) {
775 if (empty($user->password)) {
776 if ($createpasswords) {
777 $user->password = 'to be generated';
778 $upt->track('password', '', 'normal', false);
ce15d56d 779 $upt->track('password', get_string('uupasswordcron', 'tool_uploaduser'), 'warning', false);
8bdb31ed
PS
780 } else {
781 $upt->track('password', '', 'normal', false);
782 $upt->track('password', get_string('missingfield', 'error', 'password'), 'error');
783 $upt->track('status', $strusernotaddederror, 'error');
784 $userserrors++;
785 continue;
786 }
3f12c146 787 } else {
8bdb31ed 788 $errmsg = null;
faceca91 789 $weak = !check_password_policy($user->password, $errmsg);
8bdb31ed
PS
790 if ($resetpasswords == UU_PWRESET_ALL or ($resetpasswords == UU_PWRESET_WEAK and $weak)) {
791 if ($weak) {
792 $weakpasswords++;
793 $upt->track('password', $strinvalidpasswordpolicy, 'warning');
794 }
795 $forcechangepassword = true;
796 }
ec2d8ceb
SC
797 // Use a low cost factor when generating bcrypt hash otherwise
798 // hashing would be slow when uploading lots of users. Hashes
799 // will be automatically updated to a higher cost factor the first
800 // time the user logs in.
801 $user->password = hash_internal_user_password($user->password, true);
3f12c146 802 }
8bdb31ed 803 } else {
ec2d8ceb 804 $user->password = AUTH_PASSWORD_NOT_CACHED;
8bdb31ed 805 $upt->track('password', '-', 'normal', false);
df997f84
PS
806 }
807
9363073b 808 $user->id = user_create_user($user, false, false);
8bdb31ed
PS
809 $upt->track('username', html_writer::link(new moodle_url('/user/profile.php', array('id'=>$user->id)), s($user->username)), 'normal', false);
810
d6aea4cc 811 // pre-process custom profile menu fields data from csv file
bd8dc9ba 812 $user = uu_pre_process_custom_profile_data($user);
e4e38544 813 // save custom profile fields data
814 profile_save_data($user);
815
8bdb31ed
PS
816 if ($forcechangepassword) {
817 set_user_preference('auth_forcepasswordchange', 1, $user);
818 }
819 if ($user->password === 'to be generated') {
820 set_user_preference('create_password', 1, $user);
821 }
822
9363073b
RT
823 // Trigger event.
824 \core\event\user_created::create_from_userid($user->id)->trigger();
825
8bdb31ed
PS
826 $upt->track('status', $struseradded);
827 $upt->track('id', $user->id, 'normal', false);
828 $usersnew++;
829
2304f629 830 // make sure user context exists
bf006d2c 831 context_user::instance($user->id);
2304f629 832
8bdb31ed 833 if ($bulk == UU_BULK_NEW or $bulk == UU_BULK_ALL) {
cd1edf9e 834 if (!in_array($user->id, $SESSION->bulk_users)) {
835 $SESSION->bulk_users[] = $user->id;
066bfbfe 836 }
066bfbfe 837 }
e4e38544 838 }
839
3da0c3cb
MG
840 // Update user interests.
841 if (isset($user->interests) && strval($user->interests) !== '') {
842 useredit_update_interests($user, preg_split('/\s*,\s*/', $user->interests, -1, PREG_SPLIT_NO_EMPTY));
843 }
92b59a56
PS
844
845 // add to cohort first, it might trigger enrolments indirectly - do NOT create cohorts here!
846 foreach ($filecolumns as $column) {
847 if (!preg_match('/^cohort\d+$/', $column)) {
848 continue;
849 }
850
851 if (!empty($user->$column)) {
852 $addcohort = $user->$column;
853 if (!isset($cohorts[$addcohort])) {
854 if (is_number($addcohort)) {
855 // only non-numeric idnumbers!
856 $cohort = $DB->get_record('cohort', array('id'=>$addcohort));
857 } else {
858 $cohort = $DB->get_record('cohort', array('idnumber'=>$addcohort));
e7bc9157
MG
859 if (empty($cohort) && has_capability('moodle/cohort:manage', context_system::instance())) {
860 // Cohort was not found. Create a new one.
861 $cohortid = cohort_add_cohort((object)array(
862 'idnumber' => $addcohort,
863 'name' => $addcohort,
864 'contextid' => context_system::instance()->id
865 ));
866 $cohort = $DB->get_record('cohort', array('id'=>$cohortid));
867 }
92b59a56
PS
868 }
869
870 if (empty($cohort)) {
871 $cohorts[$addcohort] = get_string('unknowncohort', 'core_cohort', s($addcohort));
872 } else if (!empty($cohort->component)) {
873 // cohorts synchronised with external sources must not be modified!
874 $cohorts[$addcohort] = get_string('external', 'core_cohort');
875 } else {
876 $cohorts[$addcohort] = $cohort;
877 }
878 }
879
880 if (is_object($cohorts[$addcohort])) {
881 $cohort = $cohorts[$addcohort];
882 if (!$DB->record_exists('cohort_members', array('cohortid'=>$cohort->id, 'userid'=>$user->id))) {
883 cohort_add_member($cohort->id, $user->id);
884 // we might add special column later, for now let's abuse enrolments
885 $upt->track('enrolments', get_string('useradded', 'core_cohort', s($cohort->name)));
886 }
887 } else {
888 // error message
889 $upt->track('enrolments', $cohorts[$addcohort], 'error');
890 }
891 }
892 }
893
894
2686b6c3 895 // find course enrolments, groups, roles/types and enrol periods
8bdb31ed
PS
896 // this is again a special case, we always do this for any updated or created users
897 foreach ($filecolumns as $column) {
2a34360e
SP
898 if (preg_match('/^sysrole\d+$/', $column)) {
899
900 if (!empty($user->$column)) {
901 $sysrolename = $user->$column;
902 if ($sysrolename[0] == '-') {
903 $removing = true;
904 $sysrolename = substr($sysrolename, 1);
905 } else {
906 $removing = false;
907 }
908
909 if (array_key_exists($sysrolename, $sysrolecache)) {
910 $sysroleid = $sysrolecache[$sysrolename]->id;
911 } else {
912 $upt->track('enrolments', get_string('unknownrole', 'error', s($sysrolename)), 'error');
913 continue;
914 }
915
916 if ($removing) {
917 if (user_has_role_assignment($user->id, $sysroleid, SYSCONTEXTID)) {
918 role_unassign($sysroleid, $user->id, SYSCONTEXTID);
919 $upt->track('enrolments', get_string('unassignedsysrole',
920 'tool_uploaduser', $sysrolecache[$sysroleid]->name));
921 }
922 } else {
923 if (!user_has_role_assignment($user->id, $sysroleid, SYSCONTEXTID)) {
924 role_assign($sysroleid, $user->id, SYSCONTEXTID);
925 $upt->track('enrolments', get_string('assignedsysrole',
926 'tool_uploaduser', $sysrolecache[$sysroleid]->name));
927 }
928 }
929 }
930
931 continue;
932 }
e4e38544 933 if (!preg_match('/^course\d+$/', $column)) {
934 continue;
935 }
936 $i = substr($column, 6);
6b09974b 937
df997f84
PS
938 if (empty($user->{'course'.$i})) {
939 continue;
940 }
e4e38544 941 $shortname = $user->{'course'.$i};
942 if (!array_key_exists($shortname, $ccache)) {
df997f84 943 if (!$course = $DB->get_record('course', array('shortname'=>$shortname), 'id, shortname')) {
8bdb31ed 944 $upt->track('enrolments', get_string('unknowncourse', 'error', s($shortname)), 'error');
a7db355a 945 continue;
066bfbfe 946 }
e4e38544 947 $ccache[$shortname] = $course;
948 $ccache[$shortname]->groups = null;
949 }
950 $courseid = $ccache[$shortname]->id;
bf006d2c 951 $coursecontext = context_course::instance($courseid);
df997f84 952 if (!isset($manualcache[$courseid])) {
4cb02426
PS
953 $manualcache[$courseid] = false;
954 if ($manual) {
955 if ($instances = enrol_get_instances($courseid, false)) {
956 foreach ($instances as $instance) {
957 if ($instance->enrol === 'manual') {
958 $manualcache[$courseid] = $instance;
959 break;
960 }
961 }
962 }
e4e38544 963 }
df997f84 964 }
e4e38544 965
968083cd
PS
966 if ($courseid == SITEID) {
967 // Technically frontpage does not have enrolments, but only role assignments,
968 // let's not invent new lang strings here for this rarely used feature.
969
970 if (!empty($user->{'role'.$i})) {
2a34360e
SP
971 $rolename = $user->{'role'.$i};
972 if (array_key_exists($rolename, $rolecache)) {
973 $roleid = $rolecache[$rolename]->id;
968083cd 974 } else {
2a34360e 975 $upt->track('enrolments', get_string('unknownrole', 'error', s($rolename)), 'error');
968083cd
PS
976 continue;
977 }
978
2a34360e 979 role_assign($roleid, $user->id, context_course::instance($courseid));
968083cd
PS
980
981 $a = new stdClass();
982 $a->course = $shortname;
2a34360e 983 $a->role = $rolecache[$roleid]->name;
968083cd
PS
984 $upt->track('enrolments', get_string('enrolledincourserole', 'enrol_manual', $a));
985 }
986
987 } else if ($manual and $manualcache[$courseid]) {
df997f84
PS
988
989 // find role
2a34360e 990 $roleid = false;
df997f84 991 if (!empty($user->{'role'.$i})) {
2a34360e
SP
992 $rolename = $user->{'role'.$i};
993 if (array_key_exists($rolename, $rolecache)) {
994 $roleid = $rolecache[$rolename]->id;
e4e38544 995 } else {
2a34360e 996 $upt->track('enrolments', get_string('unknownrole', 'error', s($rolename)), 'error');
df997f84 997 continue;
a7db355a 998 }
e4e38544 999
df997f84
PS
1000 } else if (!empty($user->{'type'.$i})) {
1001 // if no role, then find "old" enrolment type
1002 $addtype = $user->{'type'.$i};
1003 if ($addtype < 1 or $addtype > 3) {
1004 $upt->track('enrolments', $strerror.': typeN = 1|2|3', 'error');
1005 continue;
1006 } else if (empty($formdata->{'uulegacy'.$addtype})) {
1007 continue;
1008 } else {
2a34360e 1009 $roleid = $formdata->{'uulegacy'.$addtype};
df997f84 1010 }
e4e38544 1011 } else {
df997f84 1012 // no role specified, use the default from manual enrol plugin
2a34360e 1013 $roleid = $manualcache[$courseid]->roleid;
a7db355a 1014 }
2686b6c3 1015
2a34360e 1016 if ($roleid) {
6afe875e
JH
1017 // Find duration and/or enrol status.
1018 $timeend = 0;
1019 $status = null;
1020
1021 if (isset($user->{'enrolstatus'.$i})) {
7ca44a49 1022 $enrolstatus = $user->{'enrolstatus'.$i};
6afe875e
JH
1023 if ($enrolstatus == '') {
1024 $status = null;
1025 } else if ($enrolstatus === (string)ENROL_USER_ACTIVE) {
1026 $status = ENROL_USER_ACTIVE;
1027 } else if ($enrolstatus === (string)ENROL_USER_SUSPENDED) {
1028 $status = ENROL_USER_SUSPENDED;
1029 } else {
1030 debugging('Unknown enrolment status.');
1031 }
1032 }
1033
df997f84 1034 if (!empty($user->{'enrolperiod'.$i})) {
8bdb31ed 1035 $duration = (int)$user->{'enrolperiod'.$i} * 60*60*24; // convert days to seconds
df997f84 1036 if ($duration > 0) { // sanity check
8bdb31ed 1037 $timeend = $today + $duration;
df997f84 1038 }
b1d76077
AO
1039 } else if ($manualcache[$courseid]->enrolperiod > 0) {
1040 $timeend = $today + $manualcache[$courseid]->enrolperiod;
df997f84 1041 }
2686b6c3 1042
2a34360e 1043 $manual->enrol_user($manualcache[$courseid], $user->id, $roleid, $today, $timeend, $status);
df997f84 1044
a226a972 1045 $a = new stdClass();
df997f84 1046 $a->course = $shortname;
2a34360e 1047 $a->role = $rolecache[$roleid]->name;
df997f84 1048 $upt->track('enrolments', get_string('enrolledincourserole', 'enrol_manual', $a));
066bfbfe 1049 }
e4e38544 1050 }
6b09974b 1051
e4e38544 1052 // find group to add to
1053 if (!empty($user->{'group'.$i})) {
1054 // make sure user is enrolled into course before adding into groups
4f0c2d00 1055 if (!is_enrolled($coursecontext, $user->id)) {
d85f2634 1056 $upt->track('enrolments', get_string('addedtogroupnotenrolled', '', $user->{'group'.$i}), 'error');
e4e38544 1057 continue;
1058 }
1059 //build group cache
1060 if (is_null($ccache[$shortname]->groups)) {
1061 $ccache[$shortname]->groups = array();
35987665 1062 if ($groups = groups_get_all_groups($courseid)) {
e4e38544 1063 foreach ($groups as $gid=>$group) {
a226a972 1064 $ccache[$shortname]->groups[$gid] = new stdClass();
e4e38544 1065 $ccache[$shortname]->groups[$gid]->id = $gid;
1066 $ccache[$shortname]->groups[$gid]->name = $group->name;
1067 if (!is_numeric($group->name)) { // only non-numeric names are supported!!!
8bdb31ed
PS
1068 $ccache[$shortname]->groups[$group->name] = new stdClass();
1069 $ccache[$shortname]->groups[$group->name]->id = $gid;
1070 $ccache[$shortname]->groups[$group->name]->name = $group->name;
a7db355a 1071 }
a5702569 1072 }
0063abee 1073 }
6b09974b 1074 }
e4e38544 1075 // group exists?
1076 $addgroup = $user->{'group'.$i};
1077 if (!array_key_exists($addgroup, $ccache[$shortname]->groups)) {
b225cf36 1078 // if group doesn't exist, create it
a226a972 1079 $newgroupdata = new stdClass();
b225cf36 1080 $newgroupdata->name = $addgroup;
1081 $newgroupdata->courseid = $ccache[$shortname]->id;
e95bf5b5
PS
1082 $newgroupdata->description = '';
1083 $gid = groups_create_group($newgroupdata);
1084 if ($gid){
1085 $ccache[$shortname]->groups[$addgroup] = new stdClass();
1086 $ccache[$shortname]->groups[$addgroup]->id = $gid;
b225cf36 1087 $ccache[$shortname]->groups[$addgroup]->name = $newgroupdata->name;
1088 } else {
8bdb31ed 1089 $upt->track('enrolments', get_string('unknowngroup', 'error', s($addgroup)), 'error');
b225cf36 1090 continue;
1091 }
e4e38544 1092 }
1093 $gid = $ccache[$shortname]->groups[$addgroup]->id;
1094 $gname = $ccache[$shortname]->groups[$addgroup]->name;
1095
9c000a99 1096 try {
1097 if (groups_add_member($gid, $user->id)) {
8bdb31ed 1098 $upt->track('enrolments', get_string('addedtogroup', '', s($gname)));
df997f84 1099 } else {
8bdb31ed 1100 $upt->track('enrolments', get_string('addedtogroupnot', '', s($gname)), 'error');
9c000a99 1101 }
1102 } catch (moodle_exception $e) {
8bdb31ed 1103 $upt->track('enrolments', get_string('addedtogroupnot', '', s($gname)), 'error');
e4e38544 1104 continue;
1105 }
a5702569 1106 }
066bfbfe 1107 }
1108 }
e4e38544 1109 $upt->close(); // close table
1110
1111 $cir->close();
1112 $cir->cleanup(true);
1113
20486a5a 1114 echo $OUTPUT->box_start('boxwidthnarrow boxaligncenter generalbox', 'uploadresults');
e4e38544 1115 echo '<p>';
8bdb31ed 1116 if ($optype != UU_USER_UPDATE) {
ce15d56d 1117 echo get_string('userscreated', 'tool_uploaduser').': '.$usersnew.'<br />';
e4e38544 1118 }
8bdb31ed 1119 if ($optype == UU_USER_UPDATE or $optype == UU_USER_ADD_UPDATE) {
ce15d56d 1120 echo get_string('usersupdated', 'tool_uploaduser').': '.$usersupdated.'<br />';
e4e38544 1121 }
1122 if ($allowdeletes) {
ce15d56d
PS
1123 echo get_string('usersdeleted', 'tool_uploaduser').': '.$deletes.'<br />';
1124 echo get_string('deleteerrors', 'tool_uploaduser').': '.$deleteerrors.'<br />';
e4e38544 1125 }
1126 if ($allowrenames) {
ce15d56d
PS
1127 echo get_string('usersrenamed', 'tool_uploaduser').': '.$renames.'<br />';
1128 echo get_string('renameerrors', 'tool_uploaduser').': '.$renameerrors.'<br />';
e4e38544 1129 }
1130 if ($usersskipped) {
ce15d56d 1131 echo get_string('usersskipped', 'tool_uploaduser').': '.$usersskipped.'<br />';
e4e38544 1132 }
ce15d56d
PS
1133 echo get_string('usersweakpassword', 'tool_uploaduser').': '.$weakpasswords.'<br />';
1134 echo get_string('errors', 'tool_uploaduser').': '.$userserrors.'</p>';
20486a5a 1135 echo $OUTPUT->box_end();
e4e38544 1136
1137 if ($bulk) {
8fbce1c8 1138 echo $OUTPUT->continue_button($bulknurl);
e4e38544 1139 } else {
8fbce1c8 1140 echo $OUTPUT->continue_button($returnurl);
e4e38544 1141 }
73d6f52f 1142 echo $OUTPUT->footer();
df7ecfe4 1143 die;
6b09974b 1144}
0a6150ca 1145
df7ecfe4 1146// Print the header
61ef8f9f 1147echo $OUTPUT->header();
df7ecfe4 1148
ce15d56d 1149echo $OUTPUT->heading(get_string('uploaduserspreview', 'tool_uploaduser'));
df7ecfe4 1150
8bdb31ed
PS
1151// NOTE: this is JUST csv processing preview, we must not prevent import from here if there is something in the file!!
1152// this was intended for validation of csv formatting and encoding, not filtering the data!!!!
1153// we definitely must not process the whole file!
1154
1155// preview table data
1156$data = array();
e4e38544 1157$cir->init();
8bdb31ed 1158$linenum = 1; //column header is first line
1b4d2d56 1159$noerror = true; // Keep status of any error.
8bdb31ed
PS
1160while ($linenum <= $previewrows and $fields = $cir->next()) {
1161 $linenum++;
3fe2cfb5 1162 $rowcols = array();
8bdb31ed
PS
1163 $rowcols['line'] = $linenum;
1164 foreach($fields as $key => $field) {
7ca44a49 1165 $rowcols[$filecolumns[$key]] = s(trim($field));
3fe2cfb5 1166 }
8bdb31ed 1167 $rowcols['status'] = array();
3fe2cfb5 1168
8bdb31ed
PS
1169 if (isset($rowcols['username'])) {
1170 $stdusername = clean_param($rowcols['username'], PARAM_USERNAME);
1171 if ($rowcols['username'] !== $stdusername) {
1172 $rowcols['status'][] = get_string('invalidusernameupload');
3fe2cfb5 1173 }
8bdb31ed
PS
1174 if ($userid = $DB->get_field('user', 'id', array('username'=>$stdusername, 'mnethostid'=>$CFG->mnet_localhost_id))) {
1175 $rowcols['username'] = html_writer::link(new moodle_url('/user/profile.php', array('id'=>$userid)), $rowcols['username']);
e4e38544 1176 }
8bdb31ed
PS
1177 } else {
1178 $rowcols['status'][] = get_string('missingusername');
df7ecfe4 1179 }
07ed083e 1180
43070e61
PS
1181 if (isset($rowcols['email'])) {
1182 if (!validate_email($rowcols['email'])) {
1183 $rowcols['status'][] = get_string('invalidemail');
1184 }
1185 if ($DB->record_exists('user', array('email'=>$rowcols['email']))) {
1186 $rowcols['status'][] = $stremailduplicate;
1187 }
07ed083e 1188 }
fd9672ac
RW
1189
1190 if (isset($rowcols['city'])) {
7ca44a49 1191 $rowcols['city'] = $rowcols['city'];
fd9672ac 1192 }
1b4d2d56
RT
1193 // Check if rowcols have custom profile field with correct data and update error state.
1194 $noerror = uu_check_custom_profile_data($rowcols) && $noerror;
8bdb31ed
PS
1195 $rowcols['status'] = implode('<br />', $rowcols['status']);
1196 $data[] = $rowcols;
07ed083e 1197}
8bdb31ed
PS
1198if ($fields = $cir->next()) {
1199 $data[] = array_fill(0, count($fields) + 2, '...');
07ed083e 1200}
8bdb31ed 1201$cir->close();
3fe2cfb5
RW
1202
1203$table = new html_table();
1204$table->id = "uupreview";
16be8974 1205$table->attributes['class'] = 'generaltable';
3fe2cfb5 1206$table->tablealign = 'center';
ce15d56d 1207$table->summary = get_string('uploaduserspreview', 'tool_uploaduser');
3fe2cfb5 1208$table->head = array();
8bdb31ed 1209$table->data = $data;
3fe2cfb5 1210
ce15d56d 1211$table->head[] = get_string('uucsvline', 'tool_uploaduser');
8bdb31ed
PS
1212foreach ($filecolumns as $column) {
1213 $table->head[] = $column;
07ed083e 1214}
8bdb31ed 1215$table->head[] = get_string('status');
07ed083e 1216
3f12c146 1217echo html_writer::tag('div', html_writer::table($table), array('class'=>'flexible-wrap'));
3fe2cfb5 1218
1b4d2d56
RT
1219// Print the form if valid values are available
1220if ($noerror) {
1221 $mform2->display();
1222}
73d6f52f 1223echo $OUTPUT->footer();
df7ecfe4 1224die;
1225