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='') {
495 if ($total < 2) { // No need to show anything
499 if (empty($starttime)) {
500 $starttime = $lasttime = time();
501 $lasttime = $starttime - $updatetime;
502 echo '<table width="500" cellpadding="0" cellspacing="0" align="center"><tr><td width="500">';
503 echo '<div id="bar'.$total.'" style="border-style:solid;border-width:1px;width:500px;height:50px;">';
504 echo '<div id="slider'.$total.'" style="border-style:solid;border-width:1px;height:48px;width:10px;background-color:green;"></div>';
506 echo '<div id="text'.$total.'" align="center" style="width:500px;"></div>';
507 echo '</td></tr></table>';
513 if ($done && (($now - $lasttime) >= $updatetime)) {
514 $elapsedtime = $now - $starttime;
515 $projectedtime = (int)(((float)$total / (float)$done) * $elapsedtime) - $elapsedtime;
516 $percentage = round((float)$done / (float)$total, 2);
517 $width = (int)(500 * $percentage);
519 if ($projectedtime > 10) {
520 $projectedtext = ' Ending: '.format_time($projectedtime);
526 echo 'document.getElementById("text'.$total.'").innerHTML = "'.addslashes($donetext).' ('.$done.'/'.$total.') '.$projectedtext.'";'."\n";
527 echo 'document.getElementById("slider'.$total.'").style.width = \''.$width.'px\';'."\n";
535 function upgrade_get_javascript() {
538 if (!empty($_SESSION['installautopilot'])) {
539 $linktoscrolltoerrors = '<script type="text/javascript">var installautopilot = true;</script>'."\n";
541 $linktoscrolltoerrors = '<script type="text/javascript">var installautopilot = false;</script>'."\n";
543 $linktoscrolltoerrors .= '<script type="text/javascript" src="' . $CFG->wwwroot
. '/lib/scroll_to_errors.js"></script>';
545 return $linktoscrolltoerrors;
548 function create_admin_user() {
551 if (empty($CFG->rolesactive
)) { // No admin user yet.
553 $user = new object();
554 $user->auth
= 'manual';
555 $user->firstname
= get_string('admin');
556 $user->lastname
= get_string('user');
557 $user->username
= 'admin';
558 $user->password
= hash_internal_user_password('admin');
559 $user->email
= 'root@localhost';
560 $user->confirmed
= 1;
561 $user->mnethostid
= $CFG->mnet_localhost_id
;
562 $user->lang
= $CFG->lang
;
563 $user->maildisplay
= 1;
564 $user->timemodified
= time();
566 if (!$user->id
= insert_record('user', $user)) {
567 error('SERIOUS ERROR: Could not create admin user record !!!');
570 if (!$user = get_record('user', 'id', $user->id
)) { // Double check.
571 error('User ID was incorrect (can\'t find it)');
574 // Assign the default admin roles to the new user.
575 if (!$adminroles = get_roles_with_capability('moodle/legacy:admin', CAP_ALLOW
)) {
576 error('No admin role could be found');
578 $sitecontext = get_context_instance(CONTEXT_SYSTEM
);
579 foreach ($adminroles as $adminrole) {
580 role_assign($adminrole->id
, $user->id
, 0, $sitecontext->id
);
583 set_config('rolesactive', 1);
586 $USER = get_complete_user_data('username', 'admin');
587 $USER->newadminuser
= 1;
588 load_all_capabilities();
590 redirect("$CFG->wwwroot/user/editadvanced.php?id=$user->id"); // Edit thyself
592 error('Can not create admin!');
596 ////////////////////////////////////////////////
597 /// upgrade logging functions
598 ////////////////////////////////////////////////
600 $upgradeloghandle = false;
601 $upgradelogbuffer = '';
602 // I did not find out how to use static variable in callback function,
603 // the problem was that I could not flush the static buffer :-(
604 global $upgradeloghandle, $upgradelogbuffer;
607 * Check if upgrade is already running.
609 * If anything goes wrong due to missing call to upgrade_log_finish()
610 * just restart the browser.
612 * @param string warning message indicating upgrade is already running
613 * @param int page reload timeout
615 function upgrade_check_running($message, $timeout) {
616 if (!empty($_SESSION['upgraderunning'])) {
618 redirect(me(), $message, $timeout);
623 * Start logging of output into file (if not disabled) and
624 * prevent aborting and concurrent execution of upgrade script.
626 * Please note that you can not write into session variables after calling this function!
628 * This function may be called repeatedly.
630 function upgrade_log_start() {
631 global $CFG, $upgradeloghandle;
633 if (!empty($_SESSION['upgraderunning'])) {
634 return; // logging already started
637 @ignore_user_abort
(true); // ignore if user stops or otherwise aborts page loading
638 $_SESSION['upgraderunning'] = 1; // set upgrade indicator
639 if (empty($CFG->dbsessions
)) { // workaround for bug in adodb, db session can not be restarted
640 session_write_close(); // from now on user can reload page - will be displayed warning
642 make_upload_directory('upgradelogs');
643 ob_start('upgrade_log_callback', 2); // function for logging to disk; flush each line of text ASAP
644 register_shutdown_function('upgrade_log_finish'); // in case somebody forgets to stop logging
648 * Terminate logging of output, flush all data, allow script aborting
649 * and reopen session for writing. Function error() does terminate the logging too.
651 * Please make sure that each upgrade_log_start() is properly terminated by
652 * this function or error().
654 * This function may be called repeatedly.
656 function upgrade_log_finish() {
657 global $CFG, $upgradeloghandle, $upgradelogbuffer;
659 if (empty($_SESSION['upgraderunning'])) {
660 return; // logging already terminated
664 if ($upgradelogbuffer !== '') {
665 @fwrite
($upgradeloghandle, $upgradelogbuffer);
666 $upgradelogbuffer = '';
668 if ($upgradeloghandle and ($upgradeloghandle !== 'error')) {
669 @fclose
($upgradeloghandle);
670 $upgradeloghandle = false;
672 if (empty($CFG->dbsessions
)) {
673 @session_start
(); // ignore header errors, we only need to reopen session
675 $_SESSION['upgraderunning'] = 0; // clear upgrade indicator
676 if (connection_aborted()) {
679 @ignore_user_abort
(false);
683 * Callback function for logging into files. Not more than one file is created per minute,
684 * upgrade session (terminated by upgrade_log_finish()) is always stored in one file.
686 * This function must not output any characters or throw warnigns and errors!
688 function upgrade_log_callback($string) {
689 global $CFG, $upgradeloghandle, $upgradelogbuffer;
691 if (empty($CFG->disableupgradelogging
) and ($string != '') and ($upgradeloghandle !== 'error')) {
692 if ($upgradeloghandle or ($upgradeloghandle = @fopen
($CFG->dataroot
.'/upgradelogs/upg_'.date('Ymd-Hi').'.html', 'a'))) {
693 $upgradelogbuffer .= $string;
694 if (strlen($upgradelogbuffer) > 2048) { // 2kB write buffer
695 @fwrite
($upgradeloghandle, $upgradelogbuffer);
696 $upgradelogbuffer = '';
699 $upgradeloghandle = 'error';
706 * Try to verify that dataroot is not accessible from web.
707 * It is not 100% correct but might help to reduce number of vulnerable sites.
709 * Protection from httpd.conf and .htaccess is not detected properly.
711 function is_dataroot_insecure() {
714 $siteroot = str_replace('\\', '/', strrev($CFG->dirroot
.'/')); // win32 backslash workaround
716 $rp = preg_replace('|https?://[^/]+|i', '', $CFG->wwwroot
, 1);
717 $rp = strrev(trim($rp, '/'));
718 $rp = explode('/', $rp);
720 if (strpos($siteroot, '/'.$r.'/') === 0) {
721 $siteroot = substr($siteroot, strlen($r)+
1); // moodle web in subdirectory
723 break; // probably alias root
727 $siteroot = strrev($siteroot);
728 $dataroot = str_replace('\\', '/', $CFG->dataroot
.'/');
730 if (strpos($dataroot, $siteroot) === 0) {
736 /// =============================================================================================================
737 /// administration tree classes and functions
740 // n.b. documentation is still in progress for this code
744 /// This file performs the following tasks:
745 /// -it defines the necessary objects and interfaces to build the Moodle
747 /// -it defines the admin_externalpage_setup(), admin_externalpage_print_header(),
748 /// and admin_externalpage_print_footer() functions used on admin pages
750 /// ADMIN_SETTING OBJECTS
752 /// Moodle settings are represented by objects that inherit from the admin_setting
753 /// class. These objects encapsulate how to read a setting, how to write a new value
754 /// to a setting, and how to appropriately display the HTML to modify the setting.
756 /// ADMIN_SETTINGPAGE OBJECTS
758 /// The admin_setting objects are then grouped into admin_settingpages. The latter
759 /// appear in the Moodle admin tree block. All interaction with admin_settingpage
760 /// objects is handled by the admin/settings.php file.
762 /// ADMIN_EXTERNALPAGE OBJECTS
764 /// There are some settings in Moodle that are too complex to (efficiently) handle
765 /// with admin_settingpages. (Consider, for example, user management and displaying
766 /// lists of users.) In this case, we use the admin_externalpage object. This object
767 /// places a link to an external PHP file in the admin tree block.
769 /// If you're using an admin_externalpage object for some settings, you can take
770 /// advantage of the admin_externalpage_* functions. For example, suppose you wanted
771 /// to add a foo.php file into admin. First off, you add the following line to
772 /// admin/settings/first.php (at the end of the file) or to some other file in
775 /// $ADMIN->add('userinterface', new admin_externalpage('foo', get_string('foo'),
776 /// $CFG->wwwdir . '/' . '$CFG->admin . '/foo.php', 'some_role_permission'));
778 /// Next, in foo.php, your file structure would resemble the following:
780 /// require_once('.../config.php');
781 /// require_once($CFG->libdir.'/adminlib.php');
782 /// admin_externalpage_setup('foo');
783 /// // functionality like processing form submissions goes here
784 /// admin_externalpage_print_header();
785 /// // your HTML goes here
786 /// admin_externalpage_print_footer();
788 /// The admin_externalpage_setup() function call ensures the user is logged in,
789 /// and makes sure that they have the proper role permission to access the page.
791 /// The admin_externalpage_print_header() function prints the header (it figures
792 /// out what category and subcategories the page is classified under) and ensures
793 /// that you're using the admin pagelib (which provides the admin tree block and
794 /// the admin bookmarks block).
796 /// The admin_externalpage_print_footer() function properly closes the tables
797 /// opened up by the admin_externalpage_print_header() function and prints the
798 /// standard Moodle footer.
800 /// ADMIN_CATEGORY OBJECTS
802 /// Above and beyond all this, we have admin_category objects. These objects
803 /// appear as folders in the admin tree block. They contain admin_settingpage's,
804 /// admin_externalpage's, and other admin_category's.
808 /// admin_settingpage's, admin_externalpage's, and admin_category's all inherit
809 /// from part_of_admin_tree (a pseudointerface). This interface insists that
810 /// a class has a check_access method for access permissions, a locate method
811 /// used to find a specific node in the admin tree and find parent path.
813 /// admin_category's inherit from parentable_part_of_admin_tree. This pseudo-
814 /// interface ensures that the class implements a recursive add function which
815 /// accepts a part_of_admin_tree object and searches for the proper place to
816 /// put it. parentable_part_of_admin_tree implies part_of_admin_tree.
818 /// Please note that the $this->name field of any part_of_admin_tree must be
819 /// UNIQUE throughout the ENTIRE admin tree.
821 /// The $this->name field of an admin_setting object (which is *not* part_of_
822 /// admin_tree) must be unique on the respective admin_settingpage where it is
826 /// CLASS DEFINITIONS /////////////////////////////////////////////////////////
829 * Pseudointerface for anything appearing in the admin tree
831 * The pseudointerface that is implemented by anything that appears in the admin tree
832 * block. It forces inheriting classes to define a method for checking user permissions
833 * and methods for finding something in the admin tree.
835 * @author Vincenzo K. Marcovecchio
838 class part_of_admin_tree
{
841 * Finds a named part_of_admin_tree.
843 * Used to find a part_of_admin_tree. If a class only inherits part_of_admin_tree
844 * and not parentable_part_of_admin_tree, then this function should only check if
845 * $this->name matches $name. If it does, it should return a reference to $this,
846 * otherwise, it should return a reference to NULL.
848 * If a class inherits parentable_part_of_admin_tree, this method should be called
849 * recursively on all child objects (assuming, of course, the parent object's name
850 * doesn't match the search criterion).
852 * @param string $name The internal name of the part_of_admin_tree we're searching for.
853 * @return mixed An object reference or a NULL reference.
855 function &locate($name) {
856 trigger_error('Admin class does not implement method <strong>locate()</strong>', E_USER_WARNING
);
861 * Removes named part_of_admin_tree.
863 * @param string $name The internal name of the part_of_admin_tree we want to remove.
864 * @return bool success.
866 function prune($name) {
867 trigger_error('Admin class does not implement method <strong>prune()</strong>', E_USER_WARNING
);
874 * @return mixed array-object structure of found settings and pages
876 function search($query) {
877 trigger_error('Admin class does not implement method <strong>search()</strong>', E_USER_WARNING
);
882 * Verifies current user's access to this part_of_admin_tree.
884 * Used to check if the current user has access to this part of the admin tree or
885 * not. If a class only inherits part_of_admin_tree and not parentable_part_of_admin_tree,
886 * then this method is usually just a call to has_capability() in the site context.
888 * If a class inherits parentable_part_of_admin_tree, this method should return the
889 * logical OR of the return of check_access() on all child objects.
891 * @return bool True if the user has access, false if she doesn't.
893 function check_access() {
894 trigger_error('Admin class does not implement method <strong>check_access()</strong>', E_USER_WARNING
);
899 * Mostly usefull for removing of some parts of the tree in admin tree block.
901 * @return True is hidden from normal list view
903 function is_hidden() {
904 trigger_error('Admin class does not implement method <strong>is_hidden()</strong>', E_USER_WARNING
);
910 * Pseudointerface implemented by any part_of_admin_tree that has children.
912 * The pseudointerface implemented by any part_of_admin_tree that can be a parent
913 * to other part_of_admin_tree's. (For now, this only includes admin_category.) Apart
914 * from ensuring part_of_admin_tree compliancy, it also ensures inheriting methods
915 * include an add method for adding other part_of_admin_tree objects as children.
917 * @author Vincenzo K. Marcovecchio
920 class parentable_part_of_admin_tree
extends part_of_admin_tree
{
923 * Adds a part_of_admin_tree object to the admin tree.
925 * Used to add a part_of_admin_tree object to this object or a child of this
926 * object. $something should only be added if $destinationname matches
927 * $this->name. If it doesn't, add should be called on child objects that are
928 * also parentable_part_of_admin_tree's.
930 * @param string $destinationname The internal name of the new parent for $something.
931 * @param part_of_admin_tree &$something The object to be added.
932 * @return bool True on success, false on failure.
934 function add($destinationname, $something) {
935 trigger_error('Admin class does not implement method <strong>add()</strong>', E_USER_WARNING
);
942 * The object used to represent folders (a.k.a. categories) in the admin tree block.
944 * Each admin_category object contains a number of part_of_admin_tree objects.
946 * @author Vincenzo K. Marcovecchio
949 class admin_category
extends parentable_part_of_admin_tree
{
952 * @var mixed An array of part_of_admin_tree objects that are this object's children
957 * @var string An internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
962 * @var string The displayed name for this category. Usually obtained through get_string()
967 * @var bool Should this category be hidden in admin tree block?
978 * Constructor for an empty admin category
980 * @param string $name The internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
981 * @param string $visiblename The displayed named for this category. Usually obtained through get_string()
982 * @param bool $hidden hide category in admin tree block
984 function admin_category($name, $visiblename, $hidden=false) {
985 $this->children
= array();
987 $this->visiblename
= $visiblename;
988 $this->hidden
= $hidden;
992 * Returns a reference to the part_of_admin_tree object with internal name $name.
994 * @param string $name The internal name of the object we want.
995 * @param bool $findpath initialize path and visiblepath arrays
996 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
998 function &locate($name, $findpath=false) {
999 if ($this->name
== $name) {
1001 $this->visiblepath
[] = $this->visiblename
;
1002 $this->path
[] = $this->name
;
1008 foreach($this->children
as $childid=>$unused) {
1009 if ($return =& $this->children
[$childid]->locate($name, $findpath)) {
1014 if (!is_null($return) and $findpath) {
1015 $return->visiblepath
[] = $this->visiblename
;
1016 $return->path
[] = $this->name
;
1023 * Search using query
1024 * @param strin query
1025 * @return mixed array-object structure of found settings and pages
1027 function search($query) {
1029 foreach ($this->children
as $child) {
1030 $subsearch = $child->search($query);
1031 if (!is_array($subsearch)) {
1032 debugging('Incorrect search result from '.$child->name
);
1035 $result = array_merge($result, $subsearch);
1041 * Removes part_of_admin_tree object with internal name $name.
1043 * @param string $name The internal name of the object we want to remove.
1044 * @return bool success
1046 function prune($name) {
1048 if ($this->name
== $name) {
1049 return false; //can not remove itself
1052 foreach($this->children
as $precedence => $child) {
1053 if ($child->name
== $name) {
1055 unset($this->children
[$precedence]);
1058 if ($this->children
[$precedence]->prune($name)) {
1066 * Adds a part_of_admin_tree to a child or grandchild (or great-grandchild, and so forth) of this object.
1068 * @param string $destinationame The internal name of the immediate parent that we want for $something.
1069 * @param mixed $something A part_of_admin_tree or setting instanceto be added.
1070 * @return bool True if successfully added, false if $something can not be added.
1072 function add($parentname, $something) {
1073 $parent =& $this->locate($parentname);
1074 if (is_null($parent)) {
1075 debugging('parent does not exist!');
1079 if (is_a($something, 'part_of_admin_tree')) {
1080 if (!is_a($parent, 'parentable_part_of_admin_tree')) {
1081 debugging('error - parts of tree can be inserted only into parentable parts');
1084 $parent->children
[] = $something;
1088 debugging('error - can not add this element');
1095 * Checks if the user has access to anything in this category.
1097 * @return bool True if the user has access to atleast one child in this category, false otherwise.
1099 function check_access() {
1100 foreach ($this->children
as $child) {
1101 if ($child->check_access()) {
1109 * Is this category hidden in admin tree block?
1111 * @return bool True if hidden
1113 function is_hidden() {
1114 return $this->hidden
;
1118 class admin_root
extends admin_category
{
1130 * full tree flag - true means all settings required, false onlypages required
1135 function admin_root() {
1136 parent
::admin_category('root', get_string('administration'), false);
1137 $this->errors
= array();
1139 $this->fulltree
= true;
1144 * Links external PHP pages into the admin tree.
1146 * See detailed usage example at the top of this document (adminlib.php)
1148 * @author Vincenzo K. Marcovecchio
1151 class admin_externalpage
extends part_of_admin_tree
{
1154 * @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects
1159 * @var string The displayed name for this external page. Usually obtained through get_string().
1164 * @var string The external URL that we should link to when someone requests this external page.
1169 * @var string The role capability/permission a user must have to access this external page.
1171 var $req_capability;
1174 * @var object The context in which capability/permission should be checked, default is site context.
1179 * @var bool hidden in admin tree block.
1190 * Constructor for adding an external page into the admin tree.
1192 * @param string $name The internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects.
1193 * @param string $visiblename The displayed name for this external page. Usually obtained through get_string().
1194 * @param string $url The external URL that we should link to when someone requests this external page.
1195 * @param mixed $req_capability The role capability/permission a user must have to access this external page. Defaults to 'moodle/site:config'.
1197 function admin_externalpage($name, $visiblename, $url, $req_capability='moodle/site:config', $hidden=false, $context=NULL) {
1198 $this->name
= $name;
1199 $this->visiblename
= $visiblename;
1201 if (is_array($req_capability)) {
1202 $this->req_capability
= $req_capability;
1204 $this->req_capability
= array($req_capability);
1206 $this->hidden
= $hidden;
1207 $this->context
= $context;
1211 * Returns a reference to the part_of_admin_tree object with internal name $name.
1213 * @param string $name The internal name of the object we want.
1214 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
1216 function &locate($name, $findpath=false) {
1217 if ($this->name
== $name) {
1219 $this->visiblepath
= array($this->visiblename
);
1220 $this->path
= array($this->name
);
1229 function prune($name) {
1234 * Search using query
1235 * @param strin query
1236 * @return mixed array-object structure of found settings and pages
1238 function search($query) {
1239 $textlib = textlib_get_instance();
1242 if (strpos(strtolower($this->name
), $query) !== false) {
1244 } else if (strpos($textlib->strtolower($this->visiblename
), $query) !== false) {
1248 $result = new object();
1249 $result->page
= $this;
1250 $result->settings
= array();
1251 return array($this->name
=> $result);
1258 * Determines if the current user has access to this external page based on $this->req_capability.
1259 * @return bool True if user has access, false otherwise.
1261 function check_access() {
1263 return true; // no access check before site is fully set up
1265 $context = empty($this->context
) ?
get_context_instance(CONTEXT_SYSTEM
) : $this->context
;
1266 foreach($this->req_capability
as $cap) {
1267 if (has_capability($cap, $context)) {
1275 * Is this external page hidden in admin tree block?
1277 * @return bool True if hidden
1279 function is_hidden() {
1280 return $this->hidden
;
1286 * Used to group a number of admin_setting objects into a page and add them to the admin tree.
1288 * @author Vincenzo K. Marcovecchio
1291 class admin_settingpage
extends part_of_admin_tree
{
1294 * @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects
1299 * @var string The displayed name for this external page. Usually obtained through get_string().
1303 * @var mixed An array of admin_setting objects that are part of this setting page.
1308 * @var string The role capability/permission a user must have to access this external page.
1310 var $req_capability;
1313 * @var object The context in which capability/permission should be checked, default is site context.
1318 * @var bool hidden in admin tree block.
1328 // see admin_externalpage
1329 function admin_settingpage($name, $visiblename, $req_capability='moodle/site:config', $hidden=false, $context=NULL) {
1330 $this->settings
= new object();
1331 $this->name
= $name;
1332 $this->visiblename
= $visiblename;
1333 if (is_array($req_capability)) {
1334 $this->req_capability
= $req_capability;
1336 $this->req_capability
= array($req_capability);
1338 $this->hidden
= $hidden;
1339 $this->context
= $context;
1342 // see admin_category
1343 function &locate($name, $findpath=false) {
1344 if ($this->name
== $name) {
1346 $this->visiblepath
= array($this->visiblename
);
1347 $this->path
= array($this->name
);
1356 function search($query) {
1359 foreach ($this->settings
as $setting) {
1360 if ($setting->is_related($query)) {
1361 $found[] = $setting;
1366 $result = new object();
1367 $result->page
= $this;
1368 $result->settings
= $found;
1369 return array($this->name
=> $result);
1372 $textlib = textlib_get_instance();
1375 if (strpos(strtolower($this->name
), $query) !== false) {
1377 } else if (strpos($textlib->strtolower($this->visiblename
), $query) !== false) {
1381 $result = new object();
1382 $result->page
= $this;
1383 $result->settings
= array();
1384 return array($this->name
=> $result);
1390 function prune($name) {
1395 * 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
1396 * n.b. each admin_setting in an admin_settingpage must have a unique internal name
1397 * @param object $setting is the admin_setting object you want to add
1398 * @return true if successful, false if not
1400 function add($setting) {
1401 if (!is_a($setting, 'admin_setting')) {
1402 debugging('error - not a setting instance');
1406 $this->settings
->{$setting->name
} = $setting;
1410 // see admin_externalpage
1411 function check_access() {
1413 return true; // no access check before site is fully set up
1415 $context = empty($this->context
) ?
get_context_instance(CONTEXT_SYSTEM
) : $this->context
;
1416 foreach($this->req_capability
as $cap) {
1417 if (has_capability($cap, $context)) {
1425 * outputs this page as html in a table (suitable for inclusion in an admin pagetype)
1426 * returns a string of the html
1428 function output_html() {
1429 $adminroot =& admin_get_root();
1430 $return = '<fieldset>'."\n".'<div class="clearer"><!-- --></div>'."\n";
1431 foreach($this->settings
as $setting) {
1432 $fullname = $setting->get_full_name();
1433 if (array_key_exists($fullname, $adminroot->errors
)) {
1434 $data = $adminroot->errors
[$fullname]->data
;
1436 $data = $setting->get_setting();
1437 if (is_null($data)) {
1438 $data = $setting->get_defaultsetting();
1441 $return .= $setting->output_html($data);
1443 $return .= '</fieldset>';
1448 * Is this settigns page hidden in admin tree block?
1450 * @return bool True if hidden
1452 function is_hidden() {
1453 return $this->hidden
;
1460 * Admin settings class. Only exists on setting pages.
1461 * Read & write happens at this level; no authentication.
1463 class admin_setting
{
1468 var $defaultsetting;
1469 var $updatedcallback;
1470 var $plugin; // null means main config table
1474 * @param $name string unique ascii name
1475 * @param $visiblename string localised name
1476 * @param strin $description localised long description
1477 * @param mixed $defaultsetting string or array depending on implementation
1479 function admin_setting($name, $visiblename, $description, $defaultsetting) {
1480 $this->name
= $name;
1481 $this->visiblename
= $visiblename;
1482 $this->description
= $description;
1483 $this->defaultsetting
= $defaultsetting;
1486 function get_full_name() {
1487 return 's_'.$this->plugin
.'_'.$this->name
;
1491 return 'id_s_'.$this->plugin
.'_'.$this->name
;
1494 function config_read($name) {
1496 if ($this->plugin
=== 'backup') {
1497 require_once($CFG->dirroot
.'/backup/lib.php');
1498 $backupconfig = backup_get_config();
1499 if (isset($backupconfig->$name)) {
1500 return $backupconfig->$name;
1505 } else if (!empty($this->plugin
)) {
1506 $value = get_config($this->plugin
, $name);
1507 return $value === false ?
NULL : $value;
1510 if (isset($CFG->$name)) {
1518 function config_write($name, $value) {
1520 if ($this->plugin
=== 'backup') {
1521 require_once($CFG->dirroot
.'/backup/lib.php');
1522 return (boolean
)backup_set_config($name, $value);
1524 return (boolean
)set_config($name, $value, $this->plugin
);
1529 * Returns current value of this setting
1530 * @return mixed array or string depending on instance, NULL means not set yet
1532 function get_setting() {
1533 // has to be overridden
1538 * Returns default setting if exists
1539 * @return mixed array or string depending on instance; NULL means no default, user must supply
1541 function get_defaultsetting() {
1542 return $this->defaultsetting
;
1547 * @param mixed string or array, must not be NULL
1548 * @return '' if ok, string error message otherwise
1550 function write_setting($data) {
1551 // should be overridden
1556 * Return part of form with setting
1557 * @param mixed data array or string depending on setting
1560 function output_html($data, $query='') {
1561 // should be overridden
1566 * function called if setting updated - cleanup, cache reset, etc.
1568 function set_updatedcallback($functionname) {
1569 $this->updatedcallback
= $functionname;
1573 * Is setting related to query text - used when searching
1574 * @param string $query
1577 function is_related($query) {
1578 if (strpos(strtolower($this->name
), $query) !== false) {
1581 $textlib = textlib_get_instance();
1582 if (strpos($textlib->strtolower($this->visiblename
), $query) !== false) {
1585 if (strpos($textlib->strtolower($this->description
), $query) !== false) {
1588 $current = $this->get_setting();
1589 if (!is_null($current)) {
1590 if (is_string($current)) {
1591 if (strpos($textlib->strtolower($current), $query) !== false) {
1596 $default = $this->get_defaultsetting();
1597 if (!is_null($default)) {
1598 if (is_string($default)) {
1599 if (strpos($textlib->strtolower($default), $query) !== false) {
1609 * No setting - just heading and text.
1611 class admin_setting_heading
extends admin_setting
{
1613 * not a setting, just text
1614 * @param string $name of setting
1615 * @param string $heading heading
1616 * @param string $information text in box
1618 function admin_setting_heading($name, $heading, $information) {
1619 parent
::admin_setting($name, $heading, $information, '');
1622 function get_setting() {
1626 function get_defaultsetting() {
1630 function write_setting($data) {
1631 // do not write any setting
1635 function output_html($data, $query='') {
1637 if ($this->visiblename
!= '') {
1638 $return .= print_heading('<a name="'.$this->name
.'">'.highlightfast($query, $this->visiblename
).'</a>', '', 3, 'main', true);
1640 if ($this->description
!= '') {
1641 $return .= print_box(highlight($query, $this->description
), 'generalbox formsettingheading', '', true);
1648 * The most flexibly setting, user is typing text
1650 class admin_setting_configtext
extends admin_setting
{
1656 * config text contructor
1657 * @param string $name of setting
1658 * @param string $visiblename localised
1659 * @param string $description long localised info
1660 * @param string $defaultsetting
1661 * @param mixed $paramtype int means PARAM_XXX type, string is a allowed format in regex
1662 * @param int $size default field size
1664 function admin_setting_configtext($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW
, $size=null) {
1665 $this->paramtype
= $paramtype;
1666 if (!is_null($size)) {
1667 $this->size
= $size;
1669 $this->size
= ($paramtype == PARAM_INT
) ?
5 : 30;
1671 parent
::admin_setting($name, $visiblename, $description, $defaultsetting);
1674 function get_setting() {
1675 return $this->config_read($this->name
);
1678 function write_setting($data) {
1679 if ($this->paramtype
=== PARAM_INT
and $data === '') {
1680 // do not complain if '' used instead of 0
1683 // $data is a string
1684 $validated = $this->validate($data);
1685 if ($validated !== true) {
1688 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
1692 * Validate data before storage
1693 * @param string data
1694 * @return mixed true if ok string if error found
1696 function validate($data) {
1697 if (is_string($this->paramtype
)) {
1698 if (preg_match($this->paramtype
, $data)) {
1701 return get_string('validateerror', 'admin');
1704 } else if ($this->paramtype
=== PARAM_RAW
) {
1708 $cleaned = stripslashes(clean_param(addslashes($data), $this->paramtype
));
1709 if ("$data" == "$cleaned") { // implicit conversion to string is needed to do exact comparison
1712 return get_string('validateerror', 'admin');
1717 function output_html($data, $query='') {
1718 $default = $this->get_defaultsetting();
1720 return format_admin_setting($this, $this->visiblename
,
1721 '<div class="form-text defaultsnext"><input type="text" size="'.$this->size
.'" id="'.$this->get_id().'" name="'.$this->get_full_name().'" value="'.s($data).'" /></div>',
1722 $this->description
, true, '', $default, $query);
1727 * General text area without html editor.
1729 class admin_setting_configtextarea
extends admin_setting_configtext
{
1733 function admin_setting_configtextarea($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW
, $cols='60', $rows='8') {
1734 $this->rows
= $rows;
1735 $this->cols
= $cols;
1736 parent
::admin_setting_configtext($name, $visiblename, $description, $defaultsetting, $paramtype);
1739 function output_html($data, $query='') {
1740 $default = $this->get_defaultsetting();
1742 $defaultinfo = $default;
1743 if (!is_null($default) and $default !== '') {
1744 $defaultinfo = "\n".$default;
1747 return format_admin_setting($this, $this->visiblename
,
1748 '<div class="form-textarea" ><textarea rows="'.$this->rows
.'" cols="'.$this->cols
.'" id="'.$this->get_id().'" name="'.$this->get_full_name().'">'.s($data).'</textarea></div>',
1749 $this->description
, true, '', $defaultinfo, $query);
1754 * Password field, allows unmasking of password
1756 class admin_setting_configpasswordunmask
extends admin_setting_configtext
{
1759 * @param string $name of setting
1760 * @param string $visiblename localised
1761 * @param string $description long localised info
1762 * @param string $defaultsetting default password
1764 function admin_setting_configpasswordunmask($name, $visiblename, $description, $defaultsetting) {
1765 parent
::admin_setting_configtext($name, $visiblename, $description, $defaultsetting, PARAM_RAW
, 30);
1768 function output_html($data, $query='') {
1769 $id = $this->get_id();
1770 $unmask = get_string('unmaskpassword', 'form');
1771 $unmaskjs = '<script type="text/javascript">
1773 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>\');
1776 return format_admin_setting($this, $this->visiblename
,
1777 '<div class="form-password"><input type="password" size="'.$this->size
.'" id="'.$this->get_id().'" name="'.$this->get_full_name().'" value="'.s($data).'" />'.$unmaskjs.'</div>',
1778 $this->description
, true, '', NULL, $query);
1785 class admin_setting_configfile
extends admin_setting_configtext
{
1788 * @param string $name of setting
1789 * @param string $visiblename localised
1790 * @param string $description long localised info
1791 * @param string $defaultdirectory default directory location
1793 function admin_setting_configfile($name, $visiblename, $description, $defaultdirectory) {
1794 parent
::admin_setting_configtext($name, $visiblename, $description, $defaultdirectory, PARAM_RAW
, 50);
1797 function output_html($data, $query='') {
1798 $default = $this->get_defaultsetting();
1801 if (file_exists($data)) {
1802 $executable = '<span class="pathok">✔</span>';
1804 $executable = '<span class="patherror">✘</span>';
1810 return format_admin_setting($this, $this->visiblename
,
1811 '<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>',
1812 $this->description
, true, '', $default, $query);
1817 * Path to executable file
1819 class admin_setting_configexecutable
extends admin_setting_configfile
{
1821 function output_html($data, $query='') {
1822 $default = $this->get_defaultsetting();
1825 if (file_exists($data) and is_executable($data)) {
1826 $executable = '<span class="pathok">✔</span>';
1828 $executable = '<span class="patherror">✘</span>';
1834 return format_admin_setting($this, $this->visiblename
,
1835 '<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>',
1836 $this->description
, true, '', $default, $query);
1843 class admin_setting_configdirectory
extends admin_setting_configfile
{
1844 function output_html($data, $query='') {
1845 $default = $this->get_defaultsetting();
1848 if (file_exists($data) and is_dir($data)) {
1849 $executable = '<span class="pathok">✔</span>';
1851 $executable = '<span class="patherror">✘</span>';
1857 return format_admin_setting($this, $this->visiblename
,
1858 '<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>',
1859 $this->description
, true, '', $default, $query);
1866 class admin_setting_configcheckbox
extends admin_setting
{
1872 * @param string $name of setting
1873 * @param string $visiblename localised
1874 * @param string $description long localised info
1875 * @param string $defaultsetting
1876 * @param string $yes value used when checked
1877 * @param string $no value used when not checked
1879 function admin_setting_configcheckbox($name, $visiblename, $description, $defaultsetting, $yes='1', $no='0') {
1880 parent
::admin_setting($name, $visiblename, $description, $defaultsetting);
1881 $this->yes
= (string)$yes;
1882 $this->no
= (string)$no;
1885 function get_setting() {
1886 return $this->config_read($this->name
);
1889 function write_setting($data) {
1890 if ((string)$data === $this->yes
) { // convert to strings before comparison
1895 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
1898 function output_html($data, $query='') {
1899 $default = $this->get_defaultsetting();
1901 if (!is_null($default)) {
1902 if ((string)$default === $this->yes
) {
1903 $defaultinfo = get_string('checkboxyes', 'admin');
1905 $defaultinfo = get_string('checkboxno', 'admin');
1908 $defaultinfo = NULL;
1911 if ((string)$data === $this->yes
) { // convert to strings before comparison
1912 $checked = 'checked="checked"';
1917 return format_admin_setting($this, $this->visiblename
,
1918 '<div class="form-checkbox defaultsnext" ><input type="hidden" name="'.$this->get_full_name().'" value="'.s($this->no
).'" /> '
1919 .'<input type="checkbox" id="'.$this->get_id().'" name="'.$this->get_full_name().'" value="'.s($this->yes
).'" '.$checked.' /></div>',
1920 $this->description
, true, '', $defaultinfo, $query);
1925 * Multiple checkboxes, each represents different value, stored in csv format
1927 class admin_setting_configmulticheckbox
extends admin_setting
{
1932 * @param string $name of setting
1933 * @param string $visiblename localised
1934 * @param string $description long localised info
1935 * @param array $defaultsetting array of selected
1936 * @param array $choices array of $value=>$label for each checkbox
1938 function admin_setting_configmulticheckbox($name, $visiblename, $description, $defaultsetting, $choices) {
1939 $this->choices
= $choices;
1940 parent
::admin_setting($name, $visiblename, $description, $defaultsetting);
1944 * This function may be used in ancestors for lazy loading of choices
1945 * @return true if loaded, false if error
1947 function load_choices() {
1949 if (is_array($this->choices)) {
1952 .... load choices here
1958 * Is setting related to query text - used when searching
1959 * @param string $query
1962 function is_related($query) {
1963 if (!$this->load_choices() or empty($this->choices
)) {
1966 if (parent
::is_related($query)) {
1970 $textlib = textlib_get_instance();
1971 foreach ($this->choices
as $desc) {
1972 if (strpos($textlib->strtolower($desc), $query) !== false) {
1979 function get_setting() {
1980 $result = $this->config_read($this->name
);
1981 if (is_null($result)) {
1984 if ($result === '') {
1987 return explode(',', $result);
1990 function write_setting($data) {
1991 if (!is_array($data)) {
1992 return ''; // ignore it
1994 if (!$this->load_choices() or empty($this->choices
)) {
1997 unset($data['xxxxx']);
1999 foreach ($data as $key => $value) {
2000 if ($value and array_key_exists($key, $this->choices
)) {
2004 return $this->config_write($this->name
, implode(',', $result)) ?
'' : get_string('errorsetting', 'admin');
2007 function output_html($data, $query='') {
2008 if (!$this->load_choices() or empty($this->choices
)) {
2011 $default = $this->get_defaultsetting();
2012 if (is_null($default)) {
2015 if (is_null($data)) {
2016 foreach ($default as $key=>$value) {
2018 $current[] = $value;
2024 $defaults = array();
2025 foreach($this->choices
as $key=>$description) {
2026 if (in_array($key, $data)) {
2027 $checked = 'checked="checked"';
2031 if (!empty($default[$key])) {
2032 $defaults[] = $description;
2035 $options[] = '<input type="checkbox" id="'.$this->get_id().'_'.$key.'" name="'.$this->get_full_name().'['.$key.']" value="1" '.$checked.' />'
2036 .'<label for="'.$this->get_id().'_'.$key.'">'.highlightfast($query, $description).'</label>';
2039 if (is_null($default)) {
2040 $defaultinfo = NULL;
2041 } else if (!empty($defaults)) {
2042 $defaultinfo = implode(', ', $defaults);
2044 $defaultinfo = get_string('none');
2047 $return = '<div class="form-multicheckbox">';
2048 $return .= '<input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
2051 foreach ($options as $option) {
2052 $return .= '<li>'.$option.'</li>';
2056 $return .= '</div>';
2058 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', $defaultinfo, $query);
2064 * Multiple checkboxes 2, value stored as string 00101011
2066 class admin_setting_configmulticheckbox2
extends admin_setting_configmulticheckbox
{
2067 function get_setting() {
2068 $result = $this->config_read($this->name
);
2069 if (is_null($result)) {
2072 if (!$this->load_choices()) {
2075 $result = str_pad($result, count($this->choices
), '0');
2076 $result = preg_split('//', $result, -1, PREG_SPLIT_NO_EMPTY
);
2078 foreach ($this->choices
as $key=>$unused) {
2079 $value = array_shift($result);
2087 function write_setting($data) {
2088 if (!is_array($data)) {
2089 return ''; // ignore it
2091 if (!$this->load_choices() or empty($this->choices
)) {
2095 foreach ($this->choices
as $key=>$unused) {
2096 if (!empty($data[$key])) {
2102 return $this->config_write($this->name
, $result) ?
'' : get_string('errorsetting', 'admin');
2107 * Select one value from list
2109 class admin_setting_configselect
extends admin_setting
{
2114 * @param string $name of setting
2115 * @param string $visiblename localised
2116 * @param string $description long localised info
2117 * @param string $defaultsetting
2118 * @param array $choices array of $value=>$label for each selection
2120 function admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices) {
2121 $this->choices
= $choices;
2122 parent
::admin_setting($name, $visiblename, $description, $defaultsetting);
2126 * This function may be used in ancestors for lazy loading of choices
2127 * @return true if loaded, false if error
2129 function load_choices() {
2131 if (is_array($this->choices)) {
2134 .... load choices here
2139 function is_related($query) {
2140 if (parent
::is_related($query)) {
2143 if (!$this->load_choices()) {
2146 $textlib = textlib_get_instance();
2147 foreach ($this->choices
as $key=>$value) {
2148 if (strpos($textlib->strtolower($key), $query) !== false) {
2151 if (strpos($textlib->strtolower($value), $query) !== false) {
2158 function get_setting() {
2159 return $this->config_read($this->name
);
2162 function write_setting($data) {
2163 if (!$this->load_choices() or empty($this->choices
)) {
2166 if (!array_key_exists($data, $this->choices
)) {
2167 return ''; // ignore it
2170 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
2173 function output_html($data, $query='') {
2174 if (!$this->load_choices() or empty($this->choices
)) {
2177 $default = $this->get_defaultsetting();
2179 if (!is_null($default) and array_key_exists($default, $this->choices
)) {
2180 $defaultinfo = $this->choices
[$default];
2182 $defaultinfo = NULL;
2185 $current = $this->get_setting();
2187 if (is_null($current)) {
2189 } else if (empty($current) and (array_key_exists('', $this->choices
) or array_key_exists(0, $this->choices
))) {
2191 } else if (!array_key_exists($current, $this->choices
)) {
2192 $warning = get_string('warningcurrentsetting', 'admin', s($current));
2193 if (!is_null($default) and $data==$current) {
2194 $data = $default; // use default instead of first value when showing the form
2198 $return = '<div class="form-select defaultsnext"><select id="'.$this->get_id().'" name="'.$this->get_full_name().'">';
2199 foreach ($this->choices
as $key => $value) {
2200 // the string cast is needed because key may be integer - 0 is equal to most strings!
2201 $return .= '<option value="'.$key.'"'.((string)$key==$data ?
' selected="selected"' : '').'>'.$value.'</option>';
2203 $return .= '</select></div>';
2205 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, true, $warning, $defaultinfo, $query);
2211 * Select multiple items from list
2213 class admin_setting_configmultiselect
extends admin_setting_configselect
{
2216 * @param string $name of setting
2217 * @param string $visiblename localised
2218 * @param string $description long localised info
2219 * @param array $defaultsetting array of selected items
2220 * @param array $choices array of $value=>$label for each list item
2222 function admin_setting_configmultiselect($name, $visiblename, $description, $defaultsetting, $choices) {
2223 parent
::admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices);
2226 function get_setting() {
2227 $result = $this->config_read($this->name
);
2228 if (is_null($result)) {
2231 if ($result === '') {
2234 return explode(',', $result);
2237 function write_setting($data) {
2238 if (!is_array($data)) {
2239 return ''; //ignore it
2241 if (!$this->load_choices() or empty($this->choices
)) {
2245 unset($data['xxxxx']);
2248 foreach ($data as $value) {
2249 if (!array_key_exists($value, $this->choices
)) {
2250 continue; // ignore it
2255 return ($this->config_write($this->name
, implode(',', $save)) ?
'' : get_string('errorsetting', 'admin'));
2259 * Is setting related to query text - used when searching
2260 * @param string $query
2263 function is_related($query) {
2264 if (!$this->load_choices() or empty($this->choices
)) {
2267 if (parent
::is_related($query)) {
2271 $textlib = textlib_get_instance();
2272 foreach ($this->choices
as $desc) {
2273 if (strpos($textlib->strtolower($desc), $query) !== false) {
2280 function output_html($data, $query='') {
2281 if (!$this->load_choices() or empty($this->choices
)) {
2284 $choices = $this->choices
;
2285 $default = $this->get_defaultsetting();
2286 if (is_null($default)) {
2289 if (is_null($data)) {
2293 $defaults = array();
2294 $return = '<div class="form-select"><input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
2295 $return .= '<select id="'.$this->get_id().'" name="'.$this->get_full_name().'[]" size="10" multiple="multiple">';
2296 foreach ($this->choices
as $key => $description) {
2297 if (in_array($key, $data)) {
2298 $selected = 'selected="selected"';
2302 if (in_array($key, $default)) {
2303 $defaults[] = $description;
2306 $return .= '<option value="'.s($key).'" '.$selected.'>'.$description.'</option>';
2309 if (is_null($default)) {
2310 $defaultinfo = NULL;
2311 } if (!empty($defaults)) {
2312 $defaultinfo = implode(', ', $defaults);
2314 $defaultinfo = get_string('none');
2317 $return .= '</select></div>';
2318 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, true, '', $defaultinfo, $query);
2324 * this is a liiitle bit messy. we're using two selects, but we're returning
2325 * them as an array named after $name (so we only use $name2 internally for the setting)
2327 class admin_setting_configtime
extends admin_setting
{
2332 * @param string $hoursname setting for hours
2333 * @param string $minutesname setting for hours
2334 * @param string $visiblename localised
2335 * @param string $description long localised info
2336 * @param array $defaultsetting array representing default time 'h'=>hours, 'm'=>minutes
2338 function admin_setting_configtime($hoursname, $minutesname, $visiblename, $description, $defaultsetting) {
2339 $this->name2
= $minutesname;
2340 parent
::admin_setting($hoursname, $visiblename, $description, $defaultsetting);
2343 function get_setting() {
2344 $result1 = $this->config_read($this->name
);
2345 $result2 = $this->config_read($this->name2
);
2346 if (is_null($result1) or is_null($result2)) {
2350 return array('h' => $result1, 'm' => $result2);
2353 function write_setting($data) {
2354 if (!is_array($data)) {
2358 $result = $this->config_write($this->name
, (int)$data['h']) && $this->config_write($this->name2
, (int)$data['m']);
2359 return ($result ?
'' : get_string('errorsetting', 'admin'));
2362 function output_html($data, $query='') {
2363 $default = $this->get_defaultsetting();
2365 if (is_array($default)) {
2366 $defaultinfo = $default['h'].':'.$default['m'];
2368 $defaultinfo = NULL;
2371 $return = '<div class="form-time defaultsnext">'.
2372 '<select id="'.$this->get_id().'h" name="'.$this->get_full_name().'[h]">';
2373 for ($i = 0; $i < 24; $i++
) {
2374 $return .= '<option value="'.$i.'"'.($i == $data['h'] ?
' selected="selected"' : '').'>'.$i.'</option>';
2376 $return .= '</select>:<select id="'.$this->get_id().'m" name="'.$this->get_full_name().'[m]">';
2377 for ($i = 0; $i < 60; $i +
= 5) {
2378 $return .= '<option value="'.$i.'"'.($i == $data['m'] ?
' selected="selected"' : '').'>'.$i.'</option>';
2380 $return .= '</select></div>';
2381 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', $defaultinfo, $query);
2387 * Special checkbox for calendar - resets SESSION vars.
2389 class admin_setting_special_adminseesall
extends admin_setting_configcheckbox
{
2390 function admin_setting_special_adminseesall() {
2391 parent
::admin_setting_configcheckbox('calendar_adminseesall', get_string('adminseesall', 'admin'),
2392 get_string('helpadminseesall', 'admin'), '0');
2395 function write_setting($data) {
2397 unset($SESSION->cal_courses_shown
);
2398 return parent
::write_setting($data);
2403 * Special select for settings that are altered in setup.php and can not be altered on the fly
2405 class admin_setting_special_selectsetup
extends admin_setting_configselect
{
2406 function get_setting() {
2407 // read directly from db!
2408 return get_config(NULL, $this->name
);
2411 function write_setting($data) {
2413 // do not change active CFG setting!
2414 $current = $CFG->{$this->name
};
2415 $result = parent
::write_setting($data);
2416 $CFG->{$this->name
} = $current;
2422 * Special select for frontpage - stores data in course table
2424 class admin_setting_sitesetselect
extends admin_setting_configselect
{
2425 function get_setting() {
2427 return $site->{$this->name
};
2430 function write_setting($data) {
2431 if (!in_array($data, array_keys($this->choices
))) {
2432 return get_string('errorsetting', 'admin');
2434 $record = new stdClass();
2435 $record->id
= SITEID
;
2436 $temp = $this->name
;
2437 $record->$temp = $data;
2438 $record->timemodified
= time();
2439 return (update_record('course', $record) ?
'' : get_string('errorsetting', 'admin'));
2444 * Special select - lists on the frontpage - hacky
2446 class admin_setting_courselist_frontpage
extends admin_setting
{
2449 function admin_setting_courselist_frontpage($loggedin) {
2451 require_once($CFG->dirroot
.'/course/lib.php');
2452 $name = 'frontpage'.($loggedin ?
'loggedin' : '');
2453 $visiblename = get_string('frontpage'.($loggedin ?
'loggedin' : ''),'admin');
2454 $description = get_string('configfrontpage'.($loggedin ?
'loggedin' : ''),'admin');
2455 $defaults = array(FRONTPAGECOURSELIST
);
2456 parent
::admin_setting($name, $visiblename, $description, $defaults);
2459 function load_choices() {
2460 if (is_array($this->choices
)) {
2463 $this->choices
= array(FRONTPAGENEWS
=> get_string('frontpagenews'),
2464 FRONTPAGECOURSELIST
=> get_string('frontpagecourselist'),
2465 FRONTPAGECATEGORYNAMES
=> get_string('frontpagecategorynames'),
2466 FRONTPAGECATEGORYCOMBO
=> get_string('frontpagecategorycombo'),
2467 'none' => get_string('none'));
2468 if ($this->name
== 'frontpage' and count_records('course') > FRONTPAGECOURSELIMIT
) {
2469 unset($this->choices
[FRONTPAGECOURSELIST
]);
2473 function get_setting() {
2474 $result = $this->config_read($this->name
);
2475 if (is_null($result)) {
2478 if ($result === '') {
2481 return explode(',', $result);
2484 function write_setting($data) {
2485 if (!is_array($data)) {
2488 $this->load_choices();
2490 foreach($data as $datum) {
2491 if ($datum == 'none' or !array_key_exists($datum, $this->choices
)) {
2494 $save[$datum] = $datum; // no duplicates
2496 return ($this->config_write($this->name
, implode(',', $save)) ?
'' : get_string('errorsetting', 'admin'));
2499 function output_html($data, $query='') {
2500 $this->load_choices();
2501 $currentsetting = array();
2502 foreach ($data as $key) {
2503 if ($key != 'none' and array_key_exists($key, $this->choices
)) {
2504 $currentsetting[] = $key; // already selected first
2508 $return = '<div class="form-group">';
2509 for ($i = 0; $i < count($this->choices
) - 1; $i++
) {
2510 if (!array_key_exists($i, $currentsetting)) {
2511 $currentsetting[$i] = 'none'; //none
2513 $return .='<select class="form-select" id="'.$this->get_id().$i.'" name="'.$this->get_full_name().'[]">';
2514 foreach ($this->choices
as $key => $value) {
2515 $return .= '<option value="'.$key.'"'.("$key" == $currentsetting[$i] ?
' selected="selected"' : '').'>'.$value.'</option>';
2517 $return .= '</select>';
2518 if ($i !== count($this->choices
) - 2) {
2519 $return .= '<br />';
2522 $return .= '</div>';
2524 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
2529 * Special checkbox for frontpage - stores data in course table
2531 class admin_setting_sitesetcheckbox
extends admin_setting_configcheckbox
{
2532 function get_setting() {
2534 return $site->{$this->name
};
2537 function write_setting($data) {
2538 $record = new object();
2539 $record->id
= SITEID
;
2540 $record->{$this->name
} = ($data == '1' ?
1 : 0);
2541 $record->timemodified
= time();
2542 return (update_record('course', $record) ?
'' : get_string('errorsetting', 'admin'));
2547 * Special text for frontpage - stores data in course table.
2548 * Empty string means not set here. Manual setting is required.
2550 class admin_setting_sitesettext
extends admin_setting_configtext
{
2551 function get_setting() {
2553 return $site->{$this->name
} != '' ?
$site->{$this->name
} : NULL;
2556 function validate($data) {
2557 $cleaned = stripslashes(clean_param(addslashes($data), PARAM_MULTILANG
));
2558 if ($cleaned === '') {
2559 return get_string('required');
2561 if ("$data" == "$cleaned") { // implicit conversion to string is needed to do exact comparison
2564 return get_string('validateerror', 'admin');
2568 function write_setting($data) {
2569 $data = trim($data);
2570 $validated = $this->validate($data);
2571 if ($validated !== true) {
2575 $record = new object();
2576 $record->id
= SITEID
;
2577 $record->{$this->name
} = addslashes($data);
2578 $record->timemodified
= time();
2579 return (update_record('course', $record) ?
'' : get_string('dbupdatefailed', 'error'));
2584 * Special text editor for site description.
2586 class admin_setting_special_frontpagedesc
extends admin_setting
{
2587 function admin_setting_special_frontpagedesc() {
2588 parent
::admin_setting('summary', get_string('frontpagedescription'), get_string('frontpagedescriptionhelp'), NULL);
2591 function get_setting() {
2593 return $site->{$this->name
};
2596 function write_setting($data) {
2597 $record = new object();
2598 $record->id
= SITEID
;
2599 $record->{$this->name
} = addslashes($data);
2600 $record->timemodified
= time();
2601 return(update_record('course', $record) ?
'' : get_string('errorsetting', 'admin'));
2604 function output_html($data, $query='') {
2607 $CFG->adminusehtmleditor
= can_use_html_editor();
2608 $return = '<div class="form-htmlarea">'.print_textarea($CFG->adminusehtmleditor
, 15, 60, 0, 0, $this->get_full_name(), $data, 0, true).'</div>';
2610 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
2614 class admin_setting_special_editorfontlist
extends admin_setting
{
2618 function admin_setting_special_editorfontlist() {
2620 $name = 'editorfontlist';
2621 $visiblename = get_string('editorfontlist', 'admin');
2622 $description = get_string('configeditorfontlist', 'admin');
2623 $defaults = array('k0' => 'Trebuchet',
2624 'v0' => 'Trebuchet MS,Verdana,Arial,Helvetica,sans-serif',
2626 'v1' => 'arial,helvetica,sans-serif',
2627 'k2' => 'Courier New',
2628 'v2' => 'courier new,courier,monospace',
2630 'v3' => 'georgia,times new roman,times,serif',
2632 'v4' => 'tahoma,arial,helvetica,sans-serif',
2633 'k5' => 'Times New Roman',
2634 'v5' => 'times new roman,times,serif',
2636 'v6' => 'verdana,arial,helvetica,sans-serif',
2639 'k8' => 'Wingdings',
2640 'v8' => 'wingdings');
2641 parent
::admin_setting($name, $visiblename, $description, $defaults);
2644 function get_setting() {
2646 $result = $this->config_read($this->name
);
2647 if (is_null($result)) {
2651 $currentsetting = array();
2652 $items = explode(';', $result);
2653 foreach ($items as $item) {
2654 $item = explode(':', $item);
2655 $currentsetting['k'.$i] = $item[0];
2656 $currentsetting['v'.$i] = $item[1];
2659 return $currentsetting;
2662 function write_setting($data) {
2664 // there miiight be an easier way to do this :)
2665 // if this is changed, make sure the $defaults array above is modified so that this
2666 // function processes it correctly
2671 foreach ($data as $key => $value) {
2672 if (substr($key,0,1) == 'k') {
2673 $keys[substr($key,1)] = $value;
2674 } elseif (substr($key,0,1) == 'v') {
2675 $values[substr($key,1)] = $value;
2680 for ($i = 0; $i < count($keys); $i++
) {
2681 if (($keys[$i] !== '') && ($values[$i] !== '')) {
2682 $result[] = clean_param($keys[$i],PARAM_NOTAGS
).':'.clean_param($values[$i], PARAM_NOTAGS
);
2686 return ($this->config_write($this->name
, implode(';', $result)) ?
'' : get_string('errorsetting', 'admin'));
2689 function output_html($data, $query='') {
2690 $fullname = $this->get_full_name();
2691 $return = '<div class="form-group">';
2692 for ($i = 0; $i < count($data) / 2; $i++
) {
2693 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.$i.']" value="'.$data['k'.$i].'" />';
2694 $return .= ' ';
2695 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.$i.']" value="'.$data['v'.$i].'" /><br />';
2697 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.$i.']" value="" />';
2698 $return .= ' ';
2699 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.$i.']" value="" /><br />';
2700 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.($i +
1).']" value="" />';
2701 $return .= ' ';
2702 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.($i +
1).']" value="" />';
2703 $return .= '</div>';
2705 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
2710 class admin_setting_emoticons
extends admin_setting
{
2714 function admin_setting_emoticons() {
2716 $name = 'emoticons';
2717 $visiblename = get_string('emoticons', 'admin');
2718 $description = get_string('configemoticons', 'admin');
2719 $defaults = array('k0' => ':-)',
2730 'v5' => 'thoughtful',
2732 'v6' => 'tongueout',
2752 'v16' => 'surprise',
2754 'v17' => 'blackeye',
2771 'k26' => '(martin)',
2775 parent
::admin_setting($name, $visiblename, $description, $defaults);
2778 function get_setting() {
2780 $result = $this->config_read($this->name
);
2781 if (is_null($result)) {
2785 $currentsetting = array();
2786 $items = explode('{;}', $result);
2787 foreach ($items as $item) {
2788 $item = explode('{:}', $item);
2789 $currentsetting['k'.$i] = $item[0];
2790 $currentsetting['v'.$i] = $item[1];
2793 return $currentsetting;
2796 function write_setting($data) {
2798 // there miiight be an easier way to do this :)
2799 // if this is changed, make sure the $defaults array above is modified so that this
2800 // function processes it correctly
2805 foreach ($data as $key => $value) {
2806 if (substr($key,0,1) == 'k') {
2807 $keys[substr($key,1)] = $value;
2808 } elseif (substr($key,0,1) == 'v') {
2809 $values[substr($key,1)] = $value;
2814 for ($i = 0; $i < count($keys); $i++
) {
2815 if (($keys[$i] !== '') && ($values[$i] !== '')) {
2816 $result[] = clean_param($keys[$i],PARAM_NOTAGS
).'{:}'.clean_param($values[$i], PARAM_NOTAGS
);
2820 return ($this->config_write($this->name
, implode('{;}', $result)) ?
'' : get_string('errorsetting', 'admin').$this->visiblename
.'<br />');
2823 function output_html($data, $query='') {
2824 $fullname = $this->get_full_name();
2825 $return = '<div class="form-group">';
2826 for ($i = 0; $i < count($data) / 2; $i++
) {
2827 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.$i.']" value="'.$data['k'.$i].'" />';
2828 $return .= ' ';
2829 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.$i.']" value="'.$data['v'.$i].'" /><br />';
2831 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.$i.']" value="" />';
2832 $return .= ' ';
2833 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.$i.']" value="" /><br />';
2834 $return .= '<input type="text" class="form-text" name="'.$fullname.'[k'.($i +
1).']" value="" />';
2835 $return .= ' ';
2836 $return .= '<input type="text" class="form-text" name="'.$fullname.'[v'.($i +
1).']" value="" />';
2837 $return .= '</div>';
2839 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
2845 * Setting for spellchecker language selection.
2847 class admin_setting_special_editordictionary
extends admin_setting_configselect
{
2849 function admin_setting_special_editordictionary() {
2850 $name = 'editordictionary';
2851 $visiblename = get_string('editordictionary','admin');
2852 $description = get_string('configeditordictionary', 'admin');
2853 parent
::admin_setting_configselect($name, $visiblename, $description, '', NULL);
2856 function load_choices() {
2857 // function borrowed from the old moodle/admin/editor.php, slightly modified
2858 // Get all installed dictionaries in the system
2859 if (is_array($this->choices
)) {
2863 $this->choices
= array();
2869 // If aspellpath isn't set don't even bother ;-)
2870 if (empty($CFG->aspellpath
)) {
2871 $this->choices
['error'] = 'Empty aspell path!';
2875 // Do we have access to popen function?
2876 if (!function_exists('popen')) {
2877 $this->choices
['error'] = 'Popen function disabled!';
2881 $cmd = $CFG->aspellpath
;
2883 $dictionaries = array();
2885 if(!($handle = @popen
(escapeshellarg($cmd).' dump dicts', 'r'))) {
2886 $this->choices
['error'] = 'Couldn\'t create handle!';
2889 while(!feof($handle)) {
2890 $output .= fread($handle, 1024);
2894 $dictionaries = explode(chr(10), $output);
2895 foreach ($dictionaries as $dict) {
2899 $this->choices
[$dict] = $dict;
2902 if (empty($this->choices
)) {
2903 $this->choices
['error'] = 'Error! Check your aspell installation!';
2910 class admin_setting_special_editorhidebuttons
extends admin_setting
{
2913 function admin_setting_special_editorhidebuttons() {
2914 parent
::admin_setting('editorhidebuttons', get_string('editorhidebuttons', 'admin'),
2915 get_string('confeditorhidebuttons', 'admin'), array());
2916 // weird array... buttonname => buttonimage (assume proper path appended). if you leave buttomimage blank, text will be printed instead
2917 $this->items
= array('fontname' => '',
2919 'formatblock' => '',
2920 'bold' => 'ed_format_bold.gif',
2921 'italic' => 'ed_format_italic.gif',
2922 'underline' => 'ed_format_underline.gif',
2923 'strikethrough' => 'ed_format_strike.gif',
2924 'subscript' => 'ed_format_sub.gif',
2925 'superscript' => 'ed_format_sup.gif',
2926 'copy' => 'ed_copy.gif',
2927 'cut' => 'ed_cut.gif',
2928 'paste' => 'ed_paste.gif',
2929 'clean' => 'ed_wordclean.gif',
2930 'undo' => 'ed_undo.gif',
2931 'redo' => 'ed_redo.gif',
2932 'justifyleft' => 'ed_align_left.gif',
2933 'justifycenter' => 'ed_align_center.gif',
2934 'justifyright' => 'ed_align_right.gif',
2935 'justifyfull' => 'ed_align_justify.gif',
2936 'lefttoright' => 'ed_left_to_right.gif',
2937 'righttoleft' => 'ed_right_to_left.gif',
2938 'insertorderedlist' => 'ed_list_num.gif',
2939 'insertunorderedlist' => 'ed_list_bullet.gif',
2940 'outdent' => 'ed_indent_less.gif',
2941 'indent' => 'ed_indent_more.gif',
2942 'forecolor' => 'ed_color_fg.gif',
2943 'hilitecolor' => 'ed_color_bg.gif',
2944 'inserthorizontalrule' => 'ed_hr.gif',
2945 'createanchor' => 'ed_anchor.gif',
2946 'createlink' => 'ed_link.gif',
2947 'unlink' => 'ed_unlink.gif',
2948 'insertimage' => 'ed_image.gif',
2949 'inserttable' => 'insert_table.gif',
2950 'insertsmile' => 'em.icon.smile.gif',
2951 'insertchar' => 'icon_ins_char.gif',
2952 'spellcheck' => 'spell-check.gif',
2953 'htmlmode' => 'ed_html.gif',
2954 'popupeditor' => 'fullscreen_maximize.gif',
2955 'search_replace' => 'ed_replace.gif');
2958 function get_setting() {
2959 $result = $this->config_read($this->name
);
2960 if (is_null($result)) {
2963 if ($result === '') {
2966 return explode(' ', $result);
2969 function write_setting($data) {
2970 if (!is_array($data)) {
2971 return ''; // ignore it
2973 unset($data['xxxxx']);
2976 foreach ($data as $key => $value) {
2977 if (!isset($this->items
[$key])) {
2978 return get_string('errorsetting', 'admin');
2980 if ($value == '1') {
2984 return ($this->config_write($this->name
, implode(' ', $result)) ?
'' : get_string('errorsetting', 'admin'));
2987 function output_html($data, $query='') {
2991 // checkboxes with input name="$this->name[$key]" value="1"
2992 // we do 15 fields per column
2994 $return = '<div class="form-group">';
2995 $return .= '<table><tr><td valign="top" align="right">';
2996 $return .= '<input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
3000 foreach($this->items
as $key => $value) {
3001 if ($count %
15 == 0 and $count != 0) {
3002 $return .= '</td><td valign="top" align="right">';
3005 $return .= '<label for="'.$this->get_id().$key.'">';
3006 $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').'" />').' ';
3007 $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"' : '').' /> ';
3008 $return .= '</label>';
3010 if ($count %
15 != 0) {
3011 $return .= '<br /><br />';
3015 $return .= '</td></tr>';
3016 $return .= '</table>';
3017 $return .= '</div>';
3019 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
3024 * Special setting for limiting of the list of available languages.
3026 class admin_setting_langlist
extends admin_setting_configtext
{
3027 function admin_setting_langlist() {
3028 parent
::admin_setting_configtext('langlist', get_string('langlist', 'admin'), get_string('configlanglist', 'admin'), '', PARAM_NOTAGS
);
3031 function write_setting($data) {
3032 $return = parent
::write_setting($data);
3033 get_list_of_languages(true);//refresh the list
3039 * Course category selection
3041 class admin_settings_coursecat_select
extends admin_setting_configselect
{
3042 function admin_settings_coursecat_select($name, $visiblename, $description, $defaultsetting) {
3043 parent
::admin_setting_configselect($name, $visiblename, $description, $defaultsetting, NULL);
3046 function load_choices() {
3048 require_once($CFG->dirroot
.'/course/lib.php');
3049 if (is_array($this->choices
)) {
3052 $this->choices
= make_categories_options();
3057 class admin_setting_special_backupdays
extends admin_setting_configmulticheckbox2
{
3058 function admin_setting_special_backupdays() {
3059 parent
::admin_setting_configmulticheckbox2('backup_sche_weekdays', get_string('schedule'), get_string('backupschedulehelp'), array(), NULL);
3060 $this->plugin
= 'backup';
3063 function load_choices() {
3064 if (is_array($this->choices
)) {
3067 $this->choices
= array();
3068 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
3069 foreach ($days as $day) {
3070 $this->choices
[$day] = get_string($day, 'calendar');
3077 * Special debug setting
3079 class admin_setting_special_debug
extends admin_setting_configselect
{
3080 function admin_setting_special_debug() {
3081 parent
::admin_setting_configselect('debug', get_string('debug', 'admin'), get_string('configdebug', 'admin'), DEBUG_NONE
, NULL);
3084 function load_choices() {
3085 if (is_array($this->choices
)) {
3088 $this->choices
= array(DEBUG_NONE
=> get_string('debugnone', 'admin'),
3089 DEBUG_MINIMAL
=> get_string('debugminimal', 'admin'),
3090 DEBUG_NORMAL
=> get_string('debugnormal', 'admin'),
3091 DEBUG_ALL
=> get_string('debugall', 'admin'),
3092 DEBUG_DEVELOPER
=> get_string('debugdeveloper', 'admin'));
3098 class admin_setting_special_calendar_weekend
extends admin_setting
{
3099 function admin_setting_special_calendar_weekend() {
3100 $name = 'calendar_weekend';
3101 $visiblename = get_string('calendar_weekend', 'admin');
3102 $description = get_string('helpweekenddays', 'admin');
3103 $default = array ('0', '6'); // Saturdays and Sundays
3104 parent
::admin_setting($name, $visiblename, $description, $default);
3107 function get_setting() {
3108 $result = $this->config_read($this->name
);
3109 if (is_null($result)) {
3112 if ($result === '') {
3115 $settings = array();
3116 for ($i=0; $i<7; $i++
) {
3117 if ($result & (1 << $i)) {
3124 function write_setting($data) {
3125 if (!is_array($data)) {
3128 unset($data['xxxxx']);
3130 foreach($data as $index) {
3131 $result |
= 1 << $index;
3133 return ($this->config_write($this->name
, $result) ?
'' : get_string('errorsetting', 'admin'));
3136 function output_html($data, $query='') {
3137 // The order matters very much because of the implied numeric keys
3138 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
3139 $return = '<table><thead><tr>';
3140 $return .= '<input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
3141 foreach($days as $index => $day) {
3142 $return .= '<td><label for="'.$this->get_id().$index.'">'.get_string($day, 'calendar').'</label></td>';
3144 $return .= '</tr></thead><tbody><tr>';
3145 foreach($days as $index => $day) {
3146 $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>';
3148 $return .= '</tr></tbody></table>';
3150 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
3157 * Graded roles in gradebook
3159 class admin_setting_special_gradebookroles
extends admin_setting_configmulticheckbox
{
3160 function admin_setting_special_gradebookroles() {
3161 parent
::admin_setting_configmulticheckbox('gradebookroles', get_string('gradebookroles', 'admin'),
3162 get_string('configgradebookroles', 'admin'), NULL, NULL);
3165 function load_choices() {
3167 if (empty($CFG->rolesactive
)) {
3170 if (is_array($this->choices
)) {
3173 if ($roles = get_records('role')) {
3174 $this->choices
= array();
3175 foreach($roles as $role) {
3176 $this->choices
[$role->id
] = format_string($role->name
);
3184 function get_defaultsetting() {
3186 if (empty($CFG->rolesactive
)) {
3190 if ($studentroles = get_roles_with_capability('moodle/legacy:student', CAP_ALLOW
)) {
3191 foreach ($studentroles as $studentrole) {
3192 $result[$studentrole->id
] = '1';
3199 class admin_setting_regradingcheckbox
extends admin_setting_configcheckbox
{
3200 function write_setting($data) {
3203 $oldvalue = $this->config_read($this->name
);
3204 $return = parent
::write_setting($data);
3205 $newvalue = $this->config_read($this->name
);
3207 if ($oldvalue !== $newvalue) {
3208 // force full regrading
3209 set_field('grade_items', 'needsupdate', 1, 'needsupdate', 0);
3217 * Which roles to show on course decription page
3219 class admin_setting_special_coursemanager
extends admin_setting_configmulticheckbox
{
3220 function admin_setting_special_coursemanager() {
3221 parent
::admin_setting_configmulticheckbox('coursemanager', get_string('coursemanager', 'admin'),
3222 get_string('configcoursemanager', 'admin'), NULL, NULL);
3225 function load_choices() {
3226 if (is_array($this->choices
)) {
3229 if ($roles = get_records('role')) {
3230 $this->choices
= array();
3231 foreach($roles as $role) {
3232 $this->choices
[$role->id
] = format_string($role->name
);
3239 function get_defaultsetting() {
3241 if (empty($CFG->rolesactive
)) {
3245 if ($teacherroles = get_roles_with_capability('moodle/legacy:editingteacher', CAP_ALLOW
)) {
3246 foreach ($teacherroles as $teacherrole) {
3247 $result[$teacherrole->id
] = '1';
3255 * Primary grade export plugin - has state tracking.
3257 class admin_setting_special_gradeexport
extends admin_setting_configmulticheckbox
{
3258 function admin_setting_special_gradeexport() {
3259 parent
::admin_setting_configmulticheckbox('gradeexport', get_string('gradeexport', 'admin'),
3260 get_string('configgradeexport', 'admin'), array(), NULL);
3263 function load_choices() {
3264 if (is_array($this->choices
)) {
3267 $this->choices
= array();
3269 if ($plugins = get_list_of_plugins('grade/export')) {
3270 foreach($plugins as $plugin) {
3271 $this->choices
[$plugin] = get_string('modulename', 'gradeexport_'.$plugin);
3279 * Grade category settings
3281 class admin_setting_gradecat_combo
extends admin_setting
{
3285 function admin_setting_gradecat_combo($name, $visiblename, $description, $defaultsetting, $choices) {
3286 $this->choices
= $choices;
3287 parent
::admin_setting($name, $visiblename, $description, $defaultsetting);
3290 function get_setting() {
3293 $value = $this->config_read($this->name
);
3294 $flag = $this->config_read($this->name
.'_flag');
3296 if (is_null($value) or is_null($flag)) {
3301 $forced = (boolean
)(1 & $flag); // first bit
3302 $adv = (boolean
)(2 & $flag); // second bit
3304 return array('value' => $value, 'forced' => $forced, 'adv' => $adv);
3307 function write_setting($data) {
3310 $value = $data['value'];
3311 $forced = empty($data['forced']) ?
0 : 1;
3312 $adv = empty($data['adv']) ?
0 : 2;
3313 $flag = ($forced |
$adv); //bitwise or
3315 if (!in_array($value, array_keys($this->choices
))) {
3316 return 'Error setting ';
3319 $oldvalue = $this->config_read($this->name
);
3320 $oldflag = (int)$this->config_read($this->name
.'_flag');
3321 $oldforced = (1 & $oldflag); // first bit
3323 $result1 = $this->config_write($this->name
, $value);
3324 $result2 = $this->config_write($this->name
.'_flag', $flag);
3326 // force regrade if needed
3327 if ($oldforced != $forced or ($forced and $value != $oldvalue)) {
3328 require_once($CFG->libdir
.'/gradelib.php');
3329 grade_category
::updated_forced_settings();
3332 if ($result1 and $result2) {
3335 return get_string('errorsetting', 'admin');
3339 function output_html($data, $query='') {
3340 $value = $data['value'];
3341 $forced = !empty($data['forced']);
3342 $adv = !empty($data['adv']);
3344 $default = $this->get_defaultsetting();
3345 if (!is_null($default)) {
3346 $defaultinfo = array();
3347 if (isset($this->choices
[$default['value']])) {
3348 $defaultinfo[] = $this->choices
[$default['value']];
3350 if (!empty($default['forced'])) {
3351 $defaultinfo[] = get_string('force');
3353 if (!empty($default['adv'])) {
3354 $defaultinfo[] = get_string('advanced');
3356 $defaultinfo = implode(', ', $defaultinfo);
3359 $defaultinfo = NULL;
3363 $return = '<div class="form-group">';
3364 $return .= '<select class="form-select" id="'.$this->get_id().'" name="'.$this->get_full_name().'[value]">';
3365 foreach ($this->choices
as $key => $val) {
3366 // the string cast is needed because key may be integer - 0 is equal to most strings!
3367 $return .= '<option value="'.$key.'"'.((string)$key==$value ?
' selected="selected"' : '').'>'.$val.'</option>';
3369 $return .= '</select>';
3370 $return .= '<input type="checkbox" class="form-checkbox" id="'.$this->get_id().'force" name="'.$this->get_full_name().'[forced]" value="1" '.($forced ?
'checked="checked"' : '').' />'
3371 .'<label for="'.$this->get_id().'force">'.get_string('force').'</label>';
3372 $return .= '<input type="checkbox" class="form-checkbox" id="'.$this->get_id().'adv" name="'.$this->get_full_name().'[adv]" value="1" '.($adv ?
'checked="checked"' : '').' />'
3373 .'<label for="'.$this->get_id().'adv">'.get_string('advanced').'</label>';
3374 $return .= '</div>';
3376 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, true, '', $defaultinfo, $query);
3382 * Selection of grade report in user profiles
3384 class admin_setting_grade_profilereport
extends admin_setting_configselect
{
3385 function admin_setting_grade_profilereport() {
3386 parent
::admin_setting_configselect('grade_profilereport', get_string('profilereport', 'grades'), get_string('configprofilereport', 'grades'), 'user', null);
3389 function load_choices() {
3390 if (is_array($this->choices
)) {
3393 $this->choices
= array();
3396 require_once($CFG->libdir
.'/gradelib.php');
3398 foreach (get_list_of_plugins('grade/report') as $plugin) {
3399 if (file_exists($CFG->dirroot
.'/grade/report/'.$plugin.'/lib.php')) {
3400 require_once($CFG->dirroot
.'/grade/report/'.$plugin.'/lib.php');
3401 $functionname = 'grade_report_'.$plugin.'_profilereport';
3402 if (function_exists($functionname)) {
3403 $this->choices
[$plugin] = get_string('modulename', 'gradereport_'.$plugin, NULL, $CFG->dirroot
.'/grade/report/'.$plugin.'/lang/');
3412 * Special class for register auth selection
3414 class admin_setting_special_registerauth
extends admin_setting_configselect
{
3415 function admin_setting_special_registerauth() {
3416 parent
::admin_setting_configselect('registerauth', get_string('selfregistration', 'auth'), get_string('selfregistration_help', 'auth'), 'email', null);
3419 function get_defaultsettings() {
3420 $this->load_choices();
3421 if (array_key_exists($this->defaultsetting
, $this->choices
)) {
3422 return $this->defaultsetting
;
3428 function load_choices() {
3431 if (is_array($this->choices
)) {
3434 $this->choices
= array();
3435 $this->choices
[''] = get_string('disable');
3437 $authsenabled = get_enabled_auth_plugins(true);
3439 foreach ($authsenabled as $auth) {
3440 $authplugin = get_auth_plugin($auth);
3441 if (!$authplugin->can_signup()) {
3444 // Get the auth title (from core or own auth lang files)
3445 $authtitle = $authplugin->get_title();
3446 $this->choices
[$auth] = $authtitle;
3453 * Module manage page
3455 class admin_page_managemods
extends admin_externalpage
{
3456 function admin_page_managemods() {
3458 parent
::admin_externalpage('managemodules', get_string('modsettings', 'admin'), "$CFG->wwwroot/$CFG->admin/modules.php");
3461 function search($query) {
3462 if ($result = parent
::search($query)) {
3467 if ($modules = get_records('modules')) {
3468 $textlib = textlib_get_instance();
3469 foreach ($modules as $module) {
3470 if (strpos($module->name
, $query) !== false) {
3474 $strmodulename = get_string('modulename', $module->name
);
3475 if (strpos($textlib->strtolower($strmodulename), $query) !== false) {
3482 $result = new object();
3483 $result->page
= $this;
3484 $result->settings
= array();
3485 return array($this->name
=> $result);
3493 * Blocks manage page
3495 class admin_page_manageblocks
extends admin_externalpage
{
3496 function admin_page_manageblocks() {
3498 parent
::admin_externalpage('manageblocks', get_string('blocksettings', 'admin'), "$CFG->wwwroot/$CFG->admin/blocks.php");
3501 function search($query) {
3503 if ($result = parent
::search($query)) {
3508 if (!empty($CFG->blocks_version
) and $blocks = get_records('block')) {
3509 $textlib = textlib_get_instance();
3510 foreach ($blocks as $block) {
3511 if (strpos($block->name
, $query) !== false) {
3515 $strblockname = get_string('blockname', 'block_'.$block->name
);
3516 if (strpos($textlib->strtolower($strblockname), $query) !== false) {
3523 $result = new object();
3524 $result->page
= $this;
3525 $result->settings
= array();
3526 return array($this->name
=> $result);
3534 * Special class for authentication administration.
3536 class admin_setting_manageauths
extends admin_setting
{
3537 function admin_setting_manageauths() {
3538 parent
::admin_setting('authsui', get_string('authsettings', 'admin'), '', '');
3541 function get_setting() {
3545 function get_defaultsetting() {
3549 function write_setting($data) {
3550 // do not write any setting
3554 function is_related($query) {
3555 if (parent
::is_related($query)) {
3559 $textlib = textlib_get_instance();
3560 $authsavailable = get_list_of_plugins('auth');
3561 foreach ($authsavailable as $auth) {
3562 if (strpos($auth, $query) !== false) {
3565 $authplugin = get_auth_plugin($auth);
3566 $authtitle = $authplugin->get_title();
3567 if (strpos($textlib->strtolower($authtitle), $query) !== false) {
3574 function output_html($data, $query='') {
3579 $txt = get_strings(array('authenticationplugins', 'users', 'administration',
3580 'settings', 'edit', 'name', 'enable', 'disable',
3581 'up', 'down', 'none'));
3582 $txt->updown
= "$txt->up/$txt->down";
3584 $authsavailable = get_list_of_plugins('auth');
3585 get_enabled_auth_plugins(true); // fix the list of enabled auths
3586 if (empty($CFG->auth
)) {
3587 $authsenabled = array();
3589 $authsenabled = explode(',', $CFG->auth
);
3592 // construct the display array, with enabled auth plugins at the top, in order
3593 $displayauths = array();
3594 $registrationauths = array();
3595 $registrationauths[''] = $txt->disable
;
3596 foreach ($authsenabled as $auth) {
3597 $authplugin = get_auth_plugin($auth);
3598 /// Get the auth title (from core or own auth lang files)
3599 $authtitle = $authplugin->get_title();
3601 $displayauths[$auth] = $authtitle;
3602 if ($authplugin->can_signup()) {
3603 $registrationauths[$auth] = $authtitle;
3607 foreach ($authsavailable as $auth) {
3608 if (array_key_exists($auth, $displayauths)) {
3609 continue; //already in the list
3611 $authplugin = get_auth_plugin($auth);
3612 /// Get the auth title (from core or own auth lang files)
3613 $authtitle = $authplugin->get_title();
3615 $displayauths[$auth] = $authtitle;
3616 if ($authplugin->can_signup()) {
3617 $registrationauths[$auth] = $authtitle;
3621 $return = print_heading(get_string('actauthhdr', 'auth'), '', 3, 'main', true);
3622 $return .= print_box_start('generalbox authsui', '', true);
3624 $table = new object();
3625 $table->head
= array($txt->name
, $txt->enable
, $txt->updown
, $txt->settings
);
3626 $table->align
= array('left', 'center', 'center', 'center');
3627 $table->width
= '90%';
3628 $table->data
= array();
3630 //add always enabled plugins first
3631 $displayname = "<span>".$displayauths['manual']."</span>";
3632 $settings = "<a href=\"auth_config.php?auth=manual\">{$txt->settings}</a>";
3633 //$settings = "<a href=\"settings.php?section=authsettingmanual\">{$txt->settings}</a>";
3634 $table->data
[] = array($displayname, '', '', $settings);
3635 $displayname = "<span>".$displayauths['nologin']."</span>";
3636 $settings = "<a href=\"auth_config.php?auth=nologin\">{$txt->settings}</a>";
3637 $table->data
[] = array($displayname, '', '', $settings);
3640 // iterate through auth plugins and add to the display table
3642 $authcount = count($authsenabled);
3643 $url = "auth.php?sesskey=" . sesskey();
3644 foreach ($displayauths as $auth => $name) {
3645 if ($auth == 'manual' or $auth == 'nologin') {
3649 if (in_array($auth, $authsenabled)) {
3650 $hideshow = "<a href=\"$url&action=disable&auth=$auth\">";
3651 $hideshow .= "<img src=\"{$CFG->pixpath}/i/hide.gif\" class=\"icon\" alt=\"disable\" /></a>";
3652 // $hideshow = "<a href=\"$url&action=disable&auth=$auth\"><input type=\"checkbox\" checked /></a>";
3654 $displayname = "<span>$name</span>";
3657 $hideshow = "<a href=\"$url&action=enable&auth=$auth\">";
3658 $hideshow .= "<img src=\"{$CFG->pixpath}/i/show.gif\" class=\"icon\" alt=\"enable\" /></a>";
3659 // $hideshow = "<a href=\"$url&action=enable&auth=$auth\"><input type=\"checkbox\" /></a>";
3661 $displayname = "<span class=\"dimmed_text\">$name</span>";
3664 // up/down link (only if auth is enabled)
3667 if ($updowncount > 1) {
3668 $updown .= "<a href=\"$url&action=up&auth=$auth\">";
3669 $updown .= "<img src=\"{$CFG->pixpath}/t/up.gif\" alt=\"up\" /></a> ";
3672 $updown .= "<img src=\"{$CFG->pixpath}/spacer.gif\" class=\"icon\" alt=\"\" /> ";
3674 if ($updowncount < $authcount) {
3675 $updown .= "<a href=\"$url&action=down&auth=$auth\">";
3676 $updown .= "<img src=\"{$CFG->pixpath}/t/down.gif\" alt=\"down\" /></a>";
3679 $updown .= "<img src=\"{$CFG->pixpath}/spacer.gif\" class=\"icon\" alt=\"\" />";
3685 if (file_exists($CFG->dirroot
.'/auth/'.$auth.'/settings.php')) {
3686 $settings = "<a href=\"settings.php?section=authsetting$auth\">{$txt->settings}</a>";
3688 $settings = "<a href=\"auth_config.php?auth=$auth\">{$txt->settings}</a>";
3691 // add a row to the table
3692 $table->data
[] =array($displayname, $hideshow, $updown, $settings);
3694 $return .= print_table($table, true);
3695 $return .= get_string('configauthenticationplugins', 'admin').'<br />'.get_string('tablenosave', 'filters');
3696 $return .= print_box_end(true);
3697 return highlight($query, $return);
3701 * Special class for filter administration.
3703 class admin_setting_managefilters
extends admin_setting
{
3704 function admin_setting_managefilters() {
3705 parent
::admin_setting('filtersui', get_string('filtersettings', 'admin'), '', '');
3708 function get_setting() {
3712 function get_defaultsetting() {
3716 function write_setting($data) {
3717 // do not write any setting
3721 function is_related($query) {
3722 if (parent
::is_related($query)) {
3726 $textlib = textlib_get_instance();
3727 $filterlocations = array('mod','filter');
3728 foreach ($filterlocations as $filterlocation) {
3729 $plugins = get_list_of_plugins($filterlocation);
3730 foreach ($plugins as $plugin) {
3731 if (strpos($plugin, $query) !== false) {
3734 $name = get_string('filtername', $plugin);
3735 if (strpos($textlib->strtolower($name), $query) !== false) {
3743 function output_html($data, $query='') {
3746 $strname = get_string('name');
3747 $strhide = get_string('disable');
3748 $strshow = get_string('enable');
3749 $strhideshow = "$strhide/$strshow";
3750 $strsettings = get_string('settings');
3751 $strup = get_string('up');
3752 $strdown = get_string('down');
3753 $strupdown = "$strup/$strdown";
3755 // get a list of possible filters (and translate name if possible)
3756 // note filters can be in the dedicated filters area OR in their
3757 // associated modules
3758 $installedfilters = array();
3759 $filtersettings_new = array();
3760 $filtersettings_old = array();
3761 $filterlocations = array('mod','filter');
3762 foreach ($filterlocations as $filterlocation) {
3763 $plugins = get_list_of_plugins($filterlocation);
3764 foreach ($plugins as $plugin) {
3765 $pluginpath = "$CFG->dirroot/$filterlocation/$plugin/filter.php";
3766 $settingspath_new = "$CFG->dirroot/$filterlocation/$plugin/filtersettings.php";
3767 $settingspath_old = "$CFG->dirroot/$filterlocation/$plugin/filterconfig.html";
3768 if (is_readable($pluginpath)) {
3769 $name = trim(get_string("filtername", $plugin));
3770 if (empty($name) or ($name == '[[filtername]]')) {
3771 $textlib = textlib_get_instance();
3772 $name = $textlib->strtotitle($plugin);
3774 $installedfilters["$filterlocation/$plugin"] = $name;
3775 if (is_readable($settingspath_new)) {
3776 $filtersettings_new[] = "$filterlocation/$plugin";
3777 } else if (is_readable($settingspath_old)) {
3778 $filtersettings_old[] = "$filterlocation/$plugin";
3784 // get all the currently selected filters
3785 if (!empty($CFG->textfilters
)) {
3786 $oldactivefilters = explode(',', $CFG->textfilters
);
3787 $oldactivefilters = array_unique($oldactivefilters);
3789 $oldactivefilters = array();
3792 // take this opportunity to clean up filters
3793 $activefilters = array();
3794 foreach ($oldactivefilters as $oldactivefilter) {
3795 if (!empty($oldactivefilter) and array_key_exists($oldactivefilter, $installedfilters)) {
3796 $activefilters[] = $oldactivefilter;
3800 // construct the display array with installed filters
3801 // at the top in the right order
3802 $displayfilters = array();
3803 foreach ($activefilters as $activefilter) {
3804 $name = $installedfilters[$activefilter];
3805 $displayfilters[$activefilter] = $name;
3807 foreach ($installedfilters as $key => $filter) {
3808 if (!array_key_exists($key, $displayfilters)) {
3809 $displayfilters[$key] = $filter;
3813 $return = print_heading(get_string('actfilterhdr', 'filters'), '', 3, 'main', true);
3814 $return .= print_box_start('generalbox filtersui', '', true);
3816 $table = new object();
3817 $table->head
= array($strname, $strhideshow, $strupdown, $strsettings);
3818 $table->align
= array('left', 'center', 'center', 'center');
3819 $table->width
= '90%';
3820 $table->data
= array();
3822 $filtersurl = "$CFG->wwwroot/$CFG->admin/filters.php?sesskey=".sesskey();
3823 $imgurl = "$CFG->pixpath/t";
3825 // iterate through filters adding to display table
3827 $activefilterscount = count($activefilters);
3828 foreach ($displayfilters as $path => $name) {
3829 $upath = urlencode($path);
3830 // get hide/show link
3831 if (in_array($path, $activefilters)) {
3832 $hideshow = "<a href=\"$filtersurl&action=hide&filterpath=$upath\">";
3833 $hideshow .= "<img src=\"{$CFG->pixpath}/i/hide.gif\" class=\"icon\" alt=\"$strhide\" /></a>";
3835 $displayname = "<span>$name</span>";
3838 $hideshow = "<a href=\"$filtersurl&action=show&filterpath=$upath\">";
3839 $hideshow .= "<img src=\"{$CFG->pixpath}/i/show.gif\" class=\"icon\" alt=\"$strshow\" /></a>";
3841 $displayname = "<span class=\"dimmed_text\">$name</span>";
3844 // get up/down link (only if not hidden)
3847 if ($updowncount>1) {
3848 $updown .= "<a href=\"$filtersurl&action=up&filterpath=$upath\">";
3849 $updown .= "<img src=\"$imgurl/up.gif\" alt=\"$strup\" /></a> ";
3852 $updown .= "<img src=\"$CFG->pixpath/spacer.gif\" class=\"icon\" alt=\"\" /> ";
3854 if ($updowncount<$activefilterscount) {
3855 $updown .= "<a href=\"$filtersurl&action=down&filterpath=$upath\">";
3856 $updown .= "<img src=\"$imgurl/down.gif\" alt=\"$strdown\" /></a>";
3859 $updown .= "<img src=\"$CFG->pixpath/spacer.gif\" class=\"icon\" alt=\"\" />";
3864 // settings link (if defined)
3866 if (in_array($path, $filtersettings_new)) {
3867 $settings = "<a href=\"settings.php?section=filtersetting".str_replace('/', '',$path)."\">$strsettings</a>";
3868 } else if (in_array($path, $filtersettings_old)) {
3869 $settings = "<a href=\"filter.php?filter=".urlencode($path)."\">$strsettings</a>";
3872 // write data into the table object
3873 $table->data
[] = array($displayname, $hideshow, $updown, $settings);
3875 $return .= print_table($table, true);
3876 $return .= get_string('tablenosave', 'filters');
3877 $return .= print_box_end(true);
3878 return highlight($query, $return);
3883 * Initialise admin page - this function does require login and permission
3884 * checks specified in page definition.
3885 * This function must be called on each admin page before other code.
3886 * @param string $section name of page
3888 function admin_externalpage_setup($section) {
3890 global $CFG, $PAGE, $USER;
3891 require_once($CFG->libdir
.'/blocklib.php');
3892 require_once($CFG->dirroot
.'/'.$CFG->admin
.'/pagelib.php');
3894 if ($site = get_site()) {
3897 redirect($CFG->wwwroot
.'/'.$CFG->admin
.'/index.php');
3901 $adminroot =& admin_get_root(false, false); // settings not required for external pages
3902 $extpage =& $adminroot->locate($section);
3904 if (empty($extpage) or !is_a($extpage, 'admin_externalpage')) {
3905 print_error('sectionerror', 'admin', "$CFG->wwwroot/$CFG->admin/");
3909 // this eliminates our need to authenticate on the actual pages
3910 if (!($extpage->check_access())) {
3911 print_error('accessdenied', 'admin');
3915 page_map_class(PAGE_ADMIN
, 'page_admin');
3916 $PAGE = page_create_object(PAGE_ADMIN
, 0); // there must be any constant id number
3917 $PAGE->init_extra($section); // hack alert!
3919 $adminediting = optional_param('adminedit', -1, PARAM_BOOL
);
3921 if (!isset($USER->adminediting
)) {
3922 $USER->adminediting
= false;
3925 if ($PAGE->user_allowed_editing()) {
3926 if ($adminediting == 1) {
3927 $USER->adminediting
= true;
3928 } elseif ($adminediting == 0) {
3929 $USER->adminediting
= false;
3935 * Print header for admin page
3936 * @param string $focus focus element
3938 function admin_externalpage_print_header($focus='') {
3940 if (!is_string($focus)) {
3941 $focus = ''; // BC compatibility, there used to be adminroot parameter
3944 global $CFG, $PAGE, $SITE, $THEME;
3946 define('ADMIN_EXT_HEADER_PRINTED', 'true');
3948 if (!empty($SITE->fullname
)) {
3949 $pageblocks = blocks_setup($PAGE);
3951 $preferred_width_left = bounded_number(BLOCK_L_MIN_WIDTH
,
3952 blocks_preferred_width($pageblocks[BLOCK_POS_LEFT
]),
3954 $preferred_width_right = bounded_number(BLOCK_R_MIN_WIDTH
,
3955 blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT
]),
3958 $PAGE->print_header('', $focus);
3959 echo '<table id="layout-table" summary=""><tr>';
3961 $lt = (empty($THEME->layouttable
)) ?
array('left', 'middle', 'right') : $THEME->layouttable
;
3962 foreach ($lt as $column) {
3964 if ($column == 'middle') break;
3966 foreach ($lt1 as $column) {
3969 echo '<td style="width: '.$preferred_width_left.'px;" id="left-column">';
3970 print_container_start();
3971 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT
);
3972 print_container_end();
3977 echo '<td id="middle-column">';
3978 print_container_start(true);
3979 $THEME->open_header_containers++
; // this is hacky workaround for the error()/notice() autoclosing problems on admin pages
3983 if (blocks_have_content($pageblocks, BLOCK_POS_RIGHT
)) {
3984 echo '<td style="width: '.$preferred_width_right.'px;" id="right-column">';
3985 print_container_start();
3986 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT
);
3987 print_container_end();
3999 * Print footer on admin page - please use normal print_footer() instead
4001 function admin_externalpage_print_footer() {
4003 global $CFG, $PAGE, $SITE, $THEME;
4005 define('ADMIN_EXT_FOOTER_PRINTED', 'true');
4007 if (!empty($SITE->fullname
)) {
4008 $pageblocks = blocks_setup($PAGE);
4009 $preferred_width_left = bounded_number(BLOCK_L_MIN_WIDTH
,
4010 blocks_preferred_width($pageblocks[BLOCK_POS_LEFT
]),
4012 $preferred_width_right = bounded_number(BLOCK_R_MIN_WIDTH
,
4013 blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT
]),
4016 $lt = (empty($THEME->layouttable
)) ?
array('left', 'middle', 'right') : $THEME->layouttable
;
4017 foreach ($lt as $column) {
4018 if ($column != 'middle') {
4020 } else if ($column == 'middle') {
4024 foreach ($lt as $column) {
4027 echo '<td style="width: '.$preferred_width_left.'px;" id="left-column">';
4028 print_container_start();
4029 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT
);
4030 print_container_end();
4035 print_container_end();
4036 $THEME->open_header_containers
--; // this is hacky workaround for the error()/notice() autoclosing problems on admin pages
4041 if (blocks_have_content($pageblocks, BLOCK_POS_RIGHT
)) {
4042 echo '<td style="width: '.$preferred_width_right.'px;" id="right-column">';
4043 print_container_start();
4044 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT
);
4045 print_container_end();
4051 echo '</tr></table>';
4057 * Returns the reference to admin tree root
4060 function &admin_get_root($reload=false, $requirefulltree=true) {
4063 static $ADMIN = NULL;
4065 if (!is_null($ADMIN)) {
4066 $olderrors = $ADMIN->errors
;
4067 $oldsearch = $ADMIN->search
;
4068 $oldfulltree = $ADMIN->fulltree
;
4070 $olderrors = array();
4072 $oldfulltree = false;
4075 if ($reload or ($requirefulltree and !$oldfulltree)) {
4079 if (is_null($ADMIN)) {
4080 // start the admin tree!
4081 $ADMIN = new admin_root();
4082 // array of error messages and search query
4083 $ADMIN->errors
= $olderrors;
4084 $ADMIN->search
= $oldsearch;
4085 if ($requirefulltree) {
4086 $ADMIN->fulltree
= true;
4088 $ADMIN->fulltree
= $oldfulltree;
4091 // we process this file first to create categories first and in correct order
4092 require($CFG->dirroot
.'/'.$CFG->admin
.'/settings/top.php');
4094 // now we process all other files in admin/settings to build the admin tree
4095 foreach (glob($CFG->dirroot
.'/'.$CFG->admin
.'/settings/*.php') as $file) {
4096 if ($file != $CFG->dirroot
.'/'.$CFG->admin
.'/settings/top.php') {
4100 if (file_exists($CFG->dirroot
.'/local/settings.php')) {
4101 include_once($CFG->dirroot
.'/local/settings.php');
4108 /// settings utility functions
4111 * This function applies default settings.
4112 * @param object $node, NULL means complete tree
4113 * @param bool $uncoditional if true overrides all values with defaults
4116 function admin_apply_default_settings($node=NULL, $unconditional=true) {
4119 if (is_null($node)) {
4120 $node =& admin_get_root();
4123 if (is_a($node, 'admin_category')) {
4124 $entries = array_keys($node->children
);
4125 foreach ($entries as $entry) {
4126 admin_apply_default_settings($node->children
[$entry], $unconditional);
4129 } else if (is_a($node, 'admin_settingpage')) {
4130 foreach ($node->settings
as $setting) {
4131 if (!$unconditional and !is_null($setting->get_setting())) {
4132 //do not override existing defaults
4135 $defaultsetting = $setting->get_defaultsetting();
4136 if (is_null($defaultsetting)) {
4137 // no value yet - default maybe applied after admin user creation or in upgradesettings
4140 $setting->write_setting($defaultsetting);
4146 * Store changed settings, this function updates the errors variable in $ADMIN
4147 * @param object $formdata from form (without magic quotes)
4148 * @return int number of changed settings
4150 function admin_write_settings($formdata) {
4151 global $CFG, $SITE, $COURSE;
4153 $olddbsessions = !empty($CFG->dbsessions
);
4154 $formdata = (array)stripslashes_recursive($formdata);
4157 foreach ($formdata as $fullname=>$value) {
4158 if (strpos($fullname, 's_') !== 0) {
4159 continue; // not a config value
4161 $data[$fullname] = $value;
4164 $adminroot =& admin_get_root();
4165 $settings = admin_find_write_settings($adminroot, $data);
4168 foreach ($settings as $fullname=>$setting) {
4169 $original = serialize($setting->get_setting()); // comparison must work for arrays too
4170 $error = $setting->write_setting($data[$fullname]);
4171 if ($error !== '') {
4172 $adminroot->errors
[$fullname] = new object();
4173 $adminroot->errors
[$fullname]->data
= $data[$fullname];
4174 $adminroot->errors
[$fullname]->id
= $setting->get_id();
4175 $adminroot->errors
[$fullname]->error
= $error;
4177 if ($original !== serialize($setting->get_setting())) {
4179 $callbackfunction = $setting->updatedcallback
;
4180 if (function_exists($callbackfunction)) {
4181 $callbackfunction($fullname);
4186 if ($olddbsessions != !empty($CFG->dbsessions
)) {
4190 // now update $SITE - it might have been changed
4191 $SITE = get_record('course', 'id', $SITE->id
);
4192 $COURSE = clone($SITE);
4194 // now reload all settings - some of them might depend on the changed
4195 admin_get_root(true);
4200 * Internal recursive function - finds all settings from submitted form
4202 function admin_find_write_settings($node, $data) {
4209 if (is_a($node, 'admin_category')) {
4210 $entries = array_keys($node->children
);
4211 foreach ($entries as $entry) {
4212 $return = array_merge($return, admin_find_write_settings($node->children
[$entry], $data));
4215 } else if (is_a($node, 'admin_settingpage')) {
4216 foreach ($node->settings
as $setting) {
4217 $fullname = $setting->get_full_name();
4218 if (array_key_exists($fullname, $data)) {
4219 $return[$fullname] = $setting;
4229 * Internal function - prints the search results
4231 function admin_search_settings_html($query) {
4234 $textlib = textlib_get_instance();
4235 if ($textlib->strlen($query) < 2) {
4238 $query = $textlib->strtolower($query);
4240 $adminroot =& admin_get_root();
4241 $findings = $adminroot->search($query);
4243 $savebutton = false;
4245 foreach ($findings as $found) {
4246 $page = $found->page
;
4247 $settings = $found->settings
;
4248 if ($page->is_hidden()) {
4249 // hidden pages are not displayed in search results
4252 if (is_a($page, 'admin_externalpage')) {
4253 $return .= print_heading(get_string('searchresults','admin').' - <a href="'.$page->url
.'">'.highlight($query, $page->visiblename
).'</a>', '', 2, 'main', true);
4254 } else if (is_a($page, 'admin_settingpage')) {
4255 $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);
4259 if (!empty($settings)) {
4261 $return .= '<fieldset class="adminsettings">'."\n";
4262 foreach ($settings as $setting) {
4263 $return .= '<div class="clearer"><!-- --></div>'."\n";
4264 $fullname = $setting->get_full_name();
4265 if (array_key_exists($fullname, $adminroot->errors
)) {
4266 $data = $adminroot->errors
[$fullname]->data
;
4268 $data = $setting->get_setting();
4269 if (is_null($data)) {
4270 $data = $setting->get_defaultsetting();
4273 $return .= $setting->output_html($data, $query);
4275 $return .= '</fieldset>';
4280 $return .= '<div class="form-buttons"><input class="form-submit" type="submit" value="'.get_string('savechanges','admin').'" /></div>';
4287 * Internal function - prints list of uninitialised settings
4289 function admin_output_new_settings_by_page($node) {
4292 if (is_a($node, 'admin_category')) {
4293 $entries = array_keys($node->children
);
4294 foreach ($entries as $entry) {
4295 $return .= admin_output_new_settings_by_page($node->children
[$entry]);
4298 } else if (is_a($node, 'admin_settingpage')) {
4299 $newsettings = array();
4300 foreach ($node->settings
as $setting) {
4301 if (is_null($setting->get_setting())) {
4302 $newsettings[] = $setting;
4305 if (count($newsettings) > 0) {
4306 $adminroot =& admin_get_root();
4307 $return .= print_heading(get_string('upgradesettings','admin').' - '.$node->visiblename
, '', 2, 'main', true);
4308 $return .= '<fieldset class="adminsettings">'."\n";
4309 foreach ($newsettings as $setting) {
4310 $fullname = $setting->get_full_name();
4311 if (array_key_exists($fullname, $adminroot->errors
)) {
4312 $data = $adminroot->errors
[$fullname]->data
;
4314 $data = $setting->get_setting();
4315 if (is_null($data)) {
4316 $data = $setting->get_defaultsetting();
4319 $return .= '<div class="clearer"><!-- --></div>'."\n";
4320 $return .= $setting->output_html($data);
4322 $return .= '</fieldset>';
4330 * Unconditionally applies default admin settings in main config table
4331 * @param array $defaults array of string values
4333 function apply_default_exception_settings($defaults) {
4334 foreach($defaults as $key => $value) {
4335 set_config($key, $value, NULL);
4340 * Format admin settings
4341 * @param string $object setting
4342 * @param string $title label element
4343 * @param string $form form fragment, html code - not highlighed automaticaly
4344 * @param string $description
4345 * @param bool $label link label to id
4346 * @param string $warning warning text
4347 * @param sting $defaultinfo defaults info, null means nothing, '' is converted to "Empty" string
4348 * @param string $query search query to be highlighted
4350 function format_admin_setting($setting, $title='', $form='', $description='', $label=true, $warning='', $defaultinfo=NULL, $query='') {
4353 $name = $setting->name
;
4354 $fullname = $setting->get_full_name();
4356 // sometimes the id is not id_s_name, but id_s_name_m or something, and this does not validate
4358 $labelfor = 'for = "'.$setting->get_id().'"';
4363 if (empty($setting->plugin
) and array_key_exists($name, $CFG->config_php_settings
)) {
4364 $override = '<div class="form-overridden">'.get_string('configoverride', 'admin').'</div>';
4369 if ($warning !== '') {
4370 $warning = '<div class="form-warning">'.$warning.'</div>';
4373 if (is_null($defaultinfo)) {
4376 if ($defaultinfo === '') {
4377 $defaultinfo = get_string('emptysettingvalue', 'admin');
4379 $defaultinfo = highlight($query, nl2br(s($defaultinfo)));
4380 $defaultinfo = '<div class="form-defaultinfo">'.get_string('defaultsettinginfo', 'admin', $defaultinfo).'</div>';
4385 <div class="form-item clearfix" id="admin-'.$setting->name
.'">
4386 <div class="form-label">
4387 <label '.$labelfor.'>'.highlightfast($query, $title).'<span class="form-shortname">'.highlightfast($query, $name).'</span>
4388 '.$override.$warning.'
4391 <div class="form-setting">'.$form.$defaultinfo.'</div>
4392 <div class="form-description">'.highlight($query, $description).'</div>
4395 $adminroot =& admin_get_root();
4396 if (array_key_exists($fullname, $adminroot->errors
)) {
4397 $str = '<fieldset class="error"><legend>'.$adminroot->errors
[$fullname]->error
.'</legend>'.$str.'</fieldset>';
4404 * Try to upgrade the given language pack (or current language)
4405 * If it doesn't work, fail silently and return false
4407 function upgrade_language_pack($lang='') {
4411 $lang = current_language();
4414 if ($lang == 'en_utf8') {
4415 return true; // Nothing to do
4418 notify(get_string('langimport', 'admin').': '.$lang.' ... ', 'notifysuccess');
4420 @mkdir
($CFG->dataroot
.'/temp/'); //make it in case it's a fresh install, it might not be there
4421 @mkdir
($CFG->dataroot
.'/lang/');
4423 require_once($CFG->libdir
.'/componentlib.class.php');
4425 if ($cd = new component_installer('http://download.moodle.org', 'lang16', $lang.'.zip', 'languages.md5', 'lang')) {
4426 $status = $cd->install(); //returns COMPONENT_(ERROR | UPTODATE | INSTALLED)
4428 if ($status == COMPONENT_INSTALLED
) {
4429 debugging('Downloading successful: '.$lang);
4430 @unlink
($CFG->dataroot
.'/cache/languages');
4439 * Based on find_new_settings{@link ()} in upgradesettings.php
4440 * Looks to find any admin settings that have not been initialized. Returns 1 if it finds any.
4442 * @param string $node The node at which to start searching.
4443 * @return boolen true if any settings haven't been initialised, false if they all have
4445 function any_new_admin_settings($node) {
4447 if (is_a($node, 'admin_category')) {
4448 $entries = array_keys($node->children
);
4449 foreach ($entries as $entry) {
4450 if (any_new_admin_settings($node->children
[$entry])){
4455 } else if (is_a($node, 'admin_settingpage')) {
4456 foreach ($node->settings
as $setting) {
4457 if ($setting->get_setting() === NULL) {
4468 * Moved from admin/replace.php so that we can use this in cron
4469 * @param string $search - string to look for (with magic quotes)
4470 * @param string $replace - string to replace (with magic quotes)
4471 * @return bool - success or fail
4473 function db_replace($search, $replace) {
4477 /// Turn off time limits, sometimes upgrades can be slow.
4479 @ob_implicit_flush
(true);
4480 while(@ob_end_flush
());
4482 if (!$tables = $db->Metatables() ) { // No tables yet at all.
4485 foreach ($tables as $table) {
4487 if (in_array($table, array($CFG->prefix
.'config'))) { // Don't process these
4491 if ($columns = $db->MetaColumns($table, false)) {
4492 foreach ($columns as $column => $data) {
4493 if (in_array($data->type
, array('text','mediumtext','longtext','varchar'))) { // Text stuff only
4495 execute_sql("UPDATE $table SET $column = REPLACE($column, '$search', '$replace');");
4506 * Prints tables of detected plugins, one table per plugin type,
4507 * and prints whether they are part of the standard Moodle
4508 * distribution or not.
4510 function print_plugin_tables() {
4511 $plugins_standard = array();
4512 $plugins_standard['mod'] = array('assignment',
4531 $plugins_standard['blocks'] = array('activity_modules',
4538 'calendar_upcoming',
4558 'social_activities',
4563 $plugins_standard['filter'] = array('activitynames',
4573 $plugins_installed = array();
4574 $installed_mods = get_records_list('modules', '', '', '', 'name');
4575 $installed_blocks = get_records_list('block', '', '', '', 'name');
4577 foreach($installed_mods as $mod) {
4578 $plugins_installed['mod'][] = $mod->name
;
4581 foreach($installed_blocks as $block) {
4582 $plugins_installed['blocks'][] = $block->name
;
4585 $plugins_ondisk = array();
4586 $plugins_ondisk['mod'] = get_list_of_plugins('mod', 'db');
4587 $plugins_ondisk['blocks'] = get_list_of_plugins('blocks', 'db');
4588 $plugins_ondisk['filter'] = get_list_of_plugins('filter', 'db');
4590 $strstandard = get_string('standard');
4591 $strnonstandard = get_string('nonstandard');
4592 $strmissingfromdisk = '(' . get_string('missingfromdisk') . ')';
4593 $strabouttobeinstalled = '(' . get_string('abouttobeinstalled') . ')';
4597 $html .= '<table class="generaltable plugincheckwrapper" cellspacing="4" cellpadding="1"><tr valign="top">';
4599 foreach ($plugins_ondisk as $cat => $list_ondisk) {
4600 $strcaption = get_string($cat);
4601 if ($cat == 'mod') {
4602 $strcaption = get_string('activitymodule');
4603 } elseif ($cat == 'filter') {
4604 $strcaption = get_string('managefilters');
4607 $html .= '<td><table class="plugincompattable generaltable boxaligncenter" cellspacing="1" cellpadding="5" '
4608 . 'id="' . $cat . 'compattable" summary="compatibility table"><caption>' . $strcaption . '</caption>' . "\n";
4609 $html .= '<tr class="r0"><th class="header c0">' . get_string('directory') . "</th>\n"
4610 . '<th class="header c1">' . get_string('name') . "</th>\n"
4611 . '<th class="header c2">' . get_string('status') . "</th>\n</tr>\n";
4615 foreach ($list_ondisk as $k => $plugin) {
4617 $standard = 'standard';
4620 if (!in_array($plugin, $plugins_standard[$cat])) {
4621 $standard = 'nonstandard';
4622 $status = 'warning';
4625 // Get real name and full path of plugin
4626 $plugin_name = "[[$plugin]]";
4628 $plugin_path = "$cat/$plugin";
4630 $plugin_name = get_plugin_name($plugin, $cat);
4632 // Determine if the plugin is about to be installed
4633 if ($cat != 'filter' && !in_array($plugin, $plugins_installed[$cat])) {
4634 $note = $strabouttobeinstalled;
4635 $plugin_name = $plugin;
4638 $html .= "<tr class=\"r$row\">\n"
4639 . "<td class=\"cell c0\">$plugin_path</td>\n"
4640 . "<td class=\"cell c1\">$plugin_name</td>\n"
4641 . "<td class=\"$standard $status cell c2\">" . $
{'str' . $standard} . " $note</td>\n</tr>\n";
4644 // If the plugin was both on disk and in the db, unset the value from the installed plugins list
4645 if ($key = array_search($plugin, $plugins_installed[$cat])) {
4646 unset($plugins_installed[$cat][$key]);
4650 // If there are plugins left in the plugins_installed list, it means they are missing from disk
4651 foreach ($plugins_installed[$cat] as $k => $missing_plugin) {
4652 // Make sure the plugin really is missing from disk
4653 if (!in_array($missing_plugin, $plugins_ondisk[$cat])) {
4654 $standard = 'standard';
4655 $status = 'warning';
4657 if (!in_array($missing_plugin, $plugins_standard[$cat])) {
4658 $standard = 'nonstandard';
4661 $plugin_name = $missing_plugin;
4662 $html .= "<tr class=\"r$row\">\n"
4663 . "<td class=\"cell c0\">?</td>\n"
4664 . "<td class=\"cell c1\">$plugin_name</td>\n"
4665 . "<td class=\"$standard $status cell c2\">" . $
{'str' . $standard} . " $strmissingfromdisk</td>\n</tr>\n";
4670 $html .= '</table></td>';
4673 $html .= '</tr></table><br />';