institutions.php 49.7 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
 *
 */
define('INTERNAL', 1);
12
define('INSTITUTIONALADMIN', 1);
13
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
14
define('TITLE', get_string('Institutions', 'admin'));
Penny Leach's avatar
Penny Leach committed
15
16
17
define('SECTION_PLUGINTYPE', 'core');
define('SECTION_PLUGINNAME', 'admin');
define('SECTION_PAGE', 'institutions');
18
require_once('pieforms/pieform.php');
19
require_once('license.php');
20
define('MENUITEM', 'manageinstitutions/institutions');
21
22
23

$institution = param_variable('i', '');
$add         = param_boolean('add');
24
25
$edit        = param_boolean('edit');
$delete      = param_boolean('delete');
26

27
28
29
30
$query = param_variable('query', '');
$offset = param_integer('offset', 0);
$limit  = 20;

31

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
$customthemedefaults = array(
    'background'   => array('type' => 'color', 'value' => '#182768'),
    'backgroundfg' => array('type' => 'color', 'value' => '#FFFFFF'),
    'link'         => array('type' => 'color', 'value' => '#d66800'),
    'headings'     => array('type' => 'color', 'value' => '#182768'),
    'sidebarbg'    => array('type' => 'color', 'value' => '#182768'),
    'sidebarfg'    => array('type' => 'color', 'value' => '#f1f2f8'),
    'sidebarlink'  => array('type' => 'color', 'value' => '#182768'),
    'navbg'        => array('type' => 'color', 'value' => '#f6871f'),
    'navfg'        => array('type' => 'color', 'value' => '#FFFFFF'),
    'subbg'        => array('type' => 'color', 'value' => '#fff4ea'),
    'subfg'        => array('type' => 'color', 'value' => '#14336F'),
    'rowbg'        => array('type' => 'color', 'value' => '#fff4ea'),
);

47
48
49
50
51
52
53
54
55
56
57
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='
58
                 . key($USER->get('admininstitutions')));
59
60
61
    }
}

62
63
if ($institution || $add) {

64
65
66
67
68
    $authinstances = auth_get_auth_instances_for_institution($institution);
    if (false == $authinstances) {
        $authinstances = array();
    }

69
    if ($delete) {
70
        function delete_validate(Pieform $form, $values) {
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
            // Ensure the institution has no members left
            if ($members = get_field('usr_institution', 'COUNT(*)', 'institution', $values['i'])) {
                $form->set_error('submit', get_string('institutionstillhas', 'admin', get_string('nmembers', 'group', $members)));
            }

            // If some users are still using one of this institution's authinstances, it's okay if
            // we can find a default authinstance for those users, otherwise it's an error.
            if ($authinstanceids = get_column('auth_instance', 'id', 'institution', $values['i'])) {
                $badusers = count_records_select(
                    'usr',
                    'authinstance IN (' . join(',', array_fill(0, count($authinstanceids), '?')) . ')',
                    $authinstanceids
                );
                if ($badusers) {
                    $defaultauth = record_exists('auth_instance', 'institution', 'mahara', 'authname', 'internal');
                    if ($values['i'] == 'mahara' || !$defaultauth) {
                        $form->set_error(
                            'submit',
                            get_string('institutionauthinuseby', 'admin', get_string('nusers', 'mahara', $badusers))
                        );
                    }
                }
93
94
95
            }
        }

96
        function delete_cancel_submit() {
97
            redirect('/admin/users/institutions.php');
98
99
        }

100
        function delete_submit(Pieform $form, $values) {
101
102
            global $SESSION;

103
            $authinstanceids = get_column('auth_instance', 'id', 'institution', $values['i']);
104
            $collectionids = get_column('collection', 'id', 'institution', $values['i']);
105
106
            $viewids = get_column('view', 'id', 'institution', $values['i']);
            $artefactids = get_column('artefact', 'id', 'institution', $values['i']);
107
            $regdataids = get_column('institution_registration', 'id', 'institution', $values['i']);
108

109
            db_begin();
110
111
112
113
114
115
116
            if ($collectionids) {
                require_once(get_config('libroot') . 'collection.php');
                foreach ($collectionids as $collectionid) {
                    $collection = new Collection($collectionid);
                    $collection->delete();
                }
            }
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
            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.
                    }
                }
            }
