edit.php 37.5 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/usersearch');
15
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
16
define('TITLE', get_string('accountsettings', 'admin'));
17
18
19
define('SECTION_PLUGINTYPE', 'core');
define('SECTION_PLUGINNAME', 'admin');
require_once('pieforms/pieform.php');
20
require_once('activity.php');
21
require_once(get_config('docroot') . 'lib/antispam.php');
22
23

$id = param_integer('id');
24
25
$user = new User;
$user->find_by_id($id);
26
$authobj = AuthFactory::create($user->authinstance);
27

28
if (!$USER->is_admin_for_user($user)) {
29
    $SESSION->add_error_msg(get_string('youcannotadministerthisuser', 'admin'));
30
    redirect(profile_url($user));
31
}
32

33
34
35
36
37
38
39
if ($user->deleted) {
    $smarty = smarty();
    $smarty->assign('PAGEHEADING', TITLE . ': ' . display_name($user));
    $smarty->assign('message', get_string('thisuserdeleted', 'admin'));
    $smarty->display('message.tpl');
    exit;
}
40
41

// Site-wide account settings
42
$currentdate = getdate();
Richard Mansfield's avatar
Richard Mansfield committed
43
$elements = array();
44
45
46
47
48
$elements['id'] = array(
    'type'    => 'hidden',
    'rules'   => array('integer' => true),
    'value'   => $id,
);
49

50
51
52
53
54
55
if (method_exists($authobj, 'change_username')) {
    $elements['username'] = array(
        'type'         => 'text',
        'title'        => get_string('changeusername', 'admin'),
        'description'  => get_string('changeusernamedescription', 'admin'),
        'defaultvalue' => $user->username,
56
57
58
        'rules' => array(
            'maxlength' => 236,
         ),
59
60
61
    );
}

62
63
64
if (method_exists($authobj, 'change_password')) {
    // Only show the password options if the plugin allows for the functionality
    $elements['password'] = array(
65
        'type'         => 'password',
66
67
68
69
70
        'title'        => get_string('resetpassword','admin'),
        'description'  => get_string('resetpassworddescription','admin'),
    );

    $elements['passwordchange'] = array(
71
        'type'         => 'switchbox',
72
73
74
75
76
        'title'        => get_string('forcepasswordchange','admin'),
        'description'  => get_string('forcepasswordchangedescription','admin'),
        'defaultvalue' => $user->passwordchange,
    );
}
77
78
if ($USER->get('admin')) {
    $elements['staff'] = array(
79
        'type'         => 'switchbox',
80
81
        'title'        => get_string('sitestaff','admin'),
        'defaultvalue' => $user->staff,
82
        'help'         => true,
83
84
    );
    $elements['admin'] = array(
85
        'type'         => 'switchbox',
86
87
        'title'        => get_string('siteadmin','admin'),
        'defaultvalue' => $user->admin,
88
        'help'         => true,
89
90
    );
}
91
92
93
94
95
96
97
98
99
100
$elements['email'] = array(
    'type'         => 'text',
    'title'        => get_string('primaryemail','admin'),
    'defaultvalue' => $user->email,
    'help'         => true,
    'rules'        => array(
        'required' => true,
        'email'    => true,
    ),
);
101
$elements['maildisabled'] = array(
102
    'type' => 'switchbox',
103
    'defaultvalue' => get_account_preference($user->id, 'maildisabled'),
104
    'title' => get_string('disableemail', 'admin'),
105
106
    'help' => true,
);
107
108
$elements['expiry'] = array(
    'type'         => 'date',
109
    'class'        => 'form-condensed',
110
111
112
113
114
115
    'title'        => get_string('accountexpiry', 'admin'),
    'description'  => get_string('accountexpirydescription', 'admin'),
    'minyear'      => $currentdate['year'] - 2,
    'maxyear'      => $currentdate['year'] + 20,
    'defaultvalue' => $user->expiry
);
116
$quotaused = get_string('quotaused', 'admin') . ': ' . display_size($user->quotaused);
117
118
119
if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) {
    $elements['quota'] = array(
        'type'         => 'bytes',
120
        'title'        => get_string('filequota1','admin'),
121
        'description'  => get_string('filequotadescription','admin') . '<br>' . $quotaused,
122
123
        'rules'        => array('integer' => true,
                                'minvalue' => 1),
124
        'class'        => 'form-inline mls',
125
126
127
128
129
130
131
        'defaultvalue' => $user->quota,
    );
}
else {
    $elements['quota'] = array(
        'type'         => 'text',
        'disabled'     => true,
132
        'title'        => get_string('filequota1', 'admin'),
133
        'description'  => get_string('filequotadescription', 'admin') . '<br>' . $quotaused,
134
        'class'        => 'form-inline mls',
135
136
137
        'value'        => display_size($user->quota),
    );
}
138

