institutions.php 23.9 KB
Newer Older
1
2
<?php
/**
Francois Marier's avatar
Francois Marier committed
3
 * Mahara: Electronic portfolio, weblog, resume builder and social networking
4
5
 * Copyright (C) 2006-2009 Catalyst IT Ltd and others; see:
 *                         http://wiki.mahara.org/Contributors
6
 *
Francois Marier's avatar
Francois Marier committed
7
8
9
10
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
11
 *
Francois Marier's avatar
Francois Marier committed
12
13
14
15
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
16
 *
Francois Marier's avatar
Francois Marier committed
17
18
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20
21
 *
 * @package    mahara
 * @subpackage admin
22
 * @author     Catalyst IT Ltd
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
24
 * @copyright  (C) 2006-2009 Catalyst IT Ltd http://catalyst.net.nz
25
26
27
 *
 */
define('INTERNAL', 1);
28
define('INSTITUTIONALADMIN', 1);
29
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
Martyn Smith's avatar
Martyn Smith committed
30
define('TITLE', get_string('institutions', 'admin'));
Penny Leach's avatar
Penny Leach committed
31
32
33
define('SECTION_PLUGINTYPE', 'core');
define('SECTION_PLUGINNAME', 'admin');
define('SECTION_PAGE', 'institutions');
34
require_once('pieforms/pieform.php');
35
define('MENUITEM', 'manageinstitutions/institutions');
36
37
38

$institution = param_variable('i', '');
$add         = param_boolean('add');
39
40
$edit        = param_boolean('edit');
$delete      = param_boolean('delete');
41

42
43
44
45
46
47
48
49
50
51
52
if (!$USER->get('admin')) {
    // Institutional admins with only 1 institution go straight to the edit page for that institution
    // They cannot add or delete institutions, or edit an institution they don't administer
    $add = false;
    $delete = false;
    if (!empty($institution) && !$USER->is_institutional_admin($institution)) {
        $institution = '';
        $edit = false;
    }
    if (empty($institution) && count($USER->get('admininstitutions')) == 1) {
        redirect(get_config('wwwroot') . 'admin/users/institutions.php?i='
53
                 . key($USER->get('admininstitutions')));
54
55
56
    }
}