135
136
137
138
139
140
141
142
143
144
145
146
147

            // If any users are still using this institution's authinstances, change them now.
            if ($authinstanceids) {
                execute_sql("
                    UPDATE {usr}
                    SET authinstance = (
                        SELECT MIN(id) FROM {auth_instance} WHERE institution = 'mahara' AND authname = 'internal'
                    )
                    WHERE authinstance IN (" . join(',', array_fill(0, count($authinstanceids), '?')) . ')',
                    $authinstanceids
                );
            }

148
149
150
            foreach ($authinstanceids as $id) {
                delete_records('auth_instance_config', 'instance', $id);
            }
151

152
153
154
155
            foreach ($regdataids as $id) {
                delete_records('institution_registration_data', 'registration_id', $id);
            }

156
157
158
159
160
            // The institution should have been removed from favourites lists when the members were removed,
            // but make sure it's gone.
            execute_sql('DELETE FROM {favorite_usr} WHERE favorite IN (SELECT id FROM {favorite} WHERE institution = ?)', array($values['i']));
            delete_records('favorite', 'institution', $values['i']);

161
            execute_sql("UPDATE {group} SET institution = NULL, shortname = NULL WHERE institution = ?", array($values['i']));
162
163
            delete_records('auth_instance', 'institution', $values['i']);
            delete_records('host', 'institution', $values['i']);
164
            delete_records('institution_locked_profile_field', 'name', $values['i']);
165
            delete_records('usr_institution_request', 'institution', $values['i']);
166
            delete_records('view_access', 'institution', $values['i']);
167
168
            delete_records('institution_data', 'institution', $values['i']);
            delete_records('institution_registration', 'institution', $values['i']);
169
170
            delete_records('site_content', 'institution', $values['i']);
            delete_records('institution_config', 'institution', $values['i']);
171
172
            delete_records('usr_custom_layout', 'institution', $values['i']);
            delete_records('usr_registration', 'institution', $values['i']);
173
174
175
176
            delete_records('institution', 'name', $values['i']);
            db_commit();

            $SESSION->add_ok_msg(get_string('institutiondeletedsuccessfully', 'admin'));
177
            redirect('/admin/users/institutions.php');
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
        }
        $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'))
                )
            )
        );
196
197
198
        $deleteform = pieform($form);
        $smarty = smarty();
        $smarty->assign('delete_form', $deleteform);
199
        $smarty->assign('institutionname', get_field('institution', 'displayname', 'name', $institution));
200
        $smarty->display('admin/users/institutions.tpl');
201
202
203
        exit;
    }

204
205
206
    $instancearray = array();
    $instancestring = '';
    $c = count($authinstances);
207
    $inuse = '';
208

209
210
    $sitelockedfields = (array) get_column('institution_locked_profile_field', 'profilefield', 'name', 'mahara');

211
212
    if (!$add) {
        $data = get_record('institution', 'name', $institution);
213
        $data->commentsortorder = get_config_institution($institution, 'commentsortorder');
214
        $lockedprofilefields = (array) get_column('institution_locked_profile_field', 'profilefield', 'name', $institution);
215

216
        // TODO: Find a better way to work around Smarty's minimal looping logic
217
218
219
220
        if (!empty($authinstances)) {
            foreach($authinstances as $key => $val) {
                $authinstances[$key]->index = $key;
                $authinstances[$key]->total = $c;
221
                $instancearray[] = (int)$val->id;
222
            }
223

224
225
            $instancestring = implode(',',$instancearray);
            $inuserecords = array();
226
227
            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
228
                    $inuserecords[] = $record->authinstance;
229
                }
230
231
            }
            $inuse = implode(',',$inuserecords);
232
        }
233
        $authtypes = auth_get_available_auth_types($institution);
234
235
236
237
    }
    else {
        $data = new StdClass;
        $data->displayname = '';
238
        $data->expiry = null;
239
        if (!get_config('usersuniquebyusername')) {
240
            $data->registerallowed = 0;
241
            $data->registerconfirm = 1;
242
        }
243
        $data->theme = 'sitedefault';
244
        $data->defaultmembershipperiod = null;
245
        $data->showonlineusers = 2;
246
        $data->allowinstitutionpublicviews = get_config('allowpublicviews') ? 1 : 0;
247
248
        $data->licensemandatory = 0;
        $data->licensedefault = '';
249
        $data->dropdownmenu = get_config('dropdownmenu') ? 1 : 0;
250
        $data->skins = get_config('skins') ? 1 : 0;
251
        $data->commentsortorder = 'earliest';
252
        $lockedprofilefields = array();
253
254

        $authtypes = auth_get_available_auth_types();
255
    }
256
    $themeoptions = get_institution_themes($institution);
257
    $themeoptions['sitedefault'] = '- ' . get_string('sitedefault', 'admin') . ' (' . $themeoptions[get_config('theme')] . ') -';
258
    uksort($themeoptions, 'theme_sort');
259

260
    $showonlineusersoptions = array('0' => get_string('none'), '1' => get_string('institutiononly', 'admin'), '2' => get_string('all', 'admin'));
261
262
    $sitename = get_config('sitename');

263
    safe_require('artefact', 'internal');
264
265
    $elements = array(
        'name' => array(
266
            'type' => 'text',
267
            'title' => get_string('institutionname', 'admin'),
268
269
270
            'rules' => array(
                'required'  => true,
                'maxlength' => 255,
271
                'regex'     => '/^[a-zA-Z]+$/'
272
            ),
Penny Leach's avatar
Penny Leach committed
273
274
            'ignore' => !$add,
            'help'   => true,
275
276
277
278
279
280
        ),
        'add' => array(
            'type'   => 'hidden',
            'value'  => true,
            'ignore' => !$add
        ),
281
282
283
        'inuse' => array(
            'type'   => 'hidden',
            'value'  => $inuse,
284
285
            'id'     => 'inuse',
            'ignore' => $add
286
        ),
287
288
289
290
291
292
293
294
295
296
297
298
        '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
299
300
            ),
            'help'   => true,
