uploadcsv.php 26 KB
Newer Older
1
2
3
4
5
<?php
/**
 *
 * @package    mahara
 * @subpackage admin
6
 * @author     Catalyst IT Ltd
7
8
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
 * @copyright  For copyright information on Mahara, please see the README file distributed with this software.
9
10
11
12
 *
 */

define('INTERNAL', 1);
13
define('INSTITUTIONALADMIN', 1);
14
define('MENUITEM', 'configusers/uploadcsv');
15
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
Martyn Smith's avatar
Martyn Smith committed
16
define('TITLE', get_string('uploadcsv', 'admin'));
17
require_once('institution.php');
Nigel McNie's avatar
Nigel McNie committed
18
safe_require('artefact', 'internal');
19

20
21
22
// Turn on autodetecting of line endings, so mac newlines (\r) will work
ini_set('auto_detect_line_endings', 1);

Nigel McNie's avatar
Nigel McNie committed
23
$FORMAT = array();
24
$specialcases = array('username', 'password', 'remoteuser');
25
26
// Don't upload social profiles for now. A user can have multiple profiles. Not sure how to put that in a csv.
$notallowed = array('socialprofile');
27
$ALLOWEDKEYS = array_keys(ArtefactTypeProfile::get_all_fields());
28
$ALLOWEDKEYS = array_diff($ALLOWEDKEYS, $notallowed);
29
30
$maildisabled = array_search('maildisabled', $ALLOWEDKEYS);
unset($ALLOWEDKEYS[$maildisabled]);
31
32
$ALLOWEDKEYS = array_merge($ALLOWEDKEYS, $specialcases);

33
34
$UPDATES         = array(); // During validation, remember which users already exist
$INSTITUTIONNAME = array(); // Mapping from institution id to display name
Nigel McNie's avatar
Nigel McNie committed
35

36
37
38
39
40
41
if ($USER->get('admin')) {
    $authinstances = auth_get_auth_instances();
} else {
    $admininstitutions = $USER->get('admininstitutions');
    $authinstances = auth_get_auth_instances_for_institutions($admininstitutions);
    if (empty($authinstances)) {
42
        $SESSION->add_info_msg(get_string('configureauthplugin', 'admin'));
43
44
45
        redirect(get_config('wwwroot').'admin/users/institutions.php?i='.key($admininstitutions).'&amp;edit=1');
    }
}
46

47
if (count($authinstances) > 0) {
48
    $options = array();
49
50

    foreach ($authinstances as $authinstance) {
Richard Mansfield's avatar
Richard Mansfield committed
51
        if ($USER->can_edit_institution($authinstance->name)) {
52
            $options[$authinstance->id] = $authinstance->displayname. ': '.$authinstance->instancename;
53
            $INSTITUTIONNAME[$authinstance->name] = $authinstance->displayname;
54
        }
55
    }
56
    if ($USER->get('admin')) {
57
        $definst = get_field('auth_instance', 'id', 'institution', 'mahara', 'active', 1);
58
59
60
61
62
        $default = $definst ? $definst : key($options);
    }
    else {
        $default = key($options);
    }
63
64

    $authinstanceelement = array(
65
66
        'type' => 'select',
        'title' => get_string('institution'),
67
68
        'description' => get_string('uploadcsvinstitution', 'admin'),
        'options' => $options,
69
        'defaultvalue' => $default
70
71
72
    );
}

73
74
$prefs = (object) expected_account_preferences();