57
58
if ($institution || $add) {

59
60
61
62
63
    $authinstances = auth_get_auth_instances_for_institution($institution);
    if (false == $authinstances) {
        $authinstances = array();
    }

64
    if ($delete) {
65
        function delete_validate(Pieform $form, $values) {
66
            if (get_field('usr_institution', 'COUNT(*)', 'institution', $values['i'])) {
67
                throw new ConfigException('Attempt to delete an institution that has members');
68
69
70
            }
        }

71
        function delete_cancel_submit() {
72
            redirect('/admin/users/institutions.php');
73
74
        }

75
        function delete_submit(Pieform $form, $values) {
76
77
            global $SESSION;

78
            $authinstanceids = get_column('auth_instance', 'id', 'institution', $values['i']);
79
80
            $viewids = get_column('view', 'id', 'institution', $values['i']);
            $artefactids = get_column('artefact', 'id', 'institution', $values['i']);
81

82
            db_begin();
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
            if ($viewids) {
                require_once(get_config('libroot') . 'view.php');
                foreach ($viewids as $viewid) {
                    $view = new View($viewid);
                    $view->delete();
                }
            }
            if ($artefactids) {
                foreach ($artefactids as $artefactid) {
                    try {
                        $a = artefact_instance_from_id($artefactid);
                        $a->delete();
                    }
                    catch (ArtefactNotFoundException $e) {
                        // Awesome, it's already gone.
                    }
                }
            }
101
102
103
104
105
            foreach ($authinstanceids as $id) {
                delete_records('auth_instance_config', 'instance', $id);
            }
            delete_records('auth_instance', 'institution', $values['i']);
            delete_records('host', 'institution', $values['i']);
106
            delete_records('institution_locked_profile_field', 'name', $values['i']);
107
            delete_records('usr_institution_request', 'institution', $values['i']);
108
109
110
111
            delete_records('institution', 'name', $values['i']);
            db_commit();

            $SESSION->add_ok_msg(get_string('institutiondeletedsuccessfully', 'admin'));
112
            redirect('/admin/users/institutions.php');
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
        }
        $form = array(
            'name' => 'delete',
            'elements' => array(
                'i' => array(
                    'type' => 'hidden',
                    'value' => $institution
                ),
                'delete' => array(
                    'type' => 'hidden',
                    'value' => 1
                ),
                'submit' => array(
                    'type' => 'submitcancel',
                    'value' => array(get_string('yes'), get_string('no'))
                )
            )
        );
131
132
133
        $deleteform = pieform($form);
        $smarty = smarty();
        $smarty->assign('delete_form', $deleteform);
134
        $smarty->assign('institutionname', get_field('institution', 'displayname', 'name', $institution));
135
        $smarty->display('admin/users/institutions.tpl');
136
137
138
        exit;
    }

139
140
141
    $instancearray = array();
    $instancestring = '';
    $c = count($authinstances);
142
    $inuse = '';
143

144
145
    $sitelockedfields = (array) get_column('institution_locked_profile_field', 'profilefield', 'name', 'mahara');

146
147
    if (!$add) {
        $data = get_record('institution', 'name', $institution);
148
        $lockedprofilefields = (array) get_column('institution_locked_profile_field', 'profilefield', 'name', $institution);
149

150
        // TODO: Find a better way to work around Smarty's minimal looping logic
151
152
153
154
        if (!empty($authinstances)) {
            foreach($authinstances as $key => $val) {
                $authinstances[$key]->index = $key;
                $authinstances[$key]->total = $c;
155
                $instancearray[] = (int)$val->id;
156
            }
157

158
159
            $instancestring = implode(',',$instancearray);
            $inuserecords = array();
160
161
            if ($records = get_records_sql_assoc('select authinstance, count(id) from {usr} where authinstance in ('.$instancestring.') group by authinstance', array())) {
                foreach ($records as $record) {
Richard Mansfield's avatar
Richard Mansfield committed
162
                    $inuserecords[] = $record->authinstance;
163
                }
164
165
            }
            $inuse = implode(',',$inuserecords);
166
        }
167
        $authtypes = auth_get_available_auth_types($institution);
168
169
170
171
    }
    else {
        $data = new StdClass;
        $data->displayname = '';
172
        $data->expiry = null;
173
174
175
        if (!get_config('usersuniquebyusername')) {
            $data->registerallowed = 1;
        }
176
        $data->theme = 'sitedefault';
177
        $data->defaultmembershipperiod = null;
178
        $lockedprofilefields = array();
179
180

        $authtypes = auth_get_available_auth_types();
181
    }
182
    $themeoptions = get_institution_themes($institution);
183
    $themeoptions['sitedefault'] = '- ' . get_string('sitedefault', 'admin') . ' (' . $themeoptions[get_config('theme')] . ') -';
184
    uksort($themeoptions, 'theme_sort');
185
186
187

    $sitename = get_config('sitename');

188
    safe_require('artefact', 'internal');
189
190
    $elements = array(
        'name' => array(
191
            'type' => 'text',
192
            'title' => get_string('institutionname', 'admin'),
193
194
195
            'rules' => array(
                'required'  => true,
                'maxlength' => 255,
196
                'regex'     => '/^[a-zA-Z]+$/'
197
            ),
Penny Leach's avatar
Penny Leach committed
198
199
            'ignore' => !$add,
            'help'   => true,
200
201
202
203
204
205
        ),
        'add' => array(
            'type'   => 'hidden',
            'value'  => true,
            'ignore' => !$add
        ),
206
207
208
        'inuse' => array(
            'type'   => 'hidden',
            'value'  => $inuse,
209
210
            'id'     => 'inuse',
            'ignore' => $add
211
        ),
212
213
214
215
216
217
218
219
220
221
222
223
        'i' => array(
            'type'   => 'hidden',
            'value'  => $institution,
            'ignore' => $add
        ),
        'displayname' => array(
            'type' => 'text',
            'title' => get_string('institutiondisplayname', 'admin'),
            'defaultvalue' => $data->displayname,
            'rules' => array(
                'required'  => true,
                'maxlength' => 255
Penny Leach's avatar
Penny Leach committed
224
225
            ),
            'help'   => true,
226
        ),
227
    );
228
    if ($USER->get('admin') && $institution != 'mahara') {
229
       $elements['expiry'] = array(
230
231
            'type'         => 'date',
            'title'        => get_string('institutionexpiry', 'admin'),
232
            'description'  => get_string('institutionexpirydescription', 'admin', hsc($sitename)),
233
234
235
236
            'defaultvalue' => is_null($data->expiry) ? null : strtotime($data->expiry),
            'help'         => true,
            'minyear'      => date('Y') - 2,
            'maxyear'      => date('Y') + 10,
237
238
        );
    }
239
240
    if ($USER->get('admin')) {
        $elements['authplugin'] = array(
241
242
243
244
245
            'type'    => 'authlist',
            'title'   => get_string('authplugin', 'admin'),
            'options' => $authinstances,
            'authtypes' => $authtypes,
            'instancearray' => $instancearray,
246
            'instancestring' => $instancestring,
247
248
            'institution' => $institution,
            'help'   => true,
249
            'ignore' => count($authtypes) == 0 || $institution == ''
250
251
252
        );
    }

253
    if (!$add && empty($authinstances)) {
254
        if ($USER->get('admin')) {
255
            $SESSION->add_error_msg(get_string('adminnoauthpluginforinstitution', 'admin'));
256
257
        }
        else {
258
            $SESSION->add_error_msg(get_string('noauthpluginforinstitution', 'admin'));
259
260
261
        }
    }

262
263
264
265
266
267
268
269
270
    if (!get_config('usersuniquebyusername')) {
        $elements['registerallowed'] = array(
            'type'         => 'checkbox',
            'title'        => get_string('registrationallowed', 'admin'),
            'description'  => get_string('registrationalloweddescription2', 'admin'),
            'defaultvalue' => $data->registerallowed,
            'help'   => true,
        );
    }
271

272
    if (empty($data->name) || $data->name != 'mahara') {
273
        $elements['defaultmembershipperiod'] = array(
274
            'type'         => 'expiry',
275
276
277
            'title'        => get_string('defaultmembershipperiod', 'admin'),
            'description'  => get_string('defaultmembershipperioddescription', 'admin'),
            'defaultvalue' => $data->defaultmembershipperiod,
Penny Leach's avatar
Penny Leach committed
278
            'help'   => true,
279
280
        );
        $elements['theme'] = array(
281
            'type'         => 'select',
282
            'title'        => get_string('theme'),
283
            'description'  => get_string('sitethemedescription','admin'),
284
            'defaultvalue' => $data->theme ? $data->theme : 'sitedefault',
285
286
287
            'collapseifoneoption' => true,
            'options'      => $themeoptions,
            'help'         => true,
288
        );
289
290
291
292
293
294
        if ($USER->get('admin')) {
            $elements['maxuseraccounts'] = array(
                'type'         => 'text',
                'title'        => get_string('maxuseraccounts','admin'),
                'description'  => get_string('maxuseraccountsdescription','admin'),
                'defaultvalue' => empty($data->maxuseraccounts) ? '' : $data->maxuseraccounts,
295
296
297
298
299
                'rules'        => array(
                    'regex'     => '/^\d*$/',
                    'maxlength' => 8,
                ),
                'size'         => 5,
300
301
            );
        }
302
    }
303

304
    $elements['lockedfields'] = array(
305
        'type' => 'fieldset',
306
        'legend' => get_string('Lockedfields', 'admin'),
307
308
309
        'collapsible' => true,
        'collapsed' => true,
        'elements' => array(),
310
    );
311
312
313
314
315
316
    if ($institution != 'mahara') {
        $elements['lockedfields']['elements']['description'] = array(
            'type' => 'html',
            'value' => get_string('disabledlockedfieldhelp', 'admin', get_field('institution', 'displayname', 'name', 'mahara')),
        );
    }
317
    foreach (ArtefactTypeProfile::get_all_fields() as $field => $type) {
318
        $elements['lockedfields']['elements'][$field] = array(
319
            'type' => 'checkbox',
320
            'title' => get_string($field, 'artefact.internal'),
321
322
            'defaultvalue' => in_array($field, $lockedprofilefields) || ($institution != 'mahara' && in_array($field, $sitelockedfields)),
            'disabled' => $institution != 'mahara' && in_array($field, $sitelockedfields)
323
324
        );
    }
325
    $elements['lockedfieldshelp'] = array(
Evonne Cheung's avatar
Evonne Cheung committed
326
        'value' => '<tr id="lockedfieldshelp"><th colspan="2">'
327
328
329
330
        . get_help_icon('core', 'admin', 'institution', 'lockedfields') 
        . '</th></tr>'
    );

331
332
333
334
335
    $elements['submit'] = array(
        'type' => 'submitcancel',
        'value' => array(get_string('submit'), get_string('cancel'))
    );

336
    $institutionform = pieform(array(
337
        'name'     => 'institution',
338
        'renderer' => 'table',
Penny Leach's avatar
Penny Leach committed
339
340
        'plugintype' => 'core',
        'pluginname' => 'admin',
341
        'elements' => $elements
342
    ));
343
344
345
346

}
else {
    // Get a list of institutions
347
    require_once(get_config('libroot') . 'institution.php');
348
    if (!$USER->get('admin')) { // Filter the list for institutional admins
349
350
        $filter      = $USER->get('admininstitutions');
        $showdefault = false;
351
352
    }
    else {
353
354
        $filter      = false;
        $showdefault = true;
355
    }
356
    $institutions = Institution::count_members($filter, $showdefault);
357
358
}