301
        ),
302
    );
303
    if ($USER->get('admin') && $institution != 'mahara') {
304
       $elements['expiry'] = array(
305
306
            'type'         => 'date',
            'title'        => get_string('institutionexpiry', 'admin'),
307
            'description'  => get_string('institutionexpirydescription', 'admin', hsc($sitename)),
308
309
310
311
            'defaultvalue' => is_null($data->expiry) ? null : strtotime($data->expiry),
            'help'         => true,
            'minyear'      => date('Y') - 2,
            'maxyear'      => date('Y') + 10,
312
313
        );
    }
314
315
    if ($USER->get('admin')) {
        $elements['authplugin'] = array(
316
317
318
319
320
            'type'    => 'authlist',
            'title'   => get_string('authplugin', 'admin'),
            'options' => $authinstances,
            'authtypes' => $authtypes,
            'instancearray' => $instancearray,
321
            'instancestring' => $instancestring,
322
323
            'institution' => $institution,
            'help'   => true,
324
            'ignore' => count($authtypes) == 0 || $institution == ''
325
326
327
        );
    }

328
    if (!$add && empty($authinstances)) {
329
        if ($USER->get('admin')) {
330
            $SESSION->add_error_msg(get_string('adminnoauthpluginforinstitution', 'admin'));
331
332
        }
        else {
333
            $SESSION->add_error_msg(get_string('noauthpluginforinstitution', 'admin'));
334
335
336
        }
    }

337
338
    if (!get_config('usersuniquebyusername')) {
        $elements['registerallowed'] = array(
339
            'type'         => 'switchbox',
340
            'title'        => get_string('registrationallowed', 'admin'),
341
            'description'  => get_string('registrationalloweddescription4', 'admin'),
342
343
344
            'defaultvalue' => $data->registerallowed,
            'help'   => true,
        );
345
        $elements['registerconfirm'] = array(
346
            'type'         => 'switchbox',
347
            'title'        => get_string('registrationconfirm', 'admin'),
348
            'description'  => get_string('registrationconfirmdescription2', 'admin'),
349
            'disabled'     => get_config('requireregistrationconfirm') == true,
350
351
            'defaultvalue' => $data->registerconfirm,
        );
352
    }
353

354
    // Some fields to hide from the default institution config screen
355
    if (empty($data->name) || $data->name != 'mahara') {
356
        $elements['defaultmembershipperiod'] = array(
357
            'type'         => 'expiry',
358
359
360
            'title'        => get_string('defaultmembershipperiod', 'admin'),
            'description'  => get_string('defaultmembershipperioddescription', 'admin'),
            'defaultvalue' => $data->defaultmembershipperiod,
Penny Leach's avatar
Penny Leach committed
361
            'help'   => true,
362
        );
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381

        $languages = get_languages();
        // Get the default language. If the institution has one stored, use that. Otherwise, use 'sitedefault'
        $defaultlang = false;
        if (!empty($data->name)) {
            $defaultlang = get_config_institution($data->name, 'lang');
        }
        // If the defaultlang they provided is no longer valid, use "site default"
        if (!$defaultlang || !array_key_exists($defaultlang, $languages)) {
            $defaultlang = 'sitedefault';
        }
        $elements['lang'] = array(
            'type' => 'select',
            'defaultvalue' => $defaultlang,
            'title' => get_string('institutionlanguage', 'admin'),
            'description' => get_string('institutionlanguagedescription', 'admin'),
            'options' => array_merge(array('sitedefault' => get_string('sitedefault', 'admin') . ' (' . $languages[get_config('lang')] . ')'), $languages),
            'ignore' => (count($languages) < 2),
        );
382
    }
383