139
140
141
142
143
144
// Probation points
if (is_using_probation($user->id)) {
    $elements['probationpoints'] = array(
        'type' => 'select',
        'title' => get_string('probationtitle', 'admin'),
        'help' => true,
145
146
        'options' => probation_form_options(),
        'defaultvalue' => ensure_valid_probation_points($user->probation),
147
148
149
    );
}

150
151
152
153
$authinstances = auth_get_auth_instances();
if (count($authinstances) > 1) {
    $options = array();

154
155
156
    // NOTE: This is a little broken at the moment. The "username in the remote
    // system" setting is only actively used by the XMLRPC authentication
    // plugin, and thus only makes sense when the user is authenticating in
157
158
    // this manner.
    //
159
160
    // We hope to one day make it possible for users to get into accounts via
    // multiple methods, at which time we can tie the username-in-remote-system
161
    // setting to the XMLRPC plugin only, making the UI a bit more consistent
162
    $external = false;
163
    $externalauthjs = array();
164
    foreach ($authinstances as $authinstance) {
165
166
167
168
        // If a user has a "No Institution" auth method (institution "mahara", id = 1) and he belongs to an Institution,
        // his Institution Admin will be able to change his auth method away to one of the Institution's auth methods
        // that's the second part of the "if"
        if ($USER->can_edit_institution($authinstance->name) || ($authinstance->id == 1 && $user->authinstance == 1)) {
169
            $options[$authinstance->id] = $authinstance->displayname . ': ' . $authinstance->instancename;
170
171
            $authobj = AuthFactory::create($authinstance->id);
            if ($authobj->needs_remote_username()) {
172
                $externalauthjs[] = $authinstance->id;
173
174
                $external = true;
            }
175
        }
176
177
    }

178
179
    if (isset($options[$user->authinstance])) {
        $elements['authinstance'] = array(
180
181
            'type'         => 'select',
            'title'        => get_string('authenticatedby', 'admin'),
182
            'description'  => get_string('authenticatedbydescription', 'admin'),
183
            'options'      => $options,
184
            'defaultvalue' => $user->authinstance,
185
            'help'         => true,
186
        );
187
188
189
190
191
192
193
        $un = get_field('auth_remote_user', 'remoteusername', 'authinstance', $user->authinstance, 'localusr', $user->id);
        $elements['remoteusername'] = array(
            'type'         => 'text',
            'title'        => get_string('remoteusername', 'admin'),
            'description'  => get_string('remoteusernamedescription1', 'admin', hsc(get_config('sitename'))),
            'help'         => true,
        );
194
195
196
        if ($un) {
            $elements['remoteusername']['defaultvalue'] = $un;
        }
197
    }
198
    $remoteusernames = json_encode(get_records_menu('auth_remote_user', 'localusr', $id));
199
    $js = "<script type='application/javascript'>
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
          var externalauths = ['" . implode("','", $externalauthjs) . "'];
          var remoteusernames = " . $remoteusernames . ";
          jQuery(document).ready(function() {
          // set up initial display
          var authinstanceid = jQuery('#edituser_site_authinstance :selected').val();
          is_external(authinstanceid);

          // update display as auth method dropdown changes
          jQuery('#edituser_site_authinstance').change(function() {
              authinstanceid = jQuery('#edituser_site_authinstance :selected').val();
              is_external(authinstanceid);
          });

          function is_external(id) {
              if (jQuery.inArray(authinstanceid,externalauths) != -1) {
                  // is external option so show external auth field and help text rows
216
217
                  jQuery('#edituser_site_remoteusername_container').css('display','block');
                  jQuery('#edituser_site_remoteusername_container').next('div').css('display','block');
218
219
220
221
                  if (remoteusernames[id]) {
                      // if value exists in auth_remote_user display it
                      jQuery('#edituser_site_remoteusername').val(remoteusernames[id]);
                  }
222
223
224
                  else {
                      jQuery('#edituser_site_remoteusername').val('');
                  }
225
226
227
228
              }
              else {
                  // is internal option so hide external auth field and help text rows
                  jQuery('#edituser_site_remoteusername_container').css('display','none');
229
                  jQuery('#edituser_site_remoteusername_container').next('div').css('display','none');
230
231
232
233
234
235
236
              }
          }
      });
      </script>";

    $elements['externalauthjs'] = array(
        'type'         => 'html',
237
        'class'        => 'hidden',
238
239
        'value'        => $js,
    );
240
241
}

242
$tags = get_column_sql('SELECT tag FROM {usr_tag} WHERE usr = ? AND NOT tag ' . db_ilike() . " 'lastinstitution:%'", array($user->id));
Hugh Davenport's avatar
Hugh Davenport committed
243
244
245
246
247
248
249
250
251

