4 * adminlib.php - Contains functions that only administrators will ever need to use
6 * @author Martin Dougiamas and many others
8 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
12 define('INSECURE_DATAROOT_WARNING', 1);
13 define('INSECURE_DATAROOT_ERROR', 2);
15 function upgrade_main_savepoint($result, $version) {
19 if ($CFG->version
>= $version) {
20 // something really wrong is going on in main upgrade script
21 error("Upgrade savepoint: Can not upgrade main version from $CFG->version to $version.");
23 set_config('version', $version);
25 notify ("Upgrade savepoint: Error during main upgrade to version $version");
29 function upgrade_mod_savepoint($result, $version, $type) {
33 function upgrade_plugin_savepoint($result, $version, $type, $dir) {
37 function upgrade_backup_savepoint($result, $version) {
41 function upgrade_blocks_savepoint($result, $version, $type) {
50 * @param string $type The type of plugins that should be updated (e.g. 'enrol', 'qtype')
51 * @param string $dir The directory where the plugins are located (e.g. 'question/questiontypes')
52 * @param string $return The url to prompt the user to continue to
54 function upgrade_plugins($type, $dir, $return) {
57 /// Let's know if the header has been printed, so the funcion is being called embedded in an outer page
58 $embedded = defined('HEADER_PRINTED');
60 $plugs = get_list_of_plugins($dir);
61 $updated_plugins = false;
62 $strpluginsetup = get_string('pluginsetup');
64 foreach ($plugs as $plug) {
66 $fullplug = $CFG->dirroot
.'/'.$dir.'/'. $plug;
70 if (is_readable($fullplug .'/version.php')) {
71 include_once($fullplug .'/version.php'); // defines $plugin with version etc
73 continue; // Nothing to do.
78 if (is_readable($fullplug . '/db/'. $CFG->dbtype
. '.php')) {
79 include_once($fullplug . '/db/'. $CFG->dbtype
. '.php'); // defines old upgrading function
82 if (is_readable($fullplug . '/db/upgrade.php')) {
83 include_once($fullplug . '/db/upgrade.php'); // defines new upgrading function
87 if (!isset($plugin)) {
91 if (!empty($plugin->requires
)) {
92 if ($plugin->requires
> $CFG->version
) {
94 $info->pluginname
= $plug;
95 $info->pluginversion
= $plugin->version
;
96 $info->currentmoodle
= $CFG->version
;
97 $info->requiremoodle
= $plugin->requires
;
98 if (!$updated_plugins && !$embedded) {
99 print_header($strpluginsetup, $strpluginsetup,
100 build_navigation(array(array('name' => $strpluginsetup, 'link' => null, 'type' => 'misc'))), '',
101 upgrade_get_javascript(), false, ' ', ' ');
104 notify(get_string('pluginrequirementsnotmet', 'error', $info));
105 $updated_plugins = true;
110 $plugin->name
= $plug; // The name MUST match the directory
112 $pluginversion = $type.'_'.$plug.'_version';
114 if (!isset($CFG->$pluginversion)) {
115 set_config($pluginversion, 0);
118 if ($CFG->$pluginversion == $plugin->version
) {
120 } else if ($CFG->$pluginversion < $plugin->version
) {
121 if (!$updated_plugins && !$embedded) {
122 print_header($strpluginsetup, $strpluginsetup,
123 build_navigation(array(array('name' => $strpluginsetup, 'link' => null, 'type' => 'misc'))), '',
124 upgrade_get_javascript(), false, ' ', ' ');
126 $updated_plugins = true;
128 print_heading($dir.'/'. $plugin->name
.' plugin needs upgrading');
130 @set_time_limit
(0); // To allow slow databases to complete the long SQL
132 if ($CFG->$pluginversion == 0) { // It's a new install of this plugin
133 /// Both old .sql files and new install.xml are supported
134 /// but we priorize install.xml (XMLDB) if present
136 if (file_exists($fullplug . '/db/install.xml')) {
137 $status = install_from_xmldb_file($fullplug . '/db/install.xml'); //New method
138 } else if (file_exists($fullplug .'/db/'. $CFG->dbtype
.'.sql')) {
139 $status = modify_database($fullplug .'/db/'. $CFG->dbtype
.'.sql'); //Old method
145 /// Continue with the instalation, roles and other stuff
147 /// OK so far, now update the plugins record
148 set_config($pluginversion, $plugin->version
);
150 /// Install capabilities
151 if (!update_capabilities($type.'/'.$plug)) {
152 error('Could not set up the capabilities for '.$plugin->name
.'!');
155 events_update_definition($type.'/'.$plug);
157 /// Run local install function if there is one
158 if (is_readable($fullplug .'/lib.php')) {
159 include_once($fullplug .'/lib.php');
160 $installfunction = $plugin->name
.'_install';
161 if (function_exists($installfunction)) {
162 if (! $installfunction() ) {
163 notify('Encountered a problem running install function for '.$module->name
.'!');
168 notify(get_string('modulesuccess', '', $plugin->name
), 'notifysuccess');
170 notify('Installing '. $plugin->name
.' FAILED!');
172 } else { // Upgrade existing install
173 /// Run de old and new upgrade functions for the module
174 $oldupgrade_function = $type.'_'.$plugin->name
.'_upgrade';
175 $newupgrade_function = 'xmldb_' . $type.'_'.$plugin->name
.'_upgrade';
177 /// First, the old function if exists
178 $oldupgrade_status = true;
179 if ($oldupgrade && function_exists($oldupgrade_function)) {
181 $oldupgrade_status = $oldupgrade_function($CFG->$pluginversion);
182 } else if ($oldupgrade) {
183 notify ('Upgrade function ' . $oldupgrade_function . ' was not available in ' .
184 $fullplug . '/db/' . $CFG->dbtype
. '.php');
187 /// Then, the new function if exists and the old one was ok
188 $newupgrade_status = true;
189 if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) {
191 $newupgrade_status = $newupgrade_function($CFG->$pluginversion);
192 } else if ($newupgrade) {
193 notify ('Upgrade function ' . $newupgrade_function . ' was not available in ' .
194 $fullplug . '/db/upgrade.php');
198 /// Now analyze upgrade results
199 if ($oldupgrade_status && $newupgrade_status) { // No upgrading failed
200 // OK so far, now update the plugins record
201 set_config($pluginversion, $plugin->version
);
202 if (!update_capabilities($type.'/'.$plug)) {
203 error('Could not update '.$plugin->name
.' capabilities!');
205 events_update_definition($type.'/'.$plug);
206 notify(get_string('modulesuccess', '', $plugin->name
), 'notifysuccess');
208 notify('Upgrading '. $plugin->name
.' from '. $CFG->$pluginversion .' to '. $plugin->version
.' FAILED!');
214 error('Version mismatch: '. $plugin->name
.' can\'t downgrade '. $CFG->$pluginversion .' -> '. $plugin->version
.' !');
218 upgrade_log_finish();
220 if ($updated_plugins && !$embedded) {
221 print_continue($return);
222 print_footer('none');
228 * Find and check all modules and load them up or upgrade them if necessary
232 * @param string $return The url to prompt the user to continue to
233 * @todo Finish documenting this function
235 function upgrade_activity_modules($return) {
239 if (!$mods = get_list_of_plugins('mod') ) {
240 error('No modules installed!');
243 $updated_modules = false;
244 $strmodulesetup = get_string('modulesetup');
246 foreach ($mods as $mod) {
248 if ($mod == 'NEWMODULE') { // Someone has unzipped the template, ignore it
252 $fullmod = $CFG->dirroot
.'/mod/'. $mod;
256 if ( is_readable($fullmod .'/version.php')) {
257 include_once($fullmod .'/version.php'); // defines $module with version etc
259 notify('Module '. $mod .': '. $fullmod .'/version.php was not readable');
265 if ( is_readable($fullmod .'/db/' . $CFG->dbtype
. '.php')) {
266 include_once($fullmod .'/db/' . $CFG->dbtype
. '.php'); // defines old upgrading function
269 if ( is_readable($fullmod . '/db/upgrade.php')) {
270 include_once($fullmod . '/db/upgrade.php'); // defines new upgrading function
274 if (!isset($module)) {
278 if (!empty($module->requires
)) {
279 if ($module->requires
> $CFG->version
) {
280 $info = new object();
281 $info->modulename
= $mod;
282 $info->moduleversion
= $module->version
;
283 $info->currentmoodle
= $CFG->version
;
284 $info->requiremoodle
= $module->requires
;
285 if (!$updated_modules) {
286 print_header($strmodulesetup, $strmodulesetup,
287 build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '',
288 upgrade_get_javascript(), false, ' ', ' ');
291 notify(get_string('modulerequirementsnotmet', 'error', $info));
292 $updated_modules = true;
297 $module->name
= $mod; // The name MUST match the directory
299 include_once($fullmod.'/lib.php'); // defines upgrading and/or installing functions
301 if ($currmodule = get_record('modules', 'name', $module->name
)) {
302 if ($currmodule->version
== $module->version
) {
304 } else if ($currmodule->version
< $module->version
) {
305 /// If versions say that we need to upgrade but no upgrade files are available, notify and continue
306 if (!$oldupgrade && !$newupgrade) {
307 notify('Upgrade files ' . $mod . ': ' . $fullmod . '/db/' . $CFG->dbtype
. '.php or ' .
308 $fullmod . '/db/upgrade.php were not readable');
311 if (!$updated_modules) {
312 print_header($strmodulesetup, $strmodulesetup,
313 build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '',
314 upgrade_get_javascript(), false, ' ', ' ');
317 print_heading($module->name
.' module needs upgrading');
319 /// Run de old and new upgrade functions for the module
320 $oldupgrade_function = $module->name
. '_upgrade';
321 $newupgrade_function = 'xmldb_' . $module->name
. '_upgrade';
323 /// First, the old function if exists
324 $oldupgrade_status = true;
325 if ($oldupgrade && function_exists($oldupgrade_function)) {
327 $oldupgrade_status = $oldupgrade_function($currmodule->version
, $module);
328 if (!$oldupgrade_status) {
329 notify ('Upgrade function ' . $oldupgrade_function .
330 ' did not complete successfully.');
332 } else if ($oldupgrade) {
333 notify ('Upgrade function ' . $oldupgrade_function . ' was not available in ' .
334 $mod . ': ' . $fullmod . '/db/' . $CFG->dbtype
. '.php');
337 /// Then, the new function if exists and the old one was ok
338 $newupgrade_status = true;
339 if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) {
341 $newupgrade_status = $newupgrade_function($currmodule->version
, $module);
342 } else if ($newupgrade && $oldupgrade_status) {
343 notify ('Upgrade function ' . $newupgrade_function . ' was not available in ' .
344 $mod . ': ' . $fullmod . '/db/upgrade.php');
348 /// Now analyze upgrade results
349 if ($oldupgrade_status && $newupgrade_status) { // No upgrading failed
350 // OK so far, now update the modules record
351 $module->id
= $currmodule->id
;
352 if (! update_record('modules', $module)) {
353 error('Could not update '. $module->name
.' record in modules table!');
355 remove_dir($CFG->dataroot
. '/cache', true); // flush cache
356 notify(get_string('modulesuccess', '', $module->name
), 'notifysuccess');
359 notify('Upgrading '. $module->name
.' from '. $currmodule->version
.' to '. $module->version
.' FAILED!');
362 /// Update the capabilities table?
363 if (!update_capabilities('mod/'.$module->name
)) {
364 error('Could not update '.$module->name
.' capabilities!');
366 events_update_definition('mod/'.$module->name
);
368 $updated_modules = true;
372 error('Version mismatch: '. $module->name
.' can\'t downgrade '. $currmodule->version
.' -> '. $module->version
.' !');
375 } else { // module not installed yet, so install it
376 if (!$updated_modules) {
377 print_header($strmodulesetup, $strmodulesetup,
378 build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '',
379 upgrade_get_javascript(), false, ' ', ' ');
382 print_heading($module->name
);
383 $updated_modules = true;
385 @set_time_limit
(0); // To allow slow databases to complete the long SQL
387 /// Both old .sql files and new install.xml are supported
388 /// but we priorize install.xml (XMLDB) if present
389 if (file_exists($fullmod . '/db/install.xml')) {
390 $status = install_from_xmldb_file($fullmod . '/db/install.xml'); //New method
392 $status = modify_database($fullmod .'/db/'. $CFG->dbtype
.'.sql'); //Old method
397 /// Continue with the installation, roles and other stuff
399 if ($module->id
= insert_record('modules', $module)) {
402 if (!update_capabilities('mod/'.$module->name
)) {
403 error('Could not set up the capabilities for '.$module->name
.'!');
407 events_update_definition('mod/'.$module->name
);
409 /// Run local install function if there is one
410 $installfunction = $module->name
.'_install';
411 if (function_exists($installfunction)) {
412 if (! $installfunction() ) {
413 notify('Encountered a problem running install function for '.$module->name
.'!');
417 notify(get_string('modulesuccess', '', $module->name
), 'notifysuccess');
420 error($module->name
.' module could not be added to the module list!');
423 error($module->name
.' tables could NOT be set up successfully!');
427 /// Check submodules of this module if necessary
429 $submoduleupgrade = $module->name
.'_upgrade_submodules';
430 if (function_exists($submoduleupgrade)) {
435 /// Run any defaults or final code that is necessary for this module
437 if ( is_readable($fullmod .'/defaults.php')) {
438 // Insert default values for any important configuration variables
440 include($fullmod .'/defaults.php'); // include here means execute, not library include
441 if (!empty($defaults)) {
442 foreach ($defaults as $name => $value) {
443 if (!isset($CFG->$name)) {
444 set_config($name, $value);
451 upgrade_log_finish(); // finish logging if started
453 if ($updated_modules) {
454 print_continue($return);
455 print_footer('none');
461 * Try to obtain or release the cron lock.
463 * @param string $name name of lock
464 * @param int $until timestamp when this lock considered stale, null means remove lock unconditionaly
465 * @param bool $ignorecurrent ignore current lock state, usually entend previous lock
466 * @return bool true if lock obtained
468 function set_cron_lock($name, $until, $ignorecurrent=false) {
470 debugging("Tried to get a cron lock for a null fieldname");
474 // remove lock by force == remove from config table
475 if (is_null($until)) {
476 set_config($name, null);
480 if (!$ignorecurrent) {
481 // read value from db - other processes might have changed it
482 $value = get_field('config', 'value', 'name', $name);
484 if ($value and $value > time()) {
490 set_config($name, $until);
494 function print_progress($done, $total, $updatetime=5, $sleeptime=1, $donetext='') {
499 if ($total < 2) { // No need to show anything
504 if ($done >= $total) {
506 if (!empty($thisbarid)) {
507 $donetext .= ' ('.$done.'/'.$total.') '.get_string('success');
508 print_progress_redraw($thisbarid, $done, $total, 500, $donetext);
509 $thisbarid = $starttime = $lasttime = NULL;
514 if (empty($starttime)) {
515 $starttime = $lasttime = time();
516 $lasttime = $starttime - $updatetime;
517 $thisbarid = uniqid();
518 echo '<table width="500" cellpadding="0" cellspacing="0" align="center"><tr><td width="500">';
519 echo '<div id="bar'.$thisbarid.'" style="border-style:solid;border-width:1px;width:500px;height:50px;">';
520 echo '<div id="slider'.$thisbarid.'" style="border-style:solid;border-width:1px;height:48px;width:10px;background-color:green;"></div>';
522 echo '<div id="text'.$thisbarid.'" align="center" style="width:500px;"></div>';
523 echo '</td></tr></table>';
529 if ($done && (($now - $lasttime) >= $updatetime)) {
530 $elapsedtime = $now - $starttime;
531 $projectedtime = (int)(((float)$total / (float)$done) * $elapsedtime) - $elapsedtime;
532 $percentage = round((float)$done / (float)$total, 2);
533 $width = (int)(500 * $percentage);
535 if ($projectedtime > 10) {
536 $projectedtext = ' Ending: '.format_time($projectedtime);
541 $donetext .= ' ('.$done.'/'.$total.') '.$projectedtext;
542 print_progress_redraw($thisbarid, $done, $total, $width, $donetext);
548 // Don't call this function directly, it's called from print_progress.
549 function print_progress_redraw($thisbarid, $done, $total, $width, $donetext='') {
550 if (empty($thisbarid)) {
554 echo 'document.getElementById("text'.$thisbarid.'").innerHTML = "'.addslashes($donetext).'";'."\n";
555 echo 'document.getElementById("slider'.$thisbarid.'").style.width = \''.$width.'px\';'."\n";
559 function upgrade_get_javascript() {
562 if (!empty($_SESSION['installautopilot'])) {
563 $linktoscrolltoerrors = '<script type="text/javascript">var installautopilot = true;</script>'."\n";
565 $linktoscrolltoerrors = '<script type="text/javascript">var installautopilot = false;</script>'."\n";
567 $linktoscrolltoerrors .= '<script type="text/javascript" src="' . $CFG->wwwroot
. '/lib/scroll_to_errors.js"></script>';
569 return $linktoscrolltoerrors;
572 function create_admin_user() {
575 if (empty($CFG->rolesactive
)) { // No admin user yet.
577 $user = new object();
578 $user->auth
= 'manual';
579 $user->firstname
= get_string('admin');
580 $user->lastname
= get_string('user');
581 $user->username
= 'admin';
582 $user->password
= hash_internal_user_password('admin');
583 $user->email
= 'root@localhost';
584 $user->confirmed
= 1;
585 $user->mnethostid
= $CFG->mnet_localhost_id
;
586 $user->lang
= $CFG->lang
;
587 $user->maildisplay
= 1;
588 $user->timemodified
= time();
590 if (!$user->id
= insert_record('user', $user)) {
591 error('SERIOUS ERROR: Could not create admin user record !!!');
594 if (!$user = get_record('user', 'id', $user->id
)) { // Double check.
595 error('User ID was incorrect (can\'t find it)');
598 // Assign the default admin roles to the new user.
599 if (!$adminroles = get_roles_with_capability('moodle/legacy:admin', CAP_ALLOW
)) {
600 error('No admin role could be found');
602 $sitecontext = get_context_instance(CONTEXT_SYSTEM
);
603 foreach ($adminroles as $adminrole) {
604 role_assign($adminrole->id
, $user->id
, 0, $sitecontext->id
);
607 set_config('rolesactive', 1);
610 $USER = get_complete_user_data('username', 'admin');
611 $USER->newadminuser
= 1;
612 load_all_capabilities();
614 redirect("$CFG->wwwroot/user/editadvanced.php?id=$user->id"); // Edit thyself
616 error('Can not create admin!');
620 ////////////////////////////////////////////////
621 /// upgrade logging functions
622 ////////////////////////////////////////////////
624 $upgradeloghandle = false;
625 $upgradelogbuffer = '';
626 // I did not find out how to use static variable in callback function,
627 // the problem was that I could not flush the static buffer :-(
628 global $upgradeloghandle, $upgradelogbuffer;
631 * Check if upgrade is already running.
633 * If anything goes wrong due to missing call to upgrade_log_finish()
634 * just restart the browser.
636 * @param string warning message indicating upgrade is already running
637 * @param int page reload timeout
639 function upgrade_check_running($message, $timeout) {
640 if (!empty($_SESSION['upgraderunning'])) {
642 redirect(me(), $message, $timeout);
647 * Start logging of output into file (if not disabled) and
648 * prevent aborting and concurrent execution of upgrade script.
650 * Please note that you can not write into session variables after calling this function!
652 * This function may be called repeatedly.
654 function upgrade_log_start() {
655 global $CFG, $upgradeloghandle;
657 if (!empty($_SESSION['upgraderunning'])) {
658 return; // logging already started
661 @ignore_user_abort
(true); // ignore if user stops or otherwise aborts page loading
662 $_SESSION['upgraderunning'] = 1; // set upgrade indicator
663 if (empty($CFG->dbsessions
)) { // workaround for bug in adodb, db session can not be restarted
664 session_write_close(); // from now on user can reload page - will be displayed warning
666 make_upload_directory('upgradelogs');
667 ob_start('upgrade_log_callback', 2); // function for logging to disk; flush each line of text ASAP
668 register_shutdown_function('upgrade_log_finish'); // in case somebody forgets to stop logging
672 * Terminate logging of output, flush all data, allow script aborting
673 * and reopen session for writing. Function error() does terminate the logging too.
675 * Please make sure that each upgrade_log_start() is properly terminated by
676 * this function or error().
678 * This function may be called repeatedly.
680 function upgrade_log_finish() {
681 global $CFG, $upgradeloghandle, $upgradelogbuffer;
683 if (empty($_SESSION['upgraderunning'])) {
684 return; // logging already terminated
688 if ($upgradelogbuffer !== '') {
689 @fwrite
($upgradeloghandle, $upgradelogbuffer);
690 $upgradelogbuffer = '';
692 if ($upgradeloghandle and ($upgradeloghandle !== 'error')) {
693 @fclose
($upgradeloghandle);
694 $upgradeloghandle = false;
696 if (empty($CFG->dbsessions
)) {
697 @session_start
(); // ignore header errors, we only need to reopen session
699 $_SESSION['upgraderunning'] = 0; // clear upgrade indicator
700 if (connection_aborted()) {
703 @ignore_user_abort
(false);
707 * Callback function for logging into files. Not more than one file is created per minute,
708 * upgrade session (terminated by upgrade_log_finish()) is always stored in one file.
710 * This function must not output any characters or throw warnigns and errors!
712 function upgrade_log_callback($string) {
713 global $CFG, $upgradeloghandle, $upgradelogbuffer;
715 if (empty($CFG->disableupgradelogging
) and ($string != '') and ($upgradeloghandle !== 'error')) {
716 if ($upgradeloghandle or ($upgradeloghandle = @fopen
($CFG->dataroot
.'/upgradelogs/upg_'.date('Ymd-Hi').'.html', 'a'))) {
717 $upgradelogbuffer .= $string;
718 if (strlen($upgradelogbuffer) > 2048) { // 2kB write buffer
719 @fwrite
($upgradeloghandle, $upgradelogbuffer);
720 $upgradelogbuffer = '';
723 $upgradeloghandle = 'error';
730 * Test if and critical warnings are present
733 function admin_critical_warnings_present() {
736 if (!has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM
))) {
740 if (!isset($SESSION->admin_critical_warning
)) {
741 $SESSION->admin_critical_warning
= 0;
742 if (ini_get_bool('register_globals')) {
743 $SESSION->admin_critical_warning
= 1;
744 } else if (is_dataroot_insecure(true) === INSECURE_DATAROOT_ERROR
) {
745 $SESSION->admin_critical_warning
= 1;
749 return $SESSION->admin_critical_warning
;
753 * Try to verify that dataroot is not accessible from web.
754 * It is not 100% correct but might help to reduce number of vulnerable sites.
756 * Protection from httpd.conf and .htaccess is not detected properly.
757 * @param bool $fetchtest try to test public access by fetching file
758 * @return mixed empty means secure, INSECURE_DATAROOT_ERROR found a critical problem, INSECURE_DATAROOT_WARNING migth be problematic
760 function is_dataroot_insecure($fetchtest=false) {
763 $siteroot = str_replace('\\', '/', strrev($CFG->dirroot
.'/')); // win32 backslash workaround
765 $rp = preg_replace('|https?://[^/]+|i', '', $CFG->wwwroot
, 1);
766 $rp = strrev(trim($rp, '/'));
767 $rp = explode('/', $rp);
769 if (strpos($siteroot, '/'.$r.'/') === 0) {
770 $siteroot = substr($siteroot, strlen($r)+
1); // moodle web in subdirectory
772 break; // probably alias root
776 $siteroot = strrev($siteroot);
777 $dataroot = str_replace('\\', '/', $CFG->dataroot
.'/');
779 if (strpos($dataroot, $siteroot) !== 0) {
784 return INSECURE_DATAROOT_WARNING
;
787 // now try all methods to fetch a test file using http protocol
789 $httpdocroot = str_replace('\\', '/', strrev($CFG->dirroot
.'/'));
790 preg_match('|(https?://[^/]+)|i', $CFG->wwwroot
, $matches);
791 $httpdocroot = $matches[1];
792 $datarooturl = $httpdocroot.'/'. substr($dataroot, strlen($siteroot));
793 if (make_upload_directory('diag', false) === false) {
794 return INSECURE_DATAROOT_WARNING
;
796 $testfile = $CFG->dataroot
.'/diag/public.txt';
797 if (!file_exists($testfile)) {
798 file_put_contents($testfile, 'test file, do not delete');
800 $teststr = trim(file_get_contents($testfile));
801 if (empty($teststr)) {
803 return INSECURE_DATAROOT_WARNING
;
806 $testurl = $datarooturl.'/diag/public.txt';
808 if (extension_loaded('curl') and ($ch = @curl_init
($testurl)) !== false) {
809 curl_setopt($ch, CURLOPT_RETURNTRANSFER
, true);
810 curl_setopt($ch, CURLOPT_HEADER
, false);
811 $data = curl_exec($ch);
812 if (!curl_errno($ch)) {
814 if ($data === $teststr) {
816 return INSECURE_DATAROOT_ERROR
;
822 if ($data = @file_get_contents
($testurl)) {
824 if ($data === $teststr) {
825 return INSECURE_DATAROOT_ERROR
;
829 preg_match('|https?://([^/]+)|i', $testurl, $matches);
830 $sitename = $matches[1];
832 if ($fp = @fsockopen
($sitename, 80, $error)) {
833 preg_match('|https?://[^/]+(.*)|i', $testurl, $matches);
834 $localurl = $matches[1];
835 $out = "GET $localurl HTTP/1.1\r\n";
836 $out .= "Host: $sitename\r\n";
837 $out .= "Connection: Close\r\n\r\n";
843 $data .= fgets($fp, 1024);
844 } else if (@fgets
($fp, 1024) === "\r\n") {
850 if ($data === $teststr) {
851 return INSECURE_DATAROOT_ERROR
;
855 return INSECURE_DATAROOT_WARNING
;
858 /// =============================================================================================================
859 /// administration tree classes and functions
862 // n.b. documentation is still in progress for this code
866 /// This file performs the following tasks:
867 /// -it defines the necessary objects and interfaces to build the Moodle
869 /// -it defines the admin_externalpage_setup(), admin_externalpage_print_header(),
870 /// and admin_externalpage_print_footer() functions used on admin pages
872 /// ADMIN_SETTING OBJECTS
874 /// Moodle settings are represented by objects that inherit from the admin_setting
875 /// class. These objects encapsulate how to read a setting, how to write a new value
876 /// to a setting, and how to appropriately display the HTML to modify the setting.
878 /// ADMIN_SETTINGPAGE OBJECTS
880 /// The admin_setting objects are then grouped into admin_settingpages. The latter
881 /// appear in the Moodle admin tree block. All interaction with admin_settingpage
882 /// objects is handled by the admin/settings.php file.
884 /// ADMIN_EXTERNALPAGE OBJECTS
886 /// There are some settings in Moodle that are too complex to (efficiently) handle
887 /// with admin_settingpages. (Consider, for example, user management and displaying
888 /// lists of users.) In this case, we use the admin_externalpage object. This object
889 /// places a link to an external PHP file in the admin tree block.
891 /// If you're using an admin_externalpage object for some settings, you can take
892 /// advantage of the admin_externalpage_* functions. For example, suppose you wanted
893 /// to add a foo.php file into admin. First off, you add the following line to
894 /// admin/settings/first.php (at the end of the file) or to some other file in
897 /// $ADMIN->add('userinterface', new admin_externalpage('foo', get_string('foo'),
898 /// $CFG->wwwdir . '/' . '$CFG->admin . '/foo.php', 'some_role_permission'));
900 /// Next, in foo.php, your file structure would resemble the following:
902 /// require_once('.../config.php');
903 /// require_once($CFG->libdir.'/adminlib.php');
904 /// admin_externalpage_setup('foo');
905 /// // functionality like processing form submissions goes here
906 /// admin_externalpage_print_header();
907 /// // your HTML goes here
908 /// admin_externalpage_print_footer();
910 /// The admin_externalpage_setup() function call ensures the user is logged in,
911 /// and makes sure that they have the proper role permission to access the page.
913 /// The admin_externalpage_print_header() function prints the header (it figures
914 /// out what category and subcategories the page is classified under) and ensures
915 /// that you're using the admin pagelib (which provides the admin tree block and
916 /// the admin bookmarks block).
918 /// The admin_externalpage_print_footer() function properly closes the tables
919 /// opened up by the admin_externalpage_print_header() function and prints the
920 /// standard Moodle footer.
922 /// ADMIN_CATEGORY OBJECTS
924 /// Above and beyond all this, we have admin_category objects. These objects
925 /// appear as folders in the admin tree block. They contain admin_settingpage's,
926 /// admin_externalpage's, and other admin_category's.
930 /// admin_settingpage's, admin_externalpage's, and admin_category's all inherit
931 /// from part_of_admin_tree (a pseudointerface). This interface insists that
932 /// a class has a check_access method for access permissions, a locate method
933 /// used to find a specific node in the admin tree and find parent path.
935 /// admin_category's inherit from parentable_part_of_admin_tree. This pseudo-
936 /// interface ensures that the class implements a recursive add function which
937 /// accepts a part_of_admin_tree object and searches for the proper place to
938 /// put it. parentable_part_of_admin_tree implies part_of_admin_tree.
940 /// Please note that the $this->name field of any part_of_admin_tree must be
941 /// UNIQUE throughout the ENTIRE admin tree.
943 /// The $this->name field of an admin_setting object (which is *not* part_of_
944 /// admin_tree) must be unique on the respective admin_settingpage where it is
948 /// CLASS DEFINITIONS /////////////////////////////////////////////////////////
951 * Pseudointerface for anything appearing in the admin tree
953 * The pseudointerface that is implemented by anything that appears in the admin tree
954 * block. It forces inheriting classes to define a method for checking user permissions
955 * and methods for finding something in the admin tree.
957 * @author Vincenzo K. Marcovecchio
960 class part_of_admin_tree
{
963 * Finds a named part_of_admin_tree.
965 * Used to find a part_of_admin_tree. If a class only inherits part_of_admin_tree
966 * and not parentable_part_of_admin_tree, then this function should only check if
967 * $this->name matches $name. If it does, it should return a reference to $this,
968 * otherwise, it should return a reference to NULL.
970 * If a class inherits parentable_part_of_admin_tree, this method should be called
971 * recursively on all child objects (assuming, of course, the parent object's name
972 * doesn't match the search criterion).
974 * @param string $name The internal name of the part_of_admin_tree we're searching for.
975 * @return mixed An object reference or a NULL reference.
977 function &locate($name) {
978 trigger_error('Admin class does not implement method <strong>locate()</strong>', E_USER_WARNING
);
983 * Removes named part_of_admin_tree.
985 * @param string $name The internal name of the part_of_admin_tree we want to remove.
986 * @return bool success.
988 function prune($name) {
989 trigger_error('Admin class does not implement method <strong>prune()</strong>', E_USER_WARNING
);
996 * @return mixed array-object structure of found settings and pages
998 function search($query) {
999 trigger_error('Admin class does not implement method <strong>search()</strong>', E_USER_WARNING
);
1004 * Verifies current user's access to this part_of_admin_tree.
1006 * Used to check if the current user has access to this part of the admin tree or
1007 * not. If a class only inherits part_of_admin_tree and not parentable_part_of_admin_tree,
1008 * then this method is usually just a call to has_capability() in the site context.
1010 * If a class inherits parentable_part_of_admin_tree, this method should return the
1011 * logical OR of the return of check_access() on all child objects.
1013 * @return bool True if the user has access, false if she doesn't.
1015 function check_access() {
1016 trigger_error('Admin class does not implement method <strong>check_access()</strong>', E_USER_WARNING
);
1021 * Mostly usefull for removing of some parts of the tree in admin tree block.
1023 * @return True is hidden from normal list view
1025 function is_hidden() {
1026 trigger_error('Admin class does not implement method <strong>is_hidden()</strong>', E_USER_WARNING
);
1032 * Pseudointerface implemented by any part_of_admin_tree that has children.
1034 * The pseudointerface implemented by any part_of_admin_tree that can be a parent
1035 * to other part_of_admin_tree's. (For now, this only includes admin_category.) Apart
1036 * from ensuring part_of_admin_tree compliancy, it also ensures inheriting methods
1037 * include an add method for adding other part_of_admin_tree objects as children.
1039 * @author Vincenzo K. Marcovecchio
1042 class parentable_part_of_admin_tree
extends part_of_admin_tree
{
1045 * Adds a part_of_admin_tree object to the admin tree.
1047 * Used to add a part_of_admin_tree object to this object or a child of this
1048 * object. $something should only be added if $destinationname matches
1049 * $this->name. If it doesn't, add should be called on child objects that are
1050 * also parentable_part_of_admin_tree's.
1052 * @param string $destinationname The internal name of the new parent for $something.
1053 * @param part_of_admin_tree &$something The object to be added.
1054 * @return bool True on success, false on failure.
1056 function add($destinationname, $something) {
1057 trigger_error('Admin class does not implement method <strong>add()</strong>', E_USER_WARNING
);
1064 * The object used to represent folders (a.k.a. categories) in the admin tree block.
1066 * Each admin_category object contains a number of part_of_admin_tree objects.
1068 * @author Vincenzo K. Marcovecchio
1071 class admin_category
extends parentable_part_of_admin_tree
{
1074 * @var mixed An array of part_of_admin_tree objects that are this object's children
1079 * @var string An internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
1084 * @var string The displayed name for this category. Usually obtained through get_string()
1089 * @var bool Should this category be hidden in admin tree block?
1100 * Constructor for an empty admin category
1102 * @param string $name The internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
1103 * @param string $visiblename The displayed named for this category. Usually obtained through get_string()
1104 * @param bool $hidden hide category in admin tree block
1106 function admin_category($name, $visiblename, $hidden=false) {
1107 $this->children
= array();
1108 $this->name
= $name;
1109 $this->visiblename
= $visiblename;
1110 $this->hidden
= $hidden;
1114 * Returns a reference to the part_of_admin_tree object with internal name $name.
1116 * @param string $name The internal name of the object we want.
1117 * @param bool $findpath initialize path and visiblepath arrays
1118 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
1120 function &locate($name, $findpath=false) {
1121 if ($this->name
== $name) {
1123 $this->visiblepath
[] = $this->visiblename
;
1124 $this->path
[] = $this->name
;
1130 foreach($this->children
as $childid=>$unused) {
1131 if ($return =& $this->children
[$childid]->locate($name, $findpath)) {
1136 if (!is_null($return) and $findpath) {
1137 $return->visiblepath
[] = $this->visiblename
;
1138 $return->path
[] = $this->name
;
1145 * Search using query
1146 * @param strin query
1147 * @return mixed array-object structure of found settings and pages
1149 function search($query) {
1151 foreach ($this->children
as $child) {
1152 $subsearch = $child->search($query);
1153 if (!is_array($subsearch)) {
1154 debugging('Incorrect search result from '.$child->name
);
1157 $result = array_merge($result, $subsearch);
1163 * Removes part_of_admin_tree object with internal name $name.
1165 * @param string $name The internal name of the object we want to remove.
1166 * @return bool success
1168 function prune($name) {
1170 if ($this->name
== $name) {
1171 return false; //can not remove itself
1174 foreach($this->children
as $precedence => $child) {
1175 if ($child->name
== $name) {
1177 unset($this->children
[$precedence]);
1180 if ($this->children
[$precedence]->prune($name)) {
1188 * Adds a part_of_admin_tree to a child or grandchild (or great-grandchild, and so forth) of this object.
1190 * @param string $destinationame The internal name of the immediate parent that we want for $something.
1191 * @param mixed $something A part_of_admin_tree or setting instanceto be added.
1192 * @return bool True if successfully added, false if $something can not be added.
1194 function add($parentname, $something) {
1195 $parent =& $this->locate($parentname);
1196 if (is_null($parent)) {
1197 debugging('parent does not exist!');
1201 if (is_a($something, 'part_of_admin_tree')) {
1202 if (!is_a($parent, 'parentable_part_of_admin_tree')) {
1203 debugging('error - parts of tree can be inserted only into parentable parts');
1206 $parent->children
[] = $something;
1210 debugging('error - can not add this element');
1217 * Checks if the user has access to anything in this category.
1219 * @return bool True if the user has access to atleast one child in this category, false otherwise.
1221 function check_access() {
1222 foreach ($this->children
as $child) {
1223 if ($child->check_access()) {
1231 * Is this category hidden in admin tree block?
1233 * @return bool True if hidden
1235 function is_hidden() {
1236 return $this->hidden
;
1240 class admin_root
extends admin_category
{
1252 * full tree flag - true means all settings required, false onlypages required
1257 function admin_root() {
1258 parent
::admin_category('root', get_string('administration'), false);
1259 $this->errors
= array();
1261 $this->fulltree
= true;
1266 * Links external PHP pages into the admin tree.
1268 * See detailed usage example at the top of this document (adminlib.php)
1270 * @author Vincenzo K. Marcovecchio
1273 class admin_externalpage
extends part_of_admin_tree
{
1276 * @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects
1281 * @var string The displayed name for this external page. Usually obtained through get_string().
1286 * @var string The external URL that we should link to when someone requests this external page.
1291 * @var string The role capability/permission a user must have to access this external page.
1293 var $req_capability;
1296 * @var object The context in which capability/permission should be checked, default is site context.
1301 * @var bool hidden in admin tree block.
1312 * Constructor for adding an external page into the admin tree.
1314 * @param string $name The internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects.
1315 * @param string $visiblename The displayed name for this external page. Usually obtained through get_string().
1316 * @param string $url The external URL that we should link to when someone requests this external page.
1317 * @param mixed $req_capability The role capability/permission a user must have to access this external page. Defaults to 'moodle/site:config'.
1319 function admin_externalpage($name, $visiblename, $url, $req_capability='moodle/site:config', $hidden=false, $context=NULL) {
1320 $this->name
= $name;
1321 $this->visiblename
= $visiblename;
1323 if (is_array($req_capability)) {
1324 $this->req_capability
= $req_capability;
1326 $this->req_capability
= array($req_capability);
1328 $this->hidden
= $hidden;
1329 $this->context
= $context;
1333 * Returns a reference to the part_of_admin_tree object with internal name $name.
1335 * @param string $name The internal name of the object we want.
1336 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
1338 function &locate($name, $findpath=false) {
1339 if ($this->name
== $name) {
1341 $this->visiblepath
= array($this->visiblename
);
1342 $this->path
= array($this->name
);
1351 function prune($name) {
1356 * Search using query
1357 * @param strin query
1358 * @return mixed array-object structure of found settings and pages
1360 function search($query) {
1361 $textlib = textlib_get_instance();
1364 if (strpos(strtolower($this->name
), $query) !== false) {
1366 } else if (strpos($textlib->strtolower($this->visiblename
), $query) !== false) {
1370 $result = new object();
1371 $result->page
= $this;
1372 $result->settings
= array();
1373 return array($this->name
=> $result);
1380 * Determines if the current user has access to this external page based on $this->req_capability.
1381 * @return bool True if user has access, false otherwise.
1383 function check_access() {
1385 return true; // no access check before site is fully set up
1387 $context = empty($this->context
) ?
get_context_instance(CONTEXT_SYSTEM
) : $this->context
;
1388 foreach($this->req_capability
as $cap) {
1389 if (has_capability($cap, $context)) {
1397 * Is this external page hidden in admin tree block?
1399 * @return bool True if hidden
1401 function is_hidden() {
1402 return $this->hidden
;
1408 * Used to group a number of admin_setting objects into a page and add them to the admin tree.
1410 * @author Vincenzo K. Marcovecchio
1413 class admin_settingpage
extends part_of_admin_tree
{
1416 * @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects
1421 * @var string The displayed name for this external page. Usually obtained through get_string().
1425 * @var mixed An array of admin_setting objects that are part of this setting page.
1430 * @var string The role capability/permission a user must have to access this external page.
1432 var $req_capability;
1435 * @var object The context in which capability/permission should be checked, default is site context.
1440 * @var bool hidden in admin tree block.
1450 // see admin_externalpage
1451 function admin_settingpage($name, $visiblename, $req_capability='moodle/site:config', $hidden=false, $context=NULL) {
1452 $this->settings
= new object();
1453 $this->name
= $name;
1454 $this->visiblename
= $visiblename;
1455 if (is_array($req_capability)) {
1456 $this->req_capability
= $req_capability;
1458 $this->req_capability
= array($req_capability);
1460 $this->hidden
= $hidden;
1461 $this->context
= $context;
1464 // see admin_category
1465 function &locate($name, $findpath=false) {
1466 if ($this->name
== $name) {
1468 $this->visiblepath
= array($this->visiblename
);
1469 $this->path
= array($this->name
);
1478 function search($query) {
1481 foreach ($this->settings
as $setting) {
1482 if ($setting->is_related($query)) {
1483 $found[] = $setting;
1488 $result = new object();
1489 $result->page
= $this;
1490 $result->settings
= $found;
1491 return array($this->name
=> $result);
1494 $textlib = textlib_get_instance();
1497 if (strpos(strtolower($this->name
), $query) !== false) {
1499 } else if (strpos($textlib->strtolower($this->visiblename
), $query) !== false) {
1503 $result = new object();
1504 $result->page
= $this;
1505 $result->settings
= array();
1506 return array($this->name
=> $result);
1512 function prune($name) {
1517 * 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
1518 * n.b. each admin_setting in an admin_settingpage must have a unique internal name
1519 * @param object $setting is the admin_setting object you want to add
1520 * @return true if successful, false if not
1522 function add($setting) {
1523 if (!is_a($setting, 'admin_setting')) {
1524 debugging('error - not a setting instance');
1528 $this->settings
->{$setting->name
} = $setting;
1532 // see admin_externalpage
1533 function check_access() {
1535 return true; // no access check before site is fully set up
1537 $context = empty($this->context
) ?
get_context_instance(CONTEXT_SYSTEM
) : $this->context
;
1538 foreach($this->req_capability
as $cap) {
1539 if (has_capability($cap, $context)) {
1547 * outputs this page as html in a table (suitable for inclusion in an admin pagetype)
1548 * returns a string of the html
1550 function output_html() {
1551 $adminroot =& admin_get_root();
1552 $return = '<fieldset>'."\n".'<div class="clearer"><!-- --></div>'."\n";
1553 foreach($this->settings
as $setting) {
1554 $fullname = $setting->get_full_name();
1555 if (array_key_exists($fullname, $adminroot->errors
)) {
1556 $data = $adminroot->errors
[$fullname]->data
;
1558 $data = $setting->get_setting();
1559 if (is_null($data)) {
1560 $data = $setting->get_defaultsetting();
1563 $return .= $setting->output_html($data);
1565 $return .= '</fieldset>';
1570 * Is this settigns page hidden in admin tree block?
1572 * @return bool True if hidden
1574 function is_hidden() {
1575 return $this->hidden
;
1582 * Admin settings class. Only exists on setting pages.
1583 * Read & write happens at this level; no authentication.
1585 class admin_setting
{
1590 var $defaultsetting;
1591 var $updatedcallback;
1592 var $plugin; // null means main config table
1596 * @param $name string unique ascii name
1597 * @param $visiblename string localised name
1598 * @param strin $description localised long description
1599 * @param mixed $defaultsetting string or array depending on implementation
1601 function admin_setting($name, $visiblename, $description, $defaultsetting) {
1602 $this->name
= $name;
1603 $this->visiblename
= $visiblename;
1604 $this->description
= $description;
1605 $this->defaultsetting
= $defaultsetting;
1608 function get_full_name() {
1609 return 's_'.$this->plugin
.'_'.$this->name
;
1613 return 'id_s_'.$this->plugin
.'_'.$this->name
;
1616 function config_read($name) {
1618 if ($this->plugin
=== 'backup') {
1619 require_once($CFG->dirroot
.'/backup/lib.php');
1620 $backupconfig = backup_get_config();
1621 if (isset($backupconfig->$name)) {
1622 return $backupconfig->$name;
1627 } else if (!empty($this->plugin
)) {
1628 $value = get_config($this->plugin
, $name);
1629 return $value === false ?
NULL : $value;
1632 if (isset($CFG->$name)) {
1640 function config_write($name, $value) {
1642 if ($this->plugin
=== 'backup') {
1643 require_once($CFG->dirroot
.'/backup/lib.php');
1644 return (boolean
)backup_set_config($name, $value);
1646 return (boolean
)set_config($name, $value, $this->plugin
);
1651 * Returns current value of this setting
1652 * @return mixed array or string depending on instance, NULL means not set yet
1654 function get_setting() {
1655 // has to be overridden
1660 * Returns default setting if exists
1661 * @return mixed array or string depending on instance; NULL means no default, user must supply
1663 function get_defaultsetting() {
1664 return $this->defaultsetting
;
1669 * @param mixed string or array, must not be NULL
1670 * @return '' if ok, string error message otherwise
1672 function write_setting($data) {
1673 // should be overridden
1678 * Return part of form with setting
1679 * @param mixed data array or string depending on setting
1682 function output_html($data, $query='') {
1683 // should be overridden
1688 * function called if setting updated - cleanup, cache reset, etc.
1690 function set_updatedcallback($functionname) {
1691 $this->updatedcallback
= $functionname;
1695 * Is setting related to query text - used when searching
1696 * @param string $query
1699 function is_related($query) {
1700 if (strpos(strtolower($this->name
), $query) !== false) {
1703 $textlib = textlib_get_instance();
1704 if (strpos($textlib->strtolower($this->visiblename
), $query) !== false) {
1707 if (strpos($textlib->strtolower($this->description
), $query) !== false) {
1710 $current = $this->get_setting();
1711 if (!is_null($current)) {
1712 if (is_string($current)) {
1713 if (strpos($textlib->strtolower($current), $query) !== false) {
1718 $default = $this->get_defaultsetting();
1719 if (!is_null($default)) {
1720 if (is_string($default)) {
1721 if (strpos($textlib->strtolower($default), $query) !== false) {
1731 * No setting - just heading and text.
1733 class admin_setting_heading
extends admin_setting
{
1735 * not a setting, just text
1736 * @param string $name of setting
1737 * @param string $heading heading
1738 * @param string $information text in box
1740 function admin_setting_heading($name, $heading, $information) {
1741 parent
::admin_setting($name, $heading, $information, '');
1744 function get_setting() {
1748 function get_defaultsetting() {
1752 function write_setting($data) {
1753 // do not write any setting
1757 function output_html($data, $query='') {
1759 if ($this->visiblename
!= '') {
1760 $return .= print_heading('<a name="'.$this->name
.'">'.highlightfast($query, $this->visiblename
).'</a>', '', 3, 'main', true);
1762 if ($this->description
!= '') {
1763 $return .= print_box(highlight($query, $this->description
), 'generalbox formsettingheading', '', true);
1770 * The most flexibly setting, user is typing text
1772 class admin_setting_configtext
extends admin_setting
{
1778 * config text contructor
1779 * @param string $name of setting
1780 * @param string $visiblename localised
1781 * @param string $description long localised info
1782 * @param string $defaultsetting
1783 * @param mixed $paramtype int means PARAM_XXX type, string is a allowed format in regex
1784 * @param int $size default field size
1786 function admin_setting_configtext($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW
, $size=null) {
1787 $this->paramtype
= $paramtype;
1788 if (!is_null($size)) {
1789 $this->size
= $size;
1791 $this->size
= ($paramtype == PARAM_INT
) ?
5 : 30;
1793 parent
::admin_setting($name, $visiblename, $description, $defaultsetting);
1796 function get_setting() {
1797 return $this->config_read($this->name
);
1800 function write_setting($data) {
1801 if ($this->paramtype
=== PARAM_INT
and $data === '') {
1802 // do not complain if '' used instead of 0
1805 // $data is a string
1806 $validated = $this->validate($data);
1807 if ($validated !== true) {
1810 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
1814 * Validate data before storage
1815 * @param string data
1816 * @return mixed true if ok string if error found
1818 function validate($data) {
1819 if (is_string($this->paramtype
)) {
1820 if (preg_match($this->paramtype
, $data)) {
1823 return get_string('validateerror', 'admin');
1826 } else if ($this->paramtype
=== PARAM_RAW
) {
1830 $cleaned = stripslashes(clean_param(addslashes($data), $this->paramtype
));
1831 if ("$data" == "$cleaned") { // implicit conversion to string is needed to do exact comparison
1834 return get_string('validateerror', 'admin');
1839 function output_html($data, $query='') {
1840 $default = $this->get_defaultsetting();
1842 return format_admin_setting($this, $this->visiblename
,
1843 '<div class="form-text defaultsnext"><input type="text" size="'.$this->size
.'" id="'.$this->get_id().'" name="'.$this->get_full_name().'" value="'.s($data).'" /></div>',
1844 $this->description
, true, '', $default, $query);
1849 * General text area without html editor.
1851 class admin_setting_configtextarea
extends admin_setting_configtext
{
1855 function admin_setting_configtextarea($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW
, $cols='60', $rows='8') {
1856 $this->rows
= $rows;
1857 $this->cols
= $cols;
1858 parent
::admin_setting_configtext($name, $visiblename, $description, $defaultsetting, $paramtype);
1861 function output_html($data, $query='') {
1862 $default = $this->get_defaultsetting();
1864 $defaultinfo = $default;
1865 if (!is_null($default) and $default !== '') {
1866 $defaultinfo = "\n".$default;
1869 return format_admin_setting($this, $this->visiblename
,
1870 '<div class="form-textarea" ><textarea rows="'.$this->rows
.'" cols="'.$this->cols
.'" id="'.$this->get_id().'" name="'.$this->get_full_name().'">'.s($data).'</textarea></div>',
1871 $this->description
, true, '', $defaultinfo, $query);
1876 * Password field, allows unmasking of password
1878 class admin_setting_configpasswordunmask
extends admin_setting_configtext
{
1881 * @param string $name of setting
1882 * @param string $visiblename localised
1883 * @param string $description long localised info
1884 * @param string $defaultsetting default password
1886 function admin_setting_configpasswordunmask($name, $visiblename, $description, $defaultsetting) {
1887 parent
::admin_setting_configtext($name, $visiblename, $description, $defaultsetting, PARAM_RAW
, 30);
1890 function output_html($data, $query='') {
1891 $id = $this->get_id();
1892 $unmask = get_string('unmaskpassword', 'form');
1893 $unmaskjs = '<script type="text/javascript">
1895 document.write(\'<span class="unmask"><input id="'.$id.'unmask" value="1" type="checkbox" onclick="unmaskPassword(\\\''.$id.'\\\')"/><label for="'.$id.'unmask">'.addslashes_js($unmask).'<\/label><\/span>\');
1896 document.getElementById("'.$this->get_id().'").setAttribute("autocomplete", "off");
1899 return format_admin_setting($this, $this->visiblename
,
1900 '<div class="form-password"><input type="password" size="'.$this->size
.'" id="'.$this->get_id().'" name="'.$this->get_full_name().'" value="'.s($data).'" />'.$unmaskjs.'</div>',
1901 $this->description
, true, '', NULL, $query);
1908 class admin_setting_configfile
extends admin_setting_configtext
{
1911 * @param string $name of setting
1912 * @param string $visiblename localised
1913 * @param string $description long localised info
1914 * @param string $defaultdirectory default directory location
1916 function admin_setting_configfile($name, $visiblename, $description, $defaultdirectory) {
1917 parent
::admin_setting_configtext($name, $visiblename, $description, $defaultdirectory, PARAM_RAW
, 50);
1920 function output_html($data, $query='') {
1921 $default = $this->get_defaultsetting();
1924 if (file_exists($data)) {
1925 $executable = '<span class="pathok">✔</span>';
1927 $executable = '<span class="patherror">✘</span>';
1933 return format_admin_setting($this, $this->visiblename
,
1934 '<div class="form-file defaultsnext"><input type="text" size="'.$this->size
.'" id="'.$this->get_id().'" name="'.$this->get_full_name().'" value="'.s($data).'" />'.$executable.'</div>',
1935 $this->description
, true, '', $default, $query);
1940 * Path to executable file
1942 class admin_setting_configexecutable
extends admin_setting_configfile
{
1944 function output_html($data, $query='') {
1945 $default = $this->get_defaultsetting();
1948 if (file_exists($data) and is_executable($data)) {
1949 $executable = '<span class="pathok">✔</span>';
1951 $executable = '<span class="patherror">✘</span>';
1957 return format_admin_setting($this, $this->visiblename
,
1958 '<div class="form-file defaultsnext"><input type="text" size="'.$this->size
.'" id="'.$this->get_id().'" name="'.$this->get_full_name().'" value="'.s($data).'" />'.$executable.'</div>',
1959 $this->description
, true, '', $default, $query);
1966 class admin_setting_configdirectory
extends admin_setting_configfile
{
1967 function output_html($data, $query='') {
1968 $default = $this->get_defaultsetting();
1971 if (file_exists($data) and is_dir($data)) {
1972 $executable = '<span class="pathok">✔</span>';
1974 $executable = '<span class="patherror">✘</span>';
1980 return format_admin_setting($this, $this->visiblename
,
1981 '<div class="form-file defaultsnext"><input type="text" size="'.$this->size
.'" id="'.$this->get_id().'" name="'.$this->get_full_name().'" value="'.s($data).'" />'.$executable.'</div>',
1982 $this->description
, true, '', $default, $query);
1989 class admin_setting_configcheckbox
extends admin_setting
{
1995 * @param string $name of setting
1996 * @param string $visiblename localised
1997 * @param string $description long localised info
1998 * @param string $defaultsetting
1999 * @param string $yes value used when checked
2000 * @param string $no value used when not checked
2002 function admin_setting_configcheckbox($name, $visiblename, $description, $defaultsetting, $yes='1', $no='0') {
2003 parent
::admin_setting($name, $visiblename, $description, $defaultsetting);
2004 $this->yes
= (string)$yes;
2005 $this->no
= (string)$no;
2008 function get_setting() {
2009 return $this->config_read($this->name
);
2012 function write_setting($data) {
2013 if ((string)$data === $this->yes
) { // convert to strings before comparison
2018 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
2021 function output_html($data, $query='') {
2022 $default = $this->get_defaultsetting();
2024 if (!is_null($default)) {
2025 if ((string)$default === $this->yes
) {
2026 $defaultinfo = get_string('checkboxyes', 'admin');
2028 $defaultinfo = get_string('checkboxno', 'admin');
2031 $defaultinfo = NULL;
2034 if ((string)$data === $this->yes
) { // convert to strings before comparison
2035 $checked = 'checked="checked"';
2040 return format_admin_setting($this, $this->visiblename
,
2041 '<div class="form-checkbox defaultsnext" ><input type="hidden" name="'.$this->get_full_name().'" value="'.s($this->no
).'" /> '
2042 .'<input type="checkbox" id="'.$this->get_id().'" name="'.$this->get_full_name().'" value="'.s($this->yes
).'" '.$checked.' /></div>',
2043 $this->description
, true, '', $defaultinfo, $query);
2048 * Multiple checkboxes, each represents different value, stored in csv format
2050 class admin_setting_configmulticheckbox
extends admin_setting
{
2055 * @param string $name of setting
2056 * @param string $visiblename localised
2057 * @param string $description long localised info
2058 * @param array $defaultsetting array of selected
2059 * @param array $choices array of $value=>$label for each checkbox
2061 function admin_setting_configmulticheckbox($name, $visiblename, $description, $defaultsetting, $choices) {
2062 $this->choices
= $choices;
2063 parent
::admin_setting($name, $visiblename, $description, $defaultsetting);
2067 * This function may be used in ancestors for lazy loading of choices
2068 * @return true if loaded, false if error
2070 function load_choices() {
2072 if (is_array($this->choices)) {
2075 .... load choices here
2081 * Is setting related to query text - used when searching
2082 * @param string $query
2085 function is_related($query) {
2086 if (!$this->load_choices() or empty($this->choices
)) {
2089 if (parent
::is_related($query)) {
2093 $textlib = textlib_get_instance();
2094 foreach ($this->choices
as $desc) {
2095 if (strpos($textlib->strtolower($desc), $query) !== false) {
2102 function get_setting() {
2103 $result = $this->config_read($this->name
);
2104 if (is_null($result)) {
2107 if ($result === '') {
2110 return explode(',', $result);
2113 function write_setting($data) {
2114 if (!is_array($data)) {
2115 return ''; // ignore it
2117 if (!$this->load_choices() or empty($this->choices
)) {
2120 unset($data['xxxxx']);
2122 foreach ($data as $key => $value) {
2123 if ($value and array_key_exists($key, $this->choices
)) {
2127 return $this->config_write($this->name
, implode(',', $result)) ?
'' : get_string('errorsetting', 'admin');
2130 function output_html($data, $query='') {
2131 if (!$this->load_choices() or empty($this->choices
)) {
2134 $default = $this->get_defaultsetting();
2135 if (is_null($default)) {
2138 if (is_null($data)) {
2139 foreach ($default as $key=>$value) {
2141 $current[] = $value;
2147 $defaults = array();
2148 foreach($this->choices
as $key=>$description) {
2149 if (in_array($key, $data)) {
2150 $checked = 'checked="checked"';
2154 if (!empty($default[$key])) {
2155 $defaults[] = $description;
2158 $options[] = '<input type="checkbox" id="'.$this->get_id().'_'.$key.'" name="'.$this->get_full_name().'['.$key.']" value="1" '.$checked.' />'
2159 .'<label for="'.$this->get_id().'_'.$key.'">'.highlightfast($query, $description).'</label>';
2162 if (is_null($default)) {
2163 $defaultinfo = NULL;
2164 } else if (!empty($defaults)) {
2165 $defaultinfo = implode(', ', $defaults);
2167 $defaultinfo = get_string('none');
2170 $return = '<div class="form-multicheckbox">';
2171 $return .= '<input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
2174 foreach ($options as $option) {
2175 $return .= '<li>'.$option.'</li>';
2179 $return .= '</div>';
2181 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', $defaultinfo, $query);
2187 * Multiple checkboxes 2, value stored as string 00101011
2189 class admin_setting_configmulticheckbox2
extends admin_setting_configmulticheckbox
{
2190 function get_setting() {
2191 $result = $this->config_read($this->name
);
2192 if (is_null($result)) {
2195 if (!$this->load_choices()) {
2198 $result = str_pad($result, count($this->choices
), '0');
2199 $result = preg_split('//', $result, -1, PREG_SPLIT_NO_EMPTY
);
2201 foreach ($this->choices
as $key=>$unused) {
2202 $value = array_shift($result);
2210 function write_setting($data) {
2211 if (!is_array($data)) {
2212 return ''; // ignore it
2214 if (!$this->load_choices() or empty($this->choices
)) {
2218 foreach ($this->choices
as $key=>$unused) {
2219 if (!empty($data[$key])) {
2225 return $this->config_write($this->name
, $result) ?
'' : get_string('errorsetting', 'admin');
2230 * Select one value from list
2232 class admin_setting_configselect
extends admin_setting
{
2237 * @param string $name of setting
2238 * @param string $visiblename localised
2239 * @param string $description long localised info
2240 * @param string $defaultsetting
2241 * @param array $choices array of $value=>$label for each selection
2243 function admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices) {
2244 $this->choices
= $choices;
2245 parent
::admin_setting($name, $visiblename, $description, $defaultsetting);
2249 * This function may be used in ancestors for lazy loading of choices
2250 * @return true if loaded, false if error
2252 function load_choices() {
2254 if (is_array($this->choices)) {
2257 .... load choices here
2262 function is_related($query) {
2263 if (parent
::is_related($query)) {
2266 if (!$this->load_choices()) {
2269 $textlib = textlib_get_instance();
2270 foreach ($this->choices
as $key=>$value) {
2271 if (strpos($textlib->strtolower($key), $query) !== false) {
2274 if (strpos($textlib->strtolower($value), $query) !== false) {
2281 function get_setting() {
2282 return $this->config_read($this->name
);
2285 function write_setting($data) {
2286 if (!$this->load_choices() or empty($this->choices
)) {
2289 if (!array_key_exists($data, $this->choices
)) {
2290 return ''; // ignore it
2293 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
2296 function output_html($data, $query='') {
2297 if (!$this->load_choices() or empty($this->choices
)) {
2300 $default = $this->get_defaultsetting();
2302 if (!is_null($default) and array_key_exists($default, $this->choices
)) {
2303 $defaultinfo = $this->choices
[$default];
2305 $defaultinfo = NULL;
2308 $current = $this->get_setting();
2310 if (is_null($current)) {
2312 } else if (empty($current) and (array_key_exists('', $this->choices
) or array_key_exists(0, $this->choices
))) {
2314 } else if (!array_key_exists($current, $this->choices
)) {
2315 $warning = get_string('warningcurrentsetting', 'admin', s($current));
2316 if (!is_null($default) and $data==$current) {
2317 $data = $default; // use default instead of first value when showing the form
2321 $return = '<div class="form-select defaultsnext"><select id="'.$this->get_id().'" name="'.$this->get_full_name().'">';
2322 foreach ($this->choices
as $key => $value) {
2323 // the string cast is needed because key may be integer - 0 is equal to most strings!
2324 $return .= '<option value="'.$key.'"'.((string)$key==$data ?
' selected="selected"' : '').'>'.$value.'</option>';
2326 $return .= '</select></div>';
2328 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, true, $warning, $defaultinfo, $query);
2334 * Select multiple items from list
2336 class admin_setting_configmultiselect
extends admin_setting_configselect
{
2339 * @param string $name of setting
2340 * @param string $visiblename localised
2341 * @param string $description long localised info
2342 * @param array $defaultsetting array of selected items
2343 * @param array $choices array of $value=>$label for each list item
2345 function admin_setting_configmultiselect($name, $visiblename, $description, $defaultsetting, $choices) {
2346 parent
::admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices);
2349 function get_setting() {
2350 $result = $this->config_read($this->name
);
2351 if (is_null($result)) {
2354 if ($result === '') {
2357 return explode(',', $result);
2360 function write_setting($data) {
2361 if (!is_array($data)) {
2362 return ''; //ignore it
2364 if (!$this->load_choices() or empty($this->choices
)) {
2368 unset($data['xxxxx']);
2371 foreach ($data as $value) {
2372 if (!array_key_exists($value, $this->choices
)) {
2373 continue; // ignore it
2378 return ($this->config_write($this->name
, implode(',', $save)) ?
'' : get_string('errorsetting', 'admin'));
2382 * Is setting related to query text - used when searching
2383 * @param string $query
2386 function is_related($query) {
2387 if (!$this->load_choices() or empty($this->choices
)) {
2390 if (parent
::is_related($query)) {
2394 $textlib = textlib_get_instance();
2395 foreach ($this->choices
as $desc) {
2396 if (strpos($textlib->strtolower($desc), $query) !== false) {
2403 function output_html($data, $query='') {
2404 if (!$this->load_choices() or empty($this->choices
)) {
2407 $choices = $this->choices
;
2408 $default = $this->get_defaultsetting();
2409 if (is_null($default)) {
2412 if (is_null($data)) {
2416 $defaults = array();
2417 $return = '<div class="form-select"><input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
2418 $return .= '<select id="'.$this->get_id().'" name="'.$this->get_full_name().'[]" size="10" multiple="multiple">';
2419 foreach ($this->choices
as $key => $description) {
2420 if (in_array($key, $data)) {
2421 $selected = 'selected="selected"';
2425 if (in_array($key, $default)) {
2426 $defaults[] = $description;
2429 $return .= '<option value="'.s($key).'" '.$selected.'>'.$description.'</option>';
2432 if (is_null($default)) {
2433 $defaultinfo = NULL;
2434 } if (!empty($defaults)) {
2435 $defaultinfo = implode(', ', $defaults);
2437 $defaultinfo = get_string('none');
2440 $return .= '</select></div>';
2441 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, true, '', $defaultinfo, $query);
2447 * this is a liiitle bit messy. we're using two selects, but we're returning
2448 * them as an array named after $name (so we only use $name2 internally for the setting)
2450 class admin_setting_configtime
extends admin_setting
{
2455 * @param string $hoursname setting for hours
2456 * @param string $minutesname setting for hours
2457 * @param string $visiblename localised
2458 * @param string $description long localised info
2459 * @param array $defaultsetting array representing default time 'h'=>hours, 'm'=>minutes
2461 function admin_setting_configtime($hoursname, $minutesname, $visiblename, $description, $defaultsetting) {
2462 $this->name2
= $minutesname;
2463 parent
::admin_setting($hoursname, $visiblename, $description, $defaultsetting);
2466 function get_setting() {
2467 $result1 = $this->config_read($this->name
);
2468 $result2 = $this->config_read($this->name2
);
2469 if (is_null($result1) or is_null($result2)) {
2473 return array('h' => $result1, 'm' => $result2);
2476 function write_setting($data) {
2477 if (!is_array($data)) {
2481 $result = $this->config_write($this->name
, (int)$data['h']) && $this->config_write($this->name2
, (int)$data['m']);
2482 return ($result ?
'' : get_string('errorsetting', 'admin'));
2485 function output_html($data, $query='') {
2486 $default = $this->get_defaultsetting();
2488 if (is_array($default)) {
2489 $defaultinfo = $default['h'].':'.$default['m'];
2491 $defaultinfo = NULL;
2494 $return = '<div class="form-time defaultsnext">'.
2495 '<select id="'.$this->get_id().'h" name="'.$this->get_full_name().'[h]">';
2496 for ($i = 0; $i < 24; $i++
) {
2497 $return .= '<option value="'.$i.'"'.($i == $data['h'] ?
' selected="selected"' : '').'>'.$i.'</option>';
2499 $return .= '</select>:<select id="'.$this->get_id().'m" name="'.$this->get_full_name().'[m]">';
2500 for ($i = 0; $i < 60; $i +
= 5) {
2501 $return .= '<option value="'.$i.'"'.($i == $data['m'] ?
' selected="selected"' : '').'>'.$i.'</option>';
2503 $return .= '</select></div>';
2504 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', $defaultinfo, $query);
2510 * Special checkbox for calendar - resets SESSION vars.
2512 class admin_setting_special_adminseesall
extends admin_setting_configcheckbox
{
2513 function admin_setting_special_adminseesall() {
2514 parent
::admin_setting_configcheckbox('calendar_adminseesall', get_string('adminseesall', 'admin'),
2515 get_string('helpadminseesall', 'admin'), '0');
2518 function write_setting($data) {
2520 unset($SESSION->cal_courses_shown
);
2521 return parent
::write_setting($data);
2526 * Special select for settings that are altered in setup.php and can not be altered on the fly
2528 class admin_setting_special_selectsetup
extends admin_setting_configselect
{
2529 function get_setting() {
2530 // read directly from db!
2531 return get_config(NULL, $this->name
);
2534 function write_setting($data) {
2536 // do not change active CFG setting!
2537 $current = $CFG->{$this->name
};
2538 $result = parent
::write_setting($data);
2539 $CFG->{$this->name
} = $current;
2545 * Special select for frontpage - stores data in course table
2547 class admin_setting_sitesetselect
extends admin_setting_configselect
{
2548 function get_setting() {
2550 return $site->{$this->name
};
2553 function write_setting($data) {
2554 if (!in_array($data, array_keys($this->choices
))) {
2555 return get_string('errorsetting', 'admin');
2557 $record = new stdClass();
2558 $record->id
= SITEID
;
2559 $temp = $this->name
;
2560 $record->$temp = $data;
2561 $record->timemodified
= time();
2562 return (update_record('course', $record) ?
'' : get_string('errorsetting', 'admin'));
2567 * Special select - lists on the frontpage - hacky
2569 class admin_setting_courselist_frontpage
extends admin_setting
{
2572 function admin_setting_courselist_frontpage($loggedin) {
2574 require_once($CFG->dirroot
.'/course/lib.php');
2575 $name = 'frontpage'.($loggedin ?
'loggedin' : '');
2576 $visiblename = get_string('frontpage'.($loggedin ?
'loggedin' : ''),'admin');
2577 $description = get_string('configfrontpage'.($loggedin ?
'loggedin' : ''),'admin');
2578 $defaults = array(FRONTPAGECOURSELIST
);
2579 parent
::admin_setting($name, $visiblename, $description, $defaults);
2582 function load_choices() {
2583 if (is_array($this->choices
)) {
2586 $this->choices
= array(FRONTPAGENEWS
=> get_string('frontpagenews'),
2587 FRONTPAGECOURSELIST
=> get_string('frontpagecourselist'),
2588 FRONTPAGECATEGORYNAMES
=> get_string('frontpagecategorynames'),
2589 FRONTPAGECATEGORYCOMBO
=> get_string('frontpagecategorycombo'),
2590 'none' => get_string('none'));
2591 if ($this->name
== 'frontpage' and count_records('course') > FRONTPAGECOURSELIMIT
) {
2592 unset($this->choices
[FRONTPAGECOURSELIST
]);
2596 function get_setting() {
2597 $result = $this->config_read($this->name
);
2598 if (is_null($result)) {
2601 if ($result === '') {
2604 return explode(',', $result);
2607 function write_setting($data) {
2608 if (!is_array($data)) {
2611 $this->load_choices();
2613 foreach($data as $datum) {
2614 if ($datum == 'none' or !array_key_exists($datum, $this->choices
)) {
2617 $save[$datum] = $datum; // no duplicates
2619 return ($this->config_write($this->name
, implode(',', $save)) ?
'' : get_string('errorsetting', 'admin'));
2622 function output_html($data, $query='') {
2623 $this->load_choices();
2624 $currentsetting = array();
2625 foreach ($data as $key) {
2626 if ($key != 'none' and array_key_exists($key, $this->choices
)) {
2627 $currentsetting[] = $key; // already selected first
2631 $return = '<div class="form-group">';
2632 for ($i = 0; $i < count($this->choices
) - 1; $i++
) {
2633 if (!array_key_exists($i, $currentsetting)) {
2634 $currentsetting[$i] = 'none'; //none
2636 $return .='<select class="form-select" id="'.$this->get_id().$i.'" name="'.$this->get_full_name().'[]">';
2637 foreach ($this->choices
as $key => $value) {
2638 $return .= '<option value="'.$key.'"'.("$key" == $currentsetting[$i] ?
' selected="selected"' : '').'>'.$value.'</option>';
2640 $return .= '</select>';
2641 if ($i !== count($this->choices
) - 2) {
2642 $return .= '<br />';
2645 $return .= '</div>';
2647 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
2652 * Special checkbox for frontpage - stores data in course table
2654 class admin_setting_sitesetcheckbox
extends admin_setting_configcheckbox
{
2655 function get_setting() {
2657 return $site->{$this->name
};
2660 function write_setting($data) {
2661 $record = new object();
2662 $record->id
= SITEID
;
2663 $record->{$this->name
} = ($data == '1' ?
1 : 0);
2664 $record->timemodified
= time();
2665 return (update_record('course', $record) ?
'' : get_string('errorsetting', 'admin'));
2670 * Special text for frontpage - stores data in course table.
2671 * Empty string means not set here. Manual setting is required.
2673 class admin_setting_sitesettext
extends admin_setting_configtext
{
2674 function get_setting() {
2676 return $site->{$this->name
} != '' ?
$site->{$this->name
} : NULL;
2679 function validate($data) {
2680 $cleaned = stripslashes(clean_param(addslashes($data), PARAM_MULTILANG
));
2681 if ($cleaned === '') {
2682 return get_string('required');
2684 if ("$data" == "$cleaned") { // implicit conversion to string is needed to do exact comparison
2687 return get_string('validateerror', 'admin');
2691 function write_setting($data) {
2692 $data = trim($data);
2693 $validated = $this->validate($data);
2694 if ($validated !== true) {
2698 $record = new object();
2699 $record->id
= SITEID
;
2700 $record->{$this->name
} = addslashes($data);
2701 $record->timemodified
= time();
2702 return (update_record('course', $record) ?
'' : get_string('dbupdatefailed', 'error'));
2707 * Special text editor for site description.
2709 class admin_setting_special_frontpagedesc
extends admin_setting
{
2710 function admin_setting_special_frontpagedesc() {
2711 parent
::admin_setting('summary', get_string('frontpagedescription'), get_string('frontpagedescriptionhelp'), NULL);
2714 function get_setting() {
2716 return $site->{$this->name
};
2719 function write_setting($data) {
2720 $record = new object();
2721 $record->id
= SITEID
;
2722 $record->{$this->name
} = addslashes($data);
2723 $record->timemodified
= time();
2724 return(update_record('course', $record) ?
'' : get_string('errorsetting', 'admin'));
2727 function output_html($data, $query='') {
2730 $CFG->adminusehtmleditor
= can_use_html_editor();
2731 $return = '<div class="form-htmlarea">'.print_textarea($CFG->adminusehtmleditor
, 15, 60, 0, 0, $this->get_full_name(), $data, 0, true).'</div>';
2733 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
2737 class admin_setting_special_editorfontlist
extends admin_setting
{
2741 function admin_setting_special_editorfontlist() {
2743 $name = 'editorfontlist';
2744 $visiblename = get_string('editorfontlist', 'admin');
2745 $description = get_string('configeditorfontlist', 'admin');
2746 $defaults = array('k0' => 'Trebuchet',
2747 'v0' => 'Trebuchet MS,Verdana,Arial,Helvetica,sans-serif',
2749 'v1' => 'arial,helvetica,sans-serif',
2750 'k2' => 'Courier New',
2751 'v2' => 'courier new,courier,monospace',
2753 'v3' => 'georgia,times new roman,times,serif',
2755 'v4' => 'tahoma,arial,helvetica,sans-serif',
2756 'k5' => 'Times New Roman',
2757 'v5' => 'times new roman,times,serif',
2759 'v6' => 'verdana,arial,helvetica,sans-serif',
2762 'k8' => 'Wingdings',
2763 'v8' => 'wingdings');
2764 parent
::admin_setting($name, $visiblename, $description, $defaults);
2767 function get_setting() {
2769 $result = $this->config_read($this->name
);
2770 if (is_null($result)) {
2774 $currentsetting = array();
2775 $items = explode(';', $result);
2776 foreach ($items as $item) {
2777 $item = explode(':', $item);
2778 $currentsetting['k'.$i] = $item[0];
2779 $currentsetting['v'.$i] = $item[1];
2782 return $currentsetting;
2785 function write_setting($data) {
2787 // there miiight be an easier way to do this :)
2788 // if this is changed, make sure the $defaults array above is modified so that this
2789 // function processes it correctly
2794 foreach ($data as $key => $value) {
2795 if (substr($key,0,1) == 'k') {
2796 $keys[substr($key,1)] = $value;
2797 } elseif (substr($key,0,1) == 'v') {
2798 $values[substr($key,1)] = $value;
2803 for ($i = 0; $i < count($keys); $i++
) {
2804 if (($keys[$i] !== '') && ($values[$i] !== '')) {
2805 $result[] = clean_param($keys[$i],PARAM_NOTAGS
).':'.clean_param($values[$i], PARAM_NOTAGS
);
2809 return ($this->config_write($this->name
, implode(';', $result)) ?
'' : get_string('errorsetting', 'admin'));
2812 function output_html($data, $query='') {
2813 $fullname = $this->get_full_name();
2814 $return = '<div class="form-group">';
2815 for ($i = 0; $i < count($data) / 2; $i++
) {
2816 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.$i.']" value="'.$data['k'.$i].'" />';
2817 $return .= ' ';
2818 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.$i.']" value="'.$data['v'.$i].'" /><br />';
2820 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.$i.']" value="" />';
2821 $return .= ' ';
2822 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.$i.']" value="" /><br />';
2823 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.($i +
1).']" value="" />';
2824 $return .= ' ';
2825 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.($i +
1).']" value="" />';
2826 $return .= '</div>';
2828 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
2833 class admin_setting_emoticons
extends admin_setting
{
2837 function admin_setting_emoticons() {
2839 $name = 'emoticons';
2840 $visiblename = get_string('emoticons', 'admin');
2841 $description = get_string('configemoticons', 'admin');
2842 $defaults = array('k0' => ':-)',
2853 'v5' => 'thoughtful',
2855 'v6' => 'tongueout',
2875 'v16' => 'surprise',
2877 'v17' => 'blackeye',
2894 'k26' => '(martin)',
2898 parent
::admin_setting($name, $visiblename, $description, $defaults);
2901 function get_setting() {
2903 $result = $this->config_read($this->name
);
2904 if (is_null($result)) {
2908 $currentsetting = array();
2909 $items = explode('{;}', $result);
2910 foreach ($items as $item) {
2911 $item = explode('{:}', $item);
2912 $currentsetting['k'.$i] = $item[0];
2913 $currentsetting['v'.$i] = $item[1];
2916 return $currentsetting;
2919 function write_setting($data) {
2921 // there miiight be an easier way to do this :)
2922 // if this is changed, make sure the $defaults array above is modified so that this
2923 // function processes it correctly
2928 foreach ($data as $key => $value) {
2929 if (substr($key,0,1) == 'k') {
2930 $keys[substr($key,1)] = $value;
2931 } elseif (substr($key,0,1) == 'v') {
2932 $values[substr($key,1)] = $value;
2937 for ($i = 0; $i < count($keys); $i++
) {
2938 if (($keys[$i] !== '') && ($values[$i] !== '')) {
2939 $result[] = clean_param($keys[$i],PARAM_NOTAGS
).'{:}'.clean_param($values[$i], PARAM_NOTAGS
);
2943 return ($this->config_write($this->name
, implode('{;}', $result)) ?
'' : get_string('errorsetting', 'admin').$this->visiblename
.'<br />');
2946 function output_html($data, $query='') {
2947 $fullname = $this->get_full_name();
2948 $return = '<div class="form-group">';
2949 for ($i = 0; $i < count($data) / 2; $i++
) {
2950 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.$i.']" value="'.$data['k'.$i].'" />';
2951 $return .= ' ';
2952 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.$i.']" value="'.$data['v'.$i].'" /><br />';
2954 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.$i.']" value="" />';
2955 $return .= ' ';
2956 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.$i.']" value="" /><br />';
2957 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.($i +
1).']" value="" />';
2958 $return .= ' ';
2959 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.($i +
1).']" value="" />';
2960 $return .= '</div>';
2962 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
2968 * Setting for spellchecker language selection.
2970 class admin_setting_special_editordictionary
extends admin_setting_configselect
{
2972 function admin_setting_special_editordictionary() {
2973 $name = 'editordictionary';
2974 $visiblename = get_string('editordictionary','admin');
2975 $description = get_string('configeditordictionary', 'admin');
2976 parent
::admin_setting_configselect($name, $visiblename, $description, '', NULL);
2979 function load_choices() {
2980 // function borrowed from the old moodle/admin/editor.php, slightly modified
2981 // Get all installed dictionaries in the system
2982 if (is_array($this->choices
)) {
2986 $this->choices
= array();
2992 // If aspellpath isn't set don't even bother ;-)
2993 if (empty($CFG->aspellpath
)) {
2994 $this->choices
['error'] = 'Empty aspell path!';
2998 // Do we have access to popen function?
2999 if (!function_exists('popen')) {
3000 $this->choices
['error'] = 'Popen function disabled!';
3004 $cmd = $CFG->aspellpath
;
3006 $dictionaries = array();
3008 if(!($handle = @popen
(escapeshellarg($cmd).' dump dicts', 'r'))) {
3009 $this->choices
['error'] = 'Couldn\'t create handle!';
3012 while(!feof($handle)) {
3013 $output .= fread($handle, 1024);
3017 $dictionaries = explode(chr(10), $output);
3018 foreach ($dictionaries as $dict) {
3022 $this->choices
[$dict] = $dict;
3025 if (empty($this->choices
)) {
3026 $this->choices
['error'] = 'Error! Check your aspell installation!';
3033 class admin_setting_special_editorhidebuttons
extends admin_setting
{
3036 function admin_setting_special_editorhidebuttons() {
3037 parent
::admin_setting('editorhidebuttons', get_string('editorhidebuttons', 'admin'),
3038 get_string('confeditorhidebuttons', 'admin'), array());
3039 // weird array... buttonname => buttonimage (assume proper path appended). if you leave buttomimage blank, text will be printed instead
3040 $this->items
= array('fontname' => '',
3042 'formatblock' => '',
3043 'bold' => 'ed_format_bold.gif',
3044 'italic' => 'ed_format_italic.gif',
3045 'underline' => 'ed_format_underline.gif',
3046 'strikethrough' => 'ed_format_strike.gif',
3047 'subscript' => 'ed_format_sub.gif',
3048 'superscript' => 'ed_format_sup.gif',
3049 'copy' => 'ed_copy.gif',
3050 'cut' => 'ed_cut.gif',
3051 'paste' => 'ed_paste.gif',
3052 'clean' => 'ed_wordclean.gif',
3053 'undo' => 'ed_undo.gif',
3054 'redo' => 'ed_redo.gif',
3055 'justifyleft' => 'ed_align_left.gif',
3056 'justifycenter' => 'ed_align_center.gif',
3057 'justifyright' => 'ed_align_right.gif',
3058 'justifyfull' => 'ed_align_justify.gif',
3059 'lefttoright' => 'ed_left_to_right.gif',
3060 'righttoleft' => 'ed_right_to_left.gif',
3061 'insertorderedlist' => 'ed_list_num.gif',
3062 'insertunorderedlist' => 'ed_list_bullet.gif',
3063 'outdent' => 'ed_indent_less.gif',
3064 'indent' => 'ed_indent_more.gif',
3065 'forecolor' => 'ed_color_fg.gif',
3066 'hilitecolor' => 'ed_color_bg.gif',
3067 'inserthorizontalrule' => 'ed_hr.gif',
3068 'createanchor' => 'ed_anchor.gif',
3069 'createlink' => 'ed_link.gif',
3070 'unlink' => 'ed_unlink.gif',
3071 'insertimage' => 'ed_image.gif',
3072 'inserttable' => 'insert_table.gif',
3073 'insertsmile' => 'em.icon.smile.gif',
3074 'insertchar' => 'icon_ins_char.gif',
3075 'spellcheck' => 'spell-check.gif',
3076 'htmlmode' => 'ed_html.gif',
3077 'popupeditor' => 'fullscreen_maximize.gif',
3078 'search_replace' => 'ed_replace.gif');
3081 function get_setting() {
3082 $result = $this->config_read($this->name
);
3083 if (is_null($result)) {
3086 if ($result === '') {
3089 return explode(' ', $result);
3092 function write_setting($data) {
3093 if (!is_array($data)) {
3094 return ''; // ignore it
3096 unset($data['xxxxx']);
3099 foreach ($data as $key => $value) {
3100 if (!isset($this->items
[$key])) {
3101 return get_string('errorsetting', 'admin');
3103 if ($value == '1') {
3107 return ($this->config_write($this->name
, implode(' ', $result)) ?
'' : get_string('errorsetting', 'admin'));
3110 function output_html($data, $query='') {
3114 // checkboxes with input name="$this->name[$key]" value="1"
3115 // we do 15 fields per column
3117 $return = '<div class="form-group">';
3118 $return .= '<table><tr><td valign="top" align="right">';
3119 $return .= '<input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
3123 foreach($this->items
as $key => $value) {
3124 if ($count %
15 == 0 and $count != 0) {
3125 $return .= '</td><td valign="top" align="right">';
3128 $return .= '<label for="'.$this->get_id().$key.'">';
3129 $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').'" />').' ';
3130 $return .= '<input type="checkbox" class="form-checkbox" value="1" id="'.$this->get_id().$key.'" name="'.$this->get_full_name().'['.$key.']"'.(in_array($key,$data) ?
' checked="checked"' : '').' /> ';
3131 $return .= '</label>';
3133 if ($count %
15 != 0) {
3134 $return .= '<br /><br />';
3138 $return .= '</td></tr>';
3139 $return .= '</table>';
3140 $return .= '</div>';
3142 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
3147 * Special setting for limiting of the list of available languages.
3149 class admin_setting_langlist
extends admin_setting_configtext
{
3150 function admin_setting_langlist() {
3151 parent
::admin_setting_configtext('langlist', get_string('langlist', 'admin'), get_string('configlanglist', 'admin'), '', PARAM_NOTAGS
);
3154 function write_setting($data) {
3155 $return = parent
::write_setting($data);
3156 get_list_of_languages(true);//refresh the list
3162 * Course category selection
3164 class admin_settings_coursecat_select
extends admin_setting_configselect
{
3165 function admin_settings_coursecat_select($name, $visiblename, $description, $defaultsetting) {
3166 parent
::admin_setting_configselect($name, $visiblename, $description, $defaultsetting, NULL);
3169 function load_choices() {
3171 require_once($CFG->dirroot
.'/course/lib.php');
3172 if (is_array($this->choices
)) {
3175 $this->choices
= make_categories_options();
3180 class admin_setting_special_backupdays
extends admin_setting_configmulticheckbox2
{
3181 function admin_setting_special_backupdays() {
3182 parent
::admin_setting_configmulticheckbox2('backup_sche_weekdays', get_string('schedule'), get_string('backupschedulehelp'), array(), NULL);
3183 $this->plugin
= 'backup';
3186 function load_choices() {
3187 if (is_array($this->choices
)) {
3190 $this->choices
= array();
3191 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
3192 foreach ($days as $day) {
3193 $this->choices
[$day] = get_string($day, 'calendar');
3200 * Special debug setting
3202 class admin_setting_special_debug
extends admin_setting_configselect
{
3203 function admin_setting_special_debug() {
3204 parent
::admin_setting_configselect('debug', get_string('debug', 'admin'), get_string('configdebug', 'admin'), DEBUG_NONE
, NULL);
3207 function load_choices() {
3208 if (is_array($this->choices
)) {
3211 $this->choices
= array(DEBUG_NONE
=> get_string('debugnone', 'admin'),
3212 DEBUG_MINIMAL
=> get_string('debugminimal', 'admin'),
3213 DEBUG_NORMAL
=> get_string('debugnormal', 'admin'),
3214 DEBUG_ALL
=> get_string('debugall', 'admin'),
3215 DEBUG_DEVELOPER
=> get_string('debugdeveloper', 'admin'));
3221 class admin_setting_special_calendar_weekend
extends admin_setting
{
3222 function admin_setting_special_calendar_weekend() {
3223 $name = 'calendar_weekend';
3224 $visiblename = get_string('calendar_weekend', 'admin');
3225 $description = get_string('helpweekenddays', 'admin');
3226 $default = array ('0', '6'); // Saturdays and Sundays
3227 parent
::admin_setting($name, $visiblename, $description, $default);
3230 function get_setting() {
3231 $result = $this->config_read($this->name
);
3232 if (is_null($result)) {
3235 if ($result === '') {
3238 $settings = array();
3239 for ($i=0; $i<7; $i++
) {
3240 if ($result & (1 << $i)) {
3247 function write_setting($data) {
3248 if (!is_array($data)) {
3251 unset($data['xxxxx']);
3253 foreach($data as $index) {
3254 $result |
= 1 << $index;
3256 return ($this->config_write($this->name
, $result) ?
'' : get_string('errorsetting', 'admin'));
3259 function output_html($data, $query='') {
3260 // The order matters very much because of the implied numeric keys
3261 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
3262 $return = '<table><thead><tr>';
3263 $return .= '<input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
3264 foreach($days as $index => $day) {
3265 $return .= '<td><label for="'.$this->get_id().$index.'">'.get_string($day, 'calendar').'</label></td>';
3267 $return .= '</tr></thead><tbody><tr>';
3268 foreach($days as $index => $day) {
3269 $return .= '<td><input type="checkbox" class="form-checkbox" id="'.$this->get_id().$index.'" name="'.$this->get_full_name().'[]" value="'.$index.'" '.(in_array("$index", $data) ?
'checked="checked"' : '').' /></td>';
3271 $return .= '</tr></tbody></table>';
3273 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
3280 * Graded roles in gradebook
3282 class admin_setting_special_gradebookroles
extends admin_setting_configmulticheckbox
{
3283 function admin_setting_special_gradebookroles() {
3284 parent
::admin_setting_configmulticheckbox('gradebookroles', get_string('gradebookroles', 'admin'),
3285 get_string('configgradebookroles', 'admin'), NULL, NULL);
3288 function load_choices() {
3290 if (empty($CFG->rolesactive
)) {
3293 if (is_array($this->choices
)) {
3296 if ($roles = get_records('role')) {
3297 $this->choices
= array();
3298 foreach($roles as $role) {
3299 $this->choices
[$role->id
] = format_string($role->name
);
3307 function get_defaultsetting() {
3309 if (empty($CFG->rolesactive
)) {
3313 if ($studentroles = get_roles_with_capability('moodle/legacy:student', CAP_ALLOW
)) {
3314 foreach ($studentroles as $studentrole) {
3315 $result[$studentrole->id
] = '1';
3322 class admin_setting_regradingcheckbox
extends admin_setting_configcheckbox
{
3323 function write_setting($data) {
3326 $oldvalue = $this->config_read($this->name
);
3327 $return = parent
::write_setting($data);
3328 $newvalue = $this->config_read($this->name
);
3330 if ($oldvalue !== $newvalue) {
3331 // force full regrading
3332 set_field('grade_items', 'needsupdate', 1, 'needsupdate', 0);
3340 * Which roles to show on course decription page
3342 class admin_setting_special_coursemanager
extends admin_setting_configmulticheckbox
{
3343 function admin_setting_special_coursemanager() {
3344 parent
::admin_setting_configmulticheckbox('coursemanager', get_string('coursemanager', 'admin'),
3345 get_string('configcoursemanager', 'admin'), NULL, NULL);
3348 function load_choices() {
3349 if (is_array($this->choices
)) {
3352 if ($roles = get_records('role','','','sortorder')) {
3353 $this->choices
= array();
3354 foreach($roles as $role) {
3355 $this->choices
[$role->id
] = format_string($role->name
);
3362 function get_defaultsetting() {
3364 if (empty($CFG->rolesactive
)) {
3368 if ($teacherroles = get_roles_with_capability('moodle/legacy:editingteacher', CAP_ALLOW
)) {
3369 foreach ($teacherroles as $teacherrole) {
3370 $result[$teacherrole->id
] = '1';
3378 * Primary grade export plugin - has state tracking.
3380 class admin_setting_special_gradeexport
extends admin_setting_configmulticheckbox
{
3381 function admin_setting_special_gradeexport() {
3382 parent
::admin_setting_configmulticheckbox('gradeexport', get_string('gradeexport', 'admin'),
3383 get_string('configgradeexport', 'admin'), array(), NULL);
3386 function load_choices() {
3387 if (is_array($this->choices
)) {
3390 $this->choices
= array();
3392 if ($plugins = get_list_of_plugins('grade/export')) {
3393 foreach($plugins as $plugin) {
3394 $this->choices
[$plugin] = get_string('modulename', 'gradeexport_'.$plugin);
3402 * Grade category settings
3404 class admin_setting_gradecat_combo
extends admin_setting
{
3408 function admin_setting_gradecat_combo($name, $visiblename, $description, $defaultsetting, $choices) {
3409 $this->choices
= $choices;
3410 parent
::admin_setting($name, $visiblename, $description, $defaultsetting);
3413 function get_setting() {
3416 $value = $this->config_read($this->name
);
3417 $flag = $this->config_read($this->name
.'_flag');
3419 if (is_null($value) or is_null($flag)) {
3424 $forced = (boolean
)(1 & $flag); // first bit
3425 $adv = (boolean
)(2 & $flag); // second bit
3427 return array('value' => $value, 'forced' => $forced, 'adv' => $adv);
3430 function write_setting($data) {
3433 $value = $data['value'];
3434 $forced = empty($data['forced']) ?
0 : 1;
3435 $adv = empty($data['adv']) ?
0 : 2;
3436 $flag = ($forced |
$adv); //bitwise or
3438 if (!in_array($value, array_keys($this->choices
))) {
3439 return 'Error setting ';
3442 $oldvalue = $this->config_read($this->name
);
3443 $oldflag = (int)$this->config_read($this->name
.'_flag');
3444 $oldforced = (1 & $oldflag); // first bit
3446 $result1 = $this->config_write($this->name
, $value);
3447 $result2 = $this->config_write($this->name
.'_flag', $flag);
3449 // force regrade if needed
3450 if ($oldforced != $forced or ($forced and $value != $oldvalue)) {
3451 require_once($CFG->libdir
.'/gradelib.php');
3452 grade_category
::updated_forced_settings();
3455 if ($result1 and $result2) {
3458 return get_string('errorsetting', 'admin');
3462 function output_html($data, $query='') {
3463 $value = $data['value'];
3464 $forced = !empty($data['forced']);
3465 $adv = !empty($data['adv']);
3467 $default = $this->get_defaultsetting();
3468 if (!is_null($default)) {
3469 $defaultinfo = array();
3470 if (isset($this->choices
[$default['value']])) {
3471 $defaultinfo[] = $this->choices
[$default['value']];
3473 if (!empty($default['forced'])) {
3474 $defaultinfo[] = get_string('force');
3476 if (!empty($default['adv'])) {
3477 $defaultinfo[] = get_string('advanced');
3479 $defaultinfo = implode(', ', $defaultinfo);
3482 $defaultinfo = NULL;
3486 $return = '<div class="form-group">';
3487 $return .= '<select class="form-select" id="'.$this->get_id().'" name="'.$this->get_full_name().'[value]">';
3488 foreach ($this->choices
as $key => $val) {
3489 // the string cast is needed because key may be integer - 0 is equal to most strings!
3490 $return .= '<option value="'.$key.'"'.((string)$key==$value ?
' selected="selected"' : '').'>'.$val.'</option>';
3492 $return .= '</select>';
3493 $return .= '<input type="checkbox" class="form-checkbox" id="'.$this->get_id().'force" name="'.$this->get_full_name().'[forced]" value="1" '.($forced ?
'checked="checked"' : '').' />'
3494 .'<label for="'.$this->get_id().'force">'.get_string('force').'</label>';
3495 $return .= '<input type="checkbox" class="form-checkbox" id="'.$this->get_id().'adv" name="'.$this->get_full_name().'[adv]" value="1" '.($adv ?
'checked="checked"' : '').' />'
3496 .'<label for="'.$this->get_id().'adv">'.get_string('advanced').'</label>';
3497 $return .= '</div>';
3499 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, true, '', $defaultinfo, $query);
3505 * Selection of grade report in user profiles
3507 class admin_setting_grade_profilereport
extends admin_setting_configselect
{
3508 function admin_setting_grade_profilereport() {
3509 parent
::admin_setting_configselect('grade_profilereport', get_string('profilereport', 'grades'), get_string('configprofilereport', 'grades'), 'user', null);
3512 function load_choices() {
3513 if (is_array($this->choices
)) {
3516 $this->choices
= array();
3519 require_once($CFG->libdir
.'/gradelib.php');
3521 foreach (get_list_of_plugins('grade/report') as $plugin) {
3522 if (file_exists($CFG->dirroot
.'/grade/report/'.$plugin.'/lib.php')) {
3523 require_once($CFG->dirroot
.'/grade/report/'.$plugin.'/lib.php');
3524 $functionname = 'grade_report_'.$plugin.'_profilereport';
3525 if (function_exists($functionname)) {
3526 $this->choices
[$plugin] = get_string('modulename', 'gradereport_'.$plugin, NULL, $CFG->dirroot
.'/grade/report/'.$plugin.'/lang/');
3535 * Special class for register auth selection
3537 class admin_setting_special_registerauth
extends admin_setting_configselect
{
3538 function admin_setting_special_registerauth() {
3539 parent
::admin_setting_configselect('registerauth', get_string('selfregistration', 'auth'), get_string('selfregistration_help', 'auth'), '', null);
3542 function get_defaultsettings() {
3543 $this->load_choices();
3544 if (array_key_exists($this->defaultsetting
, $this->choices
)) {
3545 return $this->defaultsetting
;
3551 function load_choices() {
3554 if (is_array($this->choices
)) {
3557 $this->choices
= array();
3558 $this->choices
[''] = get_string('disable');
3560 $authsenabled = get_enabled_auth_plugins(true);
3562 foreach ($authsenabled as $auth) {
3563 $authplugin = get_auth_plugin($auth);
3564 if (!$authplugin->can_signup()) {
3567 // Get the auth title (from core or own auth lang files)
3568 $authtitle = $authplugin->get_title();
3569 $this->choices
[$auth] = $authtitle;
3576 * Module manage page
3578 class admin_page_managemods
extends admin_externalpage
{
3579 function admin_page_managemods() {
3581 parent
::admin_externalpage('managemodules', get_string('modsettings', 'admin'), "$CFG->wwwroot/$CFG->admin/modules.php");
3584 function search($query) {
3585 if ($result = parent
::search($query)) {
3590 if ($modules = get_records('modules')) {
3591 $textlib = textlib_get_instance();
3592 foreach ($modules as $module) {
3593 if (strpos($module->name
, $query) !== false) {
3597 $strmodulename = get_string('modulename', $module->name
);
3598 if (strpos($textlib->strtolower($strmodulename), $query) !== false) {
3605 $result = new object();
3606 $result->page
= $this;
3607 $result->settings
= array();
3608 return array($this->name
=> $result);
3616 * Enrolment manage page
3618 class admin_enrolment_page
extends admin_externalpage
{
3619 function admin_enrolment_page() {
3621 parent
::admin_externalpage('enrolment', get_string('enrolments'), $CFG->wwwroot
. '/'.$CFG->admin
.'/enrol.php');
3624 function search($query) {
3625 if ($result = parent
::search($query)) {
3631 if ($modules = get_list_of_plugins('enrol')) {
3632 $textlib = textlib_get_instance();
3633 foreach ($modules as $plugin) {
3634 if (strpos($plugin, $query) !== false) {
3638 $strmodulename = get_string('enrolname', "enrol_$plugin");
3639 if (strpos($textlib->strtolower($strmodulename), $query) !== false) {
3645 //ugly harcoded hacks
3646 if (strpos('sendcoursewelcomemessage', $query) !== false) {
3648 } else if (strpos($textlib->strtolower(get_string('sendcoursewelcomemessage', 'admin')), $query) !== false) {
3650 } else if (strpos($textlib->strtolower(get_string('configsendcoursewelcomemessage', 'admin')), $query) !== false) {
3652 } else if (strpos($textlib->strtolower(get_string('configenrolmentplugins', 'admin')), $query) !== false) {
3656 $result = new object();
3657 $result->page
= $this;
3658 $result->settings
= array();
3659 return array($this->name
=> $result);
3667 * Blocks manage page
3669 class admin_page_manageblocks
extends admin_externalpage
{
3670 function admin_page_manageblocks() {
3672 parent
::admin_externalpage('manageblocks', get_string('blocksettings', 'admin'), "$CFG->wwwroot/$CFG->admin/blocks.php");
3675 function search($query) {
3677 if ($result = parent
::search($query)) {
3682 if (!empty($CFG->blocks_version
) and $blocks = get_records('block')) {
3683 $textlib = textlib_get_instance();
3684 foreach ($blocks as $block) {
3685 if (strpos($block->name
, $query) !== false) {
3689 $strblockname = get_string('blockname', 'block_'.$block->name
);
3690 if (strpos($textlib->strtolower($strblockname), $query) !== false) {
3697 $result = new object();
3698 $result->page
= $this;
3699 $result->settings
= array();
3700 return array($this->name
=> $result);
3708 * Special class for authentication administration.
3710 class admin_setting_manageauths
extends admin_setting
{
3711 function admin_setting_manageauths() {
3712 parent
::admin_setting('authsui', get_string('authsettings', 'admin'), '', '');
3715 function get_setting() {
3719 function get_defaultsetting() {
3723 function write_setting($data) {
3724 // do not write any setting
3728 function is_related($query) {
3729 if (parent
::is_related($query)) {
3733 $textlib = textlib_get_instance();
3734 $authsavailable = get_list_of_plugins('auth');
3735 foreach ($authsavailable as $auth) {
3736 if (strpos($auth, $query) !== false) {
3739 $authplugin = get_auth_plugin($auth);
3740 $authtitle = $authplugin->get_title();
3741 if (strpos($textlib->strtolower($authtitle), $query) !== false) {
3748 function output_html($data, $query='') {
3753 $txt = get_strings(array('authenticationplugins', 'users', 'administration',
3754 'settings', 'edit', 'name', 'enable', 'disable',
3755 'up', 'down', 'none'));
3756 $txt->updown
= "$txt->up/$txt->down";
3758 $authsavailable = get_list_of_plugins('auth');
3759 get_enabled_auth_plugins(true); // fix the list of enabled auths
3760 if (empty($CFG->auth
)) {
3761 $authsenabled = array();
3763 $authsenabled = explode(',', $CFG->auth
);
3766 // construct the display array, with enabled auth plugins at the top, in order
3767 $displayauths = array();
3768 $registrationauths = array();
3769 $registrationauths[''] = $txt->disable
;
3770 foreach ($authsenabled as $auth) {
3771 $authplugin = get_auth_plugin($auth);
3772 /// Get the auth title (from core or own auth lang files)
3773 $authtitle = $authplugin->get_title();
3775 $displayauths[$auth] = $authtitle;
3776 if ($authplugin->can_signup()) {
3777 $registrationauths[$auth] = $authtitle;
3781 foreach ($authsavailable as $auth) {
3782 if (array_key_exists($auth, $displayauths)) {
3783 continue; //already in the list
3785 $authplugin = get_auth_plugin($auth);
3786 /// Get the auth title (from core or own auth lang files)
3787 $authtitle = $authplugin->get_title();
3789 $displayauths[$auth] = $authtitle;
3790 if ($authplugin->can_signup()) {
3791 $registrationauths[$auth] = $authtitle;
3795 $return = print_heading(get_string('actauthhdr', 'auth'), '', 3, 'main', true);
3796 $return .= print_box_start('generalbox authsui', '', true);
3798 $table = new object();
3799 $table->head
= array($txt->name
, $txt->enable
, $txt->updown
, $txt->settings
);
3800 $table->align
= array('left', 'center', 'center', 'center');
3801 $table->width
= '90%';
3802 $table->data
= array();
3804 //add always enabled plugins first
3805 $displayname = "<span>".$displayauths['manual']."</span>";
3806 $settings = "<a href=\"auth_config.php?auth=manual\">{$txt->settings}</a>";
3807 //$settings = "<a href=\"settings.php?section=authsettingmanual\">{$txt->settings}</a>";
3808 $table->data
[] = array($displayname, '', '', $settings);
3809 $displayname = "<span>".$displayauths['nologin']."</span>";
3810 $settings = "<a href=\"auth_config.php?auth=nologin\">{$txt->settings}</a>";
3811 $table->data
[] = array($displayname, '', '', $settings);
3814 // iterate through auth plugins and add to the display table
3816 $authcount = count($authsenabled);
3817 $url = "auth.php?sesskey=" . sesskey();
3818 foreach ($displayauths as $auth => $name) {
3819 if ($auth == 'manual' or $auth == 'nologin') {
3823 if (in_array($auth, $authsenabled)) {
3824 $hideshow = "<a href=\"$url&action=disable&auth=$auth\">";
3825 $hideshow .= "<img src=\"{$CFG->pixpath}/i/hide.gif\" class=\"icon\" alt=\"disable\" /></a>";
3826 // $hideshow = "<a href=\"$url&action=disable&auth=$auth\"><input type=\"checkbox\" checked /></a>";
3828 $displayname = "<span>$name</span>";
3831 $hideshow = "<a href=\"$url&action=enable&auth=$auth\">";
3832 $hideshow .= "<img src=\"{$CFG->pixpath}/i/show.gif\" class=\"icon\" alt=\"enable\" /></a>";
3833 // $hideshow = "<a href=\"$url&action=enable&auth=$auth\"><input type=\"checkbox\" /></a>";
3835 $displayname = "<span class=\"dimmed_text\">$name</span>";
3838 // up/down link (only if auth is enabled)
3841 if ($updowncount > 1) {
3842 $updown .= "<a href=\"$url&action=up&auth=$auth\">";
3843 $updown .= "<img src=\"{$CFG->pixpath}/t/up.gif\" alt=\"up\" /></a> ";
3846 $updown .= "<img src=\"{$CFG->pixpath}/spacer.gif\" class=\"icon\" alt=\"\" /> ";
3848 if ($updowncount < $authcount) {
3849 $updown .= "<a href=\"$url&action=down&auth=$auth\">";
3850 $updown .= "<img src=\"{$CFG->pixpath}/t/down.gif\" alt=\"down\" /></a>";
3853 $updown .= "<img src=\"{$CFG->pixpath}/spacer.gif\" class=\"icon\" alt=\"\" />";
3859 if (file_exists($CFG->dirroot
.'/auth/'.$auth.'/settings.php')) {
3860 $settings = "<a href=\"settings.php?section=authsetting$auth\">{$txt->settings}</a>";
3862 $settings = "<a href=\"auth_config.php?auth=$auth\">{$txt->settings}</a>";
3865 // add a row to the table
3866 $table->data
[] =array($displayname, $hideshow, $updown, $settings);
3868 $return .= print_table($table, true);
3869 $return .= get_string('configauthenticationplugins', 'admin').'<br />'.get_string('tablenosave', 'filters');
3870 $return .= print_box_end(true);
3871 return highlight($query, $return);
3875 * Special class for filter administration.
3877 class admin_setting_managefilters
extends admin_setting
{
3878 function admin_setting_managefilters() {
3879 parent
::admin_setting('filtersui', get_string('filtersettings', 'admin'), '', '');
3882 function get_setting() {
3886 function get_defaultsetting() {
3890 function write_setting($data) {
3891 // do not write any setting
3895 function is_related($query) {
3896 if (parent
::is_related($query)) {
3900 $textlib = textlib_get_instance();
3901 $filterlocations = array('mod','filter');
3902 foreach ($filterlocations as $filterlocation) {
3903 $plugins = get_list_of_plugins($filterlocation);
3904 foreach ($plugins as $plugin) {
3905 if (strpos($plugin, $query) !== false) {
3908 $name = get_string('filtername', $plugin);
3909 if (strpos($textlib->strtolower($name), $query) !== false) {
3917 function output_html($data, $query='') {
3920 $strname = get_string('name');
3921 $strhide = get_string('disable');
3922 $strshow = get_string('enable');
3923 $strhideshow = "$strhide/$strshow";
3924 $strsettings = get_string('settings');
3925 $strup = get_string('up');
3926 $strdown = get_string('down');
3927 $strupdown = "$strup/$strdown";
3929 // get a list of possible filters (and translate name if possible)
3930 // note filters can be in the dedicated filters area OR in their
3931 // associated modules
3932 $installedfilters = array();
3933 $filtersettings_new = array();
3934 $filtersettings_old = array();
3935 $filterlocations = array('mod','filter');
3936 foreach ($filterlocations as $filterlocation) {
3937 $plugins = get_list_of_plugins($filterlocation);
3938 foreach ($plugins as $plugin) {
3939 $pluginpath = "$CFG->dirroot/$filterlocation/$plugin/filter.php";
3940 $settingspath_new = "$CFG->dirroot/$filterlocation/$plugin/filtersettings.php";
3941 $settingspath_old = "$CFG->dirroot/$filterlocation/$plugin/filterconfig.html";
3942 if (is_readable($pluginpath)) {
3943 $name = trim(get_string("filtername", $plugin));
3944 if (empty($name) or ($name == '[[filtername]]')) {
3945 $textlib = textlib_get_instance();
3946 $name = $textlib->strtotitle($plugin);
3948 $installedfilters["$filterlocation/$plugin"] = $name;
3949 if (is_readable($settingspath_new)) {
3950 $filtersettings_new[] = "$filterlocation/$plugin";
3951 } else if (is_readable($settingspath_old)) {
3952 $filtersettings_old[] = "$filterlocation/$plugin";
3958 // get all the currently selected filters
3959 if (!empty($CFG->textfilters
)) {
3960 $oldactivefilters = explode(',', $CFG->textfilters
);
3961 $oldactivefilters = array_unique($oldactivefilters);
3963 $oldactivefilters = array();
3966 // take this opportunity to clean up filters
3967 $activefilters = array();
3968 foreach ($oldactivefilters as $oldactivefilter) {
3969 if (!empty($oldactivefilter) and array_key_exists($oldactivefilter, $installedfilters)) {
3970 $activefilters[] = $oldactivefilter;
3974 // construct the display array with installed filters
3975 // at the top in the right order
3976 $displayfilters = array();
3977 foreach ($activefilters as $activefilter) {
3978 $name = $installedfilters[$activefilter];
3979 $displayfilters[$activefilter] = $name;
3981 foreach ($installedfilters as $key => $filter) {
3982 if (!array_key_exists($key, $displayfilters)) {
3983 $displayfilters[$key] = $filter;
3987 $return = print_heading(get_string('actfilterhdr', 'filters'), '', 3, 'main', true);
3988 $return .= print_box_start('generalbox filtersui', '', true);
3990 $table = new object();
3991 $table->head
= array($strname, $strhideshow, $strupdown, $strsettings);
3992 $table->align
= array('left', 'center', 'center', 'center');
3993 $table->width
= '90%';
3994 $table->data
= array();
3996 $filtersurl = "$CFG->wwwroot/$CFG->admin/filters.php?sesskey=".sesskey();
3997 $imgurl = "$CFG->pixpath/t";
3999 // iterate through filters adding to display table
4001 $activefilterscount = count($activefilters);
4002 foreach ($displayfilters as $path => $name) {
4003 $upath = urlencode($path);
4004 // get hide/show link
4005 if (in_array($path, $activefilters)) {
4006 $hideshow = "<a href=\"$filtersurl&action=hide&filterpath=$upath\">";
4007 $hideshow .= "<img src=\"{$CFG->pixpath}/i/hide.gif\" class=\"icon\" alt=\"$strhide\" /></a>";
4009 $displayname = "<span>$name</span>";
4012 $hideshow = "<a href=\"$filtersurl&action=show&filterpath=$upath\">";
4013 $hideshow .= "<img src=\"{$CFG->pixpath}/i/show.gif\" class=\"icon\" alt=\"$strshow\" /></a>";
4015 $displayname = "<span class=\"dimmed_text\">$name</span>";
4018 // get up/down link (only if not hidden)
4021 if ($updowncount>1) {
4022 $updown .= "<a href=\"$filtersurl&action=up&filterpath=$upath\">";
4023 $updown .= "<img src=\"$imgurl/up.gif\" alt=\"$strup\" /></a> ";
4026 $updown .= "<img src=\"$CFG->pixpath/spacer.gif\" class=\"icon\" alt=\"\" /> ";
4028 if ($updowncount<$activefilterscount) {
4029 $updown .= "<a href=\"$filtersurl&action=down&filterpath=$upath\">";
4030 $updown .= "<img src=\"$imgurl/down.gif\" alt=\"$strdown\" /></a>";
4033 $updown .= "<img src=\"$CFG->pixpath/spacer.gif\" class=\"icon\" alt=\"\" />";
4038 // settings link (if defined)
4040 if (in_array($path, $filtersettings_new)) {
4041 $settings = "<a href=\"settings.php?section=filtersetting".str_replace('/', '',$path)."\">$strsettings</a>";
4042 } else if (in_array($path, $filtersettings_old)) {
4043 $settings = "<a href=\"filter.php?filter=".urlencode($path)."\">$strsettings</a>";
4046 // write data into the table object
4047 $table->data
[] = array($displayname, $hideshow, $updown, $settings);
4049 $return .= print_table($table, true);
4050 $return .= get_string('tablenosave', 'filters');
4051 $return .= print_box_end(true);
4052 return highlight($query, $return);
4057 * Initialise admin page - this function does require login and permission
4058 * checks specified in page definition.
4059 * This function must be called on each admin page before other code.
4060 * @param string $section name of page
4062 function admin_externalpage_setup($section) {
4064 global $CFG, $PAGE, $USER;
4065 require_once($CFG->libdir
.'/blocklib.php');
4066 require_once($CFG->dirroot
.'/'.$CFG->admin
.'/pagelib.php');
4068 if ($site = get_site()) {
4071 redirect($CFG->wwwroot
.'/'.$CFG->admin
.'/index.php');
4075 $adminroot =& admin_get_root(false, false); // settings not required for external pages
4076 $extpage =& $adminroot->locate($section);
4078 if (empty($extpage) or !is_a($extpage, 'admin_externalpage')) {
4079 print_error('sectionerror', 'admin', "$CFG->wwwroot/$CFG->admin/");
4083 // this eliminates our need to authenticate on the actual pages
4084 if (!($extpage->check_access())) {
4085 print_error('accessdenied', 'admin');
4089 page_map_class(PAGE_ADMIN
, 'page_admin');
4090 $PAGE = page_create_object(PAGE_ADMIN
, 0); // there must be any constant id number
4091 $PAGE->init_extra($section); // hack alert!
4093 $adminediting = optional_param('adminedit', -1, PARAM_BOOL
);
4095 if (!isset($USER->adminediting
)) {
4096 $USER->adminediting
= false;
4099 if ($PAGE->user_allowed_editing()) {
4100 if ($adminediting == 1) {
4101 $USER->adminediting
= true;
4102 } elseif ($adminediting == 0) {
4103 $USER->adminediting
= false;
4109 * Print header for admin page
4110 * @param string $focus focus element
4112 function admin_externalpage_print_header($focus='') {
4114 if (!is_string($focus)) {
4115 $focus = ''; // BC compatibility, there used to be adminroot parameter
4118 global $CFG, $PAGE, $SITE, $THEME;
4120 define('ADMIN_EXT_HEADER_PRINTED', 'true');
4122 if (!empty($SITE->fullname
)) {
4123 $pageblocks = blocks_setup($PAGE);
4125 $preferred_width_left = bounded_number(BLOCK_L_MIN_WIDTH
,
4126 blocks_preferred_width($pageblocks[BLOCK_POS_LEFT
]),
4128 $preferred_width_right = bounded_number(BLOCK_R_MIN_WIDTH
,
4129 blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT
]),
4132 $PAGE->print_header('', $focus);
4133 echo '<table id="layout-table" summary=""><tr>';
4135 $lt = (empty($THEME->layouttable
)) ?
array('left', 'middle', 'right') : $THEME->layouttable
;
4136 foreach ($lt as $column) {
4138 if ($column == 'middle') break;
4140 foreach ($lt1 as $column) {
4143 echo '<td style="width: '.$preferred_width_left.'px;" id="left-column">';
4144 print_container_start();
4145 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT
);
4146 print_container_end();
4151 echo '<td id="middle-column">';
4152 print_container_start(true);
4153 $THEME->open_header_containers++
; // this is hacky workaround for the error()/notice() autoclosing problems on admin pages
4157 if (blocks_have_content($pageblocks, BLOCK_POS_RIGHT
)) {
4158 echo '<td style="width: '.$preferred_width_right.'px;" id="right-column">';
4159 print_container_start();
4160 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT
);
4161 print_container_end();
4173 * Print footer on admin page - please use normal print_footer() instead
4175 function admin_externalpage_print_footer() {
4177 global $CFG, $PAGE, $SITE, $THEME;
4179 define('ADMIN_EXT_FOOTER_PRINTED', 'true');
4181 if (!empty($SITE->fullname
)) {
4182 $pageblocks = blocks_setup($PAGE);
4183 $preferred_width_left = bounded_number(BLOCK_L_MIN_WIDTH
,
4184 blocks_preferred_width($pageblocks[BLOCK_POS_LEFT
]),
4186 $preferred_width_right = bounded_number(BLOCK_R_MIN_WIDTH
,
4187 blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT
]),
4190 $lt = (empty($THEME->layouttable
)) ?
array('left', 'middle', 'right') : $THEME->layouttable
;
4191 foreach ($lt as $column) {
4192 if ($column != 'middle') {
4194 } else if ($column == 'middle') {
4198 foreach ($lt as $column) {
4201 echo '<td style="width: '.$preferred_width_left.'px;" id="left-column">';
4202 print_container_start();
4203 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT
);
4204 print_container_end();
4209 print_container_end();
4210 $THEME->open_header_containers
--; // this is hacky workaround for the error()/notice() autoclosing problems on admin pages
4215 if (blocks_have_content($pageblocks, BLOCK_POS_RIGHT
)) {
4216 echo '<td style="width: '.$preferred_width_right.'px;" id="right-column">';
4217 print_container_start();
4218 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT
);
4219 print_container_end();
4225 echo '</tr></table>';
4231 * Returns the reference to admin tree root
4234 function &admin_get_root($reload=false, $requirefulltree=true) {
4237 static $ADMIN = NULL;
4239 if (!is_null($ADMIN)) {
4240 $olderrors = $ADMIN->errors
;
4241 $oldsearch = $ADMIN->search
;
4242 $oldfulltree = $ADMIN->fulltree
;
4244 $olderrors = array();
4246 $oldfulltree = false;
4249 if ($reload or ($requirefulltree and !$oldfulltree)) {
4253 if (is_null($ADMIN)) {
4254 // start the admin tree!
4255 $ADMIN = new admin_root();
4256 // array of error messages and search query
4257 $ADMIN->errors
= $olderrors;
4258 $ADMIN->search
= $oldsearch;
4259 if ($requirefulltree) {
4260 $ADMIN->fulltree
= true;
4262 $ADMIN->fulltree
= $oldfulltree;
4265 // we process this file first to create categories first and in correct order
4266 require($CFG->dirroot
.'/'.$CFG->admin
.'/settings/top.php');
4268 // now we process all other files in admin/settings to build the admin tree
4269 foreach (glob($CFG->dirroot
.'/'.$CFG->admin
.'/settings/*.php') as $file) {
4270 if ($file != $CFG->dirroot
.'/'.$CFG->admin
.'/settings/top.php') {
4274 if (file_exists($CFG->dirroot
.'/local/settings.php')) {
4275 include_once($CFG->dirroot
.'/local/settings.php');
4282 /// settings utility functions
4285 * This function applies default settings.
4286 * @param object $node, NULL means complete tree
4287 * @param bool $uncoditional if true overrides all values with defaults
4290 function admin_apply_default_settings($node=NULL, $unconditional=true) {
4293 if (is_null($node)) {
4294 $node =& admin_get_root();
4297 if (is_a($node, 'admin_category')) {
4298 $entries = array_keys($node->children
);
4299 foreach ($entries as $entry) {
4300 admin_apply_default_settings($node->children
[$entry], $unconditional);
4303 } else if (is_a($node, 'admin_settingpage')) {
4304 foreach ($node->settings
as $setting) {
4305 if (!$unconditional and !is_null($setting->get_setting())) {
4306 //do not override existing defaults
4309 $defaultsetting = $setting->get_defaultsetting();
4310 if (is_null($defaultsetting)) {
4311 // no value yet - default maybe applied after admin user creation or in upgradesettings
4314 $setting->write_setting($defaultsetting);
4320 * Store changed settings, this function updates the errors variable in $ADMIN
4321 * @param object $formdata from form (without magic quotes)
4322 * @return int number of changed settings
4324 function admin_write_settings($formdata) {
4325 global $CFG, $SITE, $COURSE;
4327 $olddbsessions = !empty($CFG->dbsessions
);
4328 $formdata = (array)stripslashes_recursive($formdata);
4331 foreach ($formdata as $fullname=>$value) {
4332 if (strpos($fullname, 's_') !== 0) {
4333 continue; // not a config value
4335 $data[$fullname] = $value;
4338 $adminroot =& admin_get_root();
4339 $settings = admin_find_write_settings($adminroot, $data);
4342 foreach ($settings as $fullname=>$setting) {
4343 $original = serialize($setting->get_setting()); // comparison must work for arrays too
4344 $error = $setting->write_setting($data[$fullname]);
4345 if ($error !== '') {
4346 $adminroot->errors
[$fullname] = new object();
4347 $adminroot->errors
[$fullname]->data
= $data[$fullname];
4348 $adminroot->errors
[$fullname]->id
= $setting->get_id();
4349 $adminroot->errors
[$fullname]->error
= $error;
4351 if ($original !== serialize($setting->get_setting())) {
4353 $callbackfunction = $setting->updatedcallback
;
4354 if (function_exists($callbackfunction)) {
4355 $callbackfunction($fullname);
4360 if ($olddbsessions != !empty($CFG->dbsessions
)) {
4364 // now update $SITE - it might have been changed
4365 $SITE = get_record('course', 'id', $SITE->id
);
4366 $COURSE = clone($SITE);
4368 // now reload all settings - some of them might depend on the changed
4369 admin_get_root(true);
4374 * Internal recursive function - finds all settings from submitted form
4376 function admin_find_write_settings($node, $data) {
4383 if (is_a($node, 'admin_category')) {
4384 $entries = array_keys($node->children
);
4385 foreach ($entries as $entry) {
4386 $return = array_merge($return, admin_find_write_settings($node->children
[$entry], $data));
4389 } else if (is_a($node, 'admin_settingpage')) {
4390 foreach ($node->settings
as $setting) {
4391 $fullname = $setting->get_full_name();
4392 if (array_key_exists($fullname, $data)) {
4393 $return[$fullname] = $setting;
4403 * Internal function - prints the search results
4405 function admin_search_settings_html($query) {
4408 $textlib = textlib_get_instance();
4409 if ($textlib->strlen($query) < 2) {
4412 $query = $textlib->strtolower($query);
4414 $adminroot =& admin_get_root();
4415 $findings = $adminroot->search($query);
4417 $savebutton = false;
4419 foreach ($findings as $found) {
4420 $page = $found->page
;
4421 $settings = $found->settings
;
4422 if ($page->is_hidden()) {
4423 // hidden pages are not displayed in search results
4426 if (is_a($page, 'admin_externalpage')) {
4427 $return .= print_heading(get_string('searchresults','admin').' - <a href="'.$page->url
.'">'.highlight($query, $page->visiblename
).'</a>', '', 2, 'main', true);
4428 } else if (is_a($page, 'admin_settingpage')) {
4429 $return .= print_heading(get_string('searchresults','admin').' - <a href="'.$CFG->wwwroot
.'/'.$CFG->admin
.'/settings.php?section='.$page->name
.'">'.highlight($query, $page->visiblename
).'</a>', '', 2, 'main', true);
4433 if (!empty($settings)) {
4435 $return .= '<fieldset class="adminsettings">'."\n";
4436 foreach ($settings as $setting) {
4437 $return .= '<div class="clearer"><!-- --></div>'."\n";
4438 $fullname = $setting->get_full_name();
4439 if (array_key_exists($fullname, $adminroot->errors
)) {
4440 $data = $adminroot->errors
[$fullname]->data
;
4442 $data = $setting->get_setting();
4443 if (is_null($data)) {
4444 $data = $setting->get_defaultsetting();
4447 $return .= $setting->output_html($data, $query);
4449 $return .= '</fieldset>';
4454 $return .= '<div class="form-buttons"><input class="form-submit" type="submit" value="'.get_string('savechanges','admin').'" /></div>';
4461 * Internal function - returns arrays of html pages with uninitialised settings
4463 function admin_output_new_settings_by_page($node) {
4466 if (is_a($node, 'admin_category')) {
4467 $entries = array_keys($node->children
);
4468 foreach ($entries as $entry) {
4469 $return +
= admin_output_new_settings_by_page($node->children
[$entry]);
4472 } else if (is_a($node, 'admin_settingpage')) {
4473 $newsettings = array();
4474 foreach ($node->settings
as $setting) {
4475 if (is_null($setting->get_setting())) {
4476 $newsettings[] = $setting;
4479 if (count($newsettings) > 0) {
4480 $adminroot =& admin_get_root();
4481 $page = print_heading(get_string('upgradesettings','admin').' - '.$node->visiblename
, '', 2, 'main', true);
4482 $page .= '<fieldset class="adminsettings">'."\n";
4483 foreach ($newsettings as $setting) {
4484 $fullname = $setting->get_full_name();
4485 if (array_key_exists($fullname, $adminroot->errors
)) {
4486 $data = $adminroot->errors
[$fullname]->data
;
4488 $data = $setting->get_setting();
4489 if (is_null($data)) {
4490 $data = $setting->get_defaultsetting();
4493 $page .= '<div class="clearer"><!-- --></div>'."\n";
4494 $page .= $setting->output_html($data);
4496 $page .= '</fieldset>';
4497 $return[$node->name
] = $page;
4505 * Unconditionally applies default admin settings in main config table
4506 * @param array $defaults array of string values
4508 function apply_default_exception_settings($defaults) {
4509 foreach($defaults as $key => $value) {
4510 set_config($key, $value, NULL);
4515 * Format admin settings
4516 * @param string $object setting
4517 * @param string $title label element
4518 * @param string $form form fragment, html code - not highlighed automaticaly
4519 * @param string $description
4520 * @param bool $label link label to id
4521 * @param string $warning warning text
4522 * @param sting $defaultinfo defaults info, null means nothing, '' is converted to "Empty" string
4523 * @param string $query search query to be highlighted
4525 function format_admin_setting($setting, $title='', $form='', $description='', $label=true, $warning='', $defaultinfo=NULL, $query='') {
4528 $name = $setting->name
;
4529 $fullname = $setting->get_full_name();
4531 // sometimes the id is not id_s_name, but id_s_name_m or something, and this does not validate
4533 $labelfor = 'for = "'.$setting->get_id().'"';
4538 if (empty($setting->plugin
) and array_key_exists($name, $CFG->config_php_settings
)) {
4539 $override = '<div class="form-overridden">'.get_string('configoverride', 'admin').'</div>';
4544 if ($warning !== '') {
4545 $warning = '<div class="form-warning">'.$warning.'</div>';
4548 if (is_null($defaultinfo)) {
4551 if ($defaultinfo === '') {
4552 $defaultinfo = get_string('emptysettingvalue', 'admin');
4554 $defaultinfo = highlight($query, nl2br(s($defaultinfo)));
4555 $defaultinfo = '<div class="form-defaultinfo">'.get_string('defaultsettinginfo', 'admin', $defaultinfo).'</div>';
4560 <div class="form-item clearfix" id="admin-'.$setting->name
.'">
4561 <div class="form-label">
4562 <label '.$labelfor.'>'.highlightfast($query, $title).'<span class="form-shortname">'.highlightfast($query, $name).'</span>
4563 '.$override.$warning.'
4566 <div class="form-setting">'.$form.$defaultinfo.'</div>
4567 <div class="form-description">'.highlight($query, $description).'</div>
4570 $adminroot =& admin_get_root();
4571 if (array_key_exists($fullname, $adminroot->errors
)) {
4572 $str = '<fieldset class="error"><legend>'.$adminroot->errors
[$fullname]->error
.'</legend>'.$str.'</fieldset>';
4579 * Try to upgrade the given language pack (or current language)
4580 * If it doesn't work, fail silently and return false
4582 function upgrade_language_pack($lang='') {
4586 $lang = current_language();
4589 if ($lang == 'en_utf8') {
4590 return true; // Nothing to do
4593 notify(get_string('langimport', 'admin').': '.$lang.' ... ', 'notifysuccess');
4595 @mkdir
($CFG->dataroot
.'/temp/'); //make it in case it's a fresh install, it might not be there
4596 @mkdir
($CFG->dataroot
.'/lang/');
4598 require_once($CFG->libdir
.'/componentlib.class.php');
4600 if ($cd = new component_installer('http://download.moodle.org', 'lang16', $lang.'.zip', 'languages.md5', 'lang')) {
4601 $status = $cd->install(); //returns COMPONENT_(ERROR | UPTODATE | INSTALLED)
4603 if ($status == COMPONENT_INSTALLED
) {
4604 debugging('Downloading successful: '.$lang);
4605 @unlink
($CFG->dataroot
.'/cache/languages');
4614 * Based on find_new_settings{@link ()} in upgradesettings.php
4615 * Looks to find any admin settings that have not been initialized. Returns 1 if it finds any.
4617 * @param string $node The node at which to start searching.
4618 * @return boolen true if any settings haven't been initialised, false if they all have
4620 function any_new_admin_settings($node) {
4622 if (is_a($node, 'admin_category')) {
4623 $entries = array_keys($node->children
);
4624 foreach ($entries as $entry) {
4625 if (any_new_admin_settings($node->children
[$entry])){
4630 } else if (is_a($node, 'admin_settingpage')) {
4631 foreach ($node->settings
as $setting) {
4632 if ($setting->get_setting() === NULL) {
4643 * Moved from admin/replace.php so that we can use this in cron
4644 * @param string $search - string to look for (with magic quotes)
4645 * @param string $replace - string to replace (with magic quotes)
4646 * @return bool - success or fail
4648 function db_replace($search, $replace) {
4652 /// Turn off time limits, sometimes upgrades can be slow.
4654 @ob_implicit_flush
(true);
4655 while(@ob_end_flush
());
4657 if (!$tables = $db->Metatables() ) { // No tables yet at all.
4660 foreach ($tables as $table) {
4662 if (in_array($table, array($CFG->prefix
.'config'))) { // Don't process these
4666 if ($columns = $db->MetaColumns($table, false)) {
4667 foreach ($columns as $column => $data) {
4668 if (in_array($data->type
, array('text','mediumtext','longtext','varchar'))) { // Text stuff only
4670 execute_sql("UPDATE $table SET $column = REPLACE($column, '$search', '$replace');");
4681 * Prints tables of detected plugins, one table per plugin type,
4682 * and prints whether they are part of the standard Moodle
4683 * distribution or not.
4685 function print_plugin_tables() {
4686 $plugins_standard = array();
4687 $plugins_standard['mod'] = array('assignment',
4706 $plugins_standard['blocks'] = array('activity_modules',
4713 'calendar_upcoming',
4733 'social_activities',
4738 $plugins_standard['filter'] = array('activitynames',
4748 $plugins_installed = array();
4749 $installed_mods = get_records_list('modules', '', '', '', 'name');
4750 $installed_blocks = get_records_list('block', '', '', '', 'name');
4752 foreach($installed_mods as $mod) {
4753 $plugins_installed['mod'][] = $mod->name
;
4756 foreach($installed_blocks as $block) {
4757 $plugins_installed['blocks'][] = $block->name
;
4760 $plugins_ondisk = array();
4761 $plugins_ondisk['mod'] = get_list_of_plugins('mod', 'db');
4762 $plugins_ondisk['blocks'] = get_list_of_plugins('blocks', 'db');
4763 $plugins_ondisk['filter'] = get_list_of_plugins('filter', 'db');
4765 $strstandard = get_string('standard');
4766 $strnonstandard = get_string('nonstandard');
4767 $strmissingfromdisk = '(' . get_string('missingfromdisk') . ')';
4768 $strabouttobeinstalled = '(' . get_string('abouttobeinstalled') . ')';
4772 $html .= '<table class="generaltable plugincheckwrapper" cellspacing="4" cellpadding="1"><tr valign="top">';
4774 foreach ($plugins_ondisk as $cat => $list_ondisk) {
4775 $strcaption = get_string($cat);
4776 if ($cat == 'mod') {
4777 $strcaption = get_string('activitymodule');
4778 } elseif ($cat == 'filter') {
4779 $strcaption = get_string('managefilters');
4782 $html .= '<td><table class="plugincompattable generaltable boxaligncenter" cellspacing="1" cellpadding="5" '
4783 . 'id="' . $cat . 'compattable" summary="compatibility table"><caption>' . $strcaption . '</caption>' . "\n";
4784 $html .= '<tr class="r0"><th class="header c0">' . get_string('directory') . "</th>\n"
4785 . '<th class="header c1">' . get_string('name') . "</th>\n"
4786 . '<th class="header c2">' . get_string('status') . "</th>\n</tr>\n";
4790 foreach ($list_ondisk as $k => $plugin) {
4792 $standard = 'standard';
4795 if (!in_array($plugin, $plugins_standard[$cat])) {
4796 $standard = 'nonstandard';
4797 $status = 'warning';
4800 // Get real name and full path of plugin
4801 $plugin_name = "[[$plugin]]";
4803 $plugin_path = "$cat/$plugin";
4805 $plugin_name = get_plugin_name($plugin, $cat);
4807 // Determine if the plugin is about to be installed
4808 if ($cat != 'filter' && !in_array($plugin, $plugins_installed[$cat])) {
4809 $note = $strabouttobeinstalled;
4810 $plugin_name = $plugin;
4813 $html .= "<tr class=\"r$row\">\n"
4814 . "<td class=\"cell c0\">$plugin_path</td>\n"
4815 . "<td class=\"cell c1\">$plugin_name</td>\n"
4816 . "<td class=\"$standard $status cell c2\">" . $
{'str' . $standard} . " $note</td>\n</tr>\n";
4819 // If the plugin was both on disk and in the db, unset the value from the installed plugins list
4820 if ($key = array_search($plugin, $plugins_installed[$cat])) {
4821 unset($plugins_installed[$cat][$key]);
4825 // If there are plugins left in the plugins_installed list, it means they are missing from disk
4826 foreach ($plugins_installed[$cat] as $k => $missing_plugin) {
4827 // Make sure the plugin really is missing from disk
4828 if (!in_array($missing_plugin, $plugins_ondisk[$cat])) {
4829 $standard = 'standard';
4830 $status = 'warning';
4832 if (!in_array($missing_plugin, $plugins_standard[$cat])) {
4833 $standard = 'nonstandard';
4836 $plugin_name = $missing_plugin;
4837 $html .= "<tr class=\"r$row\">\n"
4838 . "<td class=\"cell c0\">?</td>\n"
4839 . "<td class=\"cell c1\">$plugin_name</td>\n"
4840 . "<td class=\"$standard $status cell c2\">" . $
{'str' . $standard} . " $strmissingfromdisk</td>\n</tr>\n";
4845 $html .= '</table></td>';
4848 $html .= '</tr></table><br />';