institutions.php 49.3 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
$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'),
);

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

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

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

68
    if ($delete) {
69
        function delete_validate(Pieform $form, $values) {
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
            // 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))
                        );
                    }
                }
92
93
94
            }
        }

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

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

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

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

            // 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
                );
            }

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

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

155
156
157
158
159
            // 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']);

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

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

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

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

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

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

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

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

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

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

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

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

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

        $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),
        );
381
    }
382

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

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

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

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

559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
    // 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']);
    }

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

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

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

    $smarty = smarty(array('lib/pieforms/static/core/pieforms.js', 'paginator'));
610
611
612
613
614
615
616
617
618
619
620
621
622
623
    $smarty->assign('results', $data);
    $smarty->assign('countinstitutions', $count);

    /*search institution form*/
    $searchform = pieform(array(
        'name' => 'search',
        'renderer' => 'oneline',
        'elements' => array(
            'query' => array(
                'type' => 'text',
                'defaultvalue' => $query
            ),
            'submit' => array(
                'type' => 'submit',
Pat Kira's avatar
Pat Kira committed
624
                'class' => 'btn btn-success',
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
                'value' => get_string('search')
            )
        )
    ));
    $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);
644
    $smarty->assign('siteadmin', $USER->get('admin'));
Naomi Guyer's avatar
Naomi Guyer committed
645
    $smarty->assign('PAGEICON', 'fa fa-university');
646
647
648
    $smarty->assign('PAGEHEADING', get_string('admininstitutions', 'admin'));
    $smarty->display('admin/users/institutions.tpl');
    exit;
649
650
}

651
function institution_validate(Pieform $form, $values) {
652
653
    global $USER;

654
    if (!empty($values['name']) && !$form->get_error('name') && record_exists('institution', 'name', $values['name'])) {
655
656
        $form->set_error('name', get_string('institutionnamealreadytaken', 'admin'));
    }
657
658
659
660
    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'));
        }
661
    }
662

663
664
    if (get_config('licensemetadata') && !empty($values['licensemandatory']) &&
        (isset($values['licensedefault']) && $values['licensedefault'] == '')) {
665
666
667
        $form->set_error('licensedefault', get_string('licensedefaultmandatory', 'admin'));
    }

668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
    // 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));
        }
    }
693
694
695
696

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

    // Validate plugins settings.
    plugin_institution_prefs_validate($form, $values);
700
701
}

702
function institution_submit(Pieform $form, $values) {
703
    global $SESSION, $institution, $add, $instancearray, $USER, $authinstances, $customthemedefaults;
704
705
706
707

    db_begin();
    // Update the basic institution record...
    if ($add) {
708
709
710
        $newinstitution = new Institution();
        $newinstitution->initialise($values['name'], $values['displayname']);
        $institution = $newinstitution->name;
711
    }
712
    else {
713
714
        $newinstitution = new Institution($institution);
        $newinstitution->displayname = $values['displayname'];
715
716
        $oldinstitution = get_record('institution', 'name', $institution);
    }
717

718
    $newinstitution->showonlineusers              = !isset($values['showonlineusers']) ? 2 : $values['showonlineusers'];
719
    if (get_config('usersuniquebyusername')) {
Aaron Wells's avatar
Aaron Wells committed
720
721
        // Registering absolutely not allowed when this setting is on, it's a
        // security risk. See the documentation for the usersuniquebyusername
722
723
724
725
726
        // setting for more information
        $newinstitution->registerallowed = 0;
    }
    else {
        $newinstitution->registerallowed              = ($values['registerallowed']) ? 1 : 0;
727
        $newinstitution->registerconfirm              = ($values['registerconfirm']) ? 1 : 0;
728
    }
729
730
731
732
733
734
735
736
737
738

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

739
740
    $newinstitution->theme                 = (empty($values['theme']) || $values['theme'] == 'sitedefault') ? null : $values['theme'];
    $newinstitution->dropdownmenu          = (!empty($values['dropdownmenu'])) ? 1 : 0;
741
    $newinstitution->skins                 = (!empty($values['skins'])) ? 1 : 0;
742
743
744
    require_once(get_config('docroot') . 'artefact/comment/lib.php');
    $commentoptions = ArtefactTypeComment::get_comment_options();
    $newinstitution->commentsortorder      = (empty($values['commentsortorder'])) ? $commentoptions->sort : $values['commentsortorder'];
745

746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
    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;
    }

776
    if (get_config('licensemetadata')) {
777
778
        $newinstitution->licensemandatory = (!empty($values['licensemandatory'])) ? 1 : 0;
        $newinstitution->licensedefault = (isset($values['licensedefault'])) ? $values['licensedefault'] : '';
779
780
    }

781
782
783
784
    if (!empty($values['resetcustom']) && !empty($oldinstitution->style)) {
        $newinstitution->style = null;
    }

785
    if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) {
786
787
788
789
790
        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)
            );
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
            // 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);
                    }
                }
            }
818
        }
819
        $newinstitution->defaultquota = empty($values['defaultquota']) ? get_config_plugin('artefact', 'file', 'defaultquota') : $values['defaultquota'];
820
    }
821
822
823
824
    if ($institution != 'mahara') {
        $newinstitution->defaultmembershipperiod  = ($values['defaultmembershipperiod']) ? intval($values['defaultmembershipperiod']) : null;
        if ($USER->get('admin')) {
            $newinstitution->maxuseraccounts      = ($values['maxuseraccounts']) ? intval($values['maxuseraccounts']) : null;
825
            $newinstitution->expiry               = db_format_timestamp($values['expiry']);
826
        }
827
828
    }

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

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

835
        if (array_diff($allinstances, $instancearray)) {
836
            throw new ConfigException('Attempt to delete or update another institution\'s auth instance');
837
        }
838

839
        if (array_diff($instancearray, $allinstances)) {
840
            throw new ConfigException('One of your instances is unaccounted for in this transaction');
841
842
        }

843
844
845
        foreach($values['authplugin']['instancearray'] as $priority => $instanceid) {
            if (in_array($instanceid, $values['authplugin']['deletearray'])) {
                // Should never happen:
846
                throw new SystemException('Attempt to update AND delete an auth instance');
847
848
849
850
851
852
853
854
            }
            $record = new StdClass;
            $record->priority = $priority;
            $record->id = $instanceid;
            update_record('auth_instance', $record,  array('id' => $instanceid));
        }

        foreach($values['authplugin']['deletearray'] as $instanceid) {
855
856
857
858
            // 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
859
860
                    $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) {
861
862
863
864
865
866
867
868
869
                        // 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;
                }
            }
870
871
872
            delete_records('auth_remote_user', 'authinstance', $instanceid);
            delete_records('auth_instance_config', 'instance', $instanceid);
            delete_records('auth_instance', 'id', $instanceid);
873
874
            // Make it no longer be the parent authority to any auth instances
            delete_records('auth_instance_config', 'field', 'parent', 'value', $instanceid);
875
        }
876
877
    }

878
879
880
    // Store plugin settings.
    plugin_institution_prefs_submit($form, $values, $newinstitution);

881
882
883
    // Save the changes to the DB
    $newinstitution->commit();

884
    if ($add) {
885
886
887
888
889
890
891
892
893
        // Automatically create an internal authentication authinstance
        $authinstance = (object)array(
            'instancename' => 'internal',
            'priority'     => 0,
            'institution'  => $newinstitution->name,
            'authname'     => 'internal',
        );
        insert_record('auth_instance', $authinstance);

894
        // We need to add the default lines to the site_content table for this institution
895
        // We also need to set the institution to be using default static pages to begin with
896
897
898
899
900
901
902
903
        // 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;
904
            $page->content = get_string($page->name . 'defaultcontent', 'install', get_string('staticpageconfiginstitution', 'install'));
905
906
907
908
909
910
911
912
913
            $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);
        }
914
915
    }

916
917
918
919
920
    if (is_null($newinstitution->style) && !empty($oldinstitution->style)) {
        delete_records('style_property', 'style', $oldinstitution->style);
        delete_records('style', 'id', $oldinstitution->style);
    }

921
922
    // Set the logo after updating the institution, because the institution
    // needs to exist before it can own the logo artefact.
923
    if (!empty($values['logo'])) {
924
925
926
927
928
929
930
931
932
933
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
        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);
    }

961
962
963
964
    if (!empty($values['deletelogo'])) {
        execute_sql("UPDATE {institution} SET logo = NULL WHERE name = ?", array($institution));
    }

965
966
967
968
969
970
971
972
973
974
975
    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();

976
    if ($add) {
977
        if (!$newinstitution->registerallowed) {
Aaron Wells's avatar
Aaron Wells committed
978
979
            // If registration is not allowed, then an authinstance will not
            // have been created, and thus cause the institution page to add
980
981
982
            // its own error message on the next page load
            $SESSION->add_ok_msg(get_string('institutionaddedsuccessfully2', 'admin'));
        }
983
984
985
        $nexturl = '/admin/users/institutions.php?i='.urlencode($institution);
    }
    else {
986
        $message = get_string('institutionupdatedsuccessfully', 'admin');
987
988
989
990
991
992
        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');
            }
993
            $USER->reset_institutions();
994
        }
995
        $SESSION->add_ok_msg($message);
996
997
998
999
        $nexturl = '/admin/users/institutions.php';
    }

    redirect($nexturl);
1000
1001
1002
}

function institution_cancel_submit() {
1003
    redirect('/admin/users/institutions.php');
1004
1005
}

1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
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 {
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
                // 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)));
                }
1029
1030
1031
1032
                set_field('institution', 'suspended', 1, 'name', $values['i']);
                $SESSION->add_ok_msg(get_string('institutionsuspended', 'admin'));
            }
            redirect('/admin/users/institutions.php?i=' . $values['i']);
1033
        }
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044

        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']);
1045
        }
1046

1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066