75
76
$form = array(
    'name' => 'uploadcsv',
77
78
    'plugintype' => 'core',
    'pluginname' => 'admin',
79
    'elements' => array(
80
        'authinstance' => $authinstanceelement,
81
82
        'quota' => array(
            'type' => 'bytes',
83
            'title' => get_string('filequota1', 'admin'),
84
85
86
87
            'description' => get_string('filequotadescription', 'admin'),
            'rules' => array('integer' => true, 'minvalue' => 0),
            'defaultvalue' => get_config_plugin('artefact', 'file', 'defaultquota'),
        ),
88
89
90
91
        'file' => array(
            'type' => 'file',
            'title' => get_string('csvfile', 'admin'),
            'description' => get_string('csvfiledescription', 'admin'),
92
            'accept' => '.csv, text/csv, application/csv, text/comma-separated-values',
93
94
95
96
            'rules' => array(
                'required' => true
            )
        ),
97
        'forcepasswordchange' => array(
98
            'type'         => 'switchbox',
99
100
101
102
103
            'title'        => get_string('forceuserstochangepassword', 'admin'),
            'description'  => get_string('forceuserstochangepassworddescription', 'admin'),
            'defaultvalue' => true,
        ),
        'emailusers' => array(
104
            'type' => 'switchbox',
105
106
107
108
            'title' => get_string('emailusersaboutnewaccount', 'admin'),
            'description' => get_string('emailusersaboutnewaccountdescription', 'admin'),
            'defaultvalue' => true,
        ),
109
        'updateusers' => array(
110
            'type' => 'switchbox',
111
112
113
114
            'title' => get_string('updateusers', 'admin'),
            'description' => get_string('updateusersdescription', 'admin'),
            'defaultvalue' => false,
        ),
115
116
117
118
119
        'accountprefs' => array(
            'type' => 'fieldset',
            'legend' => get_string('accountoptionsdesc', 'account'),
            'collapsible' => true,
            'collapsed' => true,
120
            'class' => 'last with-formgroup',
121
122
            'elements' => general_account_prefs_form_elements($prefs),
        ),
123
124
125
126
127
        'progress_meter_token' => array(
            'type' => 'hidden',
            'value' => 'uploaduserscsv',
            'readonly' => TRUE,
        ),
128
129
        'submit' => array(
            'type' => 'submit',
130
            'value' => get_string('uploadcsv', 'admin'),
131
            'class' => 'btn-primary'
132
133
134
135
        )
    )
);

136
137
138
139
if ($maxcsvlines = get_config('maxusercsvlines')) {
    $form['elements']['file']['description'] .= ' ' . get_string('csvmaxusersdescription', 'admin', get_string('nusers', 'mahara', $maxcsvlines));
}

140
141
unset($prefs);