$elements['tags'] = array(
    'defaultvalue' => $tags,
    'type'         => 'tags',
    'title'        => get_string('tags'),
    'description'  => get_string('tagsdesc'),
    'help'         => true,
);

252
253
$elements['submit'] = array(
    'type'  => 'submit',
254
    'class' => 'btn-primary mbm',
255
256
257
    'value' => get_string('savechanges','admin'),
);

Richard Mansfield's avatar
Richard Mansfield committed
258
259
$siteform = pieform(array(
    'name'       => 'edituser_site',
Pat Kira's avatar
Pat Kira committed
260
    'renderer'   => 'div',
261
262
263
264
265
    'plugintype' => 'core',
    'pluginname' => 'admin',
    'elements'   => $elements,
));

266
267
function edituser_site_validate(Pieform $form, $values) {
    global $USER, $SESSION;
268
269
270
    if (!$user = get_record('usr', 'id', $values['id'])) {
        return false;
    }
271
272
273
274
275
276
277
    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)));
            $SESSION->add_error_msg(get_string('maxquotaexceeded', 'artefact.file', display_size($maxquota)));
        }
278
    }
279

280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
    $userobj = new User();
    $userobj = $userobj->find_by_id($user->id);

    if (isset($values['username']) && !empty($values['username']) && $values['username'] != $userobj->username) {

        if (!isset($values['authinstance'])) {
            $authobj = AuthFactory::create($userobj->authinstance);
        }
        else {
            $authobj = AuthFactory::create($values['authinstance']);
        }

        if (method_exists($authobj, 'change_username')) {

            if (method_exists($authobj, 'is_username_valid_admin')) {
                if (!$authobj->is_username_valid_admin($values['username'])) {
                    $form->set_error('username', get_string('usernameinvalidadminform', 'auth.internal'));
                }
            }
            else if (method_exists($authobj, 'is_username_valid')) {
                if (!$authobj->is_username_valid($values['username'])) {
                    $form->set_error('username', get_string('usernameinvalidform', 'auth.internal'));
                }
            }

305
            if (!$form->get_error('username') && record_exists_select('usr', 'LOWER(username) = ?', array(strtolower($values['username'])))) {
306
307
308
309
310
311
312
313
                $form->set_error('username', get_string('usernamealreadytaken', 'auth.internal'));
            }
        }
        else {
            $form->set_error('username', get_string('usernamechangenotallowed', 'admin'));
        }
    }