384
385
386
387
388
389
390
391
392
393
394
    $elements['logo'] = array(
        'type'        => 'file',
        'title'       => get_string('Logo', 'admin'),
        'description' => get_string('logodescription', 'admin'),
        'maxfilesize' => get_max_upload_size(false),
    );
    if (!empty($data->logo)) {
        $logourl = get_config('wwwroot') . 'thumb.php?type=logobyid&id=' . $data->logo;
        $elements['logohtml'] = array(
            'type'        => 'html',
            'value'       => '<img src="' . $logourl . '" alt="' . get_string('Logo', 'admin') . '">',
395
        );
396
        $elements['deletelogo'] = array(
397
            'type'        => 'switchbox',
398
            'switchtext'  => 'yesno',
399
            'title'       => get_string('deletelogo', 'admin'),
400
            'description' => get_string('deletelogodescription1', 'admin'),
401
402
403
        );
    }
    if (empty($data->name) || $data->name != 'mahara') {
404
405
406
        if (!empty($data->style)) {
            $customtheme = get_records_menu('style_property', 'style', $data->style, '', 'field,value');
        }
407
        $elements['theme'] = array(
408
            'type'         => 'select',
409
            'title'        => get_string('theme'),
410
            'description'  => get_string('sitethemedescription','admin'),
411
            'defaultvalue' => $data->theme ? $data->theme : 'sitedefault',
412
413
414
            'collapseifoneoption' => true,
            'options'      => $themeoptions,
            'help'         => true,
415
        );
416
417
418
419
420
421
422
423
424
425
426
427
428
        $elements['customthemefs'] = array(
            'type'         => 'fieldset',
            'class'        => 'customtheme' . ($elements['theme']['defaultvalue'] != 'custom' ? ' js-hidden' : ''),
            'legend'       => get_string('customtheme', 'admin'),
            'elements'     => array(),
        );
        foreach ($customthemedefaults as $name => $styledata) {
            $elements['customthemefs']['elements'][$name] = array(
                'type'         => $styledata['type'],
                'title'        => get_string('customtheme.' . $name, 'admin'),
                'defaultvalue' => isset($customtheme[$name]) ? $customtheme[$name] : $styledata['value'],
            );
        }
429
        $elements['customthemefs']['elements']['resetcustom'] = array(
430
            'type'         => 'switchbox',
431
432
            'class'        => 'nojs-hidden-inline',
            'title'        => get_string('resetcolours', 'admin'),
433
            'description'  => get_string('resetcoloursdesc1', 'admin'),
434
        );
435
        $elements['dropdownmenu'] = array(
436
            'type'         => 'switchbox',
437
            'title'        => get_string('dropdownmenu', 'admin'),
438
            'description'  => get_string('dropdownmenudescriptioninstitution1','admin'),
439
440
441
            'defaultvalue' => $data->dropdownmenu,
            'help'         => true,
        );
442
443
444
445
    }
    // The skins checkbox should be shown for the default institution
    if (get_config('skins')) {
        $elements['skins'] = array(
446
            'type' => 'switchbox',
447
            'title' => get_string('skins', 'admin'),
448
            'description' => get_string('skinsinstitutiondescription1', 'admin'),
449
450
451
            'defaultvalue' => $data->skins,
        );
    }
452
453
454
455
456
457
458
459
460
461
    $elements['commentsortorder'] = array(
        'type' => 'select',
        'title' => get_string('commentsortorder', 'admin'),
        'description' => get_string('commentsortorderdescription', 'admin'),
        'defaultvalue' => $data->commentsortorder,
        'options' => array('earliest' => get_string('earliest'),
                           'latest' => get_string('latest'),
                          ),
        'help' => true,
    );
462
463
    // Some more fields that are hidden from the default institution
    if (empty($data->name) || $data->name != 'mahara') {
464
465
        $elements['showonlineusers'] = array(
            'type'                  => 'select',
466
            'disabled'              => get_config('showonlineuserssideblock') ? '' : 'disabled',
467
            'title'                 => get_string('showonlineusers', 'admin'),
468
            'description'           => get_string('showonlineusersdescription','admin'),
469
470
471
472
            'defaultvalue'          => $data->showonlineusers,
            'collapseifoneoption'   => true,
            'options'               => $showonlineusersoptions,
        );
473
474
        if (get_config('licensemetadata')) {
            $elements['licensemandatory'] = array(
475
                'type'         => 'switchbox',
476
                'title'        => get_string('licensemandatory', 'admin'),
477
                'description'  => get_string('licensemandatorydescription1','admin'),
478
479
480
481
482
483
484
485
486
                'defaultvalue' => $data->licensemandatory,
            );
            $elements['licensedefault'] = license_form_el_basic(null, true);
            $elements['licensedefault']['title'] = get_string('licensedefault','admin');
            $elements['licensedefault']['description'] = get_string('licensedefaultdescription','admin');
            if ($data->licensedefault) {
                $elements['licensedefault']['defaultvalue'] = $data->licensedefault;
            }
        }
487
488
489
490
491
492
493
        if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) {
            $elements['defaultquota'] = array(
               'type'         => 'bytes',
               'title'        => get_string('defaultquota', 'artefact.file'),
               'description'  => get_string('defaultinstitutionquotadescription', 'admin'),
               'defaultvalue' => !empty($data->defaultquota) ? $data->defaultquota : get_config_plugin('artefact', 'file', 'defaultquota'),
            );
494
            $elements['updateuserquotas'] = array(
495
                'type'         => 'switchbox',
496
                'title'        => get_string('updateuserquotas', 'artefact.file'),
497
                'description'  => get_string('updateinstitutionuserquotasdesc1', 'admin'),
498
            );
499
500
501
502
503
504
505
506
507
        }
        else {
            $elements['defaultquota'] = array(
                'type' => 'text',
                'title' => get_string('defaultquota', 'artefact.file'),
                'value' => display_size(!empty($data->defaultquota) ? $data->defaultquota : get_config_plugin('artefact', 'file', 'defaultquota')),
                'disabled' => true,
            );
        }
508
509

        $elements['allowinstitutionpublicviews'] = array(
510
            'type'         => 'switchbox',
511
            'title'        => get_string('allowinstitutionpublicviews', 'admin'),
512
            'description'  => get_string('allowinstitutionpublicviewsdescription1','admin'),
513
514
515
516
517
            'defaultvalue' => get_config('allowpublicviews') && $data->allowinstitutionpublicviews,
            'disabled'     => get_config('allowpublicviews') == false,
            'help'         => true,
        );