142
143
144
145
if (!($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride'))) {
    $form['elements']['quota'] = array(
        'type'         => 'text',
        'disabled'     => true,
146
        'title'        => get_string('filequota1', 'admin'),
147
148
149
150
151
        'description'  => get_string('filequotadescription', 'admin'),
        'value'        => display_size(get_config_plugin('artefact', 'file', 'defaultquota')),
    );
}

152
153
154
155
156
/**
 * The CSV file is parsed here so validation errors can be returned to the
 * user. The data from a successful parsing is stored in the <var>$CVSDATA</var>
 * array so it can be accessed by the submit function
 *
157
158
 * @param Pieform  $form   The form to validate
 * @param array    $values The values submitted
159
 */
160
function uploadcsv_validate(Pieform $form, $values) {
161
    global $CSVDATA, $ALLOWEDKEYS, $FORMAT, $USER, $INSTITUTIONNAME, $UPDATES;
162
163
164
165
166
167

    // Don't even start attempting to parse if there are previous errors
    if ($form->has_errors()) {
        return;
    }

168
169
170
    $steps_done = 0;
    $steps_total = $values['updateusers'] ? 5 : 4;

171
    if ($values['file']['size'] == 0) {
172
        $form->set_error('file', $form->i18n('rule', 'required', 'required', array()));
173
174
175
        return;
    }

176
177
178
179
180
181
    if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) {
        $maxquotaenabled = get_config_plugin('artefact', 'file', 'maxquotaenabled');
        $maxquota = get_config_plugin('artefact', 'file', 'maxquota');
        if ($maxquotaenabled && $values['quota'] > $maxquota) {
            $form->set_error('quota', get_string('maxquotaexceededform', 'artefact.file', display_size($maxquota)));
        }
182
183
    }

184
    require_once('csvfile.php');
185

186
    $authinstance = (int) $values['authinstance'];
187
    $institution = get_field('auth_instance', 'institution', 'id', $authinstance, 'active', 1);
Richard Mansfield's avatar
Richard Mansfield committed
188
    if (!$USER->can_edit_institution($institution)) {
189
190
191
        $form->set_error('authinstance', get_string('notadminforinstitution', 'admin'));
        return;
    }
192

193
194
    $authobj = AuthFactory::create($authinstance);

195
196
    $csvusers = new CsvFile($values['file']['tmp_name']);
    $csvusers->set('allowedkeys', $ALLOWEDKEYS);
197

198
199
200
    // Now we know all of the field names are valid, we need to make
    // sure that the required fields are included
    $mandatoryfields = array(
201
        'username', 'email', 'firstname', 'lastname'
202
    );
203
204
205
206
    if (!$values['updateusers']) {
        $mandatoryfields[] = 'password';
    }

207
208
    $csvusers->set('mandatoryfields', $mandatoryfields);
    $csvdata = $csvusers->get_data();
209

210
211
212
213
    if (!empty($csvdata->errors['file'])) {
        $form->set_error('file', $csvdata->errors['file']);
        return;
    }
Nigel McNie's avatar
Nigel McNie committed
214

215
216
    $csverrors = new CSVErrors();

217
218
    $formatkeylookup = array_flip($csvdata->format);

219
220
221
222
    // First pass validates usernames & passwords in the file, and builds
    // up a list indexed by username.

    $emails = array();
223
224
225
    if (isset($formatkeylookup['remoteuser'])) {
        $remoteusers = array();
    }
226

227
228
    $num_lines = count($csvdata->data);

229
    $maxcsvlines = get_config('maxusercsvlines');
230
    if ($maxcsvlines && $maxcsvlines < $num_lines) {
231
232
233
234
        $form->set_error('file', get_string('uploadcsverrortoomanyusers', 'admin', get_string('nusers', 'mahara', $maxcsvlines)));
        return;
    }

235
236
237
238
    $existing_usernames = get_records_menu('usr', '', NULL, '', 'LOWER(username) AS username, 1 AS key2');
    $existing_usr_email_addresses = get_records_menu('usr', '', NULL, '', 'email, 1 AS key2');
    $existing_internal_email_addresses = get_records_menu('artefact_internal_profile_email', 'verified', 1, '', 'email, 1 AS key2');

239
    foreach ($csvdata->data as $key => $line) {
240
241
        // If headers exists, increment i = key + 2 for actual line number
        $i = ($csvusers->get('headerExists')) ? ($key + 2) : ($key + 1);
242

243
244
245
246
        if (!($key % 25)) {
            set_progress_info('uploaduserscsv', $key, $num_lines * $steps_total, get_string('validating', 'admin'));
        }

247
248
249
250
        // Trim non-breaking spaces -- they get left in place by File_CSV
        foreach ($line as &$field) {
            $field = preg_replace('/^(\s|\xc2\xa0)*(.*?)(\s|\xc2\xa0)*$/', '$2', $field);
        }
251

252
        if (count($line) != count($csvdata->format)) {
253
            $csverrors->add($i, get_string('uploadcsverrorwrongnumberoffields', 'admin', $i));
254
255
256
            continue;
        }

257
258
259
        // We have a line with the correct number of fields, but should validate these fields
        // Note: This validation should really be methods on each profile class, that way
        // it can be used in the profile screen as well.
260

261
        $username = $line[$formatkeylookup['username']];
262
        $password = isset($formatkeylookup['password']) ? $line[$formatkeylookup['password']] : null;
263
        $email    = $line[$formatkeylookup['email']];
264
265
266
        if (isset($remoteusers)) {
            $remoteuser = strlen($line[$formatkeylookup['remoteuser']]) ? $line[$formatkeylookup['remoteuser']] : null;
        }
Nigel McNie's avatar
Nigel McNie committed
267

268
269
        if (method_exists($authobj, 'is_username_valid_admin')) {
            if (!$authobj->is_username_valid_admin($username)) {
270
                $csverrors->add($i, get_string('uploadcsverrorinvalidusername', 'admin', $i));
271
272
273
274
            }
        }
        else if (method_exists($authobj, 'is_username_valid')) {
            if (!$authobj->is_username_valid($username)) {
275
                $csverrors->add($i, get_string('uploadcsverrorinvalidusername', 'admin', $i));
276
            }
277
        }
278
279
280
281
282
283

        if (!$values['updateusers']) {
            // Note: only checks for valid form are done here, none of the checks
            // like whether the password is too easy. The user is going to have to
            // change their password on first login anyway.
            if (method_exists($authobj, 'is_password_valid') && !$authobj->is_password_valid($password)) {
284
                $csverrors->add($i, get_string('uploadcsverrorinvalidpassword', 'admin', $i));
285
            }
286
        }
287
288
289

        if (isset($emails[$email])) {
            // Duplicate email within this file.
290
            $csverrors->add($i, get_string('uploadcsverroremailaddresstaken', 'admin', $i, $email));
291
        }
292
        else if (!sanitize_email($email)) {
293
294
            $csverrors->add($i, get_string('uploadcsverrorinvalidemail', 'admin', $i, $email));
        }
295
296
        else if (!$values['updateusers']) {
            // The email address must be new
297
            if (array_key_exists($email, $existing_usr_email_addresses) || array_key_exists($email, $existing_internal_email_addresses)) {
298
                $csverrors->add($i, get_string('uploadcsverroremailaddresstaken', 'admin', $i, $email));
299
300
301
            }
        }
        $emails[$email] = 1;
302

303
304
        if (isset($remoteusers) && $remoteuser) {
            if (isset($remoteusers[$remoteuser])) {
305
                $csverrors->add($i, get_string('uploadcsverrorduplicateremoteuser', 'admin', $i, $remoteuser));
306
307
            }
            else if (!$values['updateusers']) {
308
309
310
311
312
                if ($remoteuserowner = get_record_sql('
                    SELECT u.username
                    FROM {auth_remote_user} aru JOIN {usr} u ON aru.localusr = u.id
                    WHERE aru.remoteusername = ? AND aru.authinstance = ?',
                    array($remoteuser, $authinstance))) {
313
                    $csverrors->add($i, get_string('uploadcsverrorremoteusertaken', 'admin', $i, $remoteuser, $remoteuserowner->username));
314
315
316
317
318
                }
            }
            $remoteusers[$remoteuser] = true;
        }

319
320
321
322
323
        // If we didn't even get a username, we can't check for duplicates, so move on.
        if (strlen($username) < 1) {
            continue;
        }

324
325
        if (isset($usernames[strtolower($username)])) {
            // Duplicate username within this file.
326
            $csverrors->add($i, get_string('uploadcsverroruseralreadyexists', 'admin', $i, $username));
327
        }
328
        else {
329
            if (!$values['updateusers'] && array_key_exists(strtolower($username), $existing_usernames)) {
330
                $csverrors->add($i, get_string('uploadcsverroruseralreadyexists', 'admin', $i, $username));
331
332
333
334
335
336
337
338
            }
            $usernames[strtolower($username)] = array(
                'username' => $username,
                'password' => $password,
                'email'    => $email,
                'lineno'   => $i,
                'raw'      => $line,
            );
339
340
341
            if (!empty($remoteuser) && !empty($remoteusers[$remoteuser])) {
                $usernames[strtolower($username)]['remoteuser'] = $remoteuser;
            }
342
343
        }
    }
Nigel McNie's avatar
Nigel McNie committed
344

345
346
347
348
349
    // If the admin is trying to overwrite existing users, identified by username,
    // this second pass performs some additional checks

    if ($values['updateusers']) {

350
351
        $key = 0;

352
353
        foreach ($usernames as $lowerusername => $data) {

354
355
356
357
358
            if (!($key % 25)) {
                set_progress_info('uploaduserscsv', $num_lines + $key, $num_lines * $steps_total, get_string('checkingupdates', 'admin'));
            }
            $key++;

359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
            $line      = $data['lineno'];
            $username  = $data['username'];
            $password  = $data['password'];
            $email     = $data['email'];

            // If the user already exists, they must already be in this institution.
            $userinstitutions = get_records_sql_assoc("
                SELECT COALESCE(ui.institution, 'mahara') AS institution, u.id
                FROM {usr} u LEFT JOIN {usr_institution} ui ON u.id = ui.usr
                WHERE LOWER(u.username) = ?",
                array($lowerusername)
            );
            if ($userinstitutions) {
                if (!isset($userinstitutions[$institution])) {
                    if ($institution == 'mahara') {
                        $institutiondisplay = array();
                        foreach ($userinstitutions as $i) {
                            $institutiondisplay[] = $INSTITUTIONNAME[$i->institution];
                        }
                        $institutiondisplay = join(', ', $institutiondisplay);
                        $message = get_string('uploadcsverroruserinaninstitution', 'admin', $line, $username, $institutiondisplay);
                    }
                    else {
                        $message = get_string('uploadcsverrorusernotininstitution', 'admin', $line, $username, $INSTITUTIONNAME[$institution]);
                    }
384
                    $csverrors->add($line, $message);
385
386
387
388
389
390
391
392
393
                }
                else {
                    // Remember that this user is being updated
                    $UPDATES[$username] = 1;
                }
            }
            else {
                // New user, check the password
                if (method_exists($authobj, 'is_password_valid') && !$authobj->is_password_valid($password)) {
394
                    $csverrors->add($line, get_string('uploadcsverrorinvalidpassword', 'admin', $line));
395
396
397
                }
            }

398
399
400
401
402
            // Check if the email already exists and if it's owned by this user.  This query can return more
            // than one row when there are duplicate emails already on the site.  If that happens, things are
            // already a bit out of hand, and we'll just allow an update if this user is one of the users who
            // owns the email.
            $emailowned = get_records_sql_assoc('
403
404
405
406
407
408
409
410
                SELECT LOWER(u.username) AS lowerusername, ae.principal FROM {usr} u
                LEFT JOIN {artefact_internal_profile_email} ae ON u.id = ae.owner AND ae.verified = 1 AND ae.email = ?
                WHERE ae.owner IS NOT NULL OR u.email = ?',
                array($email, $email)
            );

            // If the email is owned by someone else, it could still be okay provided
            // that other user's email is also being changed in this csv file.
411
412
413
414
415
416
417
418
419
420
421
422
423
            if ($emailowned && !isset($emailowned[$lowerusername])) {
                foreach ($emailowned as $e) {
                    // Only primary emails can be set in uploadcsv, so it's an error when someone else
                    // owns the email as a secondary.
                    if (!$e->principal) {
                        $csverrors->add($line, get_string('uploadcsverroremailaddresstaken', 'admin', $line, $email));
                        break;
                    }
                    // It's also an error if the email owner is not being updated in this file
                    if (!isset($usernames[$e->lowerusername])) {
                        $csverrors->add($line, get_string('uploadcsverroremailaddresstaken', 'admin', $line, $email));
                        break;
                    }
424
425
426
427
                    // If the other user is being updated in this file, but isn't changing their
                    // email address, it's ok, we've already notified duplicate emails within the file.
                }
            }
428
429
430
431
432
433
434
435
436
437
438

            if (isset($remoteusers) && !empty($data['remoteuser'])) {
                $remoteuser = $data['remoteuser'];
                $remoteuserowner = get_field_sql('
                    SELECT LOWER(u.username)
                    FROM {usr} u JOIN {auth_remote_user} aru ON u.id = aru.localusr
                    WHERE aru.remoteusername = ? AND aru.authinstance = ?',
                    array($remoteuser, $authinstance)
                );
                if ($remoteuserowner && $remoteuserowner != $lowerusername && !isset($usernames[$remoteuserowner])) {
                    // The remote username is owned by some other user who is not being updated in this file
439
                    $csverrors->add($line, get_string('uploadcsverrorremoteusertaken', 'admin', $line, $remoteuser, $remoteuserowner));
440
441
                }
            }
442
        }
443
    }
444

445
    if ($errors = $csverrors->process()) {
446
        $form->set_error('file', clean_html($errors), false);
447
448
449
        return;
    }

450
451
    $FORMAT = $csvdata->format;
    $CSVDATA = $csvdata->data;
452
453
454
455
456
457
}

