MDL-24777 new emoticon_manager and its admin settings
[moodle.git] / lib / adminlib.php
bloba7b762ef0a3d5986485e0cc7a80caed131040746
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();
3233 $config = $this->config_read($this->name);
3235 if (is_null($config)) {
3236 return null;
3239 return $this->prepare_form_data($manager->decode_stored_config($config));
3243 * Save selected settings
3245 * @param array $data Array of settings to save
3246 * @return bool
3248 public function write_setting($data) {
3250 $manager = get_emoticon_manager();
3251 $emoticons = $this->process_form_data($data);
3253 if ($emoticons === false) {
3254 return false;
3257 if ($this->config_write($this->name, $manager->encode_stored_config($emoticons))) {
3258 return ''; // success
3259 } else {
3260 return get_string('errorsetting', 'admin') . $this->visiblename . html_writer::empty_tag('br');
3265 * Return XHTML field(s) for options
3267 * @param array $data Array of options to set in HTML
3268 * @return string XHTML string for the fields and wrapping div(s)
3270 public function output_html($data, $query='') {
3271 global $OUTPUT;
3273 $out = html_writer::start_tag('table', array('border' => 1, 'class' => 'generaltable'));
3274 $out .= html_writer::start_tag('thead');
3275 $out .= html_writer::start_tag('tr');
3276 $out .= html_writer::tag('th', get_string('emoticontext', 'admin'));
3277 $out .= html_writer::tag('th', get_string('emoticonimagename', 'admin'));
3278 $out .= html_writer::tag('th', get_string('emoticoncomponent', 'admin'));
3279 $out .= html_writer::tag('th', get_string('emoticonalt', 'admin'), array('colspan' => 2));
3280 $out .= html_writer::tag('th', '');
3281 $out .= html_writer::end_tag('tr');
3282 $out .= html_writer::end_tag('thead');
3283 $out .= html_writer::start_tag('tbody');
3284 $i = 0;
3285 foreach($data as $field => $value) {
3286 switch ($i) {
3287 case 0:
3288 $out .= html_writer::start_tag('tr');
3289 $current_text = $value;
3290 $current_filename = '';
3291 $current_imagecomponent = '';
3292 $current_altidentifier = '';
3293 $current_altcomponent = '';
3294 case 1:
3295 $current_filename = $value;
3296 case 2:
3297 $current_imagecomponent = $value;
3298 case 3:
3299 $current_altidentifier = $value;
3300 case 4:
3301 $current_altcomponent = $value;
3304 $out .= html_writer::tag('td',
3305 html_writer::empty_tag('input',
3306 array(
3307 'type' => 'text',
3308 'class' => 'form-text',
3309 'name' => $this->get_full_name().'['.$field.']',
3310 'value' => $value,
3312 ), array('class' => 'c'.$i)
3315 if ($i == 4) {
3316 if (get_string_manager()->string_exists($current_altidentifier, $current_altcomponent)) {
3317 $alt = get_string($current_altidentifier, $current_altcomponent);
3318 } else {
3319 $alt = $current_text;
3321 if ($current_filename) {
3322 $out .= html_writer::tag('td', $OUTPUT->render(new pix_emoticon($current_filename, $alt, $current_imagecomponent)));
3323 } else {
3324 $out .= html_writer::tag('td', '');
3326 $out .= html_writer::end_tag('tr');
3327 $i = 0;
3328 } else {
3329 $i++;
3333 $out .= html_writer::end_tag('tbody');
3334 $out .= html_writer::end_tag('table');
3335 $out = html_writer::tag('div', $out, array('class' => 'form-group'));
3336 $out .= html_writer::tag('div', html_writer::link(new moodle_url('/admin/resetemoticons.php'), get_string('emoticonsreset', 'admin')));
3338 return format_admin_setting($this, $this->visiblename, $out, $this->description, false, '', NULL, $query);
3342 * Converts the array of emoticon objects provided by {@see emoticon_manager} into admin settings form data
3344 * @see self::process_form_data()
3345 * @param array $emoticons array of emoticon objects as returned by {@see emoticon_manager}
3346 * @return array of form fields and their values
3348 protected function prepare_form_data(array $emoticons) {
3350 $form = array();
3351 $i = 0;
3352 foreach ($emoticons as $emoticon) {
3353 $form['text'.$i] = $emoticon->text;
3354 $form['imagename'.$i] = $emoticon->imagename;
3355 $form['imagecomponent'.$i] = $emoticon->imagecomponent;
3356 $form['altidentifier'.$i] = $emoticon->altidentifier;
3357 $form['altcomponent'.$i] = $emoticon->altcomponent;
3358 $i++;
3360 // add one more blank field set for new object
3361 $form['text'.$i] = '';
3362 $form['imagename'.$i] = '';
3363 $form['imagecomponent'.$i] = '';
3364 $form['altidentifier'.$i] = '';
3365 $form['altcomponent'.$i] = '';
3367 return $form;
3371 * Converts the data from admin settings form into an array of emoticon objects
3373 * @see self::prepare_form_data()
3374 * @param array $data array of admin form fields and values
3375 * @return false|array of emoticon objects
3377 protected function process_form_data(array $form) {
3379 $count = count($form); // number of form field values
3381 if ($count % 5) {
3382 // we must get five fields per emoticon object
3383 return false;
3386 $emoticons = array();
3387 for ($i = 0; $i < $count / 5; $i++) {
3388 $emoticon = new stdClass();
3389 $emoticon->text = clean_param(trim($form['text'.$i]), PARAM_NOTAGS);
3390 $emoticon->imagename = clean_param(trim($form['imagename'.$i]), PARAM_PATH);
3391 $emoticon->imagecomponent = clean_param(trim($form['imagecomponent'.$i]), PARAM_SAFEDIR);
3392 $emoticon->altidentifier = clean_param(trim($form['altidentifier'.$i]), PARAM_STRINGID);
3393 $emoticon->altcomponent = clean_param(trim($form['altcomponent'.$i]), PARAM_SAFEDIR);
3395 if (strpos($emoticon->text, ':/') !== false or strpos($emoticon->text, '//') !== false) {
3396 // prevent from breaking http://url.addresses by accident
3397 $emoticon->text = '';
3400 if (strlen($emoticon->text) < 2) {
3401 // do not allow single character emoticons
3402 $emoticon->text = '';
3405 if (preg_match('/^[a-zA-Z]+[a-zA-Z0-9]*$/', $emoticon->text)) {
3406 // emoticon text must contain some non-alphanumeric character to prevent
3407 // breaking HTML tags
3408 $emoticon->text = '';
3411 if ($emoticon->text !== '' and $emoticon->imagename !== '' and $emoticon->imagecomponent !== '') {
3412 $emoticons[] = $emoticon;
3415 return $emoticons;
3420 * Special setting for limiting of the list of available languages.
3422 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3424 class admin_setting_langlist extends admin_setting_configtext {
3426 * Calls parent::__construct with specific arguments
3428 public function __construct() {
3429 parent::__construct('langlist', get_string('langlist', 'admin'), get_string('configlanglist', 'admin'), '', PARAM_NOTAGS);
3433 * Save the new setting
3435 * @param string $data The new setting
3436 * @return bool
3438 public function write_setting($data) {
3439 $return = parent::write_setting($data);
3440 get_string_manager()->reset_caches();
3441 return $return;
3446 * Selection of one of the recognised countries using the list
3447 * returned by {@link get_list_of_countries()}.
3449 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3451 class admin_settings_country_select extends admin_setting_configselect {
3452 protected $includeall;
3453 public function __construct($name, $visiblename, $description, $defaultsetting, $includeall=false) {
3454 $this->includeall = $includeall;
3455 parent::__construct($name, $visiblename, $description, $defaultsetting, NULL);
3459 * Lazy-load the available choices for the select box
3461 public function load_choices() {
3462 global $CFG;
3463 if (is_array($this->choices)) {
3464 return true;
3466 $this->choices = array_merge(
3467 array('0' => get_string('choosedots')),
3468 get_string_manager()->get_list_of_countries($this->includeall));
3469 return true;
3474 * Course category selection
3476 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3478 class admin_settings_coursecat_select extends admin_setting_configselect {
3480 * Calls parent::__construct with specific arguments
3482 public function __construct($name, $visiblename, $description, $defaultsetting) {
3483 parent::__construct($name, $visiblename, $description, $defaultsetting, NULL);
3487 * Load the available choices for the select box
3489 * @return bool
3491 public function load_choices() {
3492 global $CFG;
3493 require_once($CFG->dirroot.'/course/lib.php');
3494 if (is_array($this->choices)) {
3495 return true;
3497 $this->choices = make_categories_options();
3498 return true;
3503 * Special control for selecting days to backup
3505 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3507 class admin_setting_special_backupdays extends admin_setting_configmulticheckbox2 {
3509 * Calls parent::__construct with specific arguments
3511 public function __construct() {
3512 parent::__construct('backup_sche_weekdays', get_string('schedule'), get_string('backupschedulehelp'), array(), NULL);
3513 $this->plugin = 'backup';
3516 * Load the available choices for the select box
3518 * @return bool Always returns true
3520 public function load_choices() {
3521 if (is_array($this->choices)) {
3522 return true;
3524 $this->choices = array();
3525 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
3526 foreach ($days as $day) {
3527 $this->choices[$day] = get_string($day, 'calendar');
3529 return true;
3534 * Special debug setting
3536 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3538 class admin_setting_special_debug extends admin_setting_configselect {
3540 * Calls parent::__construct with specific arguments
3542 public function __construct() {
3543 parent::__construct('debug', get_string('debug', 'admin'), get_string('configdebug', 'admin'), DEBUG_NONE, NULL);
3547 * Load the available choices for the select box
3549 * @return bool
3551 public function load_choices() {
3552 if (is_array($this->choices)) {
3553 return true;
3555 $this->choices = array(DEBUG_NONE => get_string('debugnone', 'admin'),
3556 DEBUG_MINIMAL => get_string('debugminimal', 'admin'),
3557 DEBUG_NORMAL => get_string('debugnormal', 'admin'),
3558 DEBUG_ALL => get_string('debugall', 'admin'),
3559 DEBUG_DEVELOPER => get_string('debugdeveloper', 'admin'));
3560 return true;
3565 * Special admin control
3567 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3569 class admin_setting_special_calendar_weekend extends admin_setting {
3571 * Calls parent::__construct with specific arguments
3573 public function __construct() {
3574 $name = 'calendar_weekend';
3575 $visiblename = get_string('calendar_weekend', 'admin');
3576 $description = get_string('helpweekenddays', 'admin');
3577 $default = array ('0', '6'); // Saturdays and Sundays
3578 parent::__construct($name, $visiblename, $description, $default);
3581 * Gets the current settings as an array
3583 * @return mixed Null if none, else array of settings
3585 public function get_setting() {
3586 $result = $this->config_read($this->name);
3587 if (is_null($result)) {
3588 return NULL;
3590 if ($result === '') {
3591 return array();
3593 $settings = array();
3594 for ($i=0; $i<7; $i++) {
3595 if ($result & (1 << $i)) {
3596 $settings[] = $i;
3599 return $settings;
3603 * Save the new settings
3605 * @param array $data Array of new settings
3606 * @return bool
3608 public function write_setting($data) {
3609 if (!is_array($data)) {
3610 return '';
3612 unset($data['xxxxx']);
3613 $result = 0;
3614 foreach($data as $index) {
3615 $result |= 1 << $index;
3617 return ($this->config_write($this->name, $result) ? '' : get_string('errorsetting', 'admin'));
3621 * Return XHTML to display the control
3623 * @param array $data array of selected days
3624 * @param string $query
3625 * @return string XHTML for display (field + wrapping div(s)
3627 public function output_html($data, $query='') {
3628 // The order matters very much because of the implied numeric keys
3629 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
3630 $return = '<table><thead><tr>';
3631 $return .= '<input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
3632 foreach($days as $index => $day) {
3633 $return .= '<td><label for="'.$this->get_id().$index.'">'.get_string($day, 'calendar').'</label></td>';
3635 $return .= '</tr></thead><tbody><tr>';
3636 foreach($days as $index => $day) {
3637 $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>';
3639 $return .= '</tr></tbody></table>';
3641 return format_admin_setting($this, $this->visiblename, $return, $this->description, false, '', NULL, $query);
3648 * Admin setting that allows a user to pick appropriate roles for something.
3650 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3652 class admin_setting_pickroles extends admin_setting_configmulticheckbox {
3653 /** @var array Array of capabilities which identify roles */
3654 private $types;
3657 * @param string $name Name of config variable
3658 * @param string $visiblename Display name
3659 * @param string $description Description
3660 * @param array $types Array of archetypes which identify
3661 * roles that will be enabled by default.
3663 public function __construct($name, $visiblename, $description, $types) {
3664 parent::__construct($name, $visiblename, $description, NULL, NULL);
3665 $this->types = $types;
3669 * Load roles as choices
3671 * @return bool true=>success, false=>error
3673 public function load_choices() {
3674 global $CFG, $DB;
3675 if (during_initial_install()) {
3676 return false;
3678 if (is_array($this->choices)) {
3679 return true;
3681 if ($roles = get_all_roles()) {
3682 $this->choices = array();
3683 foreach($roles as $role) {
3684 $this->choices[$role->id] = format_string($role->name);
3686 return true;
3687 } else {
3688 return false;
3692 * Return the default setting for this control
3694 * @return array Array of default settings
3696 public function get_defaultsetting() {
3697 global $CFG;
3699 if (during_initial_install()) {
3700 return null;
3702 $result = array();
3703 foreach($this->types as $archetype) {
3704 if ($caproles = get_archetype_roles($archetype)) {
3705 foreach ($caproles as $caprole) {
3706 $result[$caprole->id] = 1;
3710 return $result;
3715 * Text field with an advanced checkbox, that controls a additional $name.'_adv' setting.
3717 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3719 class admin_setting_configtext_with_advanced extends admin_setting_configtext {
3721 * Constructor
3722 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
3723 * @param string $visiblename localised
3724 * @param string $description long localised info
3725 * @param array $defaultsetting ('value'=>string, '__construct'=>bool)
3726 * @param mixed $paramtype int means PARAM_XXX type, string is a allowed format in regex
3727 * @param int $size default field size
3729 public function __construct($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW, $size=null) {
3730 parent::__construct($name, $visiblename, $description, $defaultsetting, $paramtype, $size);
3734 * Loads the current setting and returns array
3736 * @return array Returns array value=>xx, __construct=>xx
3738 public function get_setting() {
3739 $value = parent::get_setting();
3740 $adv = $this->config_read($this->name.'_adv');
3741 if (is_null($value) or is_null($adv)) {
3742 return NULL;
3744 return array('value' => $value, 'adv' => $adv);
3748 * Saves the new settings passed in $data
3750 * @todo Add vartype handling to ensure $data is an array
3751 * @param array $data
3752 * @return mixed string or Array
3754 public function write_setting($data) {
3755 $error = parent::write_setting($data['value']);
3756 if (!$error) {
3757 $value = empty($data['adv']) ? 0 : 1;
3758 $this->config_write($this->name.'_adv', $value);
3760 return $error;
3764 * Return XHTML for the control
3766 * @param array $data Default data array
3767 * @param string $query
3768 * @return string XHTML to display control
3770 public function output_html($data, $query='') {
3771 $default = $this->get_defaultsetting();
3772 $defaultinfo = array();
3773 if (isset($default['value'])) {
3774 if ($default['value'] === '') {
3775 $defaultinfo[] = "''";
3776 } else {
3777 $defaultinfo[] = $default['value'];
3780 if (!empty($default['adv'])) {
3781 $defaultinfo[] = get_string('advanced');
3783 $defaultinfo = implode(', ', $defaultinfo);
3785 $adv = !empty($data['adv']);
3786 $return = '<div class="form-text defaultsnext">' .
3787 '<input type="text" size="' . $this->size . '" id="' . $this->get_id() .
3788 '" name="' . $this->get_full_name() . '[value]" value="' . s($data['value']) . '" />' .
3789 ' <input type="checkbox" class="form-checkbox" id="' .
3790 $this->get_id() . '_adv" name="' . $this->get_full_name() .
3791 '[adv]" value="1" ' . ($adv ? 'checked="checked"' : '') . ' />' .
3792 ' <label for="' . $this->get_id() . '_adv">' .
3793 get_string('advanced') . '</label></div>';
3795 return format_admin_setting($this, $this->visiblename, $return,
3796 $this->description, true, '', $defaultinfo, $query);
3801 * Checkbox with an advanced checkbox that controls an additional $name.'_adv' config setting.
3803 * @copyright 2009 Petr Skoda (http://skodak.org)
3804 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3806 class admin_setting_configcheckbox_with_advanced extends admin_setting_configcheckbox {
3809 * Constructor
3810 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
3811 * @param string $visiblename localised
3812 * @param string $description long localised info
3813 * @param array $defaultsetting ('value'=>string, 'adv'=>bool)
3814 * @param string $yes value used when checked
3815 * @param string $no value used when not checked
3817 public function __construct($name, $visiblename, $description, $defaultsetting, $yes='1', $no='0') {
3818 parent::__construct($name, $visiblename, $description, $defaultsetting, $yes, $no);
3822 * Loads the current setting and returns array
3824 * @return array Returns array value=>xx, adv=>xx
3826 public function get_setting() {
3827 $value = parent::get_setting();
3828 $adv = $this->config_read($this->name.'_adv');
3829 if (is_null($value) or is_null($adv)) {
3830 return NULL;
3832 return array('value' => $value, 'adv' => $adv);
3836 * Sets the value for the setting
3838 * Sets the value for the setting to either the yes or no values
3839 * of the object by comparing $data to yes
3841 * @param mixed $data Gets converted to str for comparison against yes value
3842 * @return string empty string or error
3844 public function write_setting($data) {
3845 $error = parent::write_setting($data['value']);
3846 if (!$error) {
3847 $value = empty($data['adv']) ? 0 : 1;
3848 $this->config_write($this->name.'_adv', $value);
3850 return $error;
3854 * Returns an XHTML checkbox field and with extra advanced cehckbox
3856 * @param string $data If $data matches yes then checkbox is checked
3857 * @param string $query
3858 * @return string XHTML field
3860 public function output_html($data, $query='') {
3861 $defaults = $this->get_defaultsetting();
3862 $defaultinfo = array();
3863 if (!is_null($defaults)) {
3864 if ((string)$defaults['value'] === $this->yes) {
3865 $defaultinfo[] = get_string('checkboxyes', 'admin');
3866 } else {
3867 $defaultinfo[] = get_string('checkboxno', 'admin');
3869 if (!empty($defaults['adv'])) {
3870 $defaultinfo[] = get_string('advanced');
3873 $defaultinfo = implode(', ', $defaultinfo);
3875 if ((string)$data['value'] === $this->yes) { // convert to strings before comparison
3876 $checked = 'checked="checked"';
3877 } else {
3878 $checked = '';
3880 if (!empty($data['adv'])) {
3881 $advanced = 'checked="checked"';
3882 } else {
3883 $advanced = '';
3886 $fullname = $this->get_full_name();
3887 $novalue = s($this->no);
3888 $yesvalue = s($this->yes);
3889 $id = $this->get_id();
3890 $stradvanced = get_string('advanced');
3891 $return = <<<EOT
3892 <div class="form-checkbox defaultsnext" >
3893 <input type="hidden" name="{$fullname}[value]" value="$novalue" />
3894 <input type="checkbox" id="$id" name="{$fullname}[value]" value="$yesvalue" $checked />
3895 <input type="checkbox" class="form-checkbox" id="{$id}_adv" name="{$fullname}[adv]" value="1" $advanced />
3896 <label for="{$id}_adv">$stradvanced</label>
3897 </div>
3898 EOT;
3899 return format_admin_setting($this, $this->visiblename, $return, $this->description,
3900 true, '', $defaultinfo, $query);
3905 * Checkbox with an advanced checkbox that controls an additional $name.'_locked' config setting.
3907 * This is nearly a copy/paste of admin_setting_configcheckbox_with_adv
3909 * @copyright 2010 Sam Hemelryk
3910 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3912 class admin_setting_configcheckbox_with_lock extends admin_setting_configcheckbox {
3914 * Constructor
3915 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
3916 * @param string $visiblename localised
3917 * @param string $description long localised info
3918 * @param array $defaultsetting ('value'=>string, 'locked'=>bool)
3919 * @param string $yes value used when checked
3920 * @param string $no value used when not checked
3922 public function __construct($name, $visiblename, $description, $defaultsetting, $yes='1', $no='0') {
3923 parent::__construct($name, $visiblename, $description, $defaultsetting, $yes, $no);
3927 * Loads the current setting and returns array
3929 * @return array Returns array value=>xx, adv=>xx
3931 public function get_setting() {
3932 $value = parent::get_setting();
3933 $locked = $this->config_read($this->name.'_locked');
3934 if (is_null($value) or is_null($locked)) {
3935 return NULL;
3937 return array('value' => $value, 'locked' => $locked);
3941 * Sets the value for the setting
3943 * Sets the value for the setting to either the yes or no values
3944 * of the object by comparing $data to yes
3946 * @param mixed $data Gets converted to str for comparison against yes value
3947 * @return string empty string or error
3949 public function write_setting($data) {
3950 $error = parent::write_setting($data['value']);
3951 if (!$error) {
3952 $value = empty($data['locked']) ? 0 : 1;
3953 $this->config_write($this->name.'_locked', $value);
3955 return $error;
3959 * Returns an XHTML checkbox field and with extra locked checkbox
3961 * @param string $data If $data matches yes then checkbox is checked
3962 * @param string $query
3963 * @return string XHTML field
3965 public function output_html($data, $query='') {
3966 $defaults = $this->get_defaultsetting();
3967 $defaultinfo = array();
3968 if (!is_null($defaults)) {
3969 if ((string)$defaults['value'] === $this->yes) {
3970 $defaultinfo[] = get_string('checkboxyes', 'admin');
3971 } else {
3972 $defaultinfo[] = get_string('checkboxno', 'admin');
3974 if (!empty($defaults['locked'])) {
3975 $defaultinfo[] = get_string('locked', 'admin');
3978 $defaultinfo = implode(', ', $defaultinfo);
3980 $fullname = $this->get_full_name();
3981 $novalue = s($this->no);
3982 $yesvalue = s($this->yes);
3983 $id = $this->get_id();
3985 $checkboxparams = array('type'=>'checkbox', 'id'=>$id,'name'=>$fullname.'[value]', 'value'=>$yesvalue);
3986 if ((string)$data['value'] === $this->yes) { // convert to strings before comparison
3987 $checkboxparams['checked'] = 'checked';
3990 $lockcheckboxparams = array('type'=>'checkbox', 'id'=>$id.'_locked','name'=>$fullname.'[locked]', 'value'=>1, 'class'=>'form-checkbox');
3991 if (!empty($data['locked'])) { // convert to strings before comparison
3992 $lockcheckboxparams['checked'] = 'checked';
3995 $return = html_writer::start_tag('div', array('class'=>'form-checkbox defaultsnext'));
3996 $return .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>$fullname.'[value]', 'value'=>$novalue));
3997 $return .= html_writer::empty_tag('input', $checkboxparams);
3998 $return .= html_writer::empty_tag('input', $lockcheckboxparams);
3999 $return .= html_writer::tag('label', get_string('locked', 'admin'), array('for'=>$id.'_locked'));
4000 $return .= html_writer::end_tag('div');
4001 return format_admin_setting($this, $this->visiblename, $return, $this->description, true, '', $defaultinfo, $query);
4006 * Dropdown menu with an advanced checkbox, that controls a additional $name.'_adv' setting.
4008 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4010 class admin_setting_configselect_with_advanced extends admin_setting_configselect {
4012 * Calls parent::__construct with specific arguments
4014 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
4015 parent::__construct($name, $visiblename, $description, $defaultsetting, $choices);
4019 * Loads the current setting and returns array
4021 * @return array Returns array value=>xx, adv=>xx
4023 public function get_setting() {
4024 $value = parent::get_setting();
4025 $adv = $this->config_read($this->name.'_adv');
4026 if (is_null($value) or is_null($adv)) {
4027 return NULL;
4029 return array('value' => $value, 'adv' => $adv);
4033 * Saves the new settings passed in $data
4035 * @todo Add vartype handling to ensure $data is an array
4036 * @param array $data
4037 * @return mixed string or Array
4039 public function write_setting($data) {
4040 $error = parent::write_setting($data['value']);
4041 if (!$error) {
4042 $value = empty($data['adv']) ? 0 : 1;
4043 $this->config_write($this->name.'_adv', $value);
4045 return $error;
4049 * Return XHTML for the control
4051 * @param array $data Default data array
4052 * @param string $query
4053 * @return string XHTML to display control
4055 public function output_html($data, $query='') {
4056 $default = $this->get_defaultsetting();
4057 $current = $this->get_setting();
4059 list($selecthtml, $warning) = $this->output_select_html($data['value'],
4060 $current['value'], $default['value'], '[value]');
4061 if (!$selecthtml) {
4062 return '';
4065 if (!is_null($default) and array_key_exists($default['value'], $this->choices)) {
4066 $defaultinfo = array();
4067 if (isset($this->choices[$default['value']])) {
4068 $defaultinfo[] = $this->choices[$default['value']];
4070 if (!empty($default['adv'])) {
4071 $defaultinfo[] = get_string('advanced');
4073 $defaultinfo = implode(', ', $defaultinfo);
4074 } else {
4075 $defaultinfo = '';
4078 $adv = !empty($data['adv']);
4079 $return = '<div class="form-select defaultsnext">' . $selecthtml .
4080 ' <input type="checkbox" class="form-checkbox" id="' .
4081 $this->get_id() . '_adv" name="' . $this->get_full_name() .
4082 '[adv]" value="1" ' . ($adv ? 'checked="checked"' : '') . ' />' .
4083 ' <label for="' . $this->get_id() . '_adv">' .
4084 get_string('advanced') . '</label></div>';
4086 return format_admin_setting($this, $this->visiblename, $return, $this->description, true, $warning, $defaultinfo, $query);
4091 * Graded roles in gradebook
4093 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4095 class admin_setting_special_gradebookroles extends admin_setting_pickroles {
4097 * Calls parent::__construct with specific arguments
4099 public function __construct() {
4100 parent::__construct('gradebookroles', get_string('gradebookroles', 'admin'),
4101 get_string('configgradebookroles', 'admin'),
4102 array('student'));
4108 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4110 class admin_setting_regradingcheckbox extends admin_setting_configcheckbox {
4112 * Saves the new settings passed in $data
4114 * @param string $data
4115 * @return mixed string or Array
4117 public function write_setting($data) {
4118 global $CFG, $DB;
4120 $oldvalue = $this->config_read($this->name);
4121 $return = parent::write_setting($data);
4122 $newvalue = $this->config_read($this->name);
4124 if ($oldvalue !== $newvalue) {
4125 // force full regrading
4126 $DB->set_field('grade_items', 'needsupdate', 1, array('needsupdate'=>0));
4129 return $return;
4134 * Which roles to show on course description page
4136 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4138 class admin_setting_special_coursecontact extends admin_setting_pickroles {
4140 * Calls parent::__construct with specific arguments
4142 public function __construct() {
4143 parent::__construct('coursecontact', get_string('coursecontact', 'admin'),
4144 get_string('coursecontact_desc', 'admin'),
4145 array('editingteacher'));
4151 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4153 class admin_setting_special_gradelimiting extends admin_setting_configcheckbox {
4155 * Calls parent::__construct with specific arguments
4157 function admin_setting_special_gradelimiting() {
4158 parent::__construct('unlimitedgrades', get_string('unlimitedgrades', 'grades'),
4159 get_string('unlimitedgrades_help', 'grades'), '0', '1', '0');
4163 * Force site regrading
4165 function regrade_all() {
4166 global $CFG;
4167 require_once("$CFG->libdir/gradelib.php");
4168 grade_force_site_regrading();
4172 * Saves the new settings
4174 * @param mixed $data
4175 * @return string empty string or error message
4177 function write_setting($data) {
4178 $previous = $this->get_setting();
4180 if ($previous === null) {
4181 if ($data) {
4182 $this->regrade_all();
4184 } else {
4185 if ($data != $previous) {
4186 $this->regrade_all();
4189 return ($this->config_write($this->name, $data) ? '' : get_string('errorsetting', 'admin'));
4195 * Primary grade export plugin - has state tracking.
4197 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4199 class admin_setting_special_gradeexport extends admin_setting_configmulticheckbox {
4201 * Calls parent::__construct with specific arguments
4203 public function __construct() {
4204 parent::__construct('gradeexport', get_string('gradeexport', 'admin'),
4205 get_string('configgradeexport', 'admin'), array(), NULL);
4209 * Load the available choices for the multicheckbox
4211 * @return bool always returns true
4213 public function load_choices() {
4214 if (is_array($this->choices)) {
4215 return true;
4217 $this->choices = array();
4219 if ($plugins = get_plugin_list('gradeexport')) {
4220 foreach($plugins as $plugin => $unused) {
4221 $this->choices[$plugin] = get_string('pluginname', 'gradeexport_'.$plugin);
4224 return true;
4229 * Grade category settings
4231 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4233 class admin_setting_gradecat_combo extends admin_setting {
4234 /** @var array Array of choices */
4235 public $choices;
4238 * Sets choices and calls parent::__construct with passed arguments
4239 * @param string $name
4240 * @param string $visiblename
4241 * @param string $description
4242 * @param mixed $defaultsetting string or array depending on implementation
4243 * @param array $choices An array of choices for the control
4245 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
4246 $this->choices = $choices;
4247 parent::__construct($name, $visiblename, $description, $defaultsetting);
4251 * Return the current setting(s) array
4253 * @return array Array of value=>xx, forced=>xx, adv=>xx
4255 public function get_setting() {
4256 global $CFG;
4258 $value = $this->config_read($this->name);
4259 $flag = $this->config_read($this->name.'_flag');
4261 if (is_null($value) or is_null($flag)) {
4262 return NULL;
4265 $flag = (int)$flag;
4266 $forced = (boolean)(1 & $flag); // first bit
4267 $adv = (boolean)(2 & $flag); // second bit
4269 return array('value' => $value, 'forced' => $forced, 'adv' => $adv);
4273 * Save the new settings passed in $data
4275 * @todo Add vartype handling to ensure $data is array
4276 * @param array $data Associative array of value=>xx, forced=>xx, adv=>xx
4277 * @return string empty or error message
4279 public function write_setting($data) {
4280 global $CFG;
4282 $value = $data['value'];
4283 $forced = empty($data['forced']) ? 0 : 1;
4284 $adv = empty($data['adv']) ? 0 : 2;
4285 $flag = ($forced | $adv); //bitwise or
4287 if (!in_array($value, array_keys($this->choices))) {
4288 return 'Error setting ';
4291 $oldvalue = $this->config_read($this->name);
4292 $oldflag = (int)$this->config_read($this->name.'_flag');
4293 $oldforced = (1 & $oldflag); // first bit
4295 $result1 = $this->config_write($this->name, $value);
4296 $result2 = $this->config_write($this->name.'_flag', $flag);
4298 // force regrade if needed
4299 if ($oldforced != $forced or ($forced and $value != $oldvalue)) {
4300 require_once($CFG->libdir.'/gradelib.php');
4301 grade_category::updated_forced_settings();
4304 if ($result1 and $result2) {
4305 return '';
4306 } else {
4307 return get_string('errorsetting', 'admin');
4312 * Return XHTML to display the field and wrapping div
4314 * @todo Add vartype handling to ensure $data is array
4315 * @param array $data Associative array of value=>xx, forced=>xx, adv=>xx
4316 * @param string $query
4317 * @return string XHTML to display control
4319 public function output_html($data, $query='') {
4320 $value = $data['value'];
4321 $forced = !empty($data['forced']);
4322 $adv = !empty($data['adv']);
4324 $default = $this->get_defaultsetting();
4325 if (!is_null($default)) {
4326 $defaultinfo = array();
4327 if (isset($this->choices[$default['value']])) {
4328 $defaultinfo[] = $this->choices[$default['value']];
4330 if (!empty($default['forced'])) {
4331 $defaultinfo[] = get_string('force');
4333 if (!empty($default['adv'])) {
4334 $defaultinfo[] = get_string('advanced');
4336 $defaultinfo = implode(', ', $defaultinfo);
4338 } else {
4339 $defaultinfo = NULL;
4343 $return = '<div class="form-group">';
4344 $return .= '<select class="form-select" id="'.$this->get_id().'" name="'.$this->get_full_name().'[value]">';
4345 foreach ($this->choices as $key => $val) {
4346 // the string cast is needed because key may be integer - 0 is equal to most strings!
4347 $return .= '<option value="'.$key.'"'.((string)$key==$value ? ' selected="selected"' : '').'>'.$val.'</option>';
4349 $return .= '</select>';
4350 $return .= '<input type="checkbox" class="form-checkbox" id="'.$this->get_id().'force" name="'.$this->get_full_name().'[forced]" value="1" '.($forced ? 'checked="checked"' : '').' />'
4351 .'<label for="'.$this->get_id().'force">'.get_string('force').'</label>';
4352 $return .= '<input type="checkbox" class="form-checkbox" id="'.$this->get_id().'adv" name="'.$this->get_full_name().'[adv]" value="1" '.($adv ? 'checked="checked"' : '').' />'
4353 .'<label for="'.$this->get_id().'adv">'.get_string('advanced').'</label>';
4354 $return .= '</div>';
4356 return format_admin_setting($this, $this->visiblename, $return, $this->description, true, '', $defaultinfo, $query);
4362 * Selection of grade report in user profiles
4364 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4366 class admin_setting_grade_profilereport extends admin_setting_configselect {
4368 * Calls parent::__construct with specific arguments
4370 public function __construct() {
4371 parent::__construct('grade_profilereport', get_string('profilereport', 'grades'), get_string('profilereport_help', 'grades'), 'user', null);
4375 * Loads an array of choices for the configselect control
4377 * @return bool always return true
4379 public function load_choices() {
4380 if (is_array($this->choices)) {
4381 return true;
4383 $this->choices = array();
4385 global $CFG;
4386 require_once($CFG->libdir.'/gradelib.php');
4388 foreach (get_plugin_list('gradereport') as $plugin => $plugindir) {
4389 if (file_exists($plugindir.'/lib.php')) {
4390 require_once($plugindir.'/lib.php');
4391 $functionname = 'grade_report_'.$plugin.'_profilereport';
4392 if (function_exists($functionname)) {
4393 $this->choices[$plugin] = get_string('pluginname', 'gradereport_'.$plugin);
4397 return true;
4402 * Special class for register auth selection
4404 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4406 class admin_setting_special_registerauth extends admin_setting_configselect {
4408 * Calls parent::__construct with specific arguments
4410 public function __construct() {
4411 parent::__construct('registerauth', get_string('selfregistration', 'auth'), get_string('selfregistration_help', 'auth'), '', null);
4415 * Returns the default option
4417 * @return string empty or default option
4419 public function get_defaultsetting() {
4420 $this->load_choices();
4421 $defaultsetting = parent::get_defaultsetting();
4422 if (array_key_exists($defaultsetting, $this->choices)) {
4423 return $defaultsetting;
4424 } else {
4425 return '';
4430 * Loads the possible choices for the array
4432 * @return bool always returns true
4434 public function load_choices() {
4435 global $CFG;
4437 if (is_array($this->choices)) {
4438 return true;
4440 $this->choices = array();
4441 $this->choices[''] = get_string('disable');
4443 $authsenabled = get_enabled_auth_plugins(true);
4445 foreach ($authsenabled as $auth) {
4446 $authplugin = get_auth_plugin($auth);
4447 if (!$authplugin->can_signup()) {
4448 continue;
4450 // Get the auth title (from core or own auth lang files)
4451 $authtitle = $authplugin->get_title();
4452 $this->choices[$auth] = $authtitle;
4454 return true;
4459 * Module manage page
4461 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4463 class admin_page_managemods extends admin_externalpage {
4465 * Calls parent::__construct with specific arguments
4467 public function __construct() {
4468 global $CFG;
4469 parent::__construct('managemodules', get_string('modsettings', 'admin'), "$CFG->wwwroot/$CFG->admin/modules.php");
4473 * Try to find the specified module
4475 * @param string $query The module to search for
4476 * @return array
4478 public function search($query) {
4479 global $CFG, $DB;
4480 if ($result = parent::search($query)) {
4481 return $result;
4484 $found = false;
4485 if ($modules = $DB->get_records('modules')) {
4486 $textlib = textlib_get_instance();
4487 foreach ($modules as $module) {
4488 if (!file_exists("$CFG->dirroot/mod/$module->name/lib.php")) {
4489 continue;
4491 if (strpos($module->name, $query) !== false) {
4492 $found = true;
4493 break;
4495 $strmodulename = get_string('modulename', $module->name);
4496 if (strpos($textlib->strtolower($strmodulename), $query) !== false) {
4497 $found = true;
4498 break;
4502 if ($found) {
4503 $result = new stdClass();
4504 $result->page = $this;
4505 $result->settings = array();
4506 return array($this->name => $result);
4507 } else {
4508 return array();
4515 * Special class for enrol plugins management.
4517 * @copyright 2010 Petr Skoda {@link http://skodak.org}
4518 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4520 class admin_setting_manageenrols extends admin_setting {
4522 * Calls parent::__construct with specific arguments
4524 public function __construct() {
4525 $this->nosave = true;
4526 parent::__construct('enrolsui', get_string('manageenrols', 'enrol'), '', '');
4530 * Always returns true, does nothing
4532 * @return true
4534 public function get_setting() {
4535 return true;
4539 * Always returns true, does nothing
4541 * @return true
4543 public function get_defaultsetting() {
4544 return true;
4548 * Always returns '', does not write anything
4550 * @return string Always returns ''
4552 public function write_setting($data) {
4553 // do not write any setting
4554 return '';
4558 * Checks if $query is one of the available enrol plugins
4560 * @param string $query The string to search for
4561 * @return bool Returns true if found, false if not
4563 public function is_related($query) {
4564 if (parent::is_related($query)) {
4565 return true;
4568 $textlib = textlib_get_instance();
4569 $query = $textlib->strtolower($query);
4570 $enrols = enrol_get_plugins(false);
4571 foreach ($enrols as $name=>$enrol) {
4572 $localised = get_string('pluginname', 'enrol_'.$name);
4573 if (strpos($textlib->strtolower($name), $query) !== false) {
4574 return true;
4576 if (strpos($textlib->strtolower($localised), $query) !== false) {
4577 return true;
4580 return false;
4584 * Builds the XHTML to display the control
4586 * @param string $data Unused
4587 * @param string $query
4588 * @return string
4590 public function output_html($data, $query='') {
4591 global $CFG, $OUTPUT, $DB;
4593 // display strings
4594 $strup = get_string('up');
4595 $strdown = get_string('down');
4596 $strsettings = get_string('settings');
4597 $strenable = get_string('enable');
4598 $strdisable = get_string('disable');
4599 $struninstall = get_string('uninstallplugin', 'admin');
4600 $strusage = get_string('enrolusage', 'enrol');
4602 $enrols_available = enrol_get_plugins(false);
4603 $active_enrols = enrol_get_plugins(true);
4605 $allenrols = array();
4606 foreach ($active_enrols as $key=>$enrol) {
4607 $allenrols[$key] = true;
4609 foreach ($enrols_available as $key=>$enrol) {
4610 $allenrols[$key] = true;
4612 // now find all borked plugins and at least allow then to uninstall
4613 $borked = array();
4614 $condidates = $DB->get_fieldset_sql("SELECT DISTINCT enrol FROM {enrol}");
4615 foreach ($condidates as $candidate) {
4616 if (empty($allenrols[$candidate])) {
4617 $allenrols[$candidate] = true;
4621 $return = $OUTPUT->heading(get_string('actenrolshhdr', 'enrol'), 3, 'main', true);
4622 $return .= $OUTPUT->box_start('generalbox enrolsui');
4624 $table = new html_table();
4625 $table->head = array(get_string('name'), $strusage, $strenable, $strup.'/'.$strdown, $strsettings, $struninstall);
4626 $table->align = array('left', 'center', 'center', 'center', 'center', 'center');
4627 $table->width = '90%';
4628 $table->data = array();
4630 // iterate through enrol plugins and add to the display table
4631 $updowncount = 1;
4632 $enrolcount = count($active_enrols);
4633 $url = new moodle_url('/admin/enrol.php', array('sesskey'=>sesskey()));
4634 $printed = array();
4635 foreach($allenrols as $enrol => $unused) {
4636 if (get_string_manager()->string_exists('pluginname', 'enrol_'.$enrol)) {
4637 $name = get_string('pluginname', 'enrol_'.$enrol);
4638 } else {
4639 $name = $enrol;
4641 //usage
4642 $ci = $DB->count_records('enrol', array('enrol'=>$enrol));
4643 $cp = $DB->count_records_select('user_enrolments', "enrolid IN (SELECT id FROM {enrol} WHERE enrol = ?)", array($enrol));
4644 $usage = "$ci / $cp";
4646 // hide/show link
4647 if (isset($active_enrols[$enrol])) {
4648 $aurl = new moodle_url($url, array('action'=>'disable', 'enrol'=>$enrol));
4649 $hideshow = "<a href=\"$aurl\">";
4650 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('i/hide') . "\" class=\"icon\" alt=\"$strdisable\" /></a>";
4651 $enabled = true;
4652 $displayname = "<span>$name</span>";
4653 } else if (isset($enrols_available[$enrol])) {
4654 $aurl = new moodle_url($url, array('action'=>'enable', 'enrol'=>$enrol));
4655 $hideshow = "<a href=\"$aurl\">";
4656 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('i/show') . "\" class=\"icon\" alt=\"$strenable\" /></a>";
4657 $enabled = false;
4658 $displayname = "<span class=\"dimmed_text\">$name</span>";
4659 } else {
4660 $hideshow = '';
4661 $enabled = false;
4662 $displayname = '<span class="notifyproblem">'.$name.'</span>';
4665 // up/down link (only if enrol is enabled)
4666 $updown = '';
4667 if ($enabled) {
4668 if ($updowncount > 1) {
4669 $aurl = new moodle_url($url, array('action'=>'up', 'enrol'=>$enrol));
4670 $updown .= "<a href=\"$aurl\">";
4671 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/up') . "\" alt=\"$strup\" /></a>&nbsp;";
4672 } else {
4673 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"icon\" alt=\"\" />&nbsp;";
4675 if ($updowncount < $enrolcount) {
4676 $aurl = new moodle_url($url, array('action'=>'down', 'enrol'=>$enrol));
4677 $updown .= "<a href=\"$aurl\">";
4678 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/down') . "\" alt=\"$strdown\" /></a>";
4679 } else {
4680 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"icon\" alt=\"\" />";
4682 ++$updowncount;
4685 // settings link
4686 if (isset($active_enrols[$enrol]) or file_exists($CFG->dirroot.'/enrol/'.$enrol.'/settings.php')) {
4687 $surl = new moodle_url('/admin/settings.php', array('section'=>'enrolsettings'.$enrol));
4688 $settings = "<a href=\"$surl\">$strsettings</a>";
4689 } else {
4690 $settings = '';
4693 // uninstall
4694 $aurl = new moodle_url($url, array('action'=>'uninstall', 'enrol'=>$enrol));
4695 $uninstall = "<a href=\"$aurl\">$struninstall</a>";
4697 // add a row to the table
4698 $table->data[] = array($displayname, $usage, $hideshow, $updown, $settings, $uninstall);
4700 $printed[$enrol] = true;
4703 $return .= html_writer::table($table);
4704 $return .= get_string('configenrolplugins', 'enrol').'<br />'.get_string('tablenosave', 'admin');
4705 $return .= $OUTPUT->box_end();
4706 return highlight($query, $return);
4712 * Blocks manage page
4714 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4716 class admin_page_manageblocks extends admin_externalpage {
4718 * Calls parent::__construct with specific arguments
4720 public function __construct() {
4721 global $CFG;
4722 parent::__construct('manageblocks', get_string('blocksettings', 'admin'), "$CFG->wwwroot/$CFG->admin/blocks.php");
4726 * Search for a specific block
4728 * @param string $query The string to search for
4729 * @return array
4731 public function search($query) {
4732 global $CFG, $DB;
4733 if ($result = parent::search($query)) {
4734 return $result;
4737 $found = false;
4738 if ($blocks = $DB->get_records('block')) {
4739 $textlib = textlib_get_instance();
4740 foreach ($blocks as $block) {
4741 if (!file_exists("$CFG->dirroot/blocks/$block->name/")) {
4742 continue;
4744 if (strpos($block->name, $query) !== false) {
4745 $found = true;
4746 break;
4748 $strblockname = get_string('pluginname', 'block_'.$block->name);
4749 if (strpos($textlib->strtolower($strblockname), $query) !== false) {
4750 $found = true;
4751 break;
4755 if ($found) {
4756 $result = new stdClass();
4757 $result->page = $this;
4758 $result->settings = array();
4759 return array($this->name => $result);
4760 } else {
4761 return array();
4767 * Question type manage page
4769 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4771 class admin_page_manageqtypes extends admin_externalpage {
4773 * Calls parent::__construct with specific arguments
4775 public function __construct() {
4776 global $CFG;
4777 parent::__construct('manageqtypes', get_string('manageqtypes', 'admin'), "$CFG->wwwroot/$CFG->admin/qtypes.php");
4781 * Search QTYPES for the specified string
4783 * @param string $query The string to search for in QTYPES
4784 * @return array
4786 public function search($query) {
4787 global $CFG;
4788 if ($result = parent::search($query)) {
4789 return $result;
4792 $found = false;
4793 $textlib = textlib_get_instance();
4794 require_once($CFG->libdir . '/questionlib.php');
4795 global $QTYPES;
4796 foreach ($QTYPES as $qtype) {
4797 if (strpos($textlib->strtolower($qtype->local_name()), $query) !== false) {
4798 $found = true;
4799 break;
4802 if ($found) {
4803 $result = new stdClass();
4804 $result->page = $this;
4805 $result->settings = array();
4806 return array($this->name => $result);
4807 } else {
4808 return array();
4814 * Special class for authentication administration.
4816 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4818 class admin_setting_manageauths extends admin_setting {
4820 * Calls parent::__construct with specific arguments
4822 public function __construct() {
4823 $this->nosave = true;
4824 parent::__construct('authsui', get_string('authsettings', 'admin'), '', '');
4828 * Always returns true
4830 * @return true
4832 public function get_setting() {
4833 return true;
4837 * Always returns true
4839 * @return true
4841 public function get_defaultsetting() {
4842 return true;
4846 * Always returns '' and doesn't write anything
4848 * @return string Always returns ''
4850 public function write_setting($data) {
4851 // do not write any setting
4852 return '';
4856 * Search to find if Query is related to auth plugin
4858 * @param string $query The string to search for
4859 * @return bool true for related false for not
4861 public function is_related($query) {
4862 if (parent::is_related($query)) {
4863 return true;
4866 $textlib = textlib_get_instance();
4867 $authsavailable = get_plugin_list('auth');
4868 foreach ($authsavailable as $auth => $dir) {
4869 if (strpos($auth, $query) !== false) {
4870 return true;
4872 $authplugin = get_auth_plugin($auth);
4873 $authtitle = $authplugin->get_title();
4874 if (strpos($textlib->strtolower($authtitle), $query) !== false) {
4875 return true;
4878 return false;
4882 * Return XHTML to display control
4884 * @param mixed $data Unused
4885 * @param string $query
4886 * @return string highlight
4888 public function output_html($data, $query='') {
4889 global $CFG, $OUTPUT;
4892 // display strings
4893 $txt = get_strings(array('authenticationplugins', 'users', 'administration',
4894 'settings', 'edit', 'name', 'enable', 'disable',
4895 'up', 'down', 'none'));
4896 $txt->updown = "$txt->up/$txt->down";
4898 $authsavailable = get_plugin_list('auth');
4899 get_enabled_auth_plugins(true); // fix the list of enabled auths
4900 if (empty($CFG->auth)) {
4901 $authsenabled = array();
4902 } else {
4903 $authsenabled = explode(',', $CFG->auth);
4906 // construct the display array, with enabled auth plugins at the top, in order
4907 $displayauths = array();
4908 $registrationauths = array();
4909 $registrationauths[''] = $txt->disable;
4910 foreach ($authsenabled as $auth) {
4911 $authplugin = get_auth_plugin($auth);
4912 /// Get the auth title (from core or own auth lang files)
4913 $authtitle = $authplugin->get_title();
4914 /// Apply titles
4915 $displayauths[$auth] = $authtitle;
4916 if ($authplugin->can_signup()) {
4917 $registrationauths[$auth] = $authtitle;
4921 foreach ($authsavailable as $auth => $dir) {
4922 if (array_key_exists($auth, $displayauths)) {
4923 continue; //already in the list
4925 $authplugin = get_auth_plugin($auth);
4926 /// Get the auth title (from core or own auth lang files)
4927 $authtitle = $authplugin->get_title();
4928 /// Apply titles
4929 $displayauths[$auth] = $authtitle;
4930 if ($authplugin->can_signup()) {
4931 $registrationauths[$auth] = $authtitle;
4935 $return = $OUTPUT->heading(get_string('actauthhdr', 'auth'), 3, 'main');
4936 $return .= $OUTPUT->box_start('generalbox authsui');
4938 $table = new html_table();
4939 $table->head = array($txt->name, $txt->enable, $txt->updown, $txt->settings);
4940 $table->align = array('left', 'center', 'center', 'center');
4941 $table->data = array();
4942 $table->attributes['class'] = 'manageauthtable generaltable';
4944 //add always enabled plugins first
4945 $displayname = "<span>".$displayauths['manual']."</span>";
4946 $settings = "<a href=\"auth_config.php?auth=manual\">{$txt->settings}</a>";
4947 //$settings = "<a href=\"settings.php?section=authsettingmanual\">{$txt->settings}</a>";
4948 $table->data[] = array($displayname, '', '', $settings);
4949 $displayname = "<span>".$displayauths['nologin']."</span>";
4950 $settings = "<a href=\"auth_config.php?auth=nologin\">{$txt->settings}</a>";
4951 $table->data[] = array($displayname, '', '', $settings);
4954 // iterate through auth plugins and add to the display table
4955 $updowncount = 1;
4956 $authcount = count($authsenabled);
4957 $url = "auth.php?sesskey=" . sesskey();
4958 foreach ($displayauths as $auth => $name) {
4959 if ($auth == 'manual' or $auth == 'nologin') {
4960 continue;
4962 // hide/show link
4963 if (in_array($auth, $authsenabled)) {
4964 $hideshow = "<a href=\"$url&amp;action=disable&amp;auth=$auth\">";
4965 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('i/hide') . "\" class=\"icon\" alt=\"disable\" /></a>";
4966 // $hideshow = "<a href=\"$url&amp;action=disable&amp;auth=$auth\"><input type=\"checkbox\" checked /></a>";
4967 $enabled = true;
4968 $displayname = "<span>$name</span>";
4970 else {
4971 $hideshow = "<a href=\"$url&amp;action=enable&amp;auth=$auth\">";
4972 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('i/show') . "\" class=\"icon\" alt=\"enable\" /></a>";
4973 // $hideshow = "<a href=\"$url&amp;action=enable&amp;auth=$auth\"><input type=\"checkbox\" /></a>";
4974 $enabled = false;
4975 $displayname = "<span class=\"dimmed_text\">$name</span>";
4978 // up/down link (only if auth is enabled)
4979 $updown = '';
4980 if ($enabled) {
4981 if ($updowncount > 1) {
4982 $updown .= "<a href=\"$url&amp;action=up&amp;auth=$auth\">";
4983 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/up') . "\" alt=\"up\" /></a>&nbsp;";
4985 else {
4986 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"icon\" alt=\"\" />&nbsp;";
4988 if ($updowncount < $authcount) {
4989 $updown .= "<a href=\"$url&amp;action=down&amp;auth=$auth\">";
4990 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/down') . "\" alt=\"down\" /></a>";
4992 else {
4993 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"icon\" alt=\"\" />";
4995 ++ $updowncount;
4998 // settings link
4999 if (file_exists($CFG->dirroot.'/auth/'.$auth.'/settings.php')) {
5000 $settings = "<a href=\"settings.php?section=authsetting$auth\">{$txt->settings}</a>";
5001 } else {
5002 $settings = "<a href=\"auth_config.php?auth=$auth\">{$txt->settings}</a>";
5005 // add a row to the table
5006 $table->data[] =array($displayname, $hideshow, $updown, $settings);
5008 $return .= html_writer::table($table);
5009 $return .= get_string('configauthenticationplugins', 'admin').'<br />'.get_string('tablenosave', 'filters');
5010 $return .= $OUTPUT->box_end();
5011 return highlight($query, $return);
5016 * Special class for authentication administration.
5018 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5020 class admin_setting_manageeditors extends admin_setting {
5022 * Calls parent::__construct with specific arguments
5024 public function __construct() {
5025 $this->nosave = true;
5026 parent::__construct('editorsui', get_string('editorsettings', 'editor'), '', '');
5030 * Always returns true, does nothing
5032 * @return true
5034 public function get_setting() {
5035 return true;
5039 * Always returns true, does nothing
5041 * @return true
5043 public function get_defaultsetting() {
5044 return true;
5048 * Always returns '', does not write anything
5050 * @return string Always returns ''
5052 public function write_setting($data) {
5053 // do not write any setting
5054 return '';
5058 * Checks if $query is one of the available editors
5060 * @param string $query The string to search for
5061 * @return bool Returns true if found, false if not
5063 public function is_related($query) {
5064 if (parent::is_related($query)) {
5065 return true;
5068 $textlib = textlib_get_instance();
5069 $editors_available = editors_get_available();
5070 foreach ($editors_available as $editor=>$editorstr) {
5071 if (strpos($editor, $query) !== false) {
5072 return true;
5074 if (strpos($textlib->strtolower($editorstr), $query) !== false) {
5075 return true;
5078 return false;
5082 * Builds the XHTML to display the control
5084 * @param string $data Unused
5085 * @param string $query
5086 * @return string
5088 public function output_html($data, $query='') {
5089 global $CFG, $OUTPUT;
5091 // display strings
5092 $txt = get_strings(array('administration', 'settings', 'edit', 'name', 'enable', 'disable',
5093 'up', 'down', 'none'));
5094 $txt->updown = "$txt->up/$txt->down";
5096 $editors_available = editors_get_available();
5097 $active_editors = explode(',', $CFG->texteditors);
5099 $active_editors = array_reverse($active_editors);
5100 foreach ($active_editors as $key=>$editor) {
5101 if (empty($editors_available[$editor])) {
5102 unset($active_editors[$key]);
5103 } else {
5104 $name = $editors_available[$editor];
5105 unset($editors_available[$editor]);
5106 $editors_available[$editor] = $name;
5109 if (empty($active_editors)) {
5110 //$active_editors = array('textarea');
5112 $editors_available = array_reverse($editors_available, true);
5113 $return = $OUTPUT->heading(get_string('acteditorshhdr', 'editor'), 3, 'main', true);
5114 $return .= $OUTPUT->box_start('generalbox editorsui');
5116 $table = new html_table();
5117 $table->head = array($txt->name, $txt->enable, $txt->updown, $txt->settings);
5118 $table->align = array('left', 'center', 'center', 'center');
5119 $table->width = '90%';
5120 $table->data = array();
5122 // iterate through auth plugins and add to the display table
5123 $updowncount = 1;
5124 $editorcount = count($active_editors);
5125 $url = "editors.php?sesskey=" . sesskey();
5126 foreach ($editors_available as $editor => $name) {
5127 // hide/show link
5128 if (in_array($editor, $active_editors)) {
5129 $hideshow = "<a href=\"$url&amp;action=disable&amp;editor=$editor\">";
5130 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('i/hide') . "\" class=\"icon\" alt=\"disable\" /></a>";
5131 // $hideshow = "<a href=\"$url&amp;action=disable&amp;editor=$editor\"><input type=\"checkbox\" checked /></a>";
5132 $enabled = true;
5133 $displayname = "<span>$name</span>";
5135 else {
5136 $hideshow = "<a href=\"$url&amp;action=enable&amp;editor=$editor\">";
5137 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('i/show') . "\" class=\"icon\" alt=\"enable\" /></a>";
5138 // $hideshow = "<a href=\"$url&amp;action=enable&amp;editor=$editor\"><input type=\"checkbox\" /></a>";
5139 $enabled = false;
5140 $displayname = "<span class=\"dimmed_text\">$name</span>";
5143 // up/down link (only if auth is enabled)
5144 $updown = '';
5145 if ($enabled) {
5146 if ($updowncount > 1) {
5147 $updown .= "<a href=\"$url&amp;action=up&amp;editor=$editor\">";
5148 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/up') . "\" alt=\"up\" /></a>&nbsp;";
5150 else {
5151 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"icon\" alt=\"\" />&nbsp;";
5153 if ($updowncount < $editorcount) {
5154 $updown .= "<a href=\"$url&amp;action=down&amp;editor=$editor\">";
5155 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/down') . "\" alt=\"down\" /></a>";
5157 else {
5158 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"icon\" alt=\"\" />";
5160 ++ $updowncount;
5163 // settings link
5164 if (file_exists($CFG->dirroot.'/lib/editor/'.$editor.'/settings.php')) {
5165 $eurl = new moodle_url('/admin/settings.php', array('section'=>'editorsettingstinymce'));
5166 $settings = "<a href='$eurl'>{$txt->settings}</a>";
5167 } else {
5168 $settings = '';
5171 // add a row to the table
5172 $table->data[] =array($displayname, $hideshow, $updown, $settings);
5174 $return .= html_writer::table($table);
5175 $return .= get_string('configeditorplugins', 'editor').'<br />'.get_string('tablenosave', 'admin');
5176 $return .= $OUTPUT->box_end();
5177 return highlight($query, $return);
5182 * Special class for license administration.
5184 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5186 class admin_setting_managelicenses extends admin_setting {
5188 * Calls parent::__construct with specific arguments
5190 public function __construct() {
5191 $this->nosave = true;
5192 parent::__construct('licensesui', get_string('licensesettings', 'admin'), '', '');
5196 * Always returns true, does nothing
5198 * @return true
5200 public function get_setting() {
5201 return true;
5205 * Always returns true, does nothing
5207 * @return true
5209 public function get_defaultsetting() {
5210 return true;
5214 * Always returns '', does not write anything
5216 * @return string Always returns ''
5218 public function write_setting($data) {
5219 // do not write any setting
5220 return '';
5224 * Builds the XHTML to display the control
5226 * @param string $data Unused
5227 * @param string $query
5228 * @return string
5230 public function output_html($data, $query='') {
5231 global $CFG, $OUTPUT;
5232 require_once($CFG->libdir . '/licenselib.php');
5233 $url = "licenses.php?sesskey=" . sesskey();
5235 // display strings
5236 $txt = get_strings(array('administration', 'settings', 'name', 'enable', 'disable', 'none'));
5237 $licenses = license_manager::get_licenses();
5239 $return = $OUTPUT->heading(get_string('availablelicenses', 'admin'), 3, 'main', true);
5241 $return .= $OUTPUT->box_start('generalbox editorsui');
5243 $table = new html_table();
5244 $table->head = array($txt->name, $txt->enable);
5245 $table->align = array('left', 'center');
5246 $table->width = '100%';
5247 $table->data = array();
5249 foreach ($licenses as $value) {
5250 $displayname = html_writer::link($value->source, get_string($value->shortname, 'license'), array('target'=>'_blank'));
5252 if ($value->enabled == 1) {
5253 $hideshow = html_writer::link($url.'&action=disable&license='.$value->shortname,
5254 html_writer::tag('img', '', array('src'=>$OUTPUT->pix_url('i/hide'), 'class'=>'icon', 'alt'=>'disable')));
5255 } else {
5256 $hideshow = html_writer::link($url.'&action=enable&license='.$value->shortname,
5257 html_writer::tag('img', '', array('src'=>$OUTPUT->pix_url('i/show'), 'class'=>'icon', 'alt'=>'enable')));
5260 if ($value->shortname == $CFG->sitedefaultlicense) {
5261 $displayname .= ' '.html_writer::tag('img', '', array('src'=>$OUTPUT->pix_url('i/lock'), 'class'=>'icon', 'alt'=>get_string('default'), 'title'=>get_string('default')));
5262 $hideshow = '';
5265 $enabled = true;
5267 $table->data[] =array($displayname, $hideshow);
5269 $return .= html_writer::table($table);
5270 $return .= $OUTPUT->box_end();
5271 return highlight($query, $return);
5275 * Special class for filter administration.
5277 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5279 class admin_page_managefilters extends admin_externalpage {
5281 * Calls parent::__construct with specific arguments
5283 public function __construct() {
5284 global $CFG;
5285 parent::__construct('managefilters', get_string('filtersettings', 'admin'), "$CFG->wwwroot/$CFG->admin/filters.php");
5289 * Searches all installed filters for specified filter
5291 * @param string $query The filter(string) to search for
5292 * @param string $query
5294 public function search($query) {
5295 global $CFG;
5296 if ($result = parent::search($query)) {
5297 return $result;
5300 $found = false;
5301 $filternames = filter_get_all_installed();
5302 $textlib = textlib_get_instance();
5303 foreach ($filternames as $path => $strfiltername) {
5304 if (strpos($textlib->strtolower($strfiltername), $query) !== false) {
5305 $found = true;
5306 break;
5308 list($type, $filter) = explode('/', $path);
5309 if (strpos($filter, $query) !== false) {
5310 $found = true;
5311 break;
5315 if ($found) {
5316 $result = new stdClass;
5317 $result->page = $this;
5318 $result->settings = array();
5319 return array($this->name => $result);
5320 } else {
5321 return array();
5328 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5330 class admin_setting_manageportfolio extends admin_setting {
5331 private $baseurl;
5333 public function __construct() {
5334 global $CFG;
5335 $this->nosave = true;
5336 parent::__construct('manageportfolio', get_string('manageportfolios', 'portfolio'), '', '');
5337 $this->baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/portfolio.php?sesskey=' . sesskey();
5341 * Always returns true, does nothing
5343 * @return true
5345 public function get_setting() {
5346 return true;
5350 * Always returns true, does nothing
5352 * @return true
5354 public function get_defaultsetting() {
5355 return true;
5359 * Always returns '', does not write anything
5361 * @return string Always returns ''
5363 public function write_setting($data) {
5364 return '';
5368 * Helper function that generates a moodle_url object
5369 * relevant to the portfolio
5372 function portfolio_action_url($portfolio) {
5373 return new moodle_url($this->baseurl, array('sesskey'=>sesskey(), 'pf'=>$portfolio));
5377 * Searches the portfolio types for the specified type(string)
5379 * @param string $query The string to search for
5380 * @return bool true for found or related, false for not
5382 public function is_related($query) {
5383 if (parent::is_related($query)) {
5384 return true;
5387 $textlib = textlib_get_instance();
5388 $portfolios = get_plugin_list('portfolio');
5389 foreach ($portfolios as $p => $dir) {
5390 if (strpos($p, $query) !== false) {
5391 return true;
5394 foreach (portfolio_instances(false, false) as $instance) {
5395 $title = $instance->get('name');
5396 if (strpos($textlib->strtolower($title), $query) !== false) {
5397 return true;
5400 return false;
5404 * Builds XHTML to display the control
5406 * @param string $data Unused
5407 * @param string $query
5408 * @return string XHTML to display the control
5410 public function output_html($data, $query='') {
5411 global $CFG, $OUTPUT;
5413 // Get strings that are used
5414 $strshow = get_string('on', 'portfolio');
5415 $strhide = get_string('off', 'portfolio');
5416 $strdelete = get_string('disabledinstance', 'portfolio');
5417 $strsettings = get_string('settings');
5419 $actionchoicesforexisting = array(
5420 'show' => $strshow,
5421 'hide' => $strhide,
5422 'delete' => $strdelete
5425 $actionchoicesfornew = array(
5426 'newon' => $strshow,
5427 'newoff' => $strhide,
5428 'delete' => $strdelete
5431 $output = $OUTPUT->box_start('generalbox');
5433 $plugins = get_plugin_list('portfolio');
5434 $plugins = array_keys($plugins);
5435 $instances = portfolio_instances(false, false);
5436 $usedplugins = array();
5438 // to avoid notifications being sent out while admin is editing the page
5439 define('ADMIN_EDITING_PORTFOLIO', true);
5441 $insane = portfolio_plugin_sanity_check($plugins);
5442 $insaneinstances = portfolio_instance_sanity_check($instances);
5444 $table = new html_table();
5445 $table->head = array(get_string('plugin', 'portfolio'), '', '');
5446 $table->data = array();
5448 foreach ($instances as $i) {
5449 $settings = '<a href="' . $this->baseurl . '&amp;action=edit&amp;pf=' . $i->get('id') . '">' . $strsettings .'</a>';
5450 // Set some commonly used variables
5451 $pluginid = $i->get('id');
5452 $plugin = $i->get('plugin');
5453 $pluginname = $i->get('name');
5455 // Check if the instance is misconfigured
5456 if (array_key_exists($plugin, $insane) || array_key_exists($pluginid, $insaneinstances)) {
5457 if (!empty($insane[$plugin])) {
5458 $information = $insane[$plugin];
5459 } else if (!empty($insaneinstances[$pluginid])) {
5460 $information = $insaneinstances[$pluginid];
5462 $table->data[] = array($pluginname, $strdelete . " " . $OUTPUT->help_icon($information, 'portfolio_' . $plugin), $settings);
5463 } else {
5464 if ($i->get('visible')) {
5465 $currentaction = 'show';
5466 } else {
5467 $currentaction = 'hide';
5469 $select = new single_select($this->portfolio_action_url($pluginid, 'pf'), 'action', $actionchoicesforexisting, $currentaction, null, 'applyto' . $pluginid);
5470 $table->data[] = array($pluginname, $OUTPUT->render($select), $settings);
5472 if (!in_array($plugin, $usedplugins)) {
5473 $usedplugins[] = $plugin;
5477 // Create insane plugin array
5478 $insaneplugins = array();
5479 if (!empty($plugins)) {
5480 foreach ($plugins as $p) {
5481 // Check if it can not have multiple instances and has already been used
5482 if (!portfolio_static_function($p, 'allows_multiple_instances') && in_array($p, $usedplugins)) {
5483 continue;
5486 // Check if it is misconfigured - if so store in array then display later
5487 if (array_key_exists($p, $insane)) {
5488 $insaneplugins[] = $p;
5489 } else {
5490 $select = new single_select($this->portfolio_action_url($p, 'pf'), 'action', $actionchoicesfornew, 'delete', null, 'applyto' . $p);
5491 $table->data[] = array(portfolio_static_function($p, 'get_name'), $OUTPUT->render($select), '');
5496 // Loop through all the insane plugins
5497 if (!empty($insaneplugins)) {
5498 foreach ($insaneplugins as $p) {
5499 $table->data[] = array(portfolio_static_function($p, 'get_name'), $strdelete . " " . $OUTPUT->help_icon($insane[$p], 'portfolio_' . $p), '');
5503 $output .= html_writer::table($table);
5505 $output .= $OUTPUT->box_end();
5507 return highlight($query, $output);
5513 * Initialise admin page - this function does require login and permission
5514 * checks specified in page definition.
5516 * This function must be called on each admin page before other code.
5518 * @param string $section name of page
5519 * @param string $extrabutton extra HTML that is added after the blocks editing on/off button.
5520 * @param array $extraurlparams an array paramname => paramvalue, or parameters that need to be
5521 * added to the turn blocks editing on/off form, so this page reloads correctly.
5522 * @param string $actualurl if the actual page being viewed is not the normal one for this
5523 * page (e.g. admin/roles/allowassin.php, instead of admin/roles/manage.php, you can pass the alternate URL here.
5525 function admin_externalpage_setup($section, $extrabutton = '', array $extraurlparams = null, $actualurl = '') {
5526 global $CFG, $PAGE, $USER, $SITE, $OUTPUT;
5528 $PAGE->set_context(null); // hack - set context to something, by default to system context
5530 $site = get_site();
5531 require_login();
5533 $adminroot = admin_get_root(false, false); // settings not required for external pages
5534 $extpage = $adminroot->locate($section, true);
5536 if (empty($extpage) or !($extpage instanceof admin_externalpage)) {
5537 print_error('sectionerror', 'admin', "$CFG->wwwroot/$CFG->admin/");
5538 die;
5541 // this eliminates our need to authenticate on the actual pages
5542 if (!$extpage->check_access()) {
5543 print_error('accessdenied', 'admin');
5544 die;
5547 if ($section === 'upgradesettings') {
5548 $PAGE->set_pagelayout('maintenance');
5549 } else {
5550 $PAGE->set_pagelayout('admin');
5553 // $PAGE->set_extra_button($extrabutton); TODO
5555 if (!$actualurl) {
5556 $actualurl = $extpage->url;
5559 $extraurlparams = (array)$extraurlparams;
5560 $extraurlparams['section'] = $section; // TODO: this is an ugly hack for navigation that must be eliminated!
5562 $PAGE->set_url($actualurl, $extraurlparams);
5563 if (strpos($PAGE->pagetype, 'admin-') !== 0) {
5564 $PAGE->set_pagetype('admin-' . $PAGE->pagetype);
5566 $PAGE->set_pagelayout('admin');
5568 if (empty($SITE->fullname) || empty($SITE->shortname)) {
5569 // During initial install.
5570 $strinstallation = get_string('installation', 'install');
5571 $strsettings = get_string('settings');
5572 $PAGE->navbar->add($strsettings);
5573 $PAGE->set_title($strinstallation);
5574 $PAGE->set_heading($strinstallation);
5575 $PAGE->set_cacheable(false);
5576 return;
5579 // Normal case.
5580 $adminediting = optional_param('adminedit', -1, PARAM_BOOL);
5581 if ($PAGE->user_allowed_editing() && $adminediting != -1) {
5582 $USER->editing = $adminediting;
5585 $visiblepathtosection = array_reverse($extpage->visiblepath);
5587 if ($PAGE->user_allowed_editing()) {
5588 if ($PAGE->user_is_editing()) {
5589 $caption = get_string('blockseditoff');
5590 $url = new moodle_url($PAGE->url, array('adminedit'=>'0'));
5591 } else {
5592 $caption = get_string('blocksediton');
5593 $url = new moodle_url($PAGE->url, array('adminedit'=>'1'));
5595 $PAGE->set_button($OUTPUT->single_button($url, $caption, 'get'));
5598 $PAGE->set_title("$SITE->shortname: " . implode(": ", $visiblepathtosection));
5599 $PAGE->set_heading($SITE->fullname);
5601 // prevent caching in nav block
5602 $PAGE->navigation->clear_cache();
5606 * Returns the reference to admin tree root
5608 * @return object admin_roow object
5610 function admin_get_root($reload=false, $requirefulltree=true) {
5611 global $CFG, $DB, $OUTPUT;
5613 static $ADMIN = NULL;
5615 if (is_null($ADMIN)) {
5616 // create the admin tree!
5617 $ADMIN = new admin_root($requirefulltree);
5620 if ($reload or ($requirefulltree and !$ADMIN->fulltree)) {
5621 $ADMIN->purge_children($requirefulltree);
5624 if (!$ADMIN->loaded) {
5625 // we process this file first to create categories first and in correct order
5626 require($CFG->dirroot.'/'.$CFG->admin.'/settings/top.php');
5628 // now we process all other files in admin/settings to build the admin tree
5629 foreach (glob($CFG->dirroot.'/'.$CFG->admin.'/settings/*.php') as $file) {
5630 if ($file == $CFG->dirroot.'/'.$CFG->admin.'/settings/top.php') {
5631 continue;
5633 if ($file == $CFG->dirroot.'/'.$CFG->admin.'/settings/plugins.php') {
5634 // plugins are loaded last - they may insert pages anywhere
5635 continue;
5637 require($file);
5639 require($CFG->dirroot.'/'.$CFG->admin.'/settings/plugins.php');
5641 $ADMIN->loaded = true;
5644 return $ADMIN;
5647 /// settings utility functions
5650 * This function applies default settings.
5652 * @param object $node, NULL means complete tree, null by default
5653 * @param bool $unconditional if true overrides all values with defaults, null buy default
5655 function admin_apply_default_settings($node=NULL, $unconditional=true) {
5656 global $CFG;
5658 if (is_null($node)) {
5659 $node = admin_get_root(true, true);
5662 if ($node instanceof admin_category) {
5663 $entries = array_keys($node->children);
5664 foreach ($entries as $entry) {
5665 admin_apply_default_settings($node->children[$entry], $unconditional);
5668 } else if ($node instanceof admin_settingpage) {
5669 foreach ($node->settings as $setting) {
5670 if (!$unconditional and !is_null($setting->get_setting())) {
5671 //do not override existing defaults
5672 continue;
5674 $defaultsetting = $setting->get_defaultsetting();
5675 if (is_null($defaultsetting)) {
5676 // no value yet - default maybe applied after admin user creation or in upgradesettings
5677 continue;
5679 $setting->write_setting($defaultsetting);
5685 * Store changed settings, this function updates the errors variable in $ADMIN
5687 * @param object $formdata from form
5688 * @return int number of changed settings
5690 function admin_write_settings($formdata) {
5691 global $CFG, $SITE, $DB;
5693 $olddbsessions = !empty($CFG->dbsessions);
5694 $formdata = (array)$formdata;
5696 $data = array();
5697 foreach ($formdata as $fullname=>$value) {
5698 if (strpos($fullname, 's_') !== 0) {
5699 continue; // not a config value
5701 $data[$fullname] = $value;
5704 $adminroot = admin_get_root();
5705 $settings = admin_find_write_settings($adminroot, $data);
5707 $count = 0;
5708 foreach ($settings as $fullname=>$setting) {
5709 $original = serialize($setting->get_setting()); // comparison must work for arrays too
5710 $error = $setting->write_setting($data[$fullname]);
5711 if ($error !== '') {
5712 $adminroot->errors[$fullname] = new stdClass();
5713 $adminroot->errors[$fullname]->data = $data[$fullname];
5714 $adminroot->errors[$fullname]->id = $setting->get_id();
5715 $adminroot->errors[$fullname]->error = $error;
5717 if ($original !== serialize($setting->get_setting())) {
5718 $count++;
5719 $callbackfunction = $setting->updatedcallback;
5720 if (function_exists($callbackfunction)) {
5721 $callbackfunction($fullname);
5726 if ($olddbsessions != !empty($CFG->dbsessions)) {
5727 require_logout();
5730 // Now update $SITE - just update the fields, in case other people have a
5731 // a reference to it (e.g. $PAGE, $COURSE).
5732 $newsite = $DB->get_record('course', array('id'=>$SITE->id));
5733 foreach (get_object_vars($newsite) as $field => $value) {
5734 $SITE->$field = $value;
5737 // now reload all settings - some of them might depend on the changed
5738 admin_get_root(true);
5739 return $count;
5743 * Internal recursive function - finds all settings from submitted form
5745 * @param object $node Instance of admin_category, or admin_settingpage
5746 * @param array $data
5747 * @return array
5749 function admin_find_write_settings($node, $data) {
5750 $return = array();
5752 if (empty($data)) {
5753 return $return;
5756 if ($node instanceof admin_category) {
5757 $entries = array_keys($node->children);
5758 foreach ($entries as $entry) {
5759 $return = array_merge($return, admin_find_write_settings($node->children[$entry], $data));
5762 } else if ($node instanceof admin_settingpage) {
5763 foreach ($node->settings as $setting) {
5764 $fullname = $setting->get_full_name();
5765 if (array_key_exists($fullname, $data)) {
5766 $return[$fullname] = $setting;
5772 return $return;
5776 * Internal function - prints the search results
5778 * @param string $query String to search for
5779 * @return string empty or XHTML
5781 function admin_search_settings_html($query) {
5782 global $CFG, $OUTPUT;
5784 $textlib = textlib_get_instance();
5785 if ($textlib->strlen($query) < 2) {
5786 return '';
5788 $query = $textlib->strtolower($query);
5790 $adminroot = admin_get_root();
5791 $findings = $adminroot->search($query);
5792 $return = '';
5793 $savebutton = false;
5795 foreach ($findings as $found) {
5796 $page = $found->page;
5797 $settings = $found->settings;
5798 if ($page->is_hidden()) {
5799 // hidden pages are not displayed in search results
5800 continue;
5802 if ($page instanceof admin_externalpage) {
5803 $return .= $OUTPUT->heading(get_string('searchresults','admin').' - <a href="'.$page->url.'">'.highlight($query, $page->visiblename).'</a>', 2, 'main');
5804 } else if ($page instanceof admin_settingpage) {
5805 $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');
5806 } else {
5807 continue;
5809 if (!empty($settings)) {
5810 $return .= '<fieldset class="adminsettings">'."\n";
5811 foreach ($settings as $setting) {
5812 if (empty($setting->nosave)) {
5813 $savebutton = true;
5815 $return .= '<div class="clearer"><!-- --></div>'."\n";
5816 $fullname = $setting->get_full_name();
5817 if (array_key_exists($fullname, $adminroot->errors)) {
5818 $data = $adminroot->errors[$fullname]->data;
5819 } else {
5820 $data = $setting->get_setting();
5821 // do not use defaults if settings not available - upgradesettings handles the defaults!
5823 $return .= $setting->output_html($data, $query);
5825 $return .= '</fieldset>';
5829 if ($savebutton) {
5830 $return .= '<div class="form-buttons"><input class="form-submit" type="submit" value="'.get_string('savechanges','admin').'" /></div>';
5833 return $return;
5837 * Internal function - returns arrays of html pages with uninitialised settings
5839 * @param object $node Instance of admin_category or admin_settingpage
5840 * @return array
5842 function admin_output_new_settings_by_page($node) {
5843 global $OUTPUT;
5844 $return = array();
5846 if ($node instanceof admin_category) {
5847 $entries = array_keys($node->children);
5848 foreach ($entries as $entry) {
5849 $return += admin_output_new_settings_by_page($node->children[$entry]);
5852 } else if ($node instanceof admin_settingpage) {
5853 $newsettings = array();
5854 foreach ($node->settings as $setting) {
5855 if (is_null($setting->get_setting())) {
5856 $newsettings[] = $setting;
5859 if (count($newsettings) > 0) {
5860 $adminroot = admin_get_root();
5861 $page = $OUTPUT->heading(get_string('upgradesettings','admin').' - '.$node->visiblename, 2, 'main');
5862 $page .= '<fieldset class="adminsettings">'."\n";
5863 foreach ($newsettings as $setting) {
5864 $fullname = $setting->get_full_name();
5865 if (array_key_exists($fullname, $adminroot->errors)) {
5866 $data = $adminroot->errors[$fullname]->data;
5867 } else {
5868 $data = $setting->get_setting();
5869 if (is_null($data)) {
5870 $data = $setting->get_defaultsetting();
5873 $page .= '<div class="clearer"><!-- --></div>'."\n";
5874 $page .= $setting->output_html($data);
5876 $page .= '</fieldset>';
5877 $return[$node->name] = $page;
5881 return $return;
5885 * Format admin settings
5887 * @param object $setting
5888 * @param string $title label element
5889 * @param string $form form fragment, html code - not highlighted automatically
5890 * @param string $description
5891 * @param bool $label link label to id, true by default
5892 * @param string $warning warning text
5893 * @param sting $defaultinfo defaults info, null means nothing, '' is converted to "Empty" string, defaults to null
5894 * @param string $query search query to be highlighted
5895 * @return string XHTML
5897 function format_admin_setting($setting, $title='', $form='', $description='', $label=true, $warning='', $defaultinfo=NULL, $query='') {
5898 global $CFG;
5900 $name = empty($setting->plugin) ? $setting->name : "$setting->plugin | $setting->name";
5901 $fullname = $setting->get_full_name();
5903 // sometimes the id is not id_s_name, but id_s_name_m or something, and this does not validate
5904 if ($label) {
5905 $labelfor = 'for = "'.$setting->get_id().'"';
5906 } else {
5907 $labelfor = '';
5910 $override = '';
5911 if (empty($setting->plugin)) {
5912 if (array_key_exists($setting->name, $CFG->config_php_settings)) {
5913 $override = '<div class="form-overridden">'.get_string('configoverride', 'admin').'</div>';
5915 } else {
5916 if (array_key_exists($setting->plugin, $CFG->forced_plugin_settings) and array_key_exists($setting->name, $CFG->forced_plugin_settings[$setting->plugin])) {
5917 $override = '<div class="form-overridden">'.get_string('configoverride', 'admin').'</div>';
5921 if ($warning !== '') {
5922 $warning = '<div class="form-warning">'.$warning.'</div>';
5925 if (is_null($defaultinfo)) {
5926 $defaultinfo = '';
5927 } else {
5928 if ($defaultinfo === '') {
5929 $defaultinfo = get_string('emptysettingvalue', 'admin');
5931 $defaultinfo = highlight($query, nl2br(s($defaultinfo)));
5932 $defaultinfo = '<div class="form-defaultinfo">'.get_string('defaultsettinginfo', 'admin', $defaultinfo).'</div>';
5936 $str = '
5937 <div class="form-item clearfix" id="admin-'.$setting->name.'">
5938 <div class="form-label">
5939 <label '.$labelfor.'>'.highlightfast($query, $title).'<span class="form-shortname">'.highlightfast($query, $name).'</span>
5940 '.$override.$warning.'
5941 </label>
5942 </div>
5943 <div class="form-setting">'.$form.$defaultinfo.'</div>
5944 <div class="form-description">'.highlight($query, markdown_to_html($description)).'</div>
5945 </div>';
5947 $adminroot = admin_get_root();
5948 if (array_key_exists($fullname, $adminroot->errors)) {
5949 $str = '<fieldset class="error"><legend>'.$adminroot->errors[$fullname]->error.'</legend>'.$str.'</fieldset>';
5952 return $str;
5956 * Based on find_new_settings{@link ()} in upgradesettings.php
5957 * Looks to find any admin settings that have not been initialized. Returns 1 if it finds any.
5959 * @param object $node Instance of admin_category, or admin_settingpage
5960 * @return boolean true if any settings haven't been initialised, false if they all have
5962 function any_new_admin_settings($node) {
5964 if ($node instanceof admin_category) {
5965 $entries = array_keys($node->children);
5966 foreach ($entries as $entry) {
5967 if (any_new_admin_settings($node->children[$entry])) {
5968 return true;
5972 } else if ($node instanceof admin_settingpage) {
5973 foreach ($node->settings as $setting) {
5974 if ($setting->get_setting() === NULL) {
5975 return true;
5980 return false;
5985 * Moved from admin/replace.php so that we can use this in cron
5987 * @param string $search string to look for
5988 * @param string $replace string to replace
5989 * @return bool success or fail
5991 function db_replace($search, $replace) {
5993 global $DB, $CFG;
5995 /// Turn off time limits, sometimes upgrades can be slow.
5996 @set_time_limit(0);
5997 @ob_implicit_flush(true);
5998 while(@ob_end_flush());
6000 if (!$tables = $DB->get_tables() ) { // No tables yet at all.
6001 return false;
6003 foreach ($tables as $table) {
6005 if (in_array($table, array('config'))) { // Don't process these
6006 continue;
6009 if ($columns = $DB->get_columns($table)) {
6010 $DB->set_debug(true);
6011 foreach ($columns as $column => $data) {
6012 if (in_array($data->meta_type, array('C', 'X'))) { // Text stuff only
6013 $DB->execute("UPDATE {".$table."} SET $column = REPLACE($column, ?, ?)", array($search, $replace));
6016 $DB->set_debug(false);
6020 return true;
6024 * Prints tables of detected plugins, one table per plugin type,
6025 * and prints whether they are part of the standard Moodle
6026 * distribution or not.
6028 function print_plugin_tables() {
6029 global $DB;
6030 $plugins_standard = array();
6031 $plugins_standard['mod'] = array('assignment',
6032 'chat',
6033 'choice',
6034 'data',
6035 'feedback',
6036 'folder',
6037 'forum',
6038 'glossary',
6039 'imscp',
6040 'label',
6041 'lesson',
6042 'page',
6043 'quiz',
6044 'resource',
6045 'scorm',
6046 'survey',
6047 'url',
6048 'wiki',
6049 'workshop');
6051 $plugins_standard['blocks'] = array('activity_modules',
6052 'admin_bookmarks',
6053 'blog_menu',
6054 'blog_recent',
6055 'blog_tags',
6056 'calendar_month',
6057 'calendar_upcoming',
6058 'comments',
6059 'community',
6060 'completionstatus',
6061 'course_list',
6062 'course_overview',
6063 'course_summary',
6064 'feedback',
6065 'glossary_random',
6066 'html',
6067 'login',
6068 'mentees',
6069 'messages',
6070 'mnet_hosts',
6071 'myprofile',
6072 'navigation',
6073 'news_items',
6074 'online_users',
6075 'participants',
6076 'private_files',
6077 'quiz_results',
6078 'recent_activity',
6079 'rss_client',
6080 'search',
6081 'search_forums',
6082 'section_links',
6083 'selfcompletion',
6084 'settings',
6085 'site_main_menu',
6086 'social_activities',
6087 'tag_flickr',
6088 'tag_youtube',
6089 'tags');
6091 $plugins_standard['filter'] = array('activitynames',
6092 'algebra',
6093 'censor',
6094 'emailprotect',
6095 'filter',
6096 'mediaplugin',
6097 'multilang',
6098 'tex',
6099 'tidy',
6100 'urltolink');
6102 $plugins_installed = array();
6103 $installed_mods = $DB->get_records('modules', null, 'name');
6104 $installed_blocks = $DB->get_records('block', null, 'name');
6106 foreach($installed_mods as $mod) {
6107 $plugins_installed['mod'][] = $mod->name;
6110 foreach($installed_blocks as $block) {
6111 $plugins_installed['blocks'][] = $block->name;
6113 $plugins_installed['filter'] = array();
6115 $plugins_ondisk = array();
6116 $plugins_ondisk['mod'] = array_keys(get_plugin_list('mod'));
6117 $plugins_ondisk['blocks'] = array_keys(get_plugin_list('block'));
6118 $plugins_ondisk['filter'] = array_keys(get_plugin_list('filter'));
6120 $strstandard = get_string('standard');
6121 $strnonstandard = get_string('nonstandard');
6122 $strmissingfromdisk = '(' . get_string('missingfromdisk') . ')';
6123 $strabouttobeinstalled = '(' . get_string('abouttobeinstalled') . ')';
6125 $html = '';
6127 $html .= '<table class="generaltable plugincheckwrapper" cellspacing="4" cellpadding="1"><tr valign="top">';
6129 foreach ($plugins_ondisk as $cat => $list_ondisk) {
6130 if ($cat == 'mod') {
6131 $strcaption = get_string('activitymodule');
6132 } elseif ($cat == 'filter') {
6133 $strcaption = get_string('managefilters');
6134 } else {
6135 $strcaption = get_string($cat);
6138 $html .= '<td><table class="plugincompattable generaltable boxaligncenter" cellspacing="1" cellpadding="5" '
6139 . 'id="' . $cat . 'compattable" summary="compatibility table"><caption>' . $strcaption . '</caption>' . "\n";
6140 $html .= '<tr class="r0"><th class="header c0">' . get_string('directory') . "</th>\n"
6141 . '<th class="header c1">' . get_string('name') . "</th>\n"
6142 . '<th class="header c2">' . get_string('status') . "</th>\n</tr>\n";
6144 $row = 1;
6146 foreach ($list_ondisk as $k => $plugin) {
6147 $status = 'ok';
6148 $standard = 'standard';
6149 $note = '';
6151 if (!in_array($plugin, $plugins_standard[$cat])) {
6152 $standard = 'nonstandard';
6153 $status = 'warning';
6156 // Get real name and full path of plugin
6157 $plugin_name = "[[$plugin]]";
6159 $plugin_path = "$cat/$plugin";
6161 $plugin_name = get_plugin_name($plugin, $cat);
6163 // Determine if the plugin is about to be installed
6164 if ($cat != 'filter' && !in_array($plugin, $plugins_installed[$cat])) {
6165 $note = $strabouttobeinstalled;
6166 $plugin_name = $plugin;
6169 $html .= "<tr class=\"r$row\">\n"
6170 . "<td class=\"cell c0\">$plugin_path</td>\n"
6171 . "<td class=\"cell c1\">$plugin_name</td>\n"
6172 . "<td class=\"$standard $status cell c2\">" . ${'str' . $standard} . " $note</td>\n</tr>\n";
6173 $row++;
6175 // If the plugin was both on disk and in the db, unset the value from the installed plugins list
6176 if ($key = array_search($plugin, $plugins_installed[$cat])) {
6177 unset($plugins_installed[$cat][$key]);
6181 // If there are plugins left in the plugins_installed list, it means they are missing from disk
6182 foreach ($plugins_installed[$cat] as $k => $missing_plugin) {
6183 // Make sure the plugin really is missing from disk
6184 if (!in_array($missing_plugin, $plugins_ondisk[$cat])) {
6185 $standard = 'standard';
6186 $status = 'warning';
6188 if (!in_array($missing_plugin, $plugins_standard[$cat])) {
6189 $standard = 'nonstandard';
6192 $plugin_name = $missing_plugin;
6193 $html .= "<tr class=\"r$row\">\n"
6194 . "<td class=\"cell c0\">?</td>\n"
6195 . "<td class=\"cell c1\">$plugin_name</td>\n"
6196 . "<td class=\"$standard $status cell c2\">" . ${'str' . $standard} . " $strmissingfromdisk</td>\n</tr>\n";
6197 $row++;
6201 $html .= '</table></td>';
6204 $html .= '</tr></table><br />';
6206 echo $html;
6210 * Manage repository settings
6212 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
6214 class admin_setting_managerepository extends admin_setting {
6215 /** @var string */
6216 private $baseurl;
6219 * calls parent::__construct with specific arguments
6221 public function __construct() {
6222 global $CFG;
6223 parent::__construct('managerepository', get_string('manage', 'repository'), '', '');
6224 $this->baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/repository.php?sesskey=' . sesskey();
6228 * Always returns true, does nothing
6230 * @return true
6232 public function get_setting() {
6233 return true;
6237 * Always returns true does nothing
6239 * @return true
6241 public function get_defaultsetting() {
6242 return true;
6246 * Always returns s_managerepository
6248 * @return string Always return 's_managerepository'
6250 public function get_full_name() {
6251 return 's_managerepository';
6255 * Always returns '' doesn't do anything
6257 public function write_setting($data) {
6258 $url = $this->baseurl . '&amp;new=' . $data;
6259 return '';
6260 // TODO
6261 // Should not use redirect and exit here
6262 // Find a better way to do this.
6263 // redirect($url);
6264 // exit;
6268 * Searches repository plugins for one that matches $query
6270 * @param string $query The string to search for
6271 * @return bool true if found, false if not
6273 public function is_related($query) {
6274 if (parent::is_related($query)) {
6275 return true;
6278 $textlib = textlib_get_instance();
6279 $repositories= get_plugin_list('repository');
6280 foreach ($repositories as $p => $dir) {
6281 if (strpos($p, $query) !== false) {
6282 return true;
6285 foreach (repository::get_types() as $instance) {
6286 $title = $instance->get_typename();
6287 if (strpos($textlib->strtolower($title), $query) !== false) {
6288 return true;
6291 return false;
6295 * Helper function that generates a moodle_url object
6296 * relevant to the repository
6299 function repository_action_url($repository) {
6300 return new moodle_url($this->baseurl, array('sesskey'=>sesskey(), 'repos'=>$repository));
6304 * Builds XHTML to display the control
6306 * @param string $data Unused
6307 * @param string $query
6308 * @return string XHTML
6310 public function output_html($data, $query='') {
6311 global $CFG, $USER, $OUTPUT;
6313 // Get strings that are used
6314 $strshow = get_string('on', 'repository');
6315 $strhide = get_string('off', 'repository');
6316 $strdelete = get_string('disabled', 'repository');
6318 $actionchoicesforexisting = array(
6319 'show' => $strshow,
6320 'hide' => $strhide,
6321 'delete' => $strdelete
6324 $actionchoicesfornew = array(
6325 'newon' => $strshow,
6326 'newoff' => $strhide,
6327 'delete' => $strdelete
6330 $return = '';
6331 $return .= $OUTPUT->box_start('generalbox');
6333 // Set strings that are used multiple times
6334 $settingsstr = get_string('settings');
6335 $disablestr = get_string('disable');
6337 // Table to list plug-ins
6338 $table = new html_table();
6339 $table->head = array(get_string('name'), get_string('isactive', 'repository'), get_string('order'), $settingsstr);
6340 $table->align = array('left', 'center', 'center', 'center', 'center');
6341 $table->data = array();
6343 // Get list of used plug-ins
6344 $instances = repository::get_types();
6345 if (!empty($instances)) {
6346 // Array to store plugins being used
6347 $alreadyplugins = array();
6348 $totalinstances = count($instances);
6349 $updowncount = 1;
6350 foreach ($instances as $i) {
6351 $settings = '';
6352 $typename = $i->get_typename();
6353 // Display edit link only if you can config the type or if it has multiple instances (e.g. has instance config)
6354 $typeoptionnames = repository::static_function($typename, 'get_type_option_names');
6355 $instanceoptionnames = repository::static_function($typename, 'get_instance_option_names');
6357 if (!empty($typeoptionnames) || !empty($instanceoptionnames)) {
6358 // Calculate number of instances in order to display them for the Moodle administrator
6359 if (!empty($instanceoptionnames)) {
6360 $params = array();
6361 $params['context'] = array(get_system_context());
6362 $params['onlyvisible'] = false;
6363 $params['type'] = $typename;
6364 $admininstancenumber = count(repository::static_function($typename, 'get_instances', $params));
6365 // site instances
6366 $admininstancenumbertext = get_string('instancesforsite', 'repository', $admininstancenumber);
6367 $params['context'] = array();
6368 $instances = repository::static_function($typename, 'get_instances', $params);
6369 $courseinstances = array();
6370 $userinstances = array();
6372 foreach ($instances as $instance) {
6373 if ($instance->context->contextlevel == CONTEXT_COURSE) {
6374 $courseinstances[] = $instance;
6375 } else if ($instance->context->contextlevel == CONTEXT_USER) {
6376 $userinstances[] = $instance;
6379 // course instances
6380 $instancenumber = count($courseinstances);
6381 $courseinstancenumbertext = get_string('instancesforcourses', 'repository', $instancenumber);
6383 // user private instances
6384 $instancenumber = count($userinstances);
6385 $userinstancenumbertext = get_string('instancesforusers', 'repository', $instancenumber);
6386 } else {
6387 $admininstancenumbertext = "";
6388 $courseinstancenumbertext = "";
6389 $userinstancenumbertext = "";
6392 $settings .= '<a href="' . $this->baseurl . '&amp;action=edit&amp;repos=' . $typename . '">' . $settingsstr .'</a>';
6394 $settings .= $OUTPUT->container_start('mdl-left');
6395 $settings .= '<br/>';
6396 $settings .= $admininstancenumbertext;
6397 $settings .= '<br/>';
6398 $settings .= $courseinstancenumbertext;
6399 $settings .= '<br/>';
6400 $settings .= $userinstancenumbertext;
6401 $settings .= $OUTPUT->container_end();
6403 // Get the current visibility
6404 if ($i->get_visible()) {
6405 $currentaction = 'show';
6406 } else {
6407 $currentaction = 'hide';
6410 $select = new single_select($this->repository_action_url($typename, 'repos'), 'action', $actionchoicesforexisting, $currentaction, null, 'applyto' . basename($typename));
6412 // Display up/down link
6413 $updown = '';
6414 $spacer = $OUTPUT->spacer(array('height'=>15, 'width'=>15)); // should be done with CSS instead
6416 if ($updowncount > 1) {
6417 $updown .= "<a href=\"$this->baseurl&amp;action=moveup&amp;repos=".$typename."\">";
6418 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/up') . "\" alt=\"up\" /></a>&nbsp;";
6420 else {
6421 $updown .= $spacer;
6423 if ($updowncount < $totalinstances) {
6424 $updown .= "<a href=\"$this->baseurl&amp;action=movedown&amp;repos=".$typename."\">";
6425 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/down') . "\" alt=\"down\" /></a>";
6427 else {
6428 $updown .= $spacer;
6431 $updowncount++;
6433 $table->data[] = array($i->get_readablename(), $OUTPUT->render($select), $updown, $settings);
6435 if (!in_array($typename, $alreadyplugins)) {
6436 $alreadyplugins[] = $typename;
6441 // Get all the plugins that exist on disk
6442 $plugins = get_plugin_list('repository');
6443 if (!empty($plugins)) {
6444 foreach ($plugins as $plugin => $dir) {
6445 // Check that it has not already been listed
6446 if (!in_array($plugin, $alreadyplugins)) {
6447 $select = new single_select($this->repository_action_url($plugin, 'repos'), 'action', $actionchoicesfornew, 'delete', null, 'applyto' . basename($plugin));
6448 $table->data[] = array(get_string('pluginname', 'repository_'.$plugin), $OUTPUT->render($select), '', '');
6453 $return .= html_writer::table($table);
6454 $return .= $OUTPUT->box_end();
6455 return highlight($query, $return);
6460 * Special class for management of external services
6462 * @author Petr Skoda (skodak)
6464 class admin_setting_manageexternalservices extends admin_setting {
6466 * Calls parent::__construct with specific arguments
6468 public function __construct() {
6469 $this->nosave = true;
6470 parent::__construct('webservicesui', get_string('externalservices', 'webservice'), '', '');
6474 * Always returns true, does nothing
6476 * @return true
6478 public function get_setting() {
6479 return true;
6483 * Always returns true, does nothing
6485 * @return true
6487 public function get_defaultsetting() {
6488 return true;
6492 * Always returns '', does not write anything
6494 * @return string Always returns ''
6496 public function write_setting($data) {
6497 // do not write any setting
6498 return '';
6502 * Checks if $query is one of the available external services
6504 * @param string $query The string to search for
6505 * @return bool Returns true if found, false if not
6507 public function is_related($query) {
6508 global $DB;
6510 if (parent::is_related($query)) {
6511 return true;
6514 $textlib = textlib_get_instance();
6515 $services = $DB->get_records('external_services', array(), 'id, name');
6516 foreach ($services as $service) {
6517 if (strpos($textlib->strtolower($service->name), $query) !== false) {
6518 return true;
6521 return false;
6525 * Builds the XHTML to display the control
6527 * @param string $data Unused
6528 * @param string $query
6529 * @return string
6531 public function output_html($data, $query='') {
6532 global $CFG, $OUTPUT, $DB;
6534 // display strings
6535 $stradministration = get_string('administration');
6536 $stredit = get_string('edit');
6537 $strservice = get_string('externalservice', 'webservice');
6538 $strdelete = get_string('delete');
6539 $strplugin = get_string('plugin', 'admin');
6540 $stradd = get_string('add');
6541 $strfunctions = get_string('functions', 'webservice');
6542 $strusers = get_string('users');
6543 $strserviceusers = get_string('serviceusers', 'webservice');
6545 $esurl = "$CFG->wwwroot/$CFG->admin/webservice/service.php";
6546 $efurl = "$CFG->wwwroot/$CFG->admin/webservice/service_functions.php";
6547 $euurl = "$CFG->wwwroot/$CFG->admin/webservice/service_users.php";
6549 // built in services
6550 $services = $DB->get_records_select('external_services', 'component IS NOT NULL', null, 'name');
6551 $return = "";
6552 if (!empty($services)) {
6553 $return .= $OUTPUT->heading(get_string('servicesbuiltin', 'webservice'), 3, 'main');
6557 $table = new html_table();
6558 $table->head = array($strservice, $strplugin, $strfunctions, $strusers, $stredit);
6559 $table->align = array('left', 'left', 'center', 'center', 'center');
6560 $table->size = array('30%', '20%', '20%', '20%', '10%');
6561 $table->width = '100%';
6562 $table->data = array();
6564 // iterate through auth plugins and add to the display table
6565 foreach ($services as $service) {
6566 $name = $service->name;
6568 // hide/show link
6569 if ($service->enabled) {
6570 $displayname = "<span>$name</span>";
6571 } else {
6572 $displayname = "<span class=\"dimmed_text\">$name</span>";
6575 $plugin = $service->component;
6577 $functions = "<a href=\"$efurl?id=$service->id\">$strfunctions</a>";
6579 if ($service->restrictedusers) {
6580 $users = "<a href=\"$euurl?id=$service->id\">$strserviceusers</a>";
6581 } else {
6582 $users = get_string('allusers', 'webservice');
6585 $edit = "<a href=\"$esurl?id=$service->id\">$stredit</a>";
6587 // add a row to the table
6588 $table->data[] = array($displayname, $plugin, $functions, $users, $edit);
6590 $return .= html_writer::table($table);
6593 // Custom services
6594 $return .= $OUTPUT->heading(get_string('servicescustom', 'webservice'), 3, 'main');
6595 $services = $DB->get_records_select('external_services', 'component IS NULL', null, 'name');
6597 $table = new html_table();
6598 $table->head = array($strservice, $strdelete, $strfunctions, $strusers, $stredit);
6599 $table->align = array('left', 'center', 'center', 'center', 'center');
6600 $table->size = array('30%', '20%', '20%', '20%', '10%');
6601 $table->width = '100%';
6602 $table->data = array();
6604 // iterate through auth plugins and add to the display table
6605 foreach ($services as $service) {
6606 $name = $service->name;
6608 // hide/show link
6609 if ($service->enabled) {
6610 $displayname = "<span>$name</span>";
6611 } else {
6612 $displayname = "<span class=\"dimmed_text\">$name</span>";
6615 // delete link
6616 $delete = "<a href=\"$esurl?action=delete&amp;sesskey=".sesskey()."&amp;id=$service->id\">$strdelete</a>";
6618 $functions = "<a href=\"$efurl?id=$service->id\">$strfunctions</a>";
6620 if ($service->restrictedusers) {
6621 $users = "<a href=\"$euurl?id=$service->id\">$strserviceusers</a>";
6622 } else {
6623 $users = get_string('allusers', 'webservice');
6626 $edit = "<a href=\"$esurl?id=$service->id\">$stredit</a>";
6628 // add a row to the table
6629 $table->data[] = array($displayname, $delete, $functions, $users, $edit);
6631 // add new custom service option
6632 $return .= html_writer::table($table);
6634 $return .= '<br />';
6635 // add a token to the table
6636 $return .= "<a href=\"$esurl?id=0\">$stradd</a>";
6638 return highlight($query, $return);
6642 * Special class for plagiarism administration.
6644 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
6646 class admin_setting_manageplagiarism extends admin_setting {
6648 * Calls parent::__construct with specific arguments
6650 public function __construct() {
6651 $this->nosave = true;
6652 parent::__construct('plagiarismui', get_string('plagiarismsettings', 'plagiarism'), '', '');
6656 * Always returns true
6658 * @return true
6660 public function get_setting() {
6661 return true;
6665 * Always returns true
6667 * @return true
6669 public function get_defaultsetting() {
6670 return true;
6674 * Always returns '' and doesn't write anything
6676 * @return string Always returns ''
6678 public function write_setting($data) {
6679 // do not write any setting
6680 return '';
6684 * Return XHTML to display control
6686 * @param mixed $data Unused
6687 * @param string $query
6688 * @return string highlight
6690 public function output_html($data, $query='') {
6691 global $CFG, $OUTPUT;
6693 // display strings
6694 $txt = get_strings(array('settings', 'name'));
6696 $plagiarismplugins = get_plugin_list('plagiarism');
6697 if (empty($plagiarismplugins)) {
6698 return get_string('nopluginsinstalled', 'plagiarism');
6701 $return = $OUTPUT->heading(get_string('availableplugins', 'plagiarism'), 3, 'main');
6702 $return .= $OUTPUT->box_start('generalbox authsui');
6704 $table = new html_table();
6705 $table->head = array($txt->name, $txt->settings);
6706 $table->align = array('left', 'center');
6707 $table->data = array();
6708 $table->attributes['class'] = 'manageplagiarismtable generaltable';
6710 // iterate through auth plugins and add to the display table
6711 $authcount = count($plagiarismplugins);
6712 foreach ($plagiarismplugins as $plugin => $dir) {
6713 if (file_exists($dir.'/settings.php')) {
6714 $displayname = "<span>".get_string($plugin, 'plagiarism_'.$plugin)."</span>";
6715 // settings link
6716 $settings = "<a href=\"$CFG->wwwroot/plagiarism/$plugin/settings.php\">{$txt->settings}</a>";
6717 // add a row to the table
6718 $table->data[] =array($displayname, $settings);
6721 $return .= html_writer::table($table);
6722 $return .= get_string('configplagiarismplugins', 'plagiarism');
6723 $return .= $OUTPUT->box_end();
6724 return highlight($query, $return);
6729 * Special class for overview of external services
6731 * @author Jerome Mouneyrac
6733 class admin_setting_webservicesoverview extends admin_setting {
6736 * Calls parent::__construct with specific arguments
6738 public function __construct() {
6739 $this->nosave = true;
6740 parent::__construct('webservicesoverviewui',
6741 get_string('webservicesoverview', 'webservice'), '', '');
6745 * Always returns true, does nothing
6747 * @return true
6749 public function get_setting() {
6750 return true;
6754 * Always returns true, does nothing
6756 * @return true
6758 public function get_defaultsetting() {
6759 return true;
6763 * Always returns '', does not write anything
6765 * @return string Always returns ''
6767 public function write_setting($data) {
6768 // do not write any setting
6769 return '';
6773 * Builds the XHTML to display the control
6775 * @param string $data Unused
6776 * @param string $query
6777 * @return string
6779 public function output_html($data, $query='') {
6780 global $CFG, $OUTPUT;
6782 $return = "";
6784 /// One system controlling Moodle with Token
6785 $brtag = html_writer::empty_tag('br');
6787 $return .= $OUTPUT->heading(get_string('onesystemcontrolling', 'webservice'), 3, 'main');
6788 $table = new html_table();
6789 $table->head = array(get_string('step', 'webservice'), get_string('status'),
6790 get_string('description'));
6791 $table->size = array('30%', '10%', '60%');
6792 $table->align = array('left', 'left', 'left');
6793 $table->width = '90%';
6794 $table->data = array();
6796 $return .= $brtag . get_string('onesystemcontrollingdescription', 'webservice')
6797 . $brtag . $brtag;
6799 /// 1. Enable Web Services
6800 $row = array();
6801 $url = new moodle_url("/admin/search.php?query=enablewebservices");
6802 $row[0] = "1. " . html_writer::tag('a', get_string('enablews', 'webservice'),
6803 array('href' => $url));
6804 $status = html_writer::tag('span', get_string('no'), array('class' => 'statuscritical'));
6805 if ($CFG->enablewebservices) {
6806 $status = get_string('yes');
6808 $row[1] = $status;
6809 $row[2] = get_string('enablewsdescription', 'webservice');
6810 $table->data[] = $row;
6812 /// 2. Enable protocols
6813 $row = array();
6814 $url = new moodle_url("/admin/settings.php?section=webserviceprotocols");
6815 $row[0] = "2. " . html_writer::tag('a', get_string('enableprotocols', 'webservice'),
6816 array('href' => $url));
6817 $status = html_writer::tag('span', get_string('none'), array('class' => 'statuscritical'));
6818 //retrieve activated protocol
6819 $active_protocols = empty($CFG->webserviceprotocols) ?
6820 array() : explode(',', $CFG->webserviceprotocols);
6821 if (!empty($active_protocols)) {
6822 $status = "";
6823 foreach ($active_protocols as $protocol) {
6824 $status .= $protocol . $brtag;
6827 $row[1] = $status;
6828 $row[2] = get_string('enableprotocolsdescription', 'webservice');
6829 $table->data[] = $row;
6831 /// 3. Create user account
6832 $row = array();
6833 $url = new moodle_url("/user/editadvanced.php?id=-1");
6834 $row[0] = "3. " . html_writer::tag('a', get_string('createuser', 'webservice'),
6835 array('href' => $url));
6836 $row[1] = "";
6837 $row[2] = get_string('createuserdescription', 'webservice');
6838 $table->data[] = $row;
6840 /// 4. Add capability to users
6841 $row = array();
6842 $url = new moodle_url("/admin/roles/check.php?contextid=1");
6843 $row[0] = "4. " . html_writer::tag('a', get_string('checkusercapability', 'webservice'),
6844 array('href' => $url));
6845 $row[1] = "";
6846 $row[2] = get_string('checkusercapabilitydescription', 'webservice');
6847 $table->data[] = $row;
6849 /// 5. Select a web service
6850 $row = array();
6851 $url = new moodle_url("/admin/settings.php?section=externalservices");
6852 $row[0] = "5. " . html_writer::tag('a', get_string('selectservice', 'webservice'),
6853 array('href' => $url));
6854 $row[1] = "";
6855 $row[2] = get_string('createservicedescription', 'webservice');
6856 $table->data[] = $row;
6858 /// 6. Add functions
6859 $row = array();
6860 $url = new moodle_url("/admin/settings.php?section=externalservices");
6861 $row[0] = "6. " . html_writer::tag('a', get_string('addfunctions', 'webservice'),
6862 array('href' => $url));
6863 $row[1] = "";
6864 $row[2] = get_string('addfunctionsdescription', 'webservice');
6865 $table->data[] = $row;
6867 /// 7. Add the specific user
6868 $row = array();
6869 $url = new moodle_url("/admin/settings.php?section=externalservices");
6870 $row[0] = "7. " . html_writer::tag('a', get_string('selectspecificuser', 'webservice'),
6871 array('href' => $url));
6872 $row[1] = "";
6873 $row[2] = get_string('selectspecificuserdescription', 'webservice');
6874 $table->data[] = $row;
6876 /// 8. Create token for the specific user
6877 $row = array();
6878 $url = new moodle_url("/admin/webservice/tokens.php?sesskey=" . sesskey() . "&action=create");
6879 $row[0] = "8. " . html_writer::tag('a', get_string('createtokenforuser', 'webservice'),
6880 array('href' => $url));
6881 $row[1] = "";
6882 $row[2] = get_string('createtokenforuserdescription', 'webservice');
6883 $table->data[] = $row;
6885 /// 9. Enable the documentation
6886 $row = array();
6887 $url = new moodle_url("/admin/search.php?query=enablewsdocumentation");
6888 $row[0] = "9. " . html_writer::tag('a', get_string('enabledocumentation', 'webservice'),
6889 array('href' => $url));
6890 $status = '<span class="warning">' . get_string('no') . '</span>';
6891 if ($CFG->enablewsdocumentation) {
6892 $status = get_string('yes');
6894 $row[1] = $status;
6895 $row[2] = get_string('enabledocumentationdescription', 'webservice');
6896 $table->data[] = $row;
6898 /// 10. Test the service
6899 $row = array();
6900 $url = new moodle_url("/admin/webservice/testclient.php");
6901 $row[0] = "10. " . html_writer::tag('a', get_string('testwithtestclient', 'webservice'),
6902 array('href' => $url));
6903 $row[1] = "";
6904 $row[2] = get_string('testwithtestclientdescription', 'webservice');
6905 $table->data[] = $row;
6907 $return .= html_writer::table($table);
6909 /// Users as clients with token
6910 $return .= $brtag . $brtag . $brtag;
6911 $return .= $OUTPUT->heading(get_string('userasclients', 'webservice'), 3, 'main');
6912 $table = new html_table();
6913 $table->head = array(get_string('step', 'webservice'), get_string('status'),
6914 get_string('description'));
6915 $table->size = array('30%', '10%', '60%');
6916 $table->align = array('left', 'left', 'left');
6917 $table->width = '90%';
6918 $table->data = array();
6920 $return .= $brtag . get_string('userasclientsdescription', 'webservice') .
6921 $brtag . $brtag;
6923 /// 1. Enable Web Services
6924 $row = array();
6925 $url = new moodle_url("/admin/search.php?query=enablewebservices");
6926 $row[0] = "1. " . html_writer::tag('a', get_string('enablews', 'webservice'),
6927 array('href' => $url));
6928 $status = html_writer::tag('span', get_string('no'), array('class' => 'statuscritical'));
6929 if ($CFG->enablewebservices) {
6930 $status = get_string('yes');
6932 $row[1] = $status;
6933 $row[2] = get_string('enablewsdescription', 'webservice');
6934 $table->data[] = $row;
6936 /// 2. Enable protocols
6937 $row = array();
6938 $url = new moodle_url("/admin/settings.php?section=webserviceprotocols");
6939 $row[0] = "2. " . html_writer::tag('a', get_string('enableprotocols', 'webservice'),
6940 array('href' => $url));
6941 $status = html_writer::tag('span', get_string('none'), array('class' => 'statuscritical'));
6942 //retrieve activated protocol
6943 $active_protocols = empty($CFG->webserviceprotocols) ?
6944 array() : explode(',', $CFG->webserviceprotocols);
6945 if (!empty($active_protocols)) {
6946 $status = "";
6947 foreach ($active_protocols as $protocol) {
6948 $status .= $protocol . $brtag;
6951 $row[1] = $status;
6952 $row[2] = get_string('enableprotocolsdescription', 'webservice');
6953 $table->data[] = $row;
6956 /// 3. Select a web service
6957 $row = array();
6958 $url = new moodle_url("/admin/settings.php?section=externalservices");
6959 $row[0] = "3. " . html_writer::tag('a', get_string('selectservice', 'webservice'),
6960 array('href' => $url));
6961 $row[1] = "";
6962 $row[2] = get_string('createserviceforusersdescription', 'webservice');
6963 $table->data[] = $row;
6965 /// 4. Add functions
6966 $row = array();
6967 $url = new moodle_url("/admin/settings.php?section=externalservices");
6968 $row[0] = "4. " . html_writer::tag('a', get_string('addfunctions', 'webservice'),
6969 array('href' => $url));
6970 $row[1] = "";
6971 $row[2] = get_string('addfunctionsdescription', 'webservice');
6972 $table->data[] = $row;
6974 /// 5. Add capability to users
6975 $row = array();
6976 $url = new moodle_url("/admin/roles/check.php?contextid=1");
6977 $row[0] = "5. " . html_writer::tag('a', get_string('addcapabilitytousers', 'webservice'),
6978 array('href' => $url));
6979 $row[1] = "";
6980 $row[2] = get_string('addcapabilitytousersdescription', 'webservice');
6981 $table->data[] = $row;
6983 /// 6. Test the service
6984 $row = array();
6985 $url = new moodle_url("/admin/webservice/testclient.php");
6986 $row[0] = "6. " . html_writer::tag('a', get_string('testwithtestclient', 'webservice'),
6987 array('href' => $url));
6988 $row[1] = "";
6989 $row[2] = get_string('testauserwithtestclientdescription', 'webservice');
6990 $table->data[] = $row;
6992 $return .= html_writer::table($table);
6994 return highlight($query, $return);
7000 * Special class for web service protocol administration.
7002 * @author Petr Skoda (skodak)
7004 class admin_setting_managewebserviceprotocols extends admin_setting {
7007 * Calls parent::__construct with specific arguments
7009 public function __construct() {
7010 $this->nosave = true;
7011 parent::__construct('webservicesui', get_string('manageprotocols', 'webservice'), '', '');
7015 * Always returns true, does nothing
7017 * @return true
7019 public function get_setting() {
7020 return true;
7024 * Always returns true, does nothing
7026 * @return true
7028 public function get_defaultsetting() {
7029 return true;
7033 * Always returns '', does not write anything
7035 * @return string Always returns ''
7037 public function write_setting($data) {
7038 // do not write any setting
7039 return '';
7043 * Checks if $query is one of the available webservices
7045 * @param string $query The string to search for
7046 * @return bool Returns true if found, false if not
7048 public function is_related($query) {
7049 if (parent::is_related($query)) {
7050 return true;
7053 $textlib = textlib_get_instance();
7054 $protocols = get_plugin_list('webservice');
7055 foreach ($protocols as $protocol=>$location) {
7056 if (strpos($protocol, $query) !== false) {
7057 return true;
7059 $protocolstr = get_string('pluginname', 'webservice_'.$protocol);
7060 if (strpos($textlib->strtolower($protocolstr), $query) !== false) {
7061 return true;
7064 return false;
7068 * Builds the XHTML to display the control
7070 * @param string $data Unused
7071 * @param string $query
7072 * @return string
7074 public function output_html($data, $query='') {
7075 global $CFG, $OUTPUT;
7077 // display strings
7078 $stradministration = get_string('administration');
7079 $strsettings = get_string('settings');
7080 $stredit = get_string('edit');
7081 $strprotocol = get_string('protocol', 'webservice');
7082 $strenable = get_string('enable');
7083 $strdisable = get_string('disable');
7084 $strversion = get_string('version');
7085 $struninstall = get_string('uninstallplugin', 'admin');
7087 $protocols_available = get_plugin_list('webservice');
7088 $active_protocols = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols);
7089 ksort($protocols_available);
7091 foreach ($active_protocols as $key=>$protocol) {
7092 if (empty($protocols_available[$protocol])) {
7093 unset($active_protocols[$key]);
7097 $return = $OUTPUT->heading(get_string('actwebserviceshhdr', 'webservice'), 3, 'main');
7098 $return .= $OUTPUT->box_start('generalbox webservicesui');
7100 $table = new html_table();
7101 $table->head = array($strprotocol, $strversion, $strenable, $struninstall, $strsettings);
7102 $table->align = array('left', 'center', 'center', 'center', 'center');
7103 $table->width = '100%';
7104 $table->data = array();
7106 // iterate through auth plugins and add to the display table
7107 $url = "$CFG->wwwroot/$CFG->admin/webservice/protocols.php?sesskey=" . sesskey();
7108 foreach ($protocols_available as $protocol => $location) {
7109 $name = get_string('pluginname', 'webservice_'.$protocol);
7111 $plugin = new stdClass();
7112 if (file_exists($CFG->dirroot.'/webservice/'.$protocol.'/version.php')) {
7113 include($CFG->dirroot.'/webservice/'.$protocol.'/version.php');
7115 $version = isset($plugin->version) ? $plugin->version : '';
7117 // hide/show link
7118 if (in_array($protocol, $active_protocols)) {
7119 $hideshow = "<a href=\"$url&amp;action=disable&amp;webservice=$protocol\">";
7120 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('i/hide') . "\" class=\"icon\" alt=\"$strdisable\" /></a>";
7121 $displayname = "<span>$name</span>";
7122 } else {
7123 $hideshow = "<a href=\"$url&amp;action=enable&amp;webservice=$protocol\">";
7124 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('i/show') . "\" class=\"icon\" alt=\"$strenable\" /></a>";
7125 $displayname = "<span class=\"dimmed_text\">$name</span>";
7128 // delete link
7129 $uninstall = "<a href=\"$url&amp;action=uninstall&amp;webservice=$protocol\">$struninstall</a>";
7131 // settings link
7132 if (file_exists($CFG->dirroot.'/webservice/'.$protocol.'/settings.php')) {
7133 $settings = "<a href=\"settings.php?section=webservicesetting$protocol\">$strsettings</a>";
7134 } else {
7135 $settings = '';
7138 // add a row to the table
7139 $table->data[] = array($displayname, $version, $hideshow, $uninstall, $settings);
7141 $return .= html_writer::table($table);
7142 $return .= get_string('configwebserviceplugins', 'webservice');
7143 $return .= $OUTPUT->box_end();
7145 return highlight($query, $return);
7151 * Special class for web service token administration.
7153 * @author Jerome Mouneyrac
7155 class admin_setting_managewebservicetokens extends admin_setting {
7158 * Calls parent::__construct with specific arguments
7160 public function __construct() {
7161 $this->nosave = true;
7162 parent::__construct('webservicestokenui', get_string('managetokens', 'webservice'), '', '');
7166 * Always returns true, does nothing
7168 * @return true
7170 public function get_setting() {
7171 return true;
7175 * Always returns true, does nothing
7177 * @return true
7179 public function get_defaultsetting() {
7180 return true;
7184 * Always returns '', does not write anything
7186 * @return string Always returns ''
7188 public function write_setting($data) {
7189 // do not write any setting
7190 return '';
7194 * Builds the XHTML to display the control
7196 * @param string $data Unused
7197 * @param string $query
7198 * @return string
7200 public function output_html($data, $query='') {
7201 global $CFG, $OUTPUT, $DB, $USER;
7203 // display strings
7204 $stroperation = get_string('operation', 'webservice');
7205 $strtoken = get_string('token', 'webservice');
7206 $strservice = get_string('service', 'webservice');
7207 $struser = get_string('user');
7208 $strcontext = get_string('context', 'webservice');
7209 $strvaliduntil = get_string('validuntil', 'webservice');
7210 $striprestriction = get_string('iprestriction', 'webservice');
7212 $return = $OUTPUT->box_start('generalbox webservicestokenui');
7214 $table = new html_table();
7215 $table->head = array($strtoken, $struser, $strservice, $striprestriction, $strvaliduntil, $stroperation);
7216 $table->align = array('left', 'left', 'left', 'center', 'center', 'center');
7217 $table->width = '100%';
7218 $table->data = array();
7220 $tokenpageurl = "$CFG->wwwroot/$CFG->admin/webservice/tokens.php?sesskey=" . sesskey();
7222 //TODO: in order to let the administrator delete obsolete token, split this request in multiple request or use LEFT JOIN
7224 //here retrieve token list (including linked users firstname/lastname and linked services name)
7225 $sql = "SELECT t.id, t.token, u.id AS userid, u.firstname, u.lastname, s.name, t.validuntil, s.id AS serviceid
7226 FROM {external_tokens} t, {user} u, {external_services} s
7227 WHERE t.creatorid=? AND t.tokentype = ? AND s.id = t.externalserviceid AND t.userid = u.id";
7228 $tokens = $DB->get_records_sql($sql, array($USER->id, EXTERNAL_TOKEN_PERMANENT));
7229 if (!empty($tokens)) {
7230 foreach ($tokens as $token) {
7231 //TODO: retrieve context
7233 $delete = "<a href=\"".$tokenpageurl."&amp;action=delete&amp;tokenid=".$token->id."\">";
7234 $delete .= get_string('delete')."</a>";
7236 $validuntil = '';
7237 if (!empty($token->validuntil)) {
7238 $validuntil = date("F j, Y"); //TODO: language support (look for moodle function)
7241 $iprestriction = '';
7242 if (!empty($token->iprestriction)) {
7243 $iprestriction = $token->iprestriction;
7246 $userprofilurl = new moodle_url('/user/profile.php?id='.$token->userid);
7247 $useratag = html_writer::start_tag('a', array('href' => $userprofilurl));
7248 $useratag .= $token->firstname." ".$token->lastname;
7249 $useratag .= html_writer::end_tag('a');
7251 //check user missing capabilities
7252 require_once($CFG->dirroot . '/webservice/lib.php');
7253 $webservicemanager = new webservice();
7254 $usermissingcaps = $webservicemanager->get_missing_capabilities_by_users(
7255 array(array('id' => $token->userid)), $token->serviceid);
7257 if (!is_siteadmin($token->userid) and
7258 key_exists($token->userid, $usermissingcaps)) {
7259 $missingcapabilities = implode(',',
7260 $usermissingcaps[$token->userid]);
7261 if (!empty($missingcapabilities)) {
7262 $useratag .= html_writer::tag('div',
7263 get_string('usermissingcaps', 'webservice',
7264 $missingcapabilities)
7265 . '&nbsp;' . $OUTPUT->help_icon('missingcaps', 'webservice'),
7266 array('class' => 'missingcaps'));
7270 $table->data[] = array($token->token, $useratag, $token->name, $iprestriction, $validuntil, $delete);
7273 $return .= html_writer::table($table);
7274 } else {
7275 $return .= get_string('notoken', 'webservice');
7278 $return .= $OUTPUT->box_end();
7279 // add a token to the table
7280 $return .= "<a href=\"".$tokenpageurl."&amp;action=create\">";
7281 $return .= get_string('add')."</a>";
7283 return highlight($query, $return);
7288 * Colour picker
7290 * @copyright 2010 Sam Hemelryk
7291 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
7293 class admin_setting_configcolourpicker extends admin_setting {
7296 * Information for previewing the colour
7298 * @var array|null
7300 protected $previewconfig = null;
7304 * @param string $name
7305 * @param string $visiblename
7306 * @param string $description
7307 * @param string $defaultsetting
7308 * @param array $previewconfig Array('selector'=>'.some .css .selector','style'=>'backgroundColor');
7310 public function __construct($name, $visiblename, $description, $defaultsetting, array $previewconfig=null) {
7311 $this->previewconfig = $previewconfig;
7312 parent::__construct($name, $visiblename, $description, $defaultsetting);
7316 * Return the setting
7318 * @return mixed returns config if successful else null
7320 public function get_setting() {
7321 return $this->config_read($this->name);
7325 * Saves the setting
7327 * @param string $data
7328 * @return bool
7330 public function write_setting($data) {
7331 $data = $this->validate($data);
7332 if ($data === false) {
7333 return get_string('validateerror', 'admin');
7335 return ($this->config_write($this->name, $data) ? '' : get_string('errorsetting', 'admin'));
7339 * Validates the colour that was entered by the user
7341 * @param string $data
7342 * @return string|false
7344 protected function validate($data) {
7345 if (preg_match('/^#?([a-fA-F0-9]{3}){1,2}$/', $data)) {
7346 if (strpos($data, '#')!==0) {
7347 $data = '#'.$data;
7349 return $data;
7350 } else if (preg_match('/^[a-zA-Z]{3, 25}$/', $data)) {
7351 return $data;
7352 } else if (empty($data)) {
7353 return $this->defaultsetting;
7354 } else {
7355 return false;
7360 * Generates the HTML for the setting
7362 * @global moodle_page $PAGE
7363 * @global core_renderer $OUTPUT
7364 * @param string $data
7365 * @param string $query
7367 public function output_html($data, $query = '') {
7368 global $PAGE, $OUTPUT;
7369 $PAGE->requires->js_init_call('M.util.init_colour_picker', array($this->get_id(), $this->previewconfig));
7370 $content = html_writer::start_tag('div', array('class'=>'form-colourpicker defaultsnext'));
7371 $content .= html_writer::tag('div', $OUTPUT->pix_icon('i/loading', get_string('loading', 'admin'), 'moodle', array('class'=>'loadingicon')), array('class'=>'admin_colourpicker clearfix'));
7372 $content .= html_writer::empty_tag('input', array('type'=>'text','id'=>$this->get_id(), 'name'=>$this->get_full_name(), 'value'=>$this->get_setting(), 'size'=>'12'));
7373 if (!empty($this->previewconfig)) {
7374 $content .= html_writer::empty_tag('input', array('type'=>'button','id'=>$this->get_id().'_preview', 'value'=>get_string('preview'), 'class'=>'admin_colourpicker_preview'));
7376 $content .= html_writer::end_tag('div');
7377 return format_admin_setting($this, $this->visiblename, $content, $this->description, false, '', $this->get_defaultsetting(), $query);