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
$customthemedefaults = array(
33
    'background'   => array('type' => 'color', 'value' => '#530E53'),
34
    'backgroundfg' => array('type' => 'color', 'value' => '#FFFFFF'),
35
36
37
    'link'         => array('type' => 'color', 'value' => '#255ECC'),
    'headings'     => array('type' => 'color', 'value' => '#530E53'),
    'navbg'        => array('type' => 'color', 'value' => '#8A458A'),
38
39
40
    'navfg'        => array('type' => 'color', 'value' => '#FFFFFF'),
);

41
42
43
44
45
46
47
48
49
50
51
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='
52
                 . key($USER->get('admininstitutions')));
53
54
55
    }
}

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

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

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

90
        function delete_cancel_submit() {
91
            redirect('/admin/users/institutions.php');
92
93
        }

94
        function delete_submit(Pieform $form, $values) {
95
96
            global $SESSION;

97
            $authinstanceids = get_column('auth_instance', 'id', 'institution', $values['i']);
98
            $collectionids = get_column('collection', 'id', 'institution', $values['i']);
99
100
            $viewids = get_column('view', 'id', 'institution', $values['i']);
            $artefactids = get_column('artefact', 'id', 'institution', $values['i']);
101
            $regdataids = get_column('institution_registration', 'id', 'institution', $values['i']);
102

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

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

142
143
144
            foreach ($authinstanceids as $id) {
                delete_records('auth_instance_config', 'instance', $id);
            }
145

146
147
148
149
            foreach ($regdataids as $id) {
                delete_records('institution_registration_data', 'registration_id', $id);
            }

150
151
152
153
154
            // 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']);

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

            $SESSION->add_ok_msg(get_string('institutiondeletedsuccessfully', 'admin'));
171
            redirect('/admin/users/institutions.php');
172
173
174
175
176
177
178
179
180
181
182
183
184
185
        }
        $form = array(
            'name' => 'delete',
            'elements' => array(
                'i' => array(
                    'type' => 'hidden',
                    'value' => $institution
                ),
                'delete' => array(
                    'type' => 'hidden',
                    'value' => 1
                ),
                'submit' => array(
                    'type' => 'submitcancel',
186
                    'class' => 'btn-default',
187
188
189
190
                    'value' => array(get_string('yes'), get_string('no'))
                )
            )
        );
191
192
193
        $deleteform = pieform($form);
        $smarty = smarty();
        $smarty->assign('delete_form', $deleteform);
194
        $smarty->assign('institutionname', get_field('institution', 'displayname', 'name', $institution));
195
        $smarty->display('admin/users/institutions.tpl');
196
197
198
        exit;
    }

199
200
201
    $instancearray = array();
    $instancestring = '';
    $c = count($authinstances);
202
    $inuse = '';
203

204
205
    $sitelockedfields = (array) get_column('institution_locked_profile_field', 'profilefield', 'name', 'mahara');

206
207
    if (!$add) {
        $data = get_record('institution', 'name', $institution);
208
        $data->commentsortorder = get_config_institution($institution, 'commentsortorder');
Aaron Wells's avatar
Aaron Wells committed
209
        $data->commentthreaded = get_config_institution($institution, 'commentthreaded');
210
        $lockedprofilefields = (array) get_column('institution_locked_profile_field', 'profilefield', 'name', $institution);
211

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

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

        $authtypes = auth_get_available_auth_types();
252
    }
253
    $themeoptions = get_institution_themes($institution);
254
    $themeoptions['sitedefault'] = '- ' . get_string('sitedefault', 'admin') . ' (' . $themeoptions[get_config('theme')] . ') -';
255
    uksort($themeoptions, 'theme_sort');