518
519
520
521
522
523
        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,
524
525
526
527
528
                'rules'        => array(
                    'regex'     => '/^\d*$/',
                    'maxlength' => 8,
                ),
                'size'         => 5,
529
530
            );
        }
531
    }
532

533
    $elements['lockedfields'] = array(
534
        'type' => 'fieldset',
535
        'legend' => get_string('Lockedfields', 'admin'),
536
537
538
        'collapsible' => true,
        'collapsed' => true,
        'elements' => array(),
539
    );
540
541
542
    if ($institution != 'mahara') {
        $elements['lockedfields']['elements']['description'] = array(
            'type' => 'html',
543
            'value' => get_string('disabledlockedfieldhelp1', 'admin', get_field('institution', 'displayname', 'name', 'mahara')),
544
545
        );
    }
546
    foreach (ArtefactTypeProfile::get_all_fields() as $field => $type) {
547
        $elements['lockedfields']['elements'][$field] = array(
548
            'type' => 'switchbox',
549
            'title' => get_string($field, 'artefact.internal'),
550
551
            'defaultvalue' => in_array($field, $lockedprofilefields) || ($institution != 'mahara' && in_array($field, $sitelockedfields)),
            'disabled' => $institution != 'mahara' && in_array($field, $sitelockedfields)
552
553
        );
    }
554
    $elements['lockedfieldshelp'] = array(
Evonne Cheung's avatar
Evonne Cheung committed
555
        'value' => '<tr id="lockedfieldshelp"><th colspan="2">'
556
        . get_help_icon('core', 'admin', 'institution', 'lockedfields')
557
558
559
        . '</th></tr>'
    );

560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
    // Check for active plugins institution settings.
    $elements['pluginsfields'] = array(
        'type' => 'fieldset',
        'legend' => get_string('pluginsfields', 'admin'),
        'collapsible' => true,
        'collapsed' => true,
        'elements' => array(),
    );

    // Get plugins institution settings.
    $instobj = null;
    if (!$add && $institution != '') {
        $instobj = new Institution();
        $instobj->findByName($institution);
    }
    $elements['pluginsfields']['elements'] = array_merge($elements['pluginsfields']['elements'],
            plugin_institution_prefs_form_elements($instobj));

    // Remove plugin fieldset if no fields.
    if (empty($elements['pluginsfields']['elements'])) {
        unset($elements['pluginsfields']);
    }

583
584
585
586
587
    $elements['submit'] = array(
        'type' => 'submitcancel',
        'value' => array(get_string('submit'), get_string('cancel'))
    );

588
    $institutionform = pieform(array(
589
        'name'     => 'institution',
Pat Kira's avatar
Pat Kira committed
590
        'renderer' => 'div',
Penny Leach's avatar
Penny Leach committed
591
592
        'plugintype' => 'core',
        'pluginname' => 'admin',
593
        'elements' => $elements
594
    ));
595
596
597
598

}
else {
    // Get a list of institutions
599
    require_once(get_config('libroot') . 'institution.php');
600
    if (!$USER->get('admin')) { // Filter the list for institutional admins
601
602
        $filter      = $USER->get('admininstitutions');
        $showdefault = false;
603
604
    }
    else {
605
606
        $filter      = false;
        $showdefault = true;
607
    }
608
    $data = build_institutions_html($filter, $showdefault, $query, $limit, $offset, $count);
609
610

    $smarty = smarty(array('lib/pieforms/static/core/pieforms.js', 'paginator'));
611
    setpageicon($smarty, 'icon-university');
612
613
614
615
616
    $smarty->assign('results', $data);
    $smarty->assign('countinstitutions', $count);

    /*search institution form*/
    $searchform = pieform(array(
617
618
619
        'name'   => 'search',
        'renderer' => 'div',
        'class' => 'form-inline mbl',
620
        'elements' => array(
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
            'inputgroup' => array(
                'type'  => 'fieldset',
                'title' => get_string('Query') . ': ',
                'class' => 'input-group form-inline',
                'elements'     => array(
                    'query' => array(
                        'type'  => 'text',
                        'defaultvalue' => $query,
                    ),
                    'submit' => array(
                        'type'  => 'button',
                        'usebuttontag' => true,
                        'class' => 'btn btn-success input-group-btn',
                        'value' => get_string('search'),
                    )
                ),
637
            ),
638
        ),
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
    ));
    $smarty->assign('searchform', $searchform);

    $js = <<< EOF
    addLoadEvent(function () {
    p = {$data['pagination_js']}
    connect('search_submit', 'onclick', function (event) {
        replaceChildNodes('messages');
        var params = {'query': $('search_query').value};
        p.sendQuery(params);
        event.stop();
        });
    });
EOF;

    $smarty->assign('INLINEJAVASCRIPT', $js);
655
656
657
658
    $smarty->assign('siteadmin', $USER->get('admin'));
    $smarty->assign('PAGEHEADING', get_string('admininstitutions', 'admin'));
    $smarty->display('admin/users/institutions.tpl');
    exit;
659
660
}