359
function institution_validate(Pieform $form, $values) {
360
    if (!empty($values['name']) && !$form->get_error('name') && record_exists('institution', 'name', $values['name'])) {
361
362
363
364
        $form->set_error('name', get_string('institutionnamealreadytaken', 'admin'));
    }
}

365
function institution_submit(Pieform $form, $values) {
366
    global $SESSION, $institution, $add, $instancearray, $USER, $authinstances;
367
368
369
370
371

    db_begin();
    // Update the basic institution record...
    $newinstitution = new StdClass;
    if ($add) {
372
        $institution = $newinstitution->name = strtolower($values['name']);
373
374
375
    }

    $newinstitution->displayname                  = $values['displayname'];
376
    $newinstitution->authplugin                   = empty($values['authplugin']) ? null : $values['authplugin'];
377
378
379
380
381
382
383
384
385
    if (get_config('usersuniquebyusername')) {
        // Registering absolutely not allowed when this setting is on, it's a 
        // security risk. See the documentation for the usersuniquebyusername 
        // setting for more information
        $newinstitution->registerallowed = 0;
    }
    else {
        $newinstitution->registerallowed              = ($values['registerallowed']) ? 1 : 0;
    }
386
    $newinstitution->theme                        = (empty($values['theme']) || $values['theme'] == 'sitedefault') ? null : $values['theme'];
387
388
389
390
    if ($institution != 'mahara') {
        $newinstitution->defaultmembershipperiod  = ($values['defaultmembershipperiod']) ? intval($values['defaultmembershipperiod']) : null;
        if ($USER->get('admin')) {
            $newinstitution->maxuseraccounts      = ($values['maxuseraccounts']) ? intval($values['maxuseraccounts']) : null;
391
            $newinstitution->expiry               = db_format_timestamp($values['expiry']);
392
        }
393
394
    }

395
396
    if (!empty($values['authplugin'])) {
        $allinstances = array_merge($values['authplugin']['instancearray'], $values['authplugin']['deletearray']);
397

398
        if (array_diff($allinstances, $instancearray)) {
399
            throw new ConfigException('Attempt to delete or update another institution\'s auth instance');
400
        }
401

402
        if (array_diff($instancearray, $allinstances)) {
403
            throw new ConfigException('One of your instances is unaccounted for in this transaction');
404
405
        }

406
407
408
        foreach($values['authplugin']['instancearray'] as $priority => $instanceid) {
            if (in_array($instanceid, $values['authplugin']['deletearray'])) {
                // Should never happen:
409
                throw new SystemException('Attempt to update AND delete an auth instance');
410
411
412
413
414
415
416
417
            }
            $record = new StdClass;
            $record->priority = $priority;
            $record->id = $instanceid;
            update_record('auth_instance', $record,  array('id' => $instanceid));
        }

        foreach($values['authplugin']['deletearray'] as $instanceid) {
418
419
420
421
            // If this authinstance is the only xmlrpc authinstance that references a host, delete the host record.
            $hostwwwroot = null;
            foreach ($authinstances as $ai) {
                if ($ai->id == $instanceid && $ai->authname == 'xmlrpc') {
Francois Marier's avatar
Francois Marier committed
422
423
                    $hostwwwroot = get_field_sql("SELECT \"value\" FROM {auth_instance_config} WHERE \"instance\" = ? AND field = 'wwwroot'", array($instanceid));
                    if ($hostwwwroot && count_records_select('auth_instance_config', "field = 'wwwroot' AND \"value\" = ?", array($hostwwwroot)) == 1) {
424
425
426
427
428
429
430
431
432
                        // Unfortunately, it's possible that this host record could belong to a different institution,
                        // so specify the institution here.
                        delete_records('host', 'wwwroot', $hostwwwroot, 'institution', $institution);
                        // We really need to fix this, either by removing the institution from the host table, or refusing to allow the
                        // institution to be changed in the host record when another institution's authinstance is still pointing at it.
                    }
                    break;
                }
            }
433
434
435
436
            delete_records('auth_remote_user', 'authinstance', $instanceid);
            delete_records('auth_instance_config', 'instance', $instanceid);
            delete_records('auth_instance', 'id', $instanceid);
        }
437
438
    }

439
440
    if ($add) {
        insert_record('institution', $newinstitution);
441
442
443
444
445
446
447
448
449
450
451
        // If registration has been turned on, then we automatically insert an 
        // internal authentication authinstance
        if ($newinstitution->registerallowed) {
            $authinstance = (object)array(
                'instancename' => 'internal',
                'priority'     => 0,
                'institution'  => $newinstitution->name,
                'authname'     => 'internal',
            );
            insert_record('auth_instance', $authinstance);
        }
452
    }
453
    else {
454
455
        $where = new StdClass;
        $where->name = $institution;
456
        $oldtheme = get_field('institution', 'theme', 'name', $institution);
457
458
459
460
461
462
463
464
465
466
467
468
469
470
        update_record('institution', $newinstitution, $where);
    }

    delete_records('institution_locked_profile_field', 'name', $institution);
    foreach (ArtefactTypeProfile::get_all_fields() as $field => $type) {
        if ($values[$field]) {
            $profilefield = new StdClass;
            $profilefield->name         = $institution;
            $profilefield->profilefield = $field;
            insert_record('institution_locked_profile_field', $profilefield);
        }
    }
    db_commit();

471
    if ($add) {
472
473
474
475
476
477
        if ($newinstitution->registerallowed) {
            // If registration is not allowed, then an authinstance will not 
            // have been created, and thus cause the institution page to add 
            // its own error message on the next page load
            $SESSION->add_ok_msg(get_string('institutionaddedsuccessfully2', 'admin'));
        }
478
479
480
        $nexturl = '/admin/users/institutions.php?i='.urlencode($institution);
    }
    else {
481
        $message = get_string('institutionupdatedsuccessfully', 'admin');
482
        if (isset($values['theme']) && $oldtheme != $values['theme']
483
            && (!empty($oldtheme) || $values['theme'] != 'sitedefault')) {
484
            $USER->update_theme();
485
486
            $message .= '  ' . get_string('usersseenewthemeonlogin', 'admin');
        }
487
        $SESSION->add_ok_msg($message);
488
489
490
491
        $nexturl = '/admin/users/institutions.php';
    }

    redirect($nexturl);
492
493
494
}