256
257
258
    if (validate_theme($data->theme, $institution) === false) {
        $data->theme = 'sitedefault';
    }
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
265
266
267
268
    $elements = array(
        'add' => array(
            'type'   => 'hidden',
            'value'  => true,
            'ignore' => !$add
        ),
269
270
271
        'inuse' => array(
            'type'   => 'hidden',
            'value'  => $inuse,
272
273
            'id'     => 'inuse',
            'ignore' => $add
274
        ),
275
276
277
278
279
280
281
        'i' => array(
            'type'   => 'hidden',
            'value'  => $institution,
            'ignore' => $add
        ),
        'displayname' => array(
            'type' => 'text',
282
            'title' => get_string('institutionname', 'admin'),
283
284
285
286
            'defaultvalue' => $data->displayname,
            'rules' => array(
                'required'  => true,
                'maxlength' => 255
Penny Leach's avatar
Penny Leach committed
287
288
            ),
            'help'   => true,
289
        ),
290
    );
291
    if ($USER->get('admin') && $institution != 'mahara') {
292
       $elements['expiry'] = array(
293
294
            'type'         => 'date',
            'title'        => get_string('institutionexpiry', 'admin'),
295
            'description'  => get_string('institutionexpirydescription', 'admin', hsc($sitename)),
296
297
298
299
            'defaultvalue' => is_null($data->expiry) ? null : strtotime($data->expiry),
            'help'         => true,
            'minyear'      => date('Y') - 2,
            'maxyear'      => date('Y') + 10,
300
301
        );
    }
302
303
    if ($USER->get('admin')) {
        $elements['authplugin'] = array(
304
305
306
307
308
            'type'    => 'authlist',
            'title'   => get_string('authplugin', 'admin'),
            'options' => $authinstances,
            'authtypes' => $authtypes,
            'instancearray' => $instancearray,
309
            'instancestring' => $instancestring,
310
311
            'institution' => $institution,
            'help'   => true,
312
            'ignore' => count($authtypes) == 0 || $institution == ''
313
314
315
        );
    }

316
    if (!$add && empty($authinstances)) {
317
        if ($USER->get('admin')) {
318
            $SESSION->add_error_msg(get_string('adminnoauthpluginforinstitution', 'admin'));
319
320
        }
        else {
321
            $SESSION->add_error_msg(get_string('noauthpluginforinstitution', 'admin'));
322
323
324
        }
    }

325
326
    if (!get_config('usersuniquebyusername')) {
        $elements['registerallowed'] = array(
327
            'type'         => 'switchbox',
328
            'title'        => get_string('registrationallowed', 'admin'),
329
            'description'  => get_string('registrationalloweddescription4', 'admin'),
330
331
332
            'defaultvalue' => $data->registerallowed,
            'help'   => true,
        );
333
        $elements['registerconfirm'] = array(
334
            'type'         => 'switchbox',
335
            'title'        => get_string('registrationconfirm', 'admin'),
336
            'description'  => get_string('registrationconfirmdescription2', 'admin'),
337
            'disabled'     => get_config('requireregistrationconfirm') == true,
338
339
            'defaultvalue' => $data->registerconfirm,
        );
340
    }
341

342
    // Some fields to hide from the default institution config screen
343
    if (empty($data->name) || $data->name != 'mahara') {
344
        $elements['defaultmembershipperiod'] = array(
345
            'type'         => 'expiry',
346
347
348
            'title'        => get_string('defaultmembershipperiod', 'admin'),
            'description'  => get_string('defaultmembershipperioddescription', 'admin'),
            'defaultvalue' => $data->defaultmembershipperiod,
Penny Leach's avatar
Penny Leach committed
349
            'help'   => true,
350
        );
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369

        $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),
        );
370
    }
371

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

        $elements['allowinstitutionpublicviews'] = array(
503
            'type'         => 'switchbox',
504
            'title'        => get_string('allowinstitutionpublicviews', 'admin'),
505
            'description'  => get_string('allowinstitutionpublicviewsdescription1','admin'),
506
507
508
509
510
            'defaultvalue' => get_config('allowpublicviews') && $data->allowinstitutionpublicviews,
            'disabled'     => get_config('allowpublicviews') == false,
            'help'         => true,
        );