661
function institution_validate(Pieform $form, $values) {
662
663
    global $USER;

664
    if (!empty($values['name']) && !$form->get_error('name') && record_exists('institution', 'name', $values['name'])) {
665
666
        $form->set_error('name', get_string('institutionnamealreadytaken', 'admin'));
    }
667
668
669
670
    if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) {
        if (get_config_plugin('artefact', 'file', 'maxquotaenabled') && get_config_plugin('artefact', 'file', 'maxquota') < $values['defaultquota']) {
            $form->set_error('defaultquota', get_string('maxquotatoolow', 'artefact.file'));
        }
671
    }
672

673
674
    if (get_config('licensemetadata') && !empty($values['licensemandatory']) &&
        (isset($values['licensedefault']) && $values['licensedefault'] == '')) {
675
676
677
        $form->set_error('licensedefault', get_string('licensedefaultmandatory', 'admin'));
    }

678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
    // Check uploaded logo
    if (!empty($values['logo'])) {
        require_once('file.php');
        require_once('uploadmanager.php');
        $um = new upload_manager('logo');
        if ($error = $um->preprocess_file()) {
            $form->set_error('logo', $error);
            return false;
        }

        $imageinfo = getimagesize($values['logo']['tmp_name']);
        if (!$imageinfo || !is_image_type($imageinfo[2])) {
            $form->set_error('logo', get_string('filenotimage'));
            return false;
        }

        // Check the file isn't greater than the max allowable size
        $width          = $imageinfo[0];
        $height         = $imageinfo[1];
        $imagemaxwidth  = get_config('imagemaxwidth');
        $imagemaxheight = get_config('imagemaxheight');
        if ($width > $imagemaxwidth || $height > $imagemaxheight) {
            $form->set_error('logo', get_string('profileiconimagetoobig', 'artefact.file', $width, $height, $imagemaxwidth, $imagemaxheight));
        }
    }
703
704
705
706

    if (!empty($values['lang']) && $values['lang'] != 'sitedefault' && !array_key_exists($values['lang'], get_languages())) {
        $form->set_error('lang', get_string('institutionlanginvalid', 'admin'));
    }
707
708
709

    // Validate plugins settings.
    plugin_institution_prefs_validate($form, $values);
710
711
}

712
function institution_submit(Pieform $form, $values) {
713
    global $SESSION, $institution, $add, $instancearray, $USER, $authinstances, $customthemedefaults;
714
715
716
717

    db_begin();
    // Update the basic institution record...
    if ($add) {
718
719
720
        $newinstitution = new Institution();
        $newinstitution->initialise($values['name'], $values['displayname']);
        $institution = $newinstitution->name;
721
    }
722
    else {
723
724
        $newinstitution = new Institution($institution);
        $newinstitution->displayname = $values['displayname'];
725
726
        $oldinstitution = get_record('institution', 'name', $institution);
    }
727

728
    $newinstitution->showonlineusers              = !isset($values['showonlineusers']) ? 2 : $values['showonlineusers'];
729
    if (get_config('usersuniquebyusername')) {
Aaron Wells's avatar
Aaron Wells committed
730
731
        // Registering absolutely not allowed when this setting is on, it's a
        // security risk. See the documentation for the usersuniquebyusername
732
733
734
735
736
        // setting for more information
        $newinstitution->registerallowed = 0;
    }
    else {
        $newinstitution->registerallowed              = ($values['registerallowed']) ? 1 : 0;
737
        $newinstitution->registerconfirm              = ($values['registerconfirm']) ? 1 : 0;
738
    }
739
740
741
742
743
744
745
746
747
748

    if (!empty($values['lang'])) {
        if ($values['lang'] == 'sitedefault') {
            $newinstitution->lang = null;
        }
        else {
            $newinstitution->lang = $values['lang'];
        }
    }

749
750
    $newinstitution->theme                 = (empty($values['theme']) || $values['theme'] == 'sitedefault') ? null : $values['theme'];
    $newinstitution->dropdownmenu          = (!empty($values['dropdownmenu'])) ? 1 : 0;
751
    $newinstitution->skins                 = (!empty($values['skins'])) ? 1 : 0;
752
753
754
    require_once(get_config('docroot') . 'artefact/comment/lib.php');
    $commentoptions = ArtefactTypeComment::get_comment_options();
    $newinstitution->commentsortorder      = (empty($values['commentsortorder'])) ? $commentoptions->sort : $values['commentsortorder'];
755

756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
    if ($newinstitution->theme == 'custom') {
        if (!empty($oldinstitution->style)) {
            $styleid = $oldinstitution->style;
            delete_records('style_property', 'style', $styleid);
        }
        else {
            $record = (object) array('title' => get_string('customstylesforinstitution', 'admin', $newinstitution->displayname));
            $styleid = insert_record('style', $record, 'id', true);
        }

        $properties = array();
        $record = (object) array('style' => $styleid);
        foreach (array_keys($customthemedefaults) as $name) {
            $record->field = $name;
            $record->value = $values[$name];
            insert_record('style_property', $record);
            $properties[$name] = $values[$name];
        }

        // Cache the css
        $smarty = smarty_core();
        $smarty->assign('data', $properties);
        set_field('style', 'css', $smarty->fetch('customcss.tpl'), 'id', $styleid);

        $newinstitution->style = $styleid;
    }
    else {
        $newinstitution->style = null;
    }

786
    if (get_config('licensemetadata')) {
787
788
        $newinstitution->licensemandatory = (!empty($values['licensemandatory'])) ? 1 : 0;
        $newinstitution->licensedefault = (isset($values['licensedefault'])) ? $values['licensedefault'] : '';
789
790
    }

791
792
793
794
    if (!empty($values['resetcustom']) && !empty($oldinstitution->style)) {
        $newinstitution->style = null;
    }

795
    if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) {
796
797
798
799
800
        if (!empty($values['updateuserquotas']) && !empty($values['defaultquota'])) {
            execute_sql(
                "UPDATE {usr} SET quota = ? WHERE id IN (SELECT usr FROM {usr_institution} WHERE institution = ?)",
                array($values['defaultquota'], $institution)
            );
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
            // get all the users from the institution and make sure that they are still below
            // their quota threshold
            if ($users = get_records_sql_array('SELECT * FROM {usr} u LEFT JOIN {usr_institution} ui ON u.id = ui.usr AND ui.institution = ?', array($institution))) {
                $quotanotifylimit = get_config_plugin('artefact', 'file', 'quotanotifylimit');
                if ($quotanotifylimit <= 0 || $quotanotifylimit >= 100) {
                    $quotanotifylimit = 100;
                }
                foreach ($users as $user) {
                    $user->quota = $values['defaultquota'];
                    // check if the user has gone over the quota notify limit
                    $user->quotausedpercent = $user->quotaused / $user->quota * 100;
                    $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);
                    }
                }
            }