314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
    // Check that the external username isn't already in use by someone else
    if (isset($values['authinstance']) && isset($values['remoteusername'])) {
        // there are 4 cases for changes on the page
        // 1) ai and remoteuser have changed
        // 2) just ai has changed
        // 3) just remoteuser has changed
        // 4) the ai changes and the remoteuser is wiped - this is a delete of the old ai-remoteuser

        // determine the current remoteuser
        $current_remotename = get_field('auth_remote_user', 'remoteusername',
                                        'authinstance', $user->authinstance, 'localusr', $user->id);
        if (!$current_remotename) {
            $current_remotename = $user->username;
        }
        // what should the new remoteuser be
        $new_remoteuser = get_field('auth_remote_user', 'remoteusername',
                                    'authinstance', $values['authinstance'], 'localusr', $user->id);
        if (!$new_remoteuser) {
            $new_remoteuser = $user->username;
        }
        if (strlen(trim($values['remoteusername'])) > 0) {
            // value changed on page - use it
            if ($values['remoteusername'] != $current_remotename) {
                $new_remoteuser = $values['remoteusername'];
            }
        }

        // what really counts is who owns the target remoteuser slot
        $target_owner = get_field('auth_remote_user', 'localusr',
                                  'authinstance', $values['authinstance'], 'remoteusername', $new_remoteuser);
        // target remoteuser is owned by someone else
        if ($target_owner && $target_owner != $user->id) {
            $usedbyuser = get_field('usr', 'username', 'id', $target_owner);
            $SESSION->add_error_msg(get_string('duplicateremoteusername', 'auth', $usedbyuser));
            $form->set_error('remoteusername', get_string('duplicateremoteusernameformerror', 'auth'));
        }
350
    }
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372

    // Check if the new primary email address is valid
    if (isset($values['email']) &&
        ($values['email'] !== $user->email)) {
        $email = sanitize_email($values['email']);
        if (!$form->get_error('email')) {
            if (!$form->get_error('email') && empty($email)) {
                $form->set_error('email', get_string('invalidemailaddress', 'artefact.internal'));
            }

            if (record_exists_sql('
                    SELECT id
                    FROM {usr}
                    WHERE deleted != 1 AND email = ? AND id != ?', array($email, $user->id))
                || record_exists_sql('
                    SELECT owner
                    FROM {artefact_internal_profile_email}
                    WHERE email = ? AND owner != ?', array($email, $user->id))) {
                $form->set_error('email', get_string('emailalreadytakenbyothers', 'auth.internal'));
            }
        }
    }
373
}
374

Richard Mansfield's avatar
Richard Mansfield committed
375
function edituser_site_submit(Pieform $form, $values) {
376
    global $USER, $authobj, $SESSION;
377

378
379
380
381
    if (!$user = get_record('usr', 'id', $values['id'])) {
        return false;
    }

382
383
    if (is_using_probation()) {
        // Value should be between 0 and 10 inclusive
384
        $user->probation = ensure_valid_probation_points($values['probationpoints']);
385
386
    }

387
388
    if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) {
        $user->quota = $values['quota'];
389
390
391
392
393
        // check if the user has gone over the quota notify limit
        $quotanotifylimit = get_config_plugin('artefact', 'file', 'quotanotifylimit');
        if ($quotanotifylimit <= 0 || $quotanotifylimit >= 100) {
            $quotanotifylimit = 100;
        }
394
        $user->quotausedpercent = empty($user->quota) ? 0 : ($user->quotaused / $user->quota) * 100;
395
396
397
398
399
400
401
402
403
404
405
406
407
408
        $overlimit = false;
        if ($quotanotifylimit <= $user->quotausedpercent) {
            $overlimit = true;
        }
        $notified = get_field('usr_account_preference', 'value', 'field', 'quota_exceeded_notified', 'usr', $user->id);
        if ($overlimit && '1' !== $notified) {
            require_once(get_config('docroot') . 'artefact/file/lib.php');
            ArtefactTypeFile::notify_users_threshold_exceeded(array($user), false);
            // no need to email admin as we can alert them right now
            $SESSION->add_error_msg(get_string('useroverquotathreshold', 'artefact.file', display_name($user)));
        }
        else if ($notified && !$overlimit) {
            set_account_preference($user->id, 'quota_exceeded_notified', false);
        }
409
    }
410

411
412
413
414
415
416
417
418
419
    $unexpire = $user->expiry && strtotime($user->expiry) < time() && (empty($values['expiry']) || $values['expiry'] > time());
    $newexpiry = db_format_timestamp($values['expiry']);
    if ($user->expiry != $newexpiry) {
        $user->expiry = $newexpiry;
        if ($unexpire) {
            $user->expirymailsent = 0;
            $user->lastaccess = db_format_timestamp(time());
        }
    }
420
421
422
423
424

    // Try to kick the user from any active login sessions, before saving data.
    require_once(get_config('docroot') . 'auth/session.php');
    remove_user_sessions($user->id);

425
426
427
    if ($USER->get('admin')) {  // Not editable by institutional admins
        $user->staff = (int) ($values['staff'] == 'on');
        $user->admin = (int) ($values['admin'] == 'on');
428
429
430
        if ($user->admin) {
            activity_add_admin_defaults(array($user->id));
        }
431
432
    }

433
434
435
436
    if ($values['maildisabled'] == 0 && get_account_preference($user->id, 'maildisabled') == 1) {
        // Reset the sent and bounce counts otherwise mail will be disabled
        // on the next send attempt
        $u = new StdClass;
437
438
        $u->email = $user->email;
        $u->id = $user->id;
439
440
441
442
443
        update_bounce_count($u,true);
        update_send_count($u,true);
    }
    set_account_preference($user->id, 'maildisabled', $values['maildisabled']);

444
445
446
447
448
    // process the change of the authinstance and or the remoteuser
    if (isset($values['authinstance']) && isset($values['remoteusername'])) {
        // Authinstance can be changed by institutional admins if both the
        // old and new authinstances belong to the admin's institutions
        $authinst = get_records_select_assoc('auth_instance', 'id = ? OR id = ?',
449
                                             array($values['authinstance'], $user->authinstance));
450
451
452
        // But don't bother if the auth instance doesn't take a remote username
        $authobj = AuthFactory::create($values['authinstance']);
        if (
453
454
455
456
457
458
            $USER->get('admin')
            || (
                $USER->is_institutional_admin($authinst[$values['authinstance']]->institution)
                && (
                    $USER->is_institutional_admin($authinst[$user->authinstance]->institution)
                    || $user->authinstance == 1
459
                )
460
            )
461
        ) {
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
            if ($authobj->needs_remote_username()) {
                // determine the current remoteuser
                $current_remotename = get_field('auth_remote_user', 'remoteusername',
                                                'authinstance', $user->authinstance, 'localusr', $user->id);
                if (!$current_remotename) {
                    $current_remotename = $user->username;
                }
                // if the remoteuser is empty
                if (strlen(trim($values['remoteusername'])) == 0) {
                    delete_records('auth_remote_user', 'authinstance', $user->authinstance, 'localusr', $user->id);
                }
                // what should the new remoteuser be
                $new_remoteuser = get_field('auth_remote_user', 'remoteusername',
                                            'authinstance', $values['authinstance'], 'localusr', $user->id);
                // save the remotename for the target existence check
                $target_remotename = $new_remoteuser;
                if (!$new_remoteuser) {
                    $new_remoteuser = $user->username;
                }
                if (strlen(trim($values['remoteusername'])) > 0) {
                    // value changed on page - use it
                    if ($values['remoteusername'] != $current_remotename) {
                        $new_remoteuser = $values['remoteusername'];
                    }
                }
                // only update remote name if the input actually changed on the page  or it doesn't yet exist
                if ($current_remotename != $new_remoteuser || !$target_remotename) {
                    // only remove the ones related to this traget authinstance as we now allow multiple
                    // for dual login mechanisms
                    delete_records('auth_remote_user', 'authinstance', $values['authinstance'], 'localusr', $user->id);
                    insert_record('auth_remote_user', (object) array(
                        'authinstance'   => $values['authinstance'],
                        'remoteusername' => $new_remoteuser,
                        'localusr'       => $user->id,
                    ));
497
                }
498
            }
499
            // update the ai on the user master
500
            $user->authinstance = $values['authinstance'];
501
502
503
504
505

            // update the global $authobj to match the new authinstance
            // this is used by the password/username change methods
            // if either/both has been requested at the same time
            $authobj = AuthFactory::create($user->authinstance);
506
        }
507
    }
508

509
510
    // Only change the pw if the new auth instance allows for it
    if (method_exists($authobj, 'change_password')) {
511
        $user->passwordchange = (int) (isset($values['passwordchange']) && $values['passwordchange'] == 'on' ? 1 : 0);
512
513
514
515
516

        if (isset($values['password']) && $values['password'] !== '') {
            $userobj = new User();
            $userobj = $userobj->find_by_id($user->id);

517
518
            $user->password = $authobj->change_password($userobj, $values['password']);
            $user->salt = $userobj->salt;
519
520
521
522
523
524
525
526
527

            unset($userobj);
        }
    } else {
        // inform the user that the chosen auth instance doesn't allow password changes
        // but only if they tried changing it
        if (isset($values['password']) && $values['password'] !== '') {
            $SESSION->add_error_msg(get_string('passwordchangenotallowed', 'admin'));

528
529
530
531
            // Set empty pw with salt
            $user->password = '';
            $user->salt = auth_get_random_salt();
        }
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
    }

    if (isset($values['username']) && $values['username'] !== '') {
        $userobj = new User();
        $userobj = $userobj->find_by_id($user->id);

        if ($userobj->username != $values['username']) {
            // Only change the username if the auth instance allows for it
            if (method_exists($authobj, 'change_username')) {
                // check the existence of the chosen username
                try {
                    if ($authobj->user_exists($values['username'])) {
                        // set an error message if it is already in use
                        $SESSION->add_error_msg(get_string('usernameexists', 'account'));
                    }
                } catch (AuthUnknownUserException $e) {
                    // update the username otherwise
                    $user->username = $authobj->change_username($userobj, $values['username']);
                }
            } else {
                // inform the user that the chosen auth instance doesn't allow username changes
                $SESSION->add_error_msg(get_string('usernamechangenotallowed', 'admin'));
            }
        }
556

557
        unset($userobj);
558
    }
559

Hugh Davenport's avatar
Hugh Davenport committed
560
    db_begin();
561
562
    update_record('usr', $user);

563
564
565
    // Update user's primary email address
    set_user_primary_email($user->id, $values['email']);

Hugh Davenport's avatar
Hugh Davenport committed
566
567
    delete_records('usr_tag', 'usr', $user->id);
    if (is_array($values['tags'])) {
568
        $values['tags'] = check_case_sensitive($values['tags'], 'usr_tag');
Hugh Davenport's avatar
Hugh Davenport committed
569
570
571
572
573
574
575
576
577
578
579
580
581
582
        foreach(array_unique($values['tags']) as $tag) {
            if (empty($tag)) {
                continue;
            }
            insert_record(
                'usr_tag',
                (object) array(
                    'usr' => $user->id,
                    'tag' => strtolower($tag),
                )
            );
        }
    }
    db_commit();
583

584
    $SESSION->add_ok_msg(get_string('usersitesettingschanged', 'admin'));
585
586
587
588
    redirect('/admin/users/edit.php?id='.$user->id);
}


