MDL-11432 eliminated majority of RecordCount uses, added several missing rs_close...
[moodle.git] / lib / adminlib.php
CommitLineData
a4e10845 1<?php
88a7228a 2
3/**
4 * adminlib.php - Contains functions that only administrators will ever need to use
5 *
a4e10845 6 * @author Martin Dougiamas and many others
88a7228a 7 * @version $Id$
8 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
9 * @package moodlecore
10 */
11
12/**
ead29342 13 * Upgrade plugins
88a7228a 14 *
15 * @uses $db
16 * @uses $CFG
ead29342 17 * @param string $type The type of plugins that should be updated (e.g. 'enrol', 'qtype')
18 * @param string $dir The directory where the plugins are located (e.g. 'question/questiontypes')
19 * @param string $return The url to prompt the user to continue to
eef868d1 20 */
ead29342 21function upgrade_plugins($type, $dir, $return) {
e69ef14b 22 global $CFG, $db;
173cc1c3 23
15999a93 24/// Let's know if the header has been printed, so the funcion is being called embedded in an outer page
25 $embedded = defined('HEADER_PRINTED');
26
bb7053f3 27 $plugs = get_list_of_plugins($dir);
583fad99 28 $updated_plugins = false;
29 $strpluginsetup = get_string('pluginsetup');
30
ead29342 31 foreach ($plugs as $plug) {
173cc1c3 32
ead29342 33 $fullplug = $CFG->dirroot .'/'.$dir.'/'. $plug;
173cc1c3 34
ead29342 35 unset($plugin);
173cc1c3 36
bbbf2d40 37 if (is_readable($fullplug .'/version.php')) {
ead29342 38 include_once($fullplug .'/version.php'); // defines $plugin with version etc
173cc1c3 39 } else {
40 continue; // Nothing to do.
41 }
42
e79a09a2 43 $oldupgrade = false;
44 $newupgrade = false;
7c006e34 45 if (is_readable($fullplug . '/db/'. $CFG->dbtype . '.php')) {
46 include_once($fullplug . '/db/'. $CFG->dbtype . '.php'); // defines old upgrading function
e79a09a2 47 $oldupgrade = true;
48 }
db8bd7a6 49 if (is_readable($fullplug . '/db/upgrade.php')) {
7c006e34 50 include_once($fullplug . '/db/upgrade.php'); // defines new upgrading function
e79a09a2 51 $newupgrade = true;
52 }
53
ead29342 54 if (!isset($plugin)) {
173cc1c3 55 continue;
56 }
57
ead29342 58 if (!empty($plugin->requires)) {
59 if ($plugin->requires > $CFG->version) {
acdd790f 60 $info = new object();
ead29342 61 $info->pluginname = $plug;
62 $info->pluginversion = $plugin->version;
173cc1c3 63 $info->currentmoodle = $CFG->version;
ead29342 64 $info->requiremoodle = $plugin->requires;
15999a93 65 if (!$updated_plugins && !$embedded) {
0be6f678 66 print_header($strpluginsetup, $strpluginsetup,
67 build_navigation(array(array('name' => $strpluginsetup, 'link' => null, 'type' => 'misc'))), '',
371a32e3 68 upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
583fad99 69 }
70 upgrade_log_start();
ead29342 71 notify(get_string('pluginrequirementsnotmet', 'error', $info));
583fad99 72 $updated_plugins = true;
173cc1c3 73 continue;
74 }
75 }
76
ead29342 77 $plugin->name = $plug; // The name MUST match the directory
173cc1c3 78
ead29342 79 $pluginversion = $type.'_'.$plug.'_version';
173cc1c3 80
ead29342 81 if (!isset($CFG->$pluginversion)) {
82 set_config($pluginversion, 0);
173cc1c3 83 }
eef868d1 84
ead29342 85 if ($CFG->$pluginversion == $plugin->version) {
173cc1c3 86 // do nothing
ead29342 87 } else if ($CFG->$pluginversion < $plugin->version) {
15999a93 88 if (!$updated_plugins && !$embedded) {
0be6f678 89 print_header($strpluginsetup, $strpluginsetup,
90 build_navigation(array(array('name' => $strpluginsetup, 'link' => null, 'type' => 'misc'))), '',
371a32e3 91 upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
173cc1c3 92 }
e79a09a2 93 $updated_plugins = true;
583fad99 94 upgrade_log_start();
05b42119 95 print_heading($dir.'/'. $plugin->name .' plugin needs upgrading');
e79a09a2 96 $db->debug = true;
97 @set_time_limit(0); // To allow slow databases to complete the long SQL
98
d87a9d73 99 if ($CFG->$pluginversion == 0) { // It's a new install of this plugin
e79a09a2 100 /// Both old .sql files and new install.xml are supported
101 /// but we priorize install.xml (XMLDB) if present
102 $status = false;
db8bd7a6 103 if (file_exists($fullplug . '/db/install.xml')) {
450cf307 104 $status = install_from_xmldb_file($fullplug . '/db/install.xml'); //New method
e79a09a2 105 } else if (file_exists($fullplug .'/db/'. $CFG->dbtype .'.sql')) {
106 $status = modify_database($fullplug .'/db/'. $CFG->dbtype .'.sql'); //Old method
eef868d1 107 } else {
7c006e34 108 $status = true;
d87a9d73 109 }
e79a09a2 110
111 $db->debug = false;
eef868d1 112 /// Continue with the instalation, roles and other stuff
e79a09a2 113 if ($status) {
3f59a54e 114 /// OK so far, now update the plugins record
e79a09a2 115 set_config($pluginversion, $plugin->version);
3f59a54e 116
117 /// Install capabilities
ae628043 118 if (!update_capabilities($type.'/'.$plug)) {
3f59a54e 119 error('Could not set up the capabilities for '.$plugin->name.'!');
e79a09a2 120 }
3f59a54e 121 /// Install events
0856223c 122 events_update_definition($type.'/'.$plug);
3f59a54e 123
124 /// Run local install function if there is one
125 if (is_readable($fullplug .'/lib.php')) {
9ba38673 126 include_once($fullplug .'/lib.php');
3f59a54e 127 $installfunction = $plugin->name.'_install';
128 if (function_exists($installfunction)) {
129 if (! $installfunction() ) {
130 notify('Encountered a problem running install function for '.$module->name.'!');
131 }
132 }
133 }
9ba38673 134
e79a09a2 135 notify(get_string('modulesuccess', '', $plugin->name), 'notifysuccess');
136 } else {
137 notify('Installing '. $plugin->name .' FAILED!');
138 }
d87a9d73 139 } else { // Upgrade existing install
e79a09a2 140 /// Run de old and new upgrade functions for the module
141 $oldupgrade_function = $type.'_'.$plugin->name .'_upgrade';
142 $newupgrade_function = 'xmldb_' . $type.'_'.$plugin->name .'_upgrade';
143
144 /// First, the old function if exists
145 $oldupgrade_status = true;
146 if ($oldupgrade && function_exists($oldupgrade_function)) {
147 $db->debug = true;
148 $oldupgrade_status = $oldupgrade_function($CFG->$pluginversion);
149 } else if ($oldupgrade) {
150 notify ('Upgrade function ' . $oldupgrade_function . ' was not available in ' .
151 $fullplug . '/db/' . $CFG->dbtype . '.php');
152 }
153
154 /// Then, the new function if exists and the old one was ok
155 $newupgrade_status = true;
156 if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) {
157 $db->debug = true;
158 $newupgrade_status = $newupgrade_function($CFG->$pluginversion);
159 } else if ($newupgrade) {
160 notify ('Upgrade function ' . $newupgrade_function . ' was not available in ' .
161 $fullplug . '/db/upgrade.php');
162 }
163
164 $db->debug=false;
165 /// Now analyze upgrade results
166 if ($oldupgrade_status && $newupgrade_status) { // No upgrading failed
167 // OK so far, now update the plugins record
168 set_config($pluginversion, $plugin->version);
ae628043 169 if (!update_capabilities($type.'/'.$plug)) {
e79a09a2 170 error('Could not update '.$plugin->name.' capabilities!');
d87a9d73 171 }
0856223c 172 events_update_definition($type.'/'.$plug);
e79a09a2 173 notify(get_string('modulesuccess', '', $plugin->name), 'notifysuccess');
174 } else {
175 notify('Upgrading '. $plugin->name .' from '. $CFG->$pluginversion .' to '. $plugin->version .' FAILED!');
173cc1c3 176 }
177 }
d87a9d73 178 echo '<hr />';
173cc1c3 179 } else {
583fad99 180 upgrade_log_start();
ead29342 181 error('Version mismatch: '. $plugin->name .' can\'t downgrade '. $CFG->$pluginversion .' -> '. $plugin->version .' !');
173cc1c3 182 }
183 }
184
583fad99 185 upgrade_log_finish();
186
15999a93 187 if ($updated_plugins && !$embedded) {
173cc1c3 188 print_continue($return);
acdd790f 189 print_footer('none');
173cc1c3 190 die;
191 }
192}
193
88a7228a 194/**
195 * Find and check all modules and load them up or upgrade them if necessary
196 *
197 * @uses $db
198 * @uses $CFG
199 * @param string $return The url to prompt the user to continue to
200 * @todo Finish documenting this function
eef868d1 201 */
173cc1c3 202function upgrade_activity_modules($return) {
173cc1c3 203
e69ef14b 204 global $CFG, $db;
173cc1c3 205
88a7228a 206 if (!$mods = get_list_of_plugins('mod') ) {
207 error('No modules installed!');
173cc1c3 208 }
209
583fad99 210 $updated_modules = false;
211 $strmodulesetup = get_string('modulesetup');
212
173cc1c3 213 foreach ($mods as $mod) {
214
88a7228a 215 if ($mod == 'NEWMODULE') { // Someone has unzipped the template, ignore it
173cc1c3 216 continue;
217 }
218
88a7228a 219 $fullmod = $CFG->dirroot .'/mod/'. $mod;
173cc1c3 220
221 unset($module);
222
88a7228a 223 if ( is_readable($fullmod .'/version.php')) {
224 include_once($fullmod .'/version.php'); // defines $module with version etc
173cc1c3 225 } else {
88a7228a 226 notify('Module '. $mod .': '. $fullmod .'/version.php was not readable');
173cc1c3 227 continue;
228 }
229
d6eb06b6 230 $oldupgrade = false;
231 $newupgrade = false;
7c006e34 232 if ( is_readable($fullmod .'/db/' . $CFG->dbtype . '.php')) {
233 include_once($fullmod .'/db/' . $CFG->dbtype . '.php'); // defines old upgrading function
d6eb06b6 234 $oldupgrade = true;
235 }
db8bd7a6 236 if ( is_readable($fullmod . '/db/upgrade.php')) {
7c006e34 237 include_once($fullmod . '/db/upgrade.php'); // defines new upgrading function
d6eb06b6 238 $newupgrade = true;
173cc1c3 239 }
240
241 if (!isset($module)) {
242 continue;
243 }
244
245 if (!empty($module->requires)) {
246 if ($module->requires > $CFG->version) {
acdd790f 247 $info = new object();
173cc1c3 248 $info->modulename = $mod;
249 $info->moduleversion = $module->version;
250 $info->currentmoodle = $CFG->version;
251 $info->requiremoodle = $module->requires;
583fad99 252 if (!$updated_modules) {
0be6f678 253 print_header($strmodulesetup, $strmodulesetup,
254 build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '',
371a32e3 255 upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
583fad99 256 }
257 upgrade_log_start();
173cc1c3 258 notify(get_string('modulerequirementsnotmet', 'error', $info));
583fad99 259 $updated_modules = true;
173cc1c3 260 continue;
261 }
262 }
263
264 $module->name = $mod; // The name MUST match the directory
eef868d1 265
11e4a24b 266 include_once($fullmod.'/lib.php'); // defines upgrading and/or installing functions
267
88a7228a 268 if ($currmodule = get_record('modules', 'name', $module->name)) {
173cc1c3 269 if ($currmodule->version == $module->version) {
270 // do nothing
271 } else if ($currmodule->version < $module->version) {
d6eb06b6 272 /// If versions say that we need to upgrade but no upgrade files are available, notify and continue
273 if (!$oldupgrade && !$newupgrade) {
274 notify('Upgrade files ' . $mod . ': ' . $fullmod . '/db/' . $CFG->dbtype . '.php or ' .
275 $fullmod . '/db/upgrade.php were not readable');
276 continue;
277 }
583fad99 278 if (!$updated_modules) {
0be6f678 279 print_header($strmodulesetup, $strmodulesetup,
280 build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '',
371a32e3 281 upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
173cc1c3 282 }
583fad99 283 upgrade_log_start();
88a7228a 284 print_heading($module->name .' module needs upgrading');
d6eb06b6 285
286 /// Run de old and new upgrade functions for the module
287 $oldupgrade_function = $module->name . '_upgrade';
288 $newupgrade_function = 'xmldb_' . $module->name . '_upgrade';
289
290 /// First, the old function if exists
291 $oldupgrade_status = true;
292 if ($oldupgrade && function_exists($oldupgrade_function)) {
293 $db->debug = true;
294 $oldupgrade_status = $oldupgrade_function($currmodule->version, $module);
ba05965e 295 } else if ($oldupgrade) {
d6eb06b6 296 notify ('Upgrade function ' . $oldupgrade_function . ' was not available in ' .
297 $mod . ': ' . $fullmod . '/db/' . $CFG->dbtype . '.php');
d6eb06b6 298 }
299
300 /// Then, the new function if exists and the old one was ok
301 $newupgrade_status = true;
ba05965e 302 if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) {
d6eb06b6 303 $db->debug = true;
304 $newupgrade_status = $newupgrade_function($currmodule->version, $module);
ba05965e 305 } else if ($newupgrade) {
d6eb06b6 306 notify ('Upgrade function ' . $newupgrade_function . ' was not available in ' .
307 $mod . ': ' . $fullmod . '/db/upgrade.php');
d6eb06b6 308 }
309
e79a09a2 310 $db->debug=false;
d6eb06b6 311 /// Now analyze upgrade results
668896e5 312 if ($oldupgrade_status && $newupgrade_status) { // No upgrading failed
d6eb06b6 313 // OK so far, now update the modules record
314 $module->id = $currmodule->id;
315 if (! update_record('modules', $module)) {
316 error('Could not update '. $module->name .' record in modules table!');
173cc1c3 317 }
d6eb06b6 318 remove_dir($CFG->dataroot . '/cache', true); // flush cache
319 notify(get_string('modulesuccess', '', $module->name), 'notifysuccess');
320 echo '<hr />';
321 } else {
d6eb06b6 322 notify('Upgrading '. $module->name .' from '. $currmodule->version .' to '. $module->version .' FAILED!');
173cc1c3 323 }
bbbf2d40 324
d6eb06b6 325 /// Update the capabilities table?
bbbf2d40 326 if (!update_capabilities('mod/'.$module->name)) {
327 error('Could not update '.$module->name.' capabilities!');
328 }
0856223c 329 events_update_definition('mod/'.$module->name);
bbbf2d40 330
173cc1c3 331 $updated_modules = true;
eef868d1 332
173cc1c3 333 } else {
583fad99 334 upgrade_log_start();
88a7228a 335 error('Version mismatch: '. $module->name .' can\'t downgrade '. $currmodule->version .' -> '. $module->version .' !');
173cc1c3 336 }
eef868d1 337
173cc1c3 338 } else { // module not installed yet, so install it
583fad99 339 if (!$updated_modules) {
0be6f678 340 print_header($strmodulesetup, $strmodulesetup,
341 build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '',
371a32e3 342 upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
173cc1c3 343 }
583fad99 344 upgrade_log_start();
173cc1c3 345 print_heading($module->name);
346 $updated_modules = true;
347 $db->debug = true;
348 @set_time_limit(0); // To allow slow databases to complete the long SQL
d6eb06b6 349
350 /// Both old .sql files and new install.xml are supported
351 /// but we priorize install.xml (XMLDB) if present
db8bd7a6 352 if (file_exists($fullmod . '/db/install.xml')) {
d6eb06b6 353 $status = install_from_xmldb_file($fullmod . '/db/install.xml'); //New method
354 } else {
355 $status = modify_database($fullmod .'/db/'. $CFG->dbtype .'.sql'); //Old method
356 }
357
e79a09a2 358 $db->debug = false;
11e4a24b 359
360 /// Continue with the installation, roles and other stuff
d6eb06b6 361 if ($status) {
88a7228a 362 if ($module->id = insert_record('modules', $module)) {
11e4a24b 363
9ba38673 364 /// Capabilities
bbbf2d40 365 if (!update_capabilities('mod/'.$module->name)) {
366 error('Could not set up the capabilities for '.$module->name.'!');
367 }
9ba38673 368
11e4a24b 369 /// Events
0856223c 370 events_update_definition('mod/'.$module->name);
11e4a24b 371
372 /// Run local install function if there is one
373 $installfunction = $module->name.'_install';
374 if (function_exists($installfunction)) {
375 if (! $installfunction() ) {
376 notify('Encountered a problem running install function for '.$module->name.'!');
377 }
378 }
379
a8f68426 380 notify(get_string('modulesuccess', '', $module->name), 'notifysuccess');
88a7228a 381 echo '<hr />';
173cc1c3 382 } else {
88a7228a 383 error($module->name .' module could not be added to the module list!');
173cc1c3 384 }
eef868d1 385 } else {
88a7228a 386 error($module->name .' tables could NOT be set up successfully!');
173cc1c3 387 }
388 }
e5bd4e58 389
390 /// Check submodules of this module if necessary
391
e5bd4e58 392 $submoduleupgrade = $module->name.'_upgrade_submodules';
393 if (function_exists($submoduleupgrade)) {
394 $submoduleupgrade();
395 }
396
397
398 /// Run any defaults or final code that is necessary for this module
399
a5c0990e 400 if ( is_readable($fullmod .'/defaults.php')) {
401 // Insert default values for any important configuration variables
9e6e7502 402 unset($defaults);
eef868d1 403 include_once($fullmod .'/defaults.php');
f9a2e515 404 if (!empty($defaults)) {
405 foreach ($defaults as $name => $value) {
406 if (!isset($CFG->$name)) {
407 set_config($name, $value);
408 }
a5c0990e 409 }
410 }
411 }
173cc1c3 412 }
413
583fad99 414 upgrade_log_finish(); // finish logging if started
415
416 if ($updated_modules) {
173cc1c3 417 print_continue($return);
acdd790f 418 print_footer('none');
173cc1c3 419 die;
420 }
421}
422
eef868d1 423/**
f3221af9 424 * This function will return FALSE if the lock fails to be set (ie, if it's already locked)
80be7ee3 425 *
426 * @param string $name ?
427 * @param bool $value ?
428 * @param int $staleafter ?
429 * @param bool $clobberstale ?
430 * @todo Finish documenting this function
f3221af9 431 */
432function set_cron_lock($name,$value=true,$staleafter=7200,$clobberstale=false) {
433
434 if (empty($name)) {
435 mtrace("Tried to get a cron lock for a null fieldname");
436 return false;
437 }
438
439 if (empty($value)) {
440 set_config($name,0);
441 return true;
442 }
443
444 if ($config = get_record('config','name',$name)) {
445 if (empty($config->value)) {
446 set_config($name,time());
447 } else {
448 // check for stale.
449 if ((time() - $staleafter) > $config->value) {
450 mtrace("STALE LOCKFILE FOR $name - was $config->value");
451 if (!empty($clobberstale)) {
452 set_config($name,time());
453 return true;
454 }
455 } else {
456 return false; // was not stale - ie, we're ok to still be running.
457 }
458 }
459 }
460 else {
461 set_config($name,time());
462 }
463 return true;
464}
a597f8a8 465
fb06b255 466function print_progress($done, $total, $updatetime=5, $sleeptime=1, $donetext='') {
a597f8a8 467 static $starttime;
468 static $lasttime;
469
26ea4888 470 if ($total < 2) { // No need to show anything
471 return;
472 }
473
a597f8a8 474 if (empty($starttime)) {
475 $starttime = $lasttime = time();
476 $lasttime = $starttime - $updatetime;
477 echo '<table width="500" cellpadding="0" cellspacing="0" align="center"><tr><td width="500">';
72da5046 478 echo '<div id="bar'.$total.'" style="border-style:solid;border-width:1px;width:500px;height:50px;">';
479 echo '<div id="slider'.$total.'" style="border-style:solid;border-width:1px;height:48px;width:10px;background-color:green;"></div>';
a597f8a8 480 echo '</div>';
72da5046 481 echo '<div id="text'.$total.'" align="center" style="width:500px;"></div>';
a597f8a8 482 echo '</td></tr></table>';
483 echo '</div>';
484 }
485
a597f8a8 486 $now = time();
487
488 if ($done && (($now - $lasttime) >= $updatetime)) {
489 $elapsedtime = $now - $starttime;
490 $projectedtime = (int)(((float)$total / (float)$done) * $elapsedtime) - $elapsedtime;
76317c73 491 $percentage = round((float)$done / (float)$total, 2);
a597f8a8 492 $width = (int)(500 * $percentage);
493
fb06b255 494 if ($projectedtime > 10) {
495 $projectedtext = ' Ending: '.format_time($projectedtime);
496 } else {
497 $projectedtext = '';
498 }
499
a597f8a8 500 echo '<script>';
aae37b63 501 echo 'document.getElementById("text'.$total.'").innerHTML = "'.addslashes($donetext).' ('.$done.'/'.$total.') '.$projectedtext.'";'."\n";
502 echo 'document.getElementById("slider'.$total.'").style.width = \''.$width.'px\';'."\n";
a597f8a8 503 echo '</script>';
504
505 $lasttime = $now;
506 sleep($sleeptime);
507 }
508}
583fad99 509
371a32e3 510function upgrade_get_javascript() {
511 global $CFG;
512
513 if (!empty($_SESSION['installautopilot'])) {
514 $linktoscrolltoerrors = '<script type="text/javascript">var installautopilot = true;</script>'."\n";
515 } else {
516 $linktoscrolltoerrors = '<script type="text/javascript">var installautopilot = false;</script>'."\n";
517 }
518 $linktoscrolltoerrors .= '<script type="text/javascript" src="' . $CFG->wwwroot . '/lib/scroll_to_errors.js"></script>';
519
520 return $linktoscrolltoerrors;
521}
ad6226fb 522
523function create_admin_user() {
524 global $CFG, $USER;
525
526 if (empty($CFG->rolesactive)) { // No admin user yet.
527
528 $user = new object();
529 $user->auth = 'manual';
530 $user->firstname = get_string('admin');
531 $user->lastname = get_string('user');
532 $user->username = 'admin';
533 $user->password = hash_internal_user_password('admin');
534 $user->email = 'root@localhost';
535 $user->confirmed = 1;
536 $user->mnethostid = $CFG->mnet_localhost_id;
537 $user->lang = $CFG->lang;
538 $user->maildisplay = 1;
539 $user->timemodified = time();
540
541 if (!$user->id = insert_record('user', $user)) {
542 error('SERIOUS ERROR: Could not create admin user record !!!');
543 }
544
545 if (!$user = get_record('user', 'id', $user->id)) { // Double check.
546 error('User ID was incorrect (can\'t find it)');
547 }
548
549 // Assign the default admin roles to the new user.
550 if (!$adminroles = get_roles_with_capability('moodle/legacy:admin', CAP_ALLOW)) {
551 error('No admin role could be found');
552 }
84c8ede0 553 $sitecontext = get_context_instance(CONTEXT_SYSTEM);
ad6226fb 554 foreach ($adminroles as $adminrole) {
555 role_assign($adminrole->id, $user->id, 0, $sitecontext->id);
556 }
557
558 set_config('rolesactive', 1);
559
560 // Log the user in.
561 $USER = get_complete_user_data('username', 'admin');
562 $USER->newadminuser = 1;
563 load_all_capabilities();
564
565 redirect("$CFG->wwwroot/user/editadvanced.php?id=$user->id"); // Edit thyself
566 } else {
567 error('Can not create admin!');
568 }
569}
570
583fad99 571////////////////////////////////////////////////
572/// upgrade logging functions
573////////////////////////////////////////////////
574
575$upgradeloghandle = false;
26c91c73 576$upgradelogbuffer = '';
577// I did not find out how to use static variable in callback function,
578// the problem was that I could not flush the static buffer :-(
579global $upgradeloghandle, $upgradelogbuffer;
583fad99 580
581/**
582 * Check if upgrade is already running.
583 *
584 * If anything goes wrong due to missing call to upgrade_log_finish()
585 * just restart the browser.
586 *
587 * @param string warning message indicating upgrade is already running
588 * @param int page reload timeout
589 */
590function upgrade_check_running($message, $timeout) {
591 if (!empty($_SESSION['upgraderunning'])) {
592 print_header();
593 redirect(me(), $message, $timeout);
594 }
595}
596
597/**
598 * Start logging of output into file (if not disabled) and
599 * prevent aborting and concurrent execution of upgrade script.
600 *
601 * Please note that you can not write into session variables after calling this function!
602 *
603 * This function may be called repeatedly.
604 */
605function upgrade_log_start() {
426a369b 606 global $CFG, $upgradeloghandle;
583fad99 607
608 if (!empty($_SESSION['upgraderunning'])) {
609 return; // logging already started
610 }
611
612 @ignore_user_abort(true); // ignore if user stops or otherwise aborts page loading
613 $_SESSION['upgraderunning'] = 1; // set upgrade indicator
426a369b 614 if (empty($CFG->dbsessions)) { // workaround for bug in adodb, db session can not be restarted
615 session_write_close(); // from now on user can reload page - will be displayed warning
616 }
583fad99 617 make_upload_directory('upgradelogs');
618 ob_start('upgrade_log_callback', 2); // function for logging to disk; flush each line of text ASAP
dedb2304 619 register_shutdown_function('upgrade_log_finish'); // in case somebody forgets to stop logging
583fad99 620}
621
622/**
623 * Terminate logging of output, flush all data, allow script aborting
624 * and reopen session for writing. Function error() does terminate the logging too.
625 *
626 * Please make sure that each upgrade_log_start() is properly terminated by
627 * this function or error().
628 *
629 * This function may be called repeatedly.
630 */
631function upgrade_log_finish() {
426a369b 632 global $CFG, $upgradeloghandle, $upgradelogbuffer;
583fad99 633
634 if (empty($_SESSION['upgraderunning'])) {
635 return; // logging already terminated
636 }
637
638 @ob_end_flush();
26c91c73 639 if ($upgradelogbuffer !== '') {
640 @fwrite($upgradeloghandle, $upgradelogbuffer);
40896537 641 $upgradelogbuffer = '';
26c91c73 642 }
643 if ($upgradeloghandle and ($upgradeloghandle !== 'error')) {
644 @fclose($upgradeloghandle);
40896537 645 $upgradeloghandle = false;
26c91c73 646 }
426a369b 647 if (empty($CFG->dbsessions)) {
648 @session_start(); // ignore header errors, we only need to reopen session
649 }
583fad99 650 $_SESSION['upgraderunning'] = 0; // clear upgrade indicator
651 if (connection_aborted()) {
652 die;
653 }
654 @ignore_user_abort(false);
655}
656
657/**
658 * Callback function for logging into files. Not more than one file is created per minute,
659 * upgrade session (terminated by upgrade_log_finish()) is always stored in one file.
660 *
661 * This function must not output any characters or throw warnigns and errors!
662 */
663function upgrade_log_callback($string) {
26c91c73 664 global $CFG, $upgradeloghandle, $upgradelogbuffer;
583fad99 665
666 if (empty($CFG->disableupgradelogging) and ($string != '') and ($upgradeloghandle !== 'error')) {
667 if ($upgradeloghandle or ($upgradeloghandle = @fopen($CFG->dataroot.'/upgradelogs/upg_'.date('Ymd-Hi').'.html', 'a'))) {
26c91c73 668 $upgradelogbuffer .= $string;
669 if (strlen($upgradelogbuffer) > 2048) { // 2kB write buffer
670 @fwrite($upgradeloghandle, $upgradelogbuffer);
671 $upgradelogbuffer = '';
672 }
583fad99 673 } else {
674 $upgradeloghandle = 'error';
675 }
676 }
677 return $string;
678}
679
57e35f32 680/**
681 * Try to verify that dataroot is not accessible from web.
682 * It is not 100% correct but might help to reduce number of vulnerable sites.
683 *
684 * Protection from httpd.conf and .htaccess is not detected properly.
685 */
686function is_dataroot_insecure() {
687 global $CFG;
688
689 $siteroot = str_replace('\\', '/', strrev($CFG->dirroot.'/')); // win32 backslash workaround
690
691 $rp = preg_replace('|https?://[^/]+|i', '', $CFG->wwwroot, 1);
692 $rp = strrev(trim($rp, '/'));
693 $rp = explode('/', $rp);
694 foreach($rp as $r) {
695 if (strpos($siteroot, '/'.$r.'/') === 0) {
696 $siteroot = substr($siteroot, strlen($r)+1); // moodle web in subdirectory
697 } else {
698 break; // probably alias root
699 }
700 }
701
702 $siteroot = strrev($siteroot);
703 $dataroot = str_replace('\\', '/', $CFG->dataroot.'/');
704
705 if (strpos($dataroot, $siteroot) === 0) {
706 return true;
707 }
708 return false;
709}
6e4dc10f 710
711/// =============================================================================================================
712/// administration tree classes and functions
713
714
715// n.b. documentation is still in progress for this code
716
717/// INTRODUCTION
718
719/// This file performs the following tasks:
720/// -it defines the necessary objects and interfaces to build the Moodle
721/// admin hierarchy
eef868d1 722/// -it defines the admin_externalpage_setup(), admin_externalpage_print_header(),
6e4dc10f 723/// and admin_externalpage_print_footer() functions used on admin pages
724
725/// ADMIN_SETTING OBJECTS
726
eef868d1 727/// Moodle settings are represented by objects that inherit from the admin_setting
6e4dc10f 728/// class. These objects encapsulate how to read a setting, how to write a new value
729/// to a setting, and how to appropriately display the HTML to modify the setting.
730
731/// ADMIN_SETTINGPAGE OBJECTS
732
733/// The admin_setting objects are then grouped into admin_settingpages. The latter
734/// appear in the Moodle admin tree block. All interaction with admin_settingpage
735/// objects is handled by the admin/settings.php file.
736
737/// ADMIN_EXTERNALPAGE OBJECTS
738
739/// There are some settings in Moodle that are too complex to (efficiently) handle
740/// with admin_settingpages. (Consider, for example, user management and displaying
741/// lists of users.) In this case, we use the admin_externalpage object. This object
742/// places a link to an external PHP file in the admin tree block.
743
744/// If you're using an admin_externalpage object for some settings, you can take
745/// advantage of the admin_externalpage_* functions. For example, suppose you wanted
746/// to add a foo.php file into admin. First off, you add the following line to
747/// admin/settings/first.php (at the end of the file) or to some other file in
748/// admin/settings:
749
eef868d1 750/// $ADMIN->add('userinterface', new admin_externalpage('foo', get_string('foo'),
6e4dc10f 751/// $CFG->wwwdir . '/' . '$CFG->admin . '/foo.php', 'some_role_permission'));
752
753/// Next, in foo.php, your file structure would resemble the following:
754
755/// require_once('.../config.php');
756/// require_once($CFG->libdir.'/adminlib.php');
1ae083e4 757/// admin_externalpage_setup('foo');
6e4dc10f 758/// // functionality like processing form submissions goes here
1ae083e4 759/// admin_externalpage_print_header();
6e4dc10f 760/// // your HTML goes here
1ae083e4 761/// admin_externalpage_print_footer();
6e4dc10f 762
763/// The admin_externalpage_setup() function call ensures the user is logged in,
764/// and makes sure that they have the proper role permission to access the page.
765
766/// The admin_externalpage_print_header() function prints the header (it figures
767/// out what category and subcategories the page is classified under) and ensures
768/// that you're using the admin pagelib (which provides the admin tree block and
769/// the admin bookmarks block).
770
771/// The admin_externalpage_print_footer() function properly closes the tables
772/// opened up by the admin_externalpage_print_header() function and prints the
773/// standard Moodle footer.
774
775/// ADMIN_CATEGORY OBJECTS
776
777/// Above and beyond all this, we have admin_category objects. These objects
778/// appear as folders in the admin tree block. They contain admin_settingpage's,
779/// admin_externalpage's, and other admin_category's.
780
781/// OTHER NOTES
782
783/// admin_settingpage's, admin_externalpage's, and admin_category's all inherit
784/// from part_of_admin_tree (a pseudointerface). This interface insists that
785/// a class has a check_access method for access permissions, a locate method
786/// used to find a specific node in the admin tree, and a path method used
787/// to determine the path to a specific node in the $ADMIN tree.
788
789/// admin_category's inherit from parentable_part_of_admin_tree. This pseudo-
790/// interface ensures that the class implements a recursive add function which
791/// accepts a part_of_admin_tree object and searches for the proper place to
792/// put it. parentable_part_of_admin_tree implies part_of_admin_tree.
793
794/// Please note that the $this->name field of any part_of_admin_tree must be
795/// UNIQUE throughout the ENTIRE admin tree.
796
797/// The $this->name field of an admin_setting object (which is *not* part_of_
798/// admin_tree) must be unique on the respective admin_settingpage where it is
799/// used.
800
801
802/// MISCELLANEOUS STUFF (used by classes defined below) ///////////////////////
803include_once($CFG->dirroot . '/backup/lib.php');
804
805/// CLASS DEFINITIONS /////////////////////////////////////////////////////////
806
807/**
808 * Pseudointerface for anything appearing in the admin tree
809 *
810 * The pseudointerface that is implemented by anything that appears in the admin tree
811 * block. It forces inheriting classes to define a method for checking user permissions
812 * and methods for finding something in the admin tree.
813 *
814 * @author Vincenzo K. Marcovecchio
815 * @package admin
816 */
817class part_of_admin_tree {
818
819 /**
820 * Finds a named part_of_admin_tree.
821 *
822 * Used to find a part_of_admin_tree. If a class only inherits part_of_admin_tree
823 * and not parentable_part_of_admin_tree, then this function should only check if
824 * $this->name matches $name. If it does, it should return a reference to $this,
825 * otherwise, it should return a reference to NULL.
826 *
827 * If a class inherits parentable_part_of_admin_tree, this method should be called
828 * recursively on all child objects (assuming, of course, the parent object's name
829 * doesn't match the search criterion).
830 *
831 * @param string $name The internal name of the part_of_admin_tree we're searching for.
832 * @return mixed An object reference or a NULL reference.
833 */
eef868d1 834 function &locate($name) {
835 trigger_error('Admin class does not implement method <strong>locate()</strong>', E_USER_WARNING);
836 return;
6e4dc10f 837 }
4672d955 838
839 /**
840 * Removes named part_of_admin_tree.
841 *
842 * @param string $name The internal name of the part_of_admin_tree we want to remove.
a8a66c96 843 * @return bool success.
4672d955 844 */
845 function prune($name) {
eef868d1 846 trigger_error('Admin class does not implement method <strong>prune()</strong>', E_USER_WARNING);
4672d955 847 return;
eef868d1 848 }
4672d955 849
6e4dc10f 850 /**
851 * Verifies current user's access to this part_of_admin_tree.
852 *
853 * Used to check if the current user has access to this part of the admin tree or
854 * not. If a class only inherits part_of_admin_tree and not parentable_part_of_admin_tree,
855 * then this method is usually just a call to has_capability() in the site context.
856 *
857 * If a class inherits parentable_part_of_admin_tree, this method should return the
858 * logical OR of the return of check_access() on all child objects.
859 *
860 * @return bool True if the user has access, false if she doesn't.
861 */
eef868d1 862 function check_access() {
863 trigger_error('Admin class does not implement method <strong>check_access()</strong>', E_USER_WARNING);
864 return;
6e4dc10f 865 }
eef868d1 866
a8a66c96 867 /**
868 * Mostly usefull for removing of some parts of the tree in admin tree block.
869 *
870 * @return True is hidden from normal list view
871 */
872 function is_hidden() {
873 trigger_error('Admin class does not implement method <strong>is_hidden()</strong>', E_USER_WARNING);
874 return;
875 }
876
6e4dc10f 877 /**
878 * Determines the path to $name in the admin tree.
879 *
880 * Used to determine the path to $name in the admin tree. If a class inherits only
881 * part_of_admin_tree and not parentable_part_of_admin_tree, then this method should
882 * check if $this->name matches $name. If it does, $name is pushed onto the $path
883 * array (at the end), and $path should be returned. If it doesn't, NULL should be
884 * returned.
885 *
886 * If a class inherits parentable_part_of_admin_tree, it should do the above, but not
887 * return NULL on failure. Instead, it pushes $this->name onto $path, and then
888 * recursively calls path() on its child objects. If any are non-NULL, it should
889 * return $path (being certain that the last element of $path is equal to $name).
890 * If they are all NULL, it returns NULL.
891 *
892 * @param string $name The internal name of the part_of_admin_tree we're searching for.
893 * @param array $path Not used on external calls. Defaults to empty array.
894 * @return mixed If found, an array containing the internal names of each part_of_admin_tree that leads to $name. If not found, NULL.
895 */
eef868d1 896 function path($name, $path = array()) {
897 trigger_error('Admin class does not implement method <strong>path()</strong>', E_USER_WARNING);
898 return;
6e4dc10f 899 }
900}
901
902/**
903 * Pseudointerface implemented by any part_of_admin_tree that has children.
904 *
905 * The pseudointerface implemented by any part_of_admin_tree that can be a parent
906 * to other part_of_admin_tree's. (For now, this only includes admin_category.) Apart
eef868d1 907 * from ensuring part_of_admin_tree compliancy, it also ensures inheriting methods
6e4dc10f 908 * include an add method for adding other part_of_admin_tree objects as children.
909 *
910 * @author Vincenzo K. Marcovecchio
911 * @package admin
912 */
913class parentable_part_of_admin_tree extends part_of_admin_tree {
eef868d1 914
6e4dc10f 915 /**
916 * Adds a part_of_admin_tree object to the admin tree.
917 *
918 * Used to add a part_of_admin_tree object to this object or a child of this
919 * object. $something should only be added if $destinationname matches
920 * $this->name. If it doesn't, add should be called on child objects that are
921 * also parentable_part_of_admin_tree's.
922 *
923 * @param string $destinationname The internal name of the new parent for $something.
924 * @param part_of_admin_tree &$something The object to be added.
925 * @return bool True on success, false on failure.
926 */
eef868d1 927 function add($destinationname, &$something) {
928 trigger_error('Admin class does not implement method <strong>add()</strong>', E_USER_WARNING);
929 return;
6e4dc10f 930 }
eef868d1 931
6e4dc10f 932}
933
934/**
935 * The object used to represent folders (a.k.a. categories) in the admin tree block.
eef868d1 936 *
6e4dc10f 937 * Each admin_category object contains a number of part_of_admin_tree objects.
938 *
939 * @author Vincenzo K. Marcovecchio
940 * @package admin
941 */
942class admin_category extends parentable_part_of_admin_tree {
943
944 /**
945 * @var mixed An array of part_of_admin_tree objects that are this object's children
946 */
947 var $children;
eef868d1 948
6e4dc10f 949 /**
950 * @var string An internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
951 */
952 var $name;
eef868d1 953
6e4dc10f 954 /**
955 * @var string The displayed name for this category. Usually obtained through get_string()
956 */
957 var $visiblename;
eef868d1 958
a8a66c96 959 /**
960 * @var bool Should this category be hidden in admin tree block?
961 */
962 var $hidden;
963
6e4dc10f 964 // constructor for an empty admin category
965 // $name is the internal name of the category. it MUST be unique in the entire hierarchy
966 // $visiblename is the displayed name of the category. use a get_string for this
967
968 /**
969 * Constructor for an empty admin category
970 *
971 * @param string $name The internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
972 * @param string $visiblename The displayed named for this category. Usually obtained through get_string()
a8a66c96 973 * @param bool $hidden hide category in admin tree block
6e4dc10f 974 * @return mixed Returns the new object.
975 */
a8a66c96 976 function admin_category($name, $visiblename, $hidden = false) {
6e4dc10f 977 $this->children = array();
978 $this->name = $name;
979 $this->visiblename = $visiblename;
a8a66c96 980 $this->hidden = $hidden;
6e4dc10f 981 }
eef868d1 982
6e4dc10f 983 /**
984 * Finds the path to the part_of_admin_tree called $name.
985 *
986 * @param string $name The internal name that we're searching for.
987 * @param array $path Used internally for recursive calls. Do not specify on external calls. Defaults to array().
988 * @return mixed An array of internal names that leads to $name, or NULL if not found.
989 */
990 function path($name, $path = array()) {
eef868d1 991
6e4dc10f 992 $path[count($path)] = $this->name;
eef868d1 993
6e4dc10f 994 if ($this->name == $name) {
995 return $path;
996 }
eef868d1 997
6e4dc10f 998 foreach($this->children as $child) {
999 if ($return = $child->path($name, $path)) {
1000 return $return;
1001 }
1002 }
eef868d1 1003
6e4dc10f 1004 return NULL;
eef868d1 1005
6e4dc10f 1006 }
1007
1008 /**
1009 * Returns a reference to the part_of_admin_tree object with internal name $name.
1010 *
1011 * @param string $name The internal name of the object we want.
1012 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
1013 */
1014 function &locate($name) {
eef868d1 1015
6e4dc10f 1016 if ($this->name == $name) {
1017 return $this;
1018 }
eef868d1 1019
6e4dc10f 1020 foreach($this->children as $child) {
1021 if ($return =& $child->locate($name)) {
1022 return $return;
1023 }
1024 }
1025 $return = NULL;
1026 return $return;
1027 }
1028
4672d955 1029 /**
1030 * Removes part_of_admin_tree object with internal name $name.
1031 *
1032 * @param string $name The internal name of the object we want to remove.
a8a66c96 1033 * @return bool success
4672d955 1034 */
1035 function prune($name) {
1036
1037 if ($this->name == $name) {
1038 return false; //can not remove itself
1039 }
1040
1041 foreach($this->children as $precedence => $child) {
1042 if ($child->name == $name) {
1043 // found it!
eef868d1 1044 unset($this->children[$precedence]);
4672d955 1045 return true;
1046 }
1047 if ($this->children[$precedence]->prune($name)) {
1048 return true;
1049 }
1050 }
1051 return false;
1052 }
1053
6e4dc10f 1054 /**
1055 * Adds a part_of_admin_tree to a child or grandchild (or great-grandchild, and so forth) of this object.
1056 *
1057 * @param string $destinationame The internal name of the immediate parent that we want for &$something.
1058 * @param mixed &$something A part_of_admin_tree object to be added.
1059 * @param int $precedence The precedence of &$something when displayed. Smaller numbers mean it'll be displayed higher up in the admin menu. Defaults to '', meaning "next available position".
1060 * @return bool True if successfully added, false if &$something is not a part_of_admin_tree or if $name is not found.
1061 */
1062 function add($destinationname, &$something, $precedence = '') {
eef868d1 1063
6e4dc10f 1064 if (!is_a($something, 'part_of_admin_tree')) {
1065 return false;
1066 }
1067
1068 if ($destinationname == $this->name) {
1069 if ($precedence === '') {
1070 $this->children[] = $something;
1071 } else {
1072 if (isset($this->children[$precedence])) { // this should never, ever be triggered in a release version of moodle.
1073 echo ('<font style="color: red;">There is a precedence conflict in the category ' . $this->name . '. The object named ' . $something->name . ' is overwriting the object named ' . $this->children[$precedence]->name . '.</font><br />');
1074 }
1075 $this->children[$precedence] = $something;
1076 }
1077 return true;
1078 }
eef868d1 1079
6e4dc10f 1080 unset($entries);
eef868d1 1081
6e4dc10f 1082 $entries = array_keys($this->children);
eef868d1 1083
6e4dc10f 1084 foreach($entries as $entry) {
1085 $child =& $this->children[$entry];
1086 if (is_a($child, 'parentable_part_of_admin_tree')) {
1087 if ($child->add($destinationname, $something, $precedence)) {
1088 return true;
1089 }
1090 }
1091 }
eef868d1 1092
6e4dc10f 1093 return false;
eef868d1 1094
6e4dc10f 1095 }
eef868d1 1096
6e4dc10f 1097 /**
1098 * Checks if the user has access to anything in this category.
1099 *
1100 * @return bool True if the user has access to atleast one child in this category, false otherwise.
1101 */
1102 function check_access() {
eef868d1 1103
6e4dc10f 1104 $return = false;
1105 foreach ($this->children as $child) {
1106 $return = $return || $child->check_access();
1107 }
eef868d1 1108
6e4dc10f 1109 return $return;
eef868d1 1110
6e4dc10f 1111 }
eef868d1 1112
a8a66c96 1113 /**
1114 * Is this category hidden in admin tree block?
1115 *
1116 * @return bool True if hidden
1117 */
1118 function is_hidden() {
1119 return $this->hidden;
1120 }
6e4dc10f 1121}
1122
1123/**
1124 * Links external PHP pages into the admin tree.
1125 *
1126 * See detailed usage example at the top of this document (adminlib.php)
1127 *
1128 * @author Vincenzo K. Marcovecchio
1129 * @package admin
1130 */
1131class admin_externalpage extends part_of_admin_tree {
1132
eef868d1 1133 /**
6e4dc10f 1134 * @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects
1135 */
1136 var $name;
eef868d1 1137
6e4dc10f 1138 /**
1139 * @var string The displayed name for this external page. Usually obtained through get_string().
1140 */
1141 var $visiblename;
eef868d1 1142
6e4dc10f 1143 /**
1144 * @var string The external URL that we should link to when someone requests this external page.
1145 */
1146 var $url;
eef868d1 1147
6e4dc10f 1148 /**
1149 * @var string The role capability/permission a user must have to access this external page.
1150 */
2ce38b70 1151 var $req_capability;
eef868d1 1152
84c8ede0 1153 /**
1154 * @var object The context in which capability/permission should be checked, default is site context.
1155 */
1156 var $context;
1157
a8a66c96 1158 /**
1159 * @var bool hidden in admin tree block.
1160 */
1161 var $hidden;
1162
6e4dc10f 1163 /**
1164 * Constructor for adding an external page into the admin tree.
1165 *
1166 * @param string $name The internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects.
1167 * @param string $visiblename The displayed name for this external page. Usually obtained through get_string().
1168 * @param string $url The external URL that we should link to when someone requests this external page.
38d2d43b 1169 * @param mixed $req_capability The role capability/permission a user must have to access this external page. Defaults to 'moodle/site:config'.
6e4dc10f 1170 */
01e85af9 1171 function admin_externalpage($name, $visiblename, $url, $req_capability = 'moodle/site:config', $hidden=false, $context=NULL) {
6e4dc10f 1172 $this->name = $name;
1173 $this->visiblename = $visiblename;
1174 $this->url = $url;
38d2d43b 1175 if (is_array($req_capability)) {
1176 $this->req_capability = $req_capability;
1177 } else {
1178 $this->req_capability = array($req_capability);
1179 }
a8a66c96 1180 $this->hidden = $hidden;
84c8ede0 1181 $this->context = $context;
6e4dc10f 1182 }
eef868d1 1183
6e4dc10f 1184 /**
1185 * Finds the path to the part_of_admin_tree called $name.
1186 *
1187 * @param string $name The internal name that we're searching for.
1188 * @param array $path Used internally for recursive calls. Do not specify on external calls. Defaults to array().
1189 * @return mixed An array of internal names that leads to $name, or NULL if not found.
1190 */
1191 function path($name, $path = array()) {
1192 if ($name == $this->name) {
1193 array_push($path, $this->name);
1194 return $path;
1195 } else {
1196 return NULL;
1197 }
1198 }
eef868d1 1199
6e4dc10f 1200 /**
1201 * Returns a reference to the part_of_admin_tree object with internal name $name.
1202 *
1203 * @param string $name The internal name of the object we want.
1204 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
1205 */
1206 function &locate($name) {
1207 $return = ($this->name == $name ? $this : NULL);
1208 return $return;
1209 }
4672d955 1210
1211 function prune($name) {
1212 return false;
1213 }
1214
6e4dc10f 1215 /**
2ce38b70 1216 * Determines if the current user has access to this external page based on $this->req_capability.
6e4dc10f 1217 *
1218 * @uses CONTEXT_SYSTEM
1219 * @uses SITEID
1220 * @return bool True if user has access, false otherwise.
1221 */
1222 function check_access() {
1223 if (!get_site()) {
1224 return true; // no access check before site is fully set up
1225 }
84c8ede0 1226 $context = empty($this->context) ? get_context_instance(CONTEXT_SYSTEM) : $this->context;
38d2d43b 1227 foreach($this->req_capability as $cap) {
1228 if (has_capability($cap, $context)) {
1229 return true;
1230 }
1231 }
1232 return false;
6e4dc10f 1233 }
1234
a8a66c96 1235 /**
1236 * Is this external page hidden in admin tree block?
1237 *
1238 * @return bool True if hidden
1239 */
1240 function is_hidden() {
1241 return $this->hidden;
1242 }
1243
6e4dc10f 1244}
1245
1246/**
1247 * Used to group a number of admin_setting objects into a page and add them to the admin tree.
1248 *
1249 * @author Vincenzo K. Marcovecchio
1250 * @package admin
1251 */
1252class admin_settingpage extends part_of_admin_tree {
1253
eef868d1 1254 /**
6e4dc10f 1255 * @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects
1256 */
1257 var $name;
eef868d1 1258
6e4dc10f 1259 /**
1260 * @var string The displayed name for this external page. Usually obtained through get_string().
1261 */
1262 var $visiblename;
1263 /**
1264 * @var mixed An array of admin_setting objects that are part of this setting page.
1265 */
1266 var $settings;
eef868d1 1267
6e4dc10f 1268 /**
1269 * @var string The role capability/permission a user must have to access this external page.
1270 */
2ce38b70 1271 var $req_capability;
eef868d1 1272
84c8ede0 1273 /**
1274 * @var object The context in which capability/permission should be checked, default is site context.
1275 */
1276 var $context;
1277
a8a66c96 1278 /**
1279 * @var bool hidden in admin tree block.
1280 */
1281 var $hidden;
1282
6e4dc10f 1283 // see admin_category
1284 function path($name, $path = array()) {
1285 if ($name == $this->name) {
1286 array_push($path, $this->name);
1287 return $path;
1288 } else {
1289 return NULL;
1290 }
1291 }
eef868d1 1292
6e4dc10f 1293 // see admin_category
1294 function &locate($name) {
1295 $return = ($this->name == $name ? $this : NULL);
1296 return $return;
1297 }
4672d955 1298
1299 function prune($name) {
1300 return false;
1301 }
1302
6e4dc10f 1303 // see admin_externalpage
01e85af9 1304 function admin_settingpage($name, $visiblename, $req_capability = 'moodle/site:config', $hidden=false, $context=NULL) {
6e4dc10f 1305 global $CFG;
1306 $this->settings = new stdClass();
1307 $this->name = $name;
1308 $this->visiblename = $visiblename;
38d2d43b 1309 if (is_array($req_capability)) {
1310 $this->req_capability = $req_capability;
1311 } else {
1312 $this->req_capability = array($req_capability);
1313 }
a8a66c96 1314 $this->hidden = false;
84c8ede0 1315 $this->context = $context;
6e4dc10f 1316 }
eef868d1 1317
6e4dc10f 1318 // not the same as add for admin_category. adds an admin_setting to this admin_settingpage. settings appear (on the settingpage) in the order in which they're added
1319 // n.b. each admin_setting in an admin_settingpage must have a unique internal name
1320 // &$setting is the admin_setting object you want to add
1321 // returns true if successful, false if not (will fail if &$setting is an admin_setting or child thereof)
1322 function add(&$setting) {
1323 if (is_a($setting, 'admin_setting')) {
1324 $this->settings->{$setting->name} =& $setting;
1325 return true;
1326 }
1327 return false;
1328 }
eef868d1 1329
6e4dc10f 1330 // see admin_externalpage
1331 function check_access() {
1332 if (!get_site()) {
1333 return true; // no access check before site is fully set up
1334 }
84c8ede0 1335 $context = empty($this->context) ? get_context_instance(CONTEXT_SYSTEM) : $this->context;
38d2d43b 1336 foreach($this->req_capability as $cap) {
1337 if (has_capability($cap, $context)) {
1338 return true;
1339 }
1340 }
1341 return false;
6e4dc10f 1342 }
eef868d1 1343
6e4dc10f 1344 // outputs this page as html in a table (suitable for inclusion in an admin pagetype)
1345 // returns a string of the html
1346 function output_html() {
15a16922 1347 $return = '<fieldset>' . "\n";
6153cf58 1348 $return .= '<div class="clearer"><!-- --></div>' . "\n";
6e4dc10f 1349 foreach($this->settings as $setting) {
15a16922 1350 $return .= $setting->output_html();
6e4dc10f 1351 }
6153cf58 1352 $return .= '</fieldset>';
6e4dc10f 1353 return $return;
1354 }
1355
1356 // writes settings (the ones that have been added to this admin_settingpage) to the database, or wherever else they're supposed to be written to
1357 // -- calls write_setting() to each child setting, sending it only the data that matches each setting's internal name
1358 // $data should be the result from data_submitted()
1359 // returns an empty string if everything went well, otherwise returns a printable error string (that's language-specific)
1360 function write_settings($data) {
1361 $return = '';
1362 foreach($this->settings as $setting) {
1363 if (isset($data['s_' . $setting->name])) {
1364 $return .= $setting->write_setting($data['s_' . $setting->name]);
1365 } else {
1366 $return .= $setting->write_setting('');
1367 }
1368 }
1369 return $return;
1370 }
1371
a8a66c96 1372 /**
1373 * Is this settigns page hidden in admin tree block?
1374 *
1375 * @return bool True if hidden
1376 */
1377 function is_hidden() {
1378 return $this->hidden;
1379 }
1380
6e4dc10f 1381}
1382
1383
1384// read & write happens at this level; no authentication
1385class admin_setting {
1386
1387 var $name;
1388 var $visiblename;
1389 var $description;
1390 var $defaultsetting;
1391
1392 function admin_setting($name, $visiblename, $description, $defaultsetting) {
1393 $this->name = $name;
1394 $this->visiblename = $visiblename;
1395 $this->description = $description;
1396 $this->defaultsetting = $defaultsetting;
1397 }
eef868d1 1398
6e4dc10f 1399 function get_setting() {
1400 return NULL; // has to be overridden
1401 }
eef868d1 1402
8e5da17a 1403 function get_defaultsetting() {
1404 return $this->defaultsetting;
1405 }
1406
6e4dc10f 1407 function write_setting($data) {
1408 return; // has to be overridden
1409 }
eef868d1 1410
6e4dc10f 1411 function output_html() {
1412 return; // has to be overridden
1413 }
eef868d1 1414
6e4dc10f 1415}
1416
1417
1418class admin_setting_configtext extends admin_setting {
1419
1420 var $paramtype;
1421
50999a0b 1422 function admin_setting_configtext($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW) {
6e4dc10f 1423 $this->paramtype = $paramtype;
1424 parent::admin_setting($name, $visiblename, $description, $defaultsetting);
1425 }
1426
cc73de71 1427 // returns a string or NULL
6e4dc10f 1428 function get_setting() {
1429 global $CFG;
c8218a42 1430 return (isset($CFG->{$this->name}) ? $CFG->{$this->name} : NULL);
6e4dc10f 1431 }
eef868d1 1432
cc73de71 1433 // $data is a string
6e4dc10f 1434 function write_setting($data) {
9e24fbd1 1435 if (!$this->validate($data)) {
1436 return get_string('validateerror', 'admin') . $this->visiblename . '<br />';
c235598d 1437 }
6e4dc10f 1438 return (set_config($this->name,$data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1439 }
1440
c235598d 1441 function validate($data) {
9e24fbd1 1442 if (is_string($this->paramtype)) {
1443 return preg_match($this->paramtype, $data);
1444 } else if ($this->paramtype === PARAM_RAW) {
1445 return true;
1446 } else {
1447 $cleaned = clean_param($data, $this->paramtype);
1448 return ("$data" == "$cleaned"); // implicit conversion to string is needed to do exact comparison
1449 }
c235598d 1450 }
1451
6e4dc10f 1452 function output_html() {
c8218a42 1453 if ($this->get_setting() === NULL) {
1454 $current = $this->defaultsetting;
1455 } else {
1456 $current = $this->get_setting();
1457 }
9e24fbd1 1458 return format_admin_setting($this->name, $this->visiblename,
5259d5d8 1459 '<input type="text" class="form-text" id="id_s_'.$this->name.'" name="s_'.$this->name.'" value="'.s($current).'" />',
6153cf58 1460 $this->description);
6e4dc10f 1461 }
1462
1463}
1464
54bb33eb 1465class admin_setting_configpasswordunmask extends admin_setting_configtext {
eba8cd63 1466
54bb33eb 1467 function admin_setting_configpasswordunmask($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW) {
eba8cd63 1468 parent::admin_setting_configtext($name, $visiblename, $description, $defaultsetting, $paramtype);
1469 }
1470
1471 function output_html() {
1472 if ($this->get_setting() === NULL) {
1473 $current = $this->defaultsetting;
1474 } else {
1475 $current = $this->get_setting();
1476 }
1477 $id = 'id_s_'.$this->name;
54bb33eb 1478 $unmask = get_string('unmaskpassword', 'form');
1479 $unmaskjs = '<script type="text/javascript">
eba8cd63 1480//<![CDATA[
54bb33eb 1481document.write(\'<div class="unmask"><input id="'.$id.'unmask" value="1" type="checkbox" onclick="unmaskPassword(\\\''.$id.'\\\')"/><label for="'.$id.'unmask">'.addslashes_js($unmask).'<\/label><\/div>\');
eba8cd63 1482//]]>
1483</script>';
1484 return format_admin_setting($this->name, $this->visiblename,
54bb33eb 1485 '<input type="password" class="form-text" id="id_s_'.$this->name.'" name="s_'.$this->name.'" value="'.s($current).'" />'.$unmaskjs,
eba8cd63 1486 $this->description);
1487 }
9ba38673 1488
eba8cd63 1489}
1490
6e4dc10f 1491class admin_setting_configcheckbox extends admin_setting {
1492
1493 function admin_setting_configcheckbox($name, $visiblename, $description, $defaultsetting) {
1494 parent::admin_setting($name, $visiblename, $description, $defaultsetting);
1495 }
1496
1497 function get_setting() {
1498 global $CFG;
1499 return (isset($CFG->{$this->name}) ? $CFG->{$this->name} : NULL);
1500 }
eef868d1 1501
6e4dc10f 1502 function write_setting($data) {
1503 if ($data == '1') {
1504 return (set_config($this->name,1) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1505 } else {
1506 return (set_config($this->name,0) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1507 }
1508 }
1509
1510 function output_html() {
c8218a42 1511 if ($this->get_setting() === NULL) {
1512 $current = $this->defaultsetting;
1513 } else {
1514 $current = $this->get_setting();
1515 }
9e24fbd1 1516 return format_admin_setting($this->name, $this->visiblename,
3c6f7a78 1517 '<input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'" name="s_'. $this->name .'" value="1" ' . ($current == true ? 'checked="checked"' : '') . ' />',
6153cf58 1518 $this->description);
6e4dc10f 1519 }
1520
1521}
1522
1523class admin_setting_configselect extends admin_setting {
1524
1525 var $choices;
eef868d1 1526
6e4dc10f 1527 function admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices) {
1528 $this->choices = $choices;
1529 parent::admin_setting($name, $visiblename, $description, $defaultsetting);
1530 }
1531
1532 function get_setting() {
1533 global $CFG;
1534 return (isset($CFG->{$this->name}) ? $CFG->{$this->name} : NULL);
1535 }
eef868d1 1536
6e4dc10f 1537 function write_setting($data) {
1538 // check that what we got was in the original choices
1539 // or that the data is the default setting - needed during install when choices can not be constructed yet
1540 if ($data != $this->defaultsetting and ! in_array($data, array_keys($this->choices))) {
1541 return 'Error setting ' . $this->visiblename . '<br />';
1542 }
eef868d1 1543
6e4dc10f 1544 return (set_config($this->name, $data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1545 }
eef868d1 1546
6e4dc10f 1547 function output_html() {
c8218a42 1548 if ($this->get_setting() === NULL) {
1549 $current = $this->defaultsetting;
1550 } else {
1551 $current = $this->get_setting();
1552 }
afee9864 1553 $return = '<select class="form-select" id="id_s_'.$this->name.'" name="s_' . $this->name .'">';
6e4dc10f 1554 foreach ($this->choices as $key => $value) {
a1069b07 1555 // the string cast is needed because key may be integer - 0 is equal to most strings!
1556 $return .= '<option value="'.$key.'"'.((string)$key==$current ? ' selected="selected"' : '').'>'.$value.'</option>';
6e4dc10f 1557 }
6153cf58 1558 $return .= '</select>';
1559
fc52aa6e 1560 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
6e4dc10f 1561 }
1562
1563}
1564
1565// this is a liiitle bit messy. we're using two selects, but we're returning them as an array named after $name (so we only use $name2
1566// internally for the setting)
1567class admin_setting_configtime extends admin_setting {
1568
1569 var $name2;
1570 var $choices;
1571 var $choices2;
6e4dc10f 1572
1573 function admin_setting_configtime($hoursname, $minutesname, $visiblename, $description, $defaultsetting) {
1574 $this->name2 = $minutesname;
1575 $this->choices = array();
1576 for ($i = 0; $i < 24; $i++) {
1577 $this->choices[$i] = $i;
1578 }
1579 $this->choices2 = array();
1580 for ($i = 0; $i < 60; $i += 5) {
1581 $this->choices2[$i] = $i;
1582 }
1583 parent::admin_setting($hoursname, $visiblename, $description, $defaultsetting);
1584 }
1585
1586 function get_setting() {
1587 global $CFG;
cc73de71 1588 return (isset($CFG->{$this->name}) && isset($CFG->{$this->name2}) ? array('h' => $CFG->{$this->name}, 'm' => $CFG->{$this->name2}) : NULL);
6e4dc10f 1589 }
eef868d1 1590
6e4dc10f 1591 function write_setting($data) {
1592 // check that what we got was in the original choices
1593 if (!(in_array($data['h'], array_keys($this->choices)) && in_array($data['m'], array_keys($this->choices2)))) {
1594 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
1595 }
eef868d1 1596
6e4dc10f 1597 return (set_config($this->name, $data['h']) && set_config($this->name2, $data['m']) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1598 }
eef868d1 1599
6e4dc10f 1600 function output_html() {
cc73de71 1601 if ($this->get_setting() === NULL) {
1602 $currentsetting = $this->defaultsetting;
1603 } else {
1604 $currentsetting = $this->get_setting();
6e4dc10f 1605 }
2e0c11dd 1606 $return = '<div class="form-group">'.
1607 '<select class="form-select" id="id_s_'.$this->name.'h" name="s_' . $this->name .'[h]">';
6e4dc10f 1608 foreach ($this->choices as $key => $value) {
cc73de71 1609 $return .= '<option value="' . $key . '"' . ($key == $currentsetting['h'] ? ' selected="selected"' : '') . '>' . $value . '</option>';
6e4dc10f 1610 }
2e0c11dd 1611 $return .= '</select>:<select class="form-select" id="id_s_'.$this->name.'m" name="s_' . $this->name . '[m]">';
6e4dc10f 1612 foreach ($this->choices2 as $key => $value) {
cc73de71 1613 $return .= '<option value="' . $key . '"' . ($key == $currentsetting['m'] ? ' selected="selected"' : '') . '>' . $value . '</option>';
eef868d1 1614 }
2e0c11dd 1615 $return .= '</select></div>';
fbe31d22 1616 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
6e4dc10f 1617 }
1618
1619}
1620
1621class admin_setting_configmultiselect extends admin_setting_configselect {
1622
1623 function admin_setting_configmultiselect($name, $visiblename, $description, $defaultsetting, $choices) {
1624 parent::admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices);
1625 }
1626
1627 function get_setting() {
1628 global $CFG;
d7933a55 1629 if (isset($CFG->{$this->name})) {
1630 if ($CFG->{$this->name}) {
1631 return explode(',', $CFG->{$this->name});
1632 } else {
1633 return array();
9ba38673 1634 }
d7933a55 1635 } else {
1636 return NULL;
1637 }
6e4dc10f 1638 }
eef868d1 1639
6e4dc10f 1640 function write_setting($data) {
d7933a55 1641 if (empty($data)) {
1642 $data = array();
1643 }
6e4dc10f 1644 foreach ($data as $datum) {
1645 if (! in_array($datum, array_keys($this->choices))) {
1646 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
1647 }
1648 }
eef868d1 1649
6e4dc10f 1650 return (set_config($this->name, implode(',',$data)) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1651 }
eef868d1 1652
6e4dc10f 1653 function output_html() {
cc73de71 1654 if ($this->get_setting() === NULL) {
1655 $currentsetting = $this->defaultsetting;
0b0f7c00 1656 if (!$currentsetting) {
1657 $currentsetting = array();
1658 }
cc73de71 1659 } else {
1660 $currentsetting = $this->get_setting();
6e4dc10f 1661 }
afee9864 1662 $return = '<select class="form-select" id="id_s_'.$this->name.'" name="s_' . $this->name .'[]" size="10" multiple="multiple">';
6e4dc10f 1663 foreach ($this->choices as $key => $value) {
1664 $return .= '<option value="' . $key . '"' . (in_array($key,$currentsetting) ? ' selected="selected"' : '') . '>' . $value . '</option>';
1665 }
6153cf58 1666 $return .= '</select>';
fc52aa6e 1667 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
6e4dc10f 1668 }
1669
1670}
1671
1672class admin_setting_special_adminseesall extends admin_setting_configcheckbox {
eef868d1 1673
6e4dc10f 1674 function admin_setting_special_adminseesall() {
1675 $name = 'calendar_adminseesall';
1676 $visiblename = get_string('adminseesall', 'admin');
1677 $description = get_string('helpadminseesall', 'admin');
1678 parent::admin_setting($name, $visiblename, $description, 0);
1679 }
1680
1681 function write_setting($data) {
1682 global $SESSION;
1683 unset($SESSION->cal_courses_shown);
1684 parent::write_setting($data);
1685 }
1686}
1687
1688class admin_setting_sitesetselect extends admin_setting_configselect {
1689
1690 var $id;
1691
1692 function admin_setting_sitesetselect($name, $visiblename, $description, $defaultsetting, $choices) {
1693
1694 $this->id = SITEID;
1695 parent::admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices);
eef868d1 1696
6e4dc10f 1697 }
eef868d1 1698
6e4dc10f 1699 function get_setting() {
1700 $site = get_site();
1701 return (isset($site->{$this->name}) ? $site->{$this->name} : NULL);
1702 }
eef868d1 1703
6e4dc10f 1704 function write_setting($data) {
1705 if (!in_array($data, array_keys($this->choices))) {
1706 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
1707 }
1708 $record = new stdClass();
1709 $record->id = $this->id;
1710 $temp = $this->name;
1711 $record->$temp = $data;
1712 $record->timemodified = time();
1713 return (update_record('course', $record) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1714 }
eef868d1 1715
6e4dc10f 1716}
1717
1718
e0f6e995 1719class admin_setting_courselist_frontpage extends admin_setting_configselect {
6e4dc10f 1720
e0f6e995 1721 function admin_setting_courselist_frontpage($loggedin) {
6e4dc10f 1722 global $CFG;
1723 require_once($CFG->dirroot . '/course/lib.php');
1724 $name = 'frontpage' . ($loggedin ? 'loggedin' : '');
1725 $visiblename = get_string('frontpage' . ($loggedin ? 'loggedin' : ''),'admin');
1726 $description = get_string('configfrontpage' . ($loggedin ? 'loggedin' : ''),'admin');
1727 $choices = array(FRONTPAGENEWS => get_string('frontpagenews'),
1728 FRONTPAGECOURSELIST => get_string('frontpagecourselist'),
1729 FRONTPAGECATEGORYNAMES => get_string('frontpagecategorynames'),
1730 FRONTPAGECATEGORYCOMBO => get_string('frontpagecategorycombo'),
1731 '' => get_string('none'));
9fec4e33 1732 if (!$loggedin and count_records("course") > FRONTPAGECOURSELIMIT) {
6e4dc10f 1733 unset($choices[FRONTPAGECOURSELIST]);
1734 }
4672d955 1735 $defaults = FRONTPAGECOURSELIST.',,,';
e0f6e995 1736 parent::admin_setting_configselect($name, $visiblename, $description, $defaults, $choices);
6e4dc10f 1737 }
eef868d1 1738
6e4dc10f 1739 function get_setting() {
1740 global $CFG;
1c1e7af4 1741 return (isset($CFG->{$this->name}) ? explode(',', $CFG->{$this->name}) : ',1,,');
6e4dc10f 1742 }
eef868d1 1743
6e4dc10f 1744 function write_setting($data) {
1745 if (empty($data)) {
1746 $data = array();
e0f6e995 1747 } if (!is_array($data)) {
1748 $data = explode(',', $data);
6e4dc10f 1749 }
1750 foreach($data as $datum) {
1751 if (! in_array($datum, array_keys($this->choices))) {
1752 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
1753 }
1754 }
1755 return (set_config($this->name, implode(',', $data)) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1756 }
eef868d1 1757
6e4dc10f 1758 function output_html() {
cc73de71 1759 if ($this->get_setting() === NULL) {
1760 $currentsetting = $this->defaultsetting;
1761 } else {
1762 $currentsetting = $this->get_setting();
6e4dc10f 1763 }
1764 for ($i = 0; $i < count($this->choices) - 1; $i++) {
1765 if (!isset($currentsetting[$i])) {
1766 $currentsetting[$i] = 0;
1767 }
1768 }
0a7e84c3 1769 $return = '<div class="form-group">';
6e4dc10f 1770 for ($i = 0; $i < count($this->choices) - 1; $i++) {
a1d52643 1771 $return .='<select class="form-select" id="id_s_'.$this->name.$i.'" name="s_' . $this->name .'[]">';
6e4dc10f 1772 foreach ($this->choices as $key => $value) {
1773 $return .= '<option value="' . $key . '"' . ($key == $currentsetting[$i] ? ' selected="selected"' : '') . '>' . $value . '</option>';
1774 }
1775 $return .= '</select>';
1776 if ($i !== count($this->choices) - 2) {
975211bb 1777 $return .= '<br />';
6e4dc10f 1778 }
1779 }
0a7e84c3 1780 $return .= '</div>';
1781
fbe31d22 1782 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
6e4dc10f 1783 }
1784}
1785
1786class admin_setting_sitesetcheckbox extends admin_setting_configcheckbox {
1787
1788 var $id;
1789
1790 function admin_setting_sitesetcheckbox($name, $visiblename, $description, $defaultsetting) {
1791
1792 $this->id = SITEID;
1793 parent::admin_setting_configcheckbox($name, $visiblename, $description, $defaultsetting);
eef868d1 1794
6e4dc10f 1795 }
eef868d1 1796
6e4dc10f 1797 function get_setting() {
1798 $site = get_site();
8e5da17a 1799 return $site->{$this->name};
6e4dc10f 1800 }
eef868d1 1801
6e4dc10f 1802 function write_setting($data) {
1803 $record = new stdClass();
1804 $record->id = $this->id;
1805 $temp = $this->name;
1806 $record->$temp = ($data == '1' ? 1 : 0);
1807 $record->timemodified = time();
1808 return (update_record('course', $record) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1809 }
eef868d1 1810
6e4dc10f 1811}
1812
1813class admin_setting_sitesettext extends admin_setting_configtext {
1814
1815 var $id;
1816
b89639f9 1817 function admin_setting_sitesettext($name, $visiblename, $description, $defaultsetting) {
6e4dc10f 1818
1819 $this->id = SITEID;
b89639f9 1820 parent::admin_setting_configtext($name, $visiblename, $description, $defaultsetting);
eef868d1 1821
6e4dc10f 1822 }
eef868d1 1823
6e4dc10f 1824 function get_setting() {
1825 $site = get_site();
8e5da17a 1826 return $site->{$this->name} != '' ? $site->{$this->name} : NULL;
6e4dc10f 1827 }
90cfbd0a 1828
b89639f9 1829 function validate($data) {
b0abd282 1830 $cleaned = stripslashes(clean_param($data, PARAM_MULTILANG));
b89639f9 1831 if ($cleaned == '') {
1832 return false; // can not be empty
1833 }
b0abd282 1834 return ($data == $cleaned); // implicit conversion to string is needed to do exact comparison
b89639f9 1835 }
1836
6e4dc10f 1837 function write_setting($data) {
b89639f9 1838 $data = trim($data);
9e24fbd1 1839 if (!$this->validate($data)) {
1840 return get_string('validateerror', 'admin') . $this->visiblename . '<br />';
90cfbd0a 1841 }
eef868d1 1842
6e4dc10f 1843 $record = new stdClass();
1844 $record->id = $this->id;
87fa8a17 1845 $record->{$this->name} = addslashes($data);
6e4dc10f 1846 $record->timemodified = time();
23a97d83 1847 return (update_record('course', $record) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
6e4dc10f 1848 }
90cfbd0a 1849
6e4dc10f 1850}
1851
1852class admin_setting_special_frontpagedesc extends admin_setting {
1853
1854 var $id;
eef868d1 1855
6e4dc10f 1856 function admin_setting_special_frontpagedesc() {
1857 $this->id = SITEID;
1858 $name = 'summary';
1859 $visiblename = get_string('frontpagedescription');
1860 $description = get_string('frontpagedescriptionhelp');
1861 parent::admin_setting($name, $visiblename, $description, '');
1862 }
1863
1864 function output_html() {
fa040029 1865 global $CFG;
1866
fa040029 1867 $CFG->adminusehtmleditor = can_use_html_editor();
c626c2f4 1868 $return = print_textarea($CFG->adminusehtmleditor, 15, 60, 0, 0, 's_' . $this->name, $this->get_setting(), 0, true);
eef868d1 1869
fbe31d22 1870 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
6e4dc10f 1871 }
eef868d1 1872
6e4dc10f 1873 function get_setting() {
6e4dc10f 1874 $site = get_site();
c626c2f4 1875 return $site->{$this->name};
1876 }
eef868d1 1877
c626c2f4 1878 function get_defaultsetting() {
1879 return NULL;
6e4dc10f 1880 }
eef868d1 1881
6e4dc10f 1882 function write_setting($data) {
c626c2f4 1883 $record = new object();
1884 $record->id = $this->id;
1885 $record->{$this->name} = addslashes($data);
1886 $record->timemodified = time();
eef868d1 1887
6e4dc10f 1888 return(update_record('course', $record) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
6e4dc10f 1889 }
1890
1891}
1892
1893
1894class admin_setting_special_editorfontlist extends admin_setting {
1895
1896 var $items;
1897
1898 function admin_setting_special_editorfontlist() {
1899 global $CFG;
1900 $name = 'editorfontlist';
1901 $visiblename = get_string('editorfontlist', 'admin');
1902 $description = get_string('configeditorfontlist', 'admin');
6e4dc10f 1903 $defaults = array('k0' => 'Trebuchet',
1904 'v0' => 'Trebuchet MS,Verdana,Arial,Helvetica,sans-serif',
1905 'k1' => 'Arial',
1906 'v1' => 'arial,helvetica,sans-serif',
1907 'k2' => 'Courier New',
1908 'v2' => 'courier new,courier,monospace',
1909 'k3' => 'Georgia',
1910 'v3' => 'georgia,times new roman,times,serif',
1911 'k4' => 'Tahoma',
1912 'v4' => 'tahoma,arial,helvetica,sans-serif',
1913 'k5' => 'Times New Roman',
1914 'v5' => 'times new roman,times,serif',
1915 'k6' => 'Verdana',
1916 'v6' => 'verdana,arial,helvetica,sans-serif',
1917 'k7' => 'Impact',
1918 'v7' => 'impact',
1919 'k8' => 'Wingdings',
1920 'v8' => 'wingdings');
1921 parent::admin_setting($name, $visiblename, $description, $defaults);
1922 }
eef868d1 1923
6e4dc10f 1924 function get_setting() {
cc73de71 1925 global $CFG;
1926 if (isset($CFG->editorfontlist)) {
1927 $i = 0;
1928 $currentsetting = array();
1929 $items = explode(';', $CFG->editorfontlist);
1930 foreach ($items as $item) {
1931 $item = explode(':', $item);
1932 $currentsetting['k' . $i] = $item[0];
1933 $currentsetting['v' . $i] = $item[1];
1934 $i++;
1935 }
1936 return $currentsetting;
1937 } else {
1938 return NULL;
1939 }
6e4dc10f 1940 }
eef868d1 1941
6e4dc10f 1942 function write_setting($data) {
eef868d1 1943
6e4dc10f 1944 // there miiight be an easier way to do this :)
1945 // if this is changed, make sure the $defaults array above is modified so that this
1946 // function processes it correctly
eef868d1 1947
6e4dc10f 1948 $keys = array();
1949 $values = array();
eef868d1 1950
6e4dc10f 1951 foreach ($data as $key => $value) {
1952 if (substr($key,0,1) == 'k') {
1953 $keys[substr($key,1)] = $value;
1954 } elseif (substr($key,0,1) == 'v') {
1955 $values[substr($key,1)] = $value;
1956 }
1957 }
eef868d1 1958
6e4dc10f 1959 $result = '';
1960 for ($i = 0; $i < count($keys); $i++) {
1961 if (($keys[$i] !== '') && ($values[$i] !== '')) {
1962 $result .= clean_param($keys[$i],PARAM_NOTAGS) . ':' . clean_param($values[$i], PARAM_NOTAGS) . ';';
1963 }
1964 }
eef868d1 1965
6e4dc10f 1966 $result = substr($result, 0, -1); // trim the last semicolon
eef868d1 1967
6e4dc10f 1968 return (set_config($this->name, $result) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1969 }
eef868d1 1970
6e4dc10f 1971 function output_html() {
eef868d1 1972
cc73de71 1973 if ($this->get_setting() === NULL) {
1974 $currentsetting = $this->defaultsetting;
1975 } else {
1976 $currentsetting = $this->get_setting();
6e4dc10f 1977 }
eef868d1 1978
1beed35f 1979 $return = '<div class="form-group">';
cc73de71 1980 for ($i = 0; $i < count($currentsetting) / 2; $i++) {
3c6f7a78 1981 $return .= '<input type="text" class="form-text" name="s_editorfontlist[k' . $i . ']" value="' . $currentsetting['k' . $i] . '" />';
6e4dc10f 1982 $return .= '&nbsp;&nbsp;';
3c6f7a78 1983 $return .= '<input type="text" class="form-text" name="s_editorfontlist[v' . $i . ']" value="' . $currentsetting['v' . $i] . '" /><br />';
6e4dc10f 1984 }
3c6f7a78 1985 $return .= '<input type="text" class="form-text" name="s_editorfontlist[k' . $i . ']" value="" />';
6e4dc10f 1986 $return .= '&nbsp;&nbsp;';
3c6f7a78 1987 $return .= '<input type="text" class="form-text" name="s_editorfontlist[v' . $i . ']" value="" /><br />';
1988 $return .= '<input type="text" class="form-text" name="s_editorfontlist[k' . ($i + 1) . ']" value="" />';
6e4dc10f 1989 $return .= '&nbsp;&nbsp;';
3c6f7a78 1990 $return .= '<input type="text" class="form-text" name="s_editorfontlist[v' . ($i + 1) . ']" value="" />';
1beed35f 1991 $return .= '</div>';
6153cf58 1992
60a9a6ea 1993 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
6e4dc10f 1994 }
eef868d1 1995
6e4dc10f 1996}
1997
1998class admin_setting_special_editordictionary extends admin_setting_configselect {
1999
2000 function admin_setting_special_editordictionary() {
2001 $name = 'editordictionary';
2002 $visiblename = get_string('editordictionary','admin');
2003 $description = get_string('configeditordictionary', 'admin');
2004 $choices = $this->editor_get_dictionaries();
2005 if (! is_array($choices)) {
2006 $choices = array('');
2007 }
eef868d1 2008
6e4dc10f 2009 parent::admin_setting_configselect($name, $visiblename, $description, '', $choices);
2010 }
2011
2012 // function borrowed from the old moodle/admin/editor.php, slightly modified
2013 function editor_get_dictionaries () {
2014 /// Get all installed dictionaries in the system
2015
2016 global $CFG;
eef868d1 2017
6e4dc10f 2018// error_reporting(E_ALL); // for debug, final version shouldn't have this...
2019 clearstatcache();
2020
2021 // If aspellpath isn't set don't even bother ;-)
2022 if (empty($CFG->aspellpath)) {
2023 return 'Empty aspell path!';
2024 }
2025
2026 // Do we have access to popen function?
2027 if (!function_exists('popen')) {
2028 return 'Popen function disabled!';
2029 }
eef868d1 2030
6e4dc10f 2031 $cmd = $CFG->aspellpath;
2032 $output = '';
2033 $dictionaries = array();
2034 $dicts = array();
2035
2036 if(!($handle = @popen(escapeshellarg($cmd) .' dump dicts', 'r'))) {
2037 return 'Couldn\'t create handle!';
2038 }
2039
2040 while(!feof($handle)) {
2041 $output .= fread($handle, 1024);
2042 }
2043 @pclose($handle);
2044
2045 $dictionaries = explode(chr(10), $output);
2046
2047 // Get rid of possible empty values
2048 if (is_array($dictionaries)) {
2049
2050 $cnt = count($dictionaries);
2051
2052 for ($i = 0; $i < $cnt; $i++) {
2053 if (!empty($dictionaries[$i])) {
2c41b2d7 2054 $dicts[$dictionaries[$i]] = $dictionaries[$i];
6e4dc10f 2055 }
2056 }
2057 }
2058
2059 if (count($dicts) >= 1) {
2060 return $dicts;
2061 }
2062
2063 return 'Error! Check your aspell installation!';
2064 }
2065
eef868d1 2066
6e4dc10f 2067
2068}
2069
2070
2071class admin_setting_special_editorhidebuttons extends admin_setting {
2072
2073 var $name;
2074 var $visiblename;
2075 var $description;
2076 var $items;
2077
2078 function admin_setting_special_editorhidebuttons() {
2079 $this->name = 'editorhidebuttons';
2080 $this->visiblename = get_string('editorhidebuttons', 'admin');
2081 $this->description = get_string('confeditorhidebuttons', 'admin');
2082 $this->defaultsetting = array();
2083 // weird array... buttonname => buttonimage (assume proper path appended). if you leave buttomimage blank, text will be printed instead
2084 $this->items = array('fontname' => '',
2085 'fontsize' => '',
2086 'formatblock' => '',
2087 'bold' => 'ed_format_bold.gif',
2088 'italic' => 'ed_format_italic.gif',
2089 'underline' => 'ed_format_underline.gif',
2090 'strikethrough' => 'ed_format_strike.gif',
2091 'subscript' => 'ed_format_sub.gif',
2092 'superscript' => 'ed_format_sup.gif',
2093 'copy' => 'ed_copy.gif',
2094 'cut' => 'ed_cut.gif',
2095 'paste' => 'ed_paste.gif',
2096 'clean' => 'ed_wordclean.gif',
2097 'undo' => 'ed_undo.gif',
2098 'redo' => 'ed_redo.gif',
2099 'justifyleft' => 'ed_align_left.gif',
2100 'justifycenter' => 'ed_align_center.gif',
2101 'justifyright' => 'ed_align_right.gif',
2102 'justifyfull' => 'ed_align_justify.gif',
2103 'lefttoright' => 'ed_left_to_right.gif',
2104 'righttoleft' => 'ed_right_to_left.gif',
2105 'insertorderedlist' => 'ed_list_num.gif',
2106 'insertunorderedlist' => 'ed_list_bullet.gif',
2107 'outdent' => 'ed_indent_less.gif',
2108 'indent' => 'ed_indent_more.gif',
2109 'forecolor' => 'ed_color_fg.gif',
2110 'hilitecolor' => 'ed_color_bg.gif',
2111 'inserthorizontalrule' => 'ed_hr.gif',
2112 'createanchor' => 'ed_anchor.gif',
2113 'createlink' => 'ed_link.gif',
2114 'unlink' => 'ed_unlink.gif',
2115 'insertimage' => 'ed_image.gif',
2116 'inserttable' => 'insert_table.gif',
2117 'insertsmile' => 'em.icon.smile.gif',
2118 'insertchar' => 'icon_ins_char.gif',
2119 'spellcheck' => 'spell-check.gif',
2120 'htmlmode' => 'ed_html.gif',
2121 'popupeditor' => 'fullscreen_maximize.gif',
2122 'search_replace' => 'ed_replace.gif');
2123 }
2124
2125 function get_setting() {
2126 global $CFG;
2127 return (isset($CFG->{$this->name}) ? explode(' ', $CFG->{$this->name}) : NULL);
2128 }
2129
2130 function write_setting($data) {
2131 $result = array();
2132 if (empty($data)) { $data = array(); }
2133 foreach ($data as $key => $value) {
2134 if (!in_array($key, array_keys($this->items))) {
2135 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2136 }
2137 if ($value == '1') {
2138 $result[] = $key;
2139 }
2140 }
2141 return (set_config($this->name, implode(' ',$result)) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2142 }
2143
2144 function output_html() {
eef868d1 2145
6e4dc10f 2146 global $CFG;
eef868d1 2147
6e4dc10f 2148 // checkboxes with input name="$this->name[$key]" value="1"
2149 // we do 15 fields per column
eef868d1 2150
cc73de71 2151 if ($this->get_setting() === NULL) {
2152 $currentsetting = $this->defaultsetting;
2153 } else {
2154 $currentsetting = $this->get_setting();
6e4dc10f 2155 }
eef868d1 2156
1beed35f 2157 $return = '<div class="form-group">';
2158 $return .= '<table><tr><td valign="top" align="right">';
eef868d1 2159
6e4dc10f 2160 $count = 0;
eef868d1 2161
6e4dc10f 2162 foreach($this->items as $key => $value) {
8ddbd7a6 2163 if ($count % 15 == 0 and $count != 0) {
2164 $return .= '</td><td valign="top" align="right">';
6e4dc10f 2165 }
eef868d1 2166
6e4dc10f 2167 $return .= ($value == '' ? get_string($key,'editor') : '<img width="18" height="18" src="' . $CFG->wwwroot . '/lib/editor/htmlarea/images/' . $value . '" alt="' . get_string($key,'editor') . '" title="' . get_string($key,'editor') . '" />') . '&nbsp;';
afee9864 2168 $return .= '<input type="checkbox" class="form-checkbox" value="1" id="id_s_'.$this->name.$key.'" name="s_' . $this->name . '[' . $key . ']"' . (in_array($key,$currentsetting) ? ' checked="checked"' : '') . ' />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
6e4dc10f 2169 $count++;
2170 if ($count % 15 != 0) {
2171 $return .= '<br /><br />';
2172 }
2173 }
eef868d1 2174
2175 $return .= '</td></tr>';
6e4dc10f 2176 $return .= '</table>';
1beed35f 2177 $return .= '</div>';
6e4dc10f 2178
60a9a6ea 2179 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
6e4dc10f 2180 }
2181
2182}
2183
4642650f 2184class admin_setting_langlist extends admin_setting_configtext {
2185 function admin_setting_langlist() {
2186 parent::admin_setting_configtext('langlist', get_string('langlist', 'admin'), get_string('configlanglist', 'admin'), '', PARAM_NOTAGS);
2187 }
2188
2189 function write_setting($data) {
2190 $return = parent::write_setting($data);
2191 get_list_of_languages(true);//refresh the list
2192 return $return;
2193 }
2194}
2195
6e4dc10f 2196class admin_setting_backupselect extends admin_setting_configselect {
2197
2198 function admin_setting_backupselect($name, $visiblename, $description, $default, $choices) {
2199 parent::admin_setting_configselect($name, $visiblename, $description, $default, $choices);
2200 }
2201
2202 function get_setting() {
2203 $backup_config = backup_get_config();
2204 return (isset($backup_config->{$this->name}) ? $backup_config->{$this->name} : NULL);
2205 }
eef868d1 2206
6e4dc10f 2207 function write_setting($data) {
2208 // check that what we got was in the original choices
2209 if (! in_array($data, array_keys($this->choices))) {
2210 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2211 }
eef868d1 2212
6e4dc10f 2213 return (backup_set_config($this->name, $data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2214 }
2215
2216}
2217
2218class admin_setting_special_backupsaveto extends admin_setting_configtext {
2219
2220 function admin_setting_special_backupsaveto() {
2221 $name = 'backup_sche_destination';
2222 $visiblename = get_string('saveto');
2223 $description = get_string('backupsavetohelp');
348d6827 2224 parent::admin_setting_configtext($name, $visiblename, $description, '');
6e4dc10f 2225 }
eef868d1 2226
6e4dc10f 2227 function get_setting() {
2228 $backup_config = backup_get_config();
2229 return (isset($backup_config->{$this->name}) ? $backup_config->{$this->name} : NULL);
2230 }
eef868d1 2231
6e4dc10f 2232 function write_setting($data) {
348d6827 2233 $data = trim($data);
2234 if (!empty($data) and !is_dir($data)) {
6e4dc10f 2235 return get_string('pathnotexists') . '<br />';
2236 }
2237 return (backup_set_config($this->name, $data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2238 }
2239
2240}
2241
2242class admin_setting_backupcheckbox extends admin_setting_configcheckbox {
2243
2244 function admin_setting_backupcheckbox($name, $visiblename, $description, $default) {
2245 parent::admin_setting_configcheckbox($name, $visiblename, $description, $default);
2246 }
2247
2248 function write_setting($data) {
2249 if ($data == '1') {
2250 return (backup_set_config($this->name, 1) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2251 } else {
2252 return (backup_set_config($this->name, 0) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2253 }
2254 }
eef868d1 2255
6e4dc10f 2256 function get_setting() {
2257 $backup_config = backup_get_config();
2258 return (isset($backup_config->{$this->name}) ? $backup_config->{$this->name} : NULL);
2259 }
2260
2261}
2262
2263class admin_setting_special_backuptime extends admin_setting_configtime {
2264
2265 function admin_setting_special_backuptime() {
2266 $name = 'backup_sche_hour';
2267 $name2 = 'backup_sche_minute';
2268 $visiblename = get_string('executeat');
2269 $description = get_string('backupexecuteathelp');
2270 $default = array('h' => 0, 'm' => 0);
2271 parent::admin_setting_configtime($name, $name2, $visiblename, $description, $default);
2272 }
eef868d1 2273
6e4dc10f 2274 function get_setting() {
2275 $backup_config = backup_get_config();
9fd9df20 2276 return (isset($backup_config->{$this->name}) && isset($backup_config->{$this->name}) ? array('h'=>$backup_config->{$this->name}, 'm'=>$backup_config->{$this->name2}) : NULL);
6e4dc10f 2277 }
eef868d1 2278
6e4dc10f 2279 function write_setting($data) {
2280 // check that what we got was in the original choices
2281 if (!(in_array($data['h'], array_keys($this->choices)) && in_array($data['m'], array_keys($this->choices2)))) {
2282 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2283 }
eef868d1 2284
2285 return (backup_set_config($this->name, $data['h']) && backup_set_config($this->name2, $data['m']) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
6e4dc10f 2286 }
eef868d1 2287
6e4dc10f 2288}
2289
2290class admin_setting_special_backupdays extends admin_setting {
2291
2292 function admin_setting_special_backupdays() {
2293 $name = 'backup_sche_weekdays';
2294 $visiblename = get_string('schedule');
2295 $description = get_string('backupschedulehelp');
6727c175 2296 $default = array('u' => 0, 'm' => 0, 't' => 0, 'w' => 0, 'r' => 0, 'f' => 0, 's' => 0);
2297 parent::admin_setting($name, $visiblename, $description, $default);
6e4dc10f 2298 }
eef868d1 2299
6e4dc10f 2300 function get_setting() {
2301 $backup_config = backup_get_config();
cc73de71 2302 if (isset($backup_config->{$this->name})) {
2303 $currentsetting = $backup_config->{$this->name};
2304 return array('u' => substr($currentsetting, 0, 1),
2305 'm' => substr($currentsetting, 1, 1),
2306 't' => substr($currentsetting, 2, 1),
2307 'w' => substr($currentsetting, 3, 1),
2308 'r' => substr($currentsetting, 4, 1),
2309 'f' => substr($currentsetting, 5, 1),
2310 's' => substr($currentsetting, 6, 1));
2311 } else {
2312 return NULL;
2313 }
6e4dc10f 2314 }
eef868d1 2315
6e4dc10f 2316 function output_html() {
eef868d1 2317
cc73de71 2318 if ($this->get_setting() === NULL) {
2319 $currentsetting = $this->defaultsetting;
2320 } else {
2321 $currentsetting = $this->get_setting();
6e4dc10f 2322 }
eef868d1 2323
cc73de71 2324 // rewrite for simplicity
eef868d1 2325 $currentsetting = $currentsetting['u'] . $currentsetting['m'] . $currentsetting['t'] . $currentsetting['w'] .
cc73de71 2326 $currentsetting['r'] . $currentsetting['f'] . $currentsetting['s'];
eef868d1 2327
60a9a6ea 2328 $return = '<table><tr><td><div style="text-align:center">&nbsp;&nbsp;' . get_string('sunday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div style="text-align:center">&nbsp;&nbsp;' .
2329 get_string('monday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div style="text-align:center">&nbsp;&nbsp;' . get_string('tuesday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div style="text-align:center">&nbsp;&nbsp;' .
2330 get_string('wednesday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div style="text-align:center">&nbsp;&nbsp;' . get_string('thursday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div style="text-align:center">&nbsp;&nbsp;' .
2331 get_string('friday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div style="text-align:center">&nbsp;&nbsp;' . get_string('saturday', 'calendar') . '&nbsp;&nbsp;</div></td></tr><tr>' .
2332 '<td><div style="text-align:center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'u" name="s_'. $this->name .'[u]" value="1" ' . (substr($currentsetting,0,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2333 '<td><div style="text-align:center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'m" name="s_'. $this->name .'[m]" value="1" ' . (substr($currentsetting,1,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2334 '<td><div style="text-align:center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'t" name="s_'. $this->name .'[t]" value="1" ' . (substr($currentsetting,2,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2335 '<td><div style="text-align:center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'w" name="s_'. $this->name .'[w]" value="1" ' . (substr($currentsetting,3,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2336 '<td><div style="text-align:center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'r" name="s_'. $this->name .'[r]" value="1" ' . (substr($currentsetting,4,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2337 '<td><div style="text-align:center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'f" name="s_'. $this->name .'[f]" value="1" ' . (substr($currentsetting,5,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2338 '<td><div style="text-align:center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'s" name="s_'. $this->name .'[s]" value="1" ' . (substr($currentsetting,6,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
6153cf58 2339 '</tr></table>';
2340
60a9a6ea 2341 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
eef868d1 2342
6e4dc10f 2343 }
eef868d1 2344
6e4dc10f 2345 // we're using the array trick (see http://ca.php.net/manual/en/faq.html.php#faq.html.arrays) to get the data passed to use without having to modify
2346 // admin_settingpage (note that admin_settingpage only calls write_setting with the data that matches $this->name... so if we have multiple form fields,
2347 // they MUST go into an array named $this->name, or else we won't receive them here
2348 function write_setting($data) {
2349 $week = 'umtwrfs';
2350 $result = array(0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0);
9fd9df20 2351 if (!empty($data)) {
2352 foreach($data as $key => $value) {
2353 if ($value == '1') {
2354 $result[strpos($week, $key)] = 1;
2355 }
2356 }
6e4dc10f 2357 }
2358 return (backup_set_config($this->name, implode('',$result)) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2359 }
2360}
2361
ee437bbc 2362class admin_setting_special_debug extends admin_setting_configselect {
6e4dc10f 2363
2364 function admin_setting_special_debug() {
2365 $name = 'debug';
2366 $visiblename = get_string('debug', 'admin');
2367 $description = get_string('configdebug', 'admin');
7eb0b60a 2368 $choices = array( DEBUG_NONE => get_string('debugnone', 'admin'),
2369 DEBUG_MINIMAL => get_string('debugminimal', 'admin'),
2370 DEBUG_NORMAL => get_string('debugnormal', 'admin'),
38d2d43b 2371 DEBUG_ALL => get_string('debugall', 'admin'),
2372 DEBUG_DEVELOPER => get_string('debugdeveloper', 'admin')
ee437bbc 2373 );
2374 parent::admin_setting_configselect($name, $visiblename, $description, '', $choices);
6e4dc10f 2375 }
2376
ee437bbc 2377 function get_setting() {
2378 global $CFG;
cc73de71 2379 if (isset($CFG->debug)) {
cc73de71 2380 return $CFG->debug;
2381 } else {
2382 return NULL;
ee437bbc 2383 }
6e4dc10f 2384 }
2385
ee437bbc 2386 function write_setting($data) {
2387 return (set_config($this->name,$data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
6e4dc10f 2388 }
2389
2390}
2391
2392
2393class admin_setting_special_calendar_weekend extends admin_setting {
2394
2395 function admin_setting_special_calendar_weekend() {
2396 $name = 'calendar_weekend';
2397 $visiblename = get_string('calendar_weekend', 'admin');
2398 $description = get_string('helpweekenddays', 'admin');
5eaa6aa0 2399 $default = array ('0', '6'); // Saturdays and Sundays
b91b1f92 2400 parent::admin_setting($name, $visiblename, $description, $default);
6e4dc10f 2401 }
2402
2403 function get_setting() {
2404 global $CFG;
4af8d5d3 2405 return isset($CFG->{$this->name}) ? $CFG->{$this->name} : 0;
6e4dc10f 2406 }
eef868d1 2407
6e4dc10f 2408 function write_setting($data) {
4af8d5d3 2409 $result = 0;
b91b1f92 2410 if (!empty($data)) {
4af8d5d3 2411 foreach($data as $index) {
2412 $result |= 1 << $index;
b91b1f92 2413 }
6e4dc10f 2414 }
4af8d5d3 2415 return (set_config($this->name, $result) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
6e4dc10f 2416 }
eef868d1 2417
6e4dc10f 2418 function output_html() {
cc73de71 2419 if ($this->get_setting() === NULL) {
2420 $currentsetting = $this->defaultsetting;
2421 } else {
2422 $currentsetting = $this->get_setting();
6e4dc10f 2423 }
cc73de71 2424
4af8d5d3 2425 // The order matters very much because of the implied numeric keys
2426 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
2427 $return = '<table><thead><tr>';
2428 foreach($days as $index => $day) {
2429 $return .= '<td><label for="id_s_'.$this->name.$index.'">'.get_string($day, 'calendar').'</label></td>';
2430 }
2431 $return .= '</tr></thead><tbody><tr>';
2432 foreach($days as $index => $day) {
2433 $return .= '<td><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.$index.'" name="s_'.$this->name.'[]" value="'.$index.'" '.($currentsetting & (1 << $index) ? 'checked="checked"' : '') . ' /></td>';
2434 }
2435 $return .= '</tr></tbody></table>';
6153cf58 2436
038bf621 2437 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
eef868d1 2438
6e4dc10f 2439 }
2440
2441}
2442
73afaf5b 2443/*
2444 * this is used in config->appearance->gradeconfig
5a412dbf 2445 */
0909d44e 2446class admin_setting_special_gradebookroles extends admin_setting {
5a412dbf 2447
0909d44e 2448 function admin_setting_special_gradebookroles() {
2449 $name = 'gradebookroles';
73afaf5b 2450 $visiblename = get_string('gradebookroles', 'admin');
2451 $description = get_string('configgradebookroles', 'admin');
7aa3e196 2452 $default = array(5=>'1'); // The student role in a default install
8a2cb2fa 2453 parent::admin_setting($name, $visiblename, $description, $default);
5a412dbf 2454 }
2455
2456 function get_setting() {
2457 global $CFG;
8a2cb2fa 2458 if (!empty($CFG->{$this->name})) {
60f7d402 2459 $result = explode(',', $CFG->{$this->name});
2460 foreach ($result as $roleid) {
9ba38673 2461 $array[$roleid] = 1;
60f7d402 2462 }
2463 return $array;
5a412dbf 2464 } else {
3fae9f57 2465 return null;
5a412dbf 2466 }
2467 }
2468
2469 function write_setting($data) {
2470 if (!empty($data)) {
2471 $str = '';
0909d44e 2472 foreach ($data as $key => $value) {
5a412dbf 2473 if ($value) {
2474 $str .= $key.',';
2475 }
2476 }
2477 return set_config($this->name, rtrim($str, ","))?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2478 } else {
73afaf5b 2479 return set_config($this->name, '')?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2480 }
5a412dbf 2481 }
2482
2483 function output_html() {
2484
2485 if ($this->get_setting() === NULL) {
2486 $currentsetting = $this->defaultsetting;
2487 } else {
2488 $currentsetting = $this->get_setting();
2489 }
5a412dbf 2490 // from to process which roles to display
2491 if ($roles = get_records('role')) {
73afaf5b 2492 $return = '<div class="form-group">';
2493 $first = true;
2494 foreach ($roles as $roleid=>$role) {
60f7d402 2495 if (is_array($currentsetting) && in_array($roleid, array_keys($currentsetting))) {
fb132873 2496 $checked = ' checked="checked"';
5a412dbf 2497 } else {
73afaf5b 2498 $checked = '';
5a412dbf 2499 }
73afaf5b 2500 if ($first) {
2501 $first = false;
2502 } else {
2503 $return .= '<br />';
2504 }
b0abd282 2505 $return .= '<input type="checkbox" name="s_'.$this->name.'['.$roleid.']" value="1"'.$checked.' />&nbsp;'.format_string($role->name);
5a412dbf 2506 }
73afaf5b 2507 $return .= '</div>';
5a412dbf 2508 }
73afaf5b 2509
60a9a6ea 2510 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
5a412dbf 2511
2512 }
2513
2514}
6e4dc10f 2515
d42c64ba 2516/*
2517 * this is used in config->appearance->coursemanager
2518 * (which roles to show on course decription page)
2519 */
2520class admin_setting_special_coursemanager extends admin_setting {
2521
2522 function admin_setting_special_coursemanager() {
2523 $name = 'coursemanager';
2524 $visiblename = get_string('coursemanager', 'admin');
2525 $description = get_string('configcoursemanager', 'admin');
2526 $default = array(3=>'1'); // The teahcer role in a default install
2527 parent::admin_setting($name, $visiblename, $description, $default);
2528 }
2529
2530 function get_setting() {
2531
2532 global $CFG;
2533 if (!empty($CFG->{$this->name})) {
2534 $result = explode(',', $CFG->{$this->name});
2535 foreach ($result as $roleid) {
9ba38673 2536 $array[$roleid] = 1;
d42c64ba 2537 }
2538 return $array;
b107549c 2539 } else if (isset($CFG->{$this->name})) {
2540 return array();
d42c64ba 2541 } else {
2542 return null;
2543 }
2544 }
2545
2546 function write_setting($data) {
2547
2548 if (!empty($data)) {
2549 $str = '';
2550 foreach ($data as $key => $value) {
2551 if ($value) {
2552 $str .= $key.',';
2553 }
2554 }
2555 return set_config($this->name, rtrim($str, ","))?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2556 } else {
2557 return set_config($this->name, '')?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2558 }
2559 }
2560
2561 function output_html() {
2562
2563 if ($this->get_setting() === NULL) {
2564 $currentsetting = $this->defaultsetting;
2565 } else {
2566 $currentsetting = $this->get_setting();
2567 }
2568 // from to process which roles to display
d717df34 2569 if ($roles = get_records_select('role', '', 'sortorder')) {
d42c64ba 2570 $return = '<div class="form-group">';
2571 $first = true;
2572 foreach ($roles as $roleid=>$role) {
2573 if (is_array($currentsetting) && in_array($roleid, array_keys($currentsetting))) {
2574 $checked = 'checked="checked"';
2575 } else {
2576 $checked = '';
2577 }
2578 if ($first) {
2579 $first = false;
2580 } else {
2581 $return .= '<br />';
2582 }
7203167d 2583 $return .= '<input type="checkbox" name="s_'.$this->name.'['.$roleid.']" value="1" '.$checked.' />&nbsp;'.$role->name;
d42c64ba 2584 }
2585 $return .= '</div>';
2586 }
60a9a6ea 2587 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
d42c64ba 2588 }
2589}
2590
76127f37 2591/*
2592 * this is used in config->courses->gradeexports
2593 * (which roles to show on course decription page)
2594 */
2595class admin_setting_special_gradeexport extends admin_setting {
2596
2597 function admin_setting_special_gradeexport() {
2598 $name = 'gradeexport';
2599 $visiblename = get_string('gradeexport', 'admin');
2600 $description = get_string('configgradeexport', 'admin');
2601 $default = array(3=>'1'); // The teahcer role in a default install
2602 parent::admin_setting($name, $visiblename, $description, $default);
2603 }
2604
2605 function get_setting() {
2606
2607 global $CFG;
2608 if (!empty($CFG->{$this->name})) {
2609 $result = explode(',', $CFG->{$this->name});
2610 foreach ($result as $plugin) {
9ba38673 2611 $array[$plugin] = 1;
76127f37 2612 }
2613 return $array;
2614 } else if (isset($CFG->{$this->name})) {
2615 return array();
2616 } else {
2617 return null;
2618 }
2619 }
2620
2621 function write_setting($data) {
2622
2623 if (!empty($data)) {
2624 $str = '';
2625 foreach ($data as $key => $value) {
2626 if ($value) {
2627 $str .= $key.',';
2628 }
2629 }
2630 return set_config($this->name, rtrim($str, ","))?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2631 } else {
2632 return set_config($this->name, '')?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2633 }
2634 }
2635
2636 function output_html() {
2637
2638 if ($this->get_setting() === NULL) {
2639 $currentsetting = $this->defaultsetting;
2640 } else {
2641 $currentsetting = $this->get_setting();
2642 }
2643 // from to process which roles to display
2644 if ($exports = get_list_of_plugins('grade/export')) {
2645 $return = '<div class="form-group">';
2646 $first = true;
2647 foreach ($exports as $export) {
2648 if (is_array($currentsetting) && in_array($export, array_keys($currentsetting))) {
2649 $checked = 'checked="checked"';
2650 } else {
2651 $checked = '';
2652 }
2653 if ($first) {
2654 $first = false;
2655 } else {
2656 $return .= '<br />';
2657 }
2658 $return .= '<input type="checkbox" name="s_'.$this->name.'['.$export.']" value="1" '.$checked.' />&nbsp;'.$export;
2659 }
2660 $return .= '</div>';
2661 }
2662 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
2663 }
2664}
2665
2666
2667
2668
6e4dc10f 2669class admin_setting_special_perfdebug extends admin_setting_configcheckbox {
2670
2671 function admin_setting_special_perfdebug() {
2672 $name = 'perfdebug';
2673 $visiblename = get_string('perfdebug', 'admin');
2674 $description = get_string('configperfdebug', 'admin');
2675 parent::admin_setting_configcheckbox($name, $visiblename, $description, '');
2676 }
2677
2678 function write_setting($data) {
d42c64ba 2679
6e4dc10f 2680 if ($data == '1') {
2681 return (set_config($this->name,15) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2682 } else {
2683 return (set_config($this->name,7) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2684 }
2685 }
2686
2687 function output_html() {
d42c64ba 2688
cc73de71 2689 if ($this->get_setting() === NULL) {
2690 $currentsetting = $this->defaultsetting;
2691 } else {
2692 $currentsetting = $this->get_setting();
2693 }
eef868d1 2694
3c6f7a78 2695 $return = '<input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'" name="s_'. $this->name .'" value="1" ' . ($currentsetting == 15 ? 'checked="checked"' : '') . ' />';
fc52aa6e 2696 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
6e4dc10f 2697 }
2698
2699}
2700
47b8b9eb 2701class admin_setting_special_debugdisplay extends admin_setting_configcheckbox {
2702
2703 function admin_setting_special_debugdisplay() {
2704 $name = 'debugdisplay';
2705 $visiblename = get_string('debugdisplay', 'admin');
2706 $description = get_string('configdebugdisplay', 'admin');
6349a3ba 2707 $default = ini_get('display_errors');
2708 parent::admin_setting_configcheckbox($name, $visiblename, $description, $default);
47b8b9eb 2709 }
2710
2711 function write_setting($data) {
2712
2713 if ($data == '1') {
2714 return (set_config($this->name,1) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2715 } else {
2716 return (set_config($this->name,0) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2717 }
2718 }
2719
2720 function output_html() {
2721
2722 if ($this->get_setting() === NULL) {
6349a3ba 2723 $currentsetting = $this->defaultsetting;
47b8b9eb 2724 } else {
2725 $currentsetting = $this->get_setting();
2726 }
2727
2728 $return = '<input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'" name="s_'. $this->name .'" value="1" ' . ($currentsetting == 1 ? 'checked="checked"' : '') . ' />';
2729 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
2730 }
2731
2732}
2733
2734
6e4dc10f 2735// Code for a function that helps externalpages print proper headers and footers
2736// N.B.: THIS FUNCTION HANDLES AUTHENTICATION
1ae083e4 2737function admin_externalpage_setup($section) {
6e4dc10f 2738
2739 global $CFG, $PAGE, $USER;
eef868d1 2740
1ae083e4 2741 $adminroot = admin_get_root();
2742
6e4dc10f 2743 require_once($CFG->libdir . '/blocklib.php');
02cc05a7 2744 require_once($CFG->dirroot . '/'.$CFG->admin.'/pagelib.php');
eef868d1 2745
02cc05a7 2746 page_map_class(PAGE_ADMIN, 'page_admin');
6e4dc10f 2747
e9a20759 2748 $PAGE = page_create_object(PAGE_ADMIN, 0); // there must be any constant id number
6e4dc10f 2749
02cc05a7 2750 $PAGE->init_extra($section); // hack alert!
6e4dc10f 2751
2752 $root = $adminroot->locate($PAGE->section);
2753
2754 if ($site = get_site()) {
2755 require_login();
2756 } else {
6859360c 2757 redirect($CFG->wwwroot . '/'.$CFG->admin.'/index.php');
6e4dc10f 2758 die;
2759 }
2760
2761 if (!is_a($root, 'admin_externalpage')) {
2762 error(get_string('sectionerror','admin'));
2763 die;
2764 }
2765
2766 // this eliminates our need to authenticate on the actual pages
2767 if (!($root->check_access())) {
2768 error(get_string('accessdenied', 'admin'));
2769 die;
2770 }
eef868d1 2771
6e4dc10f 2772 $adminediting = optional_param('adminedit', -1, PARAM_BOOL);
eef868d1 2773
6e4dc10f 2774 if (!isset($USER->adminediting)) {
2775 $USER->adminediting = false;
2776 }
eef868d1 2777
6e4dc10f 2778 if ($PAGE->user_allowed_editing()) {
2779 if ($adminediting == 1) {
2780 $USER->adminediting = true;
2781 } elseif ($adminediting == 0) {
2782 $USER->adminediting = false;
2783 }
2784 }
eef868d1 2785
6e4dc10f 2786}
2787
f1af7aaa 2788/**
2789 * TODO document
2790 */
1ae083e4 2791function admin_externalpage_print_header() {
6e4dc10f 2792
ce821fda 2793 global $CFG, $PAGE, $SITE, $THEME;
9ba38673 2794
f145c248 2795 if (!empty($THEME->customcorners)) {
2796 require_once($CFG->dirroot.'/lib/custom_corners_lib.php');
2797 }
eef868d1 2798
1ae083e4 2799 define('ADMIN_EXT_HEADER_PRINTED', 'true');
2800
b1ce7811 2801 if (!empty($SITE->fullname)) {
2802 $pageblocks = blocks_setup($PAGE);
6e4dc10f 2803
e524c0ed 2804 $preferred_width_left = bounded_number(BLOCK_L_MIN_WIDTH,
2805 blocks_preferred_width($pageblocks[BLOCK_POS_LEFT]),
b1ce7811 2806 BLOCK_L_MAX_WIDTH);
b1ce7811 2807 $PAGE->print_header();
5577ceb3 2808 echo '<table id="layout-table" summary=""><tr>';
f1af7aaa 2809
5730bc61 2810 $lt = (empty($THEME->layouttable)) ? array('left', 'middle', 'right') : $THEME->layouttable;
2811 foreach ($lt as $column) {
2812 $lt1[] = $column;
2813 if ($column == 'middle') break;
2814 }
2815 foreach ($lt1 as $column) {
2816 switch ($column) {
2817 case 'left':
b1ce7811 2818 echo '<td style="width: ' . $preferred_width_left . 'px;" id="left-column">';
f145c248 2819 if (!empty($THEME->customcorners)) print_custom_corners_start();
b1ce7811 2820 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT);
f145c248 2821 if (!empty($THEME->customcorners)) print_custom_corners_end();
b1ce7811 2822 echo '</td>';
5730bc61 2823 break;
f1af7aaa 2824
5730bc61 2825 case 'middle':
a06c8c2c 2826 echo '<td id="middle-column">';
f145c248 2827 if (!empty($THEME->customcorners)) print_custom_corners_start();
5730bc61 2828 break;
f1af7aaa 2829
5730bc61 2830 case 'right':
2831 if (blocks_have_content($pageblocks, BLOCK_POS_RIGHT)) {
2832 echo '<td style="width: ' . $preferred_width_right . 'px;" id="right-column">';
2833 if (!empty($THEME->customcorners)) print_custom_corners_start();
2834 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT);
2835 if (!empty($THEME->customcorners)) print_custom_corners_end();
2836 echo '</td>';
2837 }
2838 break;
2839 }
2840 }
b1ce7811 2841 } else {
2842 print_header();
2843 }
6e4dc10f 2844}
2845
1ae083e4 2846function admin_externalpage_print_footer() {
6e4dc10f 2847
ce821fda 2848 global $CFG, $PAGE, $SITE, $THEME;
9ba38673 2849
f145c248 2850 if (!empty($THEME->customcorners)) {
2851 require_once($CFG->dirroot.'/lib/custom_corners_lib.php');
2852 }
9ba38673 2853
1ae083e4 2854 define('ADMIN_EXT_FOOTER_PRINTED', 'true');
2855
b1ce7811 2856 if (!empty($SITE->fullname)) {
2857 $pageblocks = blocks_setup($PAGE);
e524c0ed 2858 $preferred_width_right = bounded_number(BLOCK_R_MIN_WIDTH,
2859 blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT]),
b1ce7811 2860 BLOCK_R_MAX_WIDTH);
5730bc61 2861
2862 $lt = (empty($THEME->layouttable)) ? array('left', 'middle', 'right') : $THEME->layouttable;
2863 foreach ($lt as $column) {
2864 if ($column != 'middle') {
2865 array_shift($lt);
2866 } else if ($column == 'middle') {
2867 break;
2868 }
2869 }
2870 foreach ($lt as $column) {
2871 switch ($column) {
2872 case 'left':
2873 echo '<td style="width: ' . $preferred_width_left . 'px;" id="left-column">';
2874 if (!empty($THEME->customcorners)) print_custom_corners_start();
2875 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT);
f145c248 2876 if (!empty($THEME->customcorners)) print_custom_corners_end();
b1ce7811 2877 echo '</td>';
5730bc61 2878 break;
f1af7aaa 2879
5730bc61 2880 case 'middle':
2881 if (!empty($THEME->customcorners)) print_custom_corners_end();
2882 echo '</td>';
2883 break;
f1af7aaa 2884
5730bc61 2885 case 'right':
d5271d3d 2886 if (blocks_have_content($pageblocks, BLOCK_POS_RIGHT)) {
ec3938f3 2887 echo '<td style="width: ' . $preferred_width_right . 'px;" id="right-column">';
f145c248 2888 if (!empty($THEME->customcorners)) print_custom_corners_start();
ec3938f3 2889 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT);
5730bc61 2890
f145c248 2891 if (!empty($THEME->customcorners)) print_custom_corners_end();
ec3938f3 2892 echo '</td>';
5730bc61 2893 }
2894 break;
2895 }
ce821fda 2896 }
ec3938f3 2897 echo '</tr></table>';
b1ce7811 2898 }
6e4dc10f 2899 print_footer();
6e4dc10f 2900}
2901
2902function admin_get_root() {
2903 global $CFG;
2904
2905 static $ADMIN;
2906
2907 if (!isset($ADMIN)) {
2908 // start the admin tree!
2058a0a1 2909 $ADMIN = new admin_category('root', get_string("administration"));
6e4dc10f 2910 // we process this file first to get categories up and running
6859360c 2911 include($CFG->dirroot . '/'.$CFG->admin.'/settings/top.php');
6e4dc10f 2912
2913 // now we process all other files in admin/settings to build the
2914 // admin tree
6859360c 2915 foreach (glob($CFG->dirroot . '/'.$CFG->admin.'/settings/*.php') as $file) {
2916 if ($file != $CFG->dirroot . '/'.$CFG->admin.'/settings/top.php') {
6e4dc10f 2917 include_once($file);
2918 }
2919 }
2920 }
eef868d1 2921
6e4dc10f 2922 return $ADMIN;
2923}
2924
8e5da17a 2925/// settings utility functions
6e4dc10f 2926
8e5da17a 2927/**
2928 * This function applies default settings.
2929 * @param object $node
2930 * @param bool $uncoditional if true overrides all values with defaults
2931 * @return void
2932 */
2933function apply_default_settings(&$node, $unconditional=true) {
6e4dc10f 2934
2935 global $CFG;
2936
2937 if (is_a($node, 'admin_category')) {
2938 $entries = array_keys($node->children);
2939 foreach ($entries as $entry) {
2940 apply_default_settings($node->children[$entry]);
2941 }
2942 return;
eef868d1 2943 }
6e4dc10f 2944
eef868d1 2945 if (is_a($node, 'admin_settingpage')) {
6e4dc10f 2946 foreach ($node->settings as $setting) {
8e5da17a 2947 if (!$unconditional and !is_null($setting->get_setting)) {
2948 //do not override existing defaults
2949 continue;
2950 }
2951 $defaultsetting = $setting->get_defaultsetting();
2952 if (is_null($defaultsetting)) {
2953 // no value yet - default maybe applied after admin user creation or in upgradesettings
2954 continue;
2955 }
2956 $CFG->{$setting->name} = $defaultsetting;
2957 $setting->write_setting($defaultsetting);
6e4dc10f 2958 unset($setting); // needed to prevent odd (imho) reference behaviour
2959 // see http://www.php.net/manual/en/language.references.whatdo.php#AEN6399
2960 }
2961 return;
2962 }
2963
2964 return;
2965
2966}
2967
2968// n.b. this function unconditionally applies default settings
2969function apply_default_exception_settings($defaults) {
2970
2971 global $CFG;
2972
2973 foreach($defaults as $key => $value) {
2974 $CFG->$key = $value;
2975 set_config($key, $value);
2976 }
2977
2978}
2979
fbe31d22 2980function format_admin_setting($name, $title='', $form='', $description='', $label=true) {
9ba38673 2981
fbe31d22 2982 // sometimes the id is not id_s_name, but id_s_name_m or something, and this does not validate
2983 if ($label) {
9ba38673 2984 $labelfor = 'for = "id_s_'.$name.'"';
fbe31d22 2985 } else {
9ba38673 2986 $labelfor = '';
fbe31d22 2987 }
9ba38673 2988
fbe31d22 2989 $str = "\n".
fc52aa6e 2990 '<div class="form-item" id="admin-'.$name.'">'."\n".
fbe31d22 2991 '<label '.$labelfor.'>'.$title."\n".
6153cf58 2992 ' <span class="form-shortname">'.$name.'</span>'."\n".
2993 '</label>'."\n".
2994 $form."\n".
edb6cba4 2995 '<div class="description">'.$description.'</div>'."\n".
23586aca 2996 '</div>'.
2997 "\n\n";
9ba38673 2998
fbe31d22 2999 return $str;
2c8766df 3000}
3001
9ba38673 3002/*
d210e12e 3003 * Try to upgrade the given language pack (or current language)
3004 * If it doesn't work, fail silently and return false
3005 */
3006function upgrade_language_pack($lang='') {
3007 global $CFG;
3008
3009 if (empty($lang)) {
3010 $lang = current_language();
3011 }
3012
3013 if ($lang == 'en_utf8') {
3014 return true; // Nothing to do
3015 }
3016
3017 notify(get_string('langimport', 'admin').': '.$lang.' ... ', 'notifysuccess');
3018
3019 @mkdir ($CFG->dataroot.'/temp/'); //make it in case it's a fresh install, it might not be there
3020 @mkdir ($CFG->dataroot.'/lang/');
3021
3022 require_once($CFG->libdir.'/componentlib.class.php');
3023
3024 if ($cd = new component_installer('http://download.moodle.org', 'lang16', $lang.'.zip', 'languages.md5', 'lang')) {
3025 $status = $cd->install(); //returns ERROR | UPTODATE | INSTALLED
3026
3027 if ($status == INSTALLED) {
3028 debugging('Downloading successful: '.$lang);
3029 @unlink($CFG->dataroot.'/cache/languages');
3030 return true;
3031 }
3032 }
3033
3034 return false;
3035}
3036
2acc1f96 3037/**
3038 * Based on find_new_settings{@link ()} in upgradesettings.php
3039 * Looks to find any admin settings that have not been initialized. Returns 1 if it finds any.
3040 *
9ba38673 3041 * @param string &$node The node at which to start searching.
2acc1f96 3042 * @return int Returns 1 if any settings haven't been initialised, 0 if they all have
3043 */
3044function any_new_admin_settings(&$node) {
3045
3046 if (is_a($node, 'admin_category')) {
3047 $entries = array_keys($node->children);
3048 foreach ($entries as $entry) {
3049 if( any_new_admin_settings($node->children[$entry]) ){
3050 return 1;
3051 }
3052 }
3053 }
3054
3055 if (is_a($node, 'admin_settingpage')) {
3056 foreach ($node->settings as $setting) {
3057 if ($setting->get_setting() === NULL) {
3058 return 1;
3059 }
3060 }
3061 }
3062
3063
3064 return 0;
3065
3066}
3067
6153cf58 3068?>