Automatic installer lang files (20110214)
[moodle.git] / lib / adminlib.php
blobf6edb2cf1b52da17f215aa1ef405a6d22b045be1
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
18 /**
19 * Functions and classes used during installation, upgrades and for admin settings.
21 * ADMIN SETTINGS TREE INTRODUCTION
23 * This file performs the following tasks:
24 * -it defines the necessary objects and interfaces to build the Moodle
25 * admin hierarchy
26 * -it defines the admin_externalpage_setup()
28 * ADMIN_SETTING OBJECTS
30 * Moodle settings are represented by objects that inherit from the admin_setting
31 * class. These objects encapsulate how to read a setting, how to write a new value
32 * to a setting, and how to appropriately display the HTML to modify the setting.
34 * ADMIN_SETTINGPAGE OBJECTS
36 * The admin_setting objects are then grouped into admin_settingpages. The latter
37 * appear in the Moodle admin tree block. All interaction with admin_settingpage
38 * objects is handled by the admin/settings.php file.
40 * ADMIN_EXTERNALPAGE OBJECTS
42 * There are some settings in Moodle that are too complex to (efficiently) handle
43 * with admin_settingpages. (Consider, for example, user management and displaying
44 * lists of users.) In this case, we use the admin_externalpage object. This object
45 * places a link to an external PHP file in the admin tree block.
47 * If you're using an admin_externalpage object for some settings, you can take
48 * advantage of the admin_externalpage_* functions. For example, suppose you wanted
49 * to add a foo.php file into admin. First off, you add the following line to
50 * admin/settings/first.php (at the end of the file) or to some other file in
51 * admin/settings:
52 * <code>
53 * $ADMIN->add('userinterface', new admin_externalpage('foo', get_string('foo'),
54 * $CFG->wwwdir . '/' . '$CFG->admin . '/foo.php', 'some_role_permission'));
55 * </code>
57 * Next, in foo.php, your file structure would resemble the following:
58 * <code>
59 * require(dirname(dirname(dirname(__FILE__))).'/config.php');
60 * require_once($CFG->libdir.'/adminlib.php');
61 * admin_externalpage_setup('foo');
62 * // functionality like processing form submissions goes here
63 * echo $OUTPUT->header();
64 * // your HTML goes here
65 * echo $OUTPUT->footer();
66 * </code>
68 * The admin_externalpage_setup() function call ensures the user is logged in,
69 * and makes sure that they have the proper role permission to access the page.
70 * It also configures all $PAGE properties needed for navigation.
72 * ADMIN_CATEGORY OBJECTS
74 * Above and beyond all this, we have admin_category objects. These objects
75 * appear as folders in the admin tree block. They contain admin_settingpage's,
76 * admin_externalpage's, and other admin_category's.
78 * OTHER NOTES
80 * admin_settingpage's, admin_externalpage's, and admin_category's all inherit
81 * from part_of_admin_tree (a pseudointerface). This interface insists that
82 * a class has a check_access method for access permissions, a locate method
83 * used to find a specific node in the admin tree and find parent path.
85 * admin_category's inherit from parentable_part_of_admin_tree. This pseudo-
86 * interface ensures that the class implements a recursive add function which
87 * accepts a part_of_admin_tree object and searches for the proper place to
88 * put it. parentable_part_of_admin_tree implies part_of_admin_tree.
90 * Please note that the $this->name field of any part_of_admin_tree must be
91 * UNIQUE throughout the ENTIRE admin tree.
93 * The $this->name field of an admin_setting object (which is *not* part_of_
94 * admin_tree) must be unique on the respective admin_settingpage where it is
95 * used.
97 * Original author: Vincenzo K. Marcovecchio
98 * Maintainer: Petr Skoda
100 * @package core
101 * @subpackage admin
102 * @copyright 1999 onwards Martin Dougiamas http://dougiamas.com
103 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
106 defined('MOODLE_INTERNAL') || die();
108 /// Add libraries
109 require_once($CFG->libdir.'/ddllib.php');
110 require_once($CFG->libdir.'/xmlize.php');
112 define('INSECURE_DATAROOT_WARNING', 1);
113 define('INSECURE_DATAROOT_ERROR', 2);
116 * Automatically clean-up all plugin data and remove the plugin DB tables
118 * @param string $type The plugin type, eg. 'mod', 'qtype', 'workshopgrading' etc.
119 * @param string $name The plugin name, eg. 'forum', 'multichoice', 'accumulative' etc.
120 * @uses global $OUTPUT to produce notices and other messages
121 * @return void
123 function uninstall_plugin($type, $name) {
124 global $CFG, $DB, $OUTPUT;
126 // recursively uninstall all module subplugins first
127 if ($type === 'mod') {
128 if (file_exists("$CFG->dirroot/mod/$name/db/subplugins.php")) {
129 $subplugins = array();
130 include("$CFG->dirroot/mod/$name/db/subplugins.php");
131 foreach ($subplugins as $subplugintype=>$dir) {
132 $instances = get_plugin_list($subplugintype);
133 foreach ($instances as $subpluginname => $notusedpluginpath) {
134 uninstall_plugin($subplugintype, $subpluginname);
141 $component = $type . '_' . $name; // eg. 'qtype_multichoice' or 'workshopgrading_accumulative' or 'mod_forum'
143 if ($type === 'mod') {
144 $pluginname = $name; // eg. 'forum'
145 if (get_string_manager()->string_exists('modulename', $component)) {
146 $strpluginname = get_string('modulename', $component);
147 } else {
148 $strpluginname = $component;
151 } else {
152 $pluginname = $component;
153 if (get_string_manager()->string_exists('pluginname', $component)) {
154 $strpluginname = get_string('pluginname', $component);
155 } else {
156 $strpluginname = $component;
160 echo $OUTPUT->heading($pluginname);
162 $plugindirectory = get_plugin_directory($type, $name);
163 $uninstalllib = $plugindirectory . '/db/uninstall.php';
164 if (file_exists($uninstalllib)) {
165 require_once($uninstalllib);
166 $uninstallfunction = 'xmldb_' . $pluginname . '_uninstall'; // eg. 'xmldb_workshop_uninstall()'
167 if (function_exists($uninstallfunction)) {
168 if (!$uninstallfunction()) {
169 echo $OUTPUT->notification('Encountered a problem running uninstall function for '. $pluginname);
174 if ($type === 'mod') {
175 // perform cleanup tasks specific for activity modules
177 if (!$module = $DB->get_record('modules', array('name' => $name))) {
178 print_error('moduledoesnotexist', 'error');
181 // delete all the relevant instances from all course sections
182 if ($coursemods = $DB->get_records('course_modules', array('module' => $module->id))) {
183 foreach ($coursemods as $coursemod) {
184 if (!delete_mod_from_section($coursemod->id, $coursemod->section)) {
185 echo $OUTPUT->notification("Could not delete the $strpluginname with id = $coursemod->id from section $coursemod->section");
190 // clear course.modinfo for courses that used this module
191 $sql = "UPDATE {course}
192 SET modinfo=''
193 WHERE id IN (SELECT DISTINCT course
194 FROM {course_modules}
195 WHERE module=?)";
196 $DB->execute($sql, array($module->id));
198 // delete all the course module records
199 $DB->delete_records('course_modules', array('module' => $module->id));
201 // delete module contexts
202 if ($coursemods) {
203 foreach ($coursemods as $coursemod) {
204 if (!delete_context(CONTEXT_MODULE, $coursemod->id)) {
205 echo $OUTPUT->notification("Could not delete the context for $strpluginname with id = $coursemod->id");
210 // delete the module entry itself
211 $DB->delete_records('modules', array('name' => $module->name));
213 // cleanup the gradebook
214 require_once($CFG->libdir.'/gradelib.php');
215 grade_uninstalled_module($module->name);
217 // Perform any custom uninstall tasks
218 if (file_exists($CFG->dirroot . '/mod/' . $module->name . '/lib.php')) {
219 require_once($CFG->dirroot . '/mod/' . $module->name . '/lib.php');
220 $uninstallfunction = $module->name . '_uninstall';
221 if (function_exists($uninstallfunction)) {
222 debugging("{$uninstallfunction}() has been deprecated. Use the plugin's db/uninstall.php instead", DEBUG_DEVELOPER);
223 if (!$uninstallfunction()) {
224 echo $OUTPUT->notification('Encountered a problem running uninstall function for '. $module->name.'!');
229 } else if ($type === 'enrol') {
230 // NOTE: this is a bit brute force way - it will not trigger events and hooks properly
231 // nuke all role assignments
232 role_unassign_all(array('component'=>$component));
233 // purge participants
234 $DB->delete_records_select('user_enrolments', "enrolid IN (SELECT id FROM {enrol} WHERE enrol = ?)", array($name));
235 // purge enrol instances
236 $DB->delete_records('enrol', array('enrol'=>$name));
237 // tweak enrol settings
238 if (!empty($CFG->enrol_plugins_enabled)) {
239 $enabledenrols = explode(',', $CFG->enrol_plugins_enabled);
240 $enabledenrols = array_unique($enabledenrols);
241 $enabledenrols = array_flip($enabledenrols);
242 unset($enabledenrols[$name]);
243 $enabledenrols = array_flip($enabledenrols);
244 if (is_array($enabledenrols)) {
245 set_config('enrol_plugins_enabled', implode(',', $enabledenrols));
250 // perform clean-up task common for all the plugin/subplugin types
252 // delete calendar events
253 $DB->delete_records('event', array('modulename' => $pluginname));
255 // delete all the logs
256 $DB->delete_records('log', array('module' => $pluginname));
258 // delete log_display information
259 $DB->delete_records('log_display', array('component' => $component));
261 // delete the module configuration records
262 unset_all_config_for_plugin($pluginname);
264 // delete the plugin tables
265 $xmldbfilepath = $plugindirectory . '/db/install.xml';
266 drop_plugin_tables($pluginname, $xmldbfilepath, false);
268 // delete the capabilities that were defined by this module
269 capabilities_cleanup($component);
271 // remove event handlers and dequeue pending events
272 events_uninstall($component);
274 echo $OUTPUT->notification(get_string('success'), 'notifysuccess');
278 * Returns the version of installed component
280 * @param string $component component name
281 * @param string $source either 'disk' or 'installed' - where to get the version information from
282 * @return string|bool version number or false if the component is not found
284 function get_component_version($component, $source='installed') {
285 global $CFG, $DB;
287 list($type, $name) = normalize_component($component);
289 // moodle core or a core subsystem
290 if ($type === 'core') {
291 if ($source === 'installed') {
292 if (empty($CFG->version)) {
293 return false;
294 } else {
295 return $CFG->version;
297 } else {
298 if (!is_readable($CFG->dirroot.'/version.php')) {
299 return false;
300 } else {
301 $version = null; //initialize variable for IDEs
302 include($CFG->dirroot.'/version.php');
303 return $version;
308 // activity module
309 if ($type === 'mod') {
310 if ($source === 'installed') {
311 return $DB->get_field('modules', 'version', array('name'=>$name));
312 } else {
313 $mods = get_plugin_list('mod');
314 if (empty($mods[$name]) or !is_readable($mods[$name].'/version.php')) {
315 return false;
316 } else {
317 $module = new stdclass();
318 include($mods[$name].'/version.php');
319 return $module->version;
324 // block
325 if ($type === 'block') {
326 if ($source === 'installed') {
327 return $DB->get_field('block', 'version', array('name'=>$name));
328 } else {
329 $blocks = get_plugin_list('block');
330 if (empty($blocks[$name]) or !is_readable($blocks[$name].'/version.php')) {
331 return false;
332 } else {
333 $plugin = new stdclass();
334 include($blocks[$name].'/version.php');
335 return $plugin->version;
340 // all other plugin types
341 if ($source === 'installed') {
342 return get_config($type.'_'.$name, 'version');
343 } else {
344 $plugins = get_plugin_list($type);
345 if (empty($plugins[$name])) {
346 return false;
347 } else {
348 $plugin = new stdclass();
349 include($plugins[$name].'/version.php');
350 return $plugin->version;
356 * Delete all plugin tables
358 * @param string $name Name of plugin, used as table prefix
359 * @param string $file Path to install.xml file
360 * @param bool $feedback defaults to true
361 * @return bool Always returns true
363 function drop_plugin_tables($name, $file, $feedback=true) {
364 global $CFG, $DB;
366 // first try normal delete
367 if (file_exists($file) and $DB->get_manager()->delete_tables_from_xmldb_file($file)) {
368 return true;
371 // then try to find all tables that start with name and are not in any xml file
372 $used_tables = get_used_table_names();
374 $tables = $DB->get_tables();
376 /// Iterate over, fixing id fields as necessary
377 foreach ($tables as $table) {
378 if (in_array($table, $used_tables)) {
379 continue;
382 if (strpos($table, $name) !== 0) {
383 continue;
386 // found orphan table --> delete it
387 if ($DB->get_manager()->table_exists($table)) {
388 $xmldb_table = new xmldb_table($table);
389 $DB->get_manager()->drop_table($xmldb_table);
393 return true;
397 * Returns names of all known tables == tables that moodle knows about.
399 * @return array Array of lowercase table names
401 function get_used_table_names() {
402 $table_names = array();
403 $dbdirs = get_db_directories();
405 foreach ($dbdirs as $dbdir) {
406 $file = $dbdir.'/install.xml';
408 $xmldb_file = new xmldb_file($file);
410 if (!$xmldb_file->fileExists()) {
411 continue;
414 $loaded = $xmldb_file->loadXMLStructure();
415 $structure = $xmldb_file->getStructure();
417 if ($loaded and $tables = $structure->getTables()) {
418 foreach($tables as $table) {
419 $table_names[] = strtolower($table->name);
424 return $table_names;
428 * Returns list of all directories where we expect install.xml files
429 * @return array Array of paths
431 function get_db_directories() {
432 global $CFG;
434 $dbdirs = array();
436 /// First, the main one (lib/db)
437 $dbdirs[] = $CFG->libdir.'/db';
439 /// Then, all the ones defined by get_plugin_types()
440 $plugintypes = get_plugin_types();
441 foreach ($plugintypes as $plugintype => $pluginbasedir) {
442 if ($plugins = get_plugin_list($plugintype)) {
443 foreach ($plugins as $plugin => $plugindir) {
444 $dbdirs[] = $plugindir.'/db';
449 return $dbdirs;
453 * Try to obtain or release the cron lock.
454 * @param string $name name of lock
455 * @param int $until timestamp when this lock considered stale, null means remove lock unconditionally
456 * @param bool $ignorecurrent ignore current lock state, usually extend previous lock, defaults to false
457 * @return bool true if lock obtained
459 function set_cron_lock($name, $until, $ignorecurrent=false) {
460 global $DB;
461 if (empty($name)) {
462 debugging("Tried to get a cron lock for a null fieldname");
463 return false;
466 // remove lock by force == remove from config table
467 if (is_null($until)) {
468 set_config($name, null);
469 return true;
472 if (!$ignorecurrent) {
473 // read value from db - other processes might have changed it
474 $value = $DB->get_field('config', 'value', array('name'=>$name));
476 if ($value and $value > time()) {
477 //lock active
478 return false;
482 set_config($name, $until);
483 return true;
487 * Test if and critical warnings are present
488 * @return bool
490 function admin_critical_warnings_present() {
491 global $SESSION;
493 if (!has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) {
494 return 0;
497 if (!isset($SESSION->admin_critical_warning)) {
498 $SESSION->admin_critical_warning = 0;
499 if (is_dataroot_insecure(true) === INSECURE_DATAROOT_ERROR) {
500 $SESSION->admin_critical_warning = 1;
504 return $SESSION->admin_critical_warning;
508 * Detects if float supports at least 10 decimal digits
510 * Detects if float supports at least 10 decimal digits
511 * and also if float-->string conversion works as expected.
513 * @return bool true if problem found
515 function is_float_problem() {
516 $num1 = 2009010200.01;
517 $num2 = 2009010200.02;
519 return ((string)$num1 === (string)$num2 or $num1 === $num2 or $num2 <= (string)$num1);
523 * Try to verify that dataroot is not accessible from web.
525 * Try to verify that dataroot is not accessible from web.
526 * It is not 100% correct but might help to reduce number of vulnerable sites.
527 * Protection from httpd.conf and .htaccess is not detected properly.
529 * @uses INSECURE_DATAROOT_WARNING
530 * @uses INSECURE_DATAROOT_ERROR
531 * @param bool $fetchtest try to test public access by fetching file, default false
532 * @return mixed empty means secure, INSECURE_DATAROOT_ERROR found a critical problem, INSECURE_DATAROOT_WARNING might be problematic
534 function is_dataroot_insecure($fetchtest=false) {
535 global $CFG;
537 $siteroot = str_replace('\\', '/', strrev($CFG->dirroot.'/')); // win32 backslash workaround
539 $rp = preg_replace('|https?://[^/]+|i', '', $CFG->wwwroot, 1);
540 $rp = strrev(trim($rp, '/'));
541 $rp = explode('/', $rp);
542 foreach($rp as $r) {
543 if (strpos($siteroot, '/'.$r.'/') === 0) {
544 $siteroot = substr($siteroot, strlen($r)+1); // moodle web in subdirectory
545 } else {
546 break; // probably alias root
550 $siteroot = strrev($siteroot);
551 $dataroot = str_replace('\\', '/', $CFG->dataroot.'/');
553 if (strpos($dataroot, $siteroot) !== 0) {
554 return false;
557 if (!$fetchtest) {
558 return INSECURE_DATAROOT_WARNING;
561 // now try all methods to fetch a test file using http protocol
563 $httpdocroot = str_replace('\\', '/', strrev($CFG->dirroot.'/'));
564 preg_match('|(https?://[^/]+)|i', $CFG->wwwroot, $matches);
565 $httpdocroot = $matches[1];
566 $datarooturl = $httpdocroot.'/'. substr($dataroot, strlen($siteroot));
567 make_upload_directory('diag');
568 $testfile = $CFG->dataroot.'/diag/public.txt';
569 if (!file_exists($testfile)) {
570 file_put_contents($testfile, 'test file, do not delete');
572 $teststr = trim(file_get_contents($testfile));
573 if (empty($teststr)) {
574 // hmm, strange
575 return INSECURE_DATAROOT_WARNING;
578 $testurl = $datarooturl.'/diag/public.txt';
579 if (extension_loaded('curl') and
580 !(stripos(ini_get('disable_functions'), 'curl_init') !== FALSE) and
581 !(stripos(ini_get('disable_functions'), 'curl_setop') !== FALSE) and
582 ($ch = @curl_init($testurl)) !== false) {
583 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
584 curl_setopt($ch, CURLOPT_HEADER, false);
585 $data = curl_exec($ch);
586 if (!curl_errno($ch)) {
587 $data = trim($data);
588 if ($data === $teststr) {
589 curl_close($ch);
590 return INSECURE_DATAROOT_ERROR;
593 curl_close($ch);
596 if ($data = @file_get_contents($testurl)) {
597 $data = trim($data);
598 if ($data === $teststr) {
599 return INSECURE_DATAROOT_ERROR;
603 preg_match('|https?://([^/]+)|i', $testurl, $matches);
604 $sitename = $matches[1];
605 $error = 0;
606 if ($fp = @fsockopen($sitename, 80, $error)) {
607 preg_match('|https?://[^/]+(.*)|i', $testurl, $matches);
608 $localurl = $matches[1];
609 $out = "GET $localurl HTTP/1.1\r\n";
610 $out .= "Host: $sitename\r\n";
611 $out .= "Connection: Close\r\n\r\n";
612 fwrite($fp, $out);
613 $data = '';
614 $incoming = false;
615 while (!feof($fp)) {
616 if ($incoming) {
617 $data .= fgets($fp, 1024);
618 } else if (@fgets($fp, 1024) === "\r\n") {
619 $incoming = true;
622 fclose($fp);
623 $data = trim($data);
624 if ($data === $teststr) {
625 return INSECURE_DATAROOT_ERROR;
629 return INSECURE_DATAROOT_WARNING;
632 /// CLASS DEFINITIONS /////////////////////////////////////////////////////////
635 * Interface for anything appearing in the admin tree
637 * The interface that is implemented by anything that appears in the admin tree
638 * block. It forces inheriting classes to define a method for checking user permissions
639 * and methods for finding something in the admin tree.
641 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
643 interface part_of_admin_tree {
646 * Finds a named part_of_admin_tree.
648 * Used to find a part_of_admin_tree. If a class only inherits part_of_admin_tree
649 * and not parentable_part_of_admin_tree, then this function should only check if
650 * $this->name matches $name. If it does, it should return a reference to $this,
651 * otherwise, it should return a reference to NULL.
653 * If a class inherits parentable_part_of_admin_tree, this method should be called
654 * recursively on all child objects (assuming, of course, the parent object's name
655 * doesn't match the search criterion).
657 * @param string $name The internal name of the part_of_admin_tree we're searching for.
658 * @return mixed An object reference or a NULL reference.
660 public function locate($name);
663 * Removes named part_of_admin_tree.
665 * @param string $name The internal name of the part_of_admin_tree we want to remove.
666 * @return bool success.
668 public function prune($name);
671 * Search using query
672 * @param string $query
673 * @return mixed array-object structure of found settings and pages
675 public function search($query);
678 * Verifies current user's access to this part_of_admin_tree.
680 * Used to check if the current user has access to this part of the admin tree or
681 * not. If a class only inherits part_of_admin_tree and not parentable_part_of_admin_tree,
682 * then this method is usually just a call to has_capability() in the site context.
684 * If a class inherits parentable_part_of_admin_tree, this method should return the
685 * logical OR of the return of check_access() on all child objects.
687 * @return bool True if the user has access, false if she doesn't.
689 public function check_access();
692 * Mostly useful for removing of some parts of the tree in admin tree block.
694 * @return True is hidden from normal list view
696 public function is_hidden();
699 * Show we display Save button at the page bottom?
700 * @return bool
702 public function show_save();
706 * Interface implemented by any part_of_admin_tree that has children.
708 * The interface implemented by any part_of_admin_tree that can be a parent
709 * to other part_of_admin_tree's. (For now, this only includes admin_category.) Apart
710 * from ensuring part_of_admin_tree compliancy, it also ensures inheriting methods
711 * include an add method for adding other part_of_admin_tree objects as children.
713 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
715 interface parentable_part_of_admin_tree extends part_of_admin_tree {
718 * Adds a part_of_admin_tree object to the admin tree.
720 * Used to add a part_of_admin_tree object to this object or a child of this
721 * object. $something should only be added if $destinationname matches
722 * $this->name. If it doesn't, add should be called on child objects that are
723 * also parentable_part_of_admin_tree's.
725 * @param string $destinationname The internal name of the new parent for $something.
726 * @param part_of_admin_tree $something The object to be added.
727 * @return bool True on success, false on failure.
729 public function add($destinationname, $something);
734 * The object used to represent folders (a.k.a. categories) in the admin tree block.
736 * Each admin_category object contains a number of part_of_admin_tree objects.
738 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
740 class admin_category implements parentable_part_of_admin_tree {
742 /** @var mixed An array of part_of_admin_tree objects that are this object's children */
743 public $children;
744 /** @var string An internal name for this category. Must be unique amongst ALL part_of_admin_tree objects */
745 public $name;
746 /** @var string The displayed name for this category. Usually obtained through get_string() */
747 public $visiblename;
748 /** @var bool Should this category be hidden in admin tree block? */
749 public $hidden;
750 /** @var mixed Either a string or an array or strings */
751 public $path;
752 /** @var mixed Either a string or an array or strings */
753 public $visiblepath;
756 * Constructor for an empty admin category
758 * @param string $name The internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
759 * @param string $visiblename The displayed named for this category. Usually obtained through get_string()
760 * @param bool $hidden hide category in admin tree block, defaults to false
762 public function __construct($name, $visiblename, $hidden=false) {
763 $this->children = array();
764 $this->name = $name;
765 $this->visiblename = $visiblename;
766 $this->hidden = $hidden;
770 * Returns a reference to the part_of_admin_tree object with internal name $name.
772 * @param string $name The internal name of the object we want.
773 * @param bool $findpath initialize path and visiblepath arrays
774 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
775 * defaults to false
777 public function locate($name, $findpath=false) {
778 if ($this->name == $name) {
779 if ($findpath) {
780 $this->visiblepath[] = $this->visiblename;
781 $this->path[] = $this->name;
783 return $this;
786 $return = NULL;
787 foreach($this->children as $childid=>$unused) {
788 if ($return = $this->children[$childid]->locate($name, $findpath)) {
789 break;
793 if (!is_null($return) and $findpath) {
794 $return->visiblepath[] = $this->visiblename;
795 $return->path[] = $this->name;
798 return $return;
802 * Search using query
804 * @param string query
805 * @return mixed array-object structure of found settings and pages
807 public function search($query) {
808 $result = array();
809 foreach ($this->children as $child) {
810 $subsearch = $child->search($query);
811 if (!is_array($subsearch)) {
812 debugging('Incorrect search result from '.$child->name);
813 continue;
815 $result = array_merge($result, $subsearch);
817 return $result;
821 * Removes part_of_admin_tree object with internal name $name.
823 * @param string $name The internal name of the object we want to remove.
824 * @return bool success
826 public function prune($name) {
828 if ($this->name == $name) {
829 return false; //can not remove itself
832 foreach($this->children as $precedence => $child) {
833 if ($child->name == $name) {
834 // found it!
835 unset($this->children[$precedence]);
836 return true;
838 if ($this->children[$precedence]->prune($name)) {
839 return true;
842 return false;
846 * Adds a part_of_admin_tree to a child or grandchild (or great-grandchild, and so forth) of this object.
848 * @param string $destinationame The internal name of the immediate parent that we want for $something.
849 * @param mixed $something A part_of_admin_tree or setting instance to be added.
850 * @return bool True if successfully added, false if $something can not be added.
852 public function add($parentname, $something) {
853 $parent = $this->locate($parentname);
854 if (is_null($parent)) {
855 debugging('parent does not exist!');
856 return false;
859 if ($something instanceof part_of_admin_tree) {
860 if (!($parent instanceof parentable_part_of_admin_tree)) {
861 debugging('error - parts of tree can be inserted only into parentable parts');
862 return false;
864 $parent->children[] = $something;
865 return true;
867 } else {
868 debugging('error - can not add this element');
869 return false;
875 * Checks if the user has access to anything in this category.
877 * @return bool True if the user has access to at least one child in this category, false otherwise.
879 public function check_access() {
880 foreach ($this->children as $child) {
881 if ($child->check_access()) {
882 return true;
885 return false;
889 * Is this category hidden in admin tree block?
891 * @return bool True if hidden
893 public function is_hidden() {
894 return $this->hidden;
898 * Show we display Save button at the page bottom?
899 * @return bool
901 public function show_save() {
902 foreach ($this->children as $child) {
903 if ($child->show_save()) {
904 return true;
907 return false;
912 * Root of admin settings tree, does not have any parent.
914 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
916 class admin_root extends admin_category {
917 /** @var array List of errors */
918 public $errors;
919 /** @var string search query */
920 public $search;
921 /** @var bool full tree flag - true means all settings required, false only pages required */
922 public $fulltree;
923 /** @var bool flag indicating loaded tree */
924 public $loaded;
925 /** @var mixed site custom defaults overriding defaults in settings files*/
926 public $custom_defaults;
929 * @param bool $fulltree true means all settings required,
930 * false only pages required
932 public function __construct($fulltree) {
933 global $CFG;
935 parent::__construct('root', get_string('administration'), false);
936 $this->errors = array();
937 $this->search = '';
938 $this->fulltree = $fulltree;
939 $this->loaded = false;
941 // load custom defaults if found
942 $this->custom_defaults = null;
943 $defaultsfile = "$CFG->dirroot/local/defaults.php";
944 if (is_readable($defaultsfile)) {
945 $defaults = array();
946 include($defaultsfile);
947 if (is_array($defaults) and count($defaults)) {
948 $this->custom_defaults = $defaults;
954 * Empties children array, and sets loaded to false
956 * @param bool $requirefulltree
958 public function purge_children($requirefulltree) {
959 $this->children = array();
960 $this->fulltree = ($requirefulltree || $this->fulltree);
961 $this->loaded = false;
966 * Links external PHP pages into the admin tree.
968 * See detailed usage example at the top of this document (adminlib.php)
970 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
972 class admin_externalpage implements part_of_admin_tree {
974 /** @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects */
975 public $name;
977 /** @var string The displayed name for this external page. Usually obtained through get_string(). */
978 public $visiblename;
980 /** @var string The external URL that we should link to when someone requests this external page. */
981 public $url;
983 /** @var string The role capability/permission a user must have to access this external page. */
984 public $req_capability;
986 /** @var object The context in which capability/permission should be checked, default is site context. */
987 public $context;
989 /** @var bool hidden in admin tree block. */
990 public $hidden;
992 /** @var mixed either string or array of string */
993 public $path;
994 public $visiblepath;
997 * Constructor for adding an external page into the admin tree.
999 * @param string $name The internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects.
1000 * @param string $visiblename The displayed name for this external page. Usually obtained through get_string().
1001 * @param string $url The external URL that we should link to when someone requests this external page.
1002 * @param mixed $req_capability The role capability/permission a user must have to access this external page. Defaults to 'moodle/site:config'.
1003 * @param boolean $hidden Is this external page hidden in admin tree block? Default false.
1004 * @param stdClass $context The context the page relates to. Not sure what happens
1005 * if you specify something other than system or front page. Defaults to system.
1007 public function __construct($name, $visiblename, $url, $req_capability='moodle/site:config', $hidden=false, $context=NULL) {
1008 $this->name = $name;
1009 $this->visiblename = $visiblename;
1010 $this->url = $url;
1011 if (is_array($req_capability)) {
1012 $this->req_capability = $req_capability;
1013 } else {
1014 $this->req_capability = array($req_capability);
1016 $this->hidden = $hidden;
1017 $this->context = $context;
1021 * Returns a reference to the part_of_admin_tree object with internal name $name.
1023 * @param string $name The internal name of the object we want.
1024 * @param bool $findpath defaults to false
1025 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
1027 public function locate($name, $findpath=false) {
1028 if ($this->name == $name) {
1029 if ($findpath) {
1030 $this->visiblepath = array($this->visiblename);
1031 $this->path = array($this->name);
1033 return $this;
1034 } else {
1035 $return = NULL;
1036 return $return;
1041 * This function always returns false, required function by interface
1043 * @param string $name
1044 * @return false
1046 public function prune($name) {
1047 return false;
1051 * Search using query
1053 * @param string $query
1054 * @return mixed array-object structure of found settings and pages
1056 public function search($query) {
1057 $textlib = textlib_get_instance();
1059 $found = false;
1060 if (strpos(strtolower($this->name), $query) !== false) {
1061 $found = true;
1062 } else if (strpos($textlib->strtolower($this->visiblename), $query) !== false) {
1063 $found = true;
1065 if ($found) {
1066 $result = new stdClass();
1067 $result->page = $this;
1068 $result->settings = array();
1069 return array($this->name => $result);
1070 } else {
1071 return array();
1076 * Determines if the current user has access to this external page based on $this->req_capability.
1078 * @return bool True if user has access, false otherwise.
1080 public function check_access() {
1081 global $CFG;
1082 $context = empty($this->context) ? get_context_instance(CONTEXT_SYSTEM) : $this->context;
1083 foreach($this->req_capability as $cap) {
1084 if (has_capability($cap, $context)) {
1085 return true;
1088 return false;
1092 * Is this external page hidden in admin tree block?
1094 * @return bool True if hidden
1096 public function is_hidden() {
1097 return $this->hidden;
1101 * Show we display Save button at the page bottom?
1102 * @return bool
1104 public function show_save() {
1105 return false;
1110 * Used to group a number of admin_setting objects into a page and add them to the admin tree.
1112 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1114 class admin_settingpage implements part_of_admin_tree {
1116 /** @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects */
1117 public $name;
1119 /** @var string The displayed name for this external page. Usually obtained through get_string(). */
1120 public $visiblename;
1122 /** @var mixed An array of admin_setting objects that are part of this setting page. */
1123 public $settings;
1125 /** @var string The role capability/permission a user must have to access this external page. */
1126 public $req_capability;
1128 /** @var object The context in which capability/permission should be checked, default is site context. */
1129 public $context;
1131 /** @var bool hidden in admin tree block. */
1132 public $hidden;
1134 /** @var mixed string of paths or array of strings of paths */
1135 public $path;
1136 public $visiblepath;
1139 * see admin_settingpage for details of this function
1141 * @param string $name The internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects.
1142 * @param string $visiblename The displayed name for this external page. Usually obtained through get_string().
1143 * @param mixed $req_capability The role capability/permission a user must have to access this external page. Defaults to 'moodle/site:config'.
1144 * @param boolean $hidden Is this external page hidden in admin tree block? Default false.
1145 * @param stdClass $context The context the page relates to. Not sure what happens
1146 * if you specify something other than system or front page. Defaults to system.
1148 public function __construct($name, $visiblename, $req_capability='moodle/site:config', $hidden=false, $context=NULL) {
1149 $this->settings = new stdClass();
1150 $this->name = $name;
1151 $this->visiblename = $visiblename;
1152 if (is_array($req_capability)) {
1153 $this->req_capability = $req_capability;
1154 } else {
1155 $this->req_capability = array($req_capability);
1157 $this->hidden = $hidden;
1158 $this->context = $context;
1162 * see admin_category
1164 * @param string $name
1165 * @param bool $findpath
1166 * @return mixed Object (this) if name == this->name, else returns null
1168 public function locate($name, $findpath=false) {
1169 if ($this->name == $name) {
1170 if ($findpath) {
1171 $this->visiblepath = array($this->visiblename);
1172 $this->path = array($this->name);
1174 return $this;
1175 } else {
1176 $return = NULL;
1177 return $return;
1182 * Search string in settings page.
1184 * @param string $query
1185 * @return array
1187 public function search($query) {
1188 $found = array();
1190 foreach ($this->settings as $setting) {
1191 if ($setting->is_related($query)) {
1192 $found[] = $setting;
1196 if ($found) {
1197 $result = new stdClass();
1198 $result->page = $this;
1199 $result->settings = $found;
1200 return array($this->name => $result);
1203 $textlib = textlib_get_instance();
1205 $found = false;
1206 if (strpos(strtolower($this->name), $query) !== false) {
1207 $found = true;
1208 } else if (strpos($textlib->strtolower($this->visiblename), $query) !== false) {
1209 $found = true;
1211 if ($found) {
1212 $result = new stdClass();
1213 $result->page = $this;
1214 $result->settings = array();
1215 return array($this->name => $result);
1216 } else {
1217 return array();
1222 * This function always returns false, required by interface
1224 * @param string $name
1225 * @return bool Always false
1227 public function prune($name) {
1228 return false;
1232 * adds an admin_setting to this admin_settingpage
1234 * 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
1235 * n.b. each admin_setting in an admin_settingpage must have a unique internal name
1237 * @param object $setting is the admin_setting object you want to add
1238 * @return bool true if successful, false if not
1240 public function add($setting) {
1241 if (!($setting instanceof admin_setting)) {
1242 debugging('error - not a setting instance');
1243 return false;
1246 $this->settings->{$setting->name} = $setting;
1247 return true;
1251 * see admin_externalpage
1253 * @return bool Returns true for yes false for no
1255 public function check_access() {
1256 global $CFG;
1257 $context = empty($this->context) ? get_context_instance(CONTEXT_SYSTEM) : $this->context;
1258 foreach($this->req_capability as $cap) {
1259 if (has_capability($cap, $context)) {
1260 return true;
1263 return false;
1267 * outputs this page as html in a table (suitable for inclusion in an admin pagetype)
1268 * @return string Returns an XHTML string
1270 public function output_html() {
1271 $adminroot = admin_get_root();
1272 $return = '<fieldset>'."\n".'<div class="clearer"><!-- --></div>'."\n";
1273 foreach($this->settings as $setting) {
1274 $fullname = $setting->get_full_name();
1275 if (array_key_exists($fullname, $adminroot->errors)) {
1276 $data = $adminroot->errors[$fullname]->data;
1277 } else {
1278 $data = $setting->get_setting();
1279 // do not use defaults if settings not available - upgrade settings handles the defaults!
1281 $return .= $setting->output_html($data);
1283 $return .= '</fieldset>';
1284 return $return;
1288 * Is this settings page hidden in admin tree block?
1290 * @return bool True if hidden
1292 public function is_hidden() {
1293 return $this->hidden;
1297 * Show we display Save button at the page bottom?
1298 * @return bool
1300 public function show_save() {
1301 foreach($this->settings as $setting) {
1302 if (empty($setting->nosave)) {
1303 return true;
1306 return false;
1312 * Admin settings class. Only exists on setting pages.
1313 * Read & write happens at this level; no authentication.
1315 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1317 abstract class admin_setting {
1318 /** @var string unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins. */
1319 public $name;
1320 /** @var string localised name */
1321 public $visiblename;
1322 /** @var string localised long description in Markdown format */
1323 public $description;
1324 /** @var mixed Can be string or array of string */
1325 public $defaultsetting;
1326 /** @var string */
1327 public $updatedcallback;
1328 /** @var mixed can be String or Null. Null means main config table */
1329 public $plugin; // null means main config table
1330 /** @var bool true indicates this setting does not actually save anything, just information */
1331 public $nosave = false;
1334 * Constructor
1335 * @param string $name unique ascii name, either 'mysetting' for settings that in config,
1336 * or 'myplugin/mysetting' for ones in config_plugins.
1337 * @param string $visiblename localised name
1338 * @param string $description localised long description
1339 * @param mixed $defaultsetting string or array depending on implementation
1341 public function __construct($name, $visiblename, $description, $defaultsetting) {
1342 $this->parse_setting_name($name);
1343 $this->visiblename = $visiblename;
1344 $this->description = $description;
1345 $this->defaultsetting = $defaultsetting;
1349 * Set up $this->name and potentially $this->plugin
1351 * Set up $this->name and possibly $this->plugin based on whether $name looks
1352 * like 'settingname' or 'plugin/settingname'. Also, do some sanity checking
1353 * on the names, that is, output a developer debug warning if the name
1354 * contains anything other than [a-zA-Z0-9_]+.
1356 * @param string $name the setting name passed in to the constructor.
1358 private function parse_setting_name($name) {
1359 $bits = explode('/', $name);
1360 if (count($bits) > 2) {
1361 throw new moodle_exception('invalidadminsettingname', '', '', $name);
1363 $this->name = array_pop($bits);
1364 if (!preg_match('/^[a-zA-Z0-9_]+$/', $this->name)) {
1365 throw new moodle_exception('invalidadminsettingname', '', '', $name);
1367 if (!empty($bits)) {
1368 $this->plugin = array_pop($bits);
1369 if ($this->plugin === 'moodle') {
1370 $this->plugin = null;
1371 } else if (!preg_match('/^[a-zA-Z0-9_]+$/', $this->plugin)) {
1372 throw new moodle_exception('invalidadminsettingname', '', '', $name);
1378 * Returns the fullname prefixed by the plugin
1379 * @return string
1381 public function get_full_name() {
1382 return 's_'.$this->plugin.'_'.$this->name;
1386 * Returns the ID string based on plugin and name
1387 * @return string
1389 public function get_id() {
1390 return 'id_s_'.$this->plugin.'_'.$this->name;
1394 * Returns the config if possible
1396 * @return mixed returns config if successfull else null
1398 public function config_read($name) {
1399 global $CFG;
1400 if (!empty($this->plugin)) {
1401 $value = get_config($this->plugin, $name);
1402 return $value === false ? NULL : $value;
1404 } else {
1405 if (isset($CFG->$name)) {
1406 return $CFG->$name;
1407 } else {
1408 return NULL;
1414 * Used to set a config pair and log change
1416 * @param string $name
1417 * @param mixed $value Gets converted to string if not null
1418 * @return bool Write setting to config table
1420 public function config_write($name, $value) {
1421 global $DB, $USER, $CFG;
1423 if ($this->nosave) {
1424 return true;
1427 // make sure it is a real change
1428 $oldvalue = get_config($this->plugin, $name);
1429 $oldvalue = ($oldvalue === false) ? null : $oldvalue; // normalise
1430 $value = is_null($value) ? null : (string)$value;
1432 if ($oldvalue === $value) {
1433 return true;
1436 // store change
1437 set_config($name, $value, $this->plugin);
1439 // log change
1440 $log = new stdClass();
1441 $log->userid = during_initial_install() ? 0 :$USER->id; // 0 as user id during install
1442 $log->timemodified = time();
1443 $log->plugin = $this->plugin;
1444 $log->name = $name;
1445 $log->value = $value;
1446 $log->oldvalue = $oldvalue;
1447 $DB->insert_record('config_log', $log);
1449 return true; // BC only
1453 * Returns current value of this setting
1454 * @return mixed array or string depending on instance, NULL means not set yet
1456 public abstract function get_setting();
1459 * Returns default setting if exists
1460 * @return mixed array or string depending on instance; NULL means no default, user must supply
1462 public function get_defaultsetting() {
1463 $adminroot = admin_get_root(false, false);
1464 if (!empty($adminroot->custom_defaults)) {
1465 $plugin = is_null($this->plugin) ? 'moodle' : $this->plugin;
1466 if (isset($adminroot->custom_defaults[$plugin])) {
1467 if (array_key_exists($this->name, $adminroot->custom_defaults[$plugin])) { // null is valid value here ;-)
1468 return $adminroot->custom_defaults[$plugin][$this->name];
1472 return $this->defaultsetting;
1476 * Store new setting
1478 * @param mixed $data string or array, must not be NULL
1479 * @return string empty string if ok, string error message otherwise
1481 public abstract function write_setting($data);
1484 * Return part of form with setting
1485 * This function should always be overwritten
1487 * @param mixed $data array or string depending on setting
1488 * @param string $query
1489 * @return string
1491 public function output_html($data, $query='') {
1492 // should be overridden
1493 return;
1497 * Function called if setting updated - cleanup, cache reset, etc.
1498 * @param string $functionname Sets the function name
1500 public function set_updatedcallback($functionname) {
1501 $this->updatedcallback = $functionname;
1505 * Is setting related to query text - used when searching
1506 * @param string $query
1507 * @return bool
1509 public function is_related($query) {
1510 if (strpos(strtolower($this->name), $query) !== false) {
1511 return true;
1513 $textlib = textlib_get_instance();
1514 if (strpos($textlib->strtolower($this->visiblename), $query) !== false) {
1515 return true;
1517 if (strpos($textlib->strtolower($this->description), $query) !== false) {
1518 return true;
1520 $current = $this->get_setting();
1521 if (!is_null($current)) {
1522 if (is_string($current)) {
1523 if (strpos($textlib->strtolower($current), $query) !== false) {
1524 return true;
1528 $default = $this->get_defaultsetting();
1529 if (!is_null($default)) {
1530 if (is_string($default)) {
1531 if (strpos($textlib->strtolower($default), $query) !== false) {
1532 return true;
1536 return false;
1541 * No setting - just heading and text.
1543 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1545 class admin_setting_heading extends admin_setting {
1547 * not a setting, just text
1548 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
1549 * @param string $heading heading
1550 * @param string $information text in box
1552 public function __construct($name, $heading, $information) {
1553 $this->nosave = true;
1554 parent::__construct($name, $heading, $information, '');
1558 * Always returns true
1559 * @return bool Always returns true
1561 public function get_setting() {
1562 return true;
1566 * Always returns true
1567 * @return bool Always returns true
1569 public function get_defaultsetting() {
1570 return true;
1574 * Never write settings
1575 * @return string Always returns an empty string
1577 public function write_setting($data) {
1578 // do not write any setting
1579 return '';
1583 * Returns an HTML string
1584 * @return string Returns an HTML string
1586 public function output_html($data, $query='') {
1587 global $OUTPUT;
1588 $return = '';
1589 if ($this->visiblename != '') {
1590 $return .= $OUTPUT->heading($this->visiblename, 3, 'main');
1592 if ($this->description != '') {
1593 $return .= $OUTPUT->box(highlight($query, markdown_to_html($this->description)), 'generalbox formsettingheading');
1595 return $return;
1600 * The most flexibly setting, user is typing text
1602 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1604 class admin_setting_configtext extends admin_setting {
1606 /** @var mixed int means PARAM_XXX type, string is a allowed format in regex */
1607 public $paramtype;
1608 /** @var int default field size */
1609 public $size;
1612 * Config text constructor
1614 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
1615 * @param string $visiblename localised
1616 * @param string $description long localised info
1617 * @param string $defaultsetting
1618 * @param mixed $paramtype int means PARAM_XXX type, string is a allowed format in regex
1619 * @param int $size default field size
1621 public function __construct($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW, $size=null) {
1622 $this->paramtype = $paramtype;
1623 if (!is_null($size)) {
1624 $this->size = $size;
1625 } else {
1626 $this->size = ($paramtype === PARAM_INT) ? 5 : 30;
1628 parent::__construct($name, $visiblename, $description, $defaultsetting);
1632 * Return the setting
1634 * @return mixed returns config if successful else null
1636 public function get_setting() {
1637 return $this->config_read($this->name);
1640 public function write_setting($data) {
1641 if ($this->paramtype === PARAM_INT and $data === '') {
1642 // do not complain if '' used instead of 0
1643 $data = 0;
1645 // $data is a string
1646 $validated = $this->validate($data);
1647 if ($validated !== true) {
1648 return $validated;
1650 return ($this->config_write($this->name, $data) ? '' : get_string('errorsetting', 'admin'));
1654 * Validate data before storage
1655 * @param string data
1656 * @return mixed true if ok string if error found
1658 public function validate($data) {
1659 // allow paramtype to be a custom regex if it is the form of /pattern/
1660 if (preg_match('#^/.*/$#', $this->paramtype)) {
1661 if (preg_match($this->paramtype, $data)) {
1662 return true;
1663 } else {
1664 return get_string('validateerror', 'admin');
1667 } else if ($this->paramtype === PARAM_RAW) {
1668 return true;
1670 } else {
1671 $cleaned = clean_param($data, $this->paramtype);
1672 if ("$data" === "$cleaned") { // implicit conversion to string is needed to do exact comparison
1673 return true;
1674 } else {
1675 return get_string('validateerror', 'admin');
1681 * Return an XHTML string for the setting
1682 * @return string Returns an XHTML string
1684 public function output_html($data, $query='') {
1685 $default = $this->get_defaultsetting();
1687 return format_admin_setting($this, $this->visiblename,
1688 '<div class="form-text defaultsnext"><input type="text" size="'.$this->size.'" id="'.$this->get_id().'" name="'.$this->get_full_name().'" value="'.s($data).'" /></div>',
1689 $this->description, true, '', $default, $query);
1694 * General text area without html editor.
1696 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1698 class admin_setting_configtextarea extends admin_setting_configtext {
1699 private $rows;
1700 private $cols;
1703 * @param string $name
1704 * @param string $visiblename
1705 * @param string $description
1706 * @param mixed $defaultsetting string or array
1707 * @param mixed $paramtype
1708 * @param string $cols The number of columns to make the editor
1709 * @param string $rows The number of rows to make the editor
1711 public function __construct($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW, $cols='60', $rows='8') {
1712 $this->rows = $rows;
1713 $this->cols = $cols;
1714 parent::__construct($name, $visiblename, $description, $defaultsetting, $paramtype);
1717 * Returns an XHTML string for the editor
1719 * @param string $data
1720 * @param string $query
1721 * @return string XHTML string for the editor
1723 public function output_html($data, $query='') {
1724 $default = $this->get_defaultsetting();
1726 $defaultinfo = $default;
1727 if (!is_null($default) and $default !== '') {
1728 $defaultinfo = "\n".$default;
1731 return format_admin_setting($this, $this->visiblename,
1732 '<div class="form-textarea" ><textarea rows="'. $this->rows .'" cols="'. $this->cols .'" id="'. $this->get_id() .'" name="'. $this->get_full_name() .'">'. s($data) .'</textarea></div>',
1733 $this->description, true, '', $defaultinfo, $query);
1738 * General text area with html editor.
1740 class admin_setting_confightmleditor extends admin_setting_configtext {
1741 private $rows;
1742 private $cols;
1745 * @param string $name
1746 * @param string $visiblename
1747 * @param string $description
1748 * @param mixed $defaultsetting string or array
1749 * @param mixed $paramtype
1751 public function __construct($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW, $cols='60', $rows='8') {
1752 $this->rows = $rows;
1753 $this->cols = $cols;
1754 parent::__construct($name, $visiblename, $description, $defaultsetting, $paramtype);
1755 editors_head_setup();
1758 * Returns an XHTML string for the editor
1760 * @param string $data
1761 * @param string $query
1762 * @return string XHTML string for the editor
1764 public function output_html($data, $query='') {
1765 $default = $this->get_defaultsetting();
1767 $defaultinfo = $default;
1768 if (!is_null($default) and $default !== '') {
1769 $defaultinfo = "\n".$default;
1772 $editor = editors_get_preferred_editor(FORMAT_HTML);
1773 $editor->use_editor($this->get_id(), array('noclean'=>true));
1775 return format_admin_setting($this, $this->visiblename,
1776 '<div class="form-textarea"><textarea rows="'. $this->rows .'" cols="'. $this->cols .'" id="'. $this->get_id() .'" name="'. $this->get_full_name() .'">'. s($data) .'</textarea></div>',
1777 $this->description, true, '', $defaultinfo, $query);
1782 * Password field, allows unmasking of password
1784 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1786 class admin_setting_configpasswordunmask extends admin_setting_configtext {
1788 * Constructor
1789 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
1790 * @param string $visiblename localised
1791 * @param string $description long localised info
1792 * @param string $defaultsetting default password
1794 public function __construct($name, $visiblename, $description, $defaultsetting) {
1795 parent::__construct($name, $visiblename, $description, $defaultsetting, PARAM_RAW, 30);
1799 * Returns XHTML for the field
1800 * Writes Javascript into the HTML below right before the last div
1802 * @todo Make javascript available through newer methods if possible
1803 * @param string $data Value for the field
1804 * @param string $query Passed as final argument for format_admin_setting
1805 * @return string XHTML field
1807 public function output_html($data, $query='') {
1808 $id = $this->get_id();
1809 $unmask = get_string('unmaskpassword', 'form');
1810 $unmaskjs = '<script type="text/javascript">
1811 //<![CDATA[
1812 var is_ie = (navigator.userAgent.toLowerCase().indexOf("msie") != -1);
1814 document.getElementById("'.$id.'").setAttribute("autocomplete", "off");
1816 var unmaskdiv = document.getElementById("'.$id.'unmaskdiv");
1818 var unmaskchb = document.createElement("input");
1819 unmaskchb.setAttribute("type", "checkbox");
1820 unmaskchb.setAttribute("id", "'.$id.'unmask");
1821 unmaskchb.onchange = function() {unmaskPassword("'.$id.'");};
1822 unmaskdiv.appendChild(unmaskchb);
1824 var unmasklbl = document.createElement("label");
1825 unmasklbl.innerHTML = "'.addslashes_js($unmask).'";
1826 if (is_ie) {
1827 unmasklbl.setAttribute("htmlFor", "'.$id.'unmask");
1828 } else {
1829 unmasklbl.setAttribute("for", "'.$id.'unmask");
1831 unmaskdiv.appendChild(unmasklbl);
1833 if (is_ie) {
1834 // ugly hack to work around the famous onchange IE bug
1835 unmaskchb.onclick = function() {this.blur();};
1836 unmaskdiv.onclick = function() {this.blur();};
1838 //]]>
1839 </script>';
1840 return format_admin_setting($this, $this->visiblename,
1841 '<div class="form-password"><input type="password" size="'.$this->size.'" id="'.$id.'" name="'.$this->get_full_name().'" value="'.s($data).'" /><div class="unmask" id="'.$id.'unmaskdiv"></div>'.$unmaskjs.'</div>',
1842 $this->description, true, '', NULL, $query);
1847 * Path to directory
1849 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1851 class admin_setting_configfile extends admin_setting_configtext {
1853 * Constructor
1854 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
1855 * @param string $visiblename localised
1856 * @param string $description long localised info
1857 * @param string $defaultdirectory default directory location
1859 public function __construct($name, $visiblename, $description, $defaultdirectory) {
1860 parent::__construct($name, $visiblename, $description, $defaultdirectory, PARAM_RAW, 50);
1864 * Returns XHTML for the field
1866 * Returns XHTML for the field and also checks whether the file
1867 * specified in $data exists using file_exists()
1869 * @param string $data File name and path to use in value attr
1870 * @param string $query
1871 * @return string XHTML field
1873 public function output_html($data, $query='') {
1874 $default = $this->get_defaultsetting();
1876 if ($data) {
1877 if (file_exists($data)) {
1878 $executable = '<span class="pathok">&#x2714;</span>';
1879 } else {
1880 $executable = '<span class="patherror">&#x2718;</span>';
1882 } else {
1883 $executable = '';
1886 return format_admin_setting($this, $this->visiblename,
1887 '<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>',
1888 $this->description, true, '', $default, $query);
1893 * Path to executable file
1895 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1897 class admin_setting_configexecutable extends admin_setting_configfile {
1900 * Returns an XHTML field
1902 * @param string $data This is the value for the field
1903 * @param string $query
1904 * @return string XHTML field
1906 public function output_html($data, $query='') {
1907 $default = $this->get_defaultsetting();
1909 if ($data) {
1910 if (file_exists($data) and is_executable($data)) {
1911 $executable = '<span class="pathok">&#x2714;</span>';
1912 } else {
1913 $executable = '<span class="patherror">&#x2718;</span>';
1915 } else {
1916 $executable = '';
1919 return format_admin_setting($this, $this->visiblename,
1920 '<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>',
1921 $this->description, true, '', $default, $query);
1926 * Path to directory
1928 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1930 class admin_setting_configdirectory extends admin_setting_configfile {
1933 * Returns an XHTML field
1935 * @param string $data This is the value for the field
1936 * @param string $query
1937 * @return string XHTML
1939 public function output_html($data, $query='') {
1940 $default = $this->get_defaultsetting();
1942 if ($data) {
1943 if (file_exists($data) and is_dir($data)) {
1944 $executable = '<span class="pathok">&#x2714;</span>';
1945 } else {
1946 $executable = '<span class="patherror">&#x2718;</span>';
1948 } else {
1949 $executable = '';
1952 return format_admin_setting($this, $this->visiblename,
1953 '<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>',
1954 $this->description, true, '', $default, $query);
1959 * Checkbox
1961 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1963 class admin_setting_configcheckbox extends admin_setting {
1964 /** @var string Value used when checked */
1965 public $yes;
1966 /** @var string Value used when not checked */
1967 public $no;
1970 * Constructor
1971 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
1972 * @param string $visiblename localised
1973 * @param string $description long localised info
1974 * @param string $defaultsetting
1975 * @param string $yes value used when checked
1976 * @param string $no value used when not checked
1978 public function __construct($name, $visiblename, $description, $defaultsetting, $yes='1', $no='0') {
1979 parent::__construct($name, $visiblename, $description, $defaultsetting);
1980 $this->yes = (string)$yes;
1981 $this->no = (string)$no;
1985 * Retrieves the current setting using the objects name
1987 * @return string
1989 public function get_setting() {
1990 return $this->config_read($this->name);
1994 * Sets the value for the setting
1996 * Sets the value for the setting to either the yes or no values
1997 * of the object by comparing $data to yes
1999 * @param mixed $data Gets converted to str for comparison against yes value
2000 * @return string empty string or error
2002 public function write_setting($data) {
2003 if ((string)$data === $this->yes) { // convert to strings before comparison
2004 $data = $this->yes;
2005 } else {
2006 $data = $this->no;
2008 return ($this->config_write($this->name, $data) ? '' : get_string('errorsetting', 'admin'));
2012 * Returns an XHTML checkbox field
2014 * @param string $data If $data matches yes then checkbox is checked
2015 * @param string $query
2016 * @return string XHTML field
2018 public function output_html($data, $query='') {
2019 $default = $this->get_defaultsetting();
2021 if (!is_null($default)) {
2022 if ((string)$default === $this->yes) {
2023 $defaultinfo = get_string('checkboxyes', 'admin');
2024 } else {
2025 $defaultinfo = get_string('checkboxno', 'admin');
2027 } else {
2028 $defaultinfo = NULL;
2031 if ((string)$data === $this->yes) { // convert to strings before comparison
2032 $checked = 'checked="checked"';
2033 } else {
2034 $checked = '';
2037 return format_admin_setting($this, $this->visiblename,
2038 '<div class="form-checkbox defaultsnext" ><input type="hidden" name="'.$this->get_full_name().'" value="'.s($this->no).'" /> '
2039 .'<input type="checkbox" id="'.$this->get_id().'" name="'.$this->get_full_name().'" value="'.s($this->yes).'" '.$checked.' /></div>',
2040 $this->description, true, '', $defaultinfo, $query);
2045 * Multiple checkboxes, each represents different value, stored in csv format
2047 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2049 class admin_setting_configmulticheckbox extends admin_setting {
2050 /** @var array Array of choices value=>label */
2051 public $choices;
2054 * Constructor: uses parent::__construct
2056 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2057 * @param string $visiblename localised
2058 * @param string $description long localised info
2059 * @param array $defaultsetting array of selected
2060 * @param array $choices array of $value=>$label for each checkbox
2062 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
2063 $this->choices = $choices;
2064 parent::__construct($name, $visiblename, $description, $defaultsetting);
2068 * This public function may be used in ancestors for lazy loading of choices
2070 * @todo Check if this function is still required content commented out only returns true
2071 * @return bool true if loaded, false if error
2073 public function load_choices() {
2075 if (is_array($this->choices)) {
2076 return true;
2078 .... load choices here
2080 return true;
2084 * Is setting related to query text - used when searching
2086 * @param string $query
2087 * @return bool true on related, false on not or failure
2089 public function is_related($query) {
2090 if (!$this->load_choices() or empty($this->choices)) {
2091 return false;
2093 if (parent::is_related($query)) {
2094 return true;
2097 $textlib = textlib_get_instance();
2098 foreach ($this->choices as $desc) {
2099 if (strpos($textlib->strtolower($desc), $query) !== false) {
2100 return true;
2103 return false;
2107 * Returns the current setting if it is set
2109 * @return mixed null if null, else an array
2111 public function get_setting() {
2112 $result = $this->config_read($this->name);
2114 if (is_null($result)) {
2115 return NULL;
2117 if ($result === '') {
2118 return array();
2120 $enabled = explode(',', $result);
2121 $setting = array();
2122 foreach ($enabled as $option) {
2123 $setting[$option] = 1;
2125 return $setting;
2129 * Saves the setting(s) provided in $data
2131 * @param array $data An array of data, if not array returns empty str
2132 * @return mixed empty string on useless data or bool true=success, false=failed
2134 public function write_setting($data) {
2135 if (!is_array($data)) {
2136 return ''; // ignore it
2138 if (!$this->load_choices() or empty($this->choices)) {
2139 return '';
2141 unset($data['xxxxx']);
2142 $result = array();
2143 foreach ($data as $key => $value) {
2144 if ($value and array_key_exists($key, $this->choices)) {
2145 $result[] = $key;
2148 return $this->config_write($this->name, implode(',', $result)) ? '' : get_string('errorsetting', 'admin');
2152 * Returns XHTML field(s) as required by choices
2154 * Relies on data being an array should data ever be another valid vartype with
2155 * acceptable value this may cause a warning/error
2156 * if (!is_array($data)) would fix the problem
2158 * @todo Add vartype handling to ensure $data is an array
2160 * @param array $data An array of checked values
2161 * @param string $query
2162 * @return string XHTML field
2164 public function output_html($data, $query='') {
2165 if (!$this->load_choices() or empty($this->choices)) {
2166 return '';
2168 $default = $this->get_defaultsetting();
2169 if (is_null($default)) {
2170 $default = array();
2172 if (is_null($data)) {
2173 $data = array();
2175 $options = array();
2176 $defaults = array();
2177 foreach ($this->choices as $key=>$description) {
2178 if (!empty($data[$key])) {
2179 $checked = 'checked="checked"';
2180 } else {
2181 $checked = '';
2183 if (!empty($default[$key])) {
2184 $defaults[] = $description;
2187 $options[] = '<input type="checkbox" id="'.$this->get_id().'_'.$key.'" name="'.$this->get_full_name().'['.$key.']" value="1" '.$checked.' />'
2188 .'<label for="'.$this->get_id().'_'.$key.'">'.highlightfast($query, $description).'</label>';
2191 if (is_null($default)) {
2192 $defaultinfo = NULL;
2193 } else if (!empty($defaults)) {
2194 $defaultinfo = implode(', ', $defaults);
2195 } else {
2196 $defaultinfo = get_string('none');
2199 $return = '<div class="form-multicheckbox">';
2200 $return .= '<input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
2201 if ($options) {
2202 $return .= '<ul>';
2203 foreach ($options as $option) {
2204 $return .= '<li>'.$option.'</li>';
2206 $return .= '</ul>';
2208 $return .= '</div>';
2210 return format_admin_setting($this, $this->visiblename, $return, $this->description, false, '', $defaultinfo, $query);
2216 * Multiple checkboxes 2, value stored as string 00101011
2218 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2220 class admin_setting_configmulticheckbox2 extends admin_setting_configmulticheckbox {
2223 * Returns the setting if set
2225 * @return mixed null if not set, else an array of set settings
2227 public function get_setting() {
2228 $result = $this->config_read($this->name);
2229 if (is_null($result)) {
2230 return NULL;
2232 if (!$this->load_choices()) {
2233 return NULL;
2235 $result = str_pad($result, count($this->choices), '0');
2236 $result = preg_split('//', $result, -1, PREG_SPLIT_NO_EMPTY);
2237 $setting = array();
2238 foreach ($this->choices as $key=>$unused) {
2239 $value = array_shift($result);
2240 if ($value) {
2241 $setting[$key] = 1;
2244 return $setting;
2248 * Save setting(s) provided in $data param
2250 * @param array $data An array of settings to save
2251 * @return mixed empty string for bad data or bool true=>success, false=>error
2253 public function write_setting($data) {
2254 if (!is_array($data)) {
2255 return ''; // ignore it
2257 if (!$this->load_choices() or empty($this->choices)) {
2258 return '';
2260 $result = '';
2261 foreach ($this->choices as $key=>$unused) {
2262 if (!empty($data[$key])) {
2263 $result .= '1';
2264 } else {
2265 $result .= '0';
2268 return $this->config_write($this->name, $result) ? '' : get_string('errorsetting', 'admin');
2273 * Select one value from list
2275 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2277 class admin_setting_configselect extends admin_setting {
2278 /** @var array Array of choices value=>label */
2279 public $choices;
2282 * Constructor
2283 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2284 * @param string $visiblename localised
2285 * @param string $description long localised info
2286 * @param string|int $defaultsetting
2287 * @param array $choices array of $value=>$label for each selection
2289 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
2290 $this->choices = $choices;
2291 parent::__construct($name, $visiblename, $description, $defaultsetting);
2295 * This function may be used in ancestors for lazy loading of choices
2297 * Override this method if loading of choices is expensive, such
2298 * as when it requires multiple db requests.
2300 * @return bool true if loaded, false if error
2302 public function load_choices() {
2304 if (is_array($this->choices)) {
2305 return true;
2307 .... load choices here
2309 return true;
2313 * Check if this is $query is related to a choice
2315 * @param string $query
2316 * @return bool true if related, false if not
2318 public function is_related($query) {
2319 if (parent::is_related($query)) {
2320 return true;
2322 if (!$this->load_choices()) {
2323 return false;
2325 $textlib = textlib_get_instance();
2326 foreach ($this->choices as $key=>$value) {
2327 if (strpos($textlib->strtolower($key), $query) !== false) {
2328 return true;
2330 if (strpos($textlib->strtolower($value), $query) !== false) {
2331 return true;
2334 return false;
2338 * Return the setting
2340 * @return mixed returns config if successful else null
2342 public function get_setting() {
2343 return $this->config_read($this->name);
2347 * Save a setting
2349 * @param string $data
2350 * @return string empty of error string
2352 public function write_setting($data) {
2353 if (!$this->load_choices() or empty($this->choices)) {
2354 return '';
2356 if (!array_key_exists($data, $this->choices)) {
2357 return ''; // ignore it
2360 return ($this->config_write($this->name, $data) ? '' : get_string('errorsetting', 'admin'));
2364 * Returns XHTML select field
2366 * Ensure the options are loaded, and generate the XHTML for the select
2367 * element and any warning message. Separating this out from output_html
2368 * makes it easier to subclass this class.
2370 * @param string $data the option to show as selected.
2371 * @param string $current the currently selected option in the database, null if none.
2372 * @param string $default the default selected option.
2373 * @return array the HTML for the select element, and a warning message.
2375 public function output_select_html($data, $current, $default, $extraname = '') {
2376 if (!$this->load_choices() or empty($this->choices)) {
2377 return array('', '');
2380 $warning = '';
2381 if (is_null($current)) {
2382 // first run
2383 } else if (empty($current) and (array_key_exists('', $this->choices) or array_key_exists(0, $this->choices))) {
2384 // no warning
2385 } else if (!array_key_exists($current, $this->choices)) {
2386 $warning = get_string('warningcurrentsetting', 'admin', s($current));
2387 if (!is_null($default) and $data == $current) {
2388 $data = $default; // use default instead of first value when showing the form
2392 $selecthtml = '<select id="'.$this->get_id().'" name="'.$this->get_full_name().$extraname.'">';
2393 foreach ($this->choices as $key => $value) {
2394 // the string cast is needed because key may be integer - 0 is equal to most strings!
2395 $selecthtml .= '<option value="'.$key.'"'.((string)$key==$data ? ' selected="selected"' : '').'>'.$value.'</option>';
2397 $selecthtml .= '</select>';
2398 return array($selecthtml, $warning);
2402 * Returns XHTML select field and wrapping div(s)
2404 * @see output_select_html()
2406 * @param string $data the option to show as selected
2407 * @param string $query
2408 * @return string XHTML field and wrapping div
2410 public function output_html($data, $query='') {
2411 $default = $this->get_defaultsetting();
2412 $current = $this->get_setting();
2414 list($selecthtml, $warning) = $this->output_select_html($data, $current, $default);
2415 if (!$selecthtml) {
2416 return '';
2419 if (!is_null($default) and array_key_exists($default, $this->choices)) {
2420 $defaultinfo = $this->choices[$default];
2421 } else {
2422 $defaultinfo = NULL;
2425 $return = '<div class="form-select defaultsnext">' . $selecthtml . '</div>';
2427 return format_admin_setting($this, $this->visiblename, $return, $this->description, true, $warning, $defaultinfo, $query);
2432 * Select multiple items from list
2434 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2436 class admin_setting_configmultiselect extends admin_setting_configselect {
2438 * Constructor
2439 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2440 * @param string $visiblename localised
2441 * @param string $description long localised info
2442 * @param array $defaultsetting array of selected items
2443 * @param array $choices array of $value=>$label for each list item
2445 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
2446 parent::__construct($name, $visiblename, $description, $defaultsetting, $choices);
2450 * Returns the select setting(s)
2452 * @return mixed null or array. Null if no settings else array of setting(s)
2454 public function get_setting() {
2455 $result = $this->config_read($this->name);
2456 if (is_null($result)) {
2457 return NULL;
2459 if ($result === '') {
2460 return array();
2462 return explode(',', $result);
2466 * Saves setting(s) provided through $data
2468 * Potential bug in the works should anyone call with this function
2469 * using a vartype that is not an array
2471 * @todo Add vartype handling to ensure $data is an array
2472 * @param array $data
2474 public function write_setting($data) {
2475 if (!is_array($data)) {
2476 return ''; //ignore it
2478 if (!$this->load_choices() or empty($this->choices)) {
2479 return '';
2482 unset($data['xxxxx']);
2484 $save = array();
2485 foreach ($data as $value) {
2486 if (!array_key_exists($value, $this->choices)) {
2487 continue; // ignore it
2489 $save[] = $value;
2492 return ($this->config_write($this->name, implode(',', $save)) ? '' : get_string('errorsetting', 'admin'));
2496 * Is setting related to query text - used when searching
2498 * @param string $query
2499 * @return bool true if related, false if not
2501 public function is_related($query) {
2502 if (!$this->load_choices() or empty($this->choices)) {
2503 return false;
2505 if (parent::is_related($query)) {
2506 return true;
2509 $textlib = textlib_get_instance();
2510 foreach ($this->choices as $desc) {
2511 if (strpos($textlib->strtolower($desc), $query) !== false) {
2512 return true;
2515 return false;
2519 * Returns XHTML multi-select field
2521 * @todo Add vartype handling to ensure $data is an array
2522 * @param array $data Array of values to select by default
2523 * @param string $query
2524 * @return string XHTML multi-select field
2526 public function output_html($data, $query='') {
2527 if (!$this->load_choices() or empty($this->choices)) {
2528 return '';
2530 $choices = $this->choices;
2531 $default = $this->get_defaultsetting();
2532 if (is_null($default)) {
2533 $default = array();
2535 if (is_null($data)) {
2536 $data = array();
2539 $defaults = array();
2540 $size = min(10, count($this->choices));
2541 $return = '<div class="form-select"><input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
2542 $return .= '<select id="'.$this->get_id().'" name="'.$this->get_full_name().'[]" size="'.$size.'" multiple="multiple">';
2543 foreach ($this->choices as $key => $description) {
2544 if (in_array($key, $data)) {
2545 $selected = 'selected="selected"';
2546 } else {
2547 $selected = '';
2549 if (in_array($key, $default)) {
2550 $defaults[] = $description;
2553 $return .= '<option value="'.s($key).'" '.$selected.'>'.$description.'</option>';
2556 if (is_null($default)) {
2557 $defaultinfo = NULL;
2558 } if (!empty($defaults)) {
2559 $defaultinfo = implode(', ', $defaults);
2560 } else {
2561 $defaultinfo = get_string('none');
2564 $return .= '</select></div>';
2565 return format_admin_setting($this, $this->visiblename, $return, $this->description, true, '', $defaultinfo, $query);
2570 * Time selector
2572 * This is a liiitle bit messy. we're using two selects, but we're returning
2573 * them as an array named after $name (so we only use $name2 internally for the setting)
2575 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2577 class admin_setting_configtime extends admin_setting {
2578 /** @var string Used for setting second select (minutes) */
2579 public $name2;
2582 * Constructor
2583 * @param string $hoursname setting for hours
2584 * @param string $minutesname setting for hours
2585 * @param string $visiblename localised
2586 * @param string $description long localised info
2587 * @param array $defaultsetting array representing default time 'h'=>hours, 'm'=>minutes
2589 public function __construct($hoursname, $minutesname, $visiblename, $description, $defaultsetting) {
2590 $this->name2 = $minutesname;
2591 parent::__construct($hoursname, $visiblename, $description, $defaultsetting);
2595 * Get the selected time
2597 * @return mixed An array containing 'h'=>xx, 'm'=>xx, or null if not set
2599 public function get_setting() {
2600 $result1 = $this->config_read($this->name);
2601 $result2 = $this->config_read($this->name2);
2602 if (is_null($result1) or is_null($result2)) {
2603 return NULL;
2606 return array('h' => $result1, 'm' => $result2);
2610 * Store the time (hours and minutes)
2612 * @param array $data Must be form 'h'=>xx, 'm'=>xx
2613 * @return bool true if success, false if not
2615 public function write_setting($data) {
2616 if (!is_array($data)) {
2617 return '';
2620 $result = $this->config_write($this->name, (int)$data['h']) && $this->config_write($this->name2, (int)$data['m']);
2621 return ($result ? '' : get_string('errorsetting', 'admin'));
2625 * Returns XHTML time select fields
2627 * @param array $data Must be form 'h'=>xx, 'm'=>xx
2628 * @param string $query
2629 * @return string XHTML time select fields and wrapping div(s)
2631 public function output_html($data, $query='') {
2632 $default = $this->get_defaultsetting();
2634 if (is_array($default)) {
2635 $defaultinfo = $default['h'].':'.$default['m'];
2636 } else {
2637 $defaultinfo = NULL;
2640 $return = '<div class="form-time defaultsnext">'.
2641 '<select id="'.$this->get_id().'h" name="'.$this->get_full_name().'[h]">';
2642 for ($i = 0; $i < 24; $i++) {
2643 $return .= '<option value="'.$i.'"'.($i == $data['h'] ? ' selected="selected"' : '').'>'.$i.'</option>';
2645 $return .= '</select>:<select id="'.$this->get_id().'m" name="'.$this->get_full_name().'[m]">';
2646 for ($i = 0; $i < 60; $i += 5) {
2647 $return .= '<option value="'.$i.'"'.($i == $data['m'] ? ' selected="selected"' : '').'>'.$i.'</option>';
2649 $return .= '</select></div>';
2650 return format_admin_setting($this, $this->visiblename, $return, $this->description, false, '', $defaultinfo, $query);
2656 * Used to validate a textarea used for ip addresses
2658 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2660 class admin_setting_configiplist extends admin_setting_configtextarea {
2663 * Validate the contents of the textarea as IP addresses
2665 * Used to validate a new line separated list of IP addresses collected from
2666 * a textarea control
2668 * @param string $data A list of IP Addresses separated by new lines
2669 * @return mixed bool true for success or string:error on failure
2671 public function validate($data) {
2672 if(!empty($data)) {
2673 $ips = explode("\n", $data);
2674 } else {
2675 return true;
2677 $result = true;
2678 foreach($ips as $ip) {
2679 $ip = trim($ip);
2680 if(preg_match('#^(\d{1,3})(\.\d{1,3}){0,3}$#', $ip, $match) ||
2681 preg_match('#^(\d{1,3})(\.\d{1,3}){0,3}(\/\d{1,2})$#', $ip, $match) ||
2682 preg_match('#^(\d{1,3})(\.\d{1,3}){3}(-\d{1,3})$#', $ip, $match)) {
2683 $result = true;
2684 } else {
2685 $result = false;
2686 break;
2689 if($result) {
2690 return true;
2691 } else {
2692 return get_string('validateerror', 'admin');
2698 * An admin setting for selecting one or more users who have a capability
2699 * in the system context
2701 * An admin setting for selecting one or more users, who have a particular capability
2702 * in the system context. Warning, make sure the list will never be too long. There is
2703 * no paging or searching of this list.
2705 * To correctly get a list of users from this config setting, you need to call the
2706 * get_users_from_config($CFG->mysetting, $capability); function in moodlelib.php.
2708 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2710 class admin_setting_users_with_capability extends admin_setting_configmultiselect {
2711 /** @var string The capabilities name */
2712 protected $capability;
2713 /** @var int include admin users too */
2714 protected $includeadmins;
2717 * Constructor.
2719 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2720 * @param string $visiblename localised name
2721 * @param string $description localised long description
2722 * @param array $defaultsetting array of usernames
2723 * @param string $capability string capability name.
2724 * @param bool $includeadmins include administrators
2726 function __construct($name, $visiblename, $description, $defaultsetting, $capability, $includeadmins = true) {
2727 $this->capability = $capability;
2728 $this->includeadmins = $includeadmins;
2729 parent::__construct($name, $visiblename, $description, $defaultsetting, NULL);
2733 * Load all of the uses who have the capability into choice array
2735 * @return bool Always returns true
2737 function load_choices() {
2738 if (is_array($this->choices)) {
2739 return true;
2741 $users = get_users_by_capability(get_context_instance(CONTEXT_SYSTEM),
2742 $this->capability, 'u.id,u.username,u.firstname,u.lastname', 'u.lastname,u.firstname');
2743 $this->choices = array(
2744 '$@NONE@$' => get_string('nobody'),
2745 '$@ALL@$' => get_string('everyonewhocan', 'admin', get_capability_string($this->capability)),
2747 if ($this->includeadmins) {
2748 $admins = get_admins();
2749 foreach ($admins as $user) {
2750 $this->choices[$user->id] = fullname($user);
2753 if (is_array($users)) {
2754 foreach ($users as $user) {
2755 $this->choices[$user->id] = fullname($user);
2758 return true;
2762 * Returns the default setting for class
2764 * @return mixed Array, or string. Empty string if no default
2766 public function get_defaultsetting() {
2767 $this->load_choices();
2768 $defaultsetting = parent::get_defaultsetting();
2769 if (empty($defaultsetting)) {
2770 return array('$@NONE@$');
2771 } else if (array_key_exists($defaultsetting, $this->choices)) {
2772 return $defaultsetting;
2773 } else {
2774 return '';
2779 * Returns the current setting
2781 * @return mixed array or string
2783 public function get_setting() {
2784 $result = parent::get_setting();
2785 if ($result === null) {
2786 // this is necessary for settings upgrade
2787 return null;
2789 if (empty($result)) {
2790 $result = array('$@NONE@$');
2792 return $result;
2796 * Save the chosen setting provided as $data
2798 * @param array $data
2799 * @return mixed string or array
2801 public function write_setting($data) {
2802 // If all is selected, remove any explicit options.
2803 if (in_array('$@ALL@$', $data)) {
2804 $data = array('$@ALL@$');
2806 // None never needs to be written to the DB.
2807 if (in_array('$@NONE@$', $data)) {
2808 unset($data[array_search('$@NONE@$', $data)]);
2810 return parent::write_setting($data);
2815 * Special checkbox for calendar - resets SESSION vars.
2817 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2819 class admin_setting_special_adminseesall extends admin_setting_configcheckbox {
2821 * Calls the parent::__construct with default values
2823 * name => calendar_adminseesall
2824 * visiblename => get_string('adminseesall', 'admin')
2825 * description => get_string('helpadminseesall', 'admin')
2826 * defaultsetting => 0
2828 public function __construct() {
2829 parent::__construct('calendar_adminseesall', get_string('adminseesall', 'admin'),
2830 get_string('helpadminseesall', 'admin'), '0');
2834 * Stores the setting passed in $data
2836 * @param mixed gets converted to string for comparison
2837 * @return string empty string or error message
2839 public function write_setting($data) {
2840 global $SESSION;
2841 unset($SESSION->cal_courses_shown);
2842 return parent::write_setting($data);
2847 * Special select for settings that are altered in setup.php and can not be altered on the fly
2849 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2851 class admin_setting_special_selectsetup extends admin_setting_configselect {
2853 * Reads the setting directly from the database
2855 * @return mixed
2857 public function get_setting() {
2858 // read directly from db!
2859 return get_config(NULL, $this->name);
2863 * Save the setting passed in $data
2865 * @param string $data The setting to save
2866 * @return string empty or error message
2868 public function write_setting($data) {
2869 global $CFG;
2870 // do not change active CFG setting!
2871 $current = $CFG->{$this->name};
2872 $result = parent::write_setting($data);
2873 $CFG->{$this->name} = $current;
2874 return $result;
2879 * Special select for frontpage - stores data in course table
2881 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2883 class admin_setting_sitesetselect extends admin_setting_configselect {
2885 * Returns the site name for the selected site
2887 * @see get_site()
2888 * @return string The site name of the selected site
2890 public function get_setting() {
2891 $site = get_site();
2892 return $site->{$this->name};
2895 * Updates the database and save the setting
2897 * @param string data
2898 * @return string empty or error message
2900 public function write_setting($data) {
2901 global $DB, $SITE;
2902 if (!in_array($data, array_keys($this->choices))) {
2903 return get_string('errorsetting', 'admin');
2905 $record = new stdClass();
2906 $record->id = SITEID;
2907 $temp = $this->name;
2908 $record->$temp = $data;
2909 $record->timemodified = time();
2910 // update $SITE
2911 $SITE->{$this->name} = $data;
2912 return ($DB->update_record('course', $record) ? '' : get_string('errorsetting', 'admin'));
2917 * Select for blog's bloglevel setting: if set to 0, will set blog_menu
2918 * block to hidden.
2920 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2922 class admin_setting_bloglevel extends admin_setting_configselect {
2924 * Updates the database and save the setting
2926 * @param string data
2927 * @return string empty or error message
2929 public function write_setting($data) {
2930 global $DB;
2931 if ($data['bloglevel'] == 0) {
2932 $DB->set_field('block', 'visible', 0, array('name' => 'blog_menu'));
2933 } else {
2934 $DB->set_field('block', 'visible', 1, array('name' => 'blog_menu'));
2936 return parent::write_setting($data);
2941 * Special select - lists on the frontpage - hacky
2943 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2945 class admin_setting_courselist_frontpage extends admin_setting {
2946 /** @var array Array of choices value=>label */
2947 public $choices;
2950 * Construct override, requires one param
2952 * @param bool $loggedin Is the user logged in
2954 public function __construct($loggedin) {
2955 global $CFG;
2956 require_once($CFG->dirroot.'/course/lib.php');
2957 $name = 'frontpage'.($loggedin ? 'loggedin' : '');
2958 $visiblename = get_string('frontpage'.($loggedin ? 'loggedin' : ''),'admin');
2959 $description = get_string('configfrontpage'.($loggedin ? 'loggedin' : ''),'admin');
2960 $defaults = array(FRONTPAGECOURSELIST);
2961 parent::__construct($name, $visiblename, $description, $defaults);
2965 * Loads the choices available
2967 * @return bool always returns true
2969 public function load_choices() {
2970 global $DB;
2971 if (is_array($this->choices)) {
2972 return true;
2974 $this->choices = array(FRONTPAGENEWS => get_string('frontpagenews'),
2975 FRONTPAGECOURSELIST => get_string('frontpagecourselist'),
2976 FRONTPAGECATEGORYNAMES => get_string('frontpagecategorynames'),
2977 FRONTPAGECATEGORYCOMBO => get_string('frontpagecategorycombo'),
2978 'none' => get_string('none'));
2979 if ($this->name == 'frontpage' and $DB->count_records('course') > FRONTPAGECOURSELIMIT) {
2980 unset($this->choices[FRONTPAGECOURSELIST]);
2982 return true;
2985 * Returns the selected settings
2987 * @param mixed array or setting or null
2989 public function get_setting() {
2990 $result = $this->config_read($this->name);
2991 if (is_null($result)) {
2992 return NULL;
2994 if ($result === '') {
2995 return array();
2997 return explode(',', $result);
3001 * Save the selected options
3003 * @param array $data
3004 * @return mixed empty string (data is not an array) or bool true=success false=failure
3006 public function write_setting($data) {
3007 if (!is_array($data)) {
3008 return '';
3010 $this->load_choices();
3011 $save = array();
3012 foreach($data as $datum) {
3013 if ($datum == 'none' or !array_key_exists($datum, $this->choices)) {
3014 continue;
3016 $save[$datum] = $datum; // no duplicates
3018 return ($this->config_write($this->name, implode(',', $save)) ? '' : get_string('errorsetting', 'admin'));
3022 * Return XHTML select field and wrapping div
3024 * @todo Add vartype handling to make sure $data is an array
3025 * @param array $data Array of elements to select by default
3026 * @return string XHTML select field and wrapping div
3028 public function output_html($data, $query='') {
3029 $this->load_choices();
3030 $currentsetting = array();
3031 foreach ($data as $key) {
3032 if ($key != 'none' and array_key_exists($key, $this->choices)) {
3033 $currentsetting[] = $key; // already selected first
3037 $return = '<div class="form-group">';
3038 for ($i = 0; $i < count($this->choices) - 1; $i++) {
3039 if (!array_key_exists($i, $currentsetting)) {
3040 $currentsetting[$i] = 'none'; //none
3042 $return .='<select class="form-select" id="'.$this->get_id().$i.'" name="'.$this->get_full_name().'[]">';
3043 foreach ($this->choices as $key => $value) {
3044 $return .= '<option value="'.$key.'"'.("$key" == $currentsetting[$i] ? ' selected="selected"' : '').'>'.$value.'</option>';
3046 $return .= '</select>';
3047 if ($i !== count($this->choices) - 2) {
3048 $return .= '<br />';
3051 $return .= '</div>';
3053 return format_admin_setting($this, $this->visiblename, $return, $this->description, false, '', NULL, $query);
3058 * Special checkbox for frontpage - stores data in course table
3060 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3062 class admin_setting_sitesetcheckbox extends admin_setting_configcheckbox {
3064 * Returns the current sites name
3066 * @return string
3068 public function get_setting() {
3069 $site = get_site();
3070 return $site->{$this->name};
3074 * Save the selected setting
3076 * @param string $data The selected site
3077 * @return string empty string or error message
3079 public function write_setting($data) {
3080 global $DB, $SITE;
3081 $record = new stdClass();
3082 $record->id = SITEID;
3083 $record->{$this->name} = ($data == '1' ? 1 : 0);
3084 $record->timemodified = time();
3085 // update $SITE
3086 $SITE->{$this->name} = $data;
3087 return ($DB->update_record('course', $record) ? '' : get_string('errorsetting', 'admin'));
3092 * Special text for frontpage - stores data in course table.
3093 * Empty string means not set here. Manual setting is required.
3095 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3097 class admin_setting_sitesettext extends admin_setting_configtext {
3099 * Return the current setting
3101 * @return mixed string or null
3103 public function get_setting() {
3104 $site = get_site();
3105 return $site->{$this->name} != '' ? $site->{$this->name} : NULL;
3109 * Validate the selected data
3111 * @param string $data The selected value to validate
3112 * @return mixed true or message string
3114 public function validate($data) {
3115 $cleaned = clean_param($data, PARAM_MULTILANG);
3116 if ($cleaned === '') {
3117 return get_string('required');
3119 if ("$data" == "$cleaned") { // implicit conversion to string is needed to do exact comparison
3120 return true;
3121 } else {
3122 return get_string('validateerror', 'admin');
3127 * Save the selected setting
3129 * @param string $data The selected value
3130 * @return string empty or error message
3132 public function write_setting($data) {
3133 global $DB, $SITE;
3134 $data = trim($data);
3135 $validated = $this->validate($data);
3136 if ($validated !== true) {
3137 return $validated;
3140 $record = new stdClass();
3141 $record->id = SITEID;
3142 $record->{$this->name} = $data;
3143 $record->timemodified = time();
3144 // update $SITE
3145 $SITE->{$this->name} = $data;
3146 return ($DB->update_record('course', $record) ? '' : get_string('dbupdatefailed', 'error'));
3151 * Special text editor for site description.
3153 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3155 class admin_setting_special_frontpagedesc extends admin_setting {
3157 * Calls parent::__construct with specific arguments
3159 public function __construct() {
3160 parent::__construct('summary', get_string('frontpagedescription'), get_string('frontpagedescriptionhelp'), NULL);
3161 editors_head_setup();
3165 * Return the current setting
3166 * @return string The current setting
3168 public function get_setting() {
3169 $site = get_site();
3170 return $site->{$this->name};
3174 * Save the new setting
3176 * @param string $data The new value to save
3177 * @return string empty or error message
3179 public function write_setting($data) {
3180 global $DB, $SITE;
3181 $record = new stdClass();
3182 $record->id = SITEID;
3183 $record->{$this->name} = $data;
3184 $record->timemodified = time();
3185 $SITE->{$this->name} = $data;
3186 return ($DB->update_record('course', $record) ? '' : get_string('errorsetting', 'admin'));
3190 * Returns XHTML for the field plus wrapping div
3192 * @param string $data The current value
3193 * @param string $query
3194 * @return string The XHTML output
3196 public function output_html($data, $query='') {
3197 global $CFG;
3199 $CFG->adminusehtmleditor = can_use_html_editor();
3200 $return = '<div class="form-htmlarea">'.print_textarea($CFG->adminusehtmleditor, 15, 60, 0, 0, $this->get_full_name(), $data, 0, true, 'summary') .'</div>';
3202 return format_admin_setting($this, $this->visiblename, $return, $this->description, false, '', NULL, $query);
3207 * Administration interface for emoticon_manager settings.
3209 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3211 class admin_setting_emoticons extends admin_setting {
3214 * Calls parent::__construct with specific args
3216 public function __construct() {
3217 global $CFG;
3219 $manager = get_emoticon_manager();
3220 $defaults = $this->prepare_form_data($manager->default_emoticons());
3221 parent::__construct('emoticons', get_string('emoticons', 'admin'), get_string('emoticons_desc', 'admin'), $defaults);
3225 * Return the current setting(s)
3227 * @return array Current settings array
3229 public function get_setting() {
3230 global $CFG;
3232 $manager = get_emoticon_manager();
3234 $config = $this->config_read($this->name);
3235 if (is_null($config)) {
3236 return null;
3239 $config = $manager->decode_stored_config($config);
3240 if (is_null($config)) {
3241 return null;
3244 return $this->prepare_form_data($config);
3248 * Save selected settings
3250 * @param array $data Array of settings to save
3251 * @return bool
3253 public function write_setting($data) {
3255 $manager = get_emoticon_manager();
3256 $emoticons = $this->process_form_data($data);
3258 if ($emoticons === false) {
3259 return false;
3262 if ($this->config_write($this->name, $manager->encode_stored_config($emoticons))) {
3263 return ''; // success
3264 } else {
3265 return get_string('errorsetting', 'admin') . $this->visiblename . html_writer::empty_tag('br');
3270 * Return XHTML field(s) for options
3272 * @param array $data Array of options to set in HTML
3273 * @return string XHTML string for the fields and wrapping div(s)
3275 public function output_html($data, $query='') {
3276 global $OUTPUT;
3278 $out = html_writer::start_tag('table', array('border' => 1, 'class' => 'generaltable'));
3279 $out .= html_writer::start_tag('thead');
3280 $out .= html_writer::start_tag('tr');
3281 $out .= html_writer::tag('th', get_string('emoticontext', 'admin'));
3282 $out .= html_writer::tag('th', get_string('emoticonimagename', 'admin'));
3283 $out .= html_writer::tag('th', get_string('emoticoncomponent', 'admin'));
3284 $out .= html_writer::tag('th', get_string('emoticonalt', 'admin'), array('colspan' => 2));
3285 $out .= html_writer::tag('th', '');
3286 $out .= html_writer::end_tag('tr');
3287 $out .= html_writer::end_tag('thead');
3288 $out .= html_writer::start_tag('tbody');
3289 $i = 0;
3290 foreach($data as $field => $value) {
3291 switch ($i) {
3292 case 0:
3293 $out .= html_writer::start_tag('tr');
3294 $current_text = $value;
3295 $current_filename = '';
3296 $current_imagecomponent = '';
3297 $current_altidentifier = '';
3298 $current_altcomponent = '';
3299 case 1:
3300 $current_filename = $value;
3301 case 2:
3302 $current_imagecomponent = $value;
3303 case 3:
3304 $current_altidentifier = $value;
3305 case 4:
3306 $current_altcomponent = $value;
3309 $out .= html_writer::tag('td',
3310 html_writer::empty_tag('input',
3311 array(
3312 'type' => 'text',
3313 'class' => 'form-text',
3314 'name' => $this->get_full_name().'['.$field.']',
3315 'value' => $value,
3317 ), array('class' => 'c'.$i)
3320 if ($i == 4) {
3321 if (get_string_manager()->string_exists($current_altidentifier, $current_altcomponent)) {
3322 $alt = get_string($current_altidentifier, $current_altcomponent);
3323 } else {
3324 $alt = $current_text;
3326 if ($current_filename) {
3327 $out .= html_writer::tag('td', $OUTPUT->render(new pix_emoticon($current_filename, $alt, $current_imagecomponent)));
3328 } else {
3329 $out .= html_writer::tag('td', '');
3331 $out .= html_writer::end_tag('tr');
3332 $i = 0;
3333 } else {
3334 $i++;
3338 $out .= html_writer::end_tag('tbody');
3339 $out .= html_writer::end_tag('table');
3340 $out = html_writer::tag('div', $out, array('class' => 'form-group'));
3341 $out .= html_writer::tag('div', html_writer::link(new moodle_url('/admin/resetemoticons.php'), get_string('emoticonsreset', 'admin')));
3343 return format_admin_setting($this, $this->visiblename, $out, $this->description, false, '', NULL, $query);
3347 * Converts the array of emoticon objects provided by {@see emoticon_manager} into admin settings form data
3349 * @see self::process_form_data()
3350 * @param array $emoticons array of emoticon objects as returned by {@see emoticon_manager}
3351 * @return array of form fields and their values
3353 protected function prepare_form_data(array $emoticons) {
3355 $form = array();
3356 $i = 0;
3357 foreach ($emoticons as $emoticon) {
3358 $form['text'.$i] = $emoticon->text;
3359 $form['imagename'.$i] = $emoticon->imagename;
3360 $form['imagecomponent'.$i] = $emoticon->imagecomponent;
3361 $form['altidentifier'.$i] = $emoticon->altidentifier;
3362 $form['altcomponent'.$i] = $emoticon->altcomponent;
3363 $i++;
3365 // add one more blank field set for new object
3366 $form['text'.$i] = '';
3367 $form['imagename'.$i] = '';
3368 $form['imagecomponent'.$i] = '';
3369 $form['altidentifier'.$i] = '';
3370 $form['altcomponent'.$i] = '';
3372 return $form;
3376 * Converts the data from admin settings form into an array of emoticon objects
3378 * @see self::prepare_form_data()
3379 * @param array $data array of admin form fields and values
3380 * @return false|array of emoticon objects
3382 protected function process_form_data(array $form) {
3384 $count = count($form); // number of form field values
3386 if ($count % 5) {
3387 // we must get five fields per emoticon object
3388 return false;
3391 $emoticons = array();
3392 for ($i = 0; $i < $count / 5; $i++) {
3393 $emoticon = new stdClass();
3394 $emoticon->text = clean_param(trim($form['text'.$i]), PARAM_NOTAGS);
3395 $emoticon->imagename = clean_param(trim($form['imagename'.$i]), PARAM_PATH);
3396 $emoticon->imagecomponent = clean_param(trim($form['imagecomponent'.$i]), PARAM_SAFEDIR);
3397 $emoticon->altidentifier = clean_param(trim($form['altidentifier'.$i]), PARAM_STRINGID);
3398 $emoticon->altcomponent = clean_param(trim($form['altcomponent'.$i]), PARAM_SAFEDIR);
3400 if (strpos($emoticon->text, ':/') !== false or strpos($emoticon->text, '//') !== false) {
3401 // prevent from breaking http://url.addresses by accident
3402 $emoticon->text = '';
3405 if (strlen($emoticon->text) < 2) {
3406 // do not allow single character emoticons
3407 $emoticon->text = '';
3410 if (preg_match('/^[a-zA-Z]+[a-zA-Z0-9]*$/', $emoticon->text)) {
3411 // emoticon text must contain some non-alphanumeric character to prevent
3412 // breaking HTML tags
3413 $emoticon->text = '';
3416 if ($emoticon->text !== '' and $emoticon->imagename !== '' and $emoticon->imagecomponent !== '') {
3417 $emoticons[] = $emoticon;
3420 return $emoticons;
3425 * Special setting for limiting of the list of available languages.
3427 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3429 class admin_setting_langlist extends admin_setting_configtext {
3431 * Calls parent::__construct with specific arguments
3433 public function __construct() {
3434 parent::__construct('langlist', get_string('langlist', 'admin'), get_string('configlanglist', 'admin'), '', PARAM_NOTAGS);
3438 * Save the new setting
3440 * @param string $data The new setting
3441 * @return bool
3443 public function write_setting($data) {
3444 $return = parent::write_setting($data);
3445 get_string_manager()->reset_caches();
3446 return $return;
3451 * Selection of one of the recognised countries using the list
3452 * returned by {@link get_list_of_countries()}.
3454 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3456 class admin_settings_country_select extends admin_setting_configselect {
3457 protected $includeall;
3458 public function __construct($name, $visiblename, $description, $defaultsetting, $includeall=false) {
3459 $this->includeall = $includeall;
3460 parent::__construct($name, $visiblename, $description, $defaultsetting, NULL);
3464 * Lazy-load the available choices for the select box
3466 public function load_choices() {
3467 global $CFG;
3468 if (is_array($this->choices)) {
3469 return true;
3471 $this->choices = array_merge(
3472 array('0' => get_string('choosedots')),
3473 get_string_manager()->get_list_of_countries($this->includeall));
3474 return true;
3479 * Course category selection
3481 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3483 class admin_settings_coursecat_select extends admin_setting_configselect {
3485 * Calls parent::__construct with specific arguments
3487 public function __construct($name, $visiblename, $description, $defaultsetting) {
3488 parent::__construct($name, $visiblename, $description, $defaultsetting, NULL);
3492 * Load the available choices for the select box
3494 * @return bool
3496 public function load_choices() {
3497 global $CFG;
3498 require_once($CFG->dirroot.'/course/lib.php');
3499 if (is_array($this->choices)) {
3500 return true;
3502 $this->choices = make_categories_options();
3503 return true;
3508 * Special control for selecting days to backup
3510 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3512 class admin_setting_special_backupdays extends admin_setting_configmulticheckbox2 {
3514 * Calls parent::__construct with specific arguments
3516 public function __construct() {
3517 parent::__construct('backup_auto_weekdays', get_string('automatedbackupschedule','backup'), get_string('automatedbackupschedulehelp','backup'), array(), NULL);
3518 $this->plugin = 'backup';
3521 * Load the available choices for the select box
3523 * @return bool Always returns true
3525 public function load_choices() {
3526 if (is_array($this->choices)) {
3527 return true;
3529 $this->choices = array();
3530 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
3531 foreach ($days as $day) {
3532 $this->choices[$day] = get_string($day, 'calendar');
3534 return true;
3539 * Special debug setting
3541 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3543 class admin_setting_special_debug extends admin_setting_configselect {
3545 * Calls parent::__construct with specific arguments
3547 public function __construct() {
3548 parent::__construct('debug', get_string('debug', 'admin'), get_string('configdebug', 'admin'), DEBUG_NONE, NULL);
3552 * Load the available choices for the select box
3554 * @return bool
3556 public function load_choices() {
3557 if (is_array($this->choices)) {
3558 return true;
3560 $this->choices = array(DEBUG_NONE => get_string('debugnone', 'admin'),
3561 DEBUG_MINIMAL => get_string('debugminimal', 'admin'),
3562 DEBUG_NORMAL => get_string('debugnormal', 'admin'),
3563 DEBUG_ALL => get_string('debugall', 'admin'),
3564 DEBUG_DEVELOPER => get_string('debugdeveloper', 'admin'));
3565 return true;
3570 * Special admin control
3572 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3574 class admin_setting_special_calendar_weekend extends admin_setting {
3576 * Calls parent::__construct with specific arguments
3578 public function __construct() {
3579 $name = 'calendar_weekend';
3580 $visiblename = get_string('calendar_weekend', 'admin');
3581 $description = get_string('helpweekenddays', 'admin');
3582 $default = array ('0', '6'); // Saturdays and Sundays
3583 parent::__construct($name, $visiblename, $description, $default);
3586 * Gets the current settings as an array
3588 * @return mixed Null if none, else array of settings
3590 public function get_setting() {
3591 $result = $this->config_read($this->name);
3592 if (is_null($result)) {
3593 return NULL;
3595 if ($result === '') {
3596 return array();
3598 $settings = array();
3599 for ($i=0; $i<7; $i++) {
3600 if ($result & (1 << $i)) {
3601 $settings[] = $i;
3604 return $settings;
3608 * Save the new settings
3610 * @param array $data Array of new settings
3611 * @return bool
3613 public function write_setting($data) {
3614 if (!is_array($data)) {
3615 return '';
3617 unset($data['xxxxx']);
3618 $result = 0;
3619 foreach($data as $index) {
3620 $result |= 1 << $index;
3622 return ($this->config_write($this->name, $result) ? '' : get_string('errorsetting', 'admin'));
3626 * Return XHTML to display the control
3628 * @param array $data array of selected days
3629 * @param string $query
3630 * @return string XHTML for display (field + wrapping div(s)
3632 public function output_html($data, $query='') {
3633 // The order matters very much because of the implied numeric keys
3634 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
3635 $return = '<table><thead><tr>';
3636 $return .= '<input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
3637 foreach($days as $index => $day) {
3638 $return .= '<td><label for="'.$this->get_id().$index.'">'.get_string($day, 'calendar').'</label></td>';
3640 $return .= '</tr></thead><tbody><tr>';
3641 foreach($days as $index => $day) {
3642 $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>';
3644 $return .= '</tr></tbody></table>';
3646 return format_admin_setting($this, $this->visiblename, $return, $this->description, false, '', NULL, $query);
3653 * Admin setting that allows a user to pick appropriate roles for something.
3655 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3657 class admin_setting_pickroles extends admin_setting_configmulticheckbox {
3658 /** @var array Array of capabilities which identify roles */
3659 private $types;
3662 * @param string $name Name of config variable
3663 * @param string $visiblename Display name
3664 * @param string $description Description
3665 * @param array $types Array of archetypes which identify
3666 * roles that will be enabled by default.
3668 public function __construct($name, $visiblename, $description, $types) {
3669 parent::__construct($name, $visiblename, $description, NULL, NULL);
3670 $this->types = $types;
3674 * Load roles as choices
3676 * @return bool true=>success, false=>error
3678 public function load_choices() {
3679 global $CFG, $DB;
3680 if (during_initial_install()) {
3681 return false;
3683 if (is_array($this->choices)) {
3684 return true;
3686 if ($roles = get_all_roles()) {
3687 $this->choices = array();
3688 foreach($roles as $role) {
3689 $this->choices[$role->id] = format_string($role->name);
3691 return true;
3692 } else {
3693 return false;
3697 * Return the default setting for this control
3699 * @return array Array of default settings
3701 public function get_defaultsetting() {
3702 global $CFG;
3704 if (during_initial_install()) {
3705 return null;
3707 $result = array();
3708 foreach($this->types as $archetype) {
3709 if ($caproles = get_archetype_roles($archetype)) {
3710 foreach ($caproles as $caprole) {
3711 $result[$caprole->id] = 1;
3715 return $result;
3720 * Text field with an advanced checkbox, that controls a additional $name.'_adv' setting.
3722 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3724 class admin_setting_configtext_with_advanced extends admin_setting_configtext {
3726 * Constructor
3727 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
3728 * @param string $visiblename localised
3729 * @param string $description long localised info
3730 * @param array $defaultsetting ('value'=>string, '__construct'=>bool)
3731 * @param mixed $paramtype int means PARAM_XXX type, string is a allowed format in regex
3732 * @param int $size default field size
3734 public function __construct($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW, $size=null) {
3735 parent::__construct($name, $visiblename, $description, $defaultsetting, $paramtype, $size);
3739 * Loads the current setting and returns array
3741 * @return array Returns array value=>xx, __construct=>xx
3743 public function get_setting() {
3744 $value = parent::get_setting();
3745 $adv = $this->config_read($this->name.'_adv');
3746 if (is_null($value) or is_null($adv)) {
3747 return NULL;
3749 return array('value' => $value, 'adv' => $adv);
3753 * Saves the new settings passed in $data
3755 * @todo Add vartype handling to ensure $data is an array
3756 * @param array $data
3757 * @return mixed string or Array
3759 public function write_setting($data) {
3760 $error = parent::write_setting($data['value']);
3761 if (!$error) {
3762 $value = empty($data['adv']) ? 0 : 1;
3763 $this->config_write($this->name.'_adv', $value);
3765 return $error;
3769 * Return XHTML for the control
3771 * @param array $data Default data array
3772 * @param string $query
3773 * @return string XHTML to display control
3775 public function output_html($data, $query='') {
3776 $default = $this->get_defaultsetting();
3777 $defaultinfo = array();
3778 if (isset($default['value'])) {
3779 if ($default['value'] === '') {
3780 $defaultinfo[] = "''";
3781 } else {
3782 $defaultinfo[] = $default['value'];
3785 if (!empty($default['adv'])) {
3786 $defaultinfo[] = get_string('advanced');
3788 $defaultinfo = implode(', ', $defaultinfo);
3790 $adv = !empty($data['adv']);
3791 $return = '<div class="form-text defaultsnext">' .
3792 '<input type="text" size="' . $this->size . '" id="' . $this->get_id() .
3793 '" name="' . $this->get_full_name() . '[value]" value="' . s($data['value']) . '" />' .
3794 ' <input type="checkbox" class="form-checkbox" id="' .
3795 $this->get_id() . '_adv" name="' . $this->get_full_name() .
3796 '[adv]" value="1" ' . ($adv ? 'checked="checked"' : '') . ' />' .
3797 ' <label for="' . $this->get_id() . '_adv">' .
3798 get_string('advanced') . '</label></div>';
3800 return format_admin_setting($this, $this->visiblename, $return,
3801 $this->description, true, '', $defaultinfo, $query);
3806 * Checkbox with an advanced checkbox that controls an additional $name.'_adv' config setting.
3808 * @copyright 2009 Petr Skoda (http://skodak.org)
3809 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3811 class admin_setting_configcheckbox_with_advanced extends admin_setting_configcheckbox {
3814 * Constructor
3815 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
3816 * @param string $visiblename localised
3817 * @param string $description long localised info
3818 * @param array $defaultsetting ('value'=>string, 'adv'=>bool)
3819 * @param string $yes value used when checked
3820 * @param string $no value used when not checked
3822 public function __construct($name, $visiblename, $description, $defaultsetting, $yes='1', $no='0') {
3823 parent::__construct($name, $visiblename, $description, $defaultsetting, $yes, $no);
3827 * Loads the current setting and returns array
3829 * @return array Returns array value=>xx, adv=>xx
3831 public function get_setting() {
3832 $value = parent::get_setting();
3833 $adv = $this->config_read($this->name.'_adv');
3834 if (is_null($value) or is_null($adv)) {
3835 return NULL;
3837 return array('value' => $value, 'adv' => $adv);
3841 * Sets the value for the setting
3843 * Sets the value for the setting to either the yes or no values
3844 * of the object by comparing $data to yes
3846 * @param mixed $data Gets converted to str for comparison against yes value
3847 * @return string empty string or error
3849 public function write_setting($data) {
3850 $error = parent::write_setting($data['value']);
3851 if (!$error) {
3852 $value = empty($data['adv']) ? 0 : 1;
3853 $this->config_write($this->name.'_adv', $value);
3855 return $error;
3859 * Returns an XHTML checkbox field and with extra advanced cehckbox
3861 * @param string $data If $data matches yes then checkbox is checked
3862 * @param string $query
3863 * @return string XHTML field
3865 public function output_html($data, $query='') {
3866 $defaults = $this->get_defaultsetting();
3867 $defaultinfo = array();
3868 if (!is_null($defaults)) {
3869 if ((string)$defaults['value'] === $this->yes) {
3870 $defaultinfo[] = get_string('checkboxyes', 'admin');
3871 } else {
3872 $defaultinfo[] = get_string('checkboxno', 'admin');
3874 if (!empty($defaults['adv'])) {
3875 $defaultinfo[] = get_string('advanced');
3878 $defaultinfo = implode(', ', $defaultinfo);
3880 if ((string)$data['value'] === $this->yes) { // convert to strings before comparison
3881 $checked = 'checked="checked"';
3882 } else {
3883 $checked = '';
3885 if (!empty($data['adv'])) {
3886 $advanced = 'checked="checked"';
3887 } else {
3888 $advanced = '';
3891 $fullname = $this->get_full_name();
3892 $novalue = s($this->no);
3893 $yesvalue = s($this->yes);
3894 $id = $this->get_id();
3895 $stradvanced = get_string('advanced');
3896 $return = <<<EOT
3897 <div class="form-checkbox defaultsnext" >
3898 <input type="hidden" name="{$fullname}[value]" value="$novalue" />
3899 <input type="checkbox" id="$id" name="{$fullname}[value]" value="$yesvalue" $checked />
3900 <input type="checkbox" class="form-checkbox" id="{$id}_adv" name="{$fullname}[adv]" value="1" $advanced />
3901 <label for="{$id}_adv">$stradvanced</label>
3902 </div>
3903 EOT;
3904 return format_admin_setting($this, $this->visiblename, $return, $this->description,
3905 true, '', $defaultinfo, $query);
3910 * Checkbox with an advanced checkbox that controls an additional $name.'_locked' config setting.
3912 * This is nearly a copy/paste of admin_setting_configcheckbox_with_adv
3914 * @copyright 2010 Sam Hemelryk
3915 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3917 class admin_setting_configcheckbox_with_lock extends admin_setting_configcheckbox {
3919 * Constructor
3920 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
3921 * @param string $visiblename localised
3922 * @param string $description long localised info
3923 * @param array $defaultsetting ('value'=>string, 'locked'=>bool)
3924 * @param string $yes value used when checked
3925 * @param string $no value used when not checked
3927 public function __construct($name, $visiblename, $description, $defaultsetting, $yes='1', $no='0') {
3928 parent::__construct($name, $visiblename, $description, $defaultsetting, $yes, $no);
3932 * Loads the current setting and returns array
3934 * @return array Returns array value=>xx, adv=>xx
3936 public function get_setting() {
3937 $value = parent::get_setting();
3938 $locked = $this->config_read($this->name.'_locked');
3939 if (is_null($value) or is_null($locked)) {
3940 return NULL;
3942 return array('value' => $value, 'locked' => $locked);
3946 * Sets the value for the setting
3948 * Sets the value for the setting to either the yes or no values
3949 * of the object by comparing $data to yes
3951 * @param mixed $data Gets converted to str for comparison against yes value
3952 * @return string empty string or error
3954 public function write_setting($data) {
3955 $error = parent::write_setting($data['value']);
3956 if (!$error) {
3957 $value = empty($data['locked']) ? 0 : 1;
3958 $this->config_write($this->name.'_locked', $value);
3960 return $error;
3964 * Returns an XHTML checkbox field and with extra locked checkbox
3966 * @param string $data If $data matches yes then checkbox is checked
3967 * @param string $query
3968 * @return string XHTML field
3970 public function output_html($data, $query='') {
3971 $defaults = $this->get_defaultsetting();
3972 $defaultinfo = array();
3973 if (!is_null($defaults)) {
3974 if ((string)$defaults['value'] === $this->yes) {
3975 $defaultinfo[] = get_string('checkboxyes', 'admin');
3976 } else {
3977 $defaultinfo[] = get_string('checkboxno', 'admin');
3979 if (!empty($defaults['locked'])) {
3980 $defaultinfo[] = get_string('locked', 'admin');
3983 $defaultinfo = implode(', ', $defaultinfo);
3985 $fullname = $this->get_full_name();
3986 $novalue = s($this->no);
3987 $yesvalue = s($this->yes);
3988 $id = $this->get_id();
3990 $checkboxparams = array('type'=>'checkbox', 'id'=>$id,'name'=>$fullname.'[value]', 'value'=>$yesvalue);
3991 if ((string)$data['value'] === $this->yes) { // convert to strings before comparison
3992 $checkboxparams['checked'] = 'checked';
3995 $lockcheckboxparams = array('type'=>'checkbox', 'id'=>$id.'_locked','name'=>$fullname.'[locked]', 'value'=>1, 'class'=>'form-checkbox');
3996 if (!empty($data['locked'])) { // convert to strings before comparison
3997 $lockcheckboxparams['checked'] = 'checked';
4000 $return = html_writer::start_tag('div', array('class'=>'form-checkbox defaultsnext'));
4001 $return .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>$fullname.'[value]', 'value'=>$novalue));
4002 $return .= html_writer::empty_tag('input', $checkboxparams);
4003 $return .= html_writer::empty_tag('input', $lockcheckboxparams);
4004 $return .= html_writer::tag('label', get_string('locked', 'admin'), array('for'=>$id.'_locked'));
4005 $return .= html_writer::end_tag('div');
4006 return format_admin_setting($this, $this->visiblename, $return, $this->description, true, '', $defaultinfo, $query);
4011 * Dropdown menu with an advanced checkbox, that controls a additional $name.'_adv' setting.
4013 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4015 class admin_setting_configselect_with_advanced extends admin_setting_configselect {
4017 * Calls parent::__construct with specific arguments
4019 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
4020 parent::__construct($name, $visiblename, $description, $defaultsetting, $choices);
4024 * Loads the current setting and returns array
4026 * @return array Returns array value=>xx, adv=>xx
4028 public function get_setting() {
4029 $value = parent::get_setting();
4030 $adv = $this->config_read($this->name.'_adv');
4031 if (is_null($value) or is_null($adv)) {
4032 return NULL;
4034 return array('value' => $value, 'adv' => $adv);
4038 * Saves the new settings passed in $data
4040 * @todo Add vartype handling to ensure $data is an array
4041 * @param array $data
4042 * @return mixed string or Array
4044 public function write_setting($data) {
4045 $error = parent::write_setting($data['value']);
4046 if (!$error) {
4047 $value = empty($data['adv']) ? 0 : 1;
4048 $this->config_write($this->name.'_adv', $value);
4050 return $error;
4054 * Return XHTML for the control
4056 * @param array $data Default data array
4057 * @param string $query
4058 * @return string XHTML to display control
4060 public function output_html($data, $query='') {
4061 $default = $this->get_defaultsetting();
4062 $current = $this->get_setting();
4064 list($selecthtml, $warning) = $this->output_select_html($data['value'],
4065 $current['value'], $default['value'], '[value]');
4066 if (!$selecthtml) {
4067 return '';
4070 if (!is_null($default) and array_key_exists($default['value'], $this->choices)) {
4071 $defaultinfo = array();
4072 if (isset($this->choices[$default['value']])) {
4073 $defaultinfo[] = $this->choices[$default['value']];
4075 if (!empty($default['adv'])) {
4076 $defaultinfo[] = get_string('advanced');
4078 $defaultinfo = implode(', ', $defaultinfo);
4079 } else {
4080 $defaultinfo = '';
4083 $adv = !empty($data['adv']);
4084 $return = '<div class="form-select defaultsnext">' . $selecthtml .
4085 ' <input type="checkbox" class="form-checkbox" id="' .
4086 $this->get_id() . '_adv" name="' . $this->get_full_name() .
4087 '[adv]" value="1" ' . ($adv ? 'checked="checked"' : '') . ' />' .
4088 ' <label for="' . $this->get_id() . '_adv">' .
4089 get_string('advanced') . '</label></div>';
4091 return format_admin_setting($this, $this->visiblename, $return, $this->description, true, $warning, $defaultinfo, $query);
4096 * Graded roles in gradebook
4098 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4100 class admin_setting_special_gradebookroles extends admin_setting_pickroles {
4102 * Calls parent::__construct with specific arguments
4104 public function __construct() {
4105 parent::__construct('gradebookroles', get_string('gradebookroles', 'admin'),
4106 get_string('configgradebookroles', 'admin'),
4107 array('student'));
4113 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4115 class admin_setting_regradingcheckbox extends admin_setting_configcheckbox {
4117 * Saves the new settings passed in $data
4119 * @param string $data
4120 * @return mixed string or Array
4122 public function write_setting($data) {
4123 global $CFG, $DB;
4125 $oldvalue = $this->config_read($this->name);
4126 $return = parent::write_setting($data);
4127 $newvalue = $this->config_read($this->name);
4129 if ($oldvalue !== $newvalue) {
4130 // force full regrading
4131 $DB->set_field('grade_items', 'needsupdate', 1, array('needsupdate'=>0));
4134 return $return;
4139 * Which roles to show on course description page
4141 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4143 class admin_setting_special_coursecontact extends admin_setting_pickroles {
4145 * Calls parent::__construct with specific arguments
4147 public function __construct() {
4148 parent::__construct('coursecontact', get_string('coursecontact', 'admin'),
4149 get_string('coursecontact_desc', 'admin'),
4150 array('editingteacher'));
4156 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4158 class admin_setting_special_gradelimiting extends admin_setting_configcheckbox {
4160 * Calls parent::__construct with specific arguments
4162 function admin_setting_special_gradelimiting() {
4163 parent::__construct('unlimitedgrades', get_string('unlimitedgrades', 'grades'),
4164 get_string('unlimitedgrades_help', 'grades'), '0', '1', '0');
4168 * Force site regrading
4170 function regrade_all() {
4171 global $CFG;
4172 require_once("$CFG->libdir/gradelib.php");
4173 grade_force_site_regrading();
4177 * Saves the new settings
4179 * @param mixed $data
4180 * @return string empty string or error message
4182 function write_setting($data) {
4183 $previous = $this->get_setting();
4185 if ($previous === null) {
4186 if ($data) {
4187 $this->regrade_all();
4189 } else {
4190 if ($data != $previous) {
4191 $this->regrade_all();
4194 return ($this->config_write($this->name, $data) ? '' : get_string('errorsetting', 'admin'));
4200 * Primary grade export plugin - has state tracking.
4202 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4204 class admin_setting_special_gradeexport extends admin_setting_configmulticheckbox {
4206 * Calls parent::__construct with specific arguments
4208 public function __construct() {
4209 parent::__construct('gradeexport', get_string('gradeexport', 'admin'),
4210 get_string('configgradeexport', 'admin'), array(), NULL);
4214 * Load the available choices for the multicheckbox
4216 * @return bool always returns true
4218 public function load_choices() {
4219 if (is_array($this->choices)) {
4220 return true;
4222 $this->choices = array();
4224 if ($plugins = get_plugin_list('gradeexport')) {
4225 foreach($plugins as $plugin => $unused) {
4226 $this->choices[$plugin] = get_string('pluginname', 'gradeexport_'.$plugin);
4229 return true;
4234 * Grade category settings
4236 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4238 class admin_setting_gradecat_combo extends admin_setting {
4239 /** @var array Array of choices */
4240 public $choices;
4243 * Sets choices and calls parent::__construct with passed arguments
4244 * @param string $name
4245 * @param string $visiblename
4246 * @param string $description
4247 * @param mixed $defaultsetting string or array depending on implementation
4248 * @param array $choices An array of choices for the control
4250 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
4251 $this->choices = $choices;
4252 parent::__construct($name, $visiblename, $description, $defaultsetting);
4256 * Return the current setting(s) array
4258 * @return array Array of value=>xx, forced=>xx, adv=>xx
4260 public function get_setting() {
4261 global $CFG;
4263 $value = $this->config_read($this->name);
4264 $flag = $this->config_read($this->name.'_flag');
4266 if (is_null($value) or is_null($flag)) {
4267 return NULL;
4270 $flag = (int)$flag;
4271 $forced = (boolean)(1 & $flag); // first bit
4272 $adv = (boolean)(2 & $flag); // second bit
4274 return array('value' => $value, 'forced' => $forced, 'adv' => $adv);
4278 * Save the new settings passed in $data
4280 * @todo Add vartype handling to ensure $data is array
4281 * @param array $data Associative array of value=>xx, forced=>xx, adv=>xx
4282 * @return string empty or error message
4284 public function write_setting($data) {
4285 global $CFG;
4287 $value = $data['value'];
4288 $forced = empty($data['forced']) ? 0 : 1;
4289 $adv = empty($data['adv']) ? 0 : 2;
4290 $flag = ($forced | $adv); //bitwise or
4292 if (!in_array($value, array_keys($this->choices))) {
4293 return 'Error setting ';
4296 $oldvalue = $this->config_read($this->name);
4297 $oldflag = (int)$this->config_read($this->name.'_flag');
4298 $oldforced = (1 & $oldflag); // first bit
4300 $result1 = $this->config_write($this->name, $value);
4301 $result2 = $this->config_write($this->name.'_flag', $flag);
4303 // force regrade if needed
4304 if ($oldforced != $forced or ($forced and $value != $oldvalue)) {
4305 require_once($CFG->libdir.'/gradelib.php');
4306 grade_category::updated_forced_settings();
4309 if ($result1 and $result2) {
4310 return '';
4311 } else {
4312 return get_string('errorsetting', 'admin');
4317 * Return XHTML to display the field and wrapping div
4319 * @todo Add vartype handling to ensure $data is array
4320 * @param array $data Associative array of value=>xx, forced=>xx, adv=>xx
4321 * @param string $query
4322 * @return string XHTML to display control
4324 public function output_html($data, $query='') {
4325 $value = $data['value'];
4326 $forced = !empty($data['forced']);
4327 $adv = !empty($data['adv']);
4329 $default = $this->get_defaultsetting();
4330 if (!is_null($default)) {
4331 $defaultinfo = array();
4332 if (isset($this->choices[$default['value']])) {
4333 $defaultinfo[] = $this->choices[$default['value']];
4335 if (!empty($default['forced'])) {
4336 $defaultinfo[] = get_string('force');
4338 if (!empty($default['adv'])) {
4339 $defaultinfo[] = get_string('advanced');
4341 $defaultinfo = implode(', ', $defaultinfo);
4343 } else {
4344 $defaultinfo = NULL;
4348 $return = '<div class="form-group">';
4349 $return .= '<select class="form-select" id="'.$this->get_id().'" name="'.$this->get_full_name().'[value]">';
4350 foreach ($this->choices as $key => $val) {
4351 // the string cast is needed because key may be integer - 0 is equal to most strings!
4352 $return .= '<option value="'.$key.'"'.((string)$key==$value ? ' selected="selected"' : '').'>'.$val.'</option>';
4354 $return .= '</select>';
4355 $return .= '<input type="checkbox" class="form-checkbox" id="'.$this->get_id().'force" name="'.$this->get_full_name().'[forced]" value="1" '.($forced ? 'checked="checked"' : '').' />'
4356 .'<label for="'.$this->get_id().'force">'.get_string('force').'</label>';
4357 $return .= '<input type="checkbox" class="form-checkbox" id="'.$this->get_id().'adv" name="'.$this->get_full_name().'[adv]" value="1" '.($adv ? 'checked="checked"' : '').' />'
4358 .'<label for="'.$this->get_id().'adv">'.get_string('advanced').'</label>';
4359 $return .= '</div>';
4361 return format_admin_setting($this, $this->visiblename, $return, $this->description, true, '', $defaultinfo, $query);
4367 * Selection of grade report in user profiles
4369 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4371 class admin_setting_grade_profilereport extends admin_setting_configselect {
4373 * Calls parent::__construct with specific arguments
4375 public function __construct() {
4376 parent::__construct('grade_profilereport', get_string('profilereport', 'grades'), get_string('profilereport_help', 'grades'), 'user', null);
4380 * Loads an array of choices for the configselect control
4382 * @return bool always return true
4384 public function load_choices() {
4385 if (is_array($this->choices)) {
4386 return true;
4388 $this->choices = array();
4390 global $CFG;
4391 require_once($CFG->libdir.'/gradelib.php');
4393 foreach (get_plugin_list('gradereport') as $plugin => $plugindir) {
4394 if (file_exists($plugindir.'/lib.php')) {
4395 require_once($plugindir.'/lib.php');
4396 $functionname = 'grade_report_'.$plugin.'_profilereport';
4397 if (function_exists($functionname)) {
4398 $this->choices[$plugin] = get_string('pluginname', 'gradereport_'.$plugin);
4402 return true;
4407 * Special class for register auth selection
4409 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4411 class admin_setting_special_registerauth extends admin_setting_configselect {
4413 * Calls parent::__construct with specific arguments
4415 public function __construct() {
4416 parent::__construct('registerauth', get_string('selfregistration', 'auth'), get_string('selfregistration_help', 'auth'), '', null);
4420 * Returns the default option
4422 * @return string empty or default option
4424 public function get_defaultsetting() {
4425 $this->load_choices();
4426 $defaultsetting = parent::get_defaultsetting();
4427 if (array_key_exists($defaultsetting, $this->choices)) {
4428 return $defaultsetting;
4429 } else {
4430 return '';
4435 * Loads the possible choices for the array
4437 * @return bool always returns true
4439 public function load_choices() {
4440 global $CFG;
4442 if (is_array($this->choices)) {
4443 return true;
4445 $this->choices = array();
4446 $this->choices[''] = get_string('disable');
4448 $authsenabled = get_enabled_auth_plugins(true);
4450 foreach ($authsenabled as $auth) {
4451 $authplugin = get_auth_plugin($auth);
4452 if (!$authplugin->can_signup()) {
4453 continue;
4455 // Get the auth title (from core or own auth lang files)
4456 $authtitle = $authplugin->get_title();
4457 $this->choices[$auth] = $authtitle;
4459 return true;
4464 * Module manage page
4466 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4468 class admin_page_managemods extends admin_externalpage {
4470 * Calls parent::__construct with specific arguments
4472 public function __construct() {
4473 global $CFG;
4474 parent::__construct('managemodules', get_string('modsettings', 'admin'), "$CFG->wwwroot/$CFG->admin/modules.php");
4478 * Try to find the specified module
4480 * @param string $query The module to search for
4481 * @return array
4483 public function search($query) {
4484 global $CFG, $DB;
4485 if ($result = parent::search($query)) {
4486 return $result;
4489 $found = false;
4490 if ($modules = $DB->get_records('modules')) {
4491 $textlib = textlib_get_instance();
4492 foreach ($modules as $module) {
4493 if (!file_exists("$CFG->dirroot/mod/$module->name/lib.php")) {
4494 continue;
4496 if (strpos($module->name, $query) !== false) {
4497 $found = true;
4498 break;
4500 $strmodulename = get_string('modulename', $module->name);
4501 if (strpos($textlib->strtolower($strmodulename), $query) !== false) {
4502 $found = true;
4503 break;
4507 if ($found) {
4508 $result = new stdClass();
4509 $result->page = $this;
4510 $result->settings = array();
4511 return array($this->name => $result);
4512 } else {
4513 return array();
4520 * Special class for enrol plugins management.
4522 * @copyright 2010 Petr Skoda {@link http://skodak.org}
4523 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4525 class admin_setting_manageenrols extends admin_setting {
4527 * Calls parent::__construct with specific arguments
4529 public function __construct() {
4530 $this->nosave = true;
4531 parent::__construct('enrolsui', get_string('manageenrols', 'enrol'), '', '');
4535 * Always returns true, does nothing
4537 * @return true
4539 public function get_setting() {
4540 return true;
4544 * Always returns true, does nothing
4546 * @return true
4548 public function get_defaultsetting() {
4549 return true;
4553 * Always returns '', does not write anything
4555 * @return string Always returns ''
4557 public function write_setting($data) {
4558 // do not write any setting
4559 return '';
4563 * Checks if $query is one of the available enrol plugins
4565 * @param string $query The string to search for
4566 * @return bool Returns true if found, false if not
4568 public function is_related($query) {
4569 if (parent::is_related($query)) {
4570 return true;
4573 $textlib = textlib_get_instance();
4574 $query = $textlib->strtolower($query);
4575 $enrols = enrol_get_plugins(false);
4576 foreach ($enrols as $name=>$enrol) {
4577 $localised = get_string('pluginname', 'enrol_'.$name);
4578 if (strpos($textlib->strtolower($name), $query) !== false) {
4579 return true;
4581 if (strpos($textlib->strtolower($localised), $query) !== false) {
4582 return true;
4585 return false;
4589 * Builds the XHTML to display the control
4591 * @param string $data Unused
4592 * @param string $query
4593 * @return string
4595 public function output_html($data, $query='') {
4596 global $CFG, $OUTPUT, $DB;
4598 // display strings
4599 $strup = get_string('up');
4600 $strdown = get_string('down');
4601 $strsettings = get_string('settings');
4602 $strenable = get_string('enable');
4603 $strdisable = get_string('disable');
4604 $struninstall = get_string('uninstallplugin', 'admin');
4605 $strusage = get_string('enrolusage', 'enrol');
4607 $enrols_available = enrol_get_plugins(false);
4608 $active_enrols = enrol_get_plugins(true);
4610 $allenrols = array();
4611 foreach ($active_enrols as $key=>$enrol) {
4612 $allenrols[$key] = true;
4614 foreach ($enrols_available as $key=>$enrol) {
4615 $allenrols[$key] = true;
4617 // now find all borked plugins and at least allow then to uninstall
4618 $borked = array();
4619 $condidates = $DB->get_fieldset_sql("SELECT DISTINCT enrol FROM {enrol}");
4620 foreach ($condidates as $candidate) {
4621 if (empty($allenrols[$candidate])) {
4622 $allenrols[$candidate] = true;
4626 $return = $OUTPUT->heading(get_string('actenrolshhdr', 'enrol'), 3, 'main', true);
4627 $return .= $OUTPUT->box_start('generalbox enrolsui');
4629 $table = new html_table();
4630 $table->head = array(get_string('name'), $strusage, $strenable, $strup.'/'.$strdown, $strsettings, $struninstall);
4631 $table->align = array('left', 'center', 'center', 'center', 'center', 'center');
4632 $table->width = '90%';
4633 $table->data = array();
4635 // iterate through enrol plugins and add to the display table
4636 $updowncount = 1;
4637 $enrolcount = count($active_enrols);
4638 $url = new moodle_url('/admin/enrol.php', array('sesskey'=>sesskey()));
4639 $printed = array();
4640 foreach($allenrols as $enrol => $unused) {
4641 if (get_string_manager()->string_exists('pluginname', 'enrol_'.$enrol)) {
4642 $name = get_string('pluginname', 'enrol_'.$enrol);
4643 } else {
4644 $name = $enrol;
4646 //usage
4647 $ci = $DB->count_records('enrol', array('enrol'=>$enrol));
4648 $cp = $DB->count_records_select('user_enrolments', "enrolid IN (SELECT id FROM {enrol} WHERE enrol = ?)", array($enrol));
4649 $usage = "$ci / $cp";
4651 // hide/show link
4652 if (isset($active_enrols[$enrol])) {
4653 $aurl = new moodle_url($url, array('action'=>'disable', 'enrol'=>$enrol));
4654 $hideshow = "<a href=\"$aurl\">";
4655 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('i/hide') . "\" class=\"icon\" alt=\"$strdisable\" /></a>";
4656 $enabled = true;
4657 $displayname = "<span>$name</span>";
4658 } else if (isset($enrols_available[$enrol])) {
4659 $aurl = new moodle_url($url, array('action'=>'enable', 'enrol'=>$enrol));
4660 $hideshow = "<a href=\"$aurl\">";
4661 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('i/show') . "\" class=\"icon\" alt=\"$strenable\" /></a>";
4662 $enabled = false;
4663 $displayname = "<span class=\"dimmed_text\">$name</span>";
4664 } else {
4665 $hideshow = '';
4666 $enabled = false;
4667 $displayname = '<span class="notifyproblem">'.$name.'</span>';
4670 // up/down link (only if enrol is enabled)
4671 $updown = '';
4672 if ($enabled) {
4673 if ($updowncount > 1) {
4674 $aurl = new moodle_url($url, array('action'=>'up', 'enrol'=>$enrol));
4675 $updown .= "<a href=\"$aurl\">";
4676 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/up') . "\" alt=\"$strup\" /></a>&nbsp;";
4677 } else {
4678 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"icon\" alt=\"\" />&nbsp;";
4680 if ($updowncount < $enrolcount) {
4681 $aurl = new moodle_url($url, array('action'=>'down', 'enrol'=>$enrol));
4682 $updown .= "<a href=\"$aurl\">";
4683 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/down') . "\" alt=\"$strdown\" /></a>";
4684 } else {
4685 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"icon\" alt=\"\" />";
4687 ++$updowncount;
4690 // settings link
4691 if (isset($active_enrols[$enrol]) or file_exists($CFG->dirroot.'/enrol/'.$enrol.'/settings.php')) {
4692 $surl = new moodle_url('/admin/settings.php', array('section'=>'enrolsettings'.$enrol));
4693 $settings = "<a href=\"$surl\">$strsettings</a>";
4694 } else {
4695 $settings = '';
4698 // uninstall
4699 $aurl = new moodle_url($url, array('action'=>'uninstall', 'enrol'=>$enrol));
4700 $uninstall = "<a href=\"$aurl\">$struninstall</a>";
4702 // add a row to the table
4703 $table->data[] = array($displayname, $usage, $hideshow, $updown, $settings, $uninstall);
4705 $printed[$enrol] = true;
4708 $return .= html_writer::table($table);
4709 $return .= get_string('configenrolplugins', 'enrol').'<br />'.get_string('tablenosave', 'admin');
4710 $return .= $OUTPUT->box_end();
4711 return highlight($query, $return);
4717 * Blocks manage page
4719 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4721 class admin_page_manageblocks extends admin_externalpage {
4723 * Calls parent::__construct with specific arguments
4725 public function __construct() {
4726 global $CFG;
4727 parent::__construct('manageblocks', get_string('blocksettings', 'admin'), "$CFG->wwwroot/$CFG->admin/blocks.php");
4731 * Search for a specific block
4733 * @param string $query The string to search for
4734 * @return array
4736 public function search($query) {
4737 global $CFG, $DB;
4738 if ($result = parent::search($query)) {
4739 return $result;
4742 $found = false;
4743 if ($blocks = $DB->get_records('block')) {
4744 $textlib = textlib_get_instance();
4745 foreach ($blocks as $block) {
4746 if (!file_exists("$CFG->dirroot/blocks/$block->name/")) {
4747 continue;
4749 if (strpos($block->name, $query) !== false) {
4750 $found = true;
4751 break;
4753 $strblockname = get_string('pluginname', 'block_'.$block->name);
4754 if (strpos($textlib->strtolower($strblockname), $query) !== false) {
4755 $found = true;
4756 break;
4760 if ($found) {
4761 $result = new stdClass();
4762 $result->page = $this;
4763 $result->settings = array();
4764 return array($this->name => $result);
4765 } else {
4766 return array();
4772 * Question type manage page
4774 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4776 class admin_page_manageqtypes extends admin_externalpage {
4778 * Calls parent::__construct with specific arguments
4780 public function __construct() {
4781 global $CFG;
4782 parent::__construct('manageqtypes', get_string('manageqtypes', 'admin'), "$CFG->wwwroot/$CFG->admin/qtypes.php");
4786 * Search QTYPES for the specified string
4788 * @param string $query The string to search for in QTYPES
4789 * @return array
4791 public function search($query) {
4792 global $CFG;
4793 if ($result = parent::search($query)) {
4794 return $result;
4797 $found = false;
4798 $textlib = textlib_get_instance();
4799 require_once($CFG->libdir . '/questionlib.php');
4800 global $QTYPES;
4801 foreach ($QTYPES as $qtype) {
4802 if (strpos($textlib->strtolower($qtype->local_name()), $query) !== false) {
4803 $found = true;
4804 break;
4807 if ($found) {
4808 $result = new stdClass();
4809 $result->page = $this;
4810 $result->settings = array();
4811 return array($this->name => $result);
4812 } else {
4813 return array();
4818 class admin_page_manageportfolios extends admin_externalpage {
4820 * Calls parent::__construct with specific arguments
4822 public function __construct() {
4823 global $CFG;
4824 parent::__construct('manageportfolios', get_string('manageportfolios', 'portfolio'),
4825 "$CFG->wwwroot/$CFG->admin/portfolio.php");
4829 * Searches page for the specified string.
4830 * @param string $query The string to search for
4831 * @return bool True if it is found on this page
4833 public function search($query) {
4834 global $CFG;
4835 if ($result = parent::search($query)) {
4836 return $result;
4839 $found = false;
4840 $textlib = textlib_get_instance();
4841 $portfolios = get_plugin_list('portfolio');
4842 foreach ($portfolios as $p => $dir) {
4843 if (strpos($p, $query) !== false) {
4844 $found = true;
4845 break;
4848 if (!$found) {
4849 foreach (portfolio_instances(false, false) as $instance) {
4850 $title = $instance->get('name');
4851 if (strpos($textlib->strtolower($title), $query) !== false) {
4852 $found = true;
4853 break;
4858 if ($found) {
4859 $result = new stdClass();
4860 $result->page = $this;
4861 $result->settings = array();
4862 return array($this->name => $result);
4863 } else {
4864 return array();
4869 class admin_page_managerepositories extends admin_externalpage {
4871 * Calls parent::__construct with specific arguments
4873 public function __construct() {
4874 global $CFG;
4875 parent::__construct('managerepositories', get_string('manage',
4876 'repository'), "$CFG->wwwroot/$CFG->admin/repository.php");
4880 * Searches page for the specified string.
4881 * @param string $query The string to search for
4882 * @return bool True if it is found on this page
4884 public function search($query) {
4885 global $CFG;
4886 if ($result = parent::search($query)) {
4887 return $result;
4890 $found = false;
4891 $textlib = textlib_get_instance();
4892 $repositories= get_plugin_list('repository');
4893 foreach ($repositories as $p => $dir) {
4894 if (strpos($p, $query) !== false) {
4895 $found = true;
4896 break;
4899 if (!$found) {
4900 foreach (repository::get_types() as $instance) {
4901 $title = $instance->get_typename();
4902 if (strpos($textlib->strtolower($title), $query) !== false) {
4903 $found = true;
4904 break;
4909 if ($found) {
4910 $result = new stdClass();
4911 $result->page = $this;
4912 $result->settings = array();
4913 return array($this->name => $result);
4914 } else {
4915 return array();
4921 * Special class for authentication administration.
4923 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4925 class admin_setting_manageauths extends admin_setting {
4927 * Calls parent::__construct with specific arguments
4929 public function __construct() {
4930 $this->nosave = true;
4931 parent::__construct('authsui', get_string('authsettings', 'admin'), '', '');
4935 * Always returns true
4937 * @return true
4939 public function get_setting() {
4940 return true;
4944 * Always returns true
4946 * @return true
4948 public function get_defaultsetting() {
4949 return true;
4953 * Always returns '' and doesn't write anything
4955 * @return string Always returns ''
4957 public function write_setting($data) {
4958 // do not write any setting
4959 return '';
4963 * Search to find if Query is related to auth plugin
4965 * @param string $query The string to search for
4966 * @return bool true for related false for not
4968 public function is_related($query) {
4969 if (parent::is_related($query)) {
4970 return true;
4973 $textlib = textlib_get_instance();
4974 $authsavailable = get_plugin_list('auth');
4975 foreach ($authsavailable as $auth => $dir) {
4976 if (strpos($auth, $query) !== false) {
4977 return true;
4979 $authplugin = get_auth_plugin($auth);
4980 $authtitle = $authplugin->get_title();
4981 if (strpos($textlib->strtolower($authtitle), $query) !== false) {
4982 return true;
4985 return false;
4989 * Return XHTML to display control
4991 * @param mixed $data Unused
4992 * @param string $query
4993 * @return string highlight
4995 public function output_html($data, $query='') {
4996 global $CFG, $OUTPUT;
4999 // display strings
5000 $txt = get_strings(array('authenticationplugins', 'users', 'administration',
5001 'settings', 'edit', 'name', 'enable', 'disable',
5002 'up', 'down', 'none'));
5003 $txt->updown = "$txt->up/$txt->down";
5005 $authsavailable = get_plugin_list('auth');
5006 get_enabled_auth_plugins(true); // fix the list of enabled auths
5007 if (empty($CFG->auth)) {
5008 $authsenabled = array();
5009 } else {
5010 $authsenabled = explode(',', $CFG->auth);
5013 // construct the display array, with enabled auth plugins at the top, in order
5014 $displayauths = array();
5015 $registrationauths = array();
5016 $registrationauths[''] = $txt->disable;
5017 foreach ($authsenabled as $auth) {
5018 $authplugin = get_auth_plugin($auth);
5019 /// Get the auth title (from core or own auth lang files)
5020 $authtitle = $authplugin->get_title();
5021 /// Apply titles
5022 $displayauths[$auth] = $authtitle;
5023 if ($authplugin->can_signup()) {
5024 $registrationauths[$auth] = $authtitle;
5028 foreach ($authsavailable as $auth => $dir) {
5029 if (array_key_exists($auth, $displayauths)) {
5030 continue; //already in the list
5032 $authplugin = get_auth_plugin($auth);
5033 /// Get the auth title (from core or own auth lang files)
5034 $authtitle = $authplugin->get_title();
5035 /// Apply titles
5036 $displayauths[$auth] = $authtitle;
5037 if ($authplugin->can_signup()) {
5038 $registrationauths[$auth] = $authtitle;
5042 $return = $OUTPUT->heading(get_string('actauthhdr', 'auth'), 3, 'main');
5043 $return .= $OUTPUT->box_start('generalbox authsui');
5045 $table = new html_table();
5046 $table->head = array($txt->name, $txt->enable, $txt->updown, $txt->settings);
5047 $table->align = array('left', 'center', 'center', 'center');
5048 $table->data = array();
5049 $table->attributes['class'] = 'manageauthtable generaltable';
5051 //add always enabled plugins first
5052 $displayname = "<span>".$displayauths['manual']."</span>";
5053 $settings = "<a href=\"auth_config.php?auth=manual\">{$txt->settings}</a>";
5054 //$settings = "<a href=\"settings.php?section=authsettingmanual\">{$txt->settings}</a>";
5055 $table->data[] = array($displayname, '', '', $settings);
5056 $displayname = "<span>".$displayauths['nologin']."</span>";
5057 $settings = "<a href=\"auth_config.php?auth=nologin\">{$txt->settings}</a>";
5058 $table->data[] = array($displayname, '', '', $settings);
5061 // iterate through auth plugins and add to the display table
5062 $updowncount = 1;
5063 $authcount = count($authsenabled);
5064 $url = "auth.php?sesskey=" . sesskey();
5065 foreach ($displayauths as $auth => $name) {
5066 if ($auth == 'manual' or $auth == 'nologin') {
5067 continue;
5069 // hide/show link
5070 if (in_array($auth, $authsenabled)) {
5071 $hideshow = "<a href=\"$url&amp;action=disable&amp;auth=$auth\">";
5072 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('i/hide') . "\" class=\"icon\" alt=\"disable\" /></a>";
5073 // $hideshow = "<a href=\"$url&amp;action=disable&amp;auth=$auth\"><input type=\"checkbox\" checked /></a>";
5074 $enabled = true;
5075 $displayname = "<span>$name</span>";
5077 else {
5078 $hideshow = "<a href=\"$url&amp;action=enable&amp;auth=$auth\">";
5079 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('i/show') . "\" class=\"icon\" alt=\"enable\" /></a>";
5080 // $hideshow = "<a href=\"$url&amp;action=enable&amp;auth=$auth\"><input type=\"checkbox\" /></a>";
5081 $enabled = false;
5082 $displayname = "<span class=\"dimmed_text\">$name</span>";
5085 // up/down link (only if auth is enabled)
5086 $updown = '';
5087 if ($enabled) {
5088 if ($updowncount > 1) {
5089 $updown .= "<a href=\"$url&amp;action=up&amp;auth=$auth\">";
5090 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/up') . "\" alt=\"up\" /></a>&nbsp;";
5092 else {
5093 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"icon\" alt=\"\" />&nbsp;";
5095 if ($updowncount < $authcount) {
5096 $updown .= "<a href=\"$url&amp;action=down&amp;auth=$auth\">";
5097 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/down') . "\" alt=\"down\" /></a>";
5099 else {
5100 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"icon\" alt=\"\" />";
5102 ++ $updowncount;
5105 // settings link
5106 if (file_exists($CFG->dirroot.'/auth/'.$auth.'/settings.php')) {
5107 $settings = "<a href=\"settings.php?section=authsetting$auth\">{$txt->settings}</a>";
5108 } else {
5109 $settings = "<a href=\"auth_config.php?auth=$auth\">{$txt->settings}</a>";
5112 // add a row to the table
5113 $table->data[] =array($displayname, $hideshow, $updown, $settings);
5115 $return .= html_writer::table($table);
5116 $return .= get_string('configauthenticationplugins', 'admin').'<br />'.get_string('tablenosave', 'filters');
5117 $return .= $OUTPUT->box_end();
5118 return highlight($query, $return);
5123 * Special class for authentication administration.
5125 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5127 class admin_setting_manageeditors extends admin_setting {
5129 * Calls parent::__construct with specific arguments
5131 public function __construct() {
5132 $this->nosave = true;
5133 parent::__construct('editorsui', get_string('editorsettings', 'editor'), '', '');
5137 * Always returns true, does nothing
5139 * @return true
5141 public function get_setting() {
5142 return true;
5146 * Always returns true, does nothing
5148 * @return true
5150 public function get_defaultsetting() {
5151 return true;
5155 * Always returns '', does not write anything
5157 * @return string Always returns ''
5159 public function write_setting($data) {
5160 // do not write any setting
5161 return '';
5165 * Checks if $query is one of the available editors
5167 * @param string $query The string to search for
5168 * @return bool Returns true if found, false if not
5170 public function is_related($query) {
5171 if (parent::is_related($query)) {
5172 return true;
5175 $textlib = textlib_get_instance();
5176 $editors_available = editors_get_available();
5177 foreach ($editors_available as $editor=>$editorstr) {
5178 if (strpos($editor, $query) !== false) {
5179 return true;
5181 if (strpos($textlib->strtolower($editorstr), $query) !== false) {
5182 return true;
5185 return false;
5189 * Builds the XHTML to display the control
5191 * @param string $data Unused
5192 * @param string $query
5193 * @return string
5195 public function output_html($data, $query='') {
5196 global $CFG, $OUTPUT;
5198 // display strings
5199 $txt = get_strings(array('administration', 'settings', 'edit', 'name', 'enable', 'disable',
5200 'up', 'down', 'none'));
5201 $txt->updown = "$txt->up/$txt->down";
5203 $editors_available = editors_get_available();
5204 $active_editors = explode(',', $CFG->texteditors);
5206 $active_editors = array_reverse($active_editors);
5207 foreach ($active_editors as $key=>$editor) {
5208 if (empty($editors_available[$editor])) {
5209 unset($active_editors[$key]);
5210 } else {
5211 $name = $editors_available[$editor];
5212 unset($editors_available[$editor]);
5213 $editors_available[$editor] = $name;
5216 if (empty($active_editors)) {
5217 //$active_editors = array('textarea');
5219 $editors_available = array_reverse($editors_available, true);
5220 $return = $OUTPUT->heading(get_string('acteditorshhdr', 'editor'), 3, 'main', true);
5221 $return .= $OUTPUT->box_start('generalbox editorsui');
5223 $table = new html_table();
5224 $table->head = array($txt->name, $txt->enable, $txt->updown, $txt->settings);
5225 $table->align = array('left', 'center', 'center', 'center');
5226 $table->width = '90%';
5227 $table->data = array();
5229 // iterate through auth plugins and add to the display table
5230 $updowncount = 1;
5231 $editorcount = count($active_editors);
5232 $url = "editors.php?sesskey=" . sesskey();
5233 foreach ($editors_available as $editor => $name) {
5234 // hide/show link
5235 if (in_array($editor, $active_editors)) {
5236 $hideshow = "<a href=\"$url&amp;action=disable&amp;editor=$editor\">";
5237 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('i/hide') . "\" class=\"icon\" alt=\"disable\" /></a>";
5238 // $hideshow = "<a href=\"$url&amp;action=disable&amp;editor=$editor\"><input type=\"checkbox\" checked /></a>";
5239 $enabled = true;
5240 $displayname = "<span>$name</span>";
5242 else {
5243 $hideshow = "<a href=\"$url&amp;action=enable&amp;editor=$editor\">";
5244 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('i/show') . "\" class=\"icon\" alt=\"enable\" /></a>";
5245 // $hideshow = "<a href=\"$url&amp;action=enable&amp;editor=$editor\"><input type=\"checkbox\" /></a>";
5246 $enabled = false;
5247 $displayname = "<span class=\"dimmed_text\">$name</span>";
5250 // up/down link (only if auth is enabled)
5251 $updown = '';
5252 if ($enabled) {
5253 if ($updowncount > 1) {
5254 $updown .= "<a href=\"$url&amp;action=up&amp;editor=$editor\">";
5255 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/up') . "\" alt=\"up\" /></a>&nbsp;";
5257 else {
5258 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"icon\" alt=\"\" />&nbsp;";
5260 if ($updowncount < $editorcount) {
5261 $updown .= "<a href=\"$url&amp;action=down&amp;editor=$editor\">";
5262 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/down') . "\" alt=\"down\" /></a>";
5264 else {
5265 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"icon\" alt=\"\" />";
5267 ++ $updowncount;
5270 // settings link
5271 if (file_exists($CFG->dirroot.'/lib/editor/'.$editor.'/settings.php')) {
5272 $eurl = new moodle_url('/admin/settings.php', array('section'=>'editorsettingstinymce'));
5273 $settings = "<a href='$eurl'>{$txt->settings}</a>";
5274 } else {
5275 $settings = '';
5278 // add a row to the table
5279 $table->data[] =array($displayname, $hideshow, $updown, $settings);
5281 $return .= html_writer::table($table);
5282 $return .= get_string('configeditorplugins', 'editor').'<br />'.get_string('tablenosave', 'admin');
5283 $return .= $OUTPUT->box_end();
5284 return highlight($query, $return);
5289 * Special class for license administration.
5291 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5293 class admin_setting_managelicenses extends admin_setting {
5295 * Calls parent::__construct with specific arguments
5297 public function __construct() {
5298 $this->nosave = true;
5299 parent::__construct('licensesui', get_string('licensesettings', 'admin'), '', '');
5303 * Always returns true, does nothing
5305 * @return true
5307 public function get_setting() {
5308 return true;
5312 * Always returns true, does nothing
5314 * @return true
5316 public function get_defaultsetting() {
5317 return true;
5321 * Always returns '', does not write anything
5323 * @return string Always returns ''
5325 public function write_setting($data) {
5326 // do not write any setting
5327 return '';
5331 * Builds the XHTML to display the control
5333 * @param string $data Unused
5334 * @param string $query
5335 * @return string
5337 public function output_html($data, $query='') {
5338 global $CFG, $OUTPUT;
5339 require_once($CFG->libdir . '/licenselib.php');
5340 $url = "licenses.php?sesskey=" . sesskey();
5342 // display strings
5343 $txt = get_strings(array('administration', 'settings', 'name', 'enable', 'disable', 'none'));
5344 $licenses = license_manager::get_licenses();
5346 $return = $OUTPUT->heading(get_string('availablelicenses', 'admin'), 3, 'main', true);
5348 $return .= $OUTPUT->box_start('generalbox editorsui');
5350 $table = new html_table();
5351 $table->head = array($txt->name, $txt->enable);
5352 $table->align = array('left', 'center');
5353 $table->width = '100%';
5354 $table->data = array();
5356 foreach ($licenses as $value) {
5357 $displayname = html_writer::link($value->source, get_string($value->shortname, 'license'), array('target'=>'_blank'));
5359 if ($value->enabled == 1) {
5360 $hideshow = html_writer::link($url.'&action=disable&license='.$value->shortname,
5361 html_writer::tag('img', '', array('src'=>$OUTPUT->pix_url('i/hide'), 'class'=>'icon', 'alt'=>'disable')));
5362 } else {
5363 $hideshow = html_writer::link($url.'&action=enable&license='.$value->shortname,
5364 html_writer::tag('img', '', array('src'=>$OUTPUT->pix_url('i/show'), 'class'=>'icon', 'alt'=>'enable')));
5367 if ($value->shortname == $CFG->sitedefaultlicense) {
5368 $displayname .= ' '.html_writer::tag('img', '', array('src'=>$OUTPUT->pix_url('i/lock'), 'class'=>'icon', 'alt'=>get_string('default'), 'title'=>get_string('default')));
5369 $hideshow = '';
5372 $enabled = true;
5374 $table->data[] =array($displayname, $hideshow);
5376 $return .= html_writer::table($table);
5377 $return .= $OUTPUT->box_end();
5378 return highlight($query, $return);
5382 * Special class for filter administration.
5384 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5386 class admin_page_managefilters extends admin_externalpage {
5388 * Calls parent::__construct with specific arguments
5390 public function __construct() {
5391 global $CFG;
5392 parent::__construct('managefilters', get_string('filtersettings', 'admin'), "$CFG->wwwroot/$CFG->admin/filters.php");
5396 * Searches all installed filters for specified filter
5398 * @param string $query The filter(string) to search for
5399 * @param string $query
5401 public function search($query) {
5402 global $CFG;
5403 if ($result = parent::search($query)) {
5404 return $result;
5407 $found = false;
5408 $filternames = filter_get_all_installed();
5409 $textlib = textlib_get_instance();
5410 foreach ($filternames as $path => $strfiltername) {
5411 if (strpos($textlib->strtolower($strfiltername), $query) !== false) {
5412 $found = true;
5413 break;
5415 list($type, $filter) = explode('/', $path);
5416 if (strpos($filter, $query) !== false) {
5417 $found = true;
5418 break;
5422 if ($found) {
5423 $result = new stdClass;
5424 $result->page = $this;
5425 $result->settings = array();
5426 return array($this->name => $result);
5427 } else {
5428 return array();
5434 * Initialise admin page - this function does require login and permission
5435 * checks specified in page definition.
5437 * This function must be called on each admin page before other code.
5439 * @global moodle_page $PAGE
5441 * @param string $section name of page
5442 * @param string $extrabutton extra HTML that is added after the blocks editing on/off button.
5443 * @param array $extraurlparams an array paramname => paramvalue, or parameters that need to be
5444 * added to the turn blocks editing on/off form, so this page reloads correctly.
5445 * @param string $actualurl if the actual page being viewed is not the normal one for this
5446 * page (e.g. admin/roles/allowassin.php, instead of admin/roles/manage.php, you can pass the alternate URL here.
5447 * @param array $options Additional options that can be specified for page setup.
5448 * pagelayout - This option can be used to set a specific pagelyaout, admin is default.
5450 function admin_externalpage_setup($section, $extrabutton = '', array $extraurlparams = null, $actualurl = '', array $options = array()) {
5451 global $CFG, $PAGE, $USER, $SITE, $OUTPUT;
5453 $PAGE->set_context(null); // hack - set context to something, by default to system context
5455 $site = get_site();
5456 require_login();
5458 $adminroot = admin_get_root(false, false); // settings not required for external pages
5459 $extpage = $adminroot->locate($section, true);
5461 if (empty($extpage) or !($extpage instanceof admin_externalpage)) {
5462 print_error('sectionerror', 'admin', "$CFG->wwwroot/$CFG->admin/");
5463 die;
5466 // this eliminates our need to authenticate on the actual pages
5467 if (!$extpage->check_access()) {
5468 print_error('accessdenied', 'admin');
5469 die;
5472 if (!empty($options['pagelayout'])) {
5473 // A specific page layout has been requested.
5474 $PAGE->set_pagelayout($options['pagelayout']);
5475 } else if ($section === 'upgradesettings') {
5476 $PAGE->set_pagelayout('maintenance');
5477 } else {
5478 $PAGE->set_pagelayout('admin');
5481 // $PAGE->set_extra_button($extrabutton); TODO
5483 if (!$actualurl) {
5484 $actualurl = $extpage->url;
5487 $PAGE->set_url($actualurl, $extraurlparams);
5488 if (strpos($PAGE->pagetype, 'admin-') !== 0) {
5489 $PAGE->set_pagetype('admin-' . $PAGE->pagetype);
5492 if (empty($SITE->fullname) || empty($SITE->shortname)) {
5493 // During initial install.
5494 $strinstallation = get_string('installation', 'install');
5495 $strsettings = get_string('settings');
5496 $PAGE->navbar->add($strsettings);
5497 $PAGE->set_title($strinstallation);
5498 $PAGE->set_heading($strinstallation);
5499 $PAGE->set_cacheable(false);
5500 return;
5503 // Locate the current item on the navigation and make it active when found.
5504 $path = $extpage->path;
5505 $node = $PAGE->settingsnav;
5506 while ($node && count($path) > 0) {
5507 $node = $node->get(array_pop($path));
5509 if ($node) {
5510 $node->make_active();
5513 // Normal case.
5514 $adminediting = optional_param('adminedit', -1, PARAM_BOOL);
5515 if ($PAGE->user_allowed_editing() && $adminediting != -1) {
5516 $USER->editing = $adminediting;
5519 $visiblepathtosection = array_reverse($extpage->visiblepath);
5521 if ($PAGE->user_allowed_editing()) {
5522 if ($PAGE->user_is_editing()) {
5523 $caption = get_string('blockseditoff');
5524 $url = new moodle_url($PAGE->url, array('adminedit'=>'0'));
5525 } else {
5526 $caption = get_string('blocksediton');
5527 $url = new moodle_url($PAGE->url, array('adminedit'=>'1'));
5529 $PAGE->set_button($OUTPUT->single_button($url, $caption, 'get'));
5532 $PAGE->set_title("$SITE->shortname: " . implode(": ", $visiblepathtosection));
5533 $PAGE->set_heading($SITE->fullname);
5535 // prevent caching in nav block
5536 $PAGE->navigation->clear_cache();
5540 * Returns the reference to admin tree root
5542 * @return object admin_roow object
5544 function admin_get_root($reload=false, $requirefulltree=true) {
5545 global $CFG, $DB, $OUTPUT;
5547 static $ADMIN = NULL;
5549 if (is_null($ADMIN)) {
5550 // create the admin tree!
5551 $ADMIN = new admin_root($requirefulltree);
5554 if ($reload or ($requirefulltree and !$ADMIN->fulltree)) {
5555 $ADMIN->purge_children($requirefulltree);
5558 if (!$ADMIN->loaded) {
5559 // we process this file first to create categories first and in correct order
5560 require($CFG->dirroot.'/'.$CFG->admin.'/settings/top.php');
5562 // now we process all other files in admin/settings to build the admin tree
5563 foreach (glob($CFG->dirroot.'/'.$CFG->admin.'/settings/*.php') as $file) {
5564 if ($file == $CFG->dirroot.'/'.$CFG->admin.'/settings/top.php') {
5565 continue;
5567 if ($file == $CFG->dirroot.'/'.$CFG->admin.'/settings/plugins.php') {
5568 // plugins are loaded last - they may insert pages anywhere
5569 continue;
5571 require($file);
5573 require($CFG->dirroot.'/'.$CFG->admin.'/settings/plugins.php');
5575 $ADMIN->loaded = true;
5578 return $ADMIN;
5581 /// settings utility functions
5584 * This function applies default settings.
5586 * @param object $node, NULL means complete tree, null by default
5587 * @param bool $unconditional if true overrides all values with defaults, null buy default
5589 function admin_apply_default_settings($node=NULL, $unconditional=true) {
5590 global $CFG;
5592 if (is_null($node)) {
5593 $node = admin_get_root(true, true);
5596 if ($node instanceof admin_category) {
5597 $entries = array_keys($node->children);
5598 foreach ($entries as $entry) {
5599 admin_apply_default_settings($node->children[$entry], $unconditional);
5602 } else if ($node instanceof admin_settingpage) {
5603 foreach ($node->settings as $setting) {
5604 if (!$unconditional and !is_null($setting->get_setting())) {
5605 //do not override existing defaults
5606 continue;
5608 $defaultsetting = $setting->get_defaultsetting();
5609 if (is_null($defaultsetting)) {
5610 // no value yet - default maybe applied after admin user creation or in upgradesettings
5611 continue;
5613 $setting->write_setting($defaultsetting);
5619 * Store changed settings, this function updates the errors variable in $ADMIN
5621 * @param object $formdata from form
5622 * @return int number of changed settings
5624 function admin_write_settings($formdata) {
5625 global $CFG, $SITE, $DB;
5627 $olddbsessions = !empty($CFG->dbsessions);
5628 $formdata = (array)$formdata;
5630 $data = array();
5631 foreach ($formdata as $fullname=>$value) {
5632 if (strpos($fullname, 's_') !== 0) {
5633 continue; // not a config value
5635 $data[$fullname] = $value;
5638 $adminroot = admin_get_root();
5639 $settings = admin_find_write_settings($adminroot, $data);
5641 $count = 0;
5642 foreach ($settings as $fullname=>$setting) {
5643 $original = serialize($setting->get_setting()); // comparison must work for arrays too
5644 $error = $setting->write_setting($data[$fullname]);
5645 if ($error !== '') {
5646 $adminroot->errors[$fullname] = new stdClass();
5647 $adminroot->errors[$fullname]->data = $data[$fullname];
5648 $adminroot->errors[$fullname]->id = $setting->get_id();
5649 $adminroot->errors[$fullname]->error = $error;
5651 if ($original !== serialize($setting->get_setting())) {
5652 $count++;
5653 $callbackfunction = $setting->updatedcallback;
5654 if (function_exists($callbackfunction)) {
5655 $callbackfunction($fullname);
5660 if ($olddbsessions != !empty($CFG->dbsessions)) {
5661 require_logout();
5664 // Now update $SITE - just update the fields, in case other people have a
5665 // a reference to it (e.g. $PAGE, $COURSE).
5666 $newsite = $DB->get_record('course', array('id'=>$SITE->id));
5667 foreach (get_object_vars($newsite) as $field => $value) {
5668 $SITE->$field = $value;
5671 // now reload all settings - some of them might depend on the changed
5672 admin_get_root(true);
5673 return $count;
5677 * Internal recursive function - finds all settings from submitted form
5679 * @param object $node Instance of admin_category, or admin_settingpage
5680 * @param array $data
5681 * @return array
5683 function admin_find_write_settings($node, $data) {
5684 $return = array();
5686 if (empty($data)) {
5687 return $return;
5690 if ($node instanceof admin_category) {
5691 $entries = array_keys($node->children);
5692 foreach ($entries as $entry) {
5693 $return = array_merge($return, admin_find_write_settings($node->children[$entry], $data));
5696 } else if ($node instanceof admin_settingpage) {
5697 foreach ($node->settings as $setting) {
5698 $fullname = $setting->get_full_name();
5699 if (array_key_exists($fullname, $data)) {
5700 $return[$fullname] = $setting;
5706 return $return;
5710 * Internal function - prints the search results
5712 * @param string $query String to search for
5713 * @return string empty or XHTML
5715 function admin_search_settings_html($query) {
5716 global $CFG, $OUTPUT;
5718 $textlib = textlib_get_instance();
5719 if ($textlib->strlen($query) < 2) {
5720 return '';
5722 $query = $textlib->strtolower($query);
5724 $adminroot = admin_get_root();
5725 $findings = $adminroot->search($query);
5726 $return = '';
5727 $savebutton = false;
5729 foreach ($findings as $found) {
5730 $page = $found->page;
5731 $settings = $found->settings;
5732 if ($page->is_hidden()) {
5733 // hidden pages are not displayed in search results
5734 continue;
5736 if ($page instanceof admin_externalpage) {
5737 $return .= $OUTPUT->heading(get_string('searchresults','admin').' - <a href="'.$page->url.'">'.highlight($query, $page->visiblename).'</a>', 2, 'main');
5738 } else if ($page instanceof admin_settingpage) {
5739 $return .= $OUTPUT->heading(get_string('searchresults','admin').' - <a href="'.$CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section='.$page->name.'">'.highlight($query, $page->visiblename).'</a>', 2, 'main');
5740 } else {
5741 continue;
5743 if (!empty($settings)) {
5744 $return .= '<fieldset class="adminsettings">'."\n";
5745 foreach ($settings as $setting) {
5746 if (empty($setting->nosave)) {
5747 $savebutton = true;
5749 $return .= '<div class="clearer"><!-- --></div>'."\n";
5750 $fullname = $setting->get_full_name();
5751 if (array_key_exists($fullname, $adminroot->errors)) {
5752 $data = $adminroot->errors[$fullname]->data;
5753 } else {
5754 $data = $setting->get_setting();
5755 // do not use defaults if settings not available - upgradesettings handles the defaults!
5757 $return .= $setting->output_html($data, $query);
5759 $return .= '</fieldset>';
5763 if ($savebutton) {
5764 $return .= '<div class="form-buttons"><input class="form-submit" type="submit" value="'.get_string('savechanges','admin').'" /></div>';
5767 return $return;
5771 * Internal function - returns arrays of html pages with uninitialised settings
5773 * @param object $node Instance of admin_category or admin_settingpage
5774 * @return array
5776 function admin_output_new_settings_by_page($node) {
5777 global $OUTPUT;
5778 $return = array();
5780 if ($node instanceof admin_category) {
5781 $entries = array_keys($node->children);
5782 foreach ($entries as $entry) {
5783 $return += admin_output_new_settings_by_page($node->children[$entry]);
5786 } else if ($node instanceof admin_settingpage) {
5787 $newsettings = array();
5788 foreach ($node->settings as $setting) {
5789 if (is_null($setting->get_setting())) {
5790 $newsettings[] = $setting;
5793 if (count($newsettings) > 0) {
5794 $adminroot = admin_get_root();
5795 $page = $OUTPUT->heading(get_string('upgradesettings','admin').' - '.$node->visiblename, 2, 'main');
5796 $page .= '<fieldset class="adminsettings">'."\n";
5797 foreach ($newsettings as $setting) {
5798 $fullname = $setting->get_full_name();
5799 if (array_key_exists($fullname, $adminroot->errors)) {
5800 $data = $adminroot->errors[$fullname]->data;
5801 } else {
5802 $data = $setting->get_setting();
5803 if (is_null($data)) {
5804 $data = $setting->get_defaultsetting();
5807 $page .= '<div class="clearer"><!-- --></div>'."\n";
5808 $page .= $setting->output_html($data);
5810 $page .= '</fieldset>';
5811 $return[$node->name] = $page;
5815 return $return;
5819 * Format admin settings
5821 * @param object $setting
5822 * @param string $title label element
5823 * @param string $form form fragment, html code - not highlighted automatically
5824 * @param string $description
5825 * @param bool $label link label to id, true by default
5826 * @param string $warning warning text
5827 * @param sting $defaultinfo defaults info, null means nothing, '' is converted to "Empty" string, defaults to null
5828 * @param string $query search query to be highlighted
5829 * @return string XHTML
5831 function format_admin_setting($setting, $title='', $form='', $description='', $label=true, $warning='', $defaultinfo=NULL, $query='') {
5832 global $CFG;
5834 $name = empty($setting->plugin) ? $setting->name : "$setting->plugin | $setting->name";
5835 $fullname = $setting->get_full_name();
5837 // sometimes the id is not id_s_name, but id_s_name_m or something, and this does not validate
5838 if ($label) {
5839 $labelfor = 'for = "'.$setting->get_id().'"';
5840 } else {
5841 $labelfor = '';
5844 $override = '';
5845 if (empty($setting->plugin)) {
5846 if (array_key_exists($setting->name, $CFG->config_php_settings)) {
5847 $override = '<div class="form-overridden">'.get_string('configoverride', 'admin').'</div>';
5849 } else {
5850 if (array_key_exists($setting->plugin, $CFG->forced_plugin_settings) and array_key_exists($setting->name, $CFG->forced_plugin_settings[$setting->plugin])) {
5851 $override = '<div class="form-overridden">'.get_string('configoverride', 'admin').'</div>';
5855 if ($warning !== '') {
5856 $warning = '<div class="form-warning">'.$warning.'</div>';
5859 if (is_null($defaultinfo)) {
5860 $defaultinfo = '';
5861 } else {
5862 if ($defaultinfo === '') {
5863 $defaultinfo = get_string('emptysettingvalue', 'admin');
5865 $defaultinfo = highlight($query, nl2br(s($defaultinfo)));
5866 $defaultinfo = '<div class="form-defaultinfo">'.get_string('defaultsettinginfo', 'admin', $defaultinfo).'</div>';
5870 $str = '
5871 <div class="form-item clearfix" id="admin-'.$setting->name.'">
5872 <div class="form-label">
5873 <label '.$labelfor.'>'.highlightfast($query, $title).'<span class="form-shortname">'.highlightfast($query, $name).'</span>
5874 '.$override.$warning.'
5875 </label>
5876 </div>
5877 <div class="form-setting">'.$form.$defaultinfo.'</div>
5878 <div class="form-description">'.highlight($query, markdown_to_html($description)).'</div>
5879 </div>';
5881 $adminroot = admin_get_root();
5882 if (array_key_exists($fullname, $adminroot->errors)) {
5883 $str = '<fieldset class="error"><legend>'.$adminroot->errors[$fullname]->error.'</legend>'.$str.'</fieldset>';
5886 return $str;
5890 * Based on find_new_settings{@link ()} in upgradesettings.php
5891 * Looks to find any admin settings that have not been initialized. Returns 1 if it finds any.
5893 * @param object $node Instance of admin_category, or admin_settingpage
5894 * @return boolean true if any settings haven't been initialised, false if they all have
5896 function any_new_admin_settings($node) {
5898 if ($node instanceof admin_category) {
5899 $entries = array_keys($node->children);
5900 foreach ($entries as $entry) {
5901 if (any_new_admin_settings($node->children[$entry])) {
5902 return true;
5906 } else if ($node instanceof admin_settingpage) {
5907 foreach ($node->settings as $setting) {
5908 if ($setting->get_setting() === NULL) {
5909 return true;
5914 return false;
5919 * Moved from admin/replace.php so that we can use this in cron
5921 * @param string $search string to look for
5922 * @param string $replace string to replace
5923 * @return bool success or fail
5925 function db_replace($search, $replace) {
5927 global $DB, $CFG;
5929 /// Turn off time limits, sometimes upgrades can be slow.
5930 @set_time_limit(0);
5932 if (!$tables = $DB->get_tables() ) { // No tables yet at all.
5933 return false;
5935 foreach ($tables as $table) {
5937 if (in_array($table, array('config'))) { // Don't process these
5938 continue;
5941 if ($columns = $DB->get_columns($table)) {
5942 $DB->set_debug(true);
5943 foreach ($columns as $column => $data) {
5944 if (in_array($data->meta_type, array('C', 'X'))) { // Text stuff only
5945 $DB->execute("UPDATE {".$table."} SET $column = REPLACE($column, ?, ?)", array($search, $replace));
5948 $DB->set_debug(false);
5952 return true;
5956 * Prints tables of detected plugins, one table per plugin type,
5957 * and prints whether they are part of the standard Moodle
5958 * distribution or not.
5960 function print_plugin_tables() {
5961 global $DB;
5962 $plugins_standard = array();
5963 $plugins_standard['mod'] = array('assignment',
5964 'chat',
5965 'choice',
5966 'data',
5967 'feedback',
5968 'folder',
5969 'forum',
5970 'glossary',
5971 'imscp',
5972 'label',
5973 'lesson',
5974 'page',
5975 'quiz',
5976 'resource',
5977 'scorm',
5978 'survey',
5979 'url',
5980 'wiki',
5981 'workshop');
5983 $plugins_standard['blocks'] = array('activity_modules',
5984 'admin_bookmarks',
5985 'blog_menu',
5986 'blog_recent',
5987 'blog_tags',
5988 'calendar_month',
5989 'calendar_upcoming',
5990 'comments',
5991 'community',
5992 'completionstatus',
5993 'course_list',
5994 'course_overview',
5995 'course_summary',
5996 'feedback',
5997 'glossary_random',
5998 'html',
5999 'login',
6000 'mentees',
6001 'messages',
6002 'mnet_hosts',
6003 'myprofile',
6004 'navigation',
6005 'news_items',
6006 'online_users',
6007 'participants',
6008 'private_files',
6009 'quiz_results',
6010 'recent_activity',
6011 'rss_client',
6012 'search',
6013 'search_forums',
6014 'section_links',
6015 'selfcompletion',
6016 'settings',
6017 'site_main_menu',
6018 'social_activities',
6019 'tag_flickr',
6020 'tag_youtube',
6021 'tags');
6023 $plugins_standard['filter'] = array('activitynames',
6024 'algebra',
6025 'censor',
6026 'emailprotect',
6027 'emoticon',
6028 'filter',
6029 'mediaplugin',
6030 'multilang',
6031 'tex',
6032 'tidy',
6033 'urltolink');
6035 $plugins_installed = array();
6036 $installed_mods = $DB->get_records('modules', null, 'name');
6037 $installed_blocks = $DB->get_records('block', null, 'name');
6039 foreach($installed_mods as $mod) {
6040 $plugins_installed['mod'][] = $mod->name;
6043 foreach($installed_blocks as $block) {
6044 $plugins_installed['blocks'][] = $block->name;
6046 $plugins_installed['filter'] = array();
6048 $plugins_ondisk = array();
6049 $plugins_ondisk['mod'] = array_keys(get_plugin_list('mod'));
6050 $plugins_ondisk['blocks'] = array_keys(get_plugin_list('block'));
6051 $plugins_ondisk['filter'] = array_keys(get_plugin_list('filter'));
6053 $strstandard = get_string('standard');
6054 $strnonstandard = get_string('nonstandard');
6055 $strmissingfromdisk = '(' . get_string('missingfromdisk') . ')';
6056 $strabouttobeinstalled = '(' . get_string('abouttobeinstalled') . ')';
6058 $html = '';
6060 $html .= '<table class="generaltable plugincheckwrapper" cellspacing="4" cellpadding="1"><tr valign="top">';
6062 foreach ($plugins_ondisk as $cat => $list_ondisk) {
6063 if ($cat == 'mod') {
6064 $strcaption = get_string('activitymodule');
6065 } elseif ($cat == 'filter') {
6066 $strcaption = get_string('managefilters');
6067 } else {
6068 $strcaption = get_string($cat);
6071 $html .= '<td><table class="plugincompattable generaltable boxaligncenter" cellspacing="1" cellpadding="5" '
6072 . 'id="' . $cat . 'compattable" summary="compatibility table"><caption>' . $strcaption . '</caption>' . "\n";
6073 $html .= '<tr class="r0"><th class="header c0">' . get_string('directory') . "</th>\n"
6074 . '<th class="header c1">' . get_string('name') . "</th>\n"
6075 . '<th class="header c2">' . get_string('status') . "</th>\n</tr>\n";
6077 $row = 1;
6079 foreach ($list_ondisk as $k => $plugin) {
6080 $status = 'ok';
6081 $standard = 'standard';
6082 $note = '';
6084 if (!in_array($plugin, $plugins_standard[$cat])) {
6085 $standard = 'nonstandard';
6086 $status = 'warning';
6089 // Get real name and full path of plugin
6090 $plugin_name = "[[$plugin]]";
6092 $plugin_path = "$cat/$plugin";
6094 $plugin_name = get_plugin_name($plugin, $cat);
6096 // Determine if the plugin is about to be installed
6097 if ($cat != 'filter' && !in_array($plugin, $plugins_installed[$cat])) {
6098 $note = $strabouttobeinstalled;
6099 $plugin_name = $plugin;
6102 $html .= "<tr class=\"r$row\">\n"
6103 . "<td class=\"cell c0\">$plugin_path</td>\n"
6104 . "<td class=\"cell c1\">$plugin_name</td>\n"
6105 . "<td class=\"$standard $status cell c2\">" . ${'str' . $standard} . " $note</td>\n</tr>\n";
6106 $row++;
6108 // If the plugin was both on disk and in the db, unset the value from the installed plugins list
6109 if ($key = array_search($plugin, $plugins_installed[$cat])) {
6110 unset($plugins_installed[$cat][$key]);
6114 // If there are plugins left in the plugins_installed list, it means they are missing from disk
6115 foreach ($plugins_installed[$cat] as $k => $missing_plugin) {
6116 // Make sure the plugin really is missing from disk
6117 if (!in_array($missing_plugin, $plugins_ondisk[$cat])) {
6118 $standard = 'standard';
6119 $status = 'warning';
6121 if (!in_array($missing_plugin, $plugins_standard[$cat])) {
6122 $standard = 'nonstandard';
6125 $plugin_name = $missing_plugin;
6126 $html .= "<tr class=\"r$row\">\n"
6127 . "<td class=\"cell c0\">?</td>\n"
6128 . "<td class=\"cell c1\">$plugin_name</td>\n"
6129 . "<td class=\"$standard $status cell c2\">" . ${'str' . $standard} . " $strmissingfromdisk</td>\n</tr>\n";
6130 $row++;
6134 $html .= '</table></td>';
6137 $html .= '</tr></table><br />';
6139 echo $html;
6143 * Manage repository settings
6145 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
6147 class admin_setting_managerepository extends admin_setting {
6148 /** @var string */
6149 private $baseurl;
6152 * calls parent::__construct with specific arguments
6154 public function __construct() {
6155 global $CFG;
6156 parent::__construct('managerepository', get_string('manage', 'repository'), '', '');
6157 $this->baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/repository.php?sesskey=' . sesskey();
6161 * Always returns true, does nothing
6163 * @return true
6165 public function get_setting() {
6166 return true;
6170 * Always returns true does nothing
6172 * @return true
6174 public function get_defaultsetting() {
6175 return true;
6179 * Always returns s_managerepository
6181 * @return string Always return 's_managerepository'
6183 public function get_full_name() {
6184 return 's_managerepository';
6188 * Always returns '' doesn't do anything
6190 public function write_setting($data) {
6191 $url = $this->baseurl . '&amp;new=' . $data;
6192 return '';
6193 // TODO
6194 // Should not use redirect and exit here
6195 // Find a better way to do this.
6196 // redirect($url);
6197 // exit;
6201 * Searches repository plugins for one that matches $query
6203 * @param string $query The string to search for
6204 * @return bool true if found, false if not
6206 public function is_related($query) {
6207 if (parent::is_related($query)) {
6208 return true;
6211 $textlib = textlib_get_instance();
6212 $repositories= get_plugin_list('repository');
6213 foreach ($repositories as $p => $dir) {
6214 if (strpos($p, $query) !== false) {
6215 return true;
6218 foreach (repository::get_types() as $instance) {
6219 $title = $instance->get_typename();
6220 if (strpos($textlib->strtolower($title), $query) !== false) {
6221 return true;
6224 return false;
6228 * Helper function that generates a moodle_url object
6229 * relevant to the repository
6232 function repository_action_url($repository) {
6233 return new moodle_url($this->baseurl, array('sesskey'=>sesskey(), 'repos'=>$repository));
6237 * Builds XHTML to display the control
6239 * @param string $data Unused
6240 * @param string $query
6241 * @return string XHTML
6243 public function output_html($data, $query='') {
6244 global $CFG, $USER, $OUTPUT;
6246 // Get strings that are used
6247 $strshow = get_string('on', 'repository');
6248 $strhide = get_string('off', 'repository');
6249 $strdelete = get_string('disabled', 'repository');
6251 $actionchoicesforexisting = array(
6252 'show' => $strshow,
6253 'hide' => $strhide,
6254 'delete' => $strdelete
6257 $actionchoicesfornew = array(
6258 'newon' => $strshow,
6259 'newoff' => $strhide,
6260 'delete' => $strdelete
6263 $return = '';
6264 $return .= $OUTPUT->box_start('generalbox');
6266 // Set strings that are used multiple times
6267 $settingsstr = get_string('settings');
6268 $disablestr = get_string('disable');
6270 // Table to list plug-ins
6271 $table = new html_table();
6272 $table->head = array(get_string('name'), get_string('isactive', 'repository'), get_string('order'), $settingsstr);
6273 $table->align = array('left', 'center', 'center', 'center', 'center');
6274 $table->data = array();
6276 // Get list of used plug-ins
6277 $instances = repository::get_types();
6278 if (!empty($instances)) {
6279 // Array to store plugins being used
6280 $alreadyplugins = array();
6281 $totalinstances = count($instances);
6282 $updowncount = 1;
6283 foreach ($instances as $i) {
6284 $settings = '';
6285 $typename = $i->get_typename();
6286 // Display edit link only if you can config the type or if it has multiple instances (e.g. has instance config)
6287 $typeoptionnames = repository::static_function($typename, 'get_type_option_names');
6288 $instanceoptionnames = repository::static_function($typename, 'get_instance_option_names');
6290 if (!empty($typeoptionnames) || !empty($instanceoptionnames)) {
6291 // Calculate number of instances in order to display them for the Moodle administrator
6292 if (!empty($instanceoptionnames)) {
6293 $params = array();
6294 $params['context'] = array(get_system_context());
6295 $params['onlyvisible'] = false;
6296 $params['type'] = $typename;
6297 $admininstancenumber = count(repository::static_function($typename, 'get_instances', $params));
6298 // site instances
6299 $admininstancenumbertext = get_string('instancesforsite', 'repository', $admininstancenumber);
6300 $params['context'] = array();
6301 $instances = repository::static_function($typename, 'get_instances', $params);
6302 $courseinstances = array();
6303 $userinstances = array();
6305 foreach ($instances as $instance) {
6306 if ($instance->context->contextlevel == CONTEXT_COURSE) {
6307 $courseinstances[] = $instance;
6308 } else if ($instance->context->contextlevel == CONTEXT_USER) {
6309 $userinstances[] = $instance;
6312 // course instances
6313 $instancenumber = count($courseinstances);
6314 $courseinstancenumbertext = get_string('instancesforcourses', 'repository', $instancenumber);
6316 // user private instances
6317 $instancenumber = count($userinstances);
6318 $userinstancenumbertext = get_string('instancesforusers', 'repository', $instancenumber);
6319 } else {
6320 $admininstancenumbertext = "";
6321 $courseinstancenumbertext = "";
6322 $userinstancenumbertext = "";
6325 $settings .= '<a href="' . $this->baseurl . '&amp;action=edit&amp;repos=' . $typename . '">' . $settingsstr .'</a>';
6327 $settings .= $OUTPUT->container_start('mdl-left');
6328 $settings .= '<br/>';
6329 $settings .= $admininstancenumbertext;
6330 $settings .= '<br/>';
6331 $settings .= $courseinstancenumbertext;
6332 $settings .= '<br/>';
6333 $settings .= $userinstancenumbertext;
6334 $settings .= $OUTPUT->container_end();
6336 // Get the current visibility
6337 if ($i->get_visible()) {
6338 $currentaction = 'show';
6339 } else {
6340 $currentaction = 'hide';
6343 $select = new single_select($this->repository_action_url($typename, 'repos'), 'action', $actionchoicesforexisting, $currentaction, null, 'applyto' . basename($typename));
6345 // Display up/down link
6346 $updown = '';
6347 $spacer = $OUTPUT->spacer(array('height'=>15, 'width'=>15)); // should be done with CSS instead
6349 if ($updowncount > 1) {
6350 $updown .= "<a href=\"$this->baseurl&amp;action=moveup&amp;repos=".$typename."\">";
6351 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/up') . "\" alt=\"up\" /></a>&nbsp;";
6353 else {
6354 $updown .= $spacer;
6356 if ($updowncount < $totalinstances) {
6357 $updown .= "<a href=\"$this->baseurl&amp;action=movedown&amp;repos=".$typename."\">";
6358 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/down') . "\" alt=\"down\" /></a>";
6360 else {
6361 $updown .= $spacer;
6364 $updowncount++;
6366 $table->data[] = array($i->get_readablename(), $OUTPUT->render($select), $updown, $settings);
6368 if (!in_array($typename, $alreadyplugins)) {
6369 $alreadyplugins[] = $typename;
6374 // Get all the plugins that exist on disk
6375 $plugins = get_plugin_list('repository');
6376 if (!empty($plugins)) {
6377 foreach ($plugins as $plugin => $dir) {
6378 // Check that it has not already been listed
6379 if (!in_array($plugin, $alreadyplugins)) {
6380 $select = new single_select($this->repository_action_url($plugin, 'repos'), 'action', $actionchoicesfornew, 'delete', null, 'applyto' . basename($plugin));
6381 $table->data[] = array(get_string('pluginname', 'repository_'.$plugin), $OUTPUT->render($select), '', '');
6386 $return .= html_writer::table($table);
6387 $return .= $OUTPUT->box_end();
6388 return highlight($query, $return);
6393 * Special class for management of external services
6395 * @author Petr Skoda (skodak)
6397 class admin_setting_manageexternalservices extends admin_setting {
6399 * Calls parent::__construct with specific arguments
6401 public function __construct() {
6402 $this->nosave = true;
6403 parent::__construct('webservicesui', get_string('externalservices', 'webservice'), '', '');
6407 * Always returns true, does nothing
6409 * @return true
6411 public function get_setting() {
6412 return true;
6416 * Always returns true, does nothing
6418 * @return true
6420 public function get_defaultsetting() {
6421 return true;
6425 * Always returns '', does not write anything
6427 * @return string Always returns ''
6429 public function write_setting($data) {
6430 // do not write any setting
6431 return '';
6435 * Checks if $query is one of the available external services
6437 * @param string $query The string to search for
6438 * @return bool Returns true if found, false if not
6440 public function is_related($query) {
6441 global $DB;
6443 if (parent::is_related($query)) {
6444 return true;
6447 $textlib = textlib_get_instance();
6448 $services = $DB->get_records('external_services', array(), 'id, name');
6449 foreach ($services as $service) {
6450 if (strpos($textlib->strtolower($service->name), $query) !== false) {
6451 return true;
6454 return false;
6458 * Builds the XHTML to display the control
6460 * @param string $data Unused
6461 * @param string $query
6462 * @return string
6464 public function output_html($data, $query='') {
6465 global $CFG, $OUTPUT, $DB;
6467 // display strings
6468 $stradministration = get_string('administration');
6469 $stredit = get_string('edit');
6470 $strservice = get_string('externalservice', 'webservice');
6471 $strdelete = get_string('delete');
6472 $strplugin = get_string('plugin', 'admin');
6473 $stradd = get_string('add');
6474 $strfunctions = get_string('functions', 'webservice');
6475 $strusers = get_string('users');
6476 $strserviceusers = get_string('serviceusers', 'webservice');
6478 $esurl = "$CFG->wwwroot/$CFG->admin/webservice/service.php";
6479 $efurl = "$CFG->wwwroot/$CFG->admin/webservice/service_functions.php";
6480 $euurl = "$CFG->wwwroot/$CFG->admin/webservice/service_users.php";
6482 // built in services
6483 $services = $DB->get_records_select('external_services', 'component IS NOT NULL', null, 'name');
6484 $return = "";
6485 if (!empty($services)) {
6486 $return .= $OUTPUT->heading(get_string('servicesbuiltin', 'webservice'), 3, 'main');
6490 $table = new html_table();
6491 $table->head = array($strservice, $strplugin, $strfunctions, $strusers, $stredit);
6492 $table->align = array('left', 'left', 'center', 'center', 'center');
6493 $table->size = array('30%', '20%', '20%', '20%', '10%');
6494 $table->width = '100%';
6495 $table->data = array();
6497 // iterate through auth plugins and add to the display table
6498 foreach ($services as $service) {
6499 $name = $service->name;
6501 // hide/show link
6502 if ($service->enabled) {
6503 $displayname = "<span>$name</span>";
6504 } else {
6505 $displayname = "<span class=\"dimmed_text\">$name</span>";
6508 $plugin = $service->component;
6510 $functions = "<a href=\"$efurl?id=$service->id\">$strfunctions</a>";
6512 if ($service->restrictedusers) {
6513 $users = "<a href=\"$euurl?id=$service->id\">$strserviceusers</a>";
6514 } else {
6515 $users = get_string('allusers', 'webservice');
6518 $edit = "<a href=\"$esurl?id=$service->id\">$stredit</a>";
6520 // add a row to the table
6521 $table->data[] = array($displayname, $plugin, $functions, $users, $edit);
6523 $return .= html_writer::table($table);
6526 // Custom services
6527 $return .= $OUTPUT->heading(get_string('servicescustom', 'webservice'), 3, 'main');
6528 $services = $DB->get_records_select('external_services', 'component IS NULL', null, 'name');
6530 $table = new html_table();
6531 $table->head = array($strservice, $strdelete, $strfunctions, $strusers, $stredit);
6532 $table->align = array('left', 'center', 'center', 'center', 'center');
6533 $table->size = array('30%', '20%', '20%', '20%', '10%');
6534 $table->width = '100%';
6535 $table->data = array();
6537 // iterate through auth plugins and add to the display table
6538 foreach ($services as $service) {
6539 $name = $service->name;
6541 // hide/show link
6542 if ($service->enabled) {
6543 $displayname = "<span>$name</span>";
6544 } else {
6545 $displayname = "<span class=\"dimmed_text\">$name</span>";
6548 // delete link
6549 $delete = "<a href=\"$esurl?action=delete&amp;sesskey=".sesskey()."&amp;id=$service->id\">$strdelete</a>";
6551 $functions = "<a href=\"$efurl?id=$service->id\">$strfunctions</a>";
6553 if ($service->restrictedusers) {
6554 $users = "<a href=\"$euurl?id=$service->id\">$strserviceusers</a>";
6555 } else {
6556 $users = get_string('allusers', 'webservice');
6559 $edit = "<a href=\"$esurl?id=$service->id\">$stredit</a>";
6561 // add a row to the table
6562 $table->data[] = array($displayname, $delete, $functions, $users, $edit);
6564 // add new custom service option
6565 $return .= html_writer::table($table);
6567 $return .= '<br />';
6568 // add a token to the table
6569 $return .= "<a href=\"$esurl?id=0\">$stradd</a>";
6571 return highlight($query, $return);
6575 * Special class for plagiarism administration.
6577 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
6579 class admin_setting_manageplagiarism extends admin_setting {
6581 * Calls parent::__construct with specific arguments
6583 public function __construct() {
6584 $this->nosave = true;
6585 parent::__construct('plagiarismui', get_string('plagiarismsettings', 'plagiarism'), '', '');
6589 * Always returns true
6591 * @return true
6593 public function get_setting() {
6594 return true;
6598 * Always returns true
6600 * @return true
6602 public function get_defaultsetting() {
6603 return true;
6607 * Always returns '' and doesn't write anything
6609 * @return string Always returns ''
6611 public function write_setting($data) {
6612 // do not write any setting
6613 return '';
6617 * Return XHTML to display control
6619 * @param mixed $data Unused
6620 * @param string $query
6621 * @return string highlight
6623 public function output_html($data, $query='') {
6624 global $CFG, $OUTPUT;
6626 // display strings
6627 $txt = get_strings(array('settings', 'name'));
6629 $plagiarismplugins = get_plugin_list('plagiarism');
6630 if (empty($plagiarismplugins)) {
6631 return get_string('nopluginsinstalled', 'plagiarism');
6634 $return = $OUTPUT->heading(get_string('availableplugins', 'plagiarism'), 3, 'main');
6635 $return .= $OUTPUT->box_start('generalbox authsui');
6637 $table = new html_table();
6638 $table->head = array($txt->name, $txt->settings);
6639 $table->align = array('left', 'center');
6640 $table->data = array();
6641 $table->attributes['class'] = 'manageplagiarismtable generaltable';
6643 // iterate through auth plugins and add to the display table
6644 $authcount = count($plagiarismplugins);
6645 foreach ($plagiarismplugins as $plugin => $dir) {
6646 if (file_exists($dir.'/settings.php')) {
6647 $displayname = "<span>".get_string($plugin, 'plagiarism_'.$plugin)."</span>";
6648 // settings link
6649 $settings = "<a href=\"$CFG->wwwroot/plagiarism/$plugin/settings.php\">{$txt->settings}</a>";
6650 // add a row to the table
6651 $table->data[] =array($displayname, $settings);
6654 $return .= html_writer::table($table);
6655 $return .= get_string('configplagiarismplugins', 'plagiarism');
6656 $return .= $OUTPUT->box_end();
6657 return highlight($query, $return);
6662 * Special class for overview of external services
6664 * @author Jerome Mouneyrac
6666 class admin_setting_webservicesoverview extends admin_setting {
6669 * Calls parent::__construct with specific arguments
6671 public function __construct() {
6672 $this->nosave = true;
6673 parent::__construct('webservicesoverviewui',
6674 get_string('webservicesoverview', 'webservice'), '', '');
6678 * Always returns true, does nothing
6680 * @return true
6682 public function get_setting() {
6683 return true;
6687 * Always returns true, does nothing
6689 * @return true
6691 public function get_defaultsetting() {
6692 return true;
6696 * Always returns '', does not write anything
6698 * @return string Always returns ''
6700 public function write_setting($data) {
6701 // do not write any setting
6702 return '';
6706 * Builds the XHTML to display the control
6708 * @param string $data Unused
6709 * @param string $query
6710 * @return string
6712 public function output_html($data, $query='') {
6713 global $CFG, $OUTPUT;
6715 $return = "";
6717 /// One system controlling Moodle with Token
6718 $brtag = html_writer::empty_tag('br');
6720 $return .= $OUTPUT->heading(get_string('onesystemcontrolling', 'webservice'), 3, 'main');
6721 $table = new html_table();
6722 $table->head = array(get_string('step', 'webservice'), get_string('status'),
6723 get_string('description'));
6724 $table->size = array('30%', '10%', '60%');
6725 $table->align = array('left', 'left', 'left');
6726 $table->width = '90%';
6727 $table->data = array();
6729 $return .= $brtag . get_string('onesystemcontrollingdescription', 'webservice')
6730 . $brtag . $brtag;
6732 /// 1. Enable Web Services
6733 $row = array();
6734 $url = new moodle_url("/admin/search.php?query=enablewebservices");
6735 $row[0] = "1. " . html_writer::tag('a', get_string('enablews', 'webservice'),
6736 array('href' => $url));
6737 $status = html_writer::tag('span', get_string('no'), array('class' => 'statuscritical'));
6738 if ($CFG->enablewebservices) {
6739 $status = get_string('yes');
6741 $row[1] = $status;
6742 $row[2] = get_string('enablewsdescription', 'webservice');
6743 $table->data[] = $row;
6745 /// 2. Enable protocols
6746 $row = array();
6747 $url = new moodle_url("/admin/settings.php?section=webserviceprotocols");
6748 $row[0] = "2. " . html_writer::tag('a', get_string('enableprotocols', 'webservice'),
6749 array('href' => $url));
6750 $status = html_writer::tag('span', get_string('none'), array('class' => 'statuscritical'));
6751 //retrieve activated protocol
6752 $active_protocols = empty($CFG->webserviceprotocols) ?
6753 array() : explode(',', $CFG->webserviceprotocols);
6754 if (!empty($active_protocols)) {
6755 $status = "";
6756 foreach ($active_protocols as $protocol) {
6757 $status .= $protocol . $brtag;
6760 $row[1] = $status;
6761 $row[2] = get_string('enableprotocolsdescription', 'webservice');
6762 $table->data[] = $row;
6764 /// 3. Create user account
6765 $row = array();
6766 $url = new moodle_url("/user/editadvanced.php?id=-1");
6767 $row[0] = "3. " . html_writer::tag('a', get_string('createuser', 'webservice'),
6768 array('href' => $url));
6769 $row[1] = "";
6770 $row[2] = get_string('createuserdescription', 'webservice');
6771 $table->data[] = $row;
6773 /// 4. Add capability to users
6774 $row = array();
6775 $url = new moodle_url("/admin/roles/check.php?contextid=1");
6776 $row[0] = "4. " . html_writer::tag('a', get_string('checkusercapability', 'webservice'),
6777 array('href' => $url));
6778 $row[1] = "";
6779 $row[2] = get_string('checkusercapabilitydescription', 'webservice');
6780 $table->data[] = $row;
6782 /// 5. Select a web service
6783 $row = array();
6784 $url = new moodle_url("/admin/settings.php?section=externalservices");
6785 $row[0] = "5. " . html_writer::tag('a', get_string('selectservice', 'webservice'),
6786 array('href' => $url));
6787 $row[1] = "";
6788 $row[2] = get_string('createservicedescription', 'webservice');
6789 $table->data[] = $row;
6791 /// 6. Add functions
6792 $row = array();
6793 $url = new moodle_url("/admin/settings.php?section=externalservices");
6794 $row[0] = "6. " . html_writer::tag('a', get_string('addfunctions', 'webservice'),
6795 array('href' => $url));
6796 $row[1] = "";
6797 $row[2] = get_string('addfunctionsdescription', 'webservice');
6798 $table->data[] = $row;
6800 /// 7. Add the specific user
6801 $row = array();
6802 $url = new moodle_url("/admin/settings.php?section=externalservices");
6803 $row[0] = "7. " . html_writer::tag('a', get_string('selectspecificuser', 'webservice'),
6804 array('href' => $url));
6805 $row[1] = "";
6806 $row[2] = get_string('selectspecificuserdescription', 'webservice');
6807 $table->data[] = $row;
6809 /// 8. Create token for the specific user
6810 $row = array();
6811 $url = new moodle_url("/admin/webservice/tokens.php?sesskey=" . sesskey() . "&action=create");
6812 $row[0] = "8. " . html_writer::tag('a', get_string('createtokenforuser', 'webservice'),
6813 array('href' => $url));
6814 $row[1] = "";
6815 $row[2] = get_string('createtokenforuserdescription', 'webservice');
6816 $table->data[] = $row;
6818 /// 9. Enable the documentation
6819 $row = array();
6820 $url = new moodle_url("/admin/search.php?query=enablewsdocumentation");
6821 $row[0] = "9. " . html_writer::tag('a', get_string('enabledocumentation', 'webservice'),
6822 array('href' => $url));
6823 $status = '<span class="warning">' . get_string('no') . '</span>';
6824 if ($CFG->enablewsdocumentation) {
6825 $status = get_string('yes');
6827 $row[1] = $status;
6828 $row[2] = get_string('enabledocumentationdescription', 'webservice');
6829 $table->data[] = $row;
6831 /// 10. Test the service
6832 $row = array();
6833 $url = new moodle_url("/admin/webservice/testclient.php");
6834 $row[0] = "10. " . html_writer::tag('a', get_string('testwithtestclient', 'webservice'),
6835 array('href' => $url));
6836 $row[1] = "";
6837 $row[2] = get_string('testwithtestclientdescription', 'webservice');
6838 $table->data[] = $row;
6840 $return .= html_writer::table($table);
6842 /// Users as clients with token
6843 $return .= $brtag . $brtag . $brtag;
6844 $return .= $OUTPUT->heading(get_string('userasclients', 'webservice'), 3, 'main');
6845 $table = new html_table();
6846 $table->head = array(get_string('step', 'webservice'), get_string('status'),
6847 get_string('description'));
6848 $table->size = array('30%', '10%', '60%');
6849 $table->align = array('left', 'left', 'left');
6850 $table->width = '90%';
6851 $table->data = array();
6853 $return .= $brtag . get_string('userasclientsdescription', 'webservice') .
6854 $brtag . $brtag;
6856 /// 1. Enable Web Services
6857 $row = array();
6858 $url = new moodle_url("/admin/search.php?query=enablewebservices");
6859 $row[0] = "1. " . html_writer::tag('a', get_string('enablews', 'webservice'),
6860 array('href' => $url));
6861 $status = html_writer::tag('span', get_string('no'), array('class' => 'statuscritical'));
6862 if ($CFG->enablewebservices) {
6863 $status = get_string('yes');
6865 $row[1] = $status;
6866 $row[2] = get_string('enablewsdescription', 'webservice');
6867 $table->data[] = $row;
6869 /// 2. Enable protocols
6870 $row = array();
6871 $url = new moodle_url("/admin/settings.php?section=webserviceprotocols");
6872 $row[0] = "2. " . html_writer::tag('a', get_string('enableprotocols', 'webservice'),
6873 array('href' => $url));
6874 $status = html_writer::tag('span', get_string('none'), array('class' => 'statuscritical'));
6875 //retrieve activated protocol
6876 $active_protocols = empty($CFG->webserviceprotocols) ?
6877 array() : explode(',', $CFG->webserviceprotocols);
6878 if (!empty($active_protocols)) {
6879 $status = "";
6880 foreach ($active_protocols as $protocol) {
6881 $status .= $protocol . $brtag;
6884 $row[1] = $status;
6885 $row[2] = get_string('enableprotocolsdescription', 'webservice');
6886 $table->data[] = $row;
6889 /// 3. Select a web service
6890 $row = array();
6891 $url = new moodle_url("/admin/settings.php?section=externalservices");
6892 $row[0] = "3. " . html_writer::tag('a', get_string('selectservice', 'webservice'),
6893 array('href' => $url));
6894 $row[1] = "";
6895 $row[2] = get_string('createserviceforusersdescription', 'webservice');
6896 $table->data[] = $row;
6898 /// 4. Add functions
6899 $row = array();
6900 $url = new moodle_url("/admin/settings.php?section=externalservices");
6901 $row[0] = "4. " . html_writer::tag('a', get_string('addfunctions', 'webservice'),
6902 array('href' => $url));
6903 $row[1] = "";
6904 $row[2] = get_string('addfunctionsdescription', 'webservice');
6905 $table->data[] = $row;
6907 /// 5. Add capability to users
6908 $row = array();
6909 $url = new moodle_url("/admin/roles/check.php?contextid=1");
6910 $row[0] = "5. " . html_writer::tag('a', get_string('addcapabilitytousers', 'webservice'),
6911 array('href' => $url));
6912 $row[1] = "";
6913 $row[2] = get_string('addcapabilitytousersdescription', 'webservice');
6914 $table->data[] = $row;
6916 /// 6. Test the service
6917 $row = array();
6918 $url = new moodle_url("/admin/webservice/testclient.php");
6919 $row[0] = "6. " . html_writer::tag('a', get_string('testwithtestclient', 'webservice'),
6920 array('href' => $url));
6921 $row[1] = "";
6922 $row[2] = get_string('testauserwithtestclientdescription', 'webservice');
6923 $table->data[] = $row;
6925 $return .= html_writer::table($table);
6927 return highlight($query, $return);
6933 * Special class for web service protocol administration.
6935 * @author Petr Skoda (skodak)
6937 class admin_setting_managewebserviceprotocols extends admin_setting {
6940 * Calls parent::__construct with specific arguments
6942 public function __construct() {
6943 $this->nosave = true;
6944 parent::__construct('webservicesui', get_string('manageprotocols', 'webservice'), '', '');
6948 * Always returns true, does nothing
6950 * @return true
6952 public function get_setting() {
6953 return true;
6957 * Always returns true, does nothing
6959 * @return true
6961 public function get_defaultsetting() {
6962 return true;
6966 * Always returns '', does not write anything
6968 * @return string Always returns ''
6970 public function write_setting($data) {
6971 // do not write any setting
6972 return '';
6976 * Checks if $query is one of the available webservices
6978 * @param string $query The string to search for
6979 * @return bool Returns true if found, false if not
6981 public function is_related($query) {
6982 if (parent::is_related($query)) {
6983 return true;
6986 $textlib = textlib_get_instance();
6987 $protocols = get_plugin_list('webservice');
6988 foreach ($protocols as $protocol=>$location) {
6989 if (strpos($protocol, $query) !== false) {
6990 return true;
6992 $protocolstr = get_string('pluginname', 'webservice_'.$protocol);
6993 if (strpos($textlib->strtolower($protocolstr), $query) !== false) {
6994 return true;
6997 return false;
7001 * Builds the XHTML to display the control
7003 * @param string $data Unused
7004 * @param string $query
7005 * @return string
7007 public function output_html($data, $query='') {
7008 global $CFG, $OUTPUT;
7010 // display strings
7011 $stradministration = get_string('administration');
7012 $strsettings = get_string('settings');
7013 $stredit = get_string('edit');
7014 $strprotocol = get_string('protocol', 'webservice');
7015 $strenable = get_string('enable');
7016 $strdisable = get_string('disable');
7017 $strversion = get_string('version');
7018 $struninstall = get_string('uninstallplugin', 'admin');
7020 $protocols_available = get_plugin_list('webservice');
7021 $active_protocols = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols);
7022 ksort($protocols_available);
7024 foreach ($active_protocols as $key=>$protocol) {
7025 if (empty($protocols_available[$protocol])) {
7026 unset($active_protocols[$key]);
7030 $return = $OUTPUT->heading(get_string('actwebserviceshhdr', 'webservice'), 3, 'main');
7031 $return .= $OUTPUT->box_start('generalbox webservicesui');
7033 $table = new html_table();
7034 $table->head = array($strprotocol, $strversion, $strenable, $struninstall, $strsettings);
7035 $table->align = array('left', 'center', 'center', 'center', 'center');
7036 $table->width = '100%';
7037 $table->data = array();
7039 // iterate through auth plugins and add to the display table
7040 $url = "$CFG->wwwroot/$CFG->admin/webservice/protocols.php?sesskey=" . sesskey();
7041 foreach ($protocols_available as $protocol => $location) {
7042 $name = get_string('pluginname', 'webservice_'.$protocol);
7044 $plugin = new stdClass();
7045 if (file_exists($CFG->dirroot.'/webservice/'.$protocol.'/version.php')) {
7046 include($CFG->dirroot.'/webservice/'.$protocol.'/version.php');
7048 $version = isset($plugin->version) ? $plugin->version : '';
7050 // hide/show link
7051 if (in_array($protocol, $active_protocols)) {
7052 $hideshow = "<a href=\"$url&amp;action=disable&amp;webservice=$protocol\">";
7053 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('i/hide') . "\" class=\"icon\" alt=\"$strdisable\" /></a>";
7054 $displayname = "<span>$name</span>";
7055 } else {
7056 $hideshow = "<a href=\"$url&amp;action=enable&amp;webservice=$protocol\">";
7057 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('i/show') . "\" class=\"icon\" alt=\"$strenable\" /></a>";
7058 $displayname = "<span class=\"dimmed_text\">$name</span>";
7061 // delete link
7062 $uninstall = "<a href=\"$url&amp;action=uninstall&amp;webservice=$protocol\">$struninstall</a>";
7064 // settings link
7065 if (file_exists($CFG->dirroot.'/webservice/'.$protocol.'/settings.php')) {
7066 $settings = "<a href=\"settings.php?section=webservicesetting$protocol\">$strsettings</a>";
7067 } else {
7068 $settings = '';
7071 // add a row to the table
7072 $table->data[] = array($displayname, $version, $hideshow, $uninstall, $settings);
7074 $return .= html_writer::table($table);
7075 $return .= get_string('configwebserviceplugins', 'webservice');
7076 $return .= $OUTPUT->box_end();
7078 return highlight($query, $return);
7084 * Special class for web service token administration.
7086 * @author Jerome Mouneyrac
7088 class admin_setting_managewebservicetokens extends admin_setting {
7091 * Calls parent::__construct with specific arguments
7093 public function __construct() {
7094 $this->nosave = true;
7095 parent::__construct('webservicestokenui', get_string('managetokens', 'webservice'), '', '');
7099 * Always returns true, does nothing
7101 * @return true
7103 public function get_setting() {
7104 return true;
7108 * Always returns true, does nothing
7110 * @return true
7112 public function get_defaultsetting() {
7113 return true;
7117 * Always returns '', does not write anything
7119 * @return string Always returns ''
7121 public function write_setting($data) {
7122 // do not write any setting
7123 return '';
7127 * Builds the XHTML to display the control
7129 * @param string $data Unused
7130 * @param string $query
7131 * @return string
7133 public function output_html($data, $query='') {
7134 global $CFG, $OUTPUT, $DB, $USER;
7136 // display strings
7137 $stroperation = get_string('operation', 'webservice');
7138 $strtoken = get_string('token', 'webservice');
7139 $strservice = get_string('service', 'webservice');
7140 $struser = get_string('user');
7141 $strcontext = get_string('context', 'webservice');
7142 $strvaliduntil = get_string('validuntil', 'webservice');
7143 $striprestriction = get_string('iprestriction', 'webservice');
7145 $return = $OUTPUT->box_start('generalbox webservicestokenui');
7147 $table = new html_table();
7148 $table->head = array($strtoken, $struser, $strservice, $striprestriction, $strvaliduntil, $stroperation);
7149 $table->align = array('left', 'left', 'left', 'center', 'center', 'center');
7150 $table->width = '100%';
7151 $table->data = array();
7153 $tokenpageurl = "$CFG->wwwroot/$CFG->admin/webservice/tokens.php?sesskey=" . sesskey();
7155 //TODO: in order to let the administrator delete obsolete token, split this request in multiple request or use LEFT JOIN
7157 //here retrieve token list (including linked users firstname/lastname and linked services name)
7158 $sql = "SELECT t.id, t.token, u.id AS userid, u.firstname, u.lastname, s.name, t.validuntil, s.id AS serviceid
7159 FROM {external_tokens} t, {user} u, {external_services} s
7160 WHERE t.creatorid=? AND t.tokentype = ? AND s.id = t.externalserviceid AND t.userid = u.id";
7161 $tokens = $DB->get_records_sql($sql, array($USER->id, EXTERNAL_TOKEN_PERMANENT));
7162 if (!empty($tokens)) {
7163 foreach ($tokens as $token) {
7164 //TODO: retrieve context
7166 $delete = "<a href=\"".$tokenpageurl."&amp;action=delete&amp;tokenid=".$token->id."\">";
7167 $delete .= get_string('delete')."</a>";
7169 $validuntil = '';
7170 if (!empty($token->validuntil)) {
7171 $validuntil = date("F j, Y"); //TODO: language support (look for moodle function)
7174 $iprestriction = '';
7175 if (!empty($token->iprestriction)) {
7176 $iprestriction = $token->iprestriction;
7179 $userprofilurl = new moodle_url('/user/profile.php?id='.$token->userid);
7180 $useratag = html_writer::start_tag('a', array('href' => $userprofilurl));
7181 $useratag .= $token->firstname." ".$token->lastname;
7182 $useratag .= html_writer::end_tag('a');
7184 //check user missing capabilities
7185 require_once($CFG->dirroot . '/webservice/lib.php');
7186 $webservicemanager = new webservice();
7187 $usermissingcaps = $webservicemanager->get_missing_capabilities_by_users(
7188 array(array('id' => $token->userid)), $token->serviceid);
7190 if (!is_siteadmin($token->userid) and
7191 key_exists($token->userid, $usermissingcaps)) {
7192 $missingcapabilities = implode(',',
7193 $usermissingcaps[$token->userid]);
7194 if (!empty($missingcapabilities)) {
7195 $useratag .= html_writer::tag('div',
7196 get_string('usermissingcaps', 'webservice',
7197 $missingcapabilities)
7198 . '&nbsp;' . $OUTPUT->help_icon('missingcaps', 'webservice'),
7199 array('class' => 'missingcaps'));
7203 $table->data[] = array($token->token, $useratag, $token->name, $iprestriction, $validuntil, $delete);
7206 $return .= html_writer::table($table);
7207 } else {
7208 $return .= get_string('notoken', 'webservice');
7211 $return .= $OUTPUT->box_end();
7212 // add a token to the table
7213 $return .= "<a href=\"".$tokenpageurl."&amp;action=create\">";
7214 $return .= get_string('add')."</a>";
7216 return highlight($query, $return);
7221 * Colour picker
7223 * @copyright 2010 Sam Hemelryk
7224 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
7226 class admin_setting_configcolourpicker extends admin_setting {
7229 * Information for previewing the colour
7231 * @var array|null
7233 protected $previewconfig = null;
7237 * @param string $name
7238 * @param string $visiblename
7239 * @param string $description
7240 * @param string $defaultsetting
7241 * @param array $previewconfig Array('selector'=>'.some .css .selector','style'=>'backgroundColor');
7243 public function __construct($name, $visiblename, $description, $defaultsetting, array $previewconfig=null) {
7244 $this->previewconfig = $previewconfig;
7245 parent::__construct($name, $visiblename, $description, $defaultsetting);
7249 * Return the setting
7251 * @return mixed returns config if successful else null
7253 public function get_setting() {
7254 return $this->config_read($this->name);
7258 * Saves the setting
7260 * @param string $data
7261 * @return bool
7263 public function write_setting($data) {
7264 $data = $this->validate($data);
7265 if ($data === false) {
7266 return get_string('validateerror', 'admin');
7268 return ($this->config_write($this->name, $data) ? '' : get_string('errorsetting', 'admin'));
7272 * Validates the colour that was entered by the user
7274 * @param string $data
7275 * @return string|false
7277 protected function validate($data) {
7278 if (preg_match('/^#?([a-fA-F0-9]{3}){1,2}$/', $data)) {
7279 if (strpos($data, '#')!==0) {
7280 $data = '#'.$data;
7282 return $data;
7283 } else if (preg_match('/^[a-zA-Z]{3, 25}$/', $data)) {
7284 return $data;
7285 } else if (empty($data)) {
7286 return $this->defaultsetting;
7287 } else {
7288 return false;
7293 * Generates the HTML for the setting
7295 * @global moodle_page $PAGE
7296 * @global core_renderer $OUTPUT
7297 * @param string $data
7298 * @param string $query
7300 public function output_html($data, $query = '') {
7301 global $PAGE, $OUTPUT;
7302 $PAGE->requires->js_init_call('M.util.init_colour_picker', array($this->get_id(), $this->previewconfig));
7303 $content = html_writer::start_tag('div', array('class'=>'form-colourpicker defaultsnext'));
7304 $content .= html_writer::tag('div', $OUTPUT->pix_icon('i/loading', get_string('loading', 'admin'), 'moodle', array('class'=>'loadingicon')), array('class'=>'admin_colourpicker clearfix'));
7305 $content .= html_writer::empty_tag('input', array('type'=>'text','id'=>$this->get_id(), 'name'=>$this->get_full_name(), 'value'=>$this->get_setting(), 'size'=>'12'));
7306 if (!empty($this->previewconfig)) {
7307 $content .= html_writer::empty_tag('input', array('type'=>'button','id'=>$this->get_id().'_preview', 'value'=>get_string('preview'), 'class'=>'admin_colourpicker_preview'));
7309 $content .= html_writer::end_tag('div');
7310 return format_admin_setting($this, $this->visiblename, $content, $this->description, false, '', $this->get_defaultsetting(), $query);