/**
 * Add the users to the system. Make sure that they have to change their
 * password on next login also.
 */
458
function uploadcsv_submit(Pieform $form, $values) {
459
    global $USER, $SESSION, $CSVDATA, $FORMAT, $UPDATES;
460

Nigel McNie's avatar
Nigel McNie committed
461
    $formatkeylookup = array_flip($FORMAT);
462

463
    $authinstance = (int) $values['authinstance'];
464
465
466
467
    $authrecord   = get_record('auth_instance', 'id', $authinstance, 'active', 1);
    if (!$authrecord) {
        throw new InvalidArgumentException("trying to add user to inactive auth instance {$authinstance}");
    }
468
    $authobj      = AuthFactory::create($authinstance);
469
470

    $institution = new Institution($authobj->institution);
471

Aaron Wells's avatar
Aaron Wells committed
472
    $maxusers = $institution->maxuseraccounts;
473
474
475
476
477
478
479
480
481
482
    if (!empty($maxusers)) {
        $members = count_records_sql('
            SELECT COUNT(*) FROM {usr} u INNER JOIN {usr_institution} i ON u.id = i.usr
            WHERE i.institution = ? AND u.deleted = 0', array($institution->name));
        if ($members + count($CSVDATA) > $maxusers) {
            $SESSION->add_error_msg(get_string('uploadcsvfailedusersexceedmaxallowed', 'admin'));
            redirect('/admin/users/uploadcsv.php');
        }
    }

483
484
485
486
487
488
    if ($values['updateusers']) {
        log_info('Updating users from the CSV file');
    }
    else {
        log_info('Inserting users from the CSV file');
    }
489
490
    db_begin();

491
    $addedusers = array();
492
493
494
495
496
497
498

    $cfgsendemail = get_config('sendemail');
    if (empty($values['emailusers'])) {
        // Temporarily disable email sent during user creation, e.g. institution membership
        $GLOBALS['CFG']->sendemail = false;
    }

499
500
501
502
503
    $key = 0;
    $steps_total = $values['updateusers'] ? 5 : 4;
    $steps_done = $steps_total - 3;
    $num_lines = sizeof($CSVDATA);

504
    foreach ($CSVDATA as $record) {
505
506
507
508
509
510
511

        if (!($key % 25)) {
            // This part has three times the weight of the other two steps.
            set_progress_info('uploaduserscsv', $num_lines * $steps_done + $key * 3, $num_lines * $steps_total, get_string('committingchanges', 'admin'));
        }
        $key++;

512
        $user = new StdClass;
513
514
515
516
517
518
519
520
521
522
523
        foreach ($FORMAT as $field) {
            if ($field == 'username'  ||
                $field == 'firstname' ||
                $field == 'lastname'  ||
                $field == 'password'  ||
                $field == 'email'     ||
                $field == 'studentid' ||
                $field == 'preferredname') {
                $user->{$field} = $record[$formatkeylookup[$field]];
            }
        }
524
        $user->authinstance = $authinstance;
525
526
527
        if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) {
            $user->quota        = $values['quota'];
        }
528

529
        $profilefields = new StdClass;
Piers Harding's avatar
Piers Harding committed
530
        $remoteuser = null;
Nigel McNie's avatar
Nigel McNie committed
531
532
533
534
        foreach ($FORMAT as $field) {
            if ($field == 'username' || $field == 'password') {
                continue;
            }
Piers Harding's avatar
Piers Harding committed
535
536
537
538
539
540
            if ($field == 'remoteuser') {
                if (!empty($record[$formatkeylookup[$field]])) {
                    $remoteuser = $record[$formatkeylookup[$field]];
                }
                continue;
            }
541
            $profilefields->{$field} = $record[$formatkeylookup[$field]];
542
        }
Nigel McNie's avatar
Nigel McNie committed
543

544
545
        if (!$values['updateusers'] || !isset($UPDATES[$user->username])) {
            $user->passwordchange = (int)$values['forcepasswordchange'];
546

547
            $user->id = create_user($user, $profilefields, $institution, $authrecord, $remoteuser, $values, true);
548
549
550
551
552

            $addedusers[] = $user;
            log_debug('added user ' . $user->username);
        }
        else if (isset($UPDATES[$user->username])) {
553
            $updated = update_user($user, $profilefields, $remoteuser, $values, true, true);
554
555
556
557
558
559
560
561
562
563

            if (empty($updated)) {
                // Nothing changed for this user
                unset($UPDATES[$user->username]);
            }
            else {
                $UPDATES[$user->username] = $updated;
                log_debug('updated user ' . $user->username . ' (' . implode(', ', array_keys($updated)) . ')');
            }
        }
564
        set_time_limit(10);
565
    }
566
    db_commit();
567

568
569
570
    // Reenable email
    set_config('sendemail', $cfgsendemail);

Aaron Wells's avatar
Aaron Wells committed
571
    // Only send e-mail to users after we're sure they have been inserted
572
573
574
575
576
    // successfully
    $straccountcreatedtext = ($values['forcepasswordchange']) ? 'accountcreatedchangepasswordtext' : 'accountcreatedtext';
    $straccountcreatedhtml = ($values['forcepasswordchange']) ? 'accountcreatedchangepasswordhtml' : 'accountcreatedhtml';
    if ($values['emailusers'] && $addedusers) {
        foreach ($addedusers as $user) {
577
578
            $failedusers = array();
            try {
579
580
581
                email_user($user, null, get_string('accountcreated', 'mahara', get_config('sitename')),
                    get_string($straccountcreatedtext, 'mahara', $user->firstname, get_config('sitename'), $user->username, $user->password, get_config('wwwroot'), get_config('sitename')),
                    get_string($straccountcreatedhtml, 'mahara', $user->firstname, get_config('wwwroot'), get_config('sitename'), $user->username, $user->password, get_config('wwwroot'), get_config('wwwroot'), get_config('sitename'))
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
                );
            }
            catch (EmailException $e) {
                log_info($e->getMessage());
                $failedusers[] = $user;
            }
        }

        if ($failedusers) {
            $message = get_string('uploadcsvsomeuserscouldnotbeemailed', 'admin') . "\n<ul>\n";
            foreach ($failedusers as $user) {
                $message .= '<li>' . full_name($user) . ' &lt;' . hsc($user->email) . "&gt;</li>\n";
            }
            $message .= "</ul>\n";
            $SESSION->add_info_msg($message, false);
597
598
599
        }
    }

600
    log_info('Added ' . count($addedusers) . ' users, updated ' . count($UPDATES) . ' users.');
601

602
603
604
605
606
607
608
609
610
611
    $SESSION->add_ok_msg(get_string('csvfileprocessedsuccessfully', 'admin'));
    if ($UPDATES) {
        $updatemsg = smarty_core();
        $updatemsg->assign('added', count($addedusers));
        $updatemsg->assign('updates', $UPDATES);
        $SESSION->add_info_msg($updatemsg->fetch('admin/users/csvupdatemessage.tpl'), false);
    }
    else {
        $SESSION->add_ok_msg(get_string('numbernewusersadded', 'admin', count($addedusers)));
    }
612
613
614

    set_progress_done('uploaduserscsv');

615
    redirect('/admin/users/uploadcsv.php');
616
617
}