589
590
591
592
593
594
595
596
597
598
599
600
601
602
// Suspension/deletion controls
$suspended = $user->get('suspendedcusr');
if (empty($suspended)) {
    $suspendform = pieform(array(
        'name'       => 'edituser_suspend',
        'plugintype' => 'core',
        'pluginname' => 'admin',
        'elements'   => array(
            'id' => array(
                 'type'    => 'hidden',
                 'value'   => $id,
            ),
            'reason' => array(
                'type'        => 'textarea',
603
                'class'       => 'under-label',
604
                'rows'        => 5,
605
                'cols'        => 28,
606
607
608
609
610
                'title'       => get_string('reason'),
                'description' => get_string('suspendedreasondescription', 'admin'),
            ),
            'submit' => array(
                'type'  => 'submit',
611
                'class' => 'btn-default',
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
                'value' => get_string('suspenduser','admin'),
            ),
        )
    ));
}
else {
    $suspendformdef = array(
        'name'       => 'edituser_unsuspend',
        'plugintype' => 'core',
        'pluginname' => 'admin',
        'renderer'   => 'oneline',
        'elements'   => array(
            'id' => array(
                 'type'    => 'hidden',
                 'value'   => $id,
            ),
            'submit' => array(
                'type'  => 'submit',
630
                'class' => 'btn-default',
631
632
633
634
635
                'value' => get_string('unsuspenduser','admin'),
            ),
        )
    );

636
637
    // Create two forms for unsuspension - one in the suspend message and the
    // other where the 'suspend' button normally goes. This keeps the HTML IDs
638
639
640
641
642
643
644
    // unique
    $suspendform  = pieform($suspendformdef);
    $suspendformdef['name'] = 'edituser_suspend2';
    $suspendformdef['successcallback'] = 'edituser_unsuspend_submit';
    $suspendform2 = pieform($suspendformdef);

    $suspender = display_name(get_record('usr', 'id', $suspended));
645
    $suspendedtime = format_date($user->get('suspendedctime'), 'strftimedate');
646
647
648
}