828
        }
829
        $newinstitution->defaultquota = empty($values['defaultquota']) ? get_config_plugin('artefact', 'file', 'defaultquota') : $values['defaultquota'];
830
    }
831
832
833
834
    if ($institution != 'mahara') {
        $newinstitution->defaultmembershipperiod  = ($values['defaultmembershipperiod']) ? intval($values['defaultmembershipperiod']) : null;
        if ($USER->get('admin')) {
            $newinstitution->maxuseraccounts      = ($values['maxuseraccounts']) ? intval($values['maxuseraccounts']) : null;
835
            $newinstitution->expiry               = db_format_timestamp($values['expiry']);
836
        }
837
838
    }

839
840
    $newinstitution->allowinstitutionpublicviews  = (isset($values['allowinstitutionpublicviews']) && $values['allowinstitutionpublicviews']) ? 1 : 0;

841
    // TODO: Move handling of authentication instances within the Institution class as well?
842
843
    if (!empty($values['authplugin'])) {
        $allinstances = array_merge($values['authplugin']['instancearray'], $values['authplugin']['deletearray']);
844

845
        if (array_diff($allinstances, $instancearray)) {
846
            throw new ConfigException('Attempt to delete or update another institution\'s auth instance');
847
        }
848

849
        if (array_diff($instancearray, $allinstances)) {
850
            throw new ConfigException('One of your instances is unaccounted for in this transaction');
851
852
        }

853
854
855
        foreach($values['authplugin']['instancearray'] as $priority => $instanceid) {
            if (in_array($instanceid, $values['authplugin']['deletearray'])) {
                // Should never happen:
856
                throw new SystemException('Attempt to update AND delete an auth instance');
857
858
859
860
861
862
863
864
            }
            $record = new StdClass;
            $record->priority = $priority;
            $record->id = $instanceid;
            update_record('auth_instance', $record,  array('id' => $instanceid));
        }

        foreach($values['authplugin']['deletearray'] as $instanceid) {
865
866
867
868
            // 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
869
870
                    $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) {
871
872
873
874
875
876
877
878
879
                        // 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;
                }
            }
880
881
882
            delete_records('auth_remote_user', 'authinstance', $instanceid);
            delete_records('auth_instance_config', 'instance', $instanceid);
            delete_records('auth_instance', 'id', $instanceid);
883
884
            // Make it no longer be the parent authority to any auth instances
            delete_records('auth_instance_config', 'field', 'parent', 'value', $instanceid);
885
        }
886
887
    }

888
889
890
    // Store plugin settings.
    plugin_institution_prefs_submit($form, $values, $newinstitution);

891
892
893
    // Save the changes to the DB
    $newinstitution->commit();