Nigel McNie's avatar
Nigel McNie committed
618
619
// Get a list of all profile fields, to inform the user on what fields they can
// put in their file.
620
natsort($ALLOWEDKEYS);
621
$fields = "<ul class='fieldslist column-list'>\n";
622
foreach ($ALLOWEDKEYS as $type) {
623
    if ($type == 'firstname' || $type == 'lastname' || $type == 'email' || $type == 'username' || $type == 'password') {
Nigel McNie's avatar
Nigel McNie committed
624
625
626
627
        continue;
    }
    $fields .= '<li>' . hsc($type) . "</li>\n";
}
Evonne Cheung's avatar
Evonne Cheung committed
628
$fields .= "<div class=cl></div></ul>\n";
Nigel McNie's avatar
Nigel McNie committed
629

630
$uploadcsvpagedescription = get_string('uploadcsvpagedescription6', 'admin', $fields);
631

632
633
$form = pieform($form);

634
635
set_progress_done('uploaduserscsv');

636
$smarty = smarty(array('adminuploadcsv'));
637
setpageicon($smarty, 'icon-user');
638
$smarty->assign('uploadcsvpagedescription', $uploadcsvpagedescription);
639
$smarty->assign('uploadcsvform', $form);
640
$smarty->display('admin/users/uploadcsv.tpl');