function edituser_suspend_submit(Pieform $form, $values) {
649
650
651
652
653
654
655
656
657
    global $SESSION, $USER, $user;
    if (!$USER->get('admin') && ($user->get('admin') || $user->get('staff'))) {
        $SESSION->add_error_msg(get_string('errorwhilesuspending', 'admin'));
    }
    else {
        suspend_user($user->get('id'), $values['reason']);
        $SESSION->add_ok_msg(get_string('usersuspended', 'admin'));
    }
    redirect('/admin/users/edit.php?id=' . $user->get('id'));
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
}

function edituser_unsuspend_submit(Pieform $form, $values) {
    global $SESSION;
    unsuspend_user($values['id']);
    $SESSION->add_ok_msg(get_string('userunsuspended', 'admin'));
    redirect('/admin/users/edit.php?id=' . $values['id']);
}

$deleteform = pieform(array(
    'name' => 'edituser_delete',
    'plugintype' => 'core',
    'pluginname' => 'admin',
    'renderer' => 'oneline',
    'elements'   => array(
        'id' => array(
            'type' => 'hidden',
            'value' => $id,
        ),
        'submit' => array(
678
679
            'type' => 'button',
            'usebuttontag' => true,
680
            'class' => 'btn-default',
681
            'value'          => '<span class="icon icon-trash icon-lg text-danger left"></span><span>'. get_string('deleteuser', 'admin') . '</span>',
682
683
684
685
686
            'confirm' => get_string('confirmdeleteuser', 'admin'),
        ),
    ),
));

687
688
689
690
691
692
function edituser_delete_validate(Pieform $form, $values) {
    global $USER, $SESSION;
    if (!$USER->get('admin')) {
        $form->set_error('submit', get_string('deletefailed', 'admin'));
        $SESSION->add_error_msg(get_string('deletefailed', 'admin'));
    }
693
694
695
696
697
698
    // Check to see if there are any pending archives in the export_queue for this user.
    // We can't delete them if there are.
    if ($results = count_records('export_queue', 'usr', $values['id'])) {
        $form->set_error('submit', get_string('deletefailed', 'admin'));
        $SESSION->add_error_msg(get_string('exportqueuenotempty', 'export'));
    }
699
700
}

701
function edituser_delete_submit(Pieform $form, $values) {
702
703
704
705
706
    global $SESSION, $USER;
    if ($USER->get('admin')) {
        delete_user($values['id']);
        $SESSION->add_ok_msg(get_string('userdeletedsuccessfully', 'admin'));
    }
707
708
709
    redirect('/admin/users/search.php');
}

Richard Mansfield's avatar
Richard Mansfield committed
710

711
// Institution settings form
Richard Mansfield's avatar
Richard Mansfield committed
712
713
714
715
716
717
718
$elements = array(
    'id' => array(
         'type'    => 'hidden',
         'value'   => $id,
     ),
);

719
720
721
722
723
724
725
726
727
728
729
function is_institute_admin($institution) {
    return $institution->admin;
}

$institutions = $user->get('institutions');
if ( !$USER->get('admin') ) { // for institution admins
    $admin_institutions = $USER->get('institutions');
    $admin_institutions = array_filter($admin_institutions, "is_institute_admin");
    $institutions = array_intersect_key($institutions, $admin_institutions);
}