894
    if ($add) {
895
896
897
898
899
900
901
902
903
        // Automatically create an internal authentication authinstance
        $authinstance = (object)array(
            'instancename' => 'internal',
            'priority'     => 0,
            'institution'  => $newinstitution->name,
            'authname'     => 'internal',
        );
        insert_record('auth_instance', $authinstance);

904
        // We need to add the default lines to the site_content table for this institution
905
        // We also need to set the institution to be using default static pages to begin with
906
907
908
909
910
911
912
913
        // so that using custom institution pages is an opt-in situation
        $pages = site_content_pages();
        $now = db_format_timestamp(time());
        foreach ($pages as $name) {
            $page = new stdClass();
            $page->name = $name;
            $page->ctime = $now;
            $page->mtime = $now;
914
            $page->content = get_string($page->name . 'defaultcontent', 'install', get_string('staticpageconfiginstitution', 'install'));
915
916
917
918
919
920
921
922
923
            $page->institution = $newinstitution->name;
            insert_record('site_content', $page);

            $institutionconfig = new stdClass();
            $institutionconfig->institution = $newinstitution->name;
            $institutionconfig->field = 'sitepages_' . $name;
            $institutionconfig->value = 'mahara';
            insert_record('institution_config', $institutionconfig);
        }
924
925
    }

926
927
928
929
930
    if (is_null($newinstitution->style) && !empty($oldinstitution->style)) {
        delete_records('style_property', 'style', $oldinstitution->style);
        delete_records('style', 'id', $oldinstitution->style);
    }

931
932
    // Set the logo after updating the institution, because the institution
    // needs to exist before it can own the logo artefact.
933
    if (!empty($values['logo'])) {
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
        safe_require('artefact', 'file');

        // Entry in artefact table
        $data = (object) array(
            'institution' => $institution,
            'title'       => 'logo',
            'description' => 'Institution logo',
            'note'        => $values['logo']['name'],
            'size'        => $values['logo']['size'],
        );

        $imageinfo      = getimagesize($values['logo']['tmp_name']);
        $data->width    = $imageinfo[0];
        $data->height   = $imageinfo[1];
        $data->filetype = $imageinfo['mime'];
        $artefact = new ArtefactTypeProfileIcon(0, $data);
        if (preg_match("/\.([^\.]+)$/", $values['logo']['name'], $saved)) {
            $artefact->set('oldextension', $saved[1]);
        }
        $artefact->commit();

        $id = $artefact->get('id');

        // Move the file into the correct place.
        $directory = get_config('dataroot') . 'artefact/file/profileicons/originals/' . ($id % 256) . '/';
        check_dir_exists($directory);
        move_uploaded_file($values['logo']['tmp_name'], $directory . $id);

        // Delete the old logo
        if (!empty($oldinstitution->logo)) {
            $oldlogo = new ArtefactTypeProfileIcon($oldinstitution->logo);
            $oldlogo->delete();
        }

        set_field('institution', 'logo', $id, 'name', $institution);
    }

971
972
973
974
    if (!empty($values['deletelogo'])) {
        execute_sql("UPDATE {institution} SET logo = NULL WHERE name = ?", array($institution));
    }

975
976
977
978
979
980
981
982
983
984
985
    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();

986
    if ($add) {
987
        if (!$newinstitution->registerallowed) {
Aaron Wells's avatar
Aaron Wells committed
988
989
            // If registration is not allowed, then an authinstance will not
            // have been created, and thus cause the institution page to add
990
991
992
            // its own error message on the next page load
            $SESSION->add_ok_msg(get_string('institutionaddedsuccessfully2', 'admin'));
        }
993
994
995
        $nexturl = '/admin/users/institutions.php?i='.urlencode($institution);
    }
    else {
996
        $message = get_string('institutionupdatedsuccessfully', 'admin');
997
998
999
1000
1001
1002
        if (isset($values['theme'])) {
            $changedtheme = $oldinstitution->theme != $values['theme']
                && (!empty($oldinstitution->theme) || $values['theme'] != 'sitedefault');
            if ($changedtheme || $values['theme'] == 'custom') {
                $message .= '  ' . get_string('usersseenewthemeonlogin', 'admin');
            }
1003
            $USER->reset_institutions();
1004
        }
1005
        $SESSION->add_ok_msg($message);
1006
1007
1008
1009
        $nexturl = '/admin/users/institutions.php';
    }

    redirect($nexturl);
1010
1011
1012
}

function institution_cancel_submit() {
1013
    redirect('/admin/users/institutions.php');
1014
1015
}

1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
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 {
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
                // Need to logout any users that are using this institution's authinstance.
                if ($loggedin = get_records_sql_array("SELECT ui.usr FROM {usr_institution} ui
                    JOIN {usr} u ON u.id = ui.usr
                    JOIN {auth_instance} ai ON ai.id = u.authinstance
                    JOIN {usr_session} us ON us.usr = u.id
                    WHERE ui.institution = ?
                    AND ai.institution = ?", array($values['i'], $values['i']))) {
                    foreach ($loggedin as $user) {
                        $loggedinarray[] = $user->usr;
                    }
                    delete_records_sql("DELETE FROM {usr_session} WHERE usr IN (" . join(',', $loggedinarray) . ")");
                    $SESSION->add_ok_msg(get_string('institutionlogoutusers', 'admin', count($loggedin)));
                }
1039
1040
1041
1042
                set_field('institution', 'suspended', 1, 'name', $values['i']);
                $SESSION->add_ok_msg(get_string('institutionsuspended', 'admin'));
            }
            redirect('/admin/users/institutions.php?i=' . $values['i']);
1043
        }
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054

        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']);
1055
        }
1056

1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
        // 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);
1077
1078
        }
        else {
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
            $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';