function institution_cancel_submit() {
495
    redirect('/admin/users/institutions.php');
496
497
}

498
499
500
501
502
503
504
505
506
507
508
509
510
511
if ($institution && $institution != 'mahara') {
    $_institution = get_record('institution', 'name', $institution);
    $suspended = $_institution->suspended;
    if ($USER->get('admin')) {
        function institution_suspend_submit(Pieform $form, $values) {
            global $SESSION, $USER;
            if (!$USER->get('admin')) {
                $SESSION->add_error_msg(get_string('errorwhilesuspending', 'admin'));
            }
            else {
                set_field('institution', 'suspended', 1, 'name', $values['i']);
                $SESSION->add_ok_msg(get_string('institutionsuspended', 'admin'));
            }
            redirect('/admin/users/institutions.php?i=' . $values['i']);
512
        }
513
514
515
516
517
518
519
520
521
522
523

        function institution_unsuspend_submit(Pieform $form, $values) {
            global $SESSION, $USER;
            if (!$USER->get('admin')) {
                $SESSION->add_error_msg(get_string('errorwhileunsuspending', 'admin'));
            }
            else {
                set_field('institution', 'suspended', 0, 'name', $values['i']);
                $SESSION->add_ok_msg(get_string('institutionunsuspended', 'admin'));
            }
            redirect('/admin/users/institutions.php?i=' . $values['i']);
524
        }
525

526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
        // Suspension controls
        if (empty($suspended)) {
            $suspendformdef = array(
                'name'       => 'institution_suspend',
                'plugintype' => 'core',
                'pluginname' => 'admin',
                'elements'   => array(
                    'i' => array(
                        'type'    => 'hidden',
                        'value'   => $institution,
                    ),
                    'submit' => array(
                        'type'        => 'submit',
                        'value'       => get_string('suspendinstitution','admin'),
                        'description' => get_string('suspendinstitutiondescription','admin'),
                    ),
                )
            );

            $suspendform  = pieform($suspendformdef);
546
547
        }
        else {
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
            $suspendformdef = array(
                'name'       => 'institution_unsuspend',
                'plugintype' => 'core',
                'pluginname' => 'admin',
                'elements'   => array(
                    'i' => array(
                        'type'    => 'hidden',
                        'value'   => $institution,
                    ),
                    'submit' => array(
                        'type'        => 'submit',
                        'value'       => get_string('unsuspendinstitution','admin'),
                        'description' => get_string('unsuspendinstitutiondescription','admin'),
                    ),
                )
            );
            $suspendform  = pieform($suspendformdef);

            // Create a second forms for unsuspension to go in the suspend message.
            // This keeps the HTML IDs unique
            $suspendformdef['name'] = 'institution_unsuspend_top';
            $suspendformdef['renderer'] = 'oneline';
            $suspendformdef['successcallback'] = 'institution_unsuspend_submit';
            $suspendform_top = pieform($suspendformdef);
        }
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
    }
}

$smarty = smarty();

if (isset($institutionform)) {
    $smarty->assign('institution_form', $institutionform);
    $smarty->assign('instancestring', $instancestring);
    $smarty->assign('add', $add);
}
else {
    $smarty->assign('siteadmin', $USER->get('admin'));
    $smarty->assign('institutions', $institutions);
}

if (isset($suspended)) {
    if ($suspended) {
        $smarty->assign('suspended', get_string('suspendedinstitutionmessage', 'admin'));
    }
    if (isset($suspendform)) {
593
594
595
        $smarty->assign('suspendform', $suspendform);
        if (isset($suspendform_top)) {
            $smarty->assign('suspendform_top', $suspendform_top);
596
        }
597
598
599
    }
}

600
$smarty->assign('PAGEHEADING', get_string('admininstitutions', 'admin'));
601
$smarty->display('admin/users/institutions.tpl');
602

603
604
605
606
607
608
609
610
611
612
function theme_sort($a, $b) {
    if ($a == 'sitedefault') {
        return -1;
    }
    if ($b == 'sitedefault') {
        return 1;
    }
    return $a > $b;
}

613
?>