730
$allinstitutions = get_records_assoc('institution', '', '', 'displayname', 'name, displayname');
731
732
$institutionloop = 0;
$institutionlength = count($institutions);
733
foreach ($institutions as $i) {
734
735
    $elements[$i->institution.'_settings'] = array(
        'type' => 'fieldset',
736
737
738
        'legend' => get_string('institutionsettings', 'admin').' - '.$i->displayname,
        'collapsible'  => true,
        'collapsed'    => true,
739
740
741
        'elements' => array(
            $i->institution.'_expiry' => array(
                'type'         => 'date',
742
743
                'title'        => get_string('membershipexpiry', 'admin'),
                'description'  => get_string('membershipexpirydescription', 'admin'),
744
                'class'        => 'form-condensed',
745
746
                'minyear'      => $currentdate['year'],
                'maxyear'      => $currentdate['year'] + 20,
747
                'defaultvalue' => $i->membership_expiry
748
749
750
            ),
            $i->institution.'_studentid' => array(
                'type'         => 'text',
751
752
                'title'        => get_string('studentid', 'admin'),
                'description'  => get_string('institutionstudentiddescription', 'admin'),
753
754
                'defaultvalue' => $i->studentid,
            ),
755
            $i->institution.'_staff' => array(
756
                'type'         => 'switchbox',
757
758
                'title'        => get_string('institutionstaff','admin'),
                'defaultvalue' => $i->staff,
759
            ),
760
            $i->institution.'_admin' => array(
761
                'type'         => 'switchbox',
762
                'title'        => get_string('institutionadmin','admin'),
763
                'description'  => get_string('institutionadmindescription1','admin'),
764
765
766
767
768
                'defaultvalue' => $i->admin,
            ),
            $i->institution.'_submit' => array(
                'type'  => 'submit',
                'value' => get_string('update'),
769
                'class' => 'btn-primary'
770
            ),
771
772
            $i->institution.'_remove' => array(
                'type'  => 'submit',
773
                'class' => 'btn-default',
774
775
                'value' => get_string('removeuserfrominstitution', 'admin'),
                'confirm' => get_string('confirmremoveuserfrominstitution', 'admin'),
776
777
            )
        )
Richard Mansfield's avatar
Richard Mansfield committed
778
    );
779
780
781
782
    if ($institutionloop == $institutionlength - 1) {
        $elements[$i->institution.'_settings']['class'] = 'last mbl';
    }
    $institutionloop++;
Richard Mansfield's avatar
Richard Mansfield committed
783
}
784

785
// Only site admins can add institutions; institutional admins must invite
786
if ($USER->get('admin')
787
788
789
790
791
792
793
794
    && (get_config('usersallowedmultipleinstitutions') || count($user->institutions) == 0)) {
    $options = array();
    foreach ($allinstitutions as $i) {
        if (!$user->in_institution($i->name) && $i->name != 'mahara') {
            $options[$i->name] = $i->displayname;
        }
    }
    if (!empty($options)) {
795
796
        $elements['addinstitutionheader'] = array(
            'type'  => 'markup',
797
            'value' => '<h4>' . get_string('addusertoinstitution', 'admin') . '</h4>',
798
        );
799
800
        $elements['addinstitution'] = array(
            'type'         => 'select',
801
            'title'        => get_string('institution'),
802
803
804
805
            'options'      => $options,
        );
        $elements['add'] = array(
            'type'  => 'submit',
806
            'class' => 'btn-primary mbs',
807
            'value' => get_string('addusertoinstitution', 'admin'),
808
809
810
811
        );
    }
}

Richard Mansfield's avatar
Richard Mansfield committed
812
813
$institutionform = pieform(array(
    'name'       => 'edituser_institution',
Pat Kira's avatar
Pat Kira committed
814
    'renderer'   => 'div',
Richard Mansfield's avatar
Richard Mansfield committed
815
816
817
818
819
    'plugintype' => 'core',
    'pluginname' => 'admin',
    'elements'   => $elements,
));

820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
function edituser_institution_validate(Pieform $form, $values) {
    $user = new User;
    if (!$user->find_by_id($values['id'])) {
        return false;
    }
    global $USER;

    $userinstitutions = $user->get('institutions');
    if (isset($values['add']) && $USER->get('admin')
        && (empty($userinstitutions) || get_config('usersallowedmultipleinstitutions'))) {
        // check if the institution is full
        require_once(get_config('docroot') . 'lib/institution.php');
        $institution = new Institution($values['addinstitution']);
        if ($institution->isFull()) {
            $institution->send_admin_institution_is_full_message();
            $form->set_error(null,get_string('institutionmaxusersexceeded', 'admin'));
        }
    }
}

Richard Mansfield's avatar
Richard Mansfield committed
840
function edituser_institution_submit(Pieform $form, $values) {
841
842
    $user = new User;
    if (!$user->find_by_id($values['id'])) {
Richard Mansfield's avatar
Richard Mansfield committed
843
844
        return false;
    }
845
    $userinstitutions = $user->get('institutions');
Richard Mansfield's avatar
Richard Mansfield committed
846

847
    global $USER, $SESSION;
848
    foreach ($userinstitutions as $i) {
Richard Mansfield's avatar
Richard Mansfield committed
849
        if ($USER->can_edit_institution($i->institution)) {
850
851
852
853
            if (isset($values[$i->institution.'_submit'])) {
                $newuser = (object) array(
                    'usr'         => $user->id,
                    'institution' => $i->institution,
854
                    'ctime'       => db_format_timestamp($i->ctime),
855
                    'studentid'   => $values[$i->institution . '_studentid'],
856
                    'staff'       => (int) ($values[$i->institution . '_staff'] == 'on'),
857
858
859
860
861
862
863
864
                    'admin'       => (int) ($values[$i->institution . '_admin'] == 'on'),
                );
                if ($values[$i->institution . '_expiry']) {
                    $newuser->expiry = db_format_timestamp($values[$i->institution . '_expiry']);
                }
                db_begin();
                delete_records('usr_institution', 'usr', $user->id, 'institution', $i->institution);
                insert_record('usr_institution', $newuser);
865
866
867
                if ($newuser->admin) {
                    activity_add_admin_defaults(array($user->id));
                }
868
869
                handle_event('updateuser', $user->id);
                db_commit();
870
                $SESSION->add_ok_msg(get_string('userinstitutionupdated', 'admin', $i->displayname));
871
                break;
872
873
            }
            else if (isset($values[$i->institution.'_remove'])) {
874
875
                if ($user->id == $USER->id) {
                    $USER->leave_institution($i->institution);
876
877
                }
                else {
878
879
                    $user->leave_institution($i->institution);
                }
880
                $SESSION->add_ok_msg(get_string('userinstitutionremoved', 'admin', $i->displayname));
881
882
883
884
                // Institutional admins can no longer access this page
                // if they remove the user from the institution, so
                // send them back to user search.
                if (!$USER->get('admin')) {
885
886
887
                    if (!$USER->is_institutional_admin()) {
                        redirect(get_config('wwwroot'));
                    }
888
889
890
891
892
                    redirect('/admin/users/search.php');
                }
                break;
            }
        }
893
894
    }

895
896
    if (isset($values['add']) && $USER->get('admin')
        && (empty($userinstitutions) || get_config('usersallowedmultipleinstitutions'))) {
897
898
899
        if ($user->id == $USER->id) {
            $USER->join_institution($values['addinstitution']);
            $USER->commit();
900
            $userinstitutions = $USER->get('institutions');
901
902
903
        }
        else {
            $user->join_institution($values['addinstitution']);
904
            $userinstitutions = $user->get('institutions');
905
        }
906
        $SESSION->add_ok_msg(get_string('userinstitutionjoined', 'admin', $userinstitutions[$values['addinstitution']]->displayname));
Richard Mansfield's avatar
Richard Mansfield committed
907
908
909
910
    }

    redirect('/admin/users/edit.php?id='.$user->id);
}
911
912
913

$smarty = smarty();
$smarty->assign('user', $user);
914
915
$smarty->assign('suspended', $suspended);
if ($suspended) {
916
    $smarty->assign('suspendedby', get_string('suspendedinfo', 'admin', $suspender, $suspendedtime));
917
}
918
$smarty->assign('suspendform', $suspendform);
919
920
921
922
if (isset($suspendform2)) {
    $smarty->assign('suspendform2', $suspendform2);
}
$smarty->assign('deleteform', $deleteform);
Richard Mansfield's avatar
Richard Mansfield committed
923
$smarty->assign('siteform', $siteform);
924
$smarty->assign('institutions', count($allinstitutions) > 1);
Richard Mansfield's avatar
Richard Mansfield committed
925
$smarty->assign('institutionform', $institutionform);
Richard Mansfield's avatar
Richard Mansfield committed
926

927
$smarty->assign('loginas', $id != $USER->get('id') && is_null($USER->get('parentuser')));
928
$smarty->assign('PAGEHEADING', TITLE . ': ' . display_name($user));
929
930
931
932
933
934
935
936
937

# Only allow deletion and suspension of a user if the viewed user is not
# the current user; or if they are the current user, they're not the only
# admin
if ($id != $USER->get('id') || count_records('usr', 'admin', 1, 'deleted', 0) > 1) {
    $smarty->assign('suspendable', ($USER->get('admin') || !$user->get('admin') && !$user->get('staff')));
    $smarty->assign('deletable', $USER->get('admin'));
}

938
$smarty->display('admin/users/edit.tpl');