MDL-11769:
[moodle-linuxchix.git] / lib / adminlib.php
blob46af0f5b45f74b5cd17e8ee4c9b6232ed5cefcee
1 <?php
3 /**
4 * adminlib.php - Contains functions that only administrators will ever need to use
6 * @author Martin Dougiamas and many others
7 * @version $Id$
8 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
9 * @package moodlecore
12 function upgrade_main_savepoint($result, $version) {
13 global $CFG;
15 if ($result) {
16 if ($CFG->version >= $version) {
17 // something really wrong is going on in main upgrade script
18 error("Upgrade savepoint: Can not upgrade main version from $CFG->version to $version.");
20 set_config('version', $version);
21 } else {
22 notify ("Upgrade savepoint: Error during main upgrade to version $version");
26 function upgrade_mod_savepoint($result, $version, $type) {
27 //TODO
30 function upgrade_plugin_savepoint($result, $version, $type, $dir) {
31 //TODO
34 function upgrade_backup_savepoint($result, $version) {
35 //TODO
38 function upgrade_blocks_savepoint($result, $version, $type) {
39 //TODO
42 /**
43 * Upgrade plugins
45 * @uses $db
46 * @uses $CFG
47 * @param string $type The type of plugins that should be updated (e.g. 'enrol', 'qtype')
48 * @param string $dir The directory where the plugins are located (e.g. 'question/questiontypes')
49 * @param string $return The url to prompt the user to continue to
51 function upgrade_plugins($type, $dir, $return) {
52 global $CFG, $db;
54 /// Let's know if the header has been printed, so the funcion is being called embedded in an outer page
55 $embedded = defined('HEADER_PRINTED');
57 $plugs = get_list_of_plugins($dir);
58 $updated_plugins = false;
59 $strpluginsetup = get_string('pluginsetup');
61 foreach ($plugs as $plug) {
63 $fullplug = $CFG->dirroot .'/'.$dir.'/'. $plug;
65 unset($plugin);
67 if (is_readable($fullplug .'/version.php')) {
68 include_once($fullplug .'/version.php'); // defines $plugin with version etc
69 } else {
70 continue; // Nothing to do.
73 $oldupgrade = false;
74 $newupgrade = false;
75 if (is_readable($fullplug . '/db/'. $CFG->dbtype . '.php')) {
76 include_once($fullplug . '/db/'. $CFG->dbtype . '.php'); // defines old upgrading function
77 $oldupgrade = true;
79 if (is_readable($fullplug . '/db/upgrade.php')) {
80 include_once($fullplug . '/db/upgrade.php'); // defines new upgrading function
81 $newupgrade = true;
84 if (!isset($plugin)) {
85 continue;
88 if (!empty($plugin->requires)) {
89 if ($plugin->requires > $CFG->version) {
90 $info = new object();
91 $info->pluginname = $plug;
92 $info->pluginversion = $plugin->version;
93 $info->currentmoodle = $CFG->version;
94 $info->requiremoodle = $plugin->requires;
95 if (!$updated_plugins && !$embedded) {
96 print_header($strpluginsetup, $strpluginsetup,
97 build_navigation(array(array('name' => $strpluginsetup, 'link' => null, 'type' => 'misc'))), '',
98 upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
100 upgrade_log_start();
101 notify(get_string('pluginrequirementsnotmet', 'error', $info));
102 $updated_plugins = true;
103 continue;
107 $plugin->name = $plug; // The name MUST match the directory
109 $pluginversion = $type.'_'.$plug.'_version';
111 if (!isset($CFG->$pluginversion)) {
112 set_config($pluginversion, 0);
115 if ($CFG->$pluginversion == $plugin->version) {
116 // do nothing
117 } else if ($CFG->$pluginversion < $plugin->version) {
118 if (!$updated_plugins && !$embedded) {
119 print_header($strpluginsetup, $strpluginsetup,
120 build_navigation(array(array('name' => $strpluginsetup, 'link' => null, 'type' => 'misc'))), '',
121 upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
123 $updated_plugins = true;
124 upgrade_log_start();
125 print_heading($dir.'/'. $plugin->name .' plugin needs upgrading');
126 $db->debug = true;
127 @set_time_limit(0); // To allow slow databases to complete the long SQL
129 if ($CFG->$pluginversion == 0) { // It's a new install of this plugin
130 /// Both old .sql files and new install.xml are supported
131 /// but we priorize install.xml (XMLDB) if present
132 $status = false;
133 if (file_exists($fullplug . '/db/install.xml')) {
134 $status = install_from_xmldb_file($fullplug . '/db/install.xml'); //New method
135 } else if (file_exists($fullplug .'/db/'. $CFG->dbtype .'.sql')) {
136 $status = modify_database($fullplug .'/db/'. $CFG->dbtype .'.sql'); //Old method
137 } else {
138 $status = true;
141 $db->debug = false;
142 /// Continue with the instalation, roles and other stuff
143 if ($status) {
144 /// OK so far, now update the plugins record
145 set_config($pluginversion, $plugin->version);
147 /// Install capabilities
148 if (!update_capabilities($type.'/'.$plug)) {
149 error('Could not set up the capabilities for '.$plugin->name.'!');
151 /// Install events
152 events_update_definition($type.'/'.$plug);
154 /// Run local install function if there is one
155 if (is_readable($fullplug .'/lib.php')) {
156 include_once($fullplug .'/lib.php');
157 $installfunction = $plugin->name.'_install';
158 if (function_exists($installfunction)) {
159 if (! $installfunction() ) {
160 notify('Encountered a problem running install function for '.$module->name.'!');
165 notify(get_string('modulesuccess', '', $plugin->name), 'notifysuccess');
166 } else {
167 notify('Installing '. $plugin->name .' FAILED!');
169 } else { // Upgrade existing install
170 /// Run de old and new upgrade functions for the module
171 $oldupgrade_function = $type.'_'.$plugin->name .'_upgrade';
172 $newupgrade_function = 'xmldb_' . $type.'_'.$plugin->name .'_upgrade';
174 /// First, the old function if exists
175 $oldupgrade_status = true;
176 if ($oldupgrade && function_exists($oldupgrade_function)) {
177 $db->debug = true;
178 $oldupgrade_status = $oldupgrade_function($CFG->$pluginversion);
179 } else if ($oldupgrade) {
180 notify ('Upgrade function ' . $oldupgrade_function . ' was not available in ' .
181 $fullplug . '/db/' . $CFG->dbtype . '.php');
184 /// Then, the new function if exists and the old one was ok
185 $newupgrade_status = true;
186 if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) {
187 $db->debug = true;
188 $newupgrade_status = $newupgrade_function($CFG->$pluginversion);
189 } else if ($newupgrade) {
190 notify ('Upgrade function ' . $newupgrade_function . ' was not available in ' .
191 $fullplug . '/db/upgrade.php');
194 $db->debug=false;
195 /// Now analyze upgrade results
196 if ($oldupgrade_status && $newupgrade_status) { // No upgrading failed
197 // OK so far, now update the plugins record
198 set_config($pluginversion, $plugin->version);
199 if (!update_capabilities($type.'/'.$plug)) {
200 error('Could not update '.$plugin->name.' capabilities!');
202 events_update_definition($type.'/'.$plug);
203 notify(get_string('modulesuccess', '', $plugin->name), 'notifysuccess');
204 } else {
205 notify('Upgrading '. $plugin->name .' from '. $CFG->$pluginversion .' to '. $plugin->version .' FAILED!');
208 echo '<hr />';
209 } else {
210 upgrade_log_start();
211 error('Version mismatch: '. $plugin->name .' can\'t downgrade '. $CFG->$pluginversion .' -> '. $plugin->version .' !');
215 upgrade_log_finish();
217 if ($updated_plugins && !$embedded) {
218 print_continue($return);
219 print_footer('none');
220 die;
225 * Find and check all modules and load them up or upgrade them if necessary
227 * @uses $db
228 * @uses $CFG
229 * @param string $return The url to prompt the user to continue to
230 * @todo Finish documenting this function
232 function upgrade_activity_modules($return) {
234 global $CFG, $db;
236 if (!$mods = get_list_of_plugins('mod') ) {
237 error('No modules installed!');
240 $updated_modules = false;
241 $strmodulesetup = get_string('modulesetup');
243 foreach ($mods as $mod) {
245 if ($mod == 'NEWMODULE') { // Someone has unzipped the template, ignore it
246 continue;
249 $fullmod = $CFG->dirroot .'/mod/'. $mod;
251 unset($module);
253 if ( is_readable($fullmod .'/version.php')) {
254 include_once($fullmod .'/version.php'); // defines $module with version etc
255 } else {
256 notify('Module '. $mod .': '. $fullmod .'/version.php was not readable');
257 continue;
260 $oldupgrade = false;
261 $newupgrade = false;
262 if ( is_readable($fullmod .'/db/' . $CFG->dbtype . '.php')) {
263 include_once($fullmod .'/db/' . $CFG->dbtype . '.php'); // defines old upgrading function
264 $oldupgrade = true;
266 if ( is_readable($fullmod . '/db/upgrade.php')) {
267 include_once($fullmod . '/db/upgrade.php'); // defines new upgrading function
268 $newupgrade = true;
271 if (!isset($module)) {
272 continue;
275 if (!empty($module->requires)) {
276 if ($module->requires > $CFG->version) {
277 $info = new object();
278 $info->modulename = $mod;
279 $info->moduleversion = $module->version;
280 $info->currentmoodle = $CFG->version;
281 $info->requiremoodle = $module->requires;
282 if (!$updated_modules) {
283 print_header($strmodulesetup, $strmodulesetup,
284 build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '',
285 upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
287 upgrade_log_start();
288 notify(get_string('modulerequirementsnotmet', 'error', $info));
289 $updated_modules = true;
290 continue;
294 $module->name = $mod; // The name MUST match the directory
296 include_once($fullmod.'/lib.php'); // defines upgrading and/or installing functions
298 if ($currmodule = get_record('modules', 'name', $module->name)) {
299 if ($currmodule->version == $module->version) {
300 // do nothing
301 } else if ($currmodule->version < $module->version) {
302 /// If versions say that we need to upgrade but no upgrade files are available, notify and continue
303 if (!$oldupgrade && !$newupgrade) {
304 notify('Upgrade files ' . $mod . ': ' . $fullmod . '/db/' . $CFG->dbtype . '.php or ' .
305 $fullmod . '/db/upgrade.php were not readable');
306 continue;
308 if (!$updated_modules) {
309 print_header($strmodulesetup, $strmodulesetup,
310 build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '',
311 upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
313 upgrade_log_start();
314 print_heading($module->name .' module needs upgrading');
316 /// Run de old and new upgrade functions for the module
317 $oldupgrade_function = $module->name . '_upgrade';
318 $newupgrade_function = 'xmldb_' . $module->name . '_upgrade';
320 /// First, the old function if exists
321 $oldupgrade_status = true;
322 if ($oldupgrade && function_exists($oldupgrade_function)) {
323 $db->debug = true;
324 $oldupgrade_status = $oldupgrade_function($currmodule->version, $module);
325 if (!$oldupgrade_status) {
326 notify ('Upgrade function ' . $oldupgrade_function .
327 ' did not complete successfully.');
329 } else if ($oldupgrade) {
330 notify ('Upgrade function ' . $oldupgrade_function . ' was not available in ' .
331 $mod . ': ' . $fullmod . '/db/' . $CFG->dbtype . '.php');
334 /// Then, the new function if exists and the old one was ok
335 $newupgrade_status = true;
336 if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) {
337 $db->debug = true;
338 $newupgrade_status = $newupgrade_function($currmodule->version, $module);
339 } else if ($newupgrade && $oldupgrade_status) {
340 notify ('Upgrade function ' . $newupgrade_function . ' was not available in ' .
341 $mod . ': ' . $fullmod . '/db/upgrade.php');
344 $db->debug=false;
345 /// Now analyze upgrade results
346 if ($oldupgrade_status && $newupgrade_status) { // No upgrading failed
347 // OK so far, now update the modules record
348 $module->id = $currmodule->id;
349 if (! update_record('modules', $module)) {
350 error('Could not update '. $module->name .' record in modules table!');
352 remove_dir($CFG->dataroot . '/cache', true); // flush cache
353 notify(get_string('modulesuccess', '', $module->name), 'notifysuccess');
354 echo '<hr />';
355 } else {
356 notify('Upgrading '. $module->name .' from '. $currmodule->version .' to '. $module->version .' FAILED!');
359 /// Update the capabilities table?
360 if (!update_capabilities('mod/'.$module->name)) {
361 error('Could not update '.$module->name.' capabilities!');
363 events_update_definition('mod/'.$module->name);
365 $updated_modules = true;
367 } else {
368 upgrade_log_start();
369 error('Version mismatch: '. $module->name .' can\'t downgrade '. $currmodule->version .' -> '. $module->version .' !');
372 } else { // module not installed yet, so install it
373 if (!$updated_modules) {
374 print_header($strmodulesetup, $strmodulesetup,
375 build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '',
376 upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
378 upgrade_log_start();
379 print_heading($module->name);
380 $updated_modules = true;
381 $db->debug = true;
382 @set_time_limit(0); // To allow slow databases to complete the long SQL
384 /// Both old .sql files and new install.xml are supported
385 /// but we priorize install.xml (XMLDB) if present
386 if (file_exists($fullmod . '/db/install.xml')) {
387 $status = install_from_xmldb_file($fullmod . '/db/install.xml'); //New method
388 } else {
389 $status = modify_database($fullmod .'/db/'. $CFG->dbtype .'.sql'); //Old method
392 $db->debug = false;
394 /// Continue with the installation, roles and other stuff
395 if ($status) {
396 if ($module->id = insert_record('modules', $module)) {
398 /// Capabilities
399 if (!update_capabilities('mod/'.$module->name)) {
400 error('Could not set up the capabilities for '.$module->name.'!');
403 /// Events
404 events_update_definition('mod/'.$module->name);
406 /// Run local install function if there is one
407 $installfunction = $module->name.'_install';
408 if (function_exists($installfunction)) {
409 if (! $installfunction() ) {
410 notify('Encountered a problem running install function for '.$module->name.'!');
414 notify(get_string('modulesuccess', '', $module->name), 'notifysuccess');
415 echo '<hr />';
416 } else {
417 error($module->name .' module could not be added to the module list!');
419 } else {
420 error($module->name .' tables could NOT be set up successfully!');
424 /// Check submodules of this module if necessary
426 $submoduleupgrade = $module->name.'_upgrade_submodules';
427 if (function_exists($submoduleupgrade)) {
428 $submoduleupgrade();
432 /// Run any defaults or final code that is necessary for this module
434 if ( is_readable($fullmod .'/defaults.php')) {
435 // Insert default values for any important configuration variables
436 unset($defaults);
437 include_once($fullmod .'/defaults.php');
438 if (!empty($defaults)) {
439 foreach ($defaults as $name => $value) {
440 if (!isset($CFG->$name)) {
441 set_config($name, $value);
448 upgrade_log_finish(); // finish logging if started
450 if ($updated_modules) {
451 print_continue($return);
452 print_footer('none');
453 die;
458 * This function will return FALSE if the lock fails to be set (ie, if it's already locked)
460 * @param string $name ?
461 * @param bool $value ?
462 * @param int $staleafter ?
463 * @param bool $clobberstale ?
464 * @todo Finish documenting this function
466 function set_cron_lock($name,$value=true,$staleafter=7200,$clobberstale=false) {
468 if (empty($name)) {
469 mtrace("Tried to get a cron lock for a null fieldname");
470 return false;
473 if (empty($value)) {
474 set_config($name,0);
475 return true;
478 if ($config = get_record('config','name',$name)) {
479 if (empty($config->value)) {
480 set_config($name,time());
481 } else {
482 // check for stale.
483 if ((time() - $staleafter) > $config->value) {
484 mtrace("STALE LOCKFILE FOR $name - was $config->value");
485 if (!empty($clobberstale)) {
486 set_config($name,time());
487 return true;
489 } else {
490 return false; // was not stale - ie, we're ok to still be running.
494 else {
495 set_config($name,time());
497 return true;
500 function print_progress($done, $total, $updatetime=5, $sleeptime=1, $donetext='') {
501 static $starttime;
502 static $lasttime;
504 if ($total < 2) { // No need to show anything
505 return;
508 if (empty($starttime)) {
509 $starttime = $lasttime = time();
510 $lasttime = $starttime - $updatetime;
511 echo '<table width="500" cellpadding="0" cellspacing="0" align="center"><tr><td width="500">';
512 echo '<div id="bar'.$total.'" style="border-style:solid;border-width:1px;width:500px;height:50px;">';
513 echo '<div id="slider'.$total.'" style="border-style:solid;border-width:1px;height:48px;width:10px;background-color:green;"></div>';
514 echo '</div>';
515 echo '<div id="text'.$total.'" align="center" style="width:500px;"></div>';
516 echo '</td></tr></table>';
517 echo '</div>';
520 $now = time();
522 if ($done && (($now - $lasttime) >= $updatetime)) {
523 $elapsedtime = $now - $starttime;
524 $projectedtime = (int)(((float)$total / (float)$done) * $elapsedtime) - $elapsedtime;
525 $percentage = round((float)$done / (float)$total, 2);
526 $width = (int)(500 * $percentage);
528 if ($projectedtime > 10) {
529 $projectedtext = ' Ending: '.format_time($projectedtime);
530 } else {
531 $projectedtext = '';
534 echo '<script>';
535 echo 'document.getElementById("text'.$total.'").innerHTML = "'.addslashes($donetext).' ('.$done.'/'.$total.') '.$projectedtext.'";'."\n";
536 echo 'document.getElementById("slider'.$total.'").style.width = \''.$width.'px\';'."\n";
537 echo '</script>';
539 $lasttime = $now;
540 sleep($sleeptime);
544 function upgrade_get_javascript() {
545 global $CFG;
547 if (!empty($_SESSION['installautopilot'])) {
548 $linktoscrolltoerrors = '<script type="text/javascript">var installautopilot = true;</script>'."\n";
549 } else {
550 $linktoscrolltoerrors = '<script type="text/javascript">var installautopilot = false;</script>'."\n";
552 $linktoscrolltoerrors .= '<script type="text/javascript" src="' . $CFG->wwwroot . '/lib/scroll_to_errors.js"></script>';
554 return $linktoscrolltoerrors;
557 function create_admin_user() {
558 global $CFG, $USER;
560 if (empty($CFG->rolesactive)) { // No admin user yet.
562 $user = new object();
563 $user->auth = 'manual';
564 $user->firstname = get_string('admin');
565 $user->lastname = get_string('user');
566 $user->username = 'admin';
567 $user->password = hash_internal_user_password('admin');
568 $user->email = 'root@localhost';
569 $user->confirmed = 1;
570 $user->mnethostid = $CFG->mnet_localhost_id;
571 $user->lang = $CFG->lang;
572 $user->maildisplay = 1;
573 $user->timemodified = time();
575 if (!$user->id = insert_record('user', $user)) {
576 error('SERIOUS ERROR: Could not create admin user record !!!');
579 if (!$user = get_record('user', 'id', $user->id)) { // Double check.
580 error('User ID was incorrect (can\'t find it)');
583 // Assign the default admin roles to the new user.
584 if (!$adminroles = get_roles_with_capability('moodle/legacy:admin', CAP_ALLOW)) {
585 error('No admin role could be found');
587 $sitecontext = get_context_instance(CONTEXT_SYSTEM);
588 foreach ($adminroles as $adminrole) {
589 role_assign($adminrole->id, $user->id, 0, $sitecontext->id);
592 set_config('rolesactive', 1);
594 // Log the user in.
595 $USER = get_complete_user_data('username', 'admin');
596 $USER->newadminuser = 1;
597 load_all_capabilities();
599 redirect("$CFG->wwwroot/user/editadvanced.php?id=$user->id"); // Edit thyself
600 } else {
601 error('Can not create admin!');
605 ////////////////////////////////////////////////
606 /// upgrade logging functions
607 ////////////////////////////////////////////////
609 $upgradeloghandle = false;
610 $upgradelogbuffer = '';
611 // I did not find out how to use static variable in callback function,
612 // the problem was that I could not flush the static buffer :-(
613 global $upgradeloghandle, $upgradelogbuffer;
616 * Check if upgrade is already running.
618 * If anything goes wrong due to missing call to upgrade_log_finish()
619 * just restart the browser.
621 * @param string warning message indicating upgrade is already running
622 * @param int page reload timeout
624 function upgrade_check_running($message, $timeout) {
625 if (!empty($_SESSION['upgraderunning'])) {
626 print_header();
627 redirect(me(), $message, $timeout);
632 * Start logging of output into file (if not disabled) and
633 * prevent aborting and concurrent execution of upgrade script.
635 * Please note that you can not write into session variables after calling this function!
637 * This function may be called repeatedly.
639 function upgrade_log_start() {
640 global $CFG, $upgradeloghandle;
642 if (!empty($_SESSION['upgraderunning'])) {
643 return; // logging already started
646 @ignore_user_abort(true); // ignore if user stops or otherwise aborts page loading
647 $_SESSION['upgraderunning'] = 1; // set upgrade indicator
648 if (empty($CFG->dbsessions)) { // workaround for bug in adodb, db session can not be restarted
649 session_write_close(); // from now on user can reload page - will be displayed warning
651 make_upload_directory('upgradelogs');
652 ob_start('upgrade_log_callback', 2); // function for logging to disk; flush each line of text ASAP
653 register_shutdown_function('upgrade_log_finish'); // in case somebody forgets to stop logging
657 * Terminate logging of output, flush all data, allow script aborting
658 * and reopen session for writing. Function error() does terminate the logging too.
660 * Please make sure that each upgrade_log_start() is properly terminated by
661 * this function or error().
663 * This function may be called repeatedly.
665 function upgrade_log_finish() {
666 global $CFG, $upgradeloghandle, $upgradelogbuffer;
668 if (empty($_SESSION['upgraderunning'])) {
669 return; // logging already terminated
672 @ob_end_flush();
673 if ($upgradelogbuffer !== '') {
674 @fwrite($upgradeloghandle, $upgradelogbuffer);
675 $upgradelogbuffer = '';
677 if ($upgradeloghandle and ($upgradeloghandle !== 'error')) {
678 @fclose($upgradeloghandle);
679 $upgradeloghandle = false;
681 if (empty($CFG->dbsessions)) {
682 @session_start(); // ignore header errors, we only need to reopen session
684 $_SESSION['upgraderunning'] = 0; // clear upgrade indicator
685 if (connection_aborted()) {
686 die;
688 @ignore_user_abort(false);
692 * Callback function for logging into files. Not more than one file is created per minute,
693 * upgrade session (terminated by upgrade_log_finish()) is always stored in one file.
695 * This function must not output any characters or throw warnigns and errors!
697 function upgrade_log_callback($string) {
698 global $CFG, $upgradeloghandle, $upgradelogbuffer;
700 if (empty($CFG->disableupgradelogging) and ($string != '') and ($upgradeloghandle !== 'error')) {
701 if ($upgradeloghandle or ($upgradeloghandle = @fopen($CFG->dataroot.'/upgradelogs/upg_'.date('Ymd-Hi').'.html', 'a'))) {
702 $upgradelogbuffer .= $string;
703 if (strlen($upgradelogbuffer) > 2048) { // 2kB write buffer
704 @fwrite($upgradeloghandle, $upgradelogbuffer);
705 $upgradelogbuffer = '';
707 } else {
708 $upgradeloghandle = 'error';
711 return $string;
715 * Try to verify that dataroot is not accessible from web.
716 * It is not 100% correct but might help to reduce number of vulnerable sites.
718 * Protection from httpd.conf and .htaccess is not detected properly.
720 function is_dataroot_insecure() {
721 global $CFG;
723 $siteroot = str_replace('\\', '/', strrev($CFG->dirroot.'/')); // win32 backslash workaround
725 $rp = preg_replace('|https?://[^/]+|i', '', $CFG->wwwroot, 1);
726 $rp = strrev(trim($rp, '/'));
727 $rp = explode('/', $rp);
728 foreach($rp as $r) {
729 if (strpos($siteroot, '/'.$r.'/') === 0) {
730 $siteroot = substr($siteroot, strlen($r)+1); // moodle web in subdirectory
731 } else {
732 break; // probably alias root
736 $siteroot = strrev($siteroot);
737 $dataroot = str_replace('\\', '/', $CFG->dataroot.'/');
739 if (strpos($dataroot, $siteroot) === 0) {
740 return true;
742 return false;
745 /// =============================================================================================================
746 /// administration tree classes and functions
749 // n.b. documentation is still in progress for this code
751 /// INTRODUCTION
753 /// This file performs the following tasks:
754 /// -it defines the necessary objects and interfaces to build the Moodle
755 /// admin hierarchy
756 /// -it defines the admin_externalpage_setup(), admin_externalpage_print_header(),
757 /// and admin_externalpage_print_footer() functions used on admin pages
759 /// ADMIN_SETTING OBJECTS
761 /// Moodle settings are represented by objects that inherit from the admin_setting
762 /// class. These objects encapsulate how to read a setting, how to write a new value
763 /// to a setting, and how to appropriately display the HTML to modify the setting.
765 /// ADMIN_SETTINGPAGE OBJECTS
767 /// The admin_setting objects are then grouped into admin_settingpages. The latter
768 /// appear in the Moodle admin tree block. All interaction with admin_settingpage
769 /// objects is handled by the admin/settings.php file.
771 /// ADMIN_EXTERNALPAGE OBJECTS
773 /// There are some settings in Moodle that are too complex to (efficiently) handle
774 /// with admin_settingpages. (Consider, for example, user management and displaying
775 /// lists of users.) In this case, we use the admin_externalpage object. This object
776 /// places a link to an external PHP file in the admin tree block.
778 /// If you're using an admin_externalpage object for some settings, you can take
779 /// advantage of the admin_externalpage_* functions. For example, suppose you wanted
780 /// to add a foo.php file into admin. First off, you add the following line to
781 /// admin/settings/first.php (at the end of the file) or to some other file in
782 /// admin/settings:
784 /// $ADMIN->add('userinterface', new admin_externalpage('foo', get_string('foo'),
785 /// $CFG->wwwdir . '/' . '$CFG->admin . '/foo.php', 'some_role_permission'));
787 /// Next, in foo.php, your file structure would resemble the following:
789 /// require_once('.../config.php');
790 /// require_once($CFG->libdir.'/adminlib.php');
791 /// admin_externalpage_setup('foo');
792 /// // functionality like processing form submissions goes here
793 /// admin_externalpage_print_header();
794 /// // your HTML goes here
795 /// admin_externalpage_print_footer();
797 /// The admin_externalpage_setup() function call ensures the user is logged in,
798 /// and makes sure that they have the proper role permission to access the page.
800 /// The admin_externalpage_print_header() function prints the header (it figures
801 /// out what category and subcategories the page is classified under) and ensures
802 /// that you're using the admin pagelib (which provides the admin tree block and
803 /// the admin bookmarks block).
805 /// The admin_externalpage_print_footer() function properly closes the tables
806 /// opened up by the admin_externalpage_print_header() function and prints the
807 /// standard Moodle footer.
809 /// ADMIN_CATEGORY OBJECTS
811 /// Above and beyond all this, we have admin_category objects. These objects
812 /// appear as folders in the admin tree block. They contain admin_settingpage's,
813 /// admin_externalpage's, and other admin_category's.
815 /// OTHER NOTES
817 /// admin_settingpage's, admin_externalpage's, and admin_category's all inherit
818 /// from part_of_admin_tree (a pseudointerface). This interface insists that
819 /// a class has a check_access method for access permissions, a locate method
820 /// used to find a specific node in the admin tree, and a path method used
821 /// to determine the path to a specific node in the $ADMIN tree.
823 /// admin_category's inherit from parentable_part_of_admin_tree. This pseudo-
824 /// interface ensures that the class implements a recursive add function which
825 /// accepts a part_of_admin_tree object and searches for the proper place to
826 /// put it. parentable_part_of_admin_tree implies part_of_admin_tree.
828 /// Please note that the $this->name field of any part_of_admin_tree must be
829 /// UNIQUE throughout the ENTIRE admin tree.
831 /// The $this->name field of an admin_setting object (which is *not* part_of_
832 /// admin_tree) must be unique on the respective admin_settingpage where it is
833 /// used.
836 /// MISCELLANEOUS STUFF (used by classes defined below) ///////////////////////
837 include_once($CFG->dirroot . '/backup/lib.php');
839 /// CLASS DEFINITIONS /////////////////////////////////////////////////////////
842 * Pseudointerface for anything appearing in the admin tree
844 * The pseudointerface that is implemented by anything that appears in the admin tree
845 * block. It forces inheriting classes to define a method for checking user permissions
846 * and methods for finding something in the admin tree.
848 * @author Vincenzo K. Marcovecchio
849 * @package admin
851 class part_of_admin_tree {
854 * Finds a named part_of_admin_tree.
856 * Used to find a part_of_admin_tree. If a class only inherits part_of_admin_tree
857 * and not parentable_part_of_admin_tree, then this function should only check if
858 * $this->name matches $name. If it does, it should return a reference to $this,
859 * otherwise, it should return a reference to NULL.
861 * If a class inherits parentable_part_of_admin_tree, this method should be called
862 * recursively on all child objects (assuming, of course, the parent object's name
863 * doesn't match the search criterion).
865 * @param string $name The internal name of the part_of_admin_tree we're searching for.
866 * @return mixed An object reference or a NULL reference.
868 function &locate($name) {
869 trigger_error('Admin class does not implement method <strong>locate()</strong>', E_USER_WARNING);
870 return;
874 * Removes named part_of_admin_tree.
876 * @param string $name The internal name of the part_of_admin_tree we want to remove.
877 * @return bool success.
879 function prune($name) {
880 trigger_error('Admin class does not implement method <strong>prune()</strong>', E_USER_WARNING);
881 return;
885 * Verifies current user's access to this part_of_admin_tree.
887 * Used to check if the current user has access to this part of the admin tree or
888 * not. If a class only inherits part_of_admin_tree and not parentable_part_of_admin_tree,
889 * then this method is usually just a call to has_capability() in the site context.
891 * If a class inherits parentable_part_of_admin_tree, this method should return the
892 * logical OR of the return of check_access() on all child objects.
894 * @return bool True if the user has access, false if she doesn't.
896 function check_access() {
897 trigger_error('Admin class does not implement method <strong>check_access()</strong>', E_USER_WARNING);
898 return;
902 * Mostly usefull for removing of some parts of the tree in admin tree block.
904 * @return True is hidden from normal list view
906 function is_hidden() {
907 trigger_error('Admin class does not implement method <strong>is_hidden()</strong>', E_USER_WARNING);
908 return;
912 * Determines the path to $name in the admin tree.
914 * Used to determine the path to $name in the admin tree. If a class inherits only
915 * part_of_admin_tree and not parentable_part_of_admin_tree, then this method should
916 * check if $this->name matches $name. If it does, $name is pushed onto the $path
917 * array (at the end), and $path should be returned. If it doesn't, NULL should be
918 * returned.
920 * If a class inherits parentable_part_of_admin_tree, it should do the above, but not
921 * return NULL on failure. Instead, it pushes $this->name onto $path, and then
922 * recursively calls path() on its child objects. If any are non-NULL, it should
923 * return $path (being certain that the last element of $path is equal to $name).
924 * If they are all NULL, it returns NULL.
926 * @param string $name The internal name of the part_of_admin_tree we're searching for.
927 * @param array $path Not used on external calls. Defaults to empty array.
928 * @return mixed If found, an array containing the internal names of each part_of_admin_tree that leads to $name. If not found, NULL.
930 function path($name, $path = array()) {
931 trigger_error('Admin class does not implement method <strong>path()</strong>', E_USER_WARNING);
932 return;
937 * Pseudointerface implemented by any part_of_admin_tree that has children.
939 * The pseudointerface implemented by any part_of_admin_tree that can be a parent
940 * to other part_of_admin_tree's. (For now, this only includes admin_category.) Apart
941 * from ensuring part_of_admin_tree compliancy, it also ensures inheriting methods
942 * include an add method for adding other part_of_admin_tree objects as children.
944 * @author Vincenzo K. Marcovecchio
945 * @package admin
947 class parentable_part_of_admin_tree extends part_of_admin_tree {
950 * Adds a part_of_admin_tree object to the admin tree.
952 * Used to add a part_of_admin_tree object to this object or a child of this
953 * object. $something should only be added if $destinationname matches
954 * $this->name. If it doesn't, add should be called on child objects that are
955 * also parentable_part_of_admin_tree's.
957 * @param string $destinationname The internal name of the new parent for $something.
958 * @param part_of_admin_tree &$something The object to be added.
959 * @return bool True on success, false on failure.
961 function add($destinationname, &$something) {
962 trigger_error('Admin class does not implement method <strong>add()</strong>', E_USER_WARNING);
963 return;
969 * The object used to represent folders (a.k.a. categories) in the admin tree block.
971 * Each admin_category object contains a number of part_of_admin_tree objects.
973 * @author Vincenzo K. Marcovecchio
974 * @package admin
976 class admin_category extends parentable_part_of_admin_tree {
979 * @var mixed An array of part_of_admin_tree objects that are this object's children
981 var $children;
984 * @var string An internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
986 var $name;
989 * @var string The displayed name for this category. Usually obtained through get_string()
991 var $visiblename;
994 * @var bool Should this category be hidden in admin tree block?
996 var $hidden;
998 // constructor for an empty admin category
999 // $name is the internal name of the category. it MUST be unique in the entire hierarchy
1000 // $visiblename is the displayed name of the category. use a get_string for this
1003 * Constructor for an empty admin category
1005 * @param string $name The internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
1006 * @param string $visiblename The displayed named for this category. Usually obtained through get_string()
1007 * @param bool $hidden hide category in admin tree block
1008 * @return mixed Returns the new object.
1010 function admin_category($name, $visiblename, $hidden = false) {
1011 $this->children = array();
1012 $this->name = $name;
1013 $this->visiblename = $visiblename;
1014 $this->hidden = $hidden;
1018 * Finds the path to the part_of_admin_tree called $name.
1020 * @param string $name The internal name that we're searching for.
1021 * @param array $path Used internally for recursive calls. Do not specify on external calls. Defaults to array().
1022 * @return mixed An array of internal names that leads to $name, or NULL if not found.
1024 function path($name, $path = array()) {
1026 $path[count($path)] = $this->name;
1028 if ($this->name == $name) {
1029 return $path;
1032 foreach($this->children as $child) {
1033 if ($return = $child->path($name, $path)) {
1034 return $return;
1038 return NULL;
1043 * Returns a reference to the part_of_admin_tree object with internal name $name.
1045 * @param string $name The internal name of the object we want.
1046 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
1048 function &locate($name) {
1050 if ($this->name == $name) {
1051 return $this;
1054 foreach($this->children as $child) {
1055 if ($return =& $child->locate($name)) {
1056 return $return;
1059 $return = NULL;
1060 return $return;
1064 * Removes part_of_admin_tree object with internal name $name.
1066 * @param string $name The internal name of the object we want to remove.
1067 * @return bool success
1069 function prune($name) {
1071 if ($this->name == $name) {
1072 return false; //can not remove itself
1075 foreach($this->children as $precedence => $child) {
1076 if ($child->name == $name) {
1077 // found it!
1078 unset($this->children[$precedence]);
1079 return true;
1081 if ($this->children[$precedence]->prune($name)) {
1082 return true;
1085 return false;
1089 * Adds a part_of_admin_tree to a child or grandchild (or great-grandchild, and so forth) of this object.
1091 * @param string $destinationame The internal name of the immediate parent that we want for &$something.
1092 * @param mixed &$something A part_of_admin_tree object to be added.
1093 * @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".
1094 * @return bool True if successfully added, false if &$something is not a part_of_admin_tree or if $name is not found.
1096 function add($destinationname, &$something, $precedence = '') {
1098 if (!is_a($something, 'part_of_admin_tree')) {
1099 return false;
1102 if ($destinationname == $this->name) {
1103 if ($precedence === '') {
1104 $this->children[] = $something;
1105 } else {
1106 if (isset($this->children[$precedence])) { // this should never, ever be triggered in a release version of moodle.
1107 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 />');
1109 $this->children[$precedence] = $something;
1111 return true;
1114 unset($entries);
1116 $entries = array_keys($this->children);
1118 foreach($entries as $entry) {
1119 $child =& $this->children[$entry];
1120 if (is_a($child, 'parentable_part_of_admin_tree')) {
1121 if ($child->add($destinationname, $something, $precedence)) {
1122 return true;
1127 return false;
1132 * Checks if the user has access to anything in this category.
1134 * @return bool True if the user has access to atleast one child in this category, false otherwise.
1136 function check_access() {
1138 $return = false;
1139 foreach ($this->children as $child) {
1140 $return = $return || $child->check_access();
1143 return $return;
1148 * Is this category hidden in admin tree block?
1150 * @return bool True if hidden
1152 function is_hidden() {
1153 return $this->hidden;
1158 * Links external PHP pages into the admin tree.
1160 * See detailed usage example at the top of this document (adminlib.php)
1162 * @author Vincenzo K. Marcovecchio
1163 * @package admin
1165 class admin_externalpage extends part_of_admin_tree {
1168 * @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects
1170 var $name;
1173 * @var string The displayed name for this external page. Usually obtained through get_string().
1175 var $visiblename;
1178 * @var string The external URL that we should link to when someone requests this external page.
1180 var $url;
1183 * @var string The role capability/permission a user must have to access this external page.
1185 var $req_capability;
1188 * @var object The context in which capability/permission should be checked, default is site context.
1190 var $context;
1193 * @var bool hidden in admin tree block.
1195 var $hidden;
1198 * Constructor for adding an external page into the admin tree.
1200 * @param string $name The internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects.
1201 * @param string $visiblename The displayed name for this external page. Usually obtained through get_string().
1202 * @param string $url The external URL that we should link to when someone requests this external page.
1203 * @param mixed $req_capability The role capability/permission a user must have to access this external page. Defaults to 'moodle/site:config'.
1205 function admin_externalpage($name, $visiblename, $url, $req_capability = 'moodle/site:config', $hidden=false, $context=NULL) {
1206 $this->name = $name;
1207 $this->visiblename = $visiblename;
1208 $this->url = $url;
1209 if (is_array($req_capability)) {
1210 $this->req_capability = $req_capability;
1211 } else {
1212 $this->req_capability = array($req_capability);
1214 $this->hidden = $hidden;
1215 $this->context = $context;
1219 * Finds the path to the part_of_admin_tree called $name.
1221 * @param string $name The internal name that we're searching for.
1222 * @param array $path Used internally for recursive calls. Do not specify on external calls. Defaults to array().
1223 * @return mixed An array of internal names that leads to $name, or NULL if not found.
1225 function path($name, $path = array()) {
1226 if ($name == $this->name) {
1227 array_push($path, $this->name);
1228 return $path;
1229 } else {
1230 return NULL;
1235 * Returns a reference to the part_of_admin_tree object with internal name $name.
1237 * @param string $name The internal name of the object we want.
1238 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
1240 function &locate($name) {
1241 $return = ($this->name == $name ? $this : NULL);
1242 return $return;
1245 function prune($name) {
1246 return false;
1250 * Determines if the current user has access to this external page based on $this->req_capability.
1252 * @uses CONTEXT_SYSTEM
1253 * @uses SITEID
1254 * @return bool True if user has access, false otherwise.
1256 function check_access() {
1257 if (!get_site()) {
1258 return true; // no access check before site is fully set up
1260 $context = empty($this->context) ? get_context_instance(CONTEXT_SYSTEM) : $this->context;
1261 foreach($this->req_capability as $cap) {
1262 if (has_capability($cap, $context)) {
1263 return true;
1266 return false;
1270 * Is this external page hidden in admin tree block?
1272 * @return bool True if hidden
1274 function is_hidden() {
1275 return $this->hidden;
1281 * Used to group a number of admin_setting objects into a page and add them to the admin tree.
1283 * @author Vincenzo K. Marcovecchio
1284 * @package admin
1286 class admin_settingpage extends part_of_admin_tree {
1289 * @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects
1291 var $name;
1294 * @var string The displayed name for this external page. Usually obtained through get_string().
1296 var $visiblename;
1298 * @var mixed An array of admin_setting objects that are part of this setting page.
1300 var $settings;
1303 * @var string The role capability/permission a user must have to access this external page.
1305 var $req_capability;
1308 * @var object The context in which capability/permission should be checked, default is site context.
1310 var $context;
1313 * @var bool hidden in admin tree block.
1315 var $hidden;
1317 // see admin_category
1318 function path($name, $path = array()) {
1319 if ($name == $this->name) {
1320 array_push($path, $this->name);
1321 return $path;
1322 } else {
1323 return NULL;
1327 // see admin_category
1328 function &locate($name) {
1329 $return = ($this->name == $name ? $this : NULL);
1330 return $return;
1333 function prune($name) {
1334 return false;
1337 // see admin_externalpage
1338 function admin_settingpage($name, $visiblename, $req_capability = 'moodle/site:config', $hidden=false, $context=NULL) {
1339 global $CFG;
1340 $this->settings = new stdClass();
1341 $this->name = $name;
1342 $this->visiblename = $visiblename;
1343 if (is_array($req_capability)) {
1344 $this->req_capability = $req_capability;
1345 } else {
1346 $this->req_capability = array($req_capability);
1348 $this->hidden = false;
1349 $this->context = $context;
1352 // 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
1353 // n.b. each admin_setting in an admin_settingpage must have a unique internal name
1354 // &$setting is the admin_setting object you want to add
1355 // returns true if successful, false if not (will fail if &$setting is an admin_setting or child thereof)
1356 function add(&$setting) {
1357 if (is_a($setting, 'admin_setting')) {
1358 $this->settings->{$setting->name} =& $setting;
1359 return true;
1361 return false;
1364 // see admin_externalpage
1365 function check_access() {
1366 if (!get_site()) {
1367 return true; // no access check before site is fully set up
1369 $context = empty($this->context) ? get_context_instance(CONTEXT_SYSTEM) : $this->context;
1370 foreach($this->req_capability as $cap) {
1371 if (has_capability($cap, $context)) {
1372 return true;
1375 return false;
1378 // outputs this page as html in a table (suitable for inclusion in an admin pagetype)
1379 // returns a string of the html
1380 function output_html() {
1381 $return = '<fieldset>' . "\n";
1382 $return .= '<div class="clearer"><!-- --></div>' . "\n";
1383 foreach($this->settings as $setting) {
1384 $return .= $setting->output_html();
1386 $return .= '</fieldset>';
1387 return $return;
1390 // 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
1391 // -- calls write_setting() to each child setting, sending it only the data that matches each setting's internal name
1392 // $data should be the result from data_submitted()
1393 // returns an empty string if everything went well, otherwise returns a printable error string (that's language-specific)
1394 function write_settings($data) {
1395 $return = '';
1396 foreach($this->settings as $setting) {
1397 if (isset($data['s_' . $setting->name])) {
1398 $return .= $setting->write_setting($data['s_' . $setting->name]);
1399 } else {
1400 $return .= $setting->write_setting('');
1403 return $return;
1407 * Is this settigns page hidden in admin tree block?
1409 * @return bool True if hidden
1411 function is_hidden() {
1412 return $this->hidden;
1418 // read & write happens at this level; no authentication
1419 class admin_setting {
1421 var $name;
1422 var $visiblename;
1423 var $description;
1424 var $defaultsetting;
1426 function admin_setting($name, $visiblename, $description, $defaultsetting) {
1427 $this->name = $name;
1428 $this->visiblename = $visiblename;
1429 $this->description = $description;
1430 $this->defaultsetting = $defaultsetting;
1433 function get_setting() {
1434 return NULL; // has to be overridden
1437 function get_defaultsetting() {
1438 return $this->defaultsetting;
1441 function write_setting($data) {
1442 return; // has to be overridden
1445 function output_html() {
1446 return; // has to be overridden
1452 class admin_setting_configtext extends admin_setting {
1454 var $paramtype;
1456 function admin_setting_configtext($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW) {
1457 $this->paramtype = $paramtype;
1458 parent::admin_setting($name, $visiblename, $description, $defaultsetting);
1461 // returns a string or NULL
1462 function get_setting() {
1463 global $CFG;
1464 return (isset($CFG->{$this->name}) ? $CFG->{$this->name} : NULL);
1467 // $data is a string
1468 function write_setting($data) {
1469 if (!$this->validate($data)) {
1470 return get_string('validateerror', 'admin') . $this->visiblename . '<br />';
1472 return (set_config($this->name,$data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1475 function validate($data) {
1476 if (is_string($this->paramtype)) {
1477 return preg_match($this->paramtype, $data);
1478 } else if ($this->paramtype === PARAM_RAW) {
1479 return true;
1480 } else {
1481 $cleaned = clean_param($data, $this->paramtype);
1482 return ("$data" == "$cleaned"); // implicit conversion to string is needed to do exact comparison
1486 function output_html() {
1487 if ($this->get_setting() === NULL) {
1488 $current = $this->defaultsetting;
1489 } else {
1490 $current = $this->get_setting();
1492 return format_admin_setting($this->name, $this->visiblename,
1493 '<input type="text" class="form-text" id="id_s_'.$this->name.'" name="s_'.$this->name.'" value="'.s($current).'" />',
1494 $this->description);
1499 class admin_setting_configpasswordunmask extends admin_setting_configtext {
1501 function admin_setting_configpasswordunmask($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW) {
1502 parent::admin_setting_configtext($name, $visiblename, $description, $defaultsetting, $paramtype);
1505 function output_html() {
1506 if ($this->get_setting() === NULL) {
1507 $current = $this->defaultsetting;
1508 } else {
1509 $current = $this->get_setting();
1511 $id = 'id_s_'.$this->name;
1512 $unmask = get_string('unmaskpassword', 'form');
1513 $unmaskjs = '<script type="text/javascript">
1514 //<![CDATA[
1515 document.write(\'<div class="unmask"><input id="'.$id.'unmask" value="1" type="checkbox" onclick="unmaskPassword(\\\''.$id.'\\\')"/><label for="'.$id.'unmask">'.addslashes_js($unmask).'<\/label><\/div>\');
1516 //]]>
1517 </script>';
1518 return format_admin_setting($this->name, $this->visiblename,
1519 '<input type="password" class="form-text" id="id_s_'.$this->name.'" name="s_'.$this->name.'" value="'.s($current).'" />'.$unmaskjs,
1520 $this->description);
1525 class admin_setting_configcheckbox extends admin_setting {
1527 function admin_setting_configcheckbox($name, $visiblename, $description, $defaultsetting) {
1528 parent::admin_setting($name, $visiblename, $description, $defaultsetting);
1531 function get_setting() {
1532 global $CFG;
1533 return (isset($CFG->{$this->name}) ? $CFG->{$this->name} : NULL);
1536 function write_setting($data) {
1537 if ($data == '1') {
1538 return (set_config($this->name,1) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1539 } else {
1540 return (set_config($this->name,0) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1544 function output_html() {
1545 if ($this->get_setting() === NULL) {
1546 $current = $this->defaultsetting;
1547 } else {
1548 $current = $this->get_setting();
1550 return format_admin_setting($this->name, $this->visiblename,
1551 '<input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'" name="s_'. $this->name .'" value="1" ' . ($current == true ? 'checked="checked"' : '') . ' />',
1552 $this->description);
1557 class admin_setting_configselect extends admin_setting {
1559 var $choices;
1561 function admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices) {
1562 $this->choices = $choices;
1563 parent::admin_setting($name, $visiblename, $description, $defaultsetting);
1566 function get_setting() {
1567 global $CFG;
1568 return (isset($CFG->{$this->name}) ? $CFG->{$this->name} : NULL);
1571 function write_setting($data) {
1572 // check that what we got was in the original choices
1573 // or that the data is the default setting - needed during install when choices can not be constructed yet
1574 if ($data != $this->defaultsetting and ! in_array($data, array_keys($this->choices))) {
1575 return 'Error setting ' . $this->visiblename . '<br />';
1578 return (set_config($this->name, $data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1581 function output_html() {
1582 if ($this->get_setting() === NULL) {
1583 $current = $this->defaultsetting;
1584 } else {
1585 $current = $this->get_setting();
1587 $return = '<select class="form-select" id="id_s_'.$this->name.'" name="s_' . $this->name .'">';
1588 foreach ($this->choices as $key => $value) {
1589 // the string cast is needed because key may be integer - 0 is equal to most strings!
1590 $return .= '<option value="'.$key.'"'.((string)$key==$current ? ' selected="selected"' : '').'>'.$value.'</option>';
1592 $return .= '</select>';
1594 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
1599 // 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
1600 // internally for the setting)
1601 class admin_setting_configtime extends admin_setting {
1603 var $name2;
1604 var $choices;
1605 var $choices2;
1607 function admin_setting_configtime($hoursname, $minutesname, $visiblename, $description, $defaultsetting) {
1608 $this->name2 = $minutesname;
1609 $this->choices = array();
1610 for ($i = 0; $i < 24; $i++) {
1611 $this->choices[$i] = $i;
1613 $this->choices2 = array();
1614 for ($i = 0; $i < 60; $i += 5) {
1615 $this->choices2[$i] = $i;
1617 parent::admin_setting($hoursname, $visiblename, $description, $defaultsetting);
1620 function get_setting() {
1621 global $CFG;
1622 return (isset($CFG->{$this->name}) && isset($CFG->{$this->name2}) ? array('h' => $CFG->{$this->name}, 'm' => $CFG->{$this->name2}) : NULL);
1625 function write_setting($data) {
1626 // check that what we got was in the original choices
1627 if (!(in_array($data['h'], array_keys($this->choices)) && in_array($data['m'], array_keys($this->choices2)))) {
1628 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
1631 return (set_config($this->name, $data['h']) && set_config($this->name2, $data['m']) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1634 function output_html() {
1635 if ($this->get_setting() === NULL) {
1636 $currentsetting = $this->defaultsetting;
1637 } else {
1638 $currentsetting = $this->get_setting();
1640 $return = '<div class="form-group">'.
1641 '<select class="form-select" id="id_s_'.$this->name.'h" name="s_' . $this->name .'[h]">';
1642 foreach ($this->choices as $key => $value) {
1643 $return .= '<option value="' . $key . '"' . ($key == $currentsetting['h'] ? ' selected="selected"' : '') . '>' . $value . '</option>';
1645 $return .= '</select>:<select class="form-select" id="id_s_'.$this->name.'m" name="s_' . $this->name . '[m]">';
1646 foreach ($this->choices2 as $key => $value) {
1647 $return .= '<option value="' . $key . '"' . ($key == $currentsetting['m'] ? ' selected="selected"' : '') . '>' . $value . '</option>';
1649 $return .= '</select></div>';
1650 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
1655 class admin_setting_configmultiselect extends admin_setting_configselect {
1657 function admin_setting_configmultiselect($name, $visiblename, $description, $defaultsetting, $choices) {
1658 parent::admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices);
1661 function get_setting() {
1662 global $CFG;
1663 if (isset($CFG->{$this->name})) {
1664 if ($CFG->{$this->name}) {
1665 return explode(',', $CFG->{$this->name});
1666 } else {
1667 return array();
1669 } else {
1670 return NULL;
1674 function write_setting($data) {
1675 if (empty($data)) {
1676 $data = array();
1678 foreach ($data as $datum) {
1679 if (! in_array($datum, array_keys($this->choices))) {
1680 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
1684 return (set_config($this->name, implode(',',$data)) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1687 function output_html() {
1688 if ($this->get_setting() === NULL) {
1689 $currentsetting = $this->defaultsetting;
1690 if (!$currentsetting) {
1691 $currentsetting = array();
1693 } else {
1694 $currentsetting = $this->get_setting();
1696 $return = '<select class="form-select" id="id_s_'.$this->name.'" name="s_' . $this->name .'[]" size="10" multiple="multiple">';
1697 foreach ($this->choices as $key => $value) {
1698 $return .= '<option value="' . $key . '"' . (in_array($key,$currentsetting) ? ' selected="selected"' : '') . '>' . $value . '</option>';
1700 $return .= '</select>';
1701 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
1706 class admin_setting_special_adminseesall extends admin_setting_configcheckbox {
1708 function admin_setting_special_adminseesall() {
1709 $name = 'calendar_adminseesall';
1710 $visiblename = get_string('adminseesall', 'admin');
1711 $description = get_string('helpadminseesall', 'admin');
1712 parent::admin_setting($name, $visiblename, $description, 0);
1715 function write_setting($data) {
1716 global $SESSION;
1717 unset($SESSION->cal_courses_shown);
1718 parent::write_setting($data);
1722 class admin_setting_sitesetselect extends admin_setting_configselect {
1724 var $id;
1726 function admin_setting_sitesetselect($name, $visiblename, $description, $defaultsetting, $choices) {
1728 $this->id = SITEID;
1729 parent::admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices);
1733 function get_setting() {
1734 $site = get_site();
1735 return (isset($site->{$this->name}) ? $site->{$this->name} : NULL);
1738 function write_setting($data) {
1739 if (!in_array($data, array_keys($this->choices))) {
1740 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
1742 $record = new stdClass();
1743 $record->id = $this->id;
1744 $temp = $this->name;
1745 $record->$temp = $data;
1746 $record->timemodified = time();
1747 return (update_record('course', $record) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1753 class admin_setting_courselist_frontpage extends admin_setting_configselect {
1755 function admin_setting_courselist_frontpage($loggedin) {
1756 global $CFG;
1757 require_once($CFG->dirroot . '/course/lib.php');
1758 $name = 'frontpage' . ($loggedin ? 'loggedin' : '');
1759 $visiblename = get_string('frontpage' . ($loggedin ? 'loggedin' : ''),'admin');
1760 $description = get_string('configfrontpage' . ($loggedin ? 'loggedin' : ''),'admin');
1761 $choices = array(FRONTPAGENEWS => get_string('frontpagenews'),
1762 FRONTPAGECOURSELIST => get_string('frontpagecourselist'),
1763 FRONTPAGECATEGORYNAMES => get_string('frontpagecategorynames'),
1764 FRONTPAGECATEGORYCOMBO => get_string('frontpagecategorycombo'),
1765 '' => get_string('none'));
1766 if (!$loggedin and count_records("course") > FRONTPAGECOURSELIMIT) {
1767 unset($choices[FRONTPAGECOURSELIST]);
1769 $defaults = FRONTPAGECOURSELIST.',,,';
1770 parent::admin_setting_configselect($name, $visiblename, $description, $defaults, $choices);
1773 function get_setting() {
1774 global $CFG;
1775 return (isset($CFG->{$this->name}) ? explode(',', $CFG->{$this->name}) : ',1,,');
1778 function write_setting($data) {
1779 if (empty($data)) {
1780 $data = array();
1781 } if (!is_array($data)) {
1782 $data = explode(',', $data);
1784 foreach($data as $datum) {
1785 if (! in_array($datum, array_keys($this->choices))) {
1786 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
1789 return (set_config($this->name, implode(',', $data)) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1792 function output_html() {
1793 if ($this->get_setting() === NULL) {
1794 $currentsetting = $this->defaultsetting;
1795 } else {
1796 $currentsetting = $this->get_setting();
1798 for ($i = 0; $i < count($this->choices) - 1; $i++) {
1799 if (!isset($currentsetting[$i])) {
1800 $currentsetting[$i] = 0;
1803 $return = '<div class="form-group">';
1804 for ($i = 0; $i < count($this->choices) - 1; $i++) {
1805 $return .='<select class="form-select" id="id_s_'.$this->name.$i.'" name="s_' . $this->name .'[]">';
1806 foreach ($this->choices as $key => $value) {
1807 $return .= '<option value="' . $key . '"' . ($key == $currentsetting[$i] ? ' selected="selected"' : '') . '>' . $value . '</option>';
1809 $return .= '</select>';
1810 if ($i !== count($this->choices) - 2) {
1811 $return .= '<br />';
1814 $return .= '</div>';
1816 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
1820 class admin_setting_sitesetcheckbox extends admin_setting_configcheckbox {
1822 var $id;
1824 function admin_setting_sitesetcheckbox($name, $visiblename, $description, $defaultsetting) {
1826 $this->id = SITEID;
1827 parent::admin_setting_configcheckbox($name, $visiblename, $description, $defaultsetting);
1831 function get_setting() {
1832 $site = get_site();
1833 return $site->{$this->name};
1836 function write_setting($data) {
1837 $record = new stdClass();
1838 $record->id = $this->id;
1839 $temp = $this->name;
1840 $record->$temp = ($data == '1' ? 1 : 0);
1841 $record->timemodified = time();
1842 return (update_record('course', $record) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1847 class admin_setting_sitesettext extends admin_setting_configtext {
1849 var $id;
1851 function admin_setting_sitesettext($name, $visiblename, $description, $defaultsetting) {
1853 $this->id = SITEID;
1854 parent::admin_setting_configtext($name, $visiblename, $description, $defaultsetting);
1858 function get_setting() {
1859 $site = get_site();
1860 return $site->{$this->name} != '' ? $site->{$this->name} : NULL;
1863 function validate($data) {
1864 $cleaned = stripslashes(clean_param($data, PARAM_MULTILANG));
1865 if ($cleaned == '') {
1866 return false; // can not be empty
1868 return ($data == $cleaned); // implicit conversion to string is needed to do exact comparison
1871 function write_setting($data) {
1872 $data = trim($data);
1873 if (!$this->validate($data)) {
1874 return get_string('validateerror', 'admin') . $this->visiblename . '<br />';
1877 $record = new stdClass();
1878 $record->id = $this->id;
1879 $record->{$this->name} = addslashes($data);
1880 $record->timemodified = time();
1881 return (update_record('course', $record) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1886 class admin_setting_special_frontpagedesc extends admin_setting {
1888 var $id;
1890 function admin_setting_special_frontpagedesc() {
1891 $this->id = SITEID;
1892 $name = 'summary';
1893 $visiblename = get_string('frontpagedescription');
1894 $description = get_string('frontpagedescriptionhelp');
1895 parent::admin_setting($name, $visiblename, $description, '');
1898 function output_html() {
1899 global $CFG;
1901 $CFG->adminusehtmleditor = can_use_html_editor();
1902 $return = print_textarea($CFG->adminusehtmleditor, 15, 60, 0, 0, 's_' . $this->name, $this->get_setting(), 0, true);
1904 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
1907 function get_setting() {
1908 $site = get_site();
1909 return $site->{$this->name};
1912 function get_defaultsetting() {
1913 return NULL;
1916 function write_setting($data) {
1917 $record = new object();
1918 $record->id = $this->id;
1919 $record->{$this->name} = addslashes($data);
1920 $record->timemodified = time();
1922 return(update_record('course', $record) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1928 class admin_setting_special_editorfontlist extends admin_setting {
1930 var $items;
1932 function admin_setting_special_editorfontlist() {
1933 global $CFG;
1934 $name = 'editorfontlist';
1935 $visiblename = get_string('editorfontlist', 'admin');
1936 $description = get_string('configeditorfontlist', 'admin');
1937 $defaults = array('k0' => 'Trebuchet',
1938 'v0' => 'Trebuchet MS,Verdana,Arial,Helvetica,sans-serif',
1939 'k1' => 'Arial',
1940 'v1' => 'arial,helvetica,sans-serif',
1941 'k2' => 'Courier New',
1942 'v2' => 'courier new,courier,monospace',
1943 'k3' => 'Georgia',
1944 'v3' => 'georgia,times new roman,times,serif',
1945 'k4' => 'Tahoma',
1946 'v4' => 'tahoma,arial,helvetica,sans-serif',
1947 'k5' => 'Times New Roman',
1948 'v5' => 'times new roman,times,serif',
1949 'k6' => 'Verdana',
1950 'v6' => 'verdana,arial,helvetica,sans-serif',
1951 'k7' => 'Impact',
1952 'v7' => 'impact',
1953 'k8' => 'Wingdings',
1954 'v8' => 'wingdings');
1955 parent::admin_setting($name, $visiblename, $description, $defaults);
1958 function get_setting() {
1959 global $CFG;
1960 if (isset($CFG->editorfontlist)) {
1961 $i = 0;
1962 $currentsetting = array();
1963 $items = explode(';', $CFG->editorfontlist);
1964 foreach ($items as $item) {
1965 $item = explode(':', $item);
1966 $currentsetting['k' . $i] = $item[0];
1967 $currentsetting['v' . $i] = $item[1];
1968 $i++;
1970 return $currentsetting;
1971 } else {
1972 return NULL;
1976 function write_setting($data) {
1978 // there miiight be an easier way to do this :)
1979 // if this is changed, make sure the $defaults array above is modified so that this
1980 // function processes it correctly
1982 $keys = array();
1983 $values = array();
1985 foreach ($data as $key => $value) {
1986 if (substr($key,0,1) == 'k') {
1987 $keys[substr($key,1)] = $value;
1988 } elseif (substr($key,0,1) == 'v') {
1989 $values[substr($key,1)] = $value;
1993 $result = '';
1994 for ($i = 0; $i < count($keys); $i++) {
1995 if (($keys[$i] !== '') && ($values[$i] !== '')) {
1996 $result .= clean_param($keys[$i],PARAM_NOTAGS) . ':' . clean_param($values[$i], PARAM_NOTAGS) . ';';
2000 $result = substr($result, 0, -1); // trim the last semicolon
2002 return (set_config($this->name, $result) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2005 function output_html() {
2007 if ($this->get_setting() === NULL) {
2008 $currentsetting = $this->defaultsetting;
2009 } else {
2010 $currentsetting = $this->get_setting();
2013 $return = '<div class="form-group">';
2014 for ($i = 0; $i < count($currentsetting) / 2; $i++) {
2015 $return .= '<input type="text" class="form-text" name="s_editorfontlist[k' . $i . ']" value="' . $currentsetting['k' . $i] . '" />';
2016 $return .= '&nbsp;&nbsp;';
2017 $return .= '<input type="text" class="form-text" name="s_editorfontlist[v' . $i . ']" value="' . $currentsetting['v' . $i] . '" /><br />';
2019 $return .= '<input type="text" class="form-text" name="s_editorfontlist[k' . $i . ']" value="" />';
2020 $return .= '&nbsp;&nbsp;';
2021 $return .= '<input type="text" class="form-text" name="s_editorfontlist[v' . $i . ']" value="" /><br />';
2022 $return .= '<input type="text" class="form-text" name="s_editorfontlist[k' . ($i + 1) . ']" value="" />';
2023 $return .= '&nbsp;&nbsp;';
2024 $return .= '<input type="text" class="form-text" name="s_editorfontlist[v' . ($i + 1) . ']" value="" />';
2025 $return .= '</div>';
2027 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
2032 class admin_setting_special_editordictionary extends admin_setting_configselect {
2034 function admin_setting_special_editordictionary() {
2035 $name = 'editordictionary';
2036 $visiblename = get_string('editordictionary','admin');
2037 $description = get_string('configeditordictionary', 'admin');
2038 $choices = $this->editor_get_dictionaries();
2039 if (! is_array($choices)) {
2040 $choices = array('');
2043 parent::admin_setting_configselect($name, $visiblename, $description, '', $choices);
2046 // function borrowed from the old moodle/admin/editor.php, slightly modified
2047 function editor_get_dictionaries () {
2048 /// Get all installed dictionaries in the system
2050 global $CFG;
2052 // error_reporting(E_ALL); // for debug, final version shouldn't have this...
2053 clearstatcache();
2055 // If aspellpath isn't set don't even bother ;-)
2056 if (empty($CFG->aspellpath)) {
2057 return 'Empty aspell path!';
2060 // Do we have access to popen function?
2061 if (!function_exists('popen')) {
2062 return 'Popen function disabled!';
2065 $cmd = $CFG->aspellpath;
2066 $output = '';
2067 $dictionaries = array();
2068 $dicts = array();
2070 if(!($handle = @popen(escapeshellarg($cmd) .' dump dicts', 'r'))) {
2071 return 'Couldn\'t create handle!';
2074 while(!feof($handle)) {
2075 $output .= fread($handle, 1024);
2077 @pclose($handle);
2079 $dictionaries = explode(chr(10), $output);
2081 // Get rid of possible empty values
2082 if (is_array($dictionaries)) {
2084 $cnt = count($dictionaries);
2086 for ($i = 0; $i < $cnt; $i++) {
2087 if (!empty($dictionaries[$i])) {
2088 $dicts[$dictionaries[$i]] = $dictionaries[$i];
2093 if (count($dicts) >= 1) {
2094 return $dicts;
2097 return 'Error! Check your aspell installation!';
2105 class admin_setting_special_editorhidebuttons extends admin_setting {
2107 var $name;
2108 var $visiblename;
2109 var $description;
2110 var $items;
2112 function admin_setting_special_editorhidebuttons() {
2113 $this->name = 'editorhidebuttons';
2114 $this->visiblename = get_string('editorhidebuttons', 'admin');
2115 $this->description = get_string('confeditorhidebuttons', 'admin');
2116 $this->defaultsetting = array();
2117 // weird array... buttonname => buttonimage (assume proper path appended). if you leave buttomimage blank, text will be printed instead
2118 $this->items = array('fontname' => '',
2119 'fontsize' => '',
2120 'formatblock' => '',
2121 'bold' => 'ed_format_bold.gif',
2122 'italic' => 'ed_format_italic.gif',
2123 'underline' => 'ed_format_underline.gif',
2124 'strikethrough' => 'ed_format_strike.gif',
2125 'subscript' => 'ed_format_sub.gif',
2126 'superscript' => 'ed_format_sup.gif',
2127 'copy' => 'ed_copy.gif',
2128 'cut' => 'ed_cut.gif',
2129 'paste' => 'ed_paste.gif',
2130 'clean' => 'ed_wordclean.gif',
2131 'undo' => 'ed_undo.gif',
2132 'redo' => 'ed_redo.gif',
2133 'justifyleft' => 'ed_align_left.gif',
2134 'justifycenter' => 'ed_align_center.gif',
2135 'justifyright' => 'ed_align_right.gif',
2136 'justifyfull' => 'ed_align_justify.gif',
2137 'lefttoright' => 'ed_left_to_right.gif',
2138 'righttoleft' => 'ed_right_to_left.gif',
2139 'insertorderedlist' => 'ed_list_num.gif',
2140 'insertunorderedlist' => 'ed_list_bullet.gif',
2141 'outdent' => 'ed_indent_less.gif',
2142 'indent' => 'ed_indent_more.gif',
2143 'forecolor' => 'ed_color_fg.gif',
2144 'hilitecolor' => 'ed_color_bg.gif',
2145 'inserthorizontalrule' => 'ed_hr.gif',
2146 'createanchor' => 'ed_anchor.gif',
2147 'createlink' => 'ed_link.gif',
2148 'unlink' => 'ed_unlink.gif',
2149 'insertimage' => 'ed_image.gif',
2150 'inserttable' => 'insert_table.gif',
2151 'insertsmile' => 'em.icon.smile.gif',
2152 'insertchar' => 'icon_ins_char.gif',
2153 'spellcheck' => 'spell-check.gif',
2154 'htmlmode' => 'ed_html.gif',
2155 'popupeditor' => 'fullscreen_maximize.gif',
2156 'search_replace' => 'ed_replace.gif');
2159 function get_setting() {
2160 global $CFG;
2161 return (isset($CFG->{$this->name}) ? explode(' ', $CFG->{$this->name}) : NULL);
2164 function write_setting($data) {
2165 $result = array();
2166 if (empty($data)) { $data = array(); }
2167 foreach ($data as $key => $value) {
2168 if (!in_array($key, array_keys($this->items))) {
2169 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2171 if ($value == '1') {
2172 $result[] = $key;
2175 return (set_config($this->name, implode(' ',$result)) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2178 function output_html() {
2180 global $CFG;
2182 // checkboxes with input name="$this->name[$key]" value="1"
2183 // we do 15 fields per column
2185 if ($this->get_setting() === NULL) {
2186 $currentsetting = $this->defaultsetting;
2187 } else {
2188 $currentsetting = $this->get_setting();
2191 $return = '<div class="form-group">';
2192 $return .= '<table><tr><td valign="top" align="right">';
2194 $count = 0;
2196 foreach($this->items as $key => $value) {
2197 if ($count % 15 == 0 and $count != 0) {
2198 $return .= '</td><td valign="top" align="right">';
2201 $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;';
2202 $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;';
2203 $count++;
2204 if ($count % 15 != 0) {
2205 $return .= '<br /><br />';
2209 $return .= '</td></tr>';
2210 $return .= '</table>';
2211 $return .= '</div>';
2213 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
2218 class admin_setting_langlist extends admin_setting_configtext {
2219 function admin_setting_langlist() {
2220 parent::admin_setting_configtext('langlist', get_string('langlist', 'admin'), get_string('configlanglist', 'admin'), '', PARAM_NOTAGS);
2223 function write_setting($data) {
2224 $return = parent::write_setting($data);
2225 get_list_of_languages(true);//refresh the list
2226 return $return;
2230 class admin_setting_backupselect extends admin_setting_configselect {
2232 function admin_setting_backupselect($name, $visiblename, $description, $default, $choices) {
2233 parent::admin_setting_configselect($name, $visiblename, $description, $default, $choices);
2236 function get_setting() {
2237 $backup_config = backup_get_config();
2238 return (isset($backup_config->{$this->name}) ? $backup_config->{$this->name} : NULL);
2241 function write_setting($data) {
2242 // check that what we got was in the original choices
2243 if (! in_array($data, array_keys($this->choices))) {
2244 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2247 return (backup_set_config($this->name, $data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2252 class admin_setting_special_backupsaveto extends admin_setting_configtext {
2254 function admin_setting_special_backupsaveto() {
2255 $name = 'backup_sche_destination';
2256 $visiblename = get_string('saveto');
2257 $description = get_string('backupsavetohelp');
2258 parent::admin_setting_configtext($name, $visiblename, $description, '');
2261 function get_setting() {
2262 $backup_config = backup_get_config();
2263 return (isset($backup_config->{$this->name}) ? $backup_config->{$this->name} : NULL);
2266 function write_setting($data) {
2267 $data = trim($data);
2268 if (!empty($data) and !is_dir($data)) {
2269 return get_string('pathnotexists') . '<br />';
2271 return (backup_set_config($this->name, $data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2276 class admin_setting_backupcheckbox extends admin_setting_configcheckbox {
2278 function admin_setting_backupcheckbox($name, $visiblename, $description, $default) {
2279 parent::admin_setting_configcheckbox($name, $visiblename, $description, $default);
2282 function write_setting($data) {
2283 if ($data == '1') {
2284 return (backup_set_config($this->name, 1) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2285 } else {
2286 return (backup_set_config($this->name, 0) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2290 function get_setting() {
2291 $backup_config = backup_get_config();
2292 return (isset($backup_config->{$this->name}) ? $backup_config->{$this->name} : NULL);
2297 class admin_setting_special_backuptime extends admin_setting_configtime {
2299 function admin_setting_special_backuptime() {
2300 $name = 'backup_sche_hour';
2301 $name2 = 'backup_sche_minute';
2302 $visiblename = get_string('executeat');
2303 $description = get_string('backupexecuteathelp');
2304 $default = array('h' => 0, 'm' => 0);
2305 parent::admin_setting_configtime($name, $name2, $visiblename, $description, $default);
2308 function get_setting() {
2309 $backup_config = backup_get_config();
2310 return (isset($backup_config->{$this->name}) && isset($backup_config->{$this->name}) ? array('h'=>$backup_config->{$this->name}, 'm'=>$backup_config->{$this->name2}) : NULL);
2313 function write_setting($data) {
2314 // check that what we got was in the original choices
2315 if (!(in_array($data['h'], array_keys($this->choices)) && in_array($data['m'], array_keys($this->choices2)))) {
2316 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2319 return (backup_set_config($this->name, $data['h']) && backup_set_config($this->name2, $data['m']) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2324 class admin_setting_special_backupdays extends admin_setting {
2326 function admin_setting_special_backupdays() {
2327 $name = 'backup_sche_weekdays';
2328 $visiblename = get_string('schedule');
2329 $description = get_string('backupschedulehelp');
2330 $default = array('u' => 0, 'm' => 0, 't' => 0, 'w' => 0, 'r' => 0, 'f' => 0, 's' => 0);
2331 parent::admin_setting($name, $visiblename, $description, $default);
2334 function get_setting() {
2335 $backup_config = backup_get_config();
2336 if (isset($backup_config->{$this->name})) {
2337 $currentsetting = $backup_config->{$this->name};
2338 return array('u' => substr($currentsetting, 0, 1),
2339 'm' => substr($currentsetting, 1, 1),
2340 't' => substr($currentsetting, 2, 1),
2341 'w' => substr($currentsetting, 3, 1),
2342 'r' => substr($currentsetting, 4, 1),
2343 'f' => substr($currentsetting, 5, 1),
2344 's' => substr($currentsetting, 6, 1));
2345 } else {
2346 return NULL;
2350 function output_html() {
2352 if ($this->get_setting() === NULL) {
2353 $currentsetting = $this->defaultsetting;
2354 } else {
2355 $currentsetting = $this->get_setting();
2358 // rewrite for simplicity
2359 $currentsetting = $currentsetting['u'] . $currentsetting['m'] . $currentsetting['t'] . $currentsetting['w'] .
2360 $currentsetting['r'] . $currentsetting['f'] . $currentsetting['s'];
2362 $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;' .
2363 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;' .
2364 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;' .
2365 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>' .
2366 '<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>' .
2367 '<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>' .
2368 '<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>' .
2369 '<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>' .
2370 '<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>' .
2371 '<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>' .
2372 '<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>' .
2373 '</tr></table>';
2375 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
2379 // 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
2380 // admin_settingpage (note that admin_settingpage only calls write_setting with the data that matches $this->name... so if we have multiple form fields,
2381 // they MUST go into an array named $this->name, or else we won't receive them here
2382 function write_setting($data) {
2383 $week = 'umtwrfs';
2384 $result = array(0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0);
2385 if (!empty($data)) {
2386 foreach($data as $key => $value) {
2387 if ($value == '1') {
2388 $result[strpos($week, $key)] = 1;
2392 return (backup_set_config($this->name, implode('',$result)) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2396 class admin_setting_special_debug extends admin_setting_configselect {
2398 function admin_setting_special_debug() {
2399 $name = 'debug';
2400 $visiblename = get_string('debug', 'admin');
2401 $description = get_string('configdebug', 'admin');
2402 $choices = array( DEBUG_NONE => get_string('debugnone', 'admin'),
2403 DEBUG_MINIMAL => get_string('debugminimal', 'admin'),
2404 DEBUG_NORMAL => get_string('debugnormal', 'admin'),
2405 DEBUG_ALL => get_string('debugall', 'admin'),
2406 DEBUG_DEVELOPER => get_string('debugdeveloper', 'admin')
2408 parent::admin_setting_configselect($name, $visiblename, $description, '', $choices);
2411 function get_setting() {
2412 global $CFG;
2413 if (isset($CFG->debug)) {
2414 return $CFG->debug;
2415 } else {
2416 return NULL;
2420 function write_setting($data) {
2421 return (set_config($this->name,$data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2427 class admin_setting_special_calendar_weekend extends admin_setting {
2429 function admin_setting_special_calendar_weekend() {
2430 $name = 'calendar_weekend';
2431 $visiblename = get_string('calendar_weekend', 'admin');
2432 $description = get_string('helpweekenddays', 'admin');
2433 $default = array ('0', '6'); // Saturdays and Sundays
2434 parent::admin_setting($name, $visiblename, $description, $default);
2437 function get_setting() {
2438 global $CFG;
2439 return isset($CFG->{$this->name}) ? $CFG->{$this->name} : 0;
2442 function write_setting($data) {
2443 $result = 0;
2444 if (!empty($data)) {
2445 foreach($data as $index) {
2446 $result |= 1 << $index;
2449 return (set_config($this->name, $result) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2452 function output_html() {
2453 if ($this->get_setting() === NULL) {
2454 $currentsetting = $this->defaultsetting;
2455 } else {
2456 $currentsetting = $this->get_setting();
2459 // The order matters very much because of the implied numeric keys
2460 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
2461 $return = '<table><thead><tr>';
2462 foreach($days as $index => $day) {
2463 $return .= '<td><label for="id_s_'.$this->name.$index.'">'.get_string($day, 'calendar').'</label></td>';
2465 $return .= '</tr></thead><tbody><tr>';
2466 foreach($days as $index => $day) {
2467 $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>';
2469 $return .= '</tr></tbody></table>';
2471 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
2478 * this is used in config->appearance->gradeconfig
2480 class admin_setting_special_gradebookroles extends admin_setting {
2482 function admin_setting_special_gradebookroles() {
2483 $name = 'gradebookroles';
2484 $visiblename = get_string('gradebookroles', 'admin');
2485 $description = get_string('configgradebookroles', 'admin');
2486 $default = array(5=>'1'); // The student role in a default install
2487 parent::admin_setting($name, $visiblename, $description, $default);
2490 function get_setting() {
2491 global $CFG;
2492 if (!empty($CFG->{$this->name})) {
2493 $result = explode(',', $CFG->{$this->name});
2494 foreach ($result as $roleid) {
2495 $array[$roleid] = 1;
2497 return $array;
2498 } else {
2499 return null;
2503 function write_setting($data) {
2504 if (!empty($data)) {
2505 $str = '';
2506 foreach ($data as $key => $value) {
2507 if ($value) {
2508 $str .= $key.',';
2511 return set_config($this->name, rtrim($str, ","))?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2512 } else {
2513 return set_config($this->name, '')?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2517 function output_html() {
2519 if ($this->get_setting() === NULL) {
2520 $currentsetting = $this->defaultsetting;
2521 } else {
2522 $currentsetting = $this->get_setting();
2524 // from to process which roles to display
2525 if ($roles = get_records('role')) {
2526 $return = '<div class="form-group">';
2527 $first = true;
2528 foreach ($roles as $roleid=>$role) {
2529 if (is_array($currentsetting) && in_array($roleid, array_keys($currentsetting))) {
2530 $checked = ' checked="checked"';
2531 } else {
2532 $checked = '';
2534 if ($first) {
2535 $first = false;
2536 } else {
2537 $return .= '<br />';
2539 $return .= '<input type="checkbox" name="s_'.$this->name.'['.$roleid.']" value="1"'.$checked.' />&nbsp;'.format_string($role->name);
2541 $return .= '</div>';
2544 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
2551 * this is used in config->appearance->coursemanager
2552 * (which roles to show on course decription page)
2554 class admin_setting_special_coursemanager extends admin_setting {
2556 function admin_setting_special_coursemanager() {
2557 $name = 'coursemanager';
2558 $visiblename = get_string('coursemanager', 'admin');
2559 $description = get_string('configcoursemanager', 'admin');
2560 $default = array(3=>'1'); // The teahcer role in a default install
2561 parent::admin_setting($name, $visiblename, $description, $default);
2564 function get_setting() {
2566 global $CFG;
2567 if (!empty($CFG->{$this->name})) {
2568 $result = explode(',', $CFG->{$this->name});
2569 foreach ($result as $roleid) {
2570 $array[$roleid] = 1;
2572 return $array;
2573 } else if (isset($CFG->{$this->name})) {
2574 return array();
2575 } else {
2576 return null;
2580 function write_setting($data) {
2582 if (!empty($data)) {
2583 $str = '';
2584 foreach ($data as $key => $value) {
2585 if ($value) {
2586 $str .= $key.',';
2589 return set_config($this->name, rtrim($str, ","))?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2590 } else {
2591 return set_config($this->name, '')?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2595 function output_html() {
2597 if ($this->get_setting() === NULL) {
2598 $currentsetting = $this->defaultsetting;
2599 } else {
2600 $currentsetting = $this->get_setting();
2602 // from to process which roles to display
2603 if ($roles = get_records_select('role', '', 'sortorder')) {
2604 $return = '<div class="form-group">';
2605 $first = true;
2606 foreach ($roles as $roleid=>$role) {
2607 if (is_array($currentsetting) && in_array($roleid, array_keys($currentsetting))) {
2608 $checked = 'checked="checked"';
2609 } else {
2610 $checked = '';
2612 if ($first) {
2613 $first = false;
2614 } else {
2615 $return .= '<br />';
2617 $return .= '<input type="checkbox" name="s_'.$this->name.'['.$roleid.']" value="1" '.$checked.' />&nbsp;'.$role->name;
2619 $return .= '</div>';
2621 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
2626 * this is used in config->courses->gradeexports
2627 * (which roles to show on course decription page)
2629 class admin_setting_special_gradeexport extends admin_setting {
2631 function admin_setting_special_gradeexport() {
2632 $name = 'gradeexport';
2633 $visiblename = get_string('gradeexport', 'admin');
2634 $description = get_string('configgradeexport', 'admin');
2635 $default = array(3=>'1'); // The teahcer role in a default install
2636 parent::admin_setting($name, $visiblename, $description, $default);
2639 function get_setting() {
2641 global $CFG;
2642 if (!empty($CFG->{$this->name})) {
2643 $result = explode(',', $CFG->{$this->name});
2644 foreach ($result as $plugin) {
2645 $array[$plugin] = 1;
2647 return $array;
2648 } else if (isset($CFG->{$this->name})) {
2649 return array();
2650 } else {
2651 return null;
2655 function write_setting($data) {
2657 if (!empty($data)) {
2658 $str = '';
2659 foreach ($data as $key => $value) {
2660 if ($value) {
2661 $str .= $key.',';
2664 return set_config($this->name, rtrim($str, ","))?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2665 } else {
2666 return set_config($this->name, '')?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2670 function output_html() {
2672 if ($this->get_setting() === NULL) {
2673 $currentsetting = $this->defaultsetting;
2674 } else {
2675 $currentsetting = $this->get_setting();
2677 // from to process which roles to display
2678 if ($exports = get_list_of_plugins('grade/export')) {
2679 $return = '<div class="form-group">';
2680 $first = true;
2681 foreach ($exports as $export) {
2682 if (is_array($currentsetting) && in_array($export, array_keys($currentsetting))) {
2683 $checked = 'checked="checked"';
2684 } else {
2685 $checked = '';
2687 if ($first) {
2688 $first = false;
2689 } else {
2690 $return .= '<br />';
2692 $return .= '<input type="checkbox" name="s_'.$this->name.'['.$export.']" value="1" '.$checked.' />&nbsp;'.$export;
2694 $return .= '</div>';
2696 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
2703 class admin_setting_special_perfdebug extends admin_setting_configcheckbox {
2705 function admin_setting_special_perfdebug() {
2706 $name = 'perfdebug';
2707 $visiblename = get_string('perfdebug', 'admin');
2708 $description = get_string('configperfdebug', 'admin');
2709 parent::admin_setting_configcheckbox($name, $visiblename, $description, '');
2712 function write_setting($data) {
2714 if ($data == '1') {
2715 return (set_config($this->name,15) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2716 } else {
2717 return (set_config($this->name,7) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2721 function output_html() {
2723 if ($this->get_setting() === NULL) {
2724 $currentsetting = $this->defaultsetting;
2725 } else {
2726 $currentsetting = $this->get_setting();
2729 $return = '<input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'" name="s_'. $this->name .'" value="1" ' . ($currentsetting == 15 ? 'checked="checked"' : '') . ' />';
2730 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
2735 class admin_setting_special_debugdisplay extends admin_setting_configcheckbox {
2737 function admin_setting_special_debugdisplay() {
2738 $name = 'debugdisplay';
2739 $visiblename = get_string('debugdisplay', 'admin');
2740 $description = get_string('configdebugdisplay', 'admin');
2741 $default = ini_get('display_errors');
2742 parent::admin_setting_configcheckbox($name, $visiblename, $description, $default);
2745 function write_setting($data) {
2747 if ($data == '1') {
2748 return (set_config($this->name,1) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2749 } else {
2750 return (set_config($this->name,0) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2754 function output_html() {
2756 if ($this->get_setting() === NULL) {
2757 $currentsetting = $this->defaultsetting;
2758 } else {
2759 $currentsetting = $this->get_setting();
2762 $return = '<input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'" name="s_'. $this->name .'" value="1" ' . ($currentsetting == 1 ? 'checked="checked"' : '') . ' />';
2763 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
2769 // Code for a function that helps externalpages print proper headers and footers
2770 // N.B.: THIS FUNCTION HANDLES AUTHENTICATION
2771 function admin_externalpage_setup($section) {
2773 global $CFG, $PAGE, $USER;
2775 $adminroot = admin_get_root();
2777 require_once($CFG->libdir . '/blocklib.php');
2778 require_once($CFG->dirroot . '/'.$CFG->admin.'/pagelib.php');
2780 page_map_class(PAGE_ADMIN, 'page_admin');
2782 $PAGE = page_create_object(PAGE_ADMIN, 0); // there must be any constant id number
2784 $PAGE->init_extra($section); // hack alert!
2786 $root = $adminroot->locate($PAGE->section);
2788 if ($site = get_site()) {
2789 require_login();
2790 } else {
2791 redirect($CFG->wwwroot . '/'.$CFG->admin.'/index.php');
2792 die;
2795 if (!is_a($root, 'admin_externalpage')) {
2796 error(get_string('sectionerror','admin'));
2797 die;
2800 // this eliminates our need to authenticate on the actual pages
2801 if (!($root->check_access())) {
2802 error(get_string('accessdenied', 'admin'));
2803 die;
2806 $adminediting = optional_param('adminedit', -1, PARAM_BOOL);
2808 if (!isset($USER->adminediting)) {
2809 $USER->adminediting = false;
2812 if ($PAGE->user_allowed_editing()) {
2813 if ($adminediting == 1) {
2814 $USER->adminediting = true;
2815 } elseif ($adminediting == 0) {
2816 $USER->adminediting = false;
2823 * TODO document
2825 function admin_externalpage_print_header() {
2827 global $CFG, $PAGE, $SITE, $THEME;
2829 if (!empty($THEME->customcorners)) {
2830 require_once($CFG->dirroot.'/lib/custom_corners_lib.php');
2833 define('ADMIN_EXT_HEADER_PRINTED', 'true');
2835 if (!empty($SITE->fullname)) {
2836 $pageblocks = blocks_setup($PAGE);
2838 $preferred_width_left = bounded_number(BLOCK_L_MIN_WIDTH,
2839 blocks_preferred_width($pageblocks[BLOCK_POS_LEFT]),
2840 BLOCK_L_MAX_WIDTH);
2841 $PAGE->print_header();
2842 echo '<table id="layout-table" summary=""><tr>';
2844 $lt = (empty($THEME->layouttable)) ? array('left', 'middle', 'right') : $THEME->layouttable;
2845 foreach ($lt as $column) {
2846 $lt1[] = $column;
2847 if ($column == 'middle') break;
2849 foreach ($lt1 as $column) {
2850 switch ($column) {
2851 case 'left':
2852 echo '<td style="width: ' . $preferred_width_left . 'px;" id="left-column">';
2853 if (!empty($THEME->customcorners)) print_custom_corners_start();
2854 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT);
2855 if (!empty($THEME->customcorners)) print_custom_corners_end();
2856 echo '</td>';
2857 break;
2859 case 'middle':
2860 echo '<td id="middle-column">';
2861 if (!empty($THEME->customcorners)) print_custom_corners_start();
2862 break;
2864 case 'right':
2865 if (blocks_have_content($pageblocks, BLOCK_POS_RIGHT)) {
2866 echo '<td style="width: ' . $preferred_width_right . 'px;" id="right-column">';
2867 if (!empty($THEME->customcorners)) print_custom_corners_start();
2868 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT);
2869 if (!empty($THEME->customcorners)) print_custom_corners_end();
2870 echo '</td>';
2872 break;
2875 } else {
2876 print_header();
2880 function admin_externalpage_print_footer() {
2882 global $CFG, $PAGE, $SITE, $THEME;
2884 if (!empty($THEME->customcorners)) {
2885 require_once($CFG->dirroot.'/lib/custom_corners_lib.php');
2888 define('ADMIN_EXT_FOOTER_PRINTED', 'true');
2890 if (!empty($SITE->fullname)) {
2891 $pageblocks = blocks_setup($PAGE);
2892 $preferred_width_right = bounded_number(BLOCK_R_MIN_WIDTH,
2893 blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT]),
2894 BLOCK_R_MAX_WIDTH);
2896 $lt = (empty($THEME->layouttable)) ? array('left', 'middle', 'right') : $THEME->layouttable;
2897 foreach ($lt as $column) {
2898 if ($column != 'middle') {
2899 array_shift($lt);
2900 } else if ($column == 'middle') {
2901 break;
2904 foreach ($lt as $column) {
2905 switch ($column) {
2906 case 'left':
2907 echo '<td style="width: ' . $preferred_width_left . 'px;" id="left-column">';
2908 if (!empty($THEME->customcorners)) print_custom_corners_start();
2909 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT);
2910 if (!empty($THEME->customcorners)) print_custom_corners_end();
2911 echo '</td>';
2912 break;
2914 case 'middle':
2915 if (!empty($THEME->customcorners)) print_custom_corners_end();
2916 echo '</td>';
2917 break;
2919 case 'right':
2920 if (blocks_have_content($pageblocks, BLOCK_POS_RIGHT)) {
2921 echo '<td style="width: ' . $preferred_width_right . 'px;" id="right-column">';
2922 if (!empty($THEME->customcorners)) print_custom_corners_start();
2923 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT);
2925 if (!empty($THEME->customcorners)) print_custom_corners_end();
2926 echo '</td>';
2928 break;
2931 echo '</tr></table>';
2933 print_footer();
2936 function admin_get_root() {
2937 global $CFG;
2939 static $ADMIN;
2941 if (!isset($ADMIN)) {
2942 // start the admin tree!
2943 $ADMIN = new admin_category('root', get_string("administration"));
2944 // we process this file first to get categories up and running
2945 include($CFG->dirroot . '/'.$CFG->admin.'/settings/top.php');
2947 // now we process all other files in admin/settings to build the
2948 // admin tree
2949 foreach (glob($CFG->dirroot . '/'.$CFG->admin.'/settings/*.php') as $file) {
2950 if ($file != $CFG->dirroot . '/'.$CFG->admin.'/settings/top.php') {
2951 include_once($file);
2956 return $ADMIN;
2959 /// settings utility functions
2962 * This function applies default settings.
2963 * @param object $node
2964 * @param bool $uncoditional if true overrides all values with defaults
2965 * @return void
2967 function apply_default_settings(&$node, $unconditional=true) {
2969 global $CFG;
2971 if (is_a($node, 'admin_category')) {
2972 $entries = array_keys($node->children);
2973 foreach ($entries as $entry) {
2974 apply_default_settings($node->children[$entry]);
2976 return;
2979 if (is_a($node, 'admin_settingpage')) {
2980 foreach ($node->settings as $setting) {
2981 if (!$unconditional and !is_null($setting->get_setting)) {
2982 //do not override existing defaults
2983 continue;
2985 $defaultsetting = $setting->get_defaultsetting();
2986 if (is_null($defaultsetting)) {
2987 // no value yet - default maybe applied after admin user creation or in upgradesettings
2988 continue;
2990 $CFG->{$setting->name} = $defaultsetting;
2991 $setting->write_setting($defaultsetting);
2992 unset($setting); // needed to prevent odd (imho) reference behaviour
2993 // see http://www.php.net/manual/en/language.references.whatdo.php#AEN6399
2995 return;
2998 return;
3002 // n.b. this function unconditionally applies default settings
3003 function apply_default_exception_settings($defaults) {
3005 global $CFG;
3007 foreach($defaults as $key => $value) {
3008 $CFG->$key = $value;
3009 set_config($key, $value);
3014 function format_admin_setting($name, $title='', $form='', $description='', $label=true) {
3016 // sometimes the id is not id_s_name, but id_s_name_m or something, and this does not validate
3017 if ($label) {
3018 $labelfor = 'for = "id_s_'.$name.'"';
3019 } else {
3020 $labelfor = '';
3023 $str = "\n".
3024 '<div class="form-item" id="admin-'.$name.'">'."\n".
3025 '<label '.$labelfor.'>'.$title."\n".
3026 ' <span class="form-shortname">'.$name.'</span>'."\n".
3027 '</label>'."\n".
3028 $form."\n".
3029 '<div class="description">'.$description.'</div>'."\n".
3030 '</div>'.
3031 "\n\n";
3033 return $str;
3037 * Try to upgrade the given language pack (or current language)
3038 * If it doesn't work, fail silently and return false
3040 function upgrade_language_pack($lang='') {
3041 global $CFG;
3043 if (empty($lang)) {
3044 $lang = current_language();
3047 if ($lang == 'en_utf8') {
3048 return true; // Nothing to do
3051 notify(get_string('langimport', 'admin').': '.$lang.' ... ', 'notifysuccess');
3053 @mkdir ($CFG->dataroot.'/temp/'); //make it in case it's a fresh install, it might not be there
3054 @mkdir ($CFG->dataroot.'/lang/');
3056 require_once($CFG->libdir.'/componentlib.class.php');
3058 if ($cd = new component_installer('http://download.moodle.org', 'lang16', $lang.'.zip', 'languages.md5', 'lang')) {
3059 $status = $cd->install(); //returns ERROR | UPTODATE | INSTALLED
3061 if ($status == INSTALLED) {
3062 debugging('Downloading successful: '.$lang);
3063 @unlink($CFG->dataroot.'/cache/languages');
3064 return true;
3068 return false;
3072 * Based on find_new_settings{@link ()} in upgradesettings.php
3073 * Looks to find any admin settings that have not been initialized. Returns 1 if it finds any.
3075 * @param string &$node The node at which to start searching.
3076 * @return int Returns 1 if any settings haven't been initialised, 0 if they all have
3078 function any_new_admin_settings(&$node) {
3080 if (is_a($node, 'admin_category')) {
3081 $entries = array_keys($node->children);
3082 foreach ($entries as $entry) {
3083 if( any_new_admin_settings($node->children[$entry]) ){
3084 return 1;
3089 if (is_a($node, 'admin_settingpage')) {
3090 foreach ($node->settings as $setting) {
3091 if ($setting->get_setting() === NULL) {
3092 return 1;
3098 return 0;