511
512
513
514
515
516
        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,
517
518
519
520
521
                'rules'        => array(
                    'regex'     => '/^\d*$/',
                    'maxlength' => 8,
                ),
                'size'         => 5,
522
523
            );
        }
524
    }
525

526
    $elements['lockedfields'] = array(
527
        'type' => 'fieldset',
Pat Kira's avatar
Pat Kira committed
528
        'class' => 'last with-formgroup',
529
        'legend' => get_string('Lockedfields', 'admin'),
530
531
532
        'collapsible' => true,
        'collapsed' => true,
        'elements' => array(),
533
    );
534
535
536
    if ($institution != 'mahara') {
        $elements['lockedfields']['elements']['description'] = array(
            'type' => 'html',
537
            'value' => get_string('disabledlockedfieldhelp1', 'admin', get_field('institution', 'displayname', 'name', 'mahara')),
538
539
        );
    }
540
    foreach (ArtefactTypeProfile::get_all_fields() as $field => $type) {
541
        $elements['lockedfields']['elements'][$field] = array(
542
            'type' => 'switchbox',
543
            'title' => get_string($field, 'artefact.internal'),
544
545
            'defaultvalue' => in_array($field, $lockedprofilefields) || ($institution != 'mahara' && in_array($field, $sitelockedfields)),
            'disabled' => $institution != 'mahara' && in_array($field, $sitelockedfields)
546
547
        );
    }
548

549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
    // 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']);
    }

572
573
    $elements['submit'] = array(
        'type' => 'submitcancel',
574
        'class' => 'btn-primary',
575
576
577
        'value' => array(get_string('submit'), get_string('cancel'))
    );

578
    $institutionform = pieform(array(
579
        'name'     => 'institution',
Pat Kira's avatar
Pat Kira committed
580
        'renderer' => 'div',
Penny Leach's avatar
Penny Leach committed
581
582
        'plugintype' => 'core',
        'pluginname' => 'admin',
583
        'elements' => $elements
584
    ));
585
586
587
588

}
else {
    // Get a list of institutions
589
    require_once(get_config('libroot') . 'institution.php');
590
    if (!$USER->get('admin')) { // Filter the list for institutional admins
591
592
        $filter      = $USER->get('admininstitutions');
        $showdefault = false;
593
594
    }
    else {
595
596
        $filter      = false;
        $showdefault = true;
597
    }
598
    $data = build_institutions_html($filter, $showdefault, $query, $limit, $offset, $count);
599
600

    $smarty = smarty(array('lib/pieforms/static/core/pieforms.js', 'paginator'));
601
    setpageicon($smarty, 'icon-university');
602
603
604
605
606
    $smarty->assign('results', $data);
    $smarty->assign('countinstitutions', $count);

    /*search institution form*/
    $searchform = pieform(array(
607
608
        'name'   => 'search',
        'renderer' => 'div',
Naomi Guyer's avatar
Naomi Guyer committed
609
        'class' => 'form-inline with-heading',
610
        'autofocus' => false,
611
        'elements' => array(
612
613
614
615
616
617
618
619
            'inputgroup' => array(
                'type'  => 'fieldset',
                'title' => get_string('Query') . ': ',
                'class' => 'input-group form-inline',
                'elements'     => array(
                    'query' => array(
                        'type'  => 'text',
                        'defaultvalue' => $query,
620
621
622
623
                        'hiddenlabel' => true,
                        'value' => get_string('search'),
                        'class' => 'emptyonfocus',
                        'title' => get_string('search'),
624
625
626
627
                    ),
                    'submit' => array(
                        'type'  => 'button',
                        'usebuttontag' => true,
628
                        'class' => 'btn-primary input-group-btn',
629
630
631
                        'value' => get_string('search'),
                    )
                ),
632
            ),
633
        ),
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
    ));
    $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);
