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 function upgrade_main_savepoint($result, $version) {
16 if ($CFG->version
>= $version) {
17 // something really wrong is going on in main upgrade script
18 error("Upgrade savepoint: Can not upgrade main version from $CFG->version to $version.");
20 set_config('version', $version);
22 notify ("Upgrade savepoint: Error during main upgrade to version $version");
26 function upgrade_mod_savepoint($result, $version, $type) {
30 function upgrade_plugin_savepoint($result, $version, $type, $dir) {
34 function upgrade_backup_savepoint($result, $version) {
38 function upgrade_blocks_savepoint($result, $version, $type) {
47 * @param string $type The type of plugins that should be updated (e.g. 'enrol', 'qtype')
48 * @param string $dir The directory where the plugins are located (e.g. 'question/questiontypes')
49 * @param string $return The url to prompt the user to continue to
51 function upgrade_plugins($type, $dir, $return) {
54 /// Let's know if the header has been printed, so the funcion is being called embedded in an outer page
55 $embedded = defined('HEADER_PRINTED');
57 $plugs = get_list_of_plugins($dir);
58 $updated_plugins = false;
59 $strpluginsetup = get_string('pluginsetup');
61 foreach ($plugs as $plug) {
63 $fullplug = $CFG->dirroot
.'/'.$dir.'/'. $plug;
67 if (is_readable($fullplug .'/version.php')) {
68 include_once($fullplug .'/version.php'); // defines $plugin with version etc
70 continue; // Nothing to do.
75 if (is_readable($fullplug . '/db/'. $CFG->dbtype
. '.php')) {
76 include_once($fullplug . '/db/'. $CFG->dbtype
. '.php'); // defines old upgrading function
79 if (is_readable($fullplug . '/db/upgrade.php')) {
80 include_once($fullplug . '/db/upgrade.php'); // defines new upgrading function
84 if (!isset($plugin)) {
88 if (!empty($plugin->requires
)) {
89 if ($plugin->requires
> $CFG->version
) {
91 $info->pluginname
= $plug;
92 $info->pluginversion
= $plugin->version
;
93 $info->currentmoodle
= $CFG->version
;
94 $info->requiremoodle
= $plugin->requires
;
95 if (!$updated_plugins && !$embedded) {
96 print_header($strpluginsetup, $strpluginsetup,
97 build_navigation(array(array('name' => $strpluginsetup, 'link' => null, 'type' => 'misc'))), '',
98 upgrade_get_javascript(), false, ' ', ' ');
101 notify(get_string('pluginrequirementsnotmet', 'error', $info));
102 $updated_plugins = true;
107 $plugin->name
= $plug; // The name MUST match the directory
109 $pluginversion = $type.'_'.$plug.'_version';
111 if (!isset($CFG->$pluginversion)) {
112 set_config($pluginversion, 0);
115 if ($CFG->$pluginversion == $plugin->version
) {
117 } else if ($CFG->$pluginversion < $plugin->version
) {
118 if (!$updated_plugins && !$embedded) {
119 print_header($strpluginsetup, $strpluginsetup,
120 build_navigation(array(array('name' => $strpluginsetup, 'link' => null, 'type' => 'misc'))), '',
121 upgrade_get_javascript(), false, ' ', ' ');
123 $updated_plugins = true;
125 print_heading($dir.'/'. $plugin->name
.' plugin needs upgrading');
127 @set_time_limit
(0); // To allow slow databases to complete the long SQL
129 if ($CFG->$pluginversion == 0) { // It's a new install of this plugin
130 /// Both old .sql files and new install.xml are supported
131 /// but we priorize install.xml (XMLDB) if present
133 if (file_exists($fullplug . '/db/install.xml')) {
134 $status = install_from_xmldb_file($fullplug . '/db/install.xml'); //New method
135 } else if (file_exists($fullplug .'/db/'. $CFG->dbtype
.'.sql')) {
136 $status = modify_database($fullplug .'/db/'. $CFG->dbtype
.'.sql'); //Old method
142 /// Continue with the instalation, roles and other stuff
144 /// OK so far, now update the plugins record
145 set_config($pluginversion, $plugin->version
);
147 /// Install capabilities
148 if (!update_capabilities($type.'/'.$plug)) {
149 error('Could not set up the capabilities for '.$plugin->name
.'!');
152 events_update_definition($type.'/'.$plug);
154 /// Run local install function if there is one
155 if (is_readable($fullplug .'/lib.php')) {
156 include_once($fullplug .'/lib.php');
157 $installfunction = $plugin->name
.'_install';
158 if (function_exists($installfunction)) {
159 if (! $installfunction() ) {
160 notify('Encountered a problem running install function for '.$module->name
.'!');
165 notify(get_string('modulesuccess', '', $plugin->name
), 'notifysuccess');
167 notify('Installing '. $plugin->name
.' FAILED!');
169 } else { // Upgrade existing install
170 /// Run de old and new upgrade functions for the module
171 $oldupgrade_function = $type.'_'.$plugin->name
.'_upgrade';
172 $newupgrade_function = 'xmldb_' . $type.'_'.$plugin->name
.'_upgrade';
174 /// First, the old function if exists
175 $oldupgrade_status = true;
176 if ($oldupgrade && function_exists($oldupgrade_function)) {
178 $oldupgrade_status = $oldupgrade_function($CFG->$pluginversion);
179 } else if ($oldupgrade) {
180 notify ('Upgrade function ' . $oldupgrade_function . ' was not available in ' .
181 $fullplug . '/db/' . $CFG->dbtype
. '.php');
184 /// Then, the new function if exists and the old one was ok
185 $newupgrade_status = true;
186 if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) {
188 $newupgrade_status = $newupgrade_function($CFG->$pluginversion);
189 } else if ($newupgrade) {
190 notify ('Upgrade function ' . $newupgrade_function . ' was not available in ' .
191 $fullplug . '/db/upgrade.php');
195 /// Now analyze upgrade results
196 if ($oldupgrade_status && $newupgrade_status) { // No upgrading failed
197 // OK so far, now update the plugins record
198 set_config($pluginversion, $plugin->version
);
199 if (!update_capabilities($type.'/'.$plug)) {
200 error('Could not update '.$plugin->name
.' capabilities!');
202 events_update_definition($type.'/'.$plug);
203 notify(get_string('modulesuccess', '', $plugin->name
), 'notifysuccess');
205 notify('Upgrading '. $plugin->name
.' from '. $CFG->$pluginversion .' to '. $plugin->version
.' FAILED!');
211 error('Version mismatch: '. $plugin->name
.' can\'t downgrade '. $CFG->$pluginversion .' -> '. $plugin->version
.' !');
215 upgrade_log_finish();
217 if ($updated_plugins && !$embedded) {
218 print_continue($return);
219 print_footer('none');
225 * Find and check all modules and load them up or upgrade them if necessary
229 * @param string $return The url to prompt the user to continue to
230 * @todo Finish documenting this function
232 function upgrade_activity_modules($return) {
236 if (!$mods = get_list_of_plugins('mod') ) {
237 error('No modules installed!');
240 $updated_modules = false;
241 $strmodulesetup = get_string('modulesetup');
243 foreach ($mods as $mod) {
245 if ($mod == 'NEWMODULE') { // Someone has unzipped the template, ignore it
249 $fullmod = $CFG->dirroot
.'/mod/'. $mod;
253 if ( is_readable($fullmod .'/version.php')) {
254 include_once($fullmod .'/version.php'); // defines $module with version etc
256 notify('Module '. $mod .': '. $fullmod .'/version.php was not readable');
262 if ( is_readable($fullmod .'/db/' . $CFG->dbtype
. '.php')) {
263 include_once($fullmod .'/db/' . $CFG->dbtype
. '.php'); // defines old upgrading function
266 if ( is_readable($fullmod . '/db/upgrade.php')) {
267 include_once($fullmod . '/db/upgrade.php'); // defines new upgrading function
271 if (!isset($module)) {
275 if (!empty($module->requires
)) {
276 if ($module->requires
> $CFG->version
) {
277 $info = new object();
278 $info->modulename
= $mod;
279 $info->moduleversion
= $module->version
;
280 $info->currentmoodle
= $CFG->version
;
281 $info->requiremoodle
= $module->requires
;
282 if (!$updated_modules) {
283 print_header($strmodulesetup, $strmodulesetup,
284 build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '',
285 upgrade_get_javascript(), false, ' ', ' ');
288 notify(get_string('modulerequirementsnotmet', 'error', $info));
289 $updated_modules = true;
294 $module->name
= $mod; // The name MUST match the directory
296 include_once($fullmod.'/lib.php'); // defines upgrading and/or installing functions
298 if ($currmodule = get_record('modules', 'name', $module->name
)) {
299 if ($currmodule->version
== $module->version
) {
301 } else if ($currmodule->version
< $module->version
) {
302 /// If versions say that we need to upgrade but no upgrade files are available, notify and continue
303 if (!$oldupgrade && !$newupgrade) {
304 notify('Upgrade files ' . $mod . ': ' . $fullmod . '/db/' . $CFG->dbtype
. '.php or ' .
305 $fullmod . '/db/upgrade.php were not readable');
308 if (!$updated_modules) {
309 print_header($strmodulesetup, $strmodulesetup,
310 build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '',
311 upgrade_get_javascript(), false, ' ', ' ');
314 print_heading($module->name
.' module needs upgrading');
316 /// Run de old and new upgrade functions for the module
317 $oldupgrade_function = $module->name
. '_upgrade';
318 $newupgrade_function = 'xmldb_' . $module->name
. '_upgrade';
320 /// First, the old function if exists
321 $oldupgrade_status = true;
322 if ($oldupgrade && function_exists($oldupgrade_function)) {
324 $oldupgrade_status = $oldupgrade_function($currmodule->version
, $module);
325 if (!$oldupgrade_status) {
326 notify ('Upgrade function ' . $oldupgrade_function .
327 ' did not complete successfully.');
329 } else if ($oldupgrade) {
330 notify ('Upgrade function ' . $oldupgrade_function . ' was not available in ' .
331 $mod . ': ' . $fullmod . '/db/' . $CFG->dbtype
. '.php');
334 /// Then, the new function if exists and the old one was ok
335 $newupgrade_status = true;
336 if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) {
338 $newupgrade_status = $newupgrade_function($currmodule->version
, $module);
339 } else if ($newupgrade && $oldupgrade_status) {
340 notify ('Upgrade function ' . $newupgrade_function . ' was not available in ' .
341 $mod . ': ' . $fullmod . '/db/upgrade.php');
345 /// Now analyze upgrade results
346 if ($oldupgrade_status && $newupgrade_status) { // No upgrading failed
347 // OK so far, now update the modules record
348 $module->id
= $currmodule->id
;
349 if (! update_record('modules', $module)) {
350 error('Could not update '. $module->name
.' record in modules table!');
352 remove_dir($CFG->dataroot
. '/cache', true); // flush cache
353 notify(get_string('modulesuccess', '', $module->name
), 'notifysuccess');
356 notify('Upgrading '. $module->name
.' from '. $currmodule->version
.' to '. $module->version
.' FAILED!');
359 /// Update the capabilities table?
360 if (!update_capabilities('mod/'.$module->name
)) {
361 error('Could not update '.$module->name
.' capabilities!');
363 events_update_definition('mod/'.$module->name
);
365 $updated_modules = true;
369 error('Version mismatch: '. $module->name
.' can\'t downgrade '. $currmodule->version
.' -> '. $module->version
.' !');
372 } else { // module not installed yet, so install it
373 if (!$updated_modules) {
374 print_header($strmodulesetup, $strmodulesetup,
375 build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '',
376 upgrade_get_javascript(), false, ' ', ' ');
379 print_heading($module->name
);
380 $updated_modules = true;
382 @set_time_limit
(0); // To allow slow databases to complete the long SQL
384 /// Both old .sql files and new install.xml are supported
385 /// but we priorize install.xml (XMLDB) if present
386 if (file_exists($fullmod . '/db/install.xml')) {
387 $status = install_from_xmldb_file($fullmod . '/db/install.xml'); //New method
389 $status = modify_database($fullmod .'/db/'. $CFG->dbtype
.'.sql'); //Old method
394 /// Continue with the installation, roles and other stuff
396 if ($module->id
= insert_record('modules', $module)) {
399 if (!update_capabilities('mod/'.$module->name
)) {
400 error('Could not set up the capabilities for '.$module->name
.'!');
404 events_update_definition('mod/'.$module->name
);
406 /// Run local install function if there is one
407 $installfunction = $module->name
.'_install';
408 if (function_exists($installfunction)) {
409 if (! $installfunction() ) {
410 notify('Encountered a problem running install function for '.$module->name
.'!');
414 notify(get_string('modulesuccess', '', $module->name
), 'notifysuccess');
417 error($module->name
.' module could not be added to the module list!');
420 error($module->name
.' tables could NOT be set up successfully!');
424 /// Check submodules of this module if necessary
426 $submoduleupgrade = $module->name
.'_upgrade_submodules';
427 if (function_exists($submoduleupgrade)) {
432 /// Run any defaults or final code that is necessary for this module
434 if ( is_readable($fullmod .'/defaults.php')) {
435 // Insert default values for any important configuration variables
437 include($fullmod .'/defaults.php'); // include here means execute, not library include
438 if (!empty($defaults)) {
439 foreach ($defaults as $name => $value) {
440 if (!isset($CFG->$name)) {
441 set_config($name, $value);
448 upgrade_log_finish(); // finish logging if started
450 if ($updated_modules) {
451 print_continue($return);
452 print_footer('none');
458 * Try to obtain or release the cron lock.
460 * @param string $name name of lock
461 * @param int $until timestamp when this lock considered stale, null means remove lock unconditionaly
462 * @param bool $ignorecurrent ignore current lock state, usually entend previous lock
463 * @return bool true if lock obtained
465 function set_cron_lock($name, $until, $ignorecurrent=false) {
467 debugging("Tried to get a cron lock for a null fieldname");
471 // remove lock by force == remove from config table
472 if (is_null($until)) {
473 set_config($name, null);
477 if (!$ignorecurrent) {
478 // read value from db - other processes might have changed it
479 $value = get_field('config', 'value', 'name', $name);
481 if ($value and $value > time()) {
487 set_config($name, $until);
491 function print_progress($done, $total, $updatetime=5, $sleeptime=1, $donetext='') {
496 if ($total < 2) { // No need to show anything
501 if ($done >= $total) {
503 if (!empty($thisbarid)) {
504 $donetext .= ' ('.$done.'/'.$total.') '.get_string('success');
505 print_progress_redraw($thisbarid, $done, $total, 500, $donetext);
506 $thisbarid = $starttime = $lasttime = NULL;
511 if (empty($starttime)) {
512 $starttime = $lasttime = time();
513 $lasttime = $starttime - $updatetime;
514 $thisbarid = uniqid();
515 echo '<table width="500" cellpadding="0" cellspacing="0" align="center"><tr><td width="500">';
516 echo '<div id="bar'.$thisbarid.'" style="border-style:solid;border-width:1px;width:500px;height:50px;">';
517 echo '<div id="slider'.$thisbarid.'" style="border-style:solid;border-width:1px;height:48px;width:10px;background-color:green;"></div>';
519 echo '<div id="text'.$thisbarid.'" align="center" style="width:500px;"></div>';
520 echo '</td></tr></table>';
526 if ($done && (($now - $lasttime) >= $updatetime)) {
527 $elapsedtime = $now - $starttime;
528 $projectedtime = (int)(((float)$total / (float)$done) * $elapsedtime) - $elapsedtime;
529 $percentage = round((float)$done / (float)$total, 2);
530 $width = (int)(500 * $percentage);
532 if ($projectedtime > 10) {
533 $projectedtext = ' Ending: '.format_time($projectedtime);
538 $donetext .= ' ('.$done.'/'.$total.') '.$projectedtext;
539 print_progress_redraw($thisbarid, $done, $total, $width, $donetext);
545 // Don't call this function directly, it's called from print_progress.
546 function print_progress_redraw($thisbarid, $done, $total, $width, $donetext='') {
547 if (empty($thisbarid)) {
551 echo 'document.getElementById("text'.$thisbarid.'").innerHTML = "'.addslashes($donetext).'";'."\n";
552 echo 'document.getElementById("slider'.$thisbarid.'").style.width = \''.$width.'px\';'."\n";
556 function upgrade_get_javascript() {
559 if (!empty($_SESSION['installautopilot'])) {
560 $linktoscrolltoerrors = '<script type="text/javascript">var installautopilot = true;</script>'."\n";
562 $linktoscrolltoerrors = '<script type="text/javascript">var installautopilot = false;</script>'."\n";
564 $linktoscrolltoerrors .= '<script type="text/javascript" src="' . $CFG->wwwroot
. '/lib/scroll_to_errors.js"></script>';
566 return $linktoscrolltoerrors;
569 function create_admin_user() {
572 if (empty($CFG->rolesactive
)) { // No admin user yet.
574 $user = new object();
575 $user->auth
= 'manual';
576 $user->firstname
= get_string('admin');
577 $user->lastname
= get_string('user');
578 $user->username
= 'admin';
579 $user->password
= hash_internal_user_password('admin');
580 $user->email
= 'root@localhost';
581 $user->confirmed
= 1;
582 $user->mnethostid
= $CFG->mnet_localhost_id
;
583 $user->lang
= $CFG->lang
;
584 $user->maildisplay
= 1;
585 $user->timemodified
= time();
587 if (!$user->id
= insert_record('user', $user)) {
588 error('SERIOUS ERROR: Could not create admin user record !!!');
591 if (!$user = get_record('user', 'id', $user->id
)) { // Double check.
592 error('User ID was incorrect (can\'t find it)');
595 // Assign the default admin roles to the new user.
596 if (!$adminroles = get_roles_with_capability('moodle/legacy:admin', CAP_ALLOW
)) {
597 error('No admin role could be found');
599 $sitecontext = get_context_instance(CONTEXT_SYSTEM
);
600 foreach ($adminroles as $adminrole) {
601 role_assign($adminrole->id
, $user->id
, 0, $sitecontext->id
);
604 set_config('rolesactive', 1);
607 $USER = get_complete_user_data('username', 'admin');
608 $USER->newadminuser
= 1;
609 load_all_capabilities();
611 redirect("$CFG->wwwroot/user/editadvanced.php?id=$user->id"); // Edit thyself
613 error('Can not create admin!');
617 ////////////////////////////////////////////////
618 /// upgrade logging functions
619 ////////////////////////////////////////////////
621 $upgradeloghandle = false;
622 $upgradelogbuffer = '';
623 // I did not find out how to use static variable in callback function,
624 // the problem was that I could not flush the static buffer :-(
625 global $upgradeloghandle, $upgradelogbuffer;
628 * Check if upgrade is already running.
630 * If anything goes wrong due to missing call to upgrade_log_finish()
631 * just restart the browser.
633 * @param string warning message indicating upgrade is already running
634 * @param int page reload timeout
636 function upgrade_check_running($message, $timeout) {
637 if (!empty($_SESSION['upgraderunning'])) {
639 redirect(me(), $message, $timeout);
644 * Start logging of output into file (if not disabled) and
645 * prevent aborting and concurrent execution of upgrade script.
647 * Please note that you can not write into session variables after calling this function!
649 * This function may be called repeatedly.
651 function upgrade_log_start() {
652 global $CFG, $upgradeloghandle;
654 if (!empty($_SESSION['upgraderunning'])) {
655 return; // logging already started
658 @ignore_user_abort
(true); // ignore if user stops or otherwise aborts page loading
659 $_SESSION['upgraderunning'] = 1; // set upgrade indicator
660 if (empty($CFG->dbsessions
)) { // workaround for bug in adodb, db session can not be restarted
661 session_write_close(); // from now on user can reload page - will be displayed warning
663 make_upload_directory('upgradelogs');
664 ob_start('upgrade_log_callback', 2); // function for logging to disk; flush each line of text ASAP
665 register_shutdown_function('upgrade_log_finish'); // in case somebody forgets to stop logging
669 * Terminate logging of output, flush all data, allow script aborting
670 * and reopen session for writing. Function error() does terminate the logging too.
672 * Please make sure that each upgrade_log_start() is properly terminated by
673 * this function or error().
675 * This function may be called repeatedly.
677 function upgrade_log_finish() {
678 global $CFG, $upgradeloghandle, $upgradelogbuffer;
680 if (empty($_SESSION['upgraderunning'])) {
681 return; // logging already terminated
685 if ($upgradelogbuffer !== '') {
686 @fwrite
($upgradeloghandle, $upgradelogbuffer);
687 $upgradelogbuffer = '';
689 if ($upgradeloghandle and ($upgradeloghandle !== 'error')) {
690 @fclose
($upgradeloghandle);
691 $upgradeloghandle = false;
693 if (empty($CFG->dbsessions
)) {
694 @session_start
(); // ignore header errors, we only need to reopen session
696 $_SESSION['upgraderunning'] = 0; // clear upgrade indicator
697 if (connection_aborted()) {
700 @ignore_user_abort
(false);
704 * Callback function for logging into files. Not more than one file is created per minute,
705 * upgrade session (terminated by upgrade_log_finish()) is always stored in one file.
707 * This function must not output any characters or throw warnigns and errors!
709 function upgrade_log_callback($string) {
710 global $CFG, $upgradeloghandle, $upgradelogbuffer;
712 if (empty($CFG->disableupgradelogging
) and ($string != '') and ($upgradeloghandle !== 'error')) {
713 if ($upgradeloghandle or ($upgradeloghandle = @fopen
($CFG->dataroot
.'/upgradelogs/upg_'.date('Ymd-Hi').'.html', 'a'))) {
714 $upgradelogbuffer .= $string;
715 if (strlen($upgradelogbuffer) > 2048) { // 2kB write buffer
716 @fwrite
($upgradeloghandle, $upgradelogbuffer);
717 $upgradelogbuffer = '';
720 $upgradeloghandle = 'error';
727 * Try to verify that dataroot is not accessible from web.
728 * It is not 100% correct but might help to reduce number of vulnerable sites.
730 * Protection from httpd.conf and .htaccess is not detected properly.
732 function is_dataroot_insecure() {
735 $siteroot = str_replace('\\', '/', strrev($CFG->dirroot
.'/')); // win32 backslash workaround
737 $rp = preg_replace('|https?://[^/]+|i', '', $CFG->wwwroot
, 1);
738 $rp = strrev(trim($rp, '/'));
739 $rp = explode('/', $rp);
741 if (strpos($siteroot, '/'.$r.'/') === 0) {
742 $siteroot = substr($siteroot, strlen($r)+
1); // moodle web in subdirectory
744 break; // probably alias root
748 $siteroot = strrev($siteroot);
749 $dataroot = str_replace('\\', '/', $CFG->dataroot
.'/');
751 if (strpos($dataroot, $siteroot) === 0) {
757 /// =============================================================================================================
758 /// administration tree classes and functions
761 // n.b. documentation is still in progress for this code
765 /// This file performs the following tasks:
766 /// -it defines the necessary objects and interfaces to build the Moodle
768 /// -it defines the admin_externalpage_setup(), admin_externalpage_print_header(),
769 /// and admin_externalpage_print_footer() functions used on admin pages
771 /// ADMIN_SETTING OBJECTS
773 /// Moodle settings are represented by objects that inherit from the admin_setting
774 /// class. These objects encapsulate how to read a setting, how to write a new value
775 /// to a setting, and how to appropriately display the HTML to modify the setting.
777 /// ADMIN_SETTINGPAGE OBJECTS
779 /// The admin_setting objects are then grouped into admin_settingpages. The latter
780 /// appear in the Moodle admin tree block. All interaction with admin_settingpage
781 /// objects is handled by the admin/settings.php file.
783 /// ADMIN_EXTERNALPAGE OBJECTS
785 /// There are some settings in Moodle that are too complex to (efficiently) handle
786 /// with admin_settingpages. (Consider, for example, user management and displaying
787 /// lists of users.) In this case, we use the admin_externalpage object. This object
788 /// places a link to an external PHP file in the admin tree block.
790 /// If you're using an admin_externalpage object for some settings, you can take
791 /// advantage of the admin_externalpage_* functions. For example, suppose you wanted
792 /// to add a foo.php file into admin. First off, you add the following line to
793 /// admin/settings/first.php (at the end of the file) or to some other file in
796 /// $ADMIN->add('userinterface', new admin_externalpage('foo', get_string('foo'),
797 /// $CFG->wwwdir . '/' . '$CFG->admin . '/foo.php', 'some_role_permission'));
799 /// Next, in foo.php, your file structure would resemble the following:
801 /// require_once('.../config.php');
802 /// require_once($CFG->libdir.'/adminlib.php');
803 /// admin_externalpage_setup('foo');
804 /// // functionality like processing form submissions goes here
805 /// admin_externalpage_print_header();
806 /// // your HTML goes here
807 /// admin_externalpage_print_footer();
809 /// The admin_externalpage_setup() function call ensures the user is logged in,
810 /// and makes sure that they have the proper role permission to access the page.
812 /// The admin_externalpage_print_header() function prints the header (it figures
813 /// out what category and subcategories the page is classified under) and ensures
814 /// that you're using the admin pagelib (which provides the admin tree block and
815 /// the admin bookmarks block).
817 /// The admin_externalpage_print_footer() function properly closes the tables
818 /// opened up by the admin_externalpage_print_header() function and prints the
819 /// standard Moodle footer.
821 /// ADMIN_CATEGORY OBJECTS
823 /// Above and beyond all this, we have admin_category objects. These objects
824 /// appear as folders in the admin tree block. They contain admin_settingpage's,
825 /// admin_externalpage's, and other admin_category's.
829 /// admin_settingpage's, admin_externalpage's, and admin_category's all inherit
830 /// from part_of_admin_tree (a pseudointerface). This interface insists that
831 /// a class has a check_access method for access permissions, a locate method
832 /// used to find a specific node in the admin tree and find parent path.
834 /// admin_category's inherit from parentable_part_of_admin_tree. This pseudo-
835 /// interface ensures that the class implements a recursive add function which
836 /// accepts a part_of_admin_tree object and searches for the proper place to
837 /// put it. parentable_part_of_admin_tree implies part_of_admin_tree.
839 /// Please note that the $this->name field of any part_of_admin_tree must be
840 /// UNIQUE throughout the ENTIRE admin tree.
842 /// The $this->name field of an admin_setting object (which is *not* part_of_
843 /// admin_tree) must be unique on the respective admin_settingpage where it is
847 /// CLASS DEFINITIONS /////////////////////////////////////////////////////////
850 * Pseudointerface for anything appearing in the admin tree
852 * The pseudointerface that is implemented by anything that appears in the admin tree
853 * block. It forces inheriting classes to define a method for checking user permissions
854 * and methods for finding something in the admin tree.
856 * @author Vincenzo K. Marcovecchio
859 class part_of_admin_tree
{
862 * Finds a named part_of_admin_tree.
864 * Used to find a part_of_admin_tree. If a class only inherits part_of_admin_tree
865 * and not parentable_part_of_admin_tree, then this function should only check if
866 * $this->name matches $name. If it does, it should return a reference to $this,
867 * otherwise, it should return a reference to NULL.
869 * If a class inherits parentable_part_of_admin_tree, this method should be called
870 * recursively on all child objects (assuming, of course, the parent object's name
871 * doesn't match the search criterion).
873 * @param string $name The internal name of the part_of_admin_tree we're searching for.
874 * @return mixed An object reference or a NULL reference.
876 function &locate($name) {
877 trigger_error('Admin class does not implement method <strong>locate()</strong>', E_USER_WARNING
);
882 * Removes named part_of_admin_tree.
884 * @param string $name The internal name of the part_of_admin_tree we want to remove.
885 * @return bool success.
887 function prune($name) {
888 trigger_error('Admin class does not implement method <strong>prune()</strong>', E_USER_WARNING
);
895 * @return mixed array-object structure of found settings and pages
897 function search($query) {
898 trigger_error('Admin class does not implement method <strong>search()</strong>', E_USER_WARNING
);
903 * Verifies current user's access to this part_of_admin_tree.
905 * Used to check if the current user has access to this part of the admin tree or
906 * not. If a class only inherits part_of_admin_tree and not parentable_part_of_admin_tree,
907 * then this method is usually just a call to has_capability() in the site context.
909 * If a class inherits parentable_part_of_admin_tree, this method should return the
910 * logical OR of the return of check_access() on all child objects.
912 * @return bool True if the user has access, false if she doesn't.
914 function check_access() {
915 trigger_error('Admin class does not implement method <strong>check_access()</strong>', E_USER_WARNING
);
920 * Mostly usefull for removing of some parts of the tree in admin tree block.
922 * @return True is hidden from normal list view
924 function is_hidden() {
925 trigger_error('Admin class does not implement method <strong>is_hidden()</strong>', E_USER_WARNING
);
931 * Pseudointerface implemented by any part_of_admin_tree that has children.
933 * The pseudointerface implemented by any part_of_admin_tree that can be a parent
934 * to other part_of_admin_tree's. (For now, this only includes admin_category.) Apart
935 * from ensuring part_of_admin_tree compliancy, it also ensures inheriting methods
936 * include an add method for adding other part_of_admin_tree objects as children.
938 * @author Vincenzo K. Marcovecchio
941 class parentable_part_of_admin_tree
extends part_of_admin_tree
{
944 * Adds a part_of_admin_tree object to the admin tree.
946 * Used to add a part_of_admin_tree object to this object or a child of this
947 * object. $something should only be added if $destinationname matches
948 * $this->name. If it doesn't, add should be called on child objects that are
949 * also parentable_part_of_admin_tree's.
951 * @param string $destinationname The internal name of the new parent for $something.
952 * @param part_of_admin_tree &$something The object to be added.
953 * @return bool True on success, false on failure.
955 function add($destinationname, $something) {
956 trigger_error('Admin class does not implement method <strong>add()</strong>', E_USER_WARNING
);
963 * The object used to represent folders (a.k.a. categories) in the admin tree block.
965 * Each admin_category object contains a number of part_of_admin_tree objects.
967 * @author Vincenzo K. Marcovecchio
970 class admin_category
extends parentable_part_of_admin_tree
{
973 * @var mixed An array of part_of_admin_tree objects that are this object's children
978 * @var string An internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
983 * @var string The displayed name for this category. Usually obtained through get_string()
988 * @var bool Should this category be hidden in admin tree block?
999 * Constructor for an empty admin category
1001 * @param string $name The internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
1002 * @param string $visiblename The displayed named for this category. Usually obtained through get_string()
1003 * @param bool $hidden hide category in admin tree block
1005 function admin_category($name, $visiblename, $hidden=false) {
1006 $this->children
= array();
1007 $this->name
= $name;
1008 $this->visiblename
= $visiblename;
1009 $this->hidden
= $hidden;
1013 * Returns a reference to the part_of_admin_tree object with internal name $name.
1015 * @param string $name The internal name of the object we want.
1016 * @param bool $findpath initialize path and visiblepath arrays
1017 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
1019 function &locate($name, $findpath=false) {
1020 if ($this->name
== $name) {
1022 $this->visiblepath
[] = $this->visiblename
;
1023 $this->path
[] = $this->name
;
1029 foreach($this->children
as $childid=>$unused) {
1030 if ($return =& $this->children
[$childid]->locate($name, $findpath)) {
1035 if (!is_null($return) and $findpath) {
1036 $return->visiblepath
[] = $this->visiblename
;
1037 $return->path
[] = $this->name
;
1044 * Search using query
1045 * @param strin query
1046 * @return mixed array-object structure of found settings and pages
1048 function search($query) {
1050 foreach ($this->children
as $child) {
1051 $subsearch = $child->search($query);
1052 if (!is_array($subsearch)) {
1053 debugging('Incorrect search result from '.$child->name
);
1056 $result = array_merge($result, $subsearch);
1062 * Removes part_of_admin_tree object with internal name $name.
1064 * @param string $name The internal name of the object we want to remove.
1065 * @return bool success
1067 function prune($name) {
1069 if ($this->name
== $name) {
1070 return false; //can not remove itself
1073 foreach($this->children
as $precedence => $child) {
1074 if ($child->name
== $name) {
1076 unset($this->children
[$precedence]);
1079 if ($this->children
[$precedence]->prune($name)) {
1087 * Adds a part_of_admin_tree to a child or grandchild (or great-grandchild, and so forth) of this object.
1089 * @param string $destinationame The internal name of the immediate parent that we want for $something.
1090 * @param mixed $something A part_of_admin_tree or setting instanceto be added.
1091 * @return bool True if successfully added, false if $something can not be added.
1093 function add($parentname, $something) {
1094 $parent =& $this->locate($parentname);
1095 if (is_null($parent)) {
1096 debugging('parent does not exist!');
1100 if (is_a($something, 'part_of_admin_tree')) {
1101 if (!is_a($parent, 'parentable_part_of_admin_tree')) {
1102 debugging('error - parts of tree can be inserted only into parentable parts');
1105 $parent->children
[] = $something;
1109 debugging('error - can not add this element');
1116 * Checks if the user has access to anything in this category.
1118 * @return bool True if the user has access to atleast one child in this category, false otherwise.
1120 function check_access() {
1121 foreach ($this->children
as $child) {
1122 if ($child->check_access()) {
1130 * Is this category hidden in admin tree block?
1132 * @return bool True if hidden
1134 function is_hidden() {
1135 return $this->hidden
;
1139 class admin_root
extends admin_category
{
1151 * full tree flag - true means all settings required, false onlypages required
1156 function admin_root() {
1157 parent
::admin_category('root', get_string('administration'), false);
1158 $this->errors
= array();
1160 $this->fulltree
= true;
1165 * Links external PHP pages into the admin tree.
1167 * See detailed usage example at the top of this document (adminlib.php)
1169 * @author Vincenzo K. Marcovecchio
1172 class admin_externalpage
extends part_of_admin_tree
{
1175 * @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects
1180 * @var string The displayed name for this external page. Usually obtained through get_string().
1185 * @var string The external URL that we should link to when someone requests this external page.
1190 * @var string The role capability/permission a user must have to access this external page.
1192 var $req_capability;
1195 * @var object The context in which capability/permission should be checked, default is site context.
1200 * @var bool hidden in admin tree block.
1211 * Constructor for adding an external page into the admin tree.
1213 * @param string $name The internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects.
1214 * @param string $visiblename The displayed name for this external page. Usually obtained through get_string().
1215 * @param string $url The external URL that we should link to when someone requests this external page.
1216 * @param mixed $req_capability The role capability/permission a user must have to access this external page. Defaults to 'moodle/site:config'.
1218 function admin_externalpage($name, $visiblename, $url, $req_capability='moodle/site:config', $hidden=false, $context=NULL) {
1219 $this->name
= $name;
1220 $this->visiblename
= $visiblename;
1222 if (is_array($req_capability)) {
1223 $this->req_capability
= $req_capability;
1225 $this->req_capability
= array($req_capability);
1227 $this->hidden
= $hidden;
1228 $this->context
= $context;
1232 * Returns a reference to the part_of_admin_tree object with internal name $name.
1234 * @param string $name The internal name of the object we want.
1235 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
1237 function &locate($name, $findpath=false) {
1238 if ($this->name
== $name) {
1240 $this->visiblepath
= array($this->visiblename
);
1241 $this->path
= array($this->name
);
1250 function prune($name) {
1255 * Search using query
1256 * @param strin query
1257 * @return mixed array-object structure of found settings and pages
1259 function search($query) {
1260 $textlib = textlib_get_instance();
1263 if (strpos(strtolower($this->name
), $query) !== false) {
1265 } else if (strpos($textlib->strtolower($this->visiblename
), $query) !== false) {
1269 $result = new object();
1270 $result->page
= $this;
1271 $result->settings
= array();
1272 return array($this->name
=> $result);
1279 * Determines if the current user has access to this external page based on $this->req_capability.
1280 * @return bool True if user has access, false otherwise.
1282 function check_access() {
1284 return true; // no access check before site is fully set up
1286 $context = empty($this->context
) ?
get_context_instance(CONTEXT_SYSTEM
) : $this->context
;
1287 foreach($this->req_capability
as $cap) {
1288 if (has_capability($cap, $context)) {
1296 * Is this external page hidden in admin tree block?
1298 * @return bool True if hidden
1300 function is_hidden() {
1301 return $this->hidden
;
1307 * Used to group a number of admin_setting objects into a page and add them to the admin tree.
1309 * @author Vincenzo K. Marcovecchio
1312 class admin_settingpage
extends part_of_admin_tree
{
1315 * @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects
1320 * @var string The displayed name for this external page. Usually obtained through get_string().
1324 * @var mixed An array of admin_setting objects that are part of this setting page.
1329 * @var string The role capability/permission a user must have to access this external page.
1331 var $req_capability;
1334 * @var object The context in which capability/permission should be checked, default is site context.
1339 * @var bool hidden in admin tree block.
1349 // see admin_externalpage
1350 function admin_settingpage($name, $visiblename, $req_capability='moodle/site:config', $hidden=false, $context=NULL) {
1351 $this->settings
= new object();
1352 $this->name
= $name;
1353 $this->visiblename
= $visiblename;
1354 if (is_array($req_capability)) {
1355 $this->req_capability
= $req_capability;
1357 $this->req_capability
= array($req_capability);
1359 $this->hidden
= $hidden;
1360 $this->context
= $context;
1363 // see admin_category
1364 function &locate($name, $findpath=false) {
1365 if ($this->name
== $name) {
1367 $this->visiblepath
= array($this->visiblename
);
1368 $this->path
= array($this->name
);
1377 function search($query) {
1380 foreach ($this->settings
as $setting) {
1381 if ($setting->is_related($query)) {
1382 $found[] = $setting;
1387 $result = new object();
1388 $result->page
= $this;
1389 $result->settings
= $found;
1390 return array($this->name
=> $result);
1393 $textlib = textlib_get_instance();
1396 if (strpos(strtolower($this->name
), $query) !== false) {
1398 } else if (strpos($textlib->strtolower($this->visiblename
), $query) !== false) {
1402 $result = new object();
1403 $result->page
= $this;
1404 $result->settings
= array();
1405 return array($this->name
=> $result);
1411 function prune($name) {
1416 * 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
1417 * n.b. each admin_setting in an admin_settingpage must have a unique internal name
1418 * @param object $setting is the admin_setting object you want to add
1419 * @return true if successful, false if not
1421 function add($setting) {
1422 if (!is_a($setting, 'admin_setting')) {
1423 debugging('error - not a setting instance');
1427 $this->settings
->{$setting->name
} = $setting;
1431 // see admin_externalpage
1432 function check_access() {
1434 return true; // no access check before site is fully set up
1436 $context = empty($this->context
) ?
get_context_instance(CONTEXT_SYSTEM
) : $this->context
;
1437 foreach($this->req_capability
as $cap) {
1438 if (has_capability($cap, $context)) {
1446 * outputs this page as html in a table (suitable for inclusion in an admin pagetype)
1447 * returns a string of the html
1449 function output_html() {
1450 $adminroot =& admin_get_root();
1451 $return = '<fieldset>'."\n".'<div class="clearer"><!-- --></div>'."\n";
1452 foreach($this->settings
as $setting) {
1453 $fullname = $setting->get_full_name();
1454 if (array_key_exists($fullname, $adminroot->errors
)) {
1455 $data = $adminroot->errors
[$fullname]->data
;
1457 $data = $setting->get_setting();
1458 if (is_null($data)) {
1459 $data = $setting->get_defaultsetting();
1462 $return .= $setting->output_html($data);
1464 $return .= '</fieldset>';
1469 * Is this settigns page hidden in admin tree block?
1471 * @return bool True if hidden
1473 function is_hidden() {
1474 return $this->hidden
;
1481 * Admin settings class. Only exists on setting pages.
1482 * Read & write happens at this level; no authentication.
1484 class admin_setting
{
1489 var $defaultsetting;
1490 var $updatedcallback;
1491 var $plugin; // null means main config table
1495 * @param $name string unique ascii name
1496 * @param $visiblename string localised name
1497 * @param strin $description localised long description
1498 * @param mixed $defaultsetting string or array depending on implementation
1500 function admin_setting($name, $visiblename, $description, $defaultsetting) {
1501 $this->name
= $name;
1502 $this->visiblename
= $visiblename;
1503 $this->description
= $description;
1504 $this->defaultsetting
= $defaultsetting;
1507 function get_full_name() {
1508 return 's_'.$this->plugin
.'_'.$this->name
;
1512 return 'id_s_'.$this->plugin
.'_'.$this->name
;
1515 function config_read($name) {
1517 if ($this->plugin
=== 'backup') {
1518 require_once($CFG->dirroot
.'/backup/lib.php');
1519 $backupconfig = backup_get_config();
1520 if (isset($backupconfig->$name)) {
1521 return $backupconfig->$name;
1526 } else if (!empty($this->plugin
)) {
1527 $value = get_config($this->plugin
, $name);
1528 return $value === false ?
NULL : $value;
1531 if (isset($CFG->$name)) {
1539 function config_write($name, $value) {
1541 if ($this->plugin
=== 'backup') {
1542 require_once($CFG->dirroot
.'/backup/lib.php');
1543 return (boolean
)backup_set_config($name, $value);
1545 return (boolean
)set_config($name, $value, $this->plugin
);
1550 * Returns current value of this setting
1551 * @return mixed array or string depending on instance, NULL means not set yet
1553 function get_setting() {
1554 // has to be overridden
1559 * Returns default setting if exists
1560 * @return mixed array or string depending on instance; NULL means no default, user must supply
1562 function get_defaultsetting() {
1563 return $this->defaultsetting
;
1568 * @param mixed string or array, must not be NULL
1569 * @return '' if ok, string error message otherwise
1571 function write_setting($data) {
1572 // should be overridden
1577 * Return part of form with setting
1578 * @param mixed data array or string depending on setting
1581 function output_html($data, $query='') {
1582 // should be overridden
1587 * function called if setting updated - cleanup, cache reset, etc.
1589 function set_updatedcallback($functionname) {
1590 $this->updatedcallback
= $functionname;
1594 * Is setting related to query text - used when searching
1595 * @param string $query
1598 function is_related($query) {
1599 if (strpos(strtolower($this->name
), $query) !== false) {
1602 $textlib = textlib_get_instance();
1603 if (strpos($textlib->strtolower($this->visiblename
), $query) !== false) {
1606 if (strpos($textlib->strtolower($this->description
), $query) !== false) {
1609 $current = $this->get_setting();
1610 if (!is_null($current)) {
1611 if (is_string($current)) {
1612 if (strpos($textlib->strtolower($current), $query) !== false) {
1617 $default = $this->get_defaultsetting();
1618 if (!is_null($default)) {
1619 if (is_string($default)) {
1620 if (strpos($textlib->strtolower($default), $query) !== false) {
1630 * No setting - just heading and text.
1632 class admin_setting_heading
extends admin_setting
{
1634 * not a setting, just text
1635 * @param string $name of setting
1636 * @param string $heading heading
1637 * @param string $information text in box
1639 function admin_setting_heading($name, $heading, $information) {
1640 parent
::admin_setting($name, $heading, $information, '');
1643 function get_setting() {
1647 function get_defaultsetting() {
1651 function write_setting($data) {
1652 // do not write any setting
1656 function output_html($data, $query='') {
1658 if ($this->visiblename
!= '') {
1659 $return .= print_heading('<a name="'.$this->name
.'">'.highlightfast($query, $this->visiblename
).'</a>', '', 3, 'main', true);
1661 if ($this->description
!= '') {
1662 $return .= print_box(highlight($query, $this->description
), 'generalbox formsettingheading', '', true);
1669 * The most flexibly setting, user is typing text
1671 class admin_setting_configtext
extends admin_setting
{
1677 * config text contructor
1678 * @param string $name of setting
1679 * @param string $visiblename localised
1680 * @param string $description long localised info
1681 * @param string $defaultsetting
1682 * @param mixed $paramtype int means PARAM_XXX type, string is a allowed format in regex
1683 * @param int $size default field size
1685 function admin_setting_configtext($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW
, $size=null) {
1686 $this->paramtype
= $paramtype;
1687 if (!is_null($size)) {
1688 $this->size
= $size;
1690 $this->size
= ($paramtype == PARAM_INT
) ?
5 : 30;
1692 parent
::admin_setting($name, $visiblename, $description, $defaultsetting);
1695 function get_setting() {
1696 return $this->config_read($this->name
);
1699 function write_setting($data) {
1700 if ($this->paramtype
=== PARAM_INT
and $data === '') {
1701 // do not complain if '' used instead of 0
1704 // $data is a string
1705 $validated = $this->validate($data);
1706 if ($validated !== true) {
1709 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
1713 * Validate data before storage
1714 * @param string data
1715 * @return mixed true if ok string if error found
1717 function validate($data) {
1718 if (is_string($this->paramtype
)) {
1719 if (preg_match($this->paramtype
, $data)) {
1722 return get_string('validateerror', 'admin');
1725 } else if ($this->paramtype
=== PARAM_RAW
) {
1729 $cleaned = stripslashes(clean_param(addslashes($data), $this->paramtype
));
1730 if ("$data" == "$cleaned") { // implicit conversion to string is needed to do exact comparison
1733 return get_string('validateerror', 'admin');
1738 function output_html($data, $query='') {
1739 $default = $this->get_defaultsetting();
1741 return format_admin_setting($this, $this->visiblename
,
1742 '<div class="form-text defaultsnext"><input type="text" size="'.$this->size
.'" id="'.$this->get_id().'" name="'.$this->get_full_name().'" value="'.s($data).'" /></div>',
1743 $this->description
, true, '', $default, $query);
1748 * General text area without html editor.
1750 class admin_setting_configtextarea
extends admin_setting_configtext
{
1754 function admin_setting_configtextarea($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW
, $cols='60', $rows='8') {
1755 $this->rows
= $rows;
1756 $this->cols
= $cols;
1757 parent
::admin_setting_configtext($name, $visiblename, $description, $defaultsetting, $paramtype);
1760 function output_html($data, $query='') {
1761 $default = $this->get_defaultsetting();
1763 $defaultinfo = $default;
1764 if (!is_null($default) and $default !== '') {
1765 $defaultinfo = "\n".$default;
1768 return format_admin_setting($this, $this->visiblename
,
1769 '<div class="form-textarea" ><textarea rows="'.$this->rows
.'" cols="'.$this->cols
.'" id="'.$this->get_id().'" name="'.$this->get_full_name().'">'.s($data).'</textarea></div>',
1770 $this->description
, true, '', $defaultinfo, $query);
1775 * Password field, allows unmasking of password
1777 class admin_setting_configpasswordunmask
extends admin_setting_configtext
{
1780 * @param string $name of setting
1781 * @param string $visiblename localised
1782 * @param string $description long localised info
1783 * @param string $defaultsetting default password
1785 function admin_setting_configpasswordunmask($name, $visiblename, $description, $defaultsetting) {
1786 parent
::admin_setting_configtext($name, $visiblename, $description, $defaultsetting, PARAM_RAW
, 30);
1789 function output_html($data, $query='') {
1790 $id = $this->get_id();
1791 $unmask = get_string('unmaskpassword', 'form');
1792 $unmaskjs = '<script type="text/javascript">
1794 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>\');
1797 return format_admin_setting($this, $this->visiblename
,
1798 '<div class="form-password"><input type="password" size="'.$this->size
.'" id="'.$this->get_id().'" name="'.$this->get_full_name().'" value="'.s($data).'" />'.$unmaskjs.'</div>',
1799 $this->description
, true, '', NULL, $query);
1806 class admin_setting_configfile
extends admin_setting_configtext
{
1809 * @param string $name of setting
1810 * @param string $visiblename localised
1811 * @param string $description long localised info
1812 * @param string $defaultdirectory default directory location
1814 function admin_setting_configfile($name, $visiblename, $description, $defaultdirectory) {
1815 parent
::admin_setting_configtext($name, $visiblename, $description, $defaultdirectory, PARAM_RAW
, 50);
1818 function output_html($data, $query='') {
1819 $default = $this->get_defaultsetting();
1822 if (file_exists($data)) {
1823 $executable = '<span class="pathok">✔</span>';
1825 $executable = '<span class="patherror">✘</span>';
1831 return format_admin_setting($this, $this->visiblename
,
1832 '<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>',
1833 $this->description
, true, '', $default, $query);
1838 * Path to executable file
1840 class admin_setting_configexecutable
extends admin_setting_configfile
{
1842 function output_html($data, $query='') {
1843 $default = $this->get_defaultsetting();
1846 if (file_exists($data) and is_executable($data)) {
1847 $executable = '<span class="pathok">✔</span>';
1849 $executable = '<span class="patherror">✘</span>';
1855 return format_admin_setting($this, $this->visiblename
,
1856 '<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>',
1857 $this->description
, true, '', $default, $query);
1864 class admin_setting_configdirectory
extends admin_setting_configfile
{
1865 function output_html($data, $query='') {
1866 $default = $this->get_defaultsetting();
1869 if (file_exists($data) and is_dir($data)) {
1870 $executable = '<span class="pathok">✔</span>';
1872 $executable = '<span class="patherror">✘</span>';
1878 return format_admin_setting($this, $this->visiblename
,
1879 '<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>',
1880 $this->description
, true, '', $default, $query);
1887 class admin_setting_configcheckbox
extends admin_setting
{
1893 * @param string $name of setting
1894 * @param string $visiblename localised
1895 * @param string $description long localised info
1896 * @param string $defaultsetting
1897 * @param string $yes value used when checked
1898 * @param string $no value used when not checked
1900 function admin_setting_configcheckbox($name, $visiblename, $description, $defaultsetting, $yes='1', $no='0') {
1901 parent
::admin_setting($name, $visiblename, $description, $defaultsetting);
1902 $this->yes
= (string)$yes;
1903 $this->no
= (string)$no;
1906 function get_setting() {
1907 return $this->config_read($this->name
);
1910 function write_setting($data) {
1911 if ((string)$data === $this->yes
) { // convert to strings before comparison
1916 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
1919 function output_html($data, $query='') {
1920 $default = $this->get_defaultsetting();
1922 if (!is_null($default)) {
1923 if ((string)$default === $this->yes
) {
1924 $defaultinfo = get_string('checkboxyes', 'admin');
1926 $defaultinfo = get_string('checkboxno', 'admin');
1929 $defaultinfo = NULL;
1932 if ((string)$data === $this->yes
) { // convert to strings before comparison
1933 $checked = 'checked="checked"';
1938 return format_admin_setting($this, $this->visiblename
,
1939 '<div class="form-checkbox defaultsnext" ><input type="hidden" name="'.$this->get_full_name().'" value="'.s($this->no
).'" /> '
1940 .'<input type="checkbox" id="'.$this->get_id().'" name="'.$this->get_full_name().'" value="'.s($this->yes
).'" '.$checked.' /></div>',
1941 $this->description
, true, '', $defaultinfo, $query);
1946 * Multiple checkboxes, each represents different value, stored in csv format
1948 class admin_setting_configmulticheckbox
extends admin_setting
{
1953 * @param string $name of setting
1954 * @param string $visiblename localised
1955 * @param string $description long localised info
1956 * @param array $defaultsetting array of selected
1957 * @param array $choices array of $value=>$label for each checkbox
1959 function admin_setting_configmulticheckbox($name, $visiblename, $description, $defaultsetting, $choices) {
1960 $this->choices
= $choices;
1961 parent
::admin_setting($name, $visiblename, $description, $defaultsetting);
1965 * This function may be used in ancestors for lazy loading of choices
1966 * @return true if loaded, false if error
1968 function load_choices() {
1970 if (is_array($this->choices)) {
1973 .... load choices here
1979 * Is setting related to query text - used when searching
1980 * @param string $query
1983 function is_related($query) {
1984 if (!$this->load_choices() or empty($this->choices
)) {
1987 if (parent
::is_related($query)) {
1991 $textlib = textlib_get_instance();
1992 foreach ($this->choices
as $desc) {
1993 if (strpos($textlib->strtolower($desc), $query) !== false) {
2000 function get_setting() {
2001 $result = $this->config_read($this->name
);
2002 if (is_null($result)) {
2005 if ($result === '') {
2008 return explode(',', $result);
2011 function write_setting($data) {
2012 if (!is_array($data)) {
2013 return ''; // ignore it
2015 if (!$this->load_choices() or empty($this->choices
)) {
2018 unset($data['xxxxx']);
2020 foreach ($data as $key => $value) {
2021 if ($value and array_key_exists($key, $this->choices
)) {
2025 return $this->config_write($this->name
, implode(',', $result)) ?
'' : get_string('errorsetting', 'admin');
2028 function output_html($data, $query='') {
2029 if (!$this->load_choices() or empty($this->choices
)) {
2032 $default = $this->get_defaultsetting();
2033 if (is_null($default)) {
2036 if (is_null($data)) {
2037 foreach ($default as $key=>$value) {
2039 $current[] = $value;
2045 $defaults = array();
2046 foreach($this->choices
as $key=>$description) {
2047 if (in_array($key, $data)) {
2048 $checked = 'checked="checked"';
2052 if (!empty($default[$key])) {
2053 $defaults[] = $description;
2056 $options[] = '<input type="checkbox" id="'.$this->get_id().'_'.$key.'" name="'.$this->get_full_name().'['.$key.']" value="1" '.$checked.' />'
2057 .'<label for="'.$this->get_id().'_'.$key.'">'.highlightfast($query, $description).'</label>';
2060 if (is_null($default)) {
2061 $defaultinfo = NULL;
2062 } else if (!empty($defaults)) {
2063 $defaultinfo = implode(', ', $defaults);
2065 $defaultinfo = get_string('none');
2068 $return = '<div class="form-multicheckbox">';
2069 $return .= '<input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
2072 foreach ($options as $option) {
2073 $return .= '<li>'.$option.'</li>';
2077 $return .= '</div>';
2079 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', $defaultinfo, $query);
2085 * Multiple checkboxes 2, value stored as string 00101011
2087 class admin_setting_configmulticheckbox2
extends admin_setting_configmulticheckbox
{
2088 function get_setting() {
2089 $result = $this->config_read($this->name
);
2090 if (is_null($result)) {
2093 if (!$this->load_choices()) {
2096 $result = str_pad($result, count($this->choices
), '0');
2097 $result = preg_split('//', $result, -1, PREG_SPLIT_NO_EMPTY
);
2099 foreach ($this->choices
as $key=>$unused) {
2100 $value = array_shift($result);
2108 function write_setting($data) {
2109 if (!is_array($data)) {
2110 return ''; // ignore it
2112 if (!$this->load_choices() or empty($this->choices
)) {
2116 foreach ($this->choices
as $key=>$unused) {
2117 if (!empty($data[$key])) {
2123 return $this->config_write($this->name
, $result) ?
'' : get_string('errorsetting', 'admin');
2128 * Select one value from list
2130 class admin_setting_configselect
extends admin_setting
{
2135 * @param string $name of setting
2136 * @param string $visiblename localised
2137 * @param string $description long localised info
2138 * @param string $defaultsetting
2139 * @param array $choices array of $value=>$label for each selection
2141 function admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices) {
2142 $this->choices
= $choices;
2143 parent
::admin_setting($name, $visiblename, $description, $defaultsetting);
2147 * This function may be used in ancestors for lazy loading of choices
2148 * @return true if loaded, false if error
2150 function load_choices() {
2152 if (is_array($this->choices)) {
2155 .... load choices here
2160 function is_related($query) {
2161 if (parent
::is_related($query)) {
2164 if (!$this->load_choices()) {
2167 $textlib = textlib_get_instance();
2168 foreach ($this->choices
as $key=>$value) {
2169 if (strpos($textlib->strtolower($key), $query) !== false) {
2172 if (strpos($textlib->strtolower($value), $query) !== false) {
2179 function get_setting() {
2180 return $this->config_read($this->name
);
2183 function write_setting($data) {
2184 if (!$this->load_choices() or empty($this->choices
)) {
2187 if (!array_key_exists($data, $this->choices
)) {
2188 return ''; // ignore it
2191 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
2194 function output_html($data, $query='') {
2195 if (!$this->load_choices() or empty($this->choices
)) {
2198 $default = $this->get_defaultsetting();
2200 if (!is_null($default) and array_key_exists($default, $this->choices
)) {
2201 $defaultinfo = $this->choices
[$default];
2203 $defaultinfo = NULL;
2206 $current = $this->get_setting();
2208 if (is_null($current)) {
2210 } else if (empty($current) and (array_key_exists('', $this->choices
) or array_key_exists(0, $this->choices
))) {
2212 } else if (!array_key_exists($current, $this->choices
)) {
2213 $warning = get_string('warningcurrentsetting', 'admin', s($current));
2214 if (!is_null($default) and $data==$current) {
2215 $data = $default; // use default instead of first value when showing the form
2219 $return = '<div class="form-select defaultsnext"><select id="'.$this->get_id().'" name="'.$this->get_full_name().'">';
2220 foreach ($this->choices
as $key => $value) {
2221 // the string cast is needed because key may be integer - 0 is equal to most strings!
2222 $return .= '<option value="'.$key.'"'.((string)$key==$data ?
' selected="selected"' : '').'>'.$value.'</option>';
2224 $return .= '</select></div>';
2226 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, true, $warning, $defaultinfo, $query);
2232 * Select multiple items from list
2234 class admin_setting_configmultiselect
extends admin_setting_configselect
{
2237 * @param string $name of setting
2238 * @param string $visiblename localised
2239 * @param string $description long localised info
2240 * @param array $defaultsetting array of selected items
2241 * @param array $choices array of $value=>$label for each list item
2243 function admin_setting_configmultiselect($name, $visiblename, $description, $defaultsetting, $choices) {
2244 parent
::admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices);
2247 function get_setting() {
2248 $result = $this->config_read($this->name
);
2249 if (is_null($result)) {
2252 if ($result === '') {
2255 return explode(',', $result);
2258 function write_setting($data) {
2259 if (!is_array($data)) {
2260 return ''; //ignore it
2262 if (!$this->load_choices() or empty($this->choices
)) {
2266 unset($data['xxxxx']);
2269 foreach ($data as $value) {
2270 if (!array_key_exists($value, $this->choices
)) {
2271 continue; // ignore it
2276 return ($this->config_write($this->name
, implode(',', $save)) ?
'' : get_string('errorsetting', 'admin'));
2280 * Is setting related to query text - used when searching
2281 * @param string $query
2284 function is_related($query) {
2285 if (!$this->load_choices() or empty($this->choices
)) {
2288 if (parent
::is_related($query)) {
2292 $textlib = textlib_get_instance();
2293 foreach ($this->choices
as $desc) {
2294 if (strpos($textlib->strtolower($desc), $query) !== false) {
2301 function output_html($data, $query='') {
2302 if (!$this->load_choices() or empty($this->choices
)) {
2305 $choices = $this->choices
;
2306 $default = $this->get_defaultsetting();
2307 if (is_null($default)) {
2310 if (is_null($data)) {
2314 $defaults = array();
2315 $return = '<div class="form-select"><input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
2316 $return .= '<select id="'.$this->get_id().'" name="'.$this->get_full_name().'[]" size="10" multiple="multiple">';
2317 foreach ($this->choices
as $key => $description) {
2318 if (in_array($key, $data)) {
2319 $selected = 'selected="selected"';
2323 if (in_array($key, $default)) {
2324 $defaults[] = $description;
2327 $return .= '<option value="'.s($key).'" '.$selected.'>'.$description.'</option>';
2330 if (is_null($default)) {
2331 $defaultinfo = NULL;
2332 } if (!empty($defaults)) {
2333 $defaultinfo = implode(', ', $defaults);
2335 $defaultinfo = get_string('none');
2338 $return .= '</select></div>';
2339 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, true, '', $defaultinfo, $query);
2345 * this is a liiitle bit messy. we're using two selects, but we're returning
2346 * them as an array named after $name (so we only use $name2 internally for the setting)
2348 class admin_setting_configtime
extends admin_setting
{
2353 * @param string $hoursname setting for hours
2354 * @param string $minutesname setting for hours
2355 * @param string $visiblename localised
2356 * @param string $description long localised info
2357 * @param array $defaultsetting array representing default time 'h'=>hours, 'm'=>minutes
2359 function admin_setting_configtime($hoursname, $minutesname, $visiblename, $description, $defaultsetting) {
2360 $this->name2
= $minutesname;
2361 parent
::admin_setting($hoursname, $visiblename, $description, $defaultsetting);
2364 function get_setting() {
2365 $result1 = $this->config_read($this->name
);
2366 $result2 = $this->config_read($this->name2
);
2367 if (is_null($result1) or is_null($result2)) {
2371 return array('h' => $result1, 'm' => $result2);
2374 function write_setting($data) {
2375 if (!is_array($data)) {
2379 $result = $this->config_write($this->name
, (int)$data['h']) && $this->config_write($this->name2
, (int)$data['m']);
2380 return ($result ?
'' : get_string('errorsetting', 'admin'));
2383 function output_html($data, $query='') {
2384 $default = $this->get_defaultsetting();
2386 if (is_array($default)) {
2387 $defaultinfo = $default['h'].':'.$default['m'];
2389 $defaultinfo = NULL;
2392 $return = '<div class="form-time defaultsnext">'.
2393 '<select id="'.$this->get_id().'h" name="'.$this->get_full_name().'[h]">';
2394 for ($i = 0; $i < 24; $i++
) {
2395 $return .= '<option value="'.$i.'"'.($i == $data['h'] ?
' selected="selected"' : '').'>'.$i.'</option>';
2397 $return .= '</select>:<select id="'.$this->get_id().'m" name="'.$this->get_full_name().'[m]">';
2398 for ($i = 0; $i < 60; $i +
= 5) {
2399 $return .= '<option value="'.$i.'"'.($i == $data['m'] ?
' selected="selected"' : '').'>'.$i.'</option>';
2401 $return .= '</select></div>';
2402 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', $defaultinfo, $query);
2408 * Special checkbox for calendar - resets SESSION vars.
2410 class admin_setting_special_adminseesall
extends admin_setting_configcheckbox
{
2411 function admin_setting_special_adminseesall() {
2412 parent
::admin_setting_configcheckbox('calendar_adminseesall', get_string('adminseesall', 'admin'),
2413 get_string('helpadminseesall', 'admin'), '0');
2416 function write_setting($data) {
2418 unset($SESSION->cal_courses_shown
);
2419 return parent
::write_setting($data);
2424 * Special select for settings that are altered in setup.php and can not be altered on the fly
2426 class admin_setting_special_selectsetup
extends admin_setting_configselect
{
2427 function get_setting() {
2428 // read directly from db!
2429 return get_config(NULL, $this->name
);
2432 function write_setting($data) {
2434 // do not change active CFG setting!
2435 $current = $CFG->{$this->name
};
2436 $result = parent
::write_setting($data);
2437 $CFG->{$this->name
} = $current;
2443 * Special select for frontpage - stores data in course table
2445 class admin_setting_sitesetselect
extends admin_setting_configselect
{
2446 function get_setting() {
2448 return $site->{$this->name
};
2451 function write_setting($data) {
2452 if (!in_array($data, array_keys($this->choices
))) {
2453 return get_string('errorsetting', 'admin');
2455 $record = new stdClass();
2456 $record->id
= SITEID
;
2457 $temp = $this->name
;
2458 $record->$temp = $data;
2459 $record->timemodified
= time();
2460 return (update_record('course', $record) ?
'' : get_string('errorsetting', 'admin'));
2465 * Special select - lists on the frontpage - hacky
2467 class admin_setting_courselist_frontpage
extends admin_setting
{
2470 function admin_setting_courselist_frontpage($loggedin) {
2472 require_once($CFG->dirroot
.'/course/lib.php');
2473 $name = 'frontpage'.($loggedin ?
'loggedin' : '');
2474 $visiblename = get_string('frontpage'.($loggedin ?
'loggedin' : ''),'admin');
2475 $description = get_string('configfrontpage'.($loggedin ?
'loggedin' : ''),'admin');
2476 $defaults = array(FRONTPAGECOURSELIST
);
2477 parent
::admin_setting($name, $visiblename, $description, $defaults);
2480 function load_choices() {
2481 if (is_array($this->choices
)) {
2484 $this->choices
= array(FRONTPAGENEWS
=> get_string('frontpagenews'),
2485 FRONTPAGECOURSELIST
=> get_string('frontpagecourselist'),
2486 FRONTPAGECATEGORYNAMES
=> get_string('frontpagecategorynames'),
2487 FRONTPAGECATEGORYCOMBO
=> get_string('frontpagecategorycombo'),
2488 'none' => get_string('none'));
2489 if ($this->name
== 'frontpage' and count_records('course') > FRONTPAGECOURSELIMIT
) {
2490 unset($this->choices
[FRONTPAGECOURSELIST
]);
2494 function get_setting() {
2495 $result = $this->config_read($this->name
);
2496 if (is_null($result)) {
2499 if ($result === '') {
2502 return explode(',', $result);
2505 function write_setting($data) {
2506 if (!is_array($data)) {
2509 $this->load_choices();
2511 foreach($data as $datum) {
2512 if ($datum == 'none' or !array_key_exists($datum, $this->choices
)) {
2515 $save[$datum] = $datum; // no duplicates
2517 return ($this->config_write($this->name
, implode(',', $save)) ?
'' : get_string('errorsetting', 'admin'));
2520 function output_html($data, $query='') {
2521 $this->load_choices();
2522 $currentsetting = array();
2523 foreach ($data as $key) {
2524 if ($key != 'none' and array_key_exists($key, $this->choices
)) {
2525 $currentsetting[] = $key; // already selected first
2529 $return = '<div class="form-group">';
2530 for ($i = 0; $i < count($this->choices
) - 1; $i++
) {
2531 if (!array_key_exists($i, $currentsetting)) {
2532 $currentsetting[$i] = 'none'; //none
2534 $return .='<select class="form-select" id="'.$this->get_id().$i.'" name="'.$this->get_full_name().'[]">';
2535 foreach ($this->choices
as $key => $value) {
2536 $return .= '<option value="'.$key.'"'.("$key" == $currentsetting[$i] ?
' selected="selected"' : '').'>'.$value.'</option>';
2538 $return .= '</select>';
2539 if ($i !== count($this->choices
) - 2) {
2540 $return .= '<br />';
2543 $return .= '</div>';
2545 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
2550 * Special checkbox for frontpage - stores data in course table
2552 class admin_setting_sitesetcheckbox
extends admin_setting_configcheckbox
{
2553 function get_setting() {
2555 return $site->{$this->name
};
2558 function write_setting($data) {
2559 $record = new object();
2560 $record->id
= SITEID
;
2561 $record->{$this->name
} = ($data == '1' ?
1 : 0);
2562 $record->timemodified
= time();
2563 return (update_record('course', $record) ?
'' : get_string('errorsetting', 'admin'));
2568 * Special text for frontpage - stores data in course table.
2569 * Empty string means not set here. Manual setting is required.
2571 class admin_setting_sitesettext
extends admin_setting_configtext
{
2572 function get_setting() {
2574 return $site->{$this->name
} != '' ?
$site->{$this->name
} : NULL;
2577 function validate($data) {
2578 $cleaned = stripslashes(clean_param(addslashes($data), PARAM_MULTILANG
));
2579 if ($cleaned === '') {
2580 return get_string('required');
2582 if ("$data" == "$cleaned") { // implicit conversion to string is needed to do exact comparison
2585 return get_string('validateerror', 'admin');
2589 function write_setting($data) {
2590 $data = trim($data);
2591 $validated = $this->validate($data);
2592 if ($validated !== true) {
2596 $record = new object();
2597 $record->id
= SITEID
;
2598 $record->{$this->name
} = addslashes($data);
2599 $record->timemodified
= time();
2600 return (update_record('course', $record) ?
'' : get_string('dbupdatefailed', 'error'));
2605 * Special text editor for site description.
2607 class admin_setting_special_frontpagedesc
extends admin_setting
{
2608 function admin_setting_special_frontpagedesc() {
2609 parent
::admin_setting('summary', get_string('frontpagedescription'), get_string('frontpagedescriptionhelp'), NULL);
2612 function get_setting() {
2614 return $site->{$this->name
};
2617 function write_setting($data) {
2618 $record = new object();
2619 $record->id
= SITEID
;
2620 $record->{$this->name
} = addslashes($data);
2621 $record->timemodified
= time();
2622 return(update_record('course', $record) ?
'' : get_string('errorsetting', 'admin'));
2625 function output_html($data, $query='') {
2628 $CFG->adminusehtmleditor
= can_use_html_editor();
2629 $return = '<div class="form-htmlarea">'.print_textarea($CFG->adminusehtmleditor
, 15, 60, 0, 0, $this->get_full_name(), $data, 0, true).'</div>';
2631 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
2635 class admin_setting_special_editorfontlist
extends admin_setting
{
2639 function admin_setting_special_editorfontlist() {
2641 $name = 'editorfontlist';
2642 $visiblename = get_string('editorfontlist', 'admin');
2643 $description = get_string('configeditorfontlist', 'admin');
2644 $defaults = array('k0' => 'Trebuchet',
2645 'v0' => 'Trebuchet MS,Verdana,Arial,Helvetica,sans-serif',
2647 'v1' => 'arial,helvetica,sans-serif',
2648 'k2' => 'Courier New',
2649 'v2' => 'courier new,courier,monospace',
2651 'v3' => 'georgia,times new roman,times,serif',
2653 'v4' => 'tahoma,arial,helvetica,sans-serif',
2654 'k5' => 'Times New Roman',
2655 'v5' => 'times new roman,times,serif',
2657 'v6' => 'verdana,arial,helvetica,sans-serif',
2660 'k8' => 'Wingdings',
2661 'v8' => 'wingdings');
2662 parent
::admin_setting($name, $visiblename, $description, $defaults);
2665 function get_setting() {
2667 $result = $this->config_read($this->name
);
2668 if (is_null($result)) {
2672 $currentsetting = array();
2673 $items = explode(';', $result);
2674 foreach ($items as $item) {
2675 $item = explode(':', $item);
2676 $currentsetting['k'.$i] = $item[0];
2677 $currentsetting['v'.$i] = $item[1];
2680 return $currentsetting;
2683 function write_setting($data) {
2685 // there miiight be an easier way to do this :)
2686 // if this is changed, make sure the $defaults array above is modified so that this
2687 // function processes it correctly
2692 foreach ($data as $key => $value) {
2693 if (substr($key,0,1) == 'k') {
2694 $keys[substr($key,1)] = $value;
2695 } elseif (substr($key,0,1) == 'v') {
2696 $values[substr($key,1)] = $value;
2701 for ($i = 0; $i < count($keys); $i++
) {
2702 if (($keys[$i] !== '') && ($values[$i] !== '')) {
2703 $result[] = clean_param($keys[$i],PARAM_NOTAGS
).':'.clean_param($values[$i], PARAM_NOTAGS
);
2707 return ($this->config_write($this->name
, implode(';', $result)) ?
'' : get_string('errorsetting', 'admin'));
2710 function output_html($data, $query='') {
2711 $fullname = $this->get_full_name();
2712 $return = '<div class="form-group">';
2713 for ($i = 0; $i < count($data) / 2; $i++
) {
2714 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.$i.']" value="'.$data['k'.$i].'" />';
2715 $return .= ' ';
2716 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.$i.']" value="'.$data['v'.$i].'" /><br />';
2718 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.$i.']" value="" />';
2719 $return .= ' ';
2720 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.$i.']" value="" /><br />';
2721 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.($i +
1).']" value="" />';
2722 $return .= ' ';
2723 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.($i +
1).']" value="" />';
2724 $return .= '</div>';
2726 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
2731 class admin_setting_emoticons
extends admin_setting
{
2735 function admin_setting_emoticons() {
2737 $name = 'emoticons';
2738 $visiblename = get_string('emoticons', 'admin');
2739 $description = get_string('configemoticons', 'admin');
2740 $defaults = array('k0' => ':-)',
2751 'v5' => 'thoughtful',
2753 'v6' => 'tongueout',
2773 'v16' => 'surprise',
2775 'v17' => 'blackeye',
2792 'k26' => '(martin)',
2796 parent
::admin_setting($name, $visiblename, $description, $defaults);
2799 function get_setting() {
2801 $result = $this->config_read($this->name
);
2802 if (is_null($result)) {
2806 $currentsetting = array();
2807 $items = explode('{;}', $result);
2808 foreach ($items as $item) {
2809 $item = explode('{:}', $item);
2810 $currentsetting['k'.$i] = $item[0];
2811 $currentsetting['v'.$i] = $item[1];
2814 return $currentsetting;
2817 function write_setting($data) {
2819 // there miiight be an easier way to do this :)
2820 // if this is changed, make sure the $defaults array above is modified so that this
2821 // function processes it correctly
2826 foreach ($data as $key => $value) {
2827 if (substr($key,0,1) == 'k') {
2828 $keys[substr($key,1)] = $value;
2829 } elseif (substr($key,0,1) == 'v') {
2830 $values[substr($key,1)] = $value;
2835 for ($i = 0; $i < count($keys); $i++
) {
2836 if (($keys[$i] !== '') && ($values[$i] !== '')) {
2837 $result[] = clean_param($keys[$i],PARAM_NOTAGS
).'{:}'.clean_param($values[$i], PARAM_NOTAGS
);
2841 return ($this->config_write($this->name
, implode('{;}', $result)) ?
'' : get_string('errorsetting', 'admin').$this->visiblename
.'<br />');
2844 function output_html($data, $query='') {
2845 $fullname = $this->get_full_name();
2846 $return = '<div class="form-group">';
2847 for ($i = 0; $i < count($data) / 2; $i++
) {
2848 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.$i.']" value="'.$data['k'.$i].'" />';
2849 $return .= ' ';
2850 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.$i.']" value="'.$data['v'.$i].'" /><br />';
2852 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.$i.']" value="" />';
2853 $return .= ' ';
2854 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.$i.']" value="" /><br />';
2855 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.($i +
1).']" value="" />';
2856 $return .= ' ';
2857 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.($i +
1).']" value="" />';
2858 $return .= '</div>';
2860 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
2866 * Setting for spellchecker language selection.
2868 class admin_setting_special_editordictionary
extends admin_setting_configselect
{
2870 function admin_setting_special_editordictionary() {
2871 $name = 'editordictionary';
2872 $visiblename = get_string('editordictionary','admin');
2873 $description = get_string('configeditordictionary', 'admin');
2874 parent
::admin_setting_configselect($name, $visiblename, $description, '', NULL);
2877 function load_choices() {
2878 // function borrowed from the old moodle/admin/editor.php, slightly modified
2879 // Get all installed dictionaries in the system
2880 if (is_array($this->choices
)) {
2884 $this->choices
= array();
2890 // If aspellpath isn't set don't even bother ;-)
2891 if (empty($CFG->aspellpath
)) {
2892 $this->choices
['error'] = 'Empty aspell path!';
2896 // Do we have access to popen function?
2897 if (!function_exists('popen')) {
2898 $this->choices
['error'] = 'Popen function disabled!';
2902 $cmd = $CFG->aspellpath
;
2904 $dictionaries = array();
2906 if(!($handle = @popen
(escapeshellarg($cmd).' dump dicts', 'r'))) {
2907 $this->choices
['error'] = 'Couldn\'t create handle!';
2910 while(!feof($handle)) {
2911 $output .= fread($handle, 1024);
2915 $dictionaries = explode(chr(10), $output);
2916 foreach ($dictionaries as $dict) {
2920 $this->choices
[$dict] = $dict;
2923 if (empty($this->choices
)) {
2924 $this->choices
['error'] = 'Error! Check your aspell installation!';
2931 class admin_setting_special_editorhidebuttons
extends admin_setting
{
2934 function admin_setting_special_editorhidebuttons() {
2935 parent
::admin_setting('editorhidebuttons', get_string('editorhidebuttons', 'admin'),
2936 get_string('confeditorhidebuttons', 'admin'), array());
2937 // weird array... buttonname => buttonimage (assume proper path appended). if you leave buttomimage blank, text will be printed instead
2938 $this->items
= array('fontname' => '',
2940 'formatblock' => '',
2941 'bold' => 'ed_format_bold.gif',
2942 'italic' => 'ed_format_italic.gif',
2943 'underline' => 'ed_format_underline.gif',
2944 'strikethrough' => 'ed_format_strike.gif',
2945 'subscript' => 'ed_format_sub.gif',
2946 'superscript' => 'ed_format_sup.gif',
2947 'copy' => 'ed_copy.gif',
2948 'cut' => 'ed_cut.gif',
2949 'paste' => 'ed_paste.gif',
2950 'clean' => 'ed_wordclean.gif',
2951 'undo' => 'ed_undo.gif',
2952 'redo' => 'ed_redo.gif',
2953 'justifyleft' => 'ed_align_left.gif',
2954 'justifycenter' => 'ed_align_center.gif',
2955 'justifyright' => 'ed_align_right.gif',
2956 'justifyfull' => 'ed_align_justify.gif',
2957 'lefttoright' => 'ed_left_to_right.gif',
2958 'righttoleft' => 'ed_right_to_left.gif',
2959 'insertorderedlist' => 'ed_list_num.gif',
2960 'insertunorderedlist' => 'ed_list_bullet.gif',
2961 'outdent' => 'ed_indent_less.gif',
2962 'indent' => 'ed_indent_more.gif',
2963 'forecolor' => 'ed_color_fg.gif',
2964 'hilitecolor' => 'ed_color_bg.gif',
2965 'inserthorizontalrule' => 'ed_hr.gif',
2966 'createanchor' => 'ed_anchor.gif',
2967 'createlink' => 'ed_link.gif',
2968 'unlink' => 'ed_unlink.gif',
2969 'insertimage' => 'ed_image.gif',
2970 'inserttable' => 'insert_table.gif',
2971 'insertsmile' => 'em.icon.smile.gif',
2972 'insertchar' => 'icon_ins_char.gif',
2973 'spellcheck' => 'spell-check.gif',
2974 'htmlmode' => 'ed_html.gif',
2975 'popupeditor' => 'fullscreen_maximize.gif',
2976 'search_replace' => 'ed_replace.gif');
2979 function get_setting() {
2980 $result = $this->config_read($this->name
);
2981 if (is_null($result)) {
2984 if ($result === '') {
2987 return explode(' ', $result);
2990 function write_setting($data) {
2991 if (!is_array($data)) {
2992 return ''; // ignore it
2994 unset($data['xxxxx']);
2997 foreach ($data as $key => $value) {
2998 if (!isset($this->items
[$key])) {
2999 return get_string('errorsetting', 'admin');
3001 if ($value == '1') {
3005 return ($this->config_write($this->name
, implode(' ', $result)) ?
'' : get_string('errorsetting', 'admin'));
3008 function output_html($data, $query='') {
3012 // checkboxes with input name="$this->name[$key]" value="1"
3013 // we do 15 fields per column
3015 $return = '<div class="form-group">';
3016 $return .= '<table><tr><td valign="top" align="right">';
3017 $return .= '<input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
3021 foreach($this->items
as $key => $value) {
3022 if ($count %
15 == 0 and $count != 0) {
3023 $return .= '</td><td valign="top" align="right">';
3026 $return .= '<label for="'.$this->get_id().$key.'">';
3027 $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').'" />').' ';
3028 $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"' : '').' /> ';
3029 $return .= '</label>';
3031 if ($count %
15 != 0) {
3032 $return .= '<br /><br />';
3036 $return .= '</td></tr>';
3037 $return .= '</table>';
3038 $return .= '</div>';
3040 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
3045 * Special setting for limiting of the list of available languages.
3047 class admin_setting_langlist
extends admin_setting_configtext
{
3048 function admin_setting_langlist() {
3049 parent
::admin_setting_configtext('langlist', get_string('langlist', 'admin'), get_string('configlanglist', 'admin'), '', PARAM_NOTAGS
);
3052 function write_setting($data) {
3053 $return = parent
::write_setting($data);
3054 get_list_of_languages(true);//refresh the list
3060 * Course category selection
3062 class admin_settings_coursecat_select
extends admin_setting_configselect
{
3063 function admin_settings_coursecat_select($name, $visiblename, $description, $defaultsetting) {
3064 parent
::admin_setting_configselect($name, $visiblename, $description, $defaultsetting, NULL);
3067 function load_choices() {
3069 require_once($CFG->dirroot
.'/course/lib.php');
3070 if (is_array($this->choices
)) {
3073 $this->choices
= make_categories_options();
3078 class admin_setting_special_backupdays
extends admin_setting_configmulticheckbox2
{
3079 function admin_setting_special_backupdays() {
3080 parent
::admin_setting_configmulticheckbox2('backup_sche_weekdays', get_string('schedule'), get_string('backupschedulehelp'), array(), NULL);
3081 $this->plugin
= 'backup';
3084 function load_choices() {
3085 if (is_array($this->choices
)) {
3088 $this->choices
= array();
3089 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
3090 foreach ($days as $day) {
3091 $this->choices
[$day] = get_string($day, 'calendar');
3098 * Special debug setting
3100 class admin_setting_special_debug
extends admin_setting_configselect
{
3101 function admin_setting_special_debug() {
3102 parent
::admin_setting_configselect('debug', get_string('debug', 'admin'), get_string('configdebug', 'admin'), DEBUG_NONE
, NULL);
3105 function load_choices() {
3106 if (is_array($this->choices
)) {
3109 $this->choices
= array(DEBUG_NONE
=> get_string('debugnone', 'admin'),
3110 DEBUG_MINIMAL
=> get_string('debugminimal', 'admin'),
3111 DEBUG_NORMAL
=> get_string('debugnormal', 'admin'),
3112 DEBUG_ALL
=> get_string('debugall', 'admin'),
3113 DEBUG_DEVELOPER
=> get_string('debugdeveloper', 'admin'));
3119 class admin_setting_special_calendar_weekend
extends admin_setting
{
3120 function admin_setting_special_calendar_weekend() {
3121 $name = 'calendar_weekend';
3122 $visiblename = get_string('calendar_weekend', 'admin');
3123 $description = get_string('helpweekenddays', 'admin');
3124 $default = array ('0', '6'); // Saturdays and Sundays
3125 parent
::admin_setting($name, $visiblename, $description, $default);
3128 function get_setting() {
3129 $result = $this->config_read($this->name
);
3130 if (is_null($result)) {
3133 if ($result === '') {
3136 $settings = array();
3137 for ($i=0; $i<7; $i++
) {
3138 if ($result & (1 << $i)) {
3145 function write_setting($data) {
3146 if (!is_array($data)) {
3149 unset($data['xxxxx']);
3151 foreach($data as $index) {
3152 $result |
= 1 << $index;
3154 return ($this->config_write($this->name
, $result) ?
'' : get_string('errorsetting', 'admin'));
3157 function output_html($data, $query='') {
3158 // The order matters very much because of the implied numeric keys
3159 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
3160 $return = '<table><thead><tr>';
3161 $return .= '<input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
3162 foreach($days as $index => $day) {
3163 $return .= '<td><label for="'.$this->get_id().$index.'">'.get_string($day, 'calendar').'</label></td>';
3165 $return .= '</tr></thead><tbody><tr>';
3166 foreach($days as $index => $day) {
3167 $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>';
3169 $return .= '</tr></tbody></table>';
3171 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
3178 * Graded roles in gradebook
3180 class admin_setting_special_gradebookroles
extends admin_setting_configmulticheckbox
{
3181 function admin_setting_special_gradebookroles() {
3182 parent
::admin_setting_configmulticheckbox('gradebookroles', get_string('gradebookroles', 'admin'),
3183 get_string('configgradebookroles', 'admin'), NULL, NULL);
3186 function load_choices() {
3188 if (empty($CFG->rolesactive
)) {
3191 if (is_array($this->choices
)) {
3194 if ($roles = get_records('role')) {
3195 $this->choices
= array();
3196 foreach($roles as $role) {
3197 $this->choices
[$role->id
] = format_string($role->name
);
3205 function get_defaultsetting() {
3207 if (empty($CFG->rolesactive
)) {
3211 if ($studentroles = get_roles_with_capability('moodle/legacy:student', CAP_ALLOW
)) {
3212 foreach ($studentroles as $studentrole) {
3213 $result[$studentrole->id
] = '1';
3220 class admin_setting_regradingcheckbox
extends admin_setting_configcheckbox
{
3221 function write_setting($data) {
3224 $oldvalue = $this->config_read($this->name
);
3225 $return = parent
::write_setting($data);
3226 $newvalue = $this->config_read($this->name
);
3228 if ($oldvalue !== $newvalue) {
3229 // force full regrading
3230 set_field('grade_items', 'needsupdate', 1, 'needsupdate', 0);
3238 * Which roles to show on course decription page
3240 class admin_setting_special_coursemanager
extends admin_setting_configmulticheckbox
{
3241 function admin_setting_special_coursemanager() {
3242 parent
::admin_setting_configmulticheckbox('coursemanager', get_string('coursemanager', 'admin'),
3243 get_string('configcoursemanager', 'admin'), NULL, NULL);
3246 function load_choices() {
3247 if (is_array($this->choices
)) {
3250 if ($roles = get_records('role','','','sortorder')) {
3251 $this->choices
= array();
3252 foreach($roles as $role) {
3253 $this->choices
[$role->id
] = format_string($role->name
);
3260 function get_defaultsetting() {
3262 if (empty($CFG->rolesactive
)) {
3266 if ($teacherroles = get_roles_with_capability('moodle/legacy:editingteacher', CAP_ALLOW
)) {
3267 foreach ($teacherroles as $teacherrole) {
3268 $result[$teacherrole->id
] = '1';
3276 * Primary grade export plugin - has state tracking.
3278 class admin_setting_special_gradeexport
extends admin_setting_configmulticheckbox
{
3279 function admin_setting_special_gradeexport() {
3280 parent
::admin_setting_configmulticheckbox('gradeexport', get_string('gradeexport', 'admin'),
3281 get_string('configgradeexport', 'admin'), array(), NULL);
3284 function load_choices() {
3285 if (is_array($this->choices
)) {
3288 $this->choices
= array();
3290 if ($plugins = get_list_of_plugins('grade/export')) {
3291 foreach($plugins as $plugin) {
3292 $this->choices
[$plugin] = get_string('modulename', 'gradeexport_'.$plugin);
3300 * Grade category settings
3302 class admin_setting_gradecat_combo
extends admin_setting
{
3306 function admin_setting_gradecat_combo($name, $visiblename, $description, $defaultsetting, $choices) {
3307 $this->choices
= $choices;
3308 parent
::admin_setting($name, $visiblename, $description, $defaultsetting);
3311 function get_setting() {
3314 $value = $this->config_read($this->name
);
3315 $flag = $this->config_read($this->name
.'_flag');
3317 if (is_null($value) or is_null($flag)) {
3322 $forced = (boolean
)(1 & $flag); // first bit
3323 $adv = (boolean
)(2 & $flag); // second bit
3325 return array('value' => $value, 'forced' => $forced, 'adv' => $adv);
3328 function write_setting($data) {
3331 $value = $data['value'];
3332 $forced = empty($data['forced']) ?
0 : 1;
3333 $adv = empty($data['adv']) ?
0 : 2;
3334 $flag = ($forced |
$adv); //bitwise or
3336 if (!in_array($value, array_keys($this->choices
))) {
3337 return 'Error setting ';
3340 $oldvalue = $this->config_read($this->name
);
3341 $oldflag = (int)$this->config_read($this->name
.'_flag');
3342 $oldforced = (1 & $oldflag); // first bit
3344 $result1 = $this->config_write($this->name
, $value);
3345 $result2 = $this->config_write($this->name
.'_flag', $flag);
3347 // force regrade if needed
3348 if ($oldforced != $forced or ($forced and $value != $oldvalue)) {
3349 require_once($CFG->libdir
.'/gradelib.php');
3350 grade_category
::updated_forced_settings();
3353 if ($result1 and $result2) {
3356 return get_string('errorsetting', 'admin');
3360 function output_html($data, $query='') {
3361 $value = $data['value'];
3362 $forced = !empty($data['forced']);
3363 $adv = !empty($data['adv']);
3365 $default = $this->get_defaultsetting();
3366 if (!is_null($default)) {
3367 $defaultinfo = array();
3368 if (isset($this->choices
[$default['value']])) {
3369 $defaultinfo[] = $this->choices
[$default['value']];
3371 if (!empty($default['forced'])) {
3372 $defaultinfo[] = get_string('force');
3374 if (!empty($default['adv'])) {
3375 $defaultinfo[] = get_string('advanced');
3377 $defaultinfo = implode(', ', $defaultinfo);
3380 $defaultinfo = NULL;
3384 $return = '<div class="form-group">';
3385 $return .= '<select class="form-select" id="'.$this->get_id().'" name="'.$this->get_full_name().'[value]">';
3386 foreach ($this->choices
as $key => $val) {
3387 // the string cast is needed because key may be integer - 0 is equal to most strings!
3388 $return .= '<option value="'.$key.'"'.((string)$key==$value ?
' selected="selected"' : '').'>'.$val.'</option>';
3390 $return .= '</select>';
3391 $return .= '<input type="checkbox" class="form-checkbox" id="'.$this->get_id().'force" name="'.$this->get_full_name().'[forced]" value="1" '.($forced ?
'checked="checked"' : '').' />'
3392 .'<label for="'.$this->get_id().'force">'.get_string('force').'</label>';
3393 $return .= '<input type="checkbox" class="form-checkbox" id="'.$this->get_id().'adv" name="'.$this->get_full_name().'[adv]" value="1" '.($adv ?
'checked="checked"' : '').' />'
3394 .'<label for="'.$this->get_id().'adv">'.get_string('advanced').'</label>';
3395 $return .= '</div>';
3397 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, true, '', $defaultinfo, $query);
3403 * Selection of grade report in user profiles
3405 class admin_setting_grade_profilereport
extends admin_setting_configselect
{
3406 function admin_setting_grade_profilereport() {
3407 parent
::admin_setting_configselect('grade_profilereport', get_string('profilereport', 'grades'), get_string('configprofilereport', 'grades'), 'user', null);
3410 function load_choices() {
3411 if (is_array($this->choices
)) {
3414 $this->choices
= array();
3417 require_once($CFG->libdir
.'/gradelib.php');
3419 foreach (get_list_of_plugins('grade/report') as $plugin) {
3420 if (file_exists($CFG->dirroot
.'/grade/report/'.$plugin.'/lib.php')) {
3421 require_once($CFG->dirroot
.'/grade/report/'.$plugin.'/lib.php');
3422 $functionname = 'grade_report_'.$plugin.'_profilereport';
3423 if (function_exists($functionname)) {
3424 $this->choices
[$plugin] = get_string('modulename', 'gradereport_'.$plugin, NULL, $CFG->dirroot
.'/grade/report/'.$plugin.'/lang/');
3433 * Special class for register auth selection
3435 class admin_setting_special_registerauth
extends admin_setting_configselect
{
3436 function admin_setting_special_registerauth() {
3437 parent
::admin_setting_configselect('registerauth', get_string('selfregistration', 'auth'), get_string('selfregistration_help', 'auth'), 'email', null);
3440 function get_defaultsettings() {
3441 $this->load_choices();
3442 if (array_key_exists($this->defaultsetting
, $this->choices
)) {
3443 return $this->defaultsetting
;
3449 function load_choices() {
3452 if (is_array($this->choices
)) {
3455 $this->choices
= array();
3456 $this->choices
[''] = get_string('disable');
3458 $authsenabled = get_enabled_auth_plugins(true);
3460 foreach ($authsenabled as $auth) {
3461 $authplugin = get_auth_plugin($auth);
3462 if (!$authplugin->can_signup()) {
3465 // Get the auth title (from core or own auth lang files)
3466 $authtitle = $authplugin->get_title();
3467 $this->choices
[$auth] = $authtitle;
3474 * Module manage page
3476 class admin_page_managemods
extends admin_externalpage
{
3477 function admin_page_managemods() {
3479 parent
::admin_externalpage('managemodules', get_string('modsettings', 'admin'), "$CFG->wwwroot/$CFG->admin/modules.php");
3482 function search($query) {
3483 if ($result = parent
::search($query)) {
3488 if ($modules = get_records('modules')) {
3489 $textlib = textlib_get_instance();
3490 foreach ($modules as $module) {
3491 if (strpos($module->name
, $query) !== false) {
3495 $strmodulename = get_string('modulename', $module->name
);
3496 if (strpos($textlib->strtolower($strmodulename), $query) !== false) {
3503 $result = new object();
3504 $result->page
= $this;
3505 $result->settings
= array();
3506 return array($this->name
=> $result);
3514 * Blocks manage page
3516 class admin_page_manageblocks
extends admin_externalpage
{
3517 function admin_page_manageblocks() {
3519 parent
::admin_externalpage('manageblocks', get_string('blocksettings', 'admin'), "$CFG->wwwroot/$CFG->admin/blocks.php");
3522 function search($query) {
3524 if ($result = parent
::search($query)) {
3529 if (!empty($CFG->blocks_version
) and $blocks = get_records('block')) {
3530 $textlib = textlib_get_instance();
3531 foreach ($blocks as $block) {
3532 if (strpos($block->name
, $query) !== false) {
3536 $strblockname = get_string('blockname', 'block_'.$block->name
);
3537 if (strpos($textlib->strtolower($strblockname), $query) !== false) {
3544 $result = new object();
3545 $result->page
= $this;
3546 $result->settings
= array();
3547 return array($this->name
=> $result);
3555 * Special class for authentication administration.
3557 class admin_setting_manageauths
extends admin_setting
{
3558 function admin_setting_manageauths() {
3559 parent
::admin_setting('authsui', get_string('authsettings', 'admin'), '', '');
3562 function get_setting() {
3566 function get_defaultsetting() {
3570 function write_setting($data) {
3571 // do not write any setting
3575 function is_related($query) {
3576 if (parent
::is_related($query)) {
3580 $textlib = textlib_get_instance();
3581 $authsavailable = get_list_of_plugins('auth');
3582 foreach ($authsavailable as $auth) {
3583 if (strpos($auth, $query) !== false) {
3586 $authplugin = get_auth_plugin($auth);
3587 $authtitle = $authplugin->get_title();
3588 if (strpos($textlib->strtolower($authtitle), $query) !== false) {
3595 function output_html($data, $query='') {
3600 $txt = get_strings(array('authenticationplugins', 'users', 'administration',
3601 'settings', 'edit', 'name', 'enable', 'disable',
3602 'up', 'down', 'none'));
3603 $txt->updown
= "$txt->up/$txt->down";
3605 $authsavailable = get_list_of_plugins('auth');
3606 get_enabled_auth_plugins(true); // fix the list of enabled auths
3607 if (empty($CFG->auth
)) {
3608 $authsenabled = array();
3610 $authsenabled = explode(',', $CFG->auth
);
3613 // construct the display array, with enabled auth plugins at the top, in order
3614 $displayauths = array();
3615 $registrationauths = array();
3616 $registrationauths[''] = $txt->disable
;
3617 foreach ($authsenabled as $auth) {
3618 $authplugin = get_auth_plugin($auth);
3619 /// Get the auth title (from core or own auth lang files)
3620 $authtitle = $authplugin->get_title();
3622 $displayauths[$auth] = $authtitle;
3623 if ($authplugin->can_signup()) {
3624 $registrationauths[$auth] = $authtitle;
3628 foreach ($authsavailable as $auth) {
3629 if (array_key_exists($auth, $displayauths)) {
3630 continue; //already in the list
3632 $authplugin = get_auth_plugin($auth);
3633 /// Get the auth title (from core or own auth lang files)
3634 $authtitle = $authplugin->get_title();
3636 $displayauths[$auth] = $authtitle;
3637 if ($authplugin->can_signup()) {
3638 $registrationauths[$auth] = $authtitle;
3642 $return = print_heading(get_string('actauthhdr', 'auth'), '', 3, 'main', true);
3643 $return .= print_box_start('generalbox authsui', '', true);
3645 $table = new object();
3646 $table->head
= array($txt->name
, $txt->enable
, $txt->updown
, $txt->settings
);
3647 $table->align
= array('left', 'center', 'center', 'center');
3648 $table->width
= '90%';
3649 $table->data
= array();
3651 //add always enabled plugins first
3652 $displayname = "<span>".$displayauths['manual']."</span>";
3653 $settings = "<a href=\"auth_config.php?auth=manual\">{$txt->settings}</a>";
3654 //$settings = "<a href=\"settings.php?section=authsettingmanual\">{$txt->settings}</a>";
3655 $table->data
[] = array($displayname, '', '', $settings);
3656 $displayname = "<span>".$displayauths['nologin']."</span>";
3657 $settings = "<a href=\"auth_config.php?auth=nologin\">{$txt->settings}</a>";
3658 $table->data
[] = array($displayname, '', '', $settings);
3661 // iterate through auth plugins and add to the display table
3663 $authcount = count($authsenabled);
3664 $url = "auth.php?sesskey=" . sesskey();
3665 foreach ($displayauths as $auth => $name) {
3666 if ($auth == 'manual' or $auth == 'nologin') {
3670 if (in_array($auth, $authsenabled)) {
3671 $hideshow = "<a href=\"$url&action=disable&auth=$auth\">";
3672 $hideshow .= "<img src=\"{$CFG->pixpath}/i/hide.gif\" class=\"icon\" alt=\"disable\" /></a>";
3673 // $hideshow = "<a href=\"$url&action=disable&auth=$auth\"><input type=\"checkbox\" checked /></a>";
3675 $displayname = "<span>$name</span>";
3678 $hideshow = "<a href=\"$url&action=enable&auth=$auth\">";
3679 $hideshow .= "<img src=\"{$CFG->pixpath}/i/show.gif\" class=\"icon\" alt=\"enable\" /></a>";
3680 // $hideshow = "<a href=\"$url&action=enable&auth=$auth\"><input type=\"checkbox\" /></a>";
3682 $displayname = "<span class=\"dimmed_text\">$name</span>";
3685 // up/down link (only if auth is enabled)
3688 if ($updowncount > 1) {
3689 $updown .= "<a href=\"$url&action=up&auth=$auth\">";
3690 $updown .= "<img src=\"{$CFG->pixpath}/t/up.gif\" alt=\"up\" /></a> ";
3693 $updown .= "<img src=\"{$CFG->pixpath}/spacer.gif\" class=\"icon\" alt=\"\" /> ";
3695 if ($updowncount < $authcount) {
3696 $updown .= "<a href=\"$url&action=down&auth=$auth\">";
3697 $updown .= "<img src=\"{$CFG->pixpath}/t/down.gif\" alt=\"down\" /></a>";
3700 $updown .= "<img src=\"{$CFG->pixpath}/spacer.gif\" class=\"icon\" alt=\"\" />";
3706 if (file_exists($CFG->dirroot
.'/auth/'.$auth.'/settings.php')) {
3707 $settings = "<a href=\"settings.php?section=authsetting$auth\">{$txt->settings}</a>";
3709 $settings = "<a href=\"auth_config.php?auth=$auth\">{$txt->settings}</a>";
3712 // add a row to the table
3713 $table->data
[] =array($displayname, $hideshow, $updown, $settings);
3715 $return .= print_table($table, true);
3716 $return .= get_string('configauthenticationplugins', 'admin').'<br />'.get_string('tablenosave', 'filters');
3717 $return .= print_box_end(true);
3718 return highlight($query, $return);
3722 * Special class for filter administration.
3724 class admin_setting_managefilters
extends admin_setting
{
3725 function admin_setting_managefilters() {
3726 parent
::admin_setting('filtersui', get_string('filtersettings', 'admin'), '', '');
3729 function get_setting() {
3733 function get_defaultsetting() {
3737 function write_setting($data) {
3738 // do not write any setting
3742 function is_related($query) {
3743 if (parent
::is_related($query)) {
3747 $textlib = textlib_get_instance();
3748 $filterlocations = array('mod','filter');
3749 foreach ($filterlocations as $filterlocation) {
3750 $plugins = get_list_of_plugins($filterlocation);
3751 foreach ($plugins as $plugin) {
3752 if (strpos($plugin, $query) !== false) {
3755 $name = get_string('filtername', $plugin);
3756 if (strpos($textlib->strtolower($name), $query) !== false) {
3764 function output_html($data, $query='') {
3767 $strname = get_string('name');
3768 $strhide = get_string('disable');
3769 $strshow = get_string('enable');
3770 $strhideshow = "$strhide/$strshow";
3771 $strsettings = get_string('settings');
3772 $strup = get_string('up');
3773 $strdown = get_string('down');
3774 $strupdown = "$strup/$strdown";
3776 // get a list of possible filters (and translate name if possible)
3777 // note filters can be in the dedicated filters area OR in their
3778 // associated modules
3779 $installedfilters = array();
3780 $filtersettings_new = array();
3781 $filtersettings_old = array();
3782 $filterlocations = array('mod','filter');
3783 foreach ($filterlocations as $filterlocation) {
3784 $plugins = get_list_of_plugins($filterlocation);
3785 foreach ($plugins as $plugin) {
3786 $pluginpath = "$CFG->dirroot/$filterlocation/$plugin/filter.php";
3787 $settingspath_new = "$CFG->dirroot/$filterlocation/$plugin/filtersettings.php";
3788 $settingspath_old = "$CFG->dirroot/$filterlocation/$plugin/filterconfig.html";
3789 if (is_readable($pluginpath)) {
3790 $name = trim(get_string("filtername", $plugin));
3791 if (empty($name) or ($name == '[[filtername]]')) {
3792 $textlib = textlib_get_instance();
3793 $name = $textlib->strtotitle($plugin);
3795 $installedfilters["$filterlocation/$plugin"] = $name;
3796 if (is_readable($settingspath_new)) {
3797 $filtersettings_new[] = "$filterlocation/$plugin";
3798 } else if (is_readable($settingspath_old)) {
3799 $filtersettings_old[] = "$filterlocation/$plugin";
3805 // get all the currently selected filters
3806 if (!empty($CFG->textfilters
)) {
3807 $oldactivefilters = explode(',', $CFG->textfilters
);
3808 $oldactivefilters = array_unique($oldactivefilters);
3810 $oldactivefilters = array();
3813 // take this opportunity to clean up filters
3814 $activefilters = array();
3815 foreach ($oldactivefilters as $oldactivefilter) {
3816 if (!empty($oldactivefilter) and array_key_exists($oldactivefilter, $installedfilters)) {
3817 $activefilters[] = $oldactivefilter;
3821 // construct the display array with installed filters
3822 // at the top in the right order
3823 $displayfilters = array();
3824 foreach ($activefilters as $activefilter) {
3825 $name = $installedfilters[$activefilter];
3826 $displayfilters[$activefilter] = $name;
3828 foreach ($installedfilters as $key => $filter) {
3829 if (!array_key_exists($key, $displayfilters)) {
3830 $displayfilters[$key] = $filter;
3834 $return = print_heading(get_string('actfilterhdr', 'filters'), '', 3, 'main', true);
3835 $return .= print_box_start('generalbox filtersui', '', true);
3837 $table = new object();
3838 $table->head
= array($strname, $strhideshow, $strupdown, $strsettings);
3839 $table->align
= array('left', 'center', 'center', 'center');
3840 $table->width
= '90%';
3841 $table->data
= array();
3843 $filtersurl = "$CFG->wwwroot/$CFG->admin/filters.php?sesskey=".sesskey();
3844 $imgurl = "$CFG->pixpath/t";
3846 // iterate through filters adding to display table
3848 $activefilterscount = count($activefilters);
3849 foreach ($displayfilters as $path => $name) {
3850 $upath = urlencode($path);
3851 // get hide/show link
3852 if (in_array($path, $activefilters)) {
3853 $hideshow = "<a href=\"$filtersurl&action=hide&filterpath=$upath\">";
3854 $hideshow .= "<img src=\"{$CFG->pixpath}/i/hide.gif\" class=\"icon\" alt=\"$strhide\" /></a>";
3856 $displayname = "<span>$name</span>";
3859 $hideshow = "<a href=\"$filtersurl&action=show&filterpath=$upath\">";
3860 $hideshow .= "<img src=\"{$CFG->pixpath}/i/show.gif\" class=\"icon\" alt=\"$strshow\" /></a>";
3862 $displayname = "<span class=\"dimmed_text\">$name</span>";
3865 // get up/down link (only if not hidden)
3868 if ($updowncount>1) {
3869 $updown .= "<a href=\"$filtersurl&action=up&filterpath=$upath\">";
3870 $updown .= "<img src=\"$imgurl/up.gif\" alt=\"$strup\" /></a> ";
3873 $updown .= "<img src=\"$CFG->pixpath/spacer.gif\" class=\"icon\" alt=\"\" /> ";
3875 if ($updowncount<$activefilterscount) {
3876 $updown .= "<a href=\"$filtersurl&action=down&filterpath=$upath\">";
3877 $updown .= "<img src=\"$imgurl/down.gif\" alt=\"$strdown\" /></a>";
3880 $updown .= "<img src=\"$CFG->pixpath/spacer.gif\" class=\"icon\" alt=\"\" />";
3885 // settings link (if defined)
3887 if (in_array($path, $filtersettings_new)) {
3888 $settings = "<a href=\"settings.php?section=filtersetting".str_replace('/', '',$path)."\">$strsettings</a>";
3889 } else if (in_array($path, $filtersettings_old)) {
3890 $settings = "<a href=\"filter.php?filter=".urlencode($path)."\">$strsettings</a>";
3893 // write data into the table object
3894 $table->data
[] = array($displayname, $hideshow, $updown, $settings);
3896 $return .= print_table($table, true);
3897 $return .= get_string('tablenosave', 'filters');
3898 $return .= print_box_end(true);
3899 return highlight($query, $return);
3904 * Initialise admin page - this function does require login and permission
3905 * checks specified in page definition.
3906 * This function must be called on each admin page before other code.
3907 * @param string $section name of page
3909 function admin_externalpage_setup($section) {
3911 global $CFG, $PAGE, $USER;
3912 require_once($CFG->libdir
.'/blocklib.php');
3913 require_once($CFG->dirroot
.'/'.$CFG->admin
.'/pagelib.php');
3915 if ($site = get_site()) {
3918 redirect($CFG->wwwroot
.'/'.$CFG->admin
.'/index.php');
3922 $adminroot =& admin_get_root(false, false); // settings not required for external pages
3923 $extpage =& $adminroot->locate($section);
3925 if (empty($extpage) or !is_a($extpage, 'admin_externalpage')) {
3926 print_error('sectionerror', 'admin', "$CFG->wwwroot/$CFG->admin/");
3930 // this eliminates our need to authenticate on the actual pages
3931 if (!($extpage->check_access())) {
3932 print_error('accessdenied', 'admin');
3936 page_map_class(PAGE_ADMIN
, 'page_admin');
3937 $PAGE = page_create_object(PAGE_ADMIN
, 0); // there must be any constant id number
3938 $PAGE->init_extra($section); // hack alert!
3940 $adminediting = optional_param('adminedit', -1, PARAM_BOOL
);
3942 if (!isset($USER->adminediting
)) {
3943 $USER->adminediting
= false;
3946 if ($PAGE->user_allowed_editing()) {
3947 if ($adminediting == 1) {
3948 $USER->adminediting
= true;
3949 } elseif ($adminediting == 0) {
3950 $USER->adminediting
= false;
3956 * Print header for admin page
3957 * @param string $focus focus element
3959 function admin_externalpage_print_header($focus='') {
3961 if (!is_string($focus)) {
3962 $focus = ''; // BC compatibility, there used to be adminroot parameter
3965 global $CFG, $PAGE, $SITE, $THEME;
3967 define('ADMIN_EXT_HEADER_PRINTED', 'true');
3969 if (!empty($SITE->fullname
)) {
3970 $pageblocks = blocks_setup($PAGE);
3972 $preferred_width_left = bounded_number(BLOCK_L_MIN_WIDTH
,
3973 blocks_preferred_width($pageblocks[BLOCK_POS_LEFT
]),
3975 $preferred_width_right = bounded_number(BLOCK_R_MIN_WIDTH
,
3976 blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT
]),
3979 $PAGE->print_header('', $focus);
3980 echo '<table id="layout-table" summary=""><tr>';
3982 $lt = (empty($THEME->layouttable
)) ?
array('left', 'middle', 'right') : $THEME->layouttable
;
3983 foreach ($lt as $column) {
3985 if ($column == 'middle') break;
3987 foreach ($lt1 as $column) {
3990 echo '<td style="width: '.$preferred_width_left.'px;" id="left-column">';
3991 print_container_start();
3992 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT
);
3993 print_container_end();
3998 echo '<td id="middle-column">';
3999 print_container_start(true);
4000 $THEME->open_header_containers++
; // this is hacky workaround for the error()/notice() autoclosing problems on admin pages
4004 if (blocks_have_content($pageblocks, BLOCK_POS_RIGHT
)) {
4005 echo '<td style="width: '.$preferred_width_right.'px;" id="right-column">';
4006 print_container_start();
4007 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT
);
4008 print_container_end();
4020 * Print footer on admin page - please use normal print_footer() instead
4022 function admin_externalpage_print_footer() {
4024 global $CFG, $PAGE, $SITE, $THEME;
4026 define('ADMIN_EXT_FOOTER_PRINTED', 'true');
4028 if (!empty($SITE->fullname
)) {
4029 $pageblocks = blocks_setup($PAGE);
4030 $preferred_width_left = bounded_number(BLOCK_L_MIN_WIDTH
,
4031 blocks_preferred_width($pageblocks[BLOCK_POS_LEFT
]),
4033 $preferred_width_right = bounded_number(BLOCK_R_MIN_WIDTH
,
4034 blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT
]),
4037 $lt = (empty($THEME->layouttable
)) ?
array('left', 'middle', 'right') : $THEME->layouttable
;
4038 foreach ($lt as $column) {
4039 if ($column != 'middle') {
4041 } else if ($column == 'middle') {
4045 foreach ($lt as $column) {
4048 echo '<td style="width: '.$preferred_width_left.'px;" id="left-column">';
4049 print_container_start();
4050 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT
);
4051 print_container_end();
4056 print_container_end();
4057 $THEME->open_header_containers
--; // this is hacky workaround for the error()/notice() autoclosing problems on admin pages
4062 if (blocks_have_content($pageblocks, BLOCK_POS_RIGHT
)) {
4063 echo '<td style="width: '.$preferred_width_right.'px;" id="right-column">';
4064 print_container_start();
4065 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT
);
4066 print_container_end();
4072 echo '</tr></table>';
4078 * Returns the reference to admin tree root
4081 function &admin_get_root($reload=false, $requirefulltree=true) {
4084 static $ADMIN = NULL;
4086 if (!is_null($ADMIN)) {
4087 $olderrors = $ADMIN->errors
;
4088 $oldsearch = $ADMIN->search
;
4089 $oldfulltree = $ADMIN->fulltree
;
4091 $olderrors = array();
4093 $oldfulltree = false;
4096 if ($reload or ($requirefulltree and !$oldfulltree)) {
4100 if (is_null($ADMIN)) {
4101 // start the admin tree!
4102 $ADMIN = new admin_root();
4103 // array of error messages and search query
4104 $ADMIN->errors
= $olderrors;
4105 $ADMIN->search
= $oldsearch;
4106 if ($requirefulltree) {
4107 $ADMIN->fulltree
= true;
4109 $ADMIN->fulltree
= $oldfulltree;
4112 // we process this file first to create categories first and in correct order
4113 require($CFG->dirroot
.'/'.$CFG->admin
.'/settings/top.php');
4115 // now we process all other files in admin/settings to build the admin tree
4116 foreach (glob($CFG->dirroot
.'/'.$CFG->admin
.'/settings/*.php') as $file) {
4117 if ($file != $CFG->dirroot
.'/'.$CFG->admin
.'/settings/top.php') {
4121 if (file_exists($CFG->dirroot
.'/local/settings.php')) {
4122 include_once($CFG->dirroot
.'/local/settings.php');
4129 /// settings utility functions
4132 * This function applies default settings.
4133 * @param object $node, NULL means complete tree
4134 * @param bool $uncoditional if true overrides all values with defaults
4137 function admin_apply_default_settings($node=NULL, $unconditional=true) {
4140 if (is_null($node)) {
4141 $node =& admin_get_root();
4144 if (is_a($node, 'admin_category')) {
4145 $entries = array_keys($node->children
);
4146 foreach ($entries as $entry) {
4147 admin_apply_default_settings($node->children
[$entry], $unconditional);
4150 } else if (is_a($node, 'admin_settingpage')) {
4151 foreach ($node->settings
as $setting) {
4152 if (!$unconditional and !is_null($setting->get_setting())) {
4153 //do not override existing defaults
4156 $defaultsetting = $setting->get_defaultsetting();
4157 if (is_null($defaultsetting)) {
4158 // no value yet - default maybe applied after admin user creation or in upgradesettings
4161 $setting->write_setting($defaultsetting);
4167 * Store changed settings, this function updates the errors variable in $ADMIN
4168 * @param object $formdata from form (without magic quotes)
4169 * @return int number of changed settings
4171 function admin_write_settings($formdata) {
4172 global $CFG, $SITE, $COURSE;
4174 $olddbsessions = !empty($CFG->dbsessions
);
4175 $formdata = (array)stripslashes_recursive($formdata);
4178 foreach ($formdata as $fullname=>$value) {
4179 if (strpos($fullname, 's_') !== 0) {
4180 continue; // not a config value
4182 $data[$fullname] = $value;
4185 $adminroot =& admin_get_root();
4186 $settings = admin_find_write_settings($adminroot, $data);
4189 foreach ($settings as $fullname=>$setting) {
4190 $original = serialize($setting->get_setting()); // comparison must work for arrays too
4191 $error = $setting->write_setting($data[$fullname]);
4192 if ($error !== '') {
4193 $adminroot->errors
[$fullname] = new object();
4194 $adminroot->errors
[$fullname]->data
= $data[$fullname];
4195 $adminroot->errors
[$fullname]->id
= $setting->get_id();
4196 $adminroot->errors
[$fullname]->error
= $error;
4198 if ($original !== serialize($setting->get_setting())) {
4200 $callbackfunction = $setting->updatedcallback
;
4201 if (function_exists($callbackfunction)) {
4202 $callbackfunction($fullname);
4207 if ($olddbsessions != !empty($CFG->dbsessions
)) {
4211 // now update $SITE - it might have been changed
4212 $SITE = get_record('course', 'id', $SITE->id
);
4213 $COURSE = clone($SITE);
4215 // now reload all settings - some of them might depend on the changed
4216 admin_get_root(true);
4221 * Internal recursive function - finds all settings from submitted form
4223 function admin_find_write_settings($node, $data) {
4230 if (is_a($node, 'admin_category')) {
4231 $entries = array_keys($node->children
);
4232 foreach ($entries as $entry) {
4233 $return = array_merge($return, admin_find_write_settings($node->children
[$entry], $data));
4236 } else if (is_a($node, 'admin_settingpage')) {
4237 foreach ($node->settings
as $setting) {
4238 $fullname = $setting->get_full_name();
4239 if (array_key_exists($fullname, $data)) {
4240 $return[$fullname] = $setting;
4250 * Internal function - prints the search results
4252 function admin_search_settings_html($query) {
4255 $textlib = textlib_get_instance();
4256 if ($textlib->strlen($query) < 2) {
4259 $query = $textlib->strtolower($query);
4261 $adminroot =& admin_get_root();
4262 $findings = $adminroot->search($query);
4264 $savebutton = false;
4266 foreach ($findings as $found) {
4267 $page = $found->page
;
4268 $settings = $found->settings
;
4269 if ($page->is_hidden()) {
4270 // hidden pages are not displayed in search results
4273 if (is_a($page, 'admin_externalpage')) {
4274 $return .= print_heading(get_string('searchresults','admin').' - <a href="'.$page->url
.'">'.highlight($query, $page->visiblename
).'</a>', '', 2, 'main', true);
4275 } else if (is_a($page, 'admin_settingpage')) {
4276 $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);
4280 if (!empty($settings)) {
4282 $return .= '<fieldset class="adminsettings">'."\n";
4283 foreach ($settings as $setting) {
4284 $return .= '<div class="clearer"><!-- --></div>'."\n";
4285 $fullname = $setting->get_full_name();
4286 if (array_key_exists($fullname, $adminroot->errors
)) {
4287 $data = $adminroot->errors
[$fullname]->data
;
4289 $data = $setting->get_setting();
4290 if (is_null($data)) {
4291 $data = $setting->get_defaultsetting();
4294 $return .= $setting->output_html($data, $query);
4296 $return .= '</fieldset>';
4301 $return .= '<div class="form-buttons"><input class="form-submit" type="submit" value="'.get_string('savechanges','admin').'" /></div>';
4308 * Internal function - prints list of uninitialised settings
4310 function admin_output_new_settings_by_page($node) {
4313 if (is_a($node, 'admin_category')) {
4314 $entries = array_keys($node->children
);
4315 foreach ($entries as $entry) {
4316 $return .= admin_output_new_settings_by_page($node->children
[$entry]);
4319 } else if (is_a($node, 'admin_settingpage')) {
4320 $newsettings = array();
4321 foreach ($node->settings
as $setting) {
4322 if (is_null($setting->get_setting())) {
4323 $newsettings[] = $setting;
4326 if (count($newsettings) > 0) {
4327 $adminroot =& admin_get_root();
4328 $return .= print_heading(get_string('upgradesettings','admin').' - '.$node->visiblename
, '', 2, 'main', true);
4329 $return .= '<fieldset class="adminsettings">'."\n";
4330 foreach ($newsettings as $setting) {
4331 $fullname = $setting->get_full_name();
4332 if (array_key_exists($fullname, $adminroot->errors
)) {
4333 $data = $adminroot->errors
[$fullname]->data
;
4335 $data = $setting->get_setting();
4336 if (is_null($data)) {
4337 $data = $setting->get_defaultsetting();
4340 $return .= '<div class="clearer"><!-- --></div>'."\n";
4341 $return .= $setting->output_html($data);
4343 $return .= '</fieldset>';
4351 * Unconditionally applies default admin settings in main config table
4352 * @param array $defaults array of string values
4354 function apply_default_exception_settings($defaults) {
4355 foreach($defaults as $key => $value) {
4356 set_config($key, $value, NULL);
4361 * Format admin settings
4362 * @param string $object setting
4363 * @param string $title label element
4364 * @param string $form form fragment, html code - not highlighed automaticaly
4365 * @param string $description
4366 * @param bool $label link label to id
4367 * @param string $warning warning text
4368 * @param sting $defaultinfo defaults info, null means nothing, '' is converted to "Empty" string
4369 * @param string $query search query to be highlighted
4371 function format_admin_setting($setting, $title='', $form='', $description='', $label=true, $warning='', $defaultinfo=NULL, $query='') {
4374 $name = $setting->name
;
4375 $fullname = $setting->get_full_name();
4377 // sometimes the id is not id_s_name, but id_s_name_m or something, and this does not validate
4379 $labelfor = 'for = "'.$setting->get_id().'"';
4384 if (empty($setting->plugin
) and array_key_exists($name, $CFG->config_php_settings
)) {
4385 $override = '<div class="form-overridden">'.get_string('configoverride', 'admin').'</div>';
4390 if ($warning !== '') {
4391 $warning = '<div class="form-warning">'.$warning.'</div>';
4394 if (is_null($defaultinfo)) {
4397 if ($defaultinfo === '') {
4398 $defaultinfo = get_string('emptysettingvalue', 'admin');
4400 $defaultinfo = highlight($query, nl2br(s($defaultinfo)));
4401 $defaultinfo = '<div class="form-defaultinfo">'.get_string('defaultsettinginfo', 'admin', $defaultinfo).'</div>';
4406 <div class="form-item clearfix" id="admin-'.$setting->name
.'">
4407 <div class="form-label">
4408 <label '.$labelfor.'>'.highlightfast($query, $title).'<span class="form-shortname">'.highlightfast($query, $name).'</span>
4409 '.$override.$warning.'
4412 <div class="form-setting">'.$form.$defaultinfo.'</div>
4413 <div class="form-description">'.highlight($query, $description).'</div>
4416 $adminroot =& admin_get_root();
4417 if (array_key_exists($fullname, $adminroot->errors
)) {
4418 $str = '<fieldset class="error"><legend>'.$adminroot->errors
[$fullname]->error
.'</legend>'.$str.'</fieldset>';
4425 * Try to upgrade the given language pack (or current language)
4426 * If it doesn't work, fail silently and return false
4428 function upgrade_language_pack($lang='') {
4432 $lang = current_language();
4435 if ($lang == 'en_utf8') {
4436 return true; // Nothing to do
4439 notify(get_string('langimport', 'admin').': '.$lang.' ... ', 'notifysuccess');
4441 @mkdir
($CFG->dataroot
.'/temp/'); //make it in case it's a fresh install, it might not be there
4442 @mkdir
($CFG->dataroot
.'/lang/');
4444 require_once($CFG->libdir
.'/componentlib.class.php');
4446 if ($cd = new component_installer('http://download.moodle.org', 'lang16', $lang.'.zip', 'languages.md5', 'lang')) {
4447 $status = $cd->install(); //returns COMPONENT_(ERROR | UPTODATE | INSTALLED)
4449 if ($status == COMPONENT_INSTALLED
) {
4450 debugging('Downloading successful: '.$lang);
4451 @unlink
($CFG->dataroot
.'/cache/languages');
4460 * Based on find_new_settings{@link ()} in upgradesettings.php
4461 * Looks to find any admin settings that have not been initialized. Returns 1 if it finds any.
4463 * @param string $node The node at which to start searching.
4464 * @return boolen true if any settings haven't been initialised, false if they all have
4466 function any_new_admin_settings($node) {
4468 if (is_a($node, 'admin_category')) {
4469 $entries = array_keys($node->children
);
4470 foreach ($entries as $entry) {
4471 if (any_new_admin_settings($node->children
[$entry])){
4476 } else if (is_a($node, 'admin_settingpage')) {
4477 foreach ($node->settings
as $setting) {
4478 if ($setting->get_setting() === NULL) {
4489 * Moved from admin/replace.php so that we can use this in cron
4490 * @param string $search - string to look for (with magic quotes)
4491 * @param string $replace - string to replace (with magic quotes)
4492 * @return bool - success or fail
4494 function db_replace($search, $replace) {
4498 /// Turn off time limits, sometimes upgrades can be slow.
4500 @ob_implicit_flush
(true);
4501 while(@ob_end_flush
());
4503 if (!$tables = $db->Metatables() ) { // No tables yet at all.
4506 foreach ($tables as $table) {
4508 if (in_array($table, array($CFG->prefix
.'config'))) { // Don't process these
4512 if ($columns = $db->MetaColumns($table, false)) {
4513 foreach ($columns as $column => $data) {
4514 if (in_array($data->type
, array('text','mediumtext','longtext','varchar'))) { // Text stuff only
4516 execute_sql("UPDATE $table SET $column = REPLACE($column, '$search', '$replace');");
4527 * Prints tables of detected plugins, one table per plugin type,
4528 * and prints whether they are part of the standard Moodle
4529 * distribution or not.
4531 function print_plugin_tables() {
4532 $plugins_standard = array();
4533 $plugins_standard['mod'] = array('assignment',
4552 $plugins_standard['blocks'] = array('activity_modules',
4559 'calendar_upcoming',
4579 'social_activities',
4584 $plugins_standard['filter'] = array('activitynames',
4594 $plugins_installed = array();
4595 $installed_mods = get_records_list('modules', '', '', '', 'name');
4596 $installed_blocks = get_records_list('block', '', '', '', 'name');
4598 foreach($installed_mods as $mod) {
4599 $plugins_installed['mod'][] = $mod->name
;
4602 foreach($installed_blocks as $block) {
4603 $plugins_installed['blocks'][] = $block->name
;
4606 $plugins_ondisk = array();
4607 $plugins_ondisk['mod'] = get_list_of_plugins('mod', 'db');
4608 $plugins_ondisk['blocks'] = get_list_of_plugins('blocks', 'db');
4609 $plugins_ondisk['filter'] = get_list_of_plugins('filter', 'db');
4611 $strstandard = get_string('standard');
4612 $strnonstandard = get_string('nonstandard');
4613 $strmissingfromdisk = '(' . get_string('missingfromdisk') . ')';
4614 $strabouttobeinstalled = '(' . get_string('abouttobeinstalled') . ')';
4618 $html .= '<table class="generaltable plugincheckwrapper" cellspacing="4" cellpadding="1"><tr valign="top">';
4620 foreach ($plugins_ondisk as $cat => $list_ondisk) {
4621 $strcaption = get_string($cat);
4622 if ($cat == 'mod') {
4623 $strcaption = get_string('activitymodule');
4624 } elseif ($cat == 'filter') {
4625 $strcaption = get_string('managefilters');
4628 $html .= '<td><table class="plugincompattable generaltable boxaligncenter" cellspacing="1" cellpadding="5" '
4629 . 'id="' . $cat . 'compattable" summary="compatibility table"><caption>' . $strcaption . '</caption>' . "\n";
4630 $html .= '<tr class="r0"><th class="header c0">' . get_string('directory') . "</th>\n"
4631 . '<th class="header c1">' . get_string('name') . "</th>\n"
4632 . '<th class="header c2">' . get_string('status') . "</th>\n</tr>\n";
4636 foreach ($list_ondisk as $k => $plugin) {
4638 $standard = 'standard';
4641 if (!in_array($plugin, $plugins_standard[$cat])) {
4642 $standard = 'nonstandard';
4643 $status = 'warning';
4646 // Get real name and full path of plugin
4647 $plugin_name = "[[$plugin]]";
4649 $plugin_path = "$cat/$plugin";
4651 $plugin_name = get_plugin_name($plugin, $cat);
4653 // Determine if the plugin is about to be installed
4654 if ($cat != 'filter' && !in_array($plugin, $plugins_installed[$cat])) {
4655 $note = $strabouttobeinstalled;
4656 $plugin_name = $plugin;
4659 $html .= "<tr class=\"r$row\">\n"
4660 . "<td class=\"cell c0\">$plugin_path</td>\n"
4661 . "<td class=\"cell c1\">$plugin_name</td>\n"
4662 . "<td class=\"$standard $status cell c2\">" . $
{'str' . $standard} . " $note</td>\n</tr>\n";
4665 // If the plugin was both on disk and in the db, unset the value from the installed plugins list
4666 if ($key = array_search($plugin, $plugins_installed[$cat])) {
4667 unset($plugins_installed[$cat][$key]);
4671 // If there are plugins left in the plugins_installed list, it means they are missing from disk
4672 foreach ($plugins_installed[$cat] as $k => $missing_plugin) {
4673 // Make sure the plugin really is missing from disk
4674 if (!in_array($missing_plugin, $plugins_ondisk[$cat])) {
4675 $standard = 'standard';
4676 $status = 'warning';
4678 if (!in_array($missing_plugin, $plugins_standard[$cat])) {
4679 $standard = 'nonstandard';
4682 $plugin_name = $missing_plugin;
4683 $html .= "<tr class=\"r$row\">\n"
4684 . "<td class=\"cell c0\">?</td>\n"
4685 . "<td class=\"cell c1\">$plugin_name</td>\n"
4686 . "<td class=\"$standard $status cell c2\">" . $
{'str' . $standard} . " $strmissingfromdisk</td>\n</tr>\n";
4691 $html .= '</table></td>';
4694 $html .= '</tr></table><br />';