650
651
652
653
    $smarty->assign('siteadmin', $USER->get('admin'));
    $smarty->assign('PAGEHEADING', get_string('admininstitutions', 'admin'));
    $smarty->display('admin/users/institutions.tpl');
    exit;
654
655
}

656
function institution_validate(Pieform $form, $values) {
657
    global $USER, $institution, $add;
658

659
660
661
662
    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'));
        }
663
    }
664

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

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

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

    // Validate plugins settings.
    plugin_institution_prefs_validate($form, $values);
702
703
}

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

    db_begin();
    // Update the basic institution record...
    if ($add) {
710
        $institution = generate_institution_name($values['displayname']);
711
        $newinstitution = new Institution();
712
        $newinstitution->initialise($institution, $values['displayname']);
713
        $institution = $newinstitution->name;
714
    }
715
    else {
716
717
        $newinstitution = new Institution($institution);
        $newinstitution->displayname = $values['displayname'];
718
        $oldinstitution = get_record('institution', 'name', $institution);
719
720
        // Clear out any cached menus for this institution
        clear_menu_cache($institution);
721
    }
722

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

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

744
745
    $newinstitution->theme                 = (empty($values['theme']) || $values['theme'] == 'sitedefault') ? null : $values['theme'];
    $newinstitution->dropdownmenu          = (!empty($values['dropdownmenu'])) ? 1 : 0;
746
    $newinstitution->skins                 = (!empty($values['skins'])) ? 1 : 0;
747
748
749
    require_once(get_config('docroot') . 'artefact/comment/lib.php');
    $commentoptions = ArtefactTypeComment::get_comment_options();
    $newinstitution->commentsortorder      = (empty($values['commentsortorder'])) ? $commentoptions->sort : $values['commentsortorder'];
Aaron Wells's avatar
Aaron Wells committed
750
    $newinstitution->commentthreaded       = (!empty($values['commentthreaded'])) ? 1 : 0;
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
776
777
778
779
780
781
    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;
    }

782
    if (get_config('licensemetadata')) {
783
784
        $newinstitution->licensemandatory = (!empty($values['licensemandatory'])) ? 1 : 0;
        $newinstitution->licensedefault = (isset($values['licensedefault'])) ? $values['licensedefault'] : '';
785
786
    }

787
788
789
790
    if (!empty($values['resetcustom']) && !empty($oldinstitution->style)) {
        $newinstitution->style = null;
    }

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

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

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

841
        if (array_diff($allinstances, $instancearray)) {
842
            throw new ConfigException('Attempt to delete or update another institution\'s auth instance');
843
        }
844

845
        if (array_diff($instancearray, $allinstances)) {
846
            throw new ConfigException('One of your instances is unaccounted for in this transaction');
847
848
        }

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

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

884
885
886
    // Store plugin settings.
    plugin_institution_prefs_submit($form, $values, $newinstitution);

887
888
889
    // Save the changes to the DB
    $newinstitution->commit();

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

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

922
923
924
925
926
    if (is_null($newinstitution->style) && !empty($oldinstitution->style)) {
        delete_records('style_property', 'style', $oldinstitution->style);
        delete_records('style', 'id', $oldinstitution->style);
    }

927
928
    // Set the logo after updating the institution, because the institution
    // needs to exist before it can own the logo artefact.
929
    if (!empty($values['logo'])) {
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
961
962
963
964
965
966
        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);
    }

967
968
969
970
    if (!empty($values['deletelogo'])) {
        execute_sql("UPDATE {institution} SET logo = NULL WHERE name = ?", array($institution));
    }

971
972
973
974
975
976
977
978
979
980
981
    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();

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

    redirect($nexturl);
1006
1007
1008
}

function institution_cancel_submit() {
1009
    redirect('/admin/users/institutions.php');
1010
1011
}

1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
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 {
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
                // 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;