2 // This file is part of Moodle - http://moodle.org/
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
18 * Functions and classes used during installation, upgrades and for admin settings.
20 * ADMIN SETTINGS TREE INTRODUCTION
22 * This file performs the following tasks:
23 * -it defines the necessary objects and interfaces to build the Moodle
25 * -it defines the admin_externalpage_setup()
27 * ADMIN_SETTING OBJECTS
29 * Moodle settings are represented by objects that inherit from the admin_setting
30 * class. These objects encapsulate how to read a setting, how to write a new value
31 * to a setting, and how to appropriately display the HTML to modify the setting.
33 * ADMIN_SETTINGPAGE OBJECTS
35 * The admin_setting objects are then grouped into admin_settingpages. The latter
36 * appear in the Moodle admin tree block. All interaction with admin_settingpage
37 * objects is handled by the admin/settings.php file.
39 * ADMIN_EXTERNALPAGE OBJECTS
41 * There are some settings in Moodle that are too complex to (efficiently) handle
42 * with admin_settingpages. (Consider, for example, user management and displaying
43 * lists of users.) In this case, we use the admin_externalpage object. This object
44 * places a link to an external PHP file in the admin tree block.
46 * If you're using an admin_externalpage object for some settings, you can take
47 * advantage of the admin_externalpage_* functions. For example, suppose you wanted
48 * to add a foo.php file into admin. First off, you add the following line to
49 * admin/settings/first.php (at the end of the file) or to some other file in
52 * $ADMIN->add('userinterface', new admin_externalpage('foo', get_string('foo'),
53 * $CFG->wwwdir . '/' . '$CFG->admin . '/foo.php', 'some_role_permission'));
56 * Next, in foo.php, your file structure would resemble the following:
58 * require(dirname(dirname(dirname(__FILE__))).'/config.php');
59 * require_once($CFG->libdir.'/adminlib.php');
60 * admin_externalpage_setup('foo');
61 * // functionality like processing form submissions goes here
62 * echo $OUTPUT->header();
63 * // your HTML goes here
64 * echo $OUTPUT->footer();
67 * The admin_externalpage_setup() function call ensures the user is logged in,
68 * and makes sure that they have the proper role permission to access the page.
69 * It also configures all $PAGE properties needed for navigation.
71 * ADMIN_CATEGORY OBJECTS
73 * Above and beyond all this, we have admin_category objects. These objects
74 * appear as folders in the admin tree block. They contain admin_settingpage's,
75 * admin_externalpage's, and other admin_category's.
79 * admin_settingpage's, admin_externalpage's, and admin_category's all inherit
80 * from part_of_admin_tree (a pseudointerface). This interface insists that
81 * a class has a check_access method for access permissions, a locate method
82 * used to find a specific node in the admin tree and find parent path.
84 * admin_category's inherit from parentable_part_of_admin_tree. This pseudo-
85 * interface ensures that the class implements a recursive add function which
86 * accepts a part_of_admin_tree object and searches for the proper place to
87 * put it. parentable_part_of_admin_tree implies part_of_admin_tree.
89 * Please note that the $this->name field of any part_of_admin_tree must be
90 * UNIQUE throughout the ENTIRE admin tree.
92 * The $this->name field of an admin_setting object (which is *not* part_of_
93 * admin_tree) must be unique on the respective admin_settingpage where it is
96 * Original author: Vincenzo K. Marcovecchio
97 * Maintainer: Petr Skoda
101 * @copyright 1999 onwards Martin Dougiamas http://dougiamas.com
102 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
105 defined('MOODLE_INTERNAL') ||
die();
108 require_once($CFG->libdir
.'/ddllib.php');
109 require_once($CFG->libdir
.'/xmlize.php');
110 require_once($CFG->libdir
.'/messagelib.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
123 function uninstall_plugin($type, $name) {
124 global $CFG, $DB, $OUTPUT;
126 // This may take a long time.
129 // recursively uninstall all module/editor subplugins first
130 if ($type === 'mod' ||
$type === 'editor') {
131 $base = get_component_directory($type . '_' . $name);
132 if (file_exists("$base/db/subplugins.php")) {
133 $subplugins = array();
134 include("$base/db/subplugins.php");
135 foreach ($subplugins as $subplugintype=>$dir) {
136 $instances = get_plugin_list($subplugintype);
137 foreach ($instances as $subpluginname => $notusedpluginpath) {
138 uninstall_plugin($subplugintype, $subpluginname);
145 $component = $type . '_' . $name; // eg. 'qtype_multichoice' or 'workshopgrading_accumulative' or 'mod_forum'
147 if ($type === 'mod') {
148 $pluginname = $name; // eg. 'forum'
149 if (get_string_manager()->string_exists('modulename', $component)) {
150 $strpluginname = get_string('modulename', $component);
152 $strpluginname = $component;
156 $pluginname = $component;
157 if (get_string_manager()->string_exists('pluginname', $component)) {
158 $strpluginname = get_string('pluginname', $component);
160 $strpluginname = $component;
164 echo $OUTPUT->heading($pluginname);
166 $plugindirectory = get_plugin_directory($type, $name);
167 $uninstalllib = $plugindirectory . '/db/uninstall.php';
168 if (file_exists($uninstalllib)) {
169 require_once($uninstalllib);
170 $uninstallfunction = 'xmldb_' . $pluginname . '_uninstall'; // eg. 'xmldb_workshop_uninstall()'
171 if (function_exists($uninstallfunction)) {
172 if (!$uninstallfunction()) {
173 echo $OUTPUT->notification('Encountered a problem running uninstall function for '. $pluginname);
178 if ($type === 'mod') {
179 // perform cleanup tasks specific for activity modules
181 if (!$module = $DB->get_record('modules', array('name' => $name))) {
182 print_error('moduledoesnotexist', 'error');
185 // delete all the relevant instances from all course sections
186 if ($coursemods = $DB->get_records('course_modules', array('module' => $module->id
))) {
187 foreach ($coursemods as $coursemod) {
188 if (!delete_mod_from_section($coursemod->id
, $coursemod->section
)) {
189 echo $OUTPUT->notification("Could not delete the $strpluginname with id = $coursemod->id from section $coursemod->section");
194 // clear course.modinfo for courses that used this module
195 $sql = "UPDATE {course}
197 WHERE id IN (SELECT DISTINCT course
198 FROM {course_modules}
200 $DB->execute($sql, array($module->id
));
202 // delete all the course module records
203 $DB->delete_records('course_modules', array('module' => $module->id
));
205 // delete module contexts
207 foreach ($coursemods as $coursemod) {
208 if (!delete_context(CONTEXT_MODULE
, $coursemod->id
)) {
209 echo $OUTPUT->notification("Could not delete the context for $strpluginname with id = $coursemod->id");
214 // delete the module entry itself
215 $DB->delete_records('modules', array('name' => $module->name
));
217 // cleanup the gradebook
218 require_once($CFG->libdir
.'/gradelib.php');
219 grade_uninstalled_module($module->name
);
221 // Perform any custom uninstall tasks
222 if (file_exists($CFG->dirroot
. '/mod/' . $module->name
. '/lib.php')) {
223 require_once($CFG->dirroot
. '/mod/' . $module->name
. '/lib.php');
224 $uninstallfunction = $module->name
. '_uninstall';
225 if (function_exists($uninstallfunction)) {
226 debugging("{$uninstallfunction}() has been deprecated. Use the plugin's db/uninstall.php instead", DEBUG_DEVELOPER
);
227 if (!$uninstallfunction()) {
228 echo $OUTPUT->notification('Encountered a problem running uninstall function for '. $module->name
.'!');
233 } else if ($type === 'enrol') {
234 // NOTE: this is a bit brute force way - it will not trigger events and hooks properly
235 // nuke all role assignments
236 role_unassign_all(array('component'=>$component));
237 // purge participants
238 $DB->delete_records_select('user_enrolments', "enrolid IN (SELECT id FROM {enrol} WHERE enrol = ?)", array($name));
239 // purge enrol instances
240 $DB->delete_records('enrol', array('enrol'=>$name));
241 // tweak enrol settings
242 if (!empty($CFG->enrol_plugins_enabled
)) {
243 $enabledenrols = explode(',', $CFG->enrol_plugins_enabled
);
244 $enabledenrols = array_unique($enabledenrols);
245 $enabledenrols = array_flip($enabledenrols);
246 unset($enabledenrols[$name]);
247 $enabledenrols = array_flip($enabledenrols);
248 if (is_array($enabledenrols)) {
249 set_config('enrol_plugins_enabled', implode(',', $enabledenrols));
253 } else if ($type === 'block') {
254 if ($block = $DB->get_record('block', array('name'=>$name))) {
255 // Inform block it's about to be deleted
256 if (file_exists("$CFG->dirroot/blocks/$block->name/block_$block->name.php")) {
257 $blockobject = block_instance($block->name
);
259 $blockobject->before_delete(); //only if we can create instance, block might have been already removed
263 // First delete instances and related contexts
264 $instances = $DB->get_records('block_instances', array('blockname' => $block->name
));
265 foreach($instances as $instance) {
266 blocks_delete_instance($instance);
270 $DB->delete_records('block', array('id'=>$block->id
));
272 } else if ($type === 'format') {
273 if (($defaultformat = get_config('moodlecourse', 'format')) && $defaultformat !== $name) {
274 $courses = $DB->get_records('course', array('format' => $name), 'id');
275 $data = (object)array('id' => null, 'format' => $defaultformat);
276 foreach ($courses as $record) {
277 $data->id
= $record->id
;
278 update_course($data);
281 $DB->delete_records('course_format_options', array('format' => $name));
284 // perform clean-up task common for all the plugin/subplugin types
286 //delete the web service functions and pre-built services
287 require_once($CFG->dirroot
.'/lib/externallib.php');
288 external_delete_descriptions($component);
290 // delete calendar events
291 $DB->delete_records('event', array('modulename' => $pluginname));
293 // delete all the logs
294 $DB->delete_records('log', array('module' => $pluginname));
296 // delete log_display information
297 $DB->delete_records('log_display', array('component' => $component));
299 // delete the module configuration records
300 unset_all_config_for_plugin($pluginname);
302 // delete message provider
303 message_provider_uninstall($component);
305 // delete message processor
306 if ($type === 'message') {
307 message_processor_uninstall($name);
310 // delete the plugin tables
311 $xmldbfilepath = $plugindirectory . '/db/install.xml';
312 drop_plugin_tables($component, $xmldbfilepath, false);
313 if ($type === 'mod' or $type === 'block') {
314 // non-frankenstyle table prefixes
315 drop_plugin_tables($name, $xmldbfilepath, false);
318 // delete the capabilities that were defined by this module
319 capabilities_cleanup($component);
321 // remove event handlers and dequeue pending events
322 events_uninstall($component);
324 // Delete all remaining files in the filepool owned by the component.
325 $fs = get_file_storage();
326 $fs->delete_component_files($component);
328 // Finally purge all caches.
331 echo $OUTPUT->notification(get_string('success'), 'notifysuccess');
335 * Returns the version of installed component
337 * @param string $component component name
338 * @param string $source either 'disk' or 'installed' - where to get the version information from
339 * @return string|bool version number or false if the component is not found
341 function get_component_version($component, $source='installed') {
344 list($type, $name) = normalize_component($component);
346 // moodle core or a core subsystem
347 if ($type === 'core') {
348 if ($source === 'installed') {
349 if (empty($CFG->version
)) {
352 return $CFG->version
;
355 if (!is_readable($CFG->dirroot
.'/version.php')) {
358 $version = null; //initialize variable for IDEs
359 include($CFG->dirroot
.'/version.php');
366 if ($type === 'mod') {
367 if ($source === 'installed') {
368 return $DB->get_field('modules', 'version', array('name'=>$name));
370 $mods = get_plugin_list('mod');
371 if (empty($mods[$name]) or !is_readable($mods[$name].'/version.php')) {
374 $module = new stdclass();
375 include($mods[$name].'/version.php');
376 return $module->version
;
382 if ($type === 'block') {
383 if ($source === 'installed') {
384 return $DB->get_field('block', 'version', array('name'=>$name));
386 $blocks = get_plugin_list('block');
387 if (empty($blocks[$name]) or !is_readable($blocks[$name].'/version.php')) {
390 $plugin = new stdclass();
391 include($blocks[$name].'/version.php');
392 return $plugin->version
;
397 // all other plugin types
398 if ($source === 'installed') {
399 return get_config($type.'_'.$name, 'version');
401 $plugins = get_plugin_list($type);
402 if (empty($plugins[$name])) {
405 $plugin = new stdclass();
406 include($plugins[$name].'/version.php');
407 return $plugin->version
;
413 * Delete all plugin tables
415 * @param string $name Name of plugin, used as table prefix
416 * @param string $file Path to install.xml file
417 * @param bool $feedback defaults to true
418 * @return bool Always returns true
420 function drop_plugin_tables($name, $file, $feedback=true) {
423 // first try normal delete
424 if (file_exists($file) and $DB->get_manager()->delete_tables_from_xmldb_file($file)) {
428 // then try to find all tables that start with name and are not in any xml file
429 $used_tables = get_used_table_names();
431 $tables = $DB->get_tables();
433 /// Iterate over, fixing id fields as necessary
434 foreach ($tables as $table) {
435 if (in_array($table, $used_tables)) {
439 if (strpos($table, $name) !== 0) {
443 // found orphan table --> delete it
444 if ($DB->get_manager()->table_exists($table)) {
445 $xmldb_table = new xmldb_table($table);
446 $DB->get_manager()->drop_table($xmldb_table);
454 * Returns names of all known tables == tables that moodle knows about.
456 * @return array Array of lowercase table names
458 function get_used_table_names() {
459 $table_names = array();
460 $dbdirs = get_db_directories();
462 foreach ($dbdirs as $dbdir) {
463 $file = $dbdir.'/install.xml';
465 $xmldb_file = new xmldb_file($file);
467 if (!$xmldb_file->fileExists()) {
471 $loaded = $xmldb_file->loadXMLStructure();
472 $structure = $xmldb_file->getStructure();
474 if ($loaded and $tables = $structure->getTables()) {
475 foreach($tables as $table) {
476 $table_names[] = strtolower($table->getName());
485 * Returns list of all directories where we expect install.xml files
486 * @return array Array of paths
488 function get_db_directories() {
493 /// First, the main one (lib/db)
494 $dbdirs[] = $CFG->libdir
.'/db';
496 /// Then, all the ones defined by get_plugin_types()
497 $plugintypes = get_plugin_types();
498 foreach ($plugintypes as $plugintype => $pluginbasedir) {
499 if ($plugins = get_plugin_list($plugintype)) {
500 foreach ($plugins as $plugin => $plugindir) {
501 $dbdirs[] = $plugindir.'/db';
510 * Try to obtain or release the cron lock.
511 * @param string $name name of lock
512 * @param int $until timestamp when this lock considered stale, null means remove lock unconditionally
513 * @param bool $ignorecurrent ignore current lock state, usually extend previous lock, defaults to false
514 * @return bool true if lock obtained
516 function set_cron_lock($name, $until, $ignorecurrent=false) {
519 debugging("Tried to get a cron lock for a null fieldname");
523 // remove lock by force == remove from config table
524 if (is_null($until)) {
525 set_config($name, null);
529 if (!$ignorecurrent) {
530 // read value from db - other processes might have changed it
531 $value = $DB->get_field('config', 'value', array('name'=>$name));
533 if ($value and $value > time()) {
539 set_config($name, $until);
544 * Test if and critical warnings are present
547 function admin_critical_warnings_present() {
550 if (!has_capability('moodle/site:config', context_system
::instance())) {
554 if (!isset($SESSION->admin_critical_warning
)) {
555 $SESSION->admin_critical_warning
= 0;
556 if (is_dataroot_insecure(true) === INSECURE_DATAROOT_ERROR
) {
557 $SESSION->admin_critical_warning
= 1;
561 return $SESSION->admin_critical_warning
;
565 * Detects if float supports at least 10 decimal digits
567 * Detects if float supports at least 10 decimal digits
568 * and also if float-->string conversion works as expected.
570 * @return bool true if problem found
572 function is_float_problem() {
573 $num1 = 2009010200.01;
574 $num2 = 2009010200.02;
576 return ((string)$num1 === (string)$num2 or $num1 === $num2 or $num2 <= (string)$num1);
580 * Try to verify that dataroot is not accessible from web.
582 * Try to verify that dataroot is not accessible from web.
583 * It is not 100% correct but might help to reduce number of vulnerable sites.
584 * Protection from httpd.conf and .htaccess is not detected properly.
586 * @uses INSECURE_DATAROOT_WARNING
587 * @uses INSECURE_DATAROOT_ERROR
588 * @param bool $fetchtest try to test public access by fetching file, default false
589 * @return mixed empty means secure, INSECURE_DATAROOT_ERROR found a critical problem, INSECURE_DATAROOT_WARNING might be problematic
591 function is_dataroot_insecure($fetchtest=false) {
594 $siteroot = str_replace('\\', '/', strrev($CFG->dirroot
.'/')); // win32 backslash workaround
596 $rp = preg_replace('|https?://[^/]+|i', '', $CFG->wwwroot
, 1);
597 $rp = strrev(trim($rp, '/'));
598 $rp = explode('/', $rp);
600 if (strpos($siteroot, '/'.$r.'/') === 0) {
601 $siteroot = substr($siteroot, strlen($r)+
1); // moodle web in subdirectory
603 break; // probably alias root
607 $siteroot = strrev($siteroot);
608 $dataroot = str_replace('\\', '/', $CFG->dataroot
.'/');
610 if (strpos($dataroot, $siteroot) !== 0) {
615 return INSECURE_DATAROOT_WARNING
;
618 // now try all methods to fetch a test file using http protocol
620 $httpdocroot = str_replace('\\', '/', strrev($CFG->dirroot
.'/'));
621 preg_match('|(https?://[^/]+)|i', $CFG->wwwroot
, $matches);
622 $httpdocroot = $matches[1];
623 $datarooturl = $httpdocroot.'/'. substr($dataroot, strlen($siteroot));
624 make_upload_directory('diag');
625 $testfile = $CFG->dataroot
.'/diag/public.txt';
626 if (!file_exists($testfile)) {
627 file_put_contents($testfile, 'test file, do not delete');
629 $teststr = trim(file_get_contents($testfile));
630 if (empty($teststr)) {
632 return INSECURE_DATAROOT_WARNING
;
635 $testurl = $datarooturl.'/diag/public.txt';
636 if (extension_loaded('curl') and
637 !(stripos(ini_get('disable_functions'), 'curl_init') !== FALSE) and
638 !(stripos(ini_get('disable_functions'), 'curl_setop') !== FALSE) and
639 ($ch = @curl_init
($testurl)) !== false) {
640 curl_setopt($ch, CURLOPT_RETURNTRANSFER
, true);
641 curl_setopt($ch, CURLOPT_HEADER
, false);
642 $data = curl_exec($ch);
643 if (!curl_errno($ch)) {
645 if ($data === $teststr) {
647 return INSECURE_DATAROOT_ERROR
;
653 if ($data = @file_get_contents
($testurl)) {
655 if ($data === $teststr) {
656 return INSECURE_DATAROOT_ERROR
;
660 preg_match('|https?://([^/]+)|i', $testurl, $matches);
661 $sitename = $matches[1];
663 if ($fp = @fsockopen
($sitename, 80, $error)) {
664 preg_match('|https?://[^/]+(.*)|i', $testurl, $matches);
665 $localurl = $matches[1];
666 $out = "GET $localurl HTTP/1.1\r\n";
667 $out .= "Host: $sitename\r\n";
668 $out .= "Connection: Close\r\n\r\n";
674 $data .= fgets($fp, 1024);
675 } else if (@fgets
($fp, 1024) === "\r\n") {
681 if ($data === $teststr) {
682 return INSECURE_DATAROOT_ERROR
;
686 return INSECURE_DATAROOT_WARNING
;
690 * Enables CLI maintenance mode by creating new dataroot/climaintenance.html file.
692 function enable_cli_maintenance_mode() {
695 if (file_exists("$CFG->dataroot/climaintenance.html")) {
696 unlink("$CFG->dataroot/climaintenance.html");
699 if (isset($CFG->maintenance_message
) and !html_is_blank($CFG->maintenance_message
)) {
700 $data = $CFG->maintenance_message
;
701 $data = bootstrap_renderer
::early_error_content($data, null, null, null);
702 $data = bootstrap_renderer
::plain_page(get_string('sitemaintenance', 'admin'), $data);
704 } else if (file_exists("$CFG->dataroot/climaintenance.template.html")) {
705 $data = file_get_contents("$CFG->dataroot/climaintenance.template.html");
708 $data = get_string('sitemaintenance', 'admin');
709 $data = bootstrap_renderer
::early_error_content($data, null, null, null);
710 $data = bootstrap_renderer
::plain_page(get_string('sitemaintenance', 'admin'), $data);
713 file_put_contents("$CFG->dataroot/climaintenance.html", $data);
714 chmod("$CFG->dataroot/climaintenance.html", $CFG->filepermissions
);
717 /// CLASS DEFINITIONS /////////////////////////////////////////////////////////
721 * Interface for anything appearing in the admin tree
723 * The interface that is implemented by anything that appears in the admin tree
724 * block. It forces inheriting classes to define a method for checking user permissions
725 * and methods for finding something in the admin tree.
727 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
729 interface part_of_admin_tree
{
732 * Finds a named part_of_admin_tree.
734 * Used to find a part_of_admin_tree. If a class only inherits part_of_admin_tree
735 * and not parentable_part_of_admin_tree, then this function should only check if
736 * $this->name matches $name. If it does, it should return a reference to $this,
737 * otherwise, it should return a reference to NULL.
739 * If a class inherits parentable_part_of_admin_tree, this method should be called
740 * recursively on all child objects (assuming, of course, the parent object's name
741 * doesn't match the search criterion).
743 * @param string $name The internal name of the part_of_admin_tree we're searching for.
744 * @return mixed An object reference or a NULL reference.
746 public function locate($name);
749 * Removes named part_of_admin_tree.
751 * @param string $name The internal name of the part_of_admin_tree we want to remove.
752 * @return bool success.
754 public function prune($name);
758 * @param string $query
759 * @return mixed array-object structure of found settings and pages
761 public function search($query);
764 * Verifies current user's access to this part_of_admin_tree.
766 * Used to check if the current user has access to this part of the admin tree or
767 * not. If a class only inherits part_of_admin_tree and not parentable_part_of_admin_tree,
768 * then this method is usually just a call to has_capability() in the site context.
770 * If a class inherits parentable_part_of_admin_tree, this method should return the
771 * logical OR of the return of check_access() on all child objects.
773 * @return bool True if the user has access, false if she doesn't.
775 public function check_access();
778 * Mostly useful for removing of some parts of the tree in admin tree block.
780 * @return True is hidden from normal list view
782 public function is_hidden();
785 * Show we display Save button at the page bottom?
788 public function show_save();
793 * Interface implemented by any part_of_admin_tree that has children.
795 * The interface implemented by any part_of_admin_tree that can be a parent
796 * to other part_of_admin_tree's. (For now, this only includes admin_category.) Apart
797 * from ensuring part_of_admin_tree compliancy, it also ensures inheriting methods
798 * include an add method for adding other part_of_admin_tree objects as children.
800 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
802 interface parentable_part_of_admin_tree
extends part_of_admin_tree
{
805 * Adds a part_of_admin_tree object to the admin tree.
807 * Used to add a part_of_admin_tree object to this object or a child of this
808 * object. $something should only be added if $destinationname matches
809 * $this->name. If it doesn't, add should be called on child objects that are
810 * also parentable_part_of_admin_tree's.
812 * $something should be appended as the last child in the $destinationname. If the
813 * $beforesibling is specified, $something should be prepended to it. If the given
814 * sibling is not found, $something should be appended to the end of $destinationname
815 * and a developer debugging message should be displayed.
817 * @param string $destinationname The internal name of the new parent for $something.
818 * @param part_of_admin_tree $something The object to be added.
819 * @return bool True on success, false on failure.
821 public function add($destinationname, $something, $beforesibling = null);
827 * The object used to represent folders (a.k.a. categories) in the admin tree block.
829 * Each admin_category object contains a number of part_of_admin_tree objects.
831 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
833 class admin_category
implements parentable_part_of_admin_tree
{
835 /** @var mixed An array of part_of_admin_tree objects that are this object's children */
837 /** @var string An internal name for this category. Must be unique amongst ALL part_of_admin_tree objects */
839 /** @var string The displayed name for this category. Usually obtained through get_string() */
841 /** @var bool Should this category be hidden in admin tree block? */
843 /** @var mixed Either a string or an array or strings */
845 /** @var mixed Either a string or an array or strings */
848 /** @var array fast lookup category cache, all categories of one tree point to one cache */
849 protected $category_cache;
852 * Constructor for an empty admin category
854 * @param string $name The internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
855 * @param string $visiblename The displayed named for this category. Usually obtained through get_string()
856 * @param bool $hidden hide category in admin tree block, defaults to false
858 public function __construct($name, $visiblename, $hidden=false) {
859 $this->children
= array();
861 $this->visiblename
= $visiblename;
862 $this->hidden
= $hidden;
866 * Returns a reference to the part_of_admin_tree object with internal name $name.
868 * @param string $name The internal name of the object we want.
869 * @param bool $findpath initialize path and visiblepath arrays
870 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
873 public function locate($name, $findpath=false) {
874 if (!isset($this->category_cache
[$this->name
])) {
875 // somebody much have purged the cache
876 $this->category_cache
[$this->name
] = $this;
879 if ($this->name
== $name) {
881 $this->visiblepath
[] = $this->visiblename
;
882 $this->path
[] = $this->name
;
887 // quick category lookup
888 if (!$findpath and isset($this->category_cache
[$name])) {
889 return $this->category_cache
[$name];
893 foreach($this->children
as $childid=>$unused) {
894 if ($return = $this->children
[$childid]->locate($name, $findpath)) {
899 if (!is_null($return) and $findpath) {
900 $return->visiblepath
[] = $this->visiblename
;
901 $return->path
[] = $this->name
;
910 * @param string query
911 * @return mixed array-object structure of found settings and pages
913 public function search($query) {
915 foreach ($this->children
as $child) {
916 $subsearch = $child->search($query);
917 if (!is_array($subsearch)) {
918 debugging('Incorrect search result from '.$child->name
);
921 $result = array_merge($result, $subsearch);
927 * Removes part_of_admin_tree object with internal name $name.
929 * @param string $name The internal name of the object we want to remove.
930 * @return bool success
932 public function prune($name) {
934 if ($this->name
== $name) {
935 return false; //can not remove itself
938 foreach($this->children
as $precedence => $child) {
939 if ($child->name
== $name) {
940 // clear cache and delete self
941 while($this->category_cache
) {
942 // delete the cache, but keep the original array address
943 array_pop($this->category_cache
);
945 unset($this->children
[$precedence]);
947 } else if ($this->children
[$precedence]->prune($name)) {
955 * Adds a part_of_admin_tree to a child or grandchild (or great-grandchild, and so forth) of this object.
957 * By default the new part of the tree is appended as the last child of the parent. You
958 * can specify a sibling node that the new part should be prepended to. If the given
959 * sibling is not found, the part is appended to the end (as it would be by default) and
960 * a developer debugging message is displayed.
962 * @throws coding_exception if the $beforesibling is empty string or is not string at all.
963 * @param string $destinationame The internal name of the immediate parent that we want for $something.
964 * @param mixed $something A part_of_admin_tree or setting instance to be added.
965 * @param string $beforesibling The name of the parent's child the $something should be prepended to.
966 * @return bool True if successfully added, false if $something can not be added.
968 public function add($parentname, $something, $beforesibling = null) {
969 $parent = $this->locate($parentname);
970 if (is_null($parent)) {
971 debugging('parent does not exist!');
975 if ($something instanceof part_of_admin_tree
) {
976 if (!($parent instanceof parentable_part_of_admin_tree
)) {
977 debugging('error - parts of tree can be inserted only into parentable parts');
980 if (debugging('', DEBUG_DEVELOPER
) && !is_null($this->locate($something->name
))) {
981 // The name of the node is already used, simply warn the developer that this should not happen.
982 // It is intentional to check for the debug level before performing the check.
983 debugging('Duplicate admin page name: ' . $something->name
, DEBUG_DEVELOPER
);
985 if (is_null($beforesibling)) {
986 // Append $something as the parent's last child.
987 $parent->children
[] = $something;
989 if (!is_string($beforesibling) or trim($beforesibling) === '') {
990 throw new coding_exception('Unexpected value of the beforesibling parameter');
992 // Try to find the position of the sibling.
993 $siblingposition = null;
994 foreach ($parent->children
as $childposition => $child) {
995 if ($child->name
=== $beforesibling) {
996 $siblingposition = $childposition;
1000 if (is_null($siblingposition)) {
1001 debugging('Sibling '.$beforesibling.' not found', DEBUG_DEVELOPER
);
1002 $parent->children
[] = $something;
1004 $parent->children
= array_merge(
1005 array_slice($parent->children
, 0, $siblingposition),
1007 array_slice($parent->children
, $siblingposition)
1011 if ($something instanceof admin_category
) {
1012 if (isset($this->category_cache
[$something->name
])) {
1013 debugging('Duplicate admin category name: '.$something->name
);
1015 $this->category_cache
[$something->name
] = $something;
1016 $something->category_cache
=& $this->category_cache
;
1017 foreach ($something->children
as $child) {
1018 // just in case somebody already added subcategories
1019 if ($child instanceof admin_category
) {
1020 if (isset($this->category_cache
[$child->name
])) {
1021 debugging('Duplicate admin category name: '.$child->name
);
1023 $this->category_cache
[$child->name
] = $child;
1024 $child->category_cache
=& $this->category_cache
;
1033 debugging('error - can not add this element');
1040 * Checks if the user has access to anything in this category.
1042 * @return bool True if the user has access to at least one child in this category, false otherwise.
1044 public function check_access() {
1045 foreach ($this->children
as $child) {
1046 if ($child->check_access()) {
1054 * Is this category hidden in admin tree block?
1056 * @return bool True if hidden
1058 public function is_hidden() {
1059 return $this->hidden
;
1063 * Show we display Save button at the page bottom?
1066 public function show_save() {
1067 foreach ($this->children
as $child) {
1068 if ($child->show_save()) {
1078 * Root of admin settings tree, does not have any parent.
1080 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1082 class admin_root
extends admin_category
{
1083 /** @var array List of errors */
1085 /** @var string search query */
1087 /** @var bool full tree flag - true means all settings required, false only pages required */
1089 /** @var bool flag indicating loaded tree */
1091 /** @var mixed site custom defaults overriding defaults in settings files*/
1092 public $custom_defaults;
1095 * @param bool $fulltree true means all settings required,
1096 * false only pages required
1098 public function __construct($fulltree) {
1101 parent
::__construct('root', get_string('administration'), false);
1102 $this->errors
= array();
1104 $this->fulltree
= $fulltree;
1105 $this->loaded
= false;
1107 $this->category_cache
= array();
1109 // load custom defaults if found
1110 $this->custom_defaults
= null;
1111 $defaultsfile = "$CFG->dirroot/local/defaults.php";
1112 if (is_readable($defaultsfile)) {
1113 $defaults = array();
1114 include($defaultsfile);
1115 if (is_array($defaults) and count($defaults)) {
1116 $this->custom_defaults
= $defaults;
1122 * Empties children array, and sets loaded to false
1124 * @param bool $requirefulltree
1126 public function purge_children($requirefulltree) {
1127 $this->children
= array();
1128 $this->fulltree
= ($requirefulltree ||
$this->fulltree
);
1129 $this->loaded
= false;
1130 //break circular dependencies - this helps PHP 5.2
1131 while($this->category_cache
) {
1132 array_pop($this->category_cache
);
1134 $this->category_cache
= array();
1140 * Links external PHP pages into the admin tree.
1142 * See detailed usage example at the top of this document (adminlib.php)
1144 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1146 class admin_externalpage
implements part_of_admin_tree
{
1148 /** @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects */
1151 /** @var string The displayed name for this external page. Usually obtained through get_string(). */
1152 public $visiblename;
1154 /** @var string The external URL that we should link to when someone requests this external page. */
1157 /** @var string The role capability/permission a user must have to access this external page. */
1158 public $req_capability;
1160 /** @var object The context in which capability/permission should be checked, default is site context. */
1163 /** @var bool hidden in admin tree block. */
1166 /** @var mixed either string or array of string */
1169 /** @var array list of visible names of page parents */
1170 public $visiblepath;
1173 * Constructor for adding an external page into the admin tree.
1175 * @param string $name The internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects.
1176 * @param string $visiblename The displayed name for this external page. Usually obtained through get_string().
1177 * @param string $url The external URL that we should link to when someone requests this external page.
1178 * @param mixed $req_capability The role capability/permission a user must have to access this external page. Defaults to 'moodle/site:config'.
1179 * @param boolean $hidden Is this external page hidden in admin tree block? Default false.
1180 * @param stdClass $context The context the page relates to. Not sure what happens
1181 * if you specify something other than system or front page. Defaults to system.
1183 public function __construct($name, $visiblename, $url, $req_capability='moodle/site:config', $hidden=false, $context=NULL) {
1184 $this->name
= $name;
1185 $this->visiblename
= $visiblename;
1187 if (is_array($req_capability)) {
1188 $this->req_capability
= $req_capability;
1190 $this->req_capability
= array($req_capability);
1192 $this->hidden
= $hidden;
1193 $this->context
= $context;
1197 * Returns a reference to the part_of_admin_tree object with internal name $name.
1199 * @param string $name The internal name of the object we want.
1200 * @param bool $findpath defaults to false
1201 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
1203 public function locate($name, $findpath=false) {
1204 if ($this->name
== $name) {
1206 $this->visiblepath
= array($this->visiblename
);
1207 $this->path
= array($this->name
);
1217 * This function always returns false, required function by interface
1219 * @param string $name
1222 public function prune($name) {
1227 * Search using query
1229 * @param string $query
1230 * @return mixed array-object structure of found settings and pages
1232 public function search($query) {
1234 if (strpos(strtolower($this->name
), $query) !== false) {
1236 } else if (strpos(textlib
::strtolower($this->visiblename
), $query) !== false) {
1240 $result = new stdClass();
1241 $result->page
= $this;
1242 $result->settings
= array();
1243 return array($this->name
=> $result);
1250 * Determines if the current user has access to this external page based on $this->req_capability.
1252 * @return bool True if user has access, false otherwise.
1254 public function check_access() {
1256 $context = empty($this->context
) ? context_system
::instance() : $this->context
;
1257 foreach($this->req_capability
as $cap) {
1258 if (has_capability($cap, $context)) {
1266 * Is this external page hidden in admin tree block?
1268 * @return bool True if hidden
1270 public function is_hidden() {
1271 return $this->hidden
;
1275 * Show we display Save button at the page bottom?
1278 public function show_save() {
1285 * Used to group a number of admin_setting objects into a page and add them to the admin tree.
1287 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1289 class admin_settingpage
implements part_of_admin_tree
{
1291 /** @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects */
1294 /** @var string The displayed name for this external page. Usually obtained through get_string(). */
1295 public $visiblename;
1297 /** @var mixed An array of admin_setting objects that are part of this setting page. */
1300 /** @var string The role capability/permission a user must have to access this external page. */
1301 public $req_capability;
1303 /** @var object The context in which capability/permission should be checked, default is site context. */
1306 /** @var bool hidden in admin tree block. */
1309 /** @var mixed string of paths or array of strings of paths */
1312 /** @var array list of visible names of page parents */
1313 public $visiblepath;
1316 * see admin_settingpage for details of this function
1318 * @param string $name The internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects.
1319 * @param string $visiblename The displayed name for this external page. Usually obtained through get_string().
1320 * @param mixed $req_capability The role capability/permission a user must have to access this external page. Defaults to 'moodle/site:config'.
1321 * @param boolean $hidden Is this external page hidden in admin tree block? Default false.
1322 * @param stdClass $context The context the page relates to. Not sure what happens
1323 * if you specify something other than system or front page. Defaults to system.
1325 public function __construct($name, $visiblename, $req_capability='moodle/site:config', $hidden=false, $context=NULL) {
1326 $this->settings
= new stdClass();
1327 $this->name
= $name;
1328 $this->visiblename
= $visiblename;
1329 if (is_array($req_capability)) {
1330 $this->req_capability
= $req_capability;
1332 $this->req_capability
= array($req_capability);
1334 $this->hidden
= $hidden;
1335 $this->context
= $context;
1339 * see admin_category
1341 * @param string $name
1342 * @param bool $findpath
1343 * @return mixed Object (this) if name == this->name, else returns null
1345 public function locate($name, $findpath=false) {
1346 if ($this->name
== $name) {
1348 $this->visiblepath
= array($this->visiblename
);
1349 $this->path
= array($this->name
);
1359 * Search string in settings page.
1361 * @param string $query
1364 public function search($query) {
1367 foreach ($this->settings
as $setting) {
1368 if ($setting->is_related($query)) {
1369 $found[] = $setting;
1374 $result = new stdClass();
1375 $result->page
= $this;
1376 $result->settings
= $found;
1377 return array($this->name
=> $result);
1381 if (strpos(strtolower($this->name
), $query) !== false) {
1383 } else if (strpos(textlib
::strtolower($this->visiblename
), $query) !== false) {
1387 $result = new stdClass();
1388 $result->page
= $this;
1389 $result->settings
= array();
1390 return array($this->name
=> $result);
1397 * This function always returns false, required by interface
1399 * @param string $name
1400 * @return bool Always false
1402 public function prune($name) {
1407 * adds an admin_setting to this admin_settingpage
1409 * 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
1410 * n.b. each admin_setting in an admin_settingpage must have a unique internal name
1412 * @param object $setting is the admin_setting object you want to add
1413 * @return bool true if successful, false if not
1415 public function add($setting) {
1416 if (!($setting instanceof admin_setting
)) {
1417 debugging('error - not a setting instance');
1421 $this->settings
->{$setting->name
} = $setting;
1426 * see admin_externalpage
1428 * @return bool Returns true for yes false for no
1430 public function check_access() {
1432 $context = empty($this->context
) ? context_system
::instance() : $this->context
;
1433 foreach($this->req_capability
as $cap) {
1434 if (has_capability($cap, $context)) {
1442 * outputs this page as html in a table (suitable for inclusion in an admin pagetype)
1443 * @return string Returns an XHTML string
1445 public function output_html() {
1446 $adminroot = admin_get_root();
1447 $return = '<fieldset>'."\n".'<div class="clearer"><!-- --></div>'."\n";
1448 foreach($this->settings
as $setting) {
1449 $fullname = $setting->get_full_name();
1450 if (array_key_exists($fullname, $adminroot->errors
)) {
1451 $data = $adminroot->errors
[$fullname]->data
;
1453 $data = $setting->get_setting();
1454 // do not use defaults if settings not available - upgrade settings handles the defaults!
1456 $return .= $setting->output_html($data);
1458 $return .= '</fieldset>';
1463 * Is this settings page hidden in admin tree block?
1465 * @return bool True if hidden
1467 public function is_hidden() {
1468 return $this->hidden
;
1472 * Show we display Save button at the page bottom?
1475 public function show_save() {
1476 foreach($this->settings
as $setting) {
1477 if (empty($setting->nosave
)) {
1487 * Admin settings class. Only exists on setting pages.
1488 * Read & write happens at this level; no authentication.
1490 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1492 abstract class admin_setting
{
1493 /** @var string unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins. */
1495 /** @var string localised name */
1496 public $visiblename;
1497 /** @var string localised long description in Markdown format */
1498 public $description;
1499 /** @var mixed Can be string or array of string */
1500 public $defaultsetting;
1502 public $updatedcallback;
1503 /** @var mixed can be String or Null. Null means main config table */
1504 public $plugin; // null means main config table
1505 /** @var bool true indicates this setting does not actually save anything, just information */
1506 public $nosave = false;
1507 /** @var bool if set, indicates that a change to this setting requires rebuild course cache */
1508 public $affectsmodinfo = false;
1512 * @param string $name unique ascii name, either 'mysetting' for settings that in config,
1513 * or 'myplugin/mysetting' for ones in config_plugins.
1514 * @param string $visiblename localised name
1515 * @param string $description localised long description
1516 * @param mixed $defaultsetting string or array depending on implementation
1518 public function __construct($name, $visiblename, $description, $defaultsetting) {
1519 $this->parse_setting_name($name);
1520 $this->visiblename
= $visiblename;
1521 $this->description
= $description;
1522 $this->defaultsetting
= $defaultsetting;
1526 * Set up $this->name and potentially $this->plugin
1528 * Set up $this->name and possibly $this->plugin based on whether $name looks
1529 * like 'settingname' or 'plugin/settingname'. Also, do some sanity checking
1530 * on the names, that is, output a developer debug warning if the name
1531 * contains anything other than [a-zA-Z0-9_]+.
1533 * @param string $name the setting name passed in to the constructor.
1535 private function parse_setting_name($name) {
1536 $bits = explode('/', $name);
1537 if (count($bits) > 2) {
1538 throw new moodle_exception('invalidadminsettingname', '', '', $name);
1540 $this->name
= array_pop($bits);
1541 if (!preg_match('/^[a-zA-Z0-9_]+$/', $this->name
)) {
1542 throw new moodle_exception('invalidadminsettingname', '', '', $name);
1544 if (!empty($bits)) {
1545 $this->plugin
= array_pop($bits);
1546 if ($this->plugin
=== 'moodle') {
1547 $this->plugin
= null;
1548 } else if (!preg_match('/^[a-zA-Z0-9_]+$/', $this->plugin
)) {
1549 throw new moodle_exception('invalidadminsettingname', '', '', $name);
1555 * Returns the fullname prefixed by the plugin
1558 public function get_full_name() {
1559 return 's_'.$this->plugin
.'_'.$this->name
;
1563 * Returns the ID string based on plugin and name
1566 public function get_id() {
1567 return 'id_s_'.$this->plugin
.'_'.$this->name
;
1571 * @param bool $affectsmodinfo If true, changes to this setting will
1572 * cause the course cache to be rebuilt
1574 public function set_affects_modinfo($affectsmodinfo) {
1575 $this->affectsmodinfo
= $affectsmodinfo;
1579 * Returns the config if possible
1581 * @return mixed returns config if successful else null
1583 public function config_read($name) {
1585 if (!empty($this->plugin
)) {
1586 $value = get_config($this->plugin
, $name);
1587 return $value === false ?
NULL : $value;
1590 if (isset($CFG->$name)) {
1599 * Used to set a config pair and log change
1601 * @param string $name
1602 * @param mixed $value Gets converted to string if not null
1603 * @return bool Write setting to config table
1605 public function config_write($name, $value) {
1606 global $DB, $USER, $CFG;
1608 if ($this->nosave
) {
1612 // make sure it is a real change
1613 $oldvalue = get_config($this->plugin
, $name);
1614 $oldvalue = ($oldvalue === false) ?
null : $oldvalue; // normalise
1615 $value = is_null($value) ?
null : (string)$value;
1617 if ($oldvalue === $value) {
1622 set_config($name, $value, $this->plugin
);
1624 // Some admin settings affect course modinfo
1625 if ($this->affectsmodinfo
) {
1626 // Clear course cache for all courses
1627 rebuild_course_cache(0, true);
1631 $log = new stdClass();
1632 $log->userid
= during_initial_install() ?
0 :$USER->id
; // 0 as user id during install
1633 $log->timemodified
= time();
1634 $log->plugin
= $this->plugin
;
1636 $log->value
= $value;
1637 $log->oldvalue
= $oldvalue;
1638 $DB->insert_record('config_log', $log);
1640 return true; // BC only
1644 * Returns current value of this setting
1645 * @return mixed array or string depending on instance, NULL means not set yet
1647 public abstract function get_setting();
1650 * Returns default setting if exists
1651 * @return mixed array or string depending on instance; NULL means no default, user must supply
1653 public function get_defaultsetting() {
1654 $adminroot = admin_get_root(false, false);
1655 if (!empty($adminroot->custom_defaults
)) {
1656 $plugin = is_null($this->plugin
) ?
'moodle' : $this->plugin
;
1657 if (isset($adminroot->custom_defaults
[$plugin])) {
1658 if (array_key_exists($this->name
, $adminroot->custom_defaults
[$plugin])) { // null is valid value here ;-)
1659 return $adminroot->custom_defaults
[$plugin][$this->name
];
1663 return $this->defaultsetting
;
1669 * @param mixed $data string or array, must not be NULL
1670 * @return string empty string if ok, string error message otherwise
1672 public abstract function write_setting($data);
1675 * Return part of form with setting
1676 * This function should always be overwritten
1678 * @param mixed $data array or string depending on setting
1679 * @param string $query
1682 public function output_html($data, $query='') {
1683 // should be overridden
1688 * Function called if setting updated - cleanup, cache reset, etc.
1689 * @param string $functionname Sets the function name
1692 public function set_updatedcallback($functionname) {
1693 $this->updatedcallback
= $functionname;
1697 * Execute postupdatecallback if necessary.
1698 * @param mixed $original original value before write_setting()
1699 * @return bool true if changed, false if not.
1701 public function post_write_settings($original) {
1702 // Comparison must work for arrays too.
1703 if (serialize($original) === serialize($this->get_setting())) {
1707 $callbackfunction = $this->updatedcallback
;
1708 if (!empty($callbackfunction) and function_exists($callbackfunction)) {
1709 $callbackfunction($this->get_full_name());
1715 * Is setting related to query text - used when searching
1716 * @param string $query
1719 public function is_related($query) {
1720 if (strpos(strtolower($this->name
), $query) !== false) {
1723 if (strpos(textlib
::strtolower($this->visiblename
), $query) !== false) {
1726 if (strpos(textlib
::strtolower($this->description
), $query) !== false) {
1729 $current = $this->get_setting();
1730 if (!is_null($current)) {
1731 if (is_string($current)) {
1732 if (strpos(textlib
::strtolower($current), $query) !== false) {
1737 $default = $this->get_defaultsetting();
1738 if (!is_null($default)) {
1739 if (is_string($default)) {
1740 if (strpos(textlib
::strtolower($default), $query) !== false) {
1751 * No setting - just heading and text.
1753 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1755 class admin_setting_heading
extends admin_setting
{
1758 * not a setting, just text
1759 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
1760 * @param string $heading heading
1761 * @param string $information text in box
1763 public function __construct($name, $heading, $information) {
1764 $this->nosave
= true;
1765 parent
::__construct($name, $heading, $information, '');
1769 * Always returns true
1770 * @return bool Always returns true
1772 public function get_setting() {
1777 * Always returns true
1778 * @return bool Always returns true
1780 public function get_defaultsetting() {
1785 * Never write settings
1786 * @return string Always returns an empty string
1788 public function write_setting($data) {
1789 // do not write any setting
1794 * Returns an HTML string
1795 * @return string Returns an HTML string
1797 public function output_html($data, $query='') {
1800 if ($this->visiblename
!= '') {
1801 $return .= $OUTPUT->heading($this->visiblename
, 3, 'main');
1803 if ($this->description
!= '') {
1804 $return .= $OUTPUT->box(highlight($query, markdown_to_html($this->description
)), 'generalbox formsettingheading');
1812 * The most flexibly setting, user is typing text
1814 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1816 class admin_setting_configtext
extends admin_setting
{
1818 /** @var mixed int means PARAM_XXX type, string is a allowed format in regex */
1820 /** @var int default field size */
1824 * Config text constructor
1826 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
1827 * @param string $visiblename localised
1828 * @param string $description long localised info
1829 * @param string $defaultsetting
1830 * @param mixed $paramtype int means PARAM_XXX type, string is a allowed format in regex
1831 * @param int $size default field size
1833 public function __construct($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW
, $size=null) {
1834 $this->paramtype
= $paramtype;
1835 if (!is_null($size)) {
1836 $this->size
= $size;
1838 $this->size
= ($paramtype === PARAM_INT
) ?
5 : 30;
1840 parent
::__construct($name, $visiblename, $description, $defaultsetting);
1844 * Return the setting
1846 * @return mixed returns config if successful else null
1848 public function get_setting() {
1849 return $this->config_read($this->name
);
1852 public function write_setting($data) {
1853 if ($this->paramtype
=== PARAM_INT
and $data === '') {
1854 // do not complain if '' used instead of 0
1857 // $data is a string
1858 $validated = $this->validate($data);
1859 if ($validated !== true) {
1862 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
1866 * Validate data before storage
1867 * @param string data
1868 * @return mixed true if ok string if error found
1870 public function validate($data) {
1871 // allow paramtype to be a custom regex if it is the form of /pattern/
1872 if (preg_match('#^/.*/$#', $this->paramtype
)) {
1873 if (preg_match($this->paramtype
, $data)) {
1876 return get_string('validateerror', 'admin');
1879 } else if ($this->paramtype
=== PARAM_RAW
) {
1883 $cleaned = clean_param($data, $this->paramtype
);
1884 if ("$data" === "$cleaned") { // implicit conversion to string is needed to do exact comparison
1887 return get_string('validateerror', 'admin');
1893 * Return an XHTML string for the setting
1894 * @return string Returns an XHTML string
1896 public function output_html($data, $query='') {
1897 $default = $this->get_defaultsetting();
1899 return format_admin_setting($this, $this->visiblename
,
1900 '<div class="form-text defaultsnext"><input type="text" size="'.$this->size
.'" id="'.$this->get_id().'" name="'.$this->get_full_name().'" value="'.s($data).'" /></div>',
1901 $this->description
, true, '', $default, $query);
1907 * General text area without html editor.
1909 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1911 class admin_setting_configtextarea
extends admin_setting_configtext
{
1916 * @param string $name
1917 * @param string $visiblename
1918 * @param string $description
1919 * @param mixed $defaultsetting string or array
1920 * @param mixed $paramtype
1921 * @param string $cols The number of columns to make the editor
1922 * @param string $rows The number of rows to make the editor
1924 public function __construct($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW
, $cols='60', $rows='8') {
1925 $this->rows
= $rows;
1926 $this->cols
= $cols;
1927 parent
::__construct($name, $visiblename, $description, $defaultsetting, $paramtype);
1931 * Returns an XHTML string for the editor
1933 * @param string $data
1934 * @param string $query
1935 * @return string XHTML string for the editor
1937 public function output_html($data, $query='') {
1938 $default = $this->get_defaultsetting();
1940 $defaultinfo = $default;
1941 if (!is_null($default) and $default !== '') {
1942 $defaultinfo = "\n".$default;
1945 return format_admin_setting($this, $this->visiblename
,
1946 '<div class="form-textarea" ><textarea rows="'. $this->rows
.'" cols="'. $this->cols
.'" id="'. $this->get_id() .'" name="'. $this->get_full_name() .'" spellcheck="true">'. s($data) .'</textarea></div>',
1947 $this->description
, true, '', $defaultinfo, $query);
1953 * General text area with html editor.
1955 class admin_setting_confightmleditor
extends admin_setting_configtext
{
1960 * @param string $name
1961 * @param string $visiblename
1962 * @param string $description
1963 * @param mixed $defaultsetting string or array
1964 * @param mixed $paramtype
1966 public function __construct($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW
, $cols='60', $rows='8') {
1967 $this->rows
= $rows;
1968 $this->cols
= $cols;
1969 parent
::__construct($name, $visiblename, $description, $defaultsetting, $paramtype);
1970 editors_head_setup();
1974 * Returns an XHTML string for the editor
1976 * @param string $data
1977 * @param string $query
1978 * @return string XHTML string for the editor
1980 public function output_html($data, $query='') {
1981 $default = $this->get_defaultsetting();
1983 $defaultinfo = $default;
1984 if (!is_null($default) and $default !== '') {
1985 $defaultinfo = "\n".$default;
1988 $editor = editors_get_preferred_editor(FORMAT_HTML
);
1989 $editor->use_editor($this->get_id(), array('noclean'=>true));
1991 return format_admin_setting($this, $this->visiblename
,
1992 '<div class="form-textarea"><textarea rows="'. $this->rows
.'" cols="'. $this->cols
.'" id="'. $this->get_id() .'" name="'. $this->get_full_name() .'" spellcheck="true">'. s($data) .'</textarea></div>',
1993 $this->description
, true, '', $defaultinfo, $query);
1999 * Password field, allows unmasking of password
2001 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2003 class admin_setting_configpasswordunmask
extends admin_setting_configtext
{
2006 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2007 * @param string $visiblename localised
2008 * @param string $description long localised info
2009 * @param string $defaultsetting default password
2011 public function __construct($name, $visiblename, $description, $defaultsetting) {
2012 parent
::__construct($name, $visiblename, $description, $defaultsetting, PARAM_RAW
, 30);
2016 * Returns XHTML for the field
2017 * Writes Javascript into the HTML below right before the last div
2019 * @todo Make javascript available through newer methods if possible
2020 * @param string $data Value for the field
2021 * @param string $query Passed as final argument for format_admin_setting
2022 * @return string XHTML field
2024 public function output_html($data, $query='') {
2025 $id = $this->get_id();
2026 $unmask = get_string('unmaskpassword', 'form');
2027 $unmaskjs = '<script type="text/javascript">
2029 var is_ie = (navigator.userAgent.toLowerCase().indexOf("msie") != -1);
2031 document.getElementById("'.$id.'").setAttribute("autocomplete", "off");
2033 var unmaskdiv = document.getElementById("'.$id.'unmaskdiv");
2035 var unmaskchb = document.createElement("input");
2036 unmaskchb.setAttribute("type", "checkbox");
2037 unmaskchb.setAttribute("id", "'.$id.'unmask");
2038 unmaskchb.onchange = function() {unmaskPassword("'.$id.'");};
2039 unmaskdiv.appendChild(unmaskchb);
2041 var unmasklbl = document.createElement("label");
2042 unmasklbl.innerHTML = "'.addslashes_js($unmask).'";
2044 unmasklbl.setAttribute("htmlFor", "'.$id.'unmask");
2046 unmasklbl.setAttribute("for", "'.$id.'unmask");
2048 unmaskdiv.appendChild(unmasklbl);
2051 // ugly hack to work around the famous onchange IE bug
2052 unmaskchb.onclick = function() {this.blur();};
2053 unmaskdiv.onclick = function() {this.blur();};
2057 return format_admin_setting($this, $this->visiblename
,
2058 '<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>',
2059 $this->description
, true, '', NULL, $query);
2067 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2069 class admin_setting_configfile
extends admin_setting_configtext
{
2072 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2073 * @param string $visiblename localised
2074 * @param string $description long localised info
2075 * @param string $defaultdirectory default directory location
2077 public function __construct($name, $visiblename, $description, $defaultdirectory) {
2078 parent
::__construct($name, $visiblename, $description, $defaultdirectory, PARAM_RAW
, 50);
2082 * Returns XHTML for the field
2084 * Returns XHTML for the field and also checks whether the file
2085 * specified in $data exists using file_exists()
2087 * @param string $data File name and path to use in value attr
2088 * @param string $query
2089 * @return string XHTML field
2091 public function output_html($data, $query='') {
2092 $default = $this->get_defaultsetting();
2095 if (file_exists($data)) {
2096 $executable = '<span class="pathok">✔</span>';
2098 $executable = '<span class="patherror">✘</span>';
2104 return format_admin_setting($this, $this->visiblename
,
2105 '<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>',
2106 $this->description
, true, '', $default, $query);
2109 * checks if execpatch has been disabled in config.php
2111 public function write_setting($data) {
2113 if (!empty($CFG->preventexecpath
)) {
2116 return parent
::write_setting($data);
2122 * Path to executable file
2124 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2126 class admin_setting_configexecutable
extends admin_setting_configfile
{
2129 * Returns an XHTML field
2131 * @param string $data This is the value for the field
2132 * @param string $query
2133 * @return string XHTML field
2135 public function output_html($data, $query='') {
2137 $default = $this->get_defaultsetting();
2140 if (file_exists($data) and is_executable($data)) {
2141 $executable = '<span class="pathok">✔</span>';
2143 $executable = '<span class="patherror">✘</span>';
2148 if (!empty($CFG->preventexecpath
)) {
2149 $this->visiblename
.= '<div class="form-overridden">'.get_string('execpathnotallowed', 'admin').'</div>';
2152 return format_admin_setting($this, $this->visiblename
,
2153 '<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>',
2154 $this->description
, true, '', $default, $query);
2162 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2164 class admin_setting_configdirectory
extends admin_setting_configfile
{
2167 * Returns an XHTML field
2169 * @param string $data This is the value for the field
2170 * @param string $query
2171 * @return string XHTML
2173 public function output_html($data, $query='') {
2174 $default = $this->get_defaultsetting();
2177 if (file_exists($data) and is_dir($data)) {
2178 $executable = '<span class="pathok">✔</span>';
2180 $executable = '<span class="patherror">✘</span>';
2186 return format_admin_setting($this, $this->visiblename
,
2187 '<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>',
2188 $this->description
, true, '', $default, $query);
2196 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2198 class admin_setting_configcheckbox
extends admin_setting
{
2199 /** @var string Value used when checked */
2201 /** @var string Value used when not checked */
2206 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2207 * @param string $visiblename localised
2208 * @param string $description long localised info
2209 * @param string $defaultsetting
2210 * @param string $yes value used when checked
2211 * @param string $no value used when not checked
2213 public function __construct($name, $visiblename, $description, $defaultsetting, $yes='1', $no='0') {
2214 parent
::__construct($name, $visiblename, $description, $defaultsetting);
2215 $this->yes
= (string)$yes;
2216 $this->no
= (string)$no;
2220 * Retrieves the current setting using the objects name
2224 public function get_setting() {
2225 return $this->config_read($this->name
);
2229 * Sets the value for the setting
2231 * Sets the value for the setting to either the yes or no values
2232 * of the object by comparing $data to yes
2234 * @param mixed $data Gets converted to str for comparison against yes value
2235 * @return string empty string or error
2237 public function write_setting($data) {
2238 if ((string)$data === $this->yes
) { // convert to strings before comparison
2243 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
2247 * Returns an XHTML checkbox field
2249 * @param string $data If $data matches yes then checkbox is checked
2250 * @param string $query
2251 * @return string XHTML field
2253 public function output_html($data, $query='') {
2254 $default = $this->get_defaultsetting();
2256 if (!is_null($default)) {
2257 if ((string)$default === $this->yes
) {
2258 $defaultinfo = get_string('checkboxyes', 'admin');
2260 $defaultinfo = get_string('checkboxno', 'admin');
2263 $defaultinfo = NULL;
2266 if ((string)$data === $this->yes
) { // convert to strings before comparison
2267 $checked = 'checked="checked"';
2272 return format_admin_setting($this, $this->visiblename
,
2273 '<div class="form-checkbox defaultsnext" ><input type="hidden" name="'.$this->get_full_name().'" value="'.s($this->no
).'" /> '
2274 .'<input type="checkbox" id="'.$this->get_id().'" name="'.$this->get_full_name().'" value="'.s($this->yes
).'" '.$checked.' /></div>',
2275 $this->description
, true, '', $defaultinfo, $query);
2281 * Multiple checkboxes, each represents different value, stored in csv format
2283 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2285 class admin_setting_configmulticheckbox
extends admin_setting
{
2286 /** @var array Array of choices value=>label */
2290 * Constructor: uses parent::__construct
2292 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2293 * @param string $visiblename localised
2294 * @param string $description long localised info
2295 * @param array $defaultsetting array of selected
2296 * @param array $choices array of $value=>$label for each checkbox
2298 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
2299 $this->choices
= $choices;
2300 parent
::__construct($name, $visiblename, $description, $defaultsetting);
2304 * This public function may be used in ancestors for lazy loading of choices
2306 * @todo Check if this function is still required content commented out only returns true
2307 * @return bool true if loaded, false if error
2309 public function load_choices() {
2311 if (is_array($this->choices)) {
2314 .... load choices here
2320 * Is setting related to query text - used when searching
2322 * @param string $query
2323 * @return bool true on related, false on not or failure
2325 public function is_related($query) {
2326 if (!$this->load_choices() or empty($this->choices
)) {
2329 if (parent
::is_related($query)) {
2333 foreach ($this->choices
as $desc) {
2334 if (strpos(textlib
::strtolower($desc), $query) !== false) {
2342 * Returns the current setting if it is set
2344 * @return mixed null if null, else an array
2346 public function get_setting() {
2347 $result = $this->config_read($this->name
);
2349 if (is_null($result)) {
2352 if ($result === '') {
2355 $enabled = explode(',', $result);
2357 foreach ($enabled as $option) {
2358 $setting[$option] = 1;
2364 * Saves the setting(s) provided in $data
2366 * @param array $data An array of data, if not array returns empty str
2367 * @return mixed empty string on useless data or bool true=success, false=failed
2369 public function write_setting($data) {
2370 if (!is_array($data)) {
2371 return ''; // ignore it
2373 if (!$this->load_choices() or empty($this->choices
)) {
2376 unset($data['xxxxx']);
2378 foreach ($data as $key => $value) {
2379 if ($value and array_key_exists($key, $this->choices
)) {
2383 return $this->config_write($this->name
, implode(',', $result)) ?
'' : get_string('errorsetting', 'admin');
2387 * Returns XHTML field(s) as required by choices
2389 * Relies on data being an array should data ever be another valid vartype with
2390 * acceptable value this may cause a warning/error
2391 * if (!is_array($data)) would fix the problem
2393 * @todo Add vartype handling to ensure $data is an array
2395 * @param array $data An array of checked values
2396 * @param string $query
2397 * @return string XHTML field
2399 public function output_html($data, $query='') {
2400 if (!$this->load_choices() or empty($this->choices
)) {
2403 $default = $this->get_defaultsetting();
2404 if (is_null($default)) {
2407 if (is_null($data)) {
2411 $defaults = array();
2412 foreach ($this->choices
as $key=>$description) {
2413 if (!empty($data[$key])) {
2414 $checked = 'checked="checked"';
2418 if (!empty($default[$key])) {
2419 $defaults[] = $description;
2422 $options[] = '<input type="checkbox" id="'.$this->get_id().'_'.$key.'" name="'.$this->get_full_name().'['.$key.']" value="1" '.$checked.' />'
2423 .'<label for="'.$this->get_id().'_'.$key.'">'.highlightfast($query, $description).'</label>';
2426 if (is_null($default)) {
2427 $defaultinfo = NULL;
2428 } else if (!empty($defaults)) {
2429 $defaultinfo = implode(', ', $defaults);
2431 $defaultinfo = get_string('none');
2434 $return = '<div class="form-multicheckbox">';
2435 $return .= '<input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
2438 foreach ($options as $option) {
2439 $return .= '<li>'.$option.'</li>';
2443 $return .= '</div>';
2445 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', $defaultinfo, $query);
2452 * Multiple checkboxes 2, value stored as string 00101011
2454 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2456 class admin_setting_configmulticheckbox2
extends admin_setting_configmulticheckbox
{
2459 * Returns the setting if set
2461 * @return mixed null if not set, else an array of set settings
2463 public function get_setting() {
2464 $result = $this->config_read($this->name
);
2465 if (is_null($result)) {
2468 if (!$this->load_choices()) {
2471 $result = str_pad($result, count($this->choices
), '0');
2472 $result = preg_split('//', $result, -1, PREG_SPLIT_NO_EMPTY
);
2474 foreach ($this->choices
as $key=>$unused) {
2475 $value = array_shift($result);
2484 * Save setting(s) provided in $data param
2486 * @param array $data An array of settings to save
2487 * @return mixed empty string for bad data or bool true=>success, false=>error
2489 public function write_setting($data) {
2490 if (!is_array($data)) {
2491 return ''; // ignore it
2493 if (!$this->load_choices() or empty($this->choices
)) {
2497 foreach ($this->choices
as $key=>$unused) {
2498 if (!empty($data[$key])) {
2504 return $this->config_write($this->name
, $result) ?
'' : get_string('errorsetting', 'admin');
2510 * Select one value from list
2512 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2514 class admin_setting_configselect
extends admin_setting
{
2515 /** @var array Array of choices value=>label */
2520 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2521 * @param string $visiblename localised
2522 * @param string $description long localised info
2523 * @param string|int $defaultsetting
2524 * @param array $choices array of $value=>$label for each selection
2526 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
2527 $this->choices
= $choices;
2528 parent
::__construct($name, $visiblename, $description, $defaultsetting);
2532 * This function may be used in ancestors for lazy loading of choices
2534 * Override this method if loading of choices is expensive, such
2535 * as when it requires multiple db requests.
2537 * @return bool true if loaded, false if error
2539 public function load_choices() {
2541 if (is_array($this->choices)) {
2544 .... load choices here
2550 * Check if this is $query is related to a choice
2552 * @param string $query
2553 * @return bool true if related, false if not
2555 public function is_related($query) {
2556 if (parent
::is_related($query)) {
2559 if (!$this->load_choices()) {
2562 foreach ($this->choices
as $key=>$value) {
2563 if (strpos(textlib
::strtolower($key), $query) !== false) {
2566 if (strpos(textlib
::strtolower($value), $query) !== false) {
2574 * Return the setting
2576 * @return mixed returns config if successful else null
2578 public function get_setting() {
2579 return $this->config_read($this->name
);
2585 * @param string $data
2586 * @return string empty of error string
2588 public function write_setting($data) {
2589 if (!$this->load_choices() or empty($this->choices
)) {
2592 if (!array_key_exists($data, $this->choices
)) {
2593 return ''; // ignore it
2596 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
2600 * Returns XHTML select field
2602 * Ensure the options are loaded, and generate the XHTML for the select
2603 * element and any warning message. Separating this out from output_html
2604 * makes it easier to subclass this class.
2606 * @param string $data the option to show as selected.
2607 * @param string $current the currently selected option in the database, null if none.
2608 * @param string $default the default selected option.
2609 * @return array the HTML for the select element, and a warning message.
2611 public function output_select_html($data, $current, $default, $extraname = '') {
2612 if (!$this->load_choices() or empty($this->choices
)) {
2613 return array('', '');
2617 if (is_null($current)) {
2619 } else if (empty($current) and (array_key_exists('', $this->choices
) or array_key_exists(0, $this->choices
))) {
2621 } else if (!array_key_exists($current, $this->choices
)) {
2622 $warning = get_string('warningcurrentsetting', 'admin', s($current));
2623 if (!is_null($default) and $data == $current) {
2624 $data = $default; // use default instead of first value when showing the form
2628 $selecthtml = '<select id="'.$this->get_id().'" name="'.$this->get_full_name().$extraname.'">';
2629 foreach ($this->choices
as $key => $value) {
2630 // the string cast is needed because key may be integer - 0 is equal to most strings!
2631 $selecthtml .= '<option value="'.$key.'"'.((string)$key==$data ?
' selected="selected"' : '').'>'.$value.'</option>';
2633 $selecthtml .= '</select>';
2634 return array($selecthtml, $warning);
2638 * Returns XHTML select field and wrapping div(s)
2640 * @see output_select_html()
2642 * @param string $data the option to show as selected
2643 * @param string $query
2644 * @return string XHTML field and wrapping div
2646 public function output_html($data, $query='') {
2647 $default = $this->get_defaultsetting();
2648 $current = $this->get_setting();
2650 list($selecthtml, $warning) = $this->output_select_html($data, $current, $default);
2655 if (!is_null($default) and array_key_exists($default, $this->choices
)) {
2656 $defaultinfo = $this->choices
[$default];
2658 $defaultinfo = NULL;
2661 $return = '<div class="form-select defaultsnext">' . $selecthtml . '</div>';
2663 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, true, $warning, $defaultinfo, $query);
2669 * Select multiple items from list
2671 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2673 class admin_setting_configmultiselect
extends admin_setting_configselect
{
2676 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2677 * @param string $visiblename localised
2678 * @param string $description long localised info
2679 * @param array $defaultsetting array of selected items
2680 * @param array $choices array of $value=>$label for each list item
2682 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
2683 parent
::__construct($name, $visiblename, $description, $defaultsetting, $choices);
2687 * Returns the select setting(s)
2689 * @return mixed null or array. Null if no settings else array of setting(s)
2691 public function get_setting() {
2692 $result = $this->config_read($this->name
);
2693 if (is_null($result)) {
2696 if ($result === '') {
2699 return explode(',', $result);
2703 * Saves setting(s) provided through $data
2705 * Potential bug in the works should anyone call with this function
2706 * using a vartype that is not an array
2708 * @param array $data
2710 public function write_setting($data) {
2711 if (!is_array($data)) {
2712 return ''; //ignore it
2714 if (!$this->load_choices() or empty($this->choices
)) {
2718 unset($data['xxxxx']);
2721 foreach ($data as $value) {
2722 if (!array_key_exists($value, $this->choices
)) {
2723 continue; // ignore it
2728 return ($this->config_write($this->name
, implode(',', $save)) ?
'' : get_string('errorsetting', 'admin'));
2732 * Is setting related to query text - used when searching
2734 * @param string $query
2735 * @return bool true if related, false if not
2737 public function is_related($query) {
2738 if (!$this->load_choices() or empty($this->choices
)) {
2741 if (parent
::is_related($query)) {
2745 foreach ($this->choices
as $desc) {
2746 if (strpos(textlib
::strtolower($desc), $query) !== false) {
2754 * Returns XHTML multi-select field
2756 * @todo Add vartype handling to ensure $data is an array
2757 * @param array $data Array of values to select by default
2758 * @param string $query
2759 * @return string XHTML multi-select field
2761 public function output_html($data, $query='') {
2762 if (!$this->load_choices() or empty($this->choices
)) {
2765 $choices = $this->choices
;
2766 $default = $this->get_defaultsetting();
2767 if (is_null($default)) {
2770 if (is_null($data)) {
2774 $defaults = array();
2775 $size = min(10, count($this->choices
));
2776 $return = '<div class="form-select"><input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
2777 $return .= '<select id="'.$this->get_id().'" name="'.$this->get_full_name().'[]" size="'.$size.'" multiple="multiple">';
2778 foreach ($this->choices
as $key => $description) {
2779 if (in_array($key, $data)) {
2780 $selected = 'selected="selected"';
2784 if (in_array($key, $default)) {
2785 $defaults[] = $description;
2788 $return .= '<option value="'.s($key).'" '.$selected.'>'.$description.'</option>';
2791 if (is_null($default)) {
2792 $defaultinfo = NULL;
2793 } if (!empty($defaults)) {
2794 $defaultinfo = implode(', ', $defaults);
2796 $defaultinfo = get_string('none');
2799 $return .= '</select></div>';
2800 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, true, '', $defaultinfo, $query);
2807 * This is a liiitle bit messy. we're using two selects, but we're returning
2808 * them as an array named after $name (so we only use $name2 internally for the setting)
2810 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2812 class admin_setting_configtime
extends admin_setting
{
2813 /** @var string Used for setting second select (minutes) */
2818 * @param string $hoursname setting for hours
2819 * @param string $minutesname setting for hours
2820 * @param string $visiblename localised
2821 * @param string $description long localised info
2822 * @param array $defaultsetting array representing default time 'h'=>hours, 'm'=>minutes
2824 public function __construct($hoursname, $minutesname, $visiblename, $description, $defaultsetting) {
2825 $this->name2
= $minutesname;
2826 parent
::__construct($hoursname, $visiblename, $description, $defaultsetting);
2830 * Get the selected time
2832 * @return mixed An array containing 'h'=>xx, 'm'=>xx, or null if not set
2834 public function get_setting() {
2835 $result1 = $this->config_read($this->name
);
2836 $result2 = $this->config_read($this->name2
);
2837 if (is_null($result1) or is_null($result2)) {
2841 return array('h' => $result1, 'm' => $result2);
2845 * Store the time (hours and minutes)
2847 * @param array $data Must be form 'h'=>xx, 'm'=>xx
2848 * @return bool true if success, false if not
2850 public function write_setting($data) {
2851 if (!is_array($data)) {
2855 $result = $this->config_write($this->name
, (int)$data['h']) && $this->config_write($this->name2
, (int)$data['m']);
2856 return ($result ?
'' : get_string('errorsetting', 'admin'));
2860 * Returns XHTML time select fields
2862 * @param array $data Must be form 'h'=>xx, 'm'=>xx
2863 * @param string $query
2864 * @return string XHTML time select fields and wrapping div(s)
2866 public function output_html($data, $query='') {
2867 $default = $this->get_defaultsetting();
2869 if (is_array($default)) {
2870 $defaultinfo = $default['h'].':'.$default['m'];
2872 $defaultinfo = NULL;
2875 $return = '<div class="form-time defaultsnext">'.
2876 '<select id="'.$this->get_id().'h" name="'.$this->get_full_name().'[h]">';
2877 for ($i = 0; $i < 24; $i++
) {
2878 $return .= '<option value="'.$i.'"'.($i == $data['h'] ?
' selected="selected"' : '').'>'.$i.'</option>';
2880 $return .= '</select>:<select id="'.$this->get_id().'m" name="'.$this->get_full_name().'[m]">';
2881 for ($i = 0; $i < 60; $i +
= 5) {
2882 $return .= '<option value="'.$i.'"'.($i == $data['m'] ?
' selected="selected"' : '').'>'.$i.'</option>';
2884 $return .= '</select></div>';
2885 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', $defaultinfo, $query);
2892 * Seconds duration setting.
2894 * @copyright 2012 Petr Skoda (http://skodak.org)
2895 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2897 class admin_setting_configduration
extends admin_setting
{
2899 /** @var int default duration unit */
2900 protected $defaultunit;
2904 * @param string $name unique ascii name, either 'mysetting' for settings that in config,
2905 * or 'myplugin/mysetting' for ones in config_plugins.
2906 * @param string $visiblename localised name
2907 * @param string $description localised long description
2908 * @param mixed $defaultsetting string or array depending on implementation
2909 * @param int $defaultunit - day, week, etc. (in seconds)
2911 public function __construct($name, $visiblename, $description, $defaultsetting, $defaultunit = 86400) {
2912 if (is_number($defaultsetting)) {
2913 $defaultsetting = self
::parse_seconds($defaultsetting);
2915 $units = self
::get_units();
2916 if (isset($units[$defaultunit])) {
2917 $this->defaultunit
= $defaultunit;
2919 $this->defaultunit
= 86400;
2921 parent
::__construct($name, $visiblename, $description, $defaultsetting);
2925 * Returns selectable units.
2929 protected static function get_units() {
2931 604800 => get_string('weeks'),
2932 86400 => get_string('days'),
2933 3600 => get_string('hours'),
2934 60 => get_string('minutes'),
2935 1 => get_string('seconds'),
2940 * Converts seconds to some more user friendly string.
2942 * @param int $seconds
2945 protected static function get_duration_text($seconds) {
2946 if (empty($seconds)) {
2947 return get_string('none');
2949 $data = self
::parse_seconds($seconds);
2950 switch ($data['u']) {
2952 return get_string('numweeks', '', $data['v']);
2954 return get_string('numdays', '', $data['v']);
2956 return get_string('numhours', '', $data['v']);
2958 return get_string('numminutes', '', $data['v']);
2960 return get_string('numseconds', '', $data['v']*$data['u']);
2965 * Finds suitable units for given duration.
2967 * @param int $seconds
2970 protected static function parse_seconds($seconds) {
2971 foreach (self
::get_units() as $unit => $unused) {
2972 if ($seconds %
$unit === 0) {
2973 return array('v'=>(int)($seconds/$unit), 'u'=>$unit);
2976 return array('v'=>(int)$seconds, 'u'=>1);
2980 * Get the selected duration as array.
2982 * @return mixed An array containing 'v'=>xx, 'u'=>xx, or null if not set
2984 public function get_setting() {
2985 $seconds = $this->config_read($this->name
);
2986 if (is_null($seconds)) {
2990 return self
::parse_seconds($seconds);
2994 * Store the duration as seconds.
2996 * @param array $data Must be form 'h'=>xx, 'm'=>xx
2997 * @return bool true if success, false if not
2999 public function write_setting($data) {
3000 if (!is_array($data)) {
3004 $seconds = (int)($data['v']*$data['u']);
3006 return get_string('errorsetting', 'admin');
3009 $result = $this->config_write($this->name
, $seconds);
3010 return ($result ?
'' : get_string('errorsetting', 'admin'));
3014 * Returns duration text+select fields.
3016 * @param array $data Must be form 'v'=>xx, 'u'=>xx
3017 * @param string $query
3018 * @return string duration text+select fields and wrapping div(s)
3020 public function output_html($data, $query='') {
3021 $default = $this->get_defaultsetting();
3023 if (is_number($default)) {
3024 $defaultinfo = self
::get_duration_text($default);
3025 } else if (is_array($default)) {
3026 $defaultinfo = self
::get_duration_text($default['v']*$default['u']);
3028 $defaultinfo = null;
3031 $units = self
::get_units();
3033 $return = '<div class="form-duration defaultsnext">';
3034 $return .= '<input type="text" size="5" id="'.$this->get_id().'v" name="'.$this->get_full_name().'[v]" value="'.s($data['v']).'" />';
3035 $return .= '<select id="'.$this->get_id().'u" name="'.$this->get_full_name().'[u]">';
3036 foreach ($units as $val => $text) {
3038 if ($data['v'] == 0) {
3039 if ($val == $this->defaultunit
) {
3040 $selected = ' selected="selected"';
3042 } else if ($val == $data['u']) {
3043 $selected = ' selected="selected"';
3045 $return .= '<option value="'.$val.'"'.$selected.'>'.$text.'</option>';
3047 $return .= '</select></div>';
3048 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', $defaultinfo, $query);
3054 * Used to validate a textarea used for ip addresses
3056 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3058 class admin_setting_configiplist
extends admin_setting_configtextarea
{
3061 * Validate the contents of the textarea as IP addresses
3063 * Used to validate a new line separated list of IP addresses collected from
3064 * a textarea control
3066 * @param string $data A list of IP Addresses separated by new lines
3067 * @return mixed bool true for success or string:error on failure
3069 public function validate($data) {
3071 $ips = explode("\n", $data);
3076 foreach($ips as $ip) {
3078 if (preg_match('#^(\d{1,3})(\.\d{1,3}){0,3}$#', $ip, $match) ||
3079 preg_match('#^(\d{1,3})(\.\d{1,3}){0,3}(\/\d{1,2})$#', $ip, $match) ||
3080 preg_match('#^(\d{1,3})(\.\d{1,3}){3}(-\d{1,3})$#', $ip, $match)) {
3090 return get_string('validateerror', 'admin');
3097 * An admin setting for selecting one or more users who have a capability
3098 * in the system context
3100 * An admin setting for selecting one or more users, who have a particular capability
3101 * in the system context. Warning, make sure the list will never be too long. There is
3102 * no paging or searching of this list.
3104 * To correctly get a list of users from this config setting, you need to call the
3105 * get_users_from_config($CFG->mysetting, $capability); function in moodlelib.php.
3107 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3109 class admin_setting_users_with_capability
extends admin_setting_configmultiselect
{
3110 /** @var string The capabilities name */
3111 protected $capability;
3112 /** @var int include admin users too */
3113 protected $includeadmins;
3118 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
3119 * @param string $visiblename localised name
3120 * @param string $description localised long description
3121 * @param array $defaultsetting array of usernames
3122 * @param string $capability string capability name.
3123 * @param bool $includeadmins include administrators
3125 function __construct($name, $visiblename, $description, $defaultsetting, $capability, $includeadmins = true) {
3126 $this->capability
= $capability;
3127 $this->includeadmins
= $includeadmins;
3128 parent
::__construct($name, $visiblename, $description, $defaultsetting, NULL);
3132 * Load all of the uses who have the capability into choice array
3134 * @return bool Always returns true
3136 function load_choices() {
3137 if (is_array($this->choices
)) {
3140 list($sort, $sortparams) = users_order_by_sql('u');
3141 if (!empty($sortparams)) {
3142 throw new coding_exception('users_order_by_sql returned some query parameters. ' .
3143 'This is unexpected, and a problem because there is no way to pass these ' .
3144 'parameters to get_users_by_capability. See MDL-34657.');
3146 $users = get_users_by_capability(context_system
::instance(),
3147 $this->capability
, 'u.id,u.username,u.firstname,u.lastname', $sort);
3148 $this->choices
= array(
3149 '$@NONE@$' => get_string('nobody'),
3150 '$@ALL@$' => get_string('everyonewhocan', 'admin', get_capability_string($this->capability
)),
3152 if ($this->includeadmins
) {
3153 $admins = get_admins();
3154 foreach ($admins as $user) {
3155 $this->choices
[$user->id
] = fullname($user);
3158 if (is_array($users)) {
3159 foreach ($users as $user) {
3160 $this->choices
[$user->id
] = fullname($user);
3167 * Returns the default setting for class
3169 * @return mixed Array, or string. Empty string if no default
3171 public function get_defaultsetting() {
3172 $this->load_choices();
3173 $defaultsetting = parent
::get_defaultsetting();
3174 if (empty($defaultsetting)) {
3175 return array('$@NONE@$');
3176 } else if (array_key_exists($defaultsetting, $this->choices
)) {
3177 return $defaultsetting;
3184 * Returns the current setting
3186 * @return mixed array or string
3188 public function get_setting() {
3189 $result = parent
::get_setting();
3190 if ($result === null) {
3191 // this is necessary for settings upgrade
3194 if (empty($result)) {
3195 $result = array('$@NONE@$');
3201 * Save the chosen setting provided as $data
3203 * @param array $data
3204 * @return mixed string or array
3206 public function write_setting($data) {
3207 // If all is selected, remove any explicit options.
3208 if (in_array('$@ALL@$', $data)) {
3209 $data = array('$@ALL@$');
3211 // None never needs to be written to the DB.
3212 if (in_array('$@NONE@$', $data)) {
3213 unset($data[array_search('$@NONE@$', $data)]);
3215 return parent
::write_setting($data);
3221 * Special checkbox for calendar - resets SESSION vars.
3223 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3225 class admin_setting_special_adminseesall
extends admin_setting_configcheckbox
{
3227 * Calls the parent::__construct with default values
3229 * name => calendar_adminseesall
3230 * visiblename => get_string('adminseesall', 'admin')
3231 * description => get_string('helpadminseesall', 'admin')
3232 * defaultsetting => 0
3234 public function __construct() {
3235 parent
::__construct('calendar_adminseesall', get_string('adminseesall', 'admin'),
3236 get_string('helpadminseesall', 'admin'), '0');
3240 * Stores the setting passed in $data
3242 * @param mixed gets converted to string for comparison
3243 * @return string empty string or error message
3245 public function write_setting($data) {
3247 return parent
::write_setting($data);
3252 * Special select for settings that are altered in setup.php and can not be altered on the fly
3254 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3256 class admin_setting_special_selectsetup
extends admin_setting_configselect
{
3258 * Reads the setting directly from the database
3262 public function get_setting() {
3263 // read directly from db!
3264 return get_config(NULL, $this->name
);
3268 * Save the setting passed in $data
3270 * @param string $data The setting to save
3271 * @return string empty or error message
3273 public function write_setting($data) {
3275 // do not change active CFG setting!
3276 $current = $CFG->{$this->name
};
3277 $result = parent
::write_setting($data);
3278 $CFG->{$this->name
} = $current;
3285 * Special select for frontpage - stores data in course table
3287 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3289 class admin_setting_sitesetselect
extends admin_setting_configselect
{
3291 * Returns the site name for the selected site
3294 * @return string The site name of the selected site
3296 public function get_setting() {
3297 $site = course_get_format(get_site())->get_course();
3298 return $site->{$this->name
};
3302 * Updates the database and save the setting
3304 * @param string data
3305 * @return string empty or error message
3307 public function write_setting($data) {
3308 global $DB, $SITE, $COURSE;
3309 if (!in_array($data, array_keys($this->choices
))) {
3310 return get_string('errorsetting', 'admin');
3312 $record = new stdClass();
3313 $record->id
= SITEID
;
3314 $temp = $this->name
;
3315 $record->$temp = $data;
3316 $record->timemodified
= time();
3318 course_get_format($SITE)->update_course_format_options($record);
3319 $DB->update_record('course', $record);
3322 $SITE = $DB->get_record('course', array('id'=>$SITE->id
), '*', MUST_EXIST
);
3323 if ($SITE->id
== $COURSE->id
) {
3326 format_base
::reset_course_cache($SITE->id
);
3335 * Select for blog's bloglevel setting: if set to 0, will set blog_menu
3338 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3340 class admin_setting_bloglevel
extends admin_setting_configselect
{
3342 * Updates the database and save the setting
3344 * @param string data
3345 * @return string empty or error message
3347 public function write_setting($data) {
3350 $blogblocks = $DB->get_records_select('block', "name LIKE 'blog_%' AND visible = 1");
3351 foreach ($blogblocks as $block) {
3352 $DB->set_field('block', 'visible', 0, array('id' => $block->id
));
3355 // reenable all blocks only when switching from disabled blogs
3356 if (isset($CFG->bloglevel
) and $CFG->bloglevel
== 0) {
3357 $blogblocks = $DB->get_records_select('block', "name LIKE 'blog_%' AND visible = 0");
3358 foreach ($blogblocks as $block) {
3359 $DB->set_field('block', 'visible', 1, array('id' => $block->id
));
3363 return parent
::write_setting($data);
3369 * Special select - lists on the frontpage - hacky
3371 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3373 class admin_setting_courselist_frontpage
extends admin_setting
{
3374 /** @var array Array of choices value=>label */
3378 * Construct override, requires one param
3380 * @param bool $loggedin Is the user logged in
3382 public function __construct($loggedin) {
3384 require_once($CFG->dirroot
.'/course/lib.php');
3385 $name = 'frontpage'.($loggedin ?
'loggedin' : '');
3386 $visiblename = get_string('frontpage'.($loggedin ?
'loggedin' : ''),'admin');
3387 $description = get_string('configfrontpage'.($loggedin ?
'loggedin' : ''),'admin');
3388 $defaults = array(FRONTPAGEALLCOURSELIST
);
3389 parent
::__construct($name, $visiblename, $description, $defaults);
3393 * Loads the choices available
3395 * @return bool always returns true
3397 public function load_choices() {
3398 if (is_array($this->choices
)) {
3401 $this->choices
= array(FRONTPAGENEWS
=> get_string('frontpagenews'),
3402 FRONTPAGEALLCOURSELIST
=> get_string('frontpagecourselist'),
3403 FRONTPAGEENROLLEDCOURSELIST
=> get_string('frontpageenrolledcourselist'),
3404 FRONTPAGECATEGORYNAMES
=> get_string('frontpagecategorynames'),
3405 FRONTPAGECATEGORYCOMBO
=> get_string('frontpagecategorycombo'),
3406 FRONTPAGECOURSESEARCH
=> get_string('frontpagecoursesearch'),
3407 'none' => get_string('none'));
3408 if ($this->name
=== 'frontpage') {
3409 unset($this->choices
[FRONTPAGEENROLLEDCOURSELIST
]);
3415 * Returns the selected settings
3417 * @param mixed array or setting or null
3419 public function get_setting() {
3420 $result = $this->config_read($this->name
);
3421 if (is_null($result)) {
3424 if ($result === '') {
3427 return explode(',', $result);
3431 * Save the selected options
3433 * @param array $data
3434 * @return mixed empty string (data is not an array) or bool true=success false=failure
3436 public function write_setting($data) {
3437 if (!is_array($data)) {
3440 $this->load_choices();
3442 foreach($data as $datum) {
3443 if ($datum == 'none' or !array_key_exists($datum, $this->choices
)) {
3446 $save[$datum] = $datum; // no duplicates
3448 return ($this->config_write($this->name
, implode(',', $save)) ?
'' : get_string('errorsetting', 'admin'));
3452 * Return XHTML select field and wrapping div
3454 * @todo Add vartype handling to make sure $data is an array
3455 * @param array $data Array of elements to select by default
3456 * @return string XHTML select field and wrapping div
3458 public function output_html($data, $query='') {
3459 $this->load_choices();
3460 $currentsetting = array();
3461 foreach ($data as $key) {
3462 if ($key != 'none' and array_key_exists($key, $this->choices
)) {
3463 $currentsetting[] = $key; // already selected first
3467 $return = '<div class="form-group">';
3468 for ($i = 0; $i < count($this->choices
) - 1; $i++
) {
3469 if (!array_key_exists($i, $currentsetting)) {
3470 $currentsetting[$i] = 'none'; //none
3472 $return .='<select class="form-select" id="'.$this->get_id().$i.'" name="'.$this->get_full_name().'[]">';
3473 foreach ($this->choices
as $key => $value) {
3474 $return .= '<option value="'.$key.'"'.("$key" == $currentsetting[$i] ?
' selected="selected"' : '').'>'.$value.'</option>';
3476 $return .= '</select>';
3477 if ($i !== count($this->choices
) - 2) {
3478 $return .= '<br />';
3481 $return .= '</div>';
3483 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
3489 * Special checkbox for frontpage - stores data in course table
3491 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3493 class admin_setting_sitesetcheckbox
extends admin_setting_configcheckbox
{
3495 * Returns the current sites name
3499 public function get_setting() {
3500 $site = course_get_format(get_site())->get_course();
3501 return $site->{$this->name
};
3505 * Save the selected setting
3507 * @param string $data The selected site
3508 * @return string empty string or error message
3510 public function write_setting($data) {
3511 global $DB, $SITE, $COURSE;
3512 $record = new stdClass();
3513 $record->id
= $SITE->id
;
3514 $record->{$this->name
} = ($data == '1' ?
1 : 0);
3515 $record->timemodified
= time();
3517 course_get_format($SITE)->update_course_format_options($record);
3518 $DB->update_record('course', $record);
3521 $SITE = $DB->get_record('course', array('id'=>$SITE->id
), '*', MUST_EXIST
);
3522 if ($SITE->id
== $COURSE->id
) {
3525 format_base
::reset_course_cache($SITE->id
);
3532 * Special text for frontpage - stores data in course table.
3533 * Empty string means not set here. Manual setting is required.
3535 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3537 class admin_setting_sitesettext
extends admin_setting_configtext
{
3539 * Return the current setting
3541 * @return mixed string or null
3543 public function get_setting() {
3544 $site = course_get_format(get_site())->get_course();
3545 return $site->{$this->name
} != '' ?
$site->{$this->name
} : NULL;
3549 * Validate the selected data
3551 * @param string $data The selected value to validate
3552 * @return mixed true or message string
3554 public function validate($data) {
3555 $cleaned = clean_param($data, PARAM_TEXT
);
3556 if ($cleaned === '') {
3557 return get_string('required');
3559 if ("$data" == "$cleaned") { // implicit conversion to string is needed to do exact comparison
3562 return get_string('validateerror', 'admin');
3567 * Save the selected setting
3569 * @param string $data The selected value
3570 * @return string empty or error message
3572 public function write_setting($data) {
3573 global $DB, $SITE, $COURSE;
3574 $data = trim($data);
3575 $validated = $this->validate($data);
3576 if ($validated !== true) {
3580 $record = new stdClass();
3581 $record->id
= $SITE->id
;
3582 $record->{$this->name
} = $data;
3583 $record->timemodified
= time();
3585 course_get_format($SITE)->update_course_format_options($record);
3586 $DB->update_record('course', $record);
3589 $SITE = $DB->get_record('course', array('id'=>$SITE->id
), '*', MUST_EXIST
);
3590 if ($SITE->id
== $COURSE->id
) {
3593 format_base
::reset_course_cache($SITE->id
);
3601 * Special text editor for site description.
3603 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3605 class admin_setting_special_frontpagedesc
extends admin_setting
{
3607 * Calls parent::__construct with specific arguments
3609 public function __construct() {
3610 parent
::__construct('summary', get_string('frontpagedescription'), get_string('frontpagedescriptionhelp'), NULL);
3611 editors_head_setup();
3615 * Return the current setting
3616 * @return string The current setting
3618 public function get_setting() {
3619 $site = course_get_format(get_site())->get_course();
3620 return $site->{$this->name
};
3624 * Save the new setting
3626 * @param string $data The new value to save
3627 * @return string empty or error message
3629 public function write_setting($data) {
3630 global $DB, $SITE, $COURSE;
3631 $record = new stdClass();
3632 $record->id
= $SITE->id
;
3633 $record->{$this->name
} = $data;
3634 $record->timemodified
= time();
3636 course_get_format($SITE)->update_course_format_options($record);
3637 $DB->update_record('course', $record);
3640 $SITE = $DB->get_record('course', array('id'=>$SITE->id
), '*', MUST_EXIST
);
3641 if ($SITE->id
== $COURSE->id
) {
3644 format_base
::reset_course_cache($SITE->id
);
3650 * Returns XHTML for the field plus wrapping div
3652 * @param string $data The current value
3653 * @param string $query
3654 * @return string The XHTML output
3656 public function output_html($data, $query='') {
3659 $CFG->adminusehtmleditor
= can_use_html_editor();
3660 $return = '<div class="form-htmlarea">'.print_textarea($CFG->adminusehtmleditor
, 15, 60, 0, 0, $this->get_full_name(), $data, 0, true, 'summary') .'</div>';
3662 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
3668 * Administration interface for emoticon_manager settings.
3670 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3672 class admin_setting_emoticons
extends admin_setting
{
3675 * Calls parent::__construct with specific args
3677 public function __construct() {
3680 $manager = get_emoticon_manager();
3681 $defaults = $this->prepare_form_data($manager->default_emoticons());
3682 parent
::__construct('emoticons', get_string('emoticons', 'admin'), get_string('emoticons_desc', 'admin'), $defaults);
3686 * Return the current setting(s)
3688 * @return array Current settings array
3690 public function get_setting() {
3693 $manager = get_emoticon_manager();
3695 $config = $this->config_read($this->name
);
3696 if (is_null($config)) {
3700 $config = $manager->decode_stored_config($config);
3701 if (is_null($config)) {
3705 return $this->prepare_form_data($config);
3709 * Save selected settings
3711 * @param array $data Array of settings to save
3714 public function write_setting($data) {
3716 $manager = get_emoticon_manager();
3717 $emoticons = $this->process_form_data($data);
3719 if ($emoticons === false) {
3723 if ($this->config_write($this->name
, $manager->encode_stored_config($emoticons))) {
3724 return ''; // success
3726 return get_string('errorsetting', 'admin') . $this->visiblename
. html_writer
::empty_tag('br');
3731 * Return XHTML field(s) for options
3733 * @param array $data Array of options to set in HTML
3734 * @return string XHTML string for the fields and wrapping div(s)
3736 public function output_html($data, $query='') {
3739 $out = html_writer
::start_tag('table', array('id' => 'emoticonsetting', 'class' => 'admintable generaltable'));
3740 $out .= html_writer
::start_tag('thead');
3741 $out .= html_writer
::start_tag('tr');
3742 $out .= html_writer
::tag('th', get_string('emoticontext', 'admin'));
3743 $out .= html_writer
::tag('th', get_string('emoticonimagename', 'admin'));
3744 $out .= html_writer
::tag('th', get_string('emoticoncomponent', 'admin'));
3745 $out .= html_writer
::tag('th', get_string('emoticonalt', 'admin'), array('colspan' => 2));
3746 $out .= html_writer
::tag('th', '');
3747 $out .= html_writer
::end_tag('tr');
3748 $out .= html_writer
::end_tag('thead');
3749 $out .= html_writer
::start_tag('tbody');
3751 foreach($data as $field => $value) {
3754 $out .= html_writer
::start_tag('tr');
3755 $current_text = $value;
3756 $current_filename = '';
3757 $current_imagecomponent = '';
3758 $current_altidentifier = '';
3759 $current_altcomponent = '';
3761 $current_filename = $value;
3763 $current_imagecomponent = $value;
3765 $current_altidentifier = $value;
3767 $current_altcomponent = $value;
3770 $out .= html_writer
::tag('td',
3771 html_writer
::empty_tag('input',
3774 'class' => 'form-text',
3775 'name' => $this->get_full_name().'['.$field.']',
3778 ), array('class' => 'c'.$i)
3782 if (get_string_manager()->string_exists($current_altidentifier, $current_altcomponent)) {
3783 $alt = get_string($current_altidentifier, $current_altcomponent);
3785 $alt = $current_text;
3787 if ($current_filename) {
3788 $out .= html_writer
::tag('td', $OUTPUT->render(new pix_emoticon($current_filename, $alt, $current_imagecomponent)));
3790 $out .= html_writer
::tag('td', '');
3792 $out .= html_writer
::end_tag('tr');
3799 $out .= html_writer
::end_tag('tbody');
3800 $out .= html_writer
::end_tag('table');
3801 $out = html_writer
::tag('div', $out, array('class' => 'form-group'));
3802 $out .= html_writer
::tag('div', html_writer
::link(new moodle_url('/admin/resetemoticons.php'), get_string('emoticonsreset', 'admin')));
3804 return format_admin_setting($this, $this->visiblename
, $out, $this->description
, false, '', NULL, $query);
3808 * Converts the array of emoticon objects provided by {@see emoticon_manager} into admin settings form data
3810 * @see self::process_form_data()
3811 * @param array $emoticons array of emoticon objects as returned by {@see emoticon_manager}
3812 * @return array of form fields and their values
3814 protected function prepare_form_data(array $emoticons) {
3818 foreach ($emoticons as $emoticon) {
3819 $form['text'.$i] = $emoticon->text
;
3820 $form['imagename'.$i] = $emoticon->imagename
;
3821 $form['imagecomponent'.$i] = $emoticon->imagecomponent
;
3822 $form['altidentifier'.$i] = $emoticon->altidentifier
;
3823 $form['altcomponent'.$i] = $emoticon->altcomponent
;
3826 // add one more blank field set for new object
3827 $form['text'.$i] = '';
3828 $form['imagename'.$i] = '';
3829 $form['imagecomponent'.$i] = '';
3830 $form['altidentifier'.$i] = '';
3831 $form['altcomponent'.$i] = '';
3837 * Converts the data from admin settings form into an array of emoticon objects
3839 * @see self::prepare_form_data()
3840 * @param array $data array of admin form fields and values
3841 * @return false|array of emoticon objects
3843 protected function process_form_data(array $form) {
3845 $count = count($form); // number of form field values
3848 // we must get five fields per emoticon object
3852 $emoticons = array();
3853 for ($i = 0; $i < $count / 5; $i++
) {
3854 $emoticon = new stdClass();
3855 $emoticon->text
= clean_param(trim($form['text'.$i]), PARAM_NOTAGS
);
3856 $emoticon->imagename
= clean_param(trim($form['imagename'.$i]), PARAM_PATH
);
3857 $emoticon->imagecomponent
= clean_param(trim($form['imagecomponent'.$i]), PARAM_COMPONENT
);
3858 $emoticon->altidentifier
= clean_param(trim($form['altidentifier'.$i]), PARAM_STRINGID
);
3859 $emoticon->altcomponent
= clean_param(trim($form['altcomponent'.$i]), PARAM_COMPONENT
);
3861 if (strpos($emoticon->text
, ':/') !== false or strpos($emoticon->text
, '//') !== false) {
3862 // prevent from breaking http://url.addresses by accident
3863 $emoticon->text
= '';
3866 if (strlen($emoticon->text
) < 2) {
3867 // do not allow single character emoticons
3868 $emoticon->text
= '';
3871 if (preg_match('/^[a-zA-Z]+[a-zA-Z0-9]*$/', $emoticon->text
)) {
3872 // emoticon text must contain some non-alphanumeric character to prevent
3873 // breaking HTML tags
3874 $emoticon->text
= '';
3877 if ($emoticon->text
!== '' and $emoticon->imagename
!== '' and $emoticon->imagecomponent
!== '') {
3878 $emoticons[] = $emoticon;
3887 * Special setting for limiting of the list of available languages.
3889 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3891 class admin_setting_langlist
extends admin_setting_configtext
{
3893 * Calls parent::__construct with specific arguments
3895 public function __construct() {
3896 parent
::__construct('langlist', get_string('langlist', 'admin'), get_string('configlanglist', 'admin'), '', PARAM_NOTAGS
);
3900 * Save the new setting
3902 * @param string $data The new setting
3905 public function write_setting($data) {
3906 $return = parent
::write_setting($data);
3907 get_string_manager()->reset_caches();
3914 * Selection of one of the recognised countries using the list
3915 * returned by {@link get_list_of_countries()}.
3917 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3919 class admin_settings_country_select
extends admin_setting_configselect
{
3920 protected $includeall;
3921 public function __construct($name, $visiblename, $description, $defaultsetting, $includeall=false) {
3922 $this->includeall
= $includeall;
3923 parent
::__construct($name, $visiblename, $description, $defaultsetting, NULL);
3927 * Lazy-load the available choices for the select box
3929 public function load_choices() {
3931 if (is_array($this->choices
)) {
3934 $this->choices
= array_merge(
3935 array('0' => get_string('choosedots')),
3936 get_string_manager()->get_list_of_countries($this->includeall
));
3943 * admin_setting_configselect for the default number of sections in a course,
3944 * simply so we can lazy-load the choices.
3946 * @copyright 2011 The Open University
3947 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3949 class admin_settings_num_course_sections
extends admin_setting_configselect
{
3950 public function __construct($name, $visiblename, $description, $defaultsetting) {
3951 parent
::__construct($name, $visiblename, $description, $defaultsetting, array());
3954 /** Lazy-load the available choices for the select box */
3955 public function load_choices() {
3956 $max = get_config('moodlecourse', 'maxsections');
3957 if (!isset($max) ||
!is_numeric($max)) {
3960 for ($i = 0; $i <= $max; $i++
) {
3961 $this->choices
[$i] = "$i";
3969 * Course category selection
3971 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3973 class admin_settings_coursecat_select
extends admin_setting_configselect
{
3975 * Calls parent::__construct with specific arguments
3977 public function __construct($name, $visiblename, $description, $defaultsetting) {
3978 parent
::__construct($name, $visiblename, $description, $defaultsetting, NULL);
3982 * Load the available choices for the select box
3986 public function load_choices() {
3988 require_once($CFG->dirroot
.'/course/lib.php');
3989 if (is_array($this->choices
)) {
3992 $this->choices
= make_categories_options();
3999 * Special control for selecting days to backup
4001 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4003 class admin_setting_special_backupdays
extends admin_setting_configmulticheckbox2
{
4005 * Calls parent::__construct with specific arguments
4007 public function __construct() {
4008 parent
::__construct('backup_auto_weekdays', get_string('automatedbackupschedule','backup'), get_string('automatedbackupschedulehelp','backup'), array(), NULL);
4009 $this->plugin
= 'backup';
4013 * Load the available choices for the select box
4015 * @return bool Always returns true
4017 public function load_choices() {
4018 if (is_array($this->choices
)) {
4021 $this->choices
= array();
4022 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
4023 foreach ($days as $day) {
4024 $this->choices
[$day] = get_string($day, 'calendar');
4032 * Special debug setting
4034 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4036 class admin_setting_special_debug
extends admin_setting_configselect
{
4038 * Calls parent::__construct with specific arguments
4040 public function __construct() {
4041 parent
::__construct('debug', get_string('debug', 'admin'), get_string('configdebug', 'admin'), DEBUG_NONE
, NULL);
4045 * Load the available choices for the select box
4049 public function load_choices() {
4050 if (is_array($this->choices
)) {
4053 $this->choices
= array(DEBUG_NONE
=> get_string('debugnone', 'admin'),
4054 DEBUG_MINIMAL
=> get_string('debugminimal', 'admin'),
4055 DEBUG_NORMAL
=> get_string('debugnormal', 'admin'),
4056 DEBUG_ALL
=> get_string('debugall', 'admin'),
4057 DEBUG_DEVELOPER
=> get_string('debugdeveloper', 'admin'));
4064 * Special admin control
4066 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4068 class admin_setting_special_calendar_weekend
extends admin_setting
{
4070 * Calls parent::__construct with specific arguments
4072 public function __construct() {
4073 $name = 'calendar_weekend';
4074 $visiblename = get_string('calendar_weekend', 'admin');
4075 $description = get_string('helpweekenddays', 'admin');
4076 $default = array ('0', '6'); // Saturdays and Sundays
4077 parent
::__construct($name, $visiblename, $description, $default);
4081 * Gets the current settings as an array
4083 * @return mixed Null if none, else array of settings
4085 public function get_setting() {
4086 $result = $this->config_read($this->name
);
4087 if (is_null($result)) {
4090 if ($result === '') {
4093 $settings = array();
4094 for ($i=0; $i<7; $i++
) {
4095 if ($result & (1 << $i)) {
4103 * Save the new settings
4105 * @param array $data Array of new settings
4108 public function write_setting($data) {
4109 if (!is_array($data)) {
4112 unset($data['xxxxx']);
4114 foreach($data as $index) {
4115 $result |
= 1 << $index;
4117 return ($this->config_write($this->name
, $result) ?
'' : get_string('errorsetting', 'admin'));
4121 * Return XHTML to display the control
4123 * @param array $data array of selected days
4124 * @param string $query
4125 * @return string XHTML for display (field + wrapping div(s)
4127 public function output_html($data, $query='') {
4128 // The order matters very much because of the implied numeric keys
4129 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
4130 $return = '<table><thead><tr>';
4131 $return .= '<input type="hidden" name="'.$this->get_full_name().'[xxxxx]" value="1" />'; // something must be submitted even if nothing selected
4132 foreach($days as $index => $day) {
4133 $return .= '<td><label for="'.$this->get_id().$index.'">'.get_string($day, 'calendar').'</label></td>';
4135 $return .= '</tr></thead><tbody><tr>';
4136 foreach($days as $index => $day) {
4137 $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>';
4139 $return .= '</tr></tbody></table>';
4141 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, false, '', NULL, $query);
4148 * Admin setting that allows a user to pick a behaviour.
4150 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4152 class admin_setting_question_behaviour
extends admin_setting_configselect
{
4154 * @param string $name name of config variable
4155 * @param string $visiblename display name
4156 * @param string $description description
4157 * @param string $default default.
4159 public function __construct($name, $visiblename, $description, $default) {
4160 parent
::__construct($name, $visiblename, $description, $default, NULL);
4164 * Load list of behaviours as choices
4165 * @return bool true => success, false => error.
4167 public function load_choices() {
4169 require_once($CFG->dirroot
. '/question/engine/lib.php');
4170 $this->choices
= question_engine
::get_behaviour_options('');
4177 * Admin setting that allows a user to pick appropriate roles for something.
4179 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4181 class admin_setting_pickroles
extends admin_setting_configmulticheckbox
{
4182 /** @var array Array of capabilities which identify roles */
4186 * @param string $name Name of config variable
4187 * @param string $visiblename Display name
4188 * @param string $description Description
4189 * @param array $types Array of archetypes which identify
4190 * roles that will be enabled by default.
4192 public function __construct($name, $visiblename, $description, $types) {
4193 parent
::__construct($name, $visiblename, $description, NULL, NULL);
4194 $this->types
= $types;
4198 * Load roles as choices
4200 * @return bool true=>success, false=>error
4202 public function load_choices() {
4204 if (during_initial_install()) {
4207 if (is_array($this->choices
)) {
4210 if ($roles = get_all_roles()) {
4211 $this->choices
= role_fix_names($roles, null, ROLENAME_ORIGINAL
, true);
4219 * Return the default setting for this control
4221 * @return array Array of default settings
4223 public function get_defaultsetting() {
4226 if (during_initial_install()) {
4230 foreach($this->types
as $archetype) {
4231 if ($caproles = get_archetype_roles($archetype)) {
4232 foreach ($caproles as $caprole) {
4233 $result[$caprole->id
] = 1;
4243 * Text field with an advanced checkbox, that controls a additional $name.'_adv' setting.
4245 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4247 class admin_setting_configtext_with_advanced
extends admin_setting_configtext
{
4250 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
4251 * @param string $visiblename localised
4252 * @param string $description long localised info
4253 * @param array $defaultsetting ('value'=>string, '__construct'=>bool)
4254 * @param mixed $paramtype int means PARAM_XXX type, string is a allowed format in regex
4255 * @param int $size default field size
4257 public function __construct($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW
, $size=null) {
4258 parent
::__construct($name, $visiblename, $description, $defaultsetting, $paramtype, $size);
4262 * Loads the current setting and returns array
4264 * @return array Returns array value=>xx, __construct=>xx
4266 public function get_setting() {
4267 $value = parent
::get_setting();
4268 $adv = $this->config_read($this->name
.'_adv');
4269 if (is_null($value) or is_null($adv)) {
4272 return array('value' => $value, 'adv' => $adv);
4276 * Saves the new settings passed in $data
4278 * @todo Add vartype handling to ensure $data is an array
4279 * @param array $data
4280 * @return mixed string or Array
4282 public function write_setting($data) {
4283 $error = parent
::write_setting($data['value']);
4285 $value = empty($data['adv']) ?
0 : 1;
4286 $this->config_write($this->name
.'_adv', $value);
4292 * Return XHTML for the control
4294 * @param array $data Default data array
4295 * @param string $query
4296 * @return string XHTML to display control
4298 public function output_html($data, $query='') {
4299 $default = $this->get_defaultsetting();
4300 $defaultinfo = array();
4301 if (isset($default['value'])) {
4302 if ($default['value'] === '') {
4303 $defaultinfo[] = "''";
4305 $defaultinfo[] = $default['value'];
4308 if (!empty($default['adv'])) {
4309 $defaultinfo[] = get_string('advanced');
4311 $defaultinfo = implode(', ', $defaultinfo);
4313 $adv = !empty($data['adv']);
4314 $return = '<div class="form-text defaultsnext">' .
4315 '<input type="text" size="' . $this->size
. '" id="' . $this->get_id() .
4316 '" name="' . $this->get_full_name() . '[value]" value="' . s($data['value']) . '" />' .
4317 ' <input type="checkbox" class="form-checkbox" id="' .
4318 $this->get_id() . '_adv" name="' . $this->get_full_name() .
4319 '[adv]" value="1" ' . ($adv ?
'checked="checked"' : '') . ' />' .
4320 ' <label for="' . $this->get_id() . '_adv">' .
4321 get_string('advanced') . '</label></div>';
4323 return format_admin_setting($this, $this->visiblename
, $return,
4324 $this->description
, true, '', $defaultinfo, $query);
4330 * Checkbox with an advanced checkbox that controls an additional $name.'_adv' config setting.
4332 * @copyright 2009 Petr Skoda (http://skodak.org)
4333 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4335 class admin_setting_configcheckbox_with_advanced
extends admin_setting_configcheckbox
{
4339 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
4340 * @param string $visiblename localised
4341 * @param string $description long localised info
4342 * @param array $defaultsetting ('value'=>string, 'adv'=>bool)
4343 * @param string $yes value used when checked
4344 * @param string $no value used when not checked
4346 public function __construct($name, $visiblename, $description, $defaultsetting, $yes='1', $no='0') {
4347 parent
::__construct($name, $visiblename, $description, $defaultsetting, $yes, $no);
4351 * Loads the current setting and returns array
4353 * @return array Returns array value=>xx, adv=>xx
4355 public function get_setting() {
4356 $value = parent
::get_setting();
4357 $adv = $this->config_read($this->name
.'_adv');
4358 if (is_null($value) or is_null($adv)) {
4361 return array('value' => $value, 'adv' => $adv);
4365 * Sets the value for the setting
4367 * Sets the value for the setting to either the yes or no values
4368 * of the object by comparing $data to yes
4370 * @param mixed $data Gets converted to str for comparison against yes value
4371 * @return string empty string or error
4373 public function write_setting($data) {
4374 $error = parent
::write_setting($data['value']);
4376 $value = empty($data['adv']) ?
0 : 1;
4377 $this->config_write($this->name
.'_adv', $value);
4383 * Returns an XHTML checkbox field and with extra advanced cehckbox
4385 * @param string $data If $data matches yes then checkbox is checked
4386 * @param string $query
4387 * @return string XHTML field
4389 public function output_html($data, $query='') {
4390 $defaults = $this->get_defaultsetting();
4391 $defaultinfo = array();
4392 if (!is_null($defaults)) {
4393 if ((string)$defaults['value'] === $this->yes
) {
4394 $defaultinfo[] = get_string('checkboxyes', 'admin');
4396 $defaultinfo[] = get_string('checkboxno', 'admin');
4398 if (!empty($defaults['adv'])) {
4399 $defaultinfo[] = get_string('advanced');
4402 $defaultinfo = implode(', ', $defaultinfo);
4404 if ((string)$data['value'] === $this->yes
) { // convert to strings before comparison
4405 $checked = 'checked="checked"';
4409 if (!empty($data['adv'])) {
4410 $advanced = 'checked="checked"';
4415 $fullname = $this->get_full_name();
4416 $novalue = s($this->no
);
4417 $yesvalue = s($this->yes
);
4418 $id = $this->get_id();
4419 $stradvanced = get_string('advanced');
4421 <div class="form-checkbox defaultsnext" >
4422 <input type="hidden" name="{$fullname}[value]" value="$novalue" />
4423 <input type="checkbox" id="$id" name="{$fullname}[value]" value="$yesvalue" $checked />
4424 <input type="checkbox" class="form-checkbox" id="{$id}_adv" name="{$fullname}[adv]" value="1" $advanced />
4425 <label for="{$id}_adv">$stradvanced</label>
4428 return format_admin_setting($this, $this->visiblename
, $return, $this->description
,
4429 true, '', $defaultinfo, $query);
4435 * Checkbox with an advanced checkbox that controls an additional $name.'_locked' config setting.
4437 * This is nearly a copy/paste of admin_setting_configcheckbox_with_adv
4439 * @copyright 2010 Sam Hemelryk
4440 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4442 class admin_setting_configcheckbox_with_lock
extends admin_setting_configcheckbox
{
4445 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
4446 * @param string $visiblename localised
4447 * @param string $description long localised info
4448 * @param array $defaultsetting ('value'=>string, 'locked'=>bool)
4449 * @param string $yes value used when checked
4450 * @param string $no value used when not checked
4452 public function __construct($name, $visiblename, $description, $defaultsetting, $yes='1', $no='0') {
4453 parent
::__construct($name, $visiblename, $description, $defaultsetting, $yes, $no);
4457 * Loads the current setting and returns array
4459 * @return array Returns array value=>xx, adv=>xx
4461 public function get_setting() {
4462 $value = parent
::get_setting();
4463 $locked = $this->config_read($this->name
.'_locked');
4464 if (is_null($value) or is_null($locked)) {
4467 return array('value' => $value, 'locked' => $locked);
4471 * Sets the value for the setting
4473 * Sets the value for the setting to either the yes or no values
4474 * of the object by comparing $data to yes
4476 * @param mixed $data Gets converted to str for comparison against yes value
4477 * @return string empty string or error
4479 public function write_setting($data) {
4480 $error = parent
::write_setting($data['value']);
4482 $value = empty($data['locked']) ?
0 : 1;
4483 $this->config_write($this->name
.'_locked', $value);
4489 * Returns an XHTML checkbox field and with extra locked checkbox
4491 * @param string $data If $data matches yes then checkbox is checked
4492 * @param string $query
4493 * @return string XHTML field
4495 public function output_html($data, $query='') {
4496 $defaults = $this->get_defaultsetting();
4497 $defaultinfo = array();
4498 if (!is_null($defaults)) {
4499 if ((string)$defaults['value'] === $this->yes
) {
4500 $defaultinfo[] = get_string('checkboxyes', 'admin');
4502 $defaultinfo[] = get_string('checkboxno', 'admin');
4504 if (!empty($defaults['locked'])) {
4505 $defaultinfo[] = get_string('locked', 'admin');
4508 $defaultinfo = implode(', ', $defaultinfo);
4510 $fullname = $this->get_full_name();
4511 $novalue = s($this->no
);
4512 $yesvalue = s($this->yes
);
4513 $id = $this->get_id();
4515 $checkboxparams = array('type'=>'checkbox', 'id'=>$id,'name'=>$fullname.'[value]', 'value'=>$yesvalue);
4516 if ((string)$data['value'] === $this->yes
) { // convert to strings before comparison
4517 $checkboxparams['checked'] = 'checked';
4520 $lockcheckboxparams = array('type'=>'checkbox', 'id'=>$id.'_locked','name'=>$fullname.'[locked]', 'value'=>1, 'class'=>'form-checkbox locked-checkbox');
4521 if (!empty($data['locked'])) { // convert to strings before comparison
4522 $lockcheckboxparams['checked'] = 'checked';
4525 $return = html_writer
::start_tag('div', array('class'=>'form-checkbox defaultsnext'));
4526 $return .= html_writer
::empty_tag('input', array('type'=>'hidden', 'name'=>$fullname.'[value]', 'value'=>$novalue));
4527 $return .= html_writer
::empty_tag('input', $checkboxparams);
4528 $return .= html_writer
::empty_tag('input', $lockcheckboxparams);
4529 $return .= html_writer
::tag('label', get_string('locked', 'admin'), array('for'=>$id.'_locked'));
4530 $return .= html_writer
::end_tag('div');
4531 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, true, '', $defaultinfo, $query);
4537 * Dropdown menu with an advanced checkbox, that controls a additional $name.'_adv' setting.
4539 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4541 class admin_setting_configselect_with_advanced
extends admin_setting_configselect
{
4543 * Calls parent::__construct with specific arguments
4545 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
4546 parent
::__construct($name, $visiblename, $description, $defaultsetting, $choices);
4550 * Loads the current setting and returns array
4552 * @return array Returns array value=>xx, adv=>xx
4554 public function get_setting() {
4555 $value = parent
::get_setting();
4556 $adv = $this->config_read($this->name
.'_adv');
4557 if (is_null($value) or is_null($adv)) {
4560 return array('value' => $value, 'adv' => $adv);
4564 * Saves the new settings passed in $data
4566 * @todo Add vartype handling to ensure $data is an array
4567 * @param array $data
4568 * @return mixed string or Array
4570 public function write_setting($data) {
4571 $error = parent
::write_setting($data['value']);
4573 $value = empty($data['adv']) ?
0 : 1;
4574 $this->config_write($this->name
.'_adv', $value);
4580 * Return XHTML for the control
4582 * @param array $data Default data array
4583 * @param string $query
4584 * @return string XHTML to display control
4586 public function output_html($data, $query='') {
4587 $default = $this->get_defaultsetting();
4588 $current = $this->get_setting();
4590 list($selecthtml, $warning) = $this->output_select_html($data['value'],
4591 $current['value'], $default['value'], '[value]');
4596 if (!is_null($default) and array_key_exists($default['value'], $this->choices
)) {
4597 $defaultinfo = array();
4598 if (isset($this->choices
[$default['value']])) {
4599 $defaultinfo[] = $this->choices
[$default['value']];
4601 if (!empty($default['adv'])) {
4602 $defaultinfo[] = get_string('advanced');
4604 $defaultinfo = implode(', ', $defaultinfo);
4609 $adv = !empty($data['adv']);
4610 $return = '<div class="form-select defaultsnext">' . $selecthtml .
4611 ' <input type="checkbox" class="form-checkbox" id="' .
4612 $this->get_id() . '_adv" name="' . $this->get_full_name() .
4613 '[adv]" value="1" ' . ($adv ?
'checked="checked"' : '') . ' />' .
4614 ' <label for="' . $this->get_id() . '_adv">' .
4615 get_string('advanced') . '</label></div>';
4617 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, true, $warning, $defaultinfo, $query);
4623 * Graded roles in gradebook
4625 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4627 class admin_setting_special_gradebookroles
extends admin_setting_pickroles
{
4629 * Calls parent::__construct with specific arguments
4631 public function __construct() {
4632 parent
::__construct('gradebookroles', get_string('gradebookroles', 'admin'),
4633 get_string('configgradebookroles', 'admin'),
4641 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4643 class admin_setting_regradingcheckbox
extends admin_setting_configcheckbox
{
4645 * Saves the new settings passed in $data
4647 * @param string $data
4648 * @return mixed string or Array
4650 public function write_setting($data) {
4653 $oldvalue = $this->config_read($this->name
);
4654 $return = parent
::write_setting($data);
4655 $newvalue = $this->config_read($this->name
);
4657 if ($oldvalue !== $newvalue) {
4658 // force full regrading
4659 $DB->set_field('grade_items', 'needsupdate', 1, array('needsupdate'=>0));
4668 * Which roles to show on course description page
4670 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4672 class admin_setting_special_coursecontact
extends admin_setting_pickroles
{
4674 * Calls parent::__construct with specific arguments
4676 public function __construct() {
4677 parent
::__construct('coursecontact', get_string('coursecontact', 'admin'),
4678 get_string('coursecontact_desc', 'admin'),
4679 array('editingteacher'));
4686 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4688 class admin_setting_special_gradelimiting
extends admin_setting_configcheckbox
{
4690 * Calls parent::__construct with specific arguments
4692 function admin_setting_special_gradelimiting() {
4693 parent
::__construct('unlimitedgrades', get_string('unlimitedgrades', 'grades'),
4694 get_string('unlimitedgrades_help', 'grades'), '0', '1', '0');
4698 * Force site regrading
4700 function regrade_all() {
4702 require_once("$CFG->libdir/gradelib.php");
4703 grade_force_site_regrading();
4707 * Saves the new settings
4709 * @param mixed $data
4710 * @return string empty string or error message
4712 function write_setting($data) {
4713 $previous = $this->get_setting();
4715 if ($previous === null) {
4717 $this->regrade_all();
4720 if ($data != $previous) {
4721 $this->regrade_all();
4724 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
4731 * Primary grade export plugin - has state tracking.
4733 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4735 class admin_setting_special_gradeexport
extends admin_setting_configmulticheckbox
{
4737 * Calls parent::__construct with specific arguments
4739 public function __construct() {
4740 parent
::__construct('gradeexport', get_string('gradeexport', 'admin'),
4741 get_string('configgradeexport', 'admin'), array(), NULL);
4745 * Load the available choices for the multicheckbox
4747 * @return bool always returns true
4749 public function load_choices() {
4750 if (is_array($this->choices
)) {
4753 $this->choices
= array();
4755 if ($plugins = get_plugin_list('gradeexport')) {
4756 foreach($plugins as $plugin => $unused) {
4757 $this->choices
[$plugin] = get_string('pluginname', 'gradeexport_'.$plugin);
4766 * Grade category settings
4768 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4770 class admin_setting_gradecat_combo
extends admin_setting
{
4771 /** @var array Array of choices */
4775 * Sets choices and calls parent::__construct with passed arguments
4776 * @param string $name
4777 * @param string $visiblename
4778 * @param string $description
4779 * @param mixed $defaultsetting string or array depending on implementation
4780 * @param array $choices An array of choices for the control
4782 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
4783 $this->choices
= $choices;
4784 parent
::__construct($name, $visiblename, $description, $defaultsetting);
4788 * Return the current setting(s) array
4790 * @return array Array of value=>xx, forced=>xx, adv=>xx
4792 public function get_setting() {
4795 $value = $this->config_read($this->name
);
4796 $flag = $this->config_read($this->name
.'_flag');
4798 if (is_null($value) or is_null($flag)) {
4803 $forced = (boolean
)(1 & $flag); // first bit
4804 $adv = (boolean
)(2 & $flag); // second bit
4806 return array('value' => $value, 'forced' => $forced, 'adv' => $adv);
4810 * Save the new settings passed in $data
4812 * @todo Add vartype handling to ensure $data is array
4813 * @param array $data Associative array of value=>xx, forced=>xx, adv=>xx
4814 * @return string empty or error message
4816 public function write_setting($data) {
4819 $value = $data['value'];
4820 $forced = empty($data['forced']) ?
0 : 1;
4821 $adv = empty($data['adv']) ?
0 : 2;
4822 $flag = ($forced |
$adv); //bitwise or
4824 if (!in_array($value, array_keys($this->choices
))) {
4825 return 'Error setting ';
4828 $oldvalue = $this->config_read($this->name
);
4829 $oldflag = (int)$this->config_read($this->name
.'_flag');
4830 $oldforced = (1 & $oldflag); // first bit
4832 $result1 = $this->config_write($this->name
, $value);
4833 $result2 = $this->config_write($this->name
.'_flag', $flag);
4835 // force regrade if needed
4836 if ($oldforced != $forced or ($forced and $value != $oldvalue)) {
4837 require_once($CFG->libdir
.'/gradelib.php');
4838 grade_category
::updated_forced_settings();
4841 if ($result1 and $result2) {
4844 return get_string('errorsetting', 'admin');
4849 * Return XHTML to display the field and wrapping div
4851 * @todo Add vartype handling to ensure $data is array
4852 * @param array $data Associative array of value=>xx, forced=>xx, adv=>xx
4853 * @param string $query
4854 * @return string XHTML to display control
4856 public function output_html($data, $query='') {
4857 $value = $data['value'];
4858 $forced = !empty($data['forced']);
4859 $adv = !empty($data['adv']);
4861 $default = $this->get_defaultsetting();
4862 if (!is_null($default)) {
4863 $defaultinfo = array();
4864 if (isset($this->choices
[$default['value']])) {
4865 $defaultinfo[] = $this->choices
[$default['value']];
4867 if (!empty($default['forced'])) {
4868 $defaultinfo[] = get_string('force');
4870 if (!empty($default['adv'])) {
4871 $defaultinfo[] = get_string('advanced');
4873 $defaultinfo = implode(', ', $defaultinfo);
4876 $defaultinfo = NULL;
4880 $return = '<div class="form-group">';
4881 $return .= '<select class="form-select" id="'.$this->get_id().'" name="'.$this->get_full_name().'[value]">';
4882 foreach ($this->choices
as $key => $val) {
4883 // the string cast is needed because key may be integer - 0 is equal to most strings!
4884 $return .= '<option value="'.$key.'"'.((string)$key==$value ?
' selected="selected"' : '').'>'.$val.'</option>';
4886 $return .= '</select>';
4887 $return .= '<input type="checkbox" class="form-checkbox" id="'.$this->get_id().'force" name="'.$this->get_full_name().'[forced]" value="1" '.($forced ?
'checked="checked"' : '').' />'
4888 .'<label for="'.$this->get_id().'force">'.get_string('force').'</label>';
4889 $return .= '<input type="checkbox" class="form-checkbox" id="'.$this->get_id().'adv" name="'.$this->get_full_name().'[adv]" value="1" '.($adv ?
'checked="checked"' : '').' />'
4890 .'<label for="'.$this->get_id().'adv">'.get_string('advanced').'</label>';
4891 $return .= '</div>';
4893 return format_admin_setting($this, $this->visiblename
, $return, $this->description
, true, '', $defaultinfo, $query);
4899 * Selection of grade report in user profiles
4901 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4903 class admin_setting_grade_profilereport
extends admin_setting_configselect
{
4905 * Calls parent::__construct with specific arguments
4907 public function __construct() {
4908 parent
::__construct('grade_profilereport', get_string('profilereport', 'grades'), get_string('profilereport_help', 'grades'), 'user', null);
4912 * Loads an array of choices for the configselect control
4914 * @return bool always return true
4916 public function load_choices() {
4917 if (is_array($this->choices
)) {
4920 $this->choices
= array();
4923 require_once($CFG->libdir
.'/gradelib.php');
4925 foreach (get_plugin_list('gradereport') as $plugin => $plugindir) {
4926 if (file_exists($plugindir.'/lib.php')) {
4927 require_once($plugindir.'/lib.php');
4928 $functionname = 'grade_report_'.$plugin.'_profilereport';
4929 if (function_exists($functionname)) {
4930 $this->choices
[$plugin] = get_string('pluginname', 'gradereport_'.$plugin);
4940 * Special class for register auth selection
4942 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4944 class admin_setting_special_registerauth
extends admin_setting_configselect
{
4946 * Calls parent::__construct with specific arguments
4948 public function __construct() {
4949 parent
::__construct('registerauth', get_string('selfregistration', 'auth'), get_string('selfregistration_help', 'auth'), '', null);
4953 * Returns the default option
4955 * @return string empty or default option
4957 public function get_defaultsetting() {
4958 $this->load_choices();
4959 $defaultsetting = parent
::get_defaultsetting();
4960 if (array_key_exists($defaultsetting, $this->choices
)) {
4961 return $defaultsetting;
4968 * Loads the possible choices for the array
4970 * @return bool always returns true
4972 public function load_choices() {
4975 if (is_array($this->choices
)) {
4978 $this->choices
= array();
4979 $this->choices
[''] = get_string('disable');
4981 $authsenabled = get_enabled_auth_plugins(true);
4983 foreach ($authsenabled as $auth) {
4984 $authplugin = get_auth_plugin($auth);
4985 if (!$authplugin->can_signup()) {
4988 // Get the auth title (from core or own auth lang files)
4989 $authtitle = $authplugin->get_title();
4990 $this->choices
[$auth] = $authtitle;
4998 * General plugins manager
5000 class admin_page_pluginsoverview
extends admin_externalpage
{
5003 * Sets basic information about the external page
5005 public function __construct() {
5007 parent
::__construct('pluginsoverview', get_string('pluginsoverview', 'core_admin'),
5008 "$CFG->wwwroot/$CFG->admin/plugins.php");
5013 * Module manage page
5015 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5017 class admin_page_managemods
extends admin_externalpage
{
5019 * Calls parent::__construct with specific arguments
5021 public function __construct() {
5023 parent
::__construct('managemodules', get_string('modsettings', 'admin'), "$CFG->wwwroot/$CFG->admin/modules.php");
5027 * Try to find the specified module
5029 * @param string $query The module to search for
5032 public function search($query) {
5034 if ($result = parent
::search($query)) {
5039 if ($modules = $DB->get_records('modules')) {
5040 foreach ($modules as $module) {
5041 if (!file_exists("$CFG->dirroot/mod/$module->name/lib.php")) {
5044 if (strpos($module->name
, $query) !== false) {
5048 $strmodulename = get_string('modulename', $module->name
);
5049 if (strpos(textlib
::strtolower($strmodulename), $query) !== false) {
5056 $result = new stdClass();
5057 $result->page
= $this;
5058 $result->settings
= array();
5059 return array($this->name
=> $result);
5068 * Special class for enrol plugins management.
5070 * @copyright 2010 Petr Skoda {@link http://skodak.org}
5071 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5073 class admin_setting_manageenrols
extends admin_setting
{
5075 * Calls parent::__construct with specific arguments
5077 public function __construct() {
5078 $this->nosave
= true;
5079 parent
::__construct('enrolsui', get_string('manageenrols', 'enrol'), '', '');
5083 * Always returns true, does nothing
5087 public function get_setting() {
5092 * Always returns true, does nothing
5096 public function get_defaultsetting() {
5101 * Always returns '', does not write anything
5103 * @return string Always returns ''
5105 public function write_setting($data) {
5106 // do not write any setting
5111 * Checks if $query is one of the available enrol plugins
5113 * @param string $query The string to search for
5114 * @return bool Returns true if found, false if not
5116 public function is_related($query) {
5117 if (parent
::is_related($query)) {
5121 $query = textlib
::strtolower($query);
5122 $enrols = enrol_get_plugins(false);
5123 foreach ($enrols as $name=>$enrol) {
5124 $localised = get_string('pluginname', 'enrol_'.$name);
5125 if (strpos(textlib
::strtolower($name), $query) !== false) {
5128 if (strpos(textlib
::strtolower($localised), $query) !== false) {
5136 * Builds the XHTML to display the control
5138 * @param string $data Unused
5139 * @param string $query
5142 public function output_html($data, $query='') {
5143 global $CFG, $OUTPUT, $DB, $PAGE;
5146 $strup = get_string('up');
5147 $strdown = get_string('down');
5148 $strsettings = get_string('settings');
5149 $strenable = get_string('enable');
5150 $strdisable = get_string('disable');
5151 $struninstall = get_string('uninstallplugin', 'admin');
5152 $strusage = get_string('enrolusage', 'enrol');
5153 $strversion = get_string('version');
5155 $pluginmanager = plugin_manager
::instance();
5157 $enrols_available = enrol_get_plugins(false);
5158 $active_enrols = enrol_get_plugins(true);
5160 $allenrols = array();
5161 foreach ($active_enrols as $key=>$enrol) {
5162 $allenrols[$key] = true;
5164 foreach ($enrols_available as $key=>$enrol) {
5165 $allenrols[$key] = true;
5167 // Now find all borked plugins and at least allow then to uninstall.
5168 $condidates = $DB->get_fieldset_sql("SELECT DISTINCT enrol FROM {enrol}");
5169 foreach ($condidates as $candidate) {
5170 if (empty($allenrols[$candidate])) {
5171 $allenrols[$candidate] = true;
5175 $return = $OUTPUT->heading(get_string('actenrolshhdr', 'enrol'), 3, 'main', true);
5176 $return .= $OUTPUT->box_start('generalbox enrolsui');
5178 $table = new html_table();
5179 $table->head
= array(get_string('name'), $strusage, $strversion, $strenable, $strup.'/'.$strdown, $strsettings, $struninstall);
5180 $table->colclasses
= array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign', 'centeralign', 'centeralign');
5181 $table->id
= 'courseenrolmentplugins';
5182 $table->attributes
['class'] = 'admintable generaltable';
5183 $table->data
= array();
5185 // Iterate through enrol plugins and add to the display table.
5187 $enrolcount = count($active_enrols);
5188 $url = new moodle_url('/admin/enrol.php', array('sesskey'=>sesskey()));
5190 foreach($allenrols as $enrol => $unused) {
5191 $plugininfo = $pluginmanager->get_plugin_info('enrol_'.$enrol);
5192 $version = get_config('enrol_'.$enrol, 'version');
5193 if ($version === false) {
5197 if (get_string_manager()->string_exists('pluginname', 'enrol_'.$enrol)) {
5198 $name = get_string('pluginname', 'enrol_'.$enrol);
5203 $ci = $DB->count_records('enrol', array('enrol'=>$enrol));
5204 $cp = $DB->count_records_select('user_enrolments', "enrolid IN (SELECT id FROM {enrol} WHERE enrol = ?)", array($enrol));
5205 $usage = "$ci / $cp";
5208 if (isset($active_enrols[$enrol])) {
5209 $aurl = new moodle_url($url, array('action'=>'disable', 'enrol'=>$enrol));
5210 $hideshow = "<a href=\"$aurl\">";
5211 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('t/hide') . "\" class=\"iconsmall\" alt=\"$strdisable\" /></a>";
5213 $displayname = "<span>$name</span>";
5214 } else if (isset($enrols_available[$enrol])) {
5215 $aurl = new moodle_url($url, array('action'=>'enable', 'enrol'=>$enrol));
5216 $hideshow = "<a href=\"$aurl\">";
5217 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('t/show') . "\" class=\"iconsmall\" alt=\"$strenable\" /></a>";
5219 $displayname = "<span class=\"dimmed_text\">$name</span>";
5223 $displayname = '<span class="notifyproblem">'.$name.'</span>';
5225 if ($PAGE->theme
->resolve_image_location('icon', 'enrol_' . $name, false)) {
5226 $icon = $OUTPUT->pix_icon('icon', '', 'enrol_' . $name, array('class' => 'icon pluginicon'));
5228 $icon = $OUTPUT->pix_icon('spacer', '', 'moodle', array('class' => 'icon pluginicon noicon'));
5231 // Up/down link (only if enrol is enabled).
5234 if ($updowncount > 1) {
5235 $aurl = new moodle_url($url, array('action'=>'up', 'enrol'=>$enrol));
5236 $updown .= "<a href=\"$aurl\">";
5237 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/up') . "\" alt=\"$strup\" class=\"iconsmall\" /></a> ";
5239 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"iconsmall\" alt=\"\" /> ";
5241 if ($updowncount < $enrolcount) {
5242 $aurl = new moodle_url($url, array('action'=>'down', 'enrol'=>$enrol));
5243 $updown .= "<a href=\"$aurl\">";
5244 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/down') . "\" alt=\"$strdown\" class=\"iconsmall\" /></a>";
5246 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"iconsmall\" alt=\"\" />";
5251 // Add settings link.
5254 } else if ($url = $plugininfo->get_settings_url()) {
5255 $settings = html_writer
::link($url, $strsettings);
5260 // Add uninstall info.
5262 $url = new moodle_url($plugininfo->get_uninstall_url(), array('return'=>'settings'));
5263 $uninstall = html_writer
::link($url, $struninstall);
5268 // Add a row to the table.
5269 $table->data
[] = array($icon.$displayname, $usage, $version, $hideshow, $updown, $settings, $uninstall);
5271 $printed[$enrol] = true;
5274 $return .= html_writer
::table($table);
5275 $return .= get_string('configenrolplugins', 'enrol').'<br />'.get_string('tablenosave', 'admin');
5276 $return .= $OUTPUT->box_end();
5277 return highlight($query, $return);
5283 * Blocks manage page
5285 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5287 class admin_page_manageblocks
extends admin_externalpage
{
5289 * Calls parent::__construct with specific arguments
5291 public function __construct() {
5293 parent
::__construct('manageblocks', get_string('blocksettings', 'admin'), "$CFG->wwwroot/$CFG->admin/blocks.php");
5297 * Search for a specific block
5299 * @param string $query The string to search for
5302 public function search($query) {
5304 if ($result = parent
::search($query)) {
5309 if ($blocks = $DB->get_records('block')) {
5310 foreach ($blocks as $block) {
5311 if (!file_exists("$CFG->dirroot/blocks/$block->name/")) {
5314 if (strpos($block->name
, $query) !== false) {
5318 $strblockname = get_string('pluginname', 'block_'.$block->name
);
5319 if (strpos(textlib
::strtolower($strblockname), $query) !== false) {
5326 $result = new stdClass();
5327 $result->page
= $this;
5328 $result->settings
= array();
5329 return array($this->name
=> $result);
5337 * Message outputs configuration
5339 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5341 class admin_page_managemessageoutputs
extends admin_externalpage
{
5343 * Calls parent::__construct with specific arguments
5345 public function __construct() {
5347 parent
::__construct('managemessageoutputs', get_string('managemessageoutputs', 'message'), new moodle_url('/admin/message.php'));
5351 * Search for a specific message processor
5353 * @param string $query The string to search for
5356 public function search($query) {
5358 if ($result = parent
::search($query)) {
5363 if ($processors = get_message_processors()) {
5364 foreach ($processors as $processor) {
5365 if (!$processor->available
) {
5368 if (strpos($processor->name
, $query) !== false) {
5372 $strprocessorname = get_string('pluginname', 'message_'.$processor->name
);
5373 if (strpos(textlib
::strtolower($strprocessorname), $query) !== false) {
5380 $result = new stdClass();
5381 $result->page
= $this;
5382 $result->settings
= array();
5383 return array($this->name
=> $result);
5391 * Default message outputs configuration
5393 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5395 class admin_page_defaultmessageoutputs
extends admin_page_managemessageoutputs
{
5397 * Calls parent::__construct with specific arguments
5399 public function __construct() {
5401 admin_externalpage
::__construct('defaultmessageoutputs', get_string('defaultmessageoutputs', 'message'), new moodle_url('/message/defaultoutputs.php'));
5407 * Manage question behaviours page
5409 * @copyright 2011 The Open University
5410 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5412 class admin_page_manageqbehaviours
extends admin_externalpage
{
5416 public function __construct() {
5418 parent
::__construct('manageqbehaviours', get_string('manageqbehaviours', 'admin'),
5419 new moodle_url('/admin/qbehaviours.php'));
5423 * Search question behaviours for the specified string
5425 * @param string $query The string to search for in question behaviours
5428 public function search($query) {
5430 if ($result = parent
::search($query)) {
5435 require_once($CFG->dirroot
. '/question/engine/lib.php');
5436 foreach (get_plugin_list('qbehaviour') as $behaviour => $notused) {
5437 if (strpos(textlib
::strtolower(question_engine
::get_behaviour_name($behaviour)),
5438 $query) !== false) {
5444 $result = new stdClass();
5445 $result->page
= $this;
5446 $result->settings
= array();
5447 return array($this->name
=> $result);
5456 * Question type manage page
5458 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5460 class admin_page_manageqtypes
extends admin_externalpage
{
5462 * Calls parent::__construct with specific arguments
5464 public function __construct() {
5466 parent
::__construct('manageqtypes', get_string('manageqtypes', 'admin'),
5467 new moodle_url('/admin/qtypes.php'));
5471 * Search question types for the specified string
5473 * @param string $query The string to search for in question types
5476 public function search($query) {
5478 if ($result = parent
::search($query)) {
5483 require_once($CFG->dirroot
. '/question/engine/bank.php');
5484 foreach (question_bank
::get_all_qtypes() as $qtype) {
5485 if (strpos(textlib
::strtolower($qtype->local_name()), $query) !== false) {
5491 $result = new stdClass();
5492 $result->page
= $this;
5493 $result->settings
= array();
5494 return array($this->name
=> $result);
5502 class admin_page_manageportfolios
extends admin_externalpage
{
5504 * Calls parent::__construct with specific arguments
5506 public function __construct() {
5508 parent
::__construct('manageportfolios', get_string('manageportfolios', 'portfolio'),
5509 "$CFG->wwwroot/$CFG->admin/portfolio.php");
5513 * Searches page for the specified string.
5514 * @param string $query The string to search for
5515 * @return bool True if it is found on this page
5517 public function search($query) {
5519 if ($result = parent
::search($query)) {
5524 $portfolios = get_plugin_list('portfolio');
5525 foreach ($portfolios as $p => $dir) {
5526 if (strpos($p, $query) !== false) {
5532 foreach (portfolio_instances(false, false) as $instance) {
5533 $title = $instance->get('name');
5534 if (strpos(textlib
::strtolower($title), $query) !== false) {
5542 $result = new stdClass();
5543 $result->page
= $this;
5544 $result->settings
= array();
5545 return array($this->name
=> $result);
5553 class admin_page_managerepositories
extends admin_externalpage
{
5555 * Calls parent::__construct with specific arguments
5557 public function __construct() {
5559 parent
::__construct('managerepositories', get_string('manage',
5560 'repository'), "$CFG->wwwroot/$CFG->admin/repository.php");
5564 * Searches page for the specified string.
5565 * @param string $query The string to search for
5566 * @return bool True if it is found on this page
5568 public function search($query) {
5570 if ($result = parent
::search($query)) {
5575 $repositories= get_plugin_list('repository');
5576 foreach ($repositories as $p => $dir) {
5577 if (strpos($p, $query) !== false) {
5583 foreach (repository
::get_types() as $instance) {
5584 $title = $instance->get_typename();
5585 if (strpos(textlib
::strtolower($title), $query) !== false) {
5593 $result = new stdClass();
5594 $result->page
= $this;
5595 $result->settings
= array();
5596 return array($this->name
=> $result);
5605 * Special class for authentication administration.
5607 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5609 class admin_setting_manageauths
extends admin_setting
{
5611 * Calls parent::__construct with specific arguments
5613 public function __construct() {
5614 $this->nosave
= true;
5615 parent
::__construct('authsui', get_string('authsettings', 'admin'), '', '');
5619 * Always returns true
5623 public function get_setting() {
5628 * Always returns true
5632 public function get_defaultsetting() {
5637 * Always returns '' and doesn't write anything
5639 * @return string Always returns ''
5641 public function write_setting($data) {
5642 // do not write any setting
5647 * Search to find if Query is related to auth plugin
5649 * @param string $query The string to search for
5650 * @return bool true for related false for not
5652 public function is_related($query) {
5653 if (parent
::is_related($query)) {
5657 $authsavailable = get_plugin_list('auth');
5658 foreach ($authsavailable as $auth => $dir) {
5659 if (strpos($auth, $query) !== false) {
5662 $authplugin = get_auth_plugin($auth);
5663 $authtitle = $authplugin->get_title();
5664 if (strpos(textlib
::strtolower($authtitle), $query) !== false) {
5672 * Return XHTML to display control
5674 * @param mixed $data Unused
5675 * @param string $query
5676 * @return string highlight
5678 public function output_html($data, $query='') {
5679 global $CFG, $OUTPUT;
5683 $txt = get_strings(array('authenticationplugins', 'users', 'administration',
5684 'settings', 'edit', 'name', 'enable', 'disable',
5685 'up', 'down', 'none'));
5686 $txt->updown
= "$txt->up/$txt->down";
5688 $authsavailable = get_plugin_list('auth');
5689 get_enabled_auth_plugins(true); // fix the list of enabled auths
5690 if (empty($CFG->auth
)) {
5691 $authsenabled = array();
5693 $authsenabled = explode(',', $CFG->auth
);
5696 // construct the display array, with enabled auth plugins at the top, in order
5697 $displayauths = array();
5698 $registrationauths = array();
5699 $registrationauths[''] = $txt->disable
;
5700 foreach ($authsenabled as $auth) {
5701 $authplugin = get_auth_plugin($auth);
5702 /// Get the auth title (from core or own auth lang files)
5703 $authtitle = $authplugin->get_title();
5705 $displayauths[$auth] = $authtitle;
5706 if ($authplugin->can_signup()) {
5707 $registrationauths[$auth] = $authtitle;
5711 foreach ($authsavailable as $auth => $dir) {
5712 if (array_key_exists($auth, $displayauths)) {
5713 continue; //already in the list
5715 $authplugin = get_auth_plugin($auth);
5716 /// Get the auth title (from core or own auth lang files)
5717 $authtitle = $authplugin->get_title();
5719 $displayauths[$auth] = $authtitle;
5720 if ($authplugin->can_signup()) {
5721 $registrationauths[$auth] = $authtitle;
5725 $return = $OUTPUT->heading(get_string('actauthhdr', 'auth'), 3, 'main');
5726 $return .= $OUTPUT->box_start('generalbox authsui');
5728 $table = new html_table();
5729 $table->head
= array($txt->name
, $txt->enable
, $txt->updown
, $txt->settings
);
5730 $table->colclasses
= array('leftalign', 'centeralign', 'centeralign', 'centeralign');
5731 $table->data
= array();
5732 $table->attributes
['class'] = 'admintable generaltable';
5733 $table->id
= 'manageauthtable';
5735 //add always enabled plugins first
5736 $displayname = "<span>".$displayauths['manual']."</span>";
5737 $settings = "<a href=\"auth_config.php?auth=manual\">{$txt->settings}</a>";
5738 //$settings = "<a href=\"settings.php?section=authsettingmanual\">{$txt->settings}</a>";
5739 $table->data
[] = array($displayname, '', '', $settings);
5740 $displayname = "<span>".$displayauths['nologin']."</span>";
5741 $settings = "<a href=\"auth_config.php?auth=nologin\">{$txt->settings}</a>";
5742 $table->data
[] = array($displayname, '', '', $settings);
5745 // iterate through auth plugins and add to the display table
5747 $authcount = count($authsenabled);
5748 $url = "auth.php?sesskey=" . sesskey();
5749 foreach ($displayauths as $auth => $name) {
5750 if ($auth == 'manual' or $auth == 'nologin') {
5754 if (in_array($auth, $authsenabled)) {
5755 $hideshow = "<a href=\"$url&action=disable&auth=$auth\">";
5756 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('t/hide') . "\" class=\"iconsmall\" alt=\"disable\" /></a>";
5757 // $hideshow = "<a href=\"$url&action=disable&auth=$auth\"><input type=\"checkbox\" checked /></a>";
5759 $displayname = "<span>$name</span>";
5762 $hideshow = "<a href=\"$url&action=enable&auth=$auth\">";
5763 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('t/show') . "\" class=\"iconsmall\" alt=\"enable\" /></a>";
5764 // $hideshow = "<a href=\"$url&action=enable&auth=$auth\"><input type=\"checkbox\" /></a>";
5766 $displayname = "<span class=\"dimmed_text\">$name</span>";
5769 // up/down link (only if auth is enabled)
5772 if ($updowncount > 1) {
5773 $updown .= "<a href=\"$url&action=up&auth=$auth\">";
5774 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/up') . "\" alt=\"up\" class=\"iconsmall\" /></a> ";
5777 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"iconsmall\" alt=\"\" /> ";
5779 if ($updowncount < $authcount) {
5780 $updown .= "<a href=\"$url&action=down&auth=$auth\">";
5781 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/down') . "\" alt=\"down\" class=\"iconsmall\" /></a>";
5784 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"iconsmall\" alt=\"\" />";
5790 if (file_exists($CFG->dirroot
.'/auth/'.$auth.'/settings.php')) {
5791 $settings = "<a href=\"settings.php?section=authsetting$auth\">{$txt->settings}</a>";
5793 $settings = "<a href=\"auth_config.php?auth=$auth\">{$txt->settings}</a>";
5796 // add a row to the table
5797 $table->data
[] =array($displayname, $hideshow, $updown, $settings);
5799 $return .= html_writer
::table($table);
5800 $return .= get_string('configauthenticationplugins', 'admin').'<br />'.get_string('tablenosave', 'filters');
5801 $return .= $OUTPUT->box_end();
5802 return highlight($query, $return);
5808 * Special class for authentication administration.
5810 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5812 class admin_setting_manageeditors
extends admin_setting
{
5814 * Calls parent::__construct with specific arguments
5816 public function __construct() {
5817 $this->nosave
= true;
5818 parent
::__construct('editorsui', get_string('editorsettings', 'editor'), '', '');
5822 * Always returns true, does nothing
5826 public function get_setting() {
5831 * Always returns true, does nothing
5835 public function get_defaultsetting() {
5840 * Always returns '', does not write anything
5842 * @return string Always returns ''
5844 public function write_setting($data) {
5845 // do not write any setting
5850 * Checks if $query is one of the available editors
5852 * @param string $query The string to search for
5853 * @return bool Returns true if found, false if not
5855 public function is_related($query) {
5856 if (parent
::is_related($query)) {
5860 $editors_available = editors_get_available();
5861 foreach ($editors_available as $editor=>$editorstr) {
5862 if (strpos($editor, $query) !== false) {
5865 if (strpos(textlib
::strtolower($editorstr), $query) !== false) {
5873 * Builds the XHTML to display the control
5875 * @param string $data Unused
5876 * @param string $query
5879 public function output_html($data, $query='') {
5880 global $CFG, $OUTPUT;
5883 $txt = get_strings(array('administration', 'settings', 'edit', 'name', 'enable', 'disable',
5884 'up', 'down', 'none'));
5885 $struninstall = get_string('uninstallplugin', 'admin');
5887 $txt->updown
= "$txt->up/$txt->down";
5889 $editors_available = editors_get_available();
5890 $active_editors = explode(',', $CFG->texteditors
);
5892 $active_editors = array_reverse($active_editors);
5893 foreach ($active_editors as $key=>$editor) {
5894 if (empty($editors_available[$editor])) {
5895 unset($active_editors[$key]);
5897 $name = $editors_available[$editor];
5898 unset($editors_available[$editor]);
5899 $editors_available[$editor] = $name;
5902 if (empty($active_editors)) {
5903 //$active_editors = array('textarea');
5905 $editors_available = array_reverse($editors_available, true);
5906 $return = $OUTPUT->heading(get_string('acteditorshhdr', 'editor'), 3, 'main', true);
5907 $return .= $OUTPUT->box_start('generalbox editorsui');
5909 $table = new html_table();
5910 $table->head
= array($txt->name
, $txt->enable
, $txt->updown
, $txt->settings
, $struninstall);
5911 $table->colclasses
= array('leftalign', 'centeralign', 'centeralign', 'centeralign');
5912 $table->id
= 'editormanagement';
5913 $table->attributes
['class'] = 'admintable generaltable';
5914 $table->data
= array();
5916 // iterate through auth plugins and add to the display table
5918 $editorcount = count($active_editors);
5919 $url = "editors.php?sesskey=" . sesskey();
5920 foreach ($editors_available as $editor => $name) {
5922 if (in_array($editor, $active_editors)) {
5923 $hideshow = "<a href=\"$url&action=disable&editor=$editor\">";
5924 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('t/hide') . "\" class=\"iconsmall\" alt=\"disable\" /></a>";
5925 // $hideshow = "<a href=\"$url&action=disable&editor=$editor\"><input type=\"checkbox\" checked /></a>";
5927 $displayname = "<span>$name</span>";
5930 $hideshow = "<a href=\"$url&action=enable&editor=$editor\">";
5931 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('t/show') . "\" class=\"iconsmall\" alt=\"enable\" /></a>";
5932 // $hideshow = "<a href=\"$url&action=enable&editor=$editor\"><input type=\"checkbox\" /></a>";
5934 $displayname = "<span class=\"dimmed_text\">$name</span>";
5937 // up/down link (only if auth is enabled)
5940 if ($updowncount > 1) {
5941 $updown .= "<a href=\"$url&action=up&editor=$editor\">";
5942 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/up') . "\" alt=\"up\" class=\"iconsmall\" /></a> ";
5945 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"iconsmall\" alt=\"\" /> ";
5947 if ($updowncount < $editorcount) {
5948 $updown .= "<a href=\"$url&action=down&editor=$editor\">";
5949 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/down') . "\" alt=\"down\" class=\"iconsmall\" /></a>";
5952 $updown .= "<img src=\"" . $OUTPUT->pix_url('spacer') . "\" class=\"iconsmall\" alt=\"\" />";
5958 if (file_exists($CFG->dirroot
.'/lib/editor/'.$editor.'/settings.php')) {
5959 $eurl = new moodle_url('/admin/settings.php', array('section'=>'editorsettings'.$editor));
5960 $settings = "<a href='$eurl'>{$txt->settings}</a>";
5965 if ($editor === 'textarea') {
5968 $uurl = new moodle_url('/admin/editors.php', array('action'=>'uninstall', 'editor'=>$editor, 'sesskey'=>sesskey()));
5969 $uninstall = html_writer
::link($uurl, $struninstall);
5972 // add a row to the table
5973 $table->data
[] =array($displayname, $hideshow, $updown, $settings, $uninstall);
5975 $return .= html_writer
::table($table);
5976 $return .= get_string('configeditorplugins', 'editor').'<br />'.get_string('tablenosave', 'admin');
5977 $return .= $OUTPUT->box_end();
5978 return highlight($query, $return);
5984 * Special class for license administration.
5986 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5988 class admin_setting_managelicenses
extends admin_setting
{
5990 * Calls parent::__construct with specific arguments
5992 public function __construct() {
5993 $this->nosave
= true;
5994 parent
::__construct('licensesui', get_string('licensesettings', 'admin'), '', '');
5998 * Always returns true, does nothing
6002 public function get_setting() {
6007 * Always returns true, does nothing
6011 public function get_defaultsetting() {
6016 * Always returns '', does not write anything
6018 * @return string Always returns ''
6020 public function write_setting($data) {
6021 // do not write any setting
6026 * Builds the XHTML to display the control
6028 * @param string $data Unused
6029 * @param string $query
6032 public function output_html($data, $query='') {
6033 global $CFG, $OUTPUT;
6034 require_once($CFG->libdir
. '/licenselib.php');
6035 $url = "licenses.php?sesskey=" . sesskey();
6038 $txt = get_strings(array('administration', 'settings', 'name', 'enable', 'disable', 'none'));
6039 $licenses = license_manager
::get_licenses();
6041 $return = $OUTPUT->heading(get_string('availablelicenses', 'admin'), 3, 'main', true);
6043 $return .= $OUTPUT->box_start('generalbox editorsui');
6045 $table = new html_table();
6046 $table->head
= array($txt->name
, $txt->enable
);
6047 $table->colclasses
= array('leftalign', 'centeralign');
6048 $table->id
= 'availablelicenses';
6049 $table->attributes
['class'] = 'admintable generaltable';
6050 $table->data
= array();
6052 foreach ($licenses as $value) {
6053 $displayname = html_writer
::link($value->source
, get_string($value->shortname
, 'license'), array('target'=>'_blank'));
6055 if ($value->enabled
== 1) {
6056 $hideshow = html_writer
::link($url.'&action=disable&license='.$value->shortname
,
6057 html_writer
::tag('img', '', array('src'=>$OUTPUT->pix_url('t/hide'), 'class'=>'iconsmall', 'alt'=>'disable')));
6059 $hideshow = html_writer
::link($url.'&action=enable&license='.$value->shortname
,
6060 html_writer
::tag('img', '', array('src'=>$OUTPUT->pix_url('t/show'), 'class'=>'iconsmall', 'alt'=>'enable')));
6063 if ($value->shortname
== $CFG->sitedefaultlicense
) {
6064 $displayname .= ' '.html_writer
::tag('img', '', array('src'=>$OUTPUT->pix_url('t/locked'), 'class'=>'iconsmall', 'alt'=>get_string('default'), 'title'=>get_string('default')));
6070 $table->data
[] =array($displayname, $hideshow);
6072 $return .= html_writer
::table($table);
6073 $return .= $OUTPUT->box_end();
6074 return highlight($query, $return);
6079 * Course formats manager. Allows to enable/disable formats and jump to settings
6081 class admin_setting_manageformats
extends admin_setting
{
6084 * Calls parent::__construct with specific arguments
6086 public function __construct() {
6087 $this->nosave
= true;
6088 parent
::__construct('formatsui', new lang_string('manageformats', 'core_admin'), '', '');
6092 * Always returns true
6096 public function get_setting() {
6101 * Always returns true
6105 public function get_defaultsetting() {
6110 * Always returns '' and doesn't write anything
6112 * @param mixed $data string or array, must not be NULL
6113 * @return string Always returns ''
6115 public function write_setting($data) {
6116 // do not write any setting
6121 * Search to find if Query is related to format plugin
6123 * @param string $query The string to search for
6124 * @return bool true for related false for not
6126 public function is_related($query) {
6127 if (parent
::is_related($query)) {
6130 $formats = plugin_manager
::instance()->get_plugins_of_type('format');
6131 foreach ($formats as $format) {
6132 if (strpos($format->component
, $query) !== false ||
6133 strpos(textlib
::strtolower($format->displayname
), $query) !== false) {
6141 * Return XHTML to display control
6143 * @param mixed $data Unused
6144 * @param string $query
6145 * @return string highlight
6147 public function output_html($data, $query='') {
6148 global $CFG, $OUTPUT;
6150 $return = $OUTPUT->heading(new lang_string('courseformats'), 3, 'main');
6151 $return .= $OUTPUT->box_start('generalbox formatsui');
6153 $formats = plugin_manager
::instance()->get_plugins_of_type('format');
6156 $txt = get_strings(array('settings', 'name', 'enable', 'disable', 'up', 'down', 'default', 'delete'));
6157 $txt->updown
= "$txt->up/$txt->down";
6159 $table = new html_table();
6160 $table->head
= array($txt->name
, $txt->enable
, $txt->updown
, $txt->delete
, $txt->settings
);
6161 $table->align
= array('left', 'center', 'center', 'center', 'center');
6162 $table->width
= '90%';
6163 $table->attributes
['class'] = 'manageformattable generaltable';
6164 $table->data
= array();
6167 $defaultformat = get_config('moodlecourse', 'format');
6168 $spacer = $OUTPUT->pix_icon('spacer', '', 'moodle', array('class' => 'iconsmall'));
6169 foreach ($formats as $format) {
6170 $url = new moodle_url('/admin/courseformats.php',
6171 array('sesskey' => sesskey(), 'format' => $format->name
));
6173 if ($format->is_enabled()) {
6174 $strformatname = html_writer
::tag('span', $format->displayname
);
6175 if ($defaultformat === $format->name
) {
6176 $hideshow = $txt->default;
6178 $hideshow = html_writer
::link($url->out(false, array('action' => 'disable')),
6179 $OUTPUT->pix_icon('t/hide', $txt->disable
, 'moodle', array('class' => 'iconsmall')));
6182 $strformatname = html_writer
::tag('span', $format->displayname
, array('class' => 'dimmed_text'));
6183 $hideshow = html_writer
::link($url->out(false, array('action' => 'enable')),
6184 $OUTPUT->pix_icon('t/show', $txt->enable
, 'moodle', array('class' => 'iconsmall')));
6188 $updown .= html_writer
::link($url->out(false, array('action' => 'up')),
6189 $OUTPUT->pix_icon('t/up', $txt->up
, 'moodle', array('class' => 'iconsmall'))). '';
6193 if ($cnt < count($formats) - 1) {
6194 $updown .= ' '.html_writer
::link($url->out(false, array('action' => 'down')),
6195 $OUTPUT->pix_icon('t/down', $txt->down
, 'moodle', array('class' => 'iconsmall')));
6201 if ($format->get_settings_url()) {
6202 $settings = html_writer
::link($format->get_settings_url(), $txt->settings
);
6205 if ($defaultformat !== $format->name
) {
6206 $uninstall = html_writer
::link($format->get_uninstall_url(), $txt->delete
);
6208 $table->data
[] =array($strformatname, $hideshow, $updown, $uninstall, $settings);
6210 $return .= html_writer
::table($table);
6211 $link = html_writer
::link(new moodle_url('/admin/settings.php', array('section' => 'coursesettings')), new lang_string('coursesettings'));
6212 $return .= html_writer
::tag('p', get_string('manageformatsgotosettings', 'admin', $link));
6213 $return .= $OUTPUT->box_end();
6214 return highlight($query, $return);
6219 * Special class for filter administration.
6221 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
6223 class admin_page_managefilters
extends admin_externalpage
{
6225 * Calls parent::__construct with specific arguments
6227 public function __construct() {
6229 parent
::__construct('managefilters', get_string('filtersettings', 'admin'), "$CFG->wwwroot/$CFG->admin/filters.php");
6233 * Searches all installed filters for specified filter
6235 * @param string $query The filter(string) to search for
6236 * @param string $query
6238 public function search($query) {
6240 if ($result = parent
::search($query)) {
6245 $filternames = filter_get_all_installed();
6246 foreach ($filternames as $path => $strfiltername) {
6247 if (strpos(textlib
::strtolower($strfiltername), $query) !== false) {
6251 if (strpos($path, $query) !== false) {
6258 $result = new stdClass
;
6259 $result->page
= $this;
6260 $result->settings
= array();
6261 return array($this->name
=> $result);
6270 * Initialise admin page - this function does require login and permission
6271 * checks specified in page definition.
6273 * This function must be called on each admin page before other code.
6275 * @global moodle_page $PAGE
6277 * @param string $section name of page
6278 * @param string $extrabutton extra HTML that is added after the blocks editing on/off button.
6279 * @param array $extraurlparams an array paramname => paramvalue, or parameters that need to be
6280 * added to the turn blocks editing on/off form, so this page reloads correctly.
6281 * @param string $actualurl if the actual page being viewed is not the normal one for this
6282 * page (e.g. admin/roles/allow.php, instead of admin/roles/manage.php, you can pass the alternate URL here.
6283 * @param array $options Additional options that can be specified for page setup.
6284 * pagelayout - This option can be used to set a specific pagelyaout, admin is default.
6286 function admin_externalpage_setup($section, $extrabutton = '', array $extraurlparams = null, $actualurl = '', array $options = array()) {
6287 global $CFG, $PAGE, $USER, $SITE, $OUTPUT;
6289 $PAGE->set_context(null); // hack - set context to something, by default to system context
6294 if (!empty($options['pagelayout'])) {
6295 // A specific page layout has been requested.
6296 $PAGE->set_pagelayout($options['pagelayout']);
6297 } else if ($section === 'upgradesettings') {
6298 $PAGE->set_pagelayout('maintenance');
6300 $PAGE->set_pagelayout('admin');
6303 $adminroot = admin_get_root(false, false); // settings not required for external pages
6304 $extpage = $adminroot->locate($section, true);
6306 if (empty($extpage) or !($extpage instanceof admin_externalpage
)) {
6307 // The requested section isn't in the admin tree
6308 // It could be because the user has inadequate capapbilities or because the section doesn't exist
6309 if (!has_capability('moodle/site:config', context_system
::instance())) {
6310 // The requested section could depend on a different capability
6311 // but most likely the user has inadequate capabilities
6312 print_error('accessdenied', 'admin');
6314 print_error('sectionerror', 'admin', "$CFG->wwwroot/$CFG->admin/");
6318 // this eliminates our need to authenticate on the actual pages
6319 if (!$extpage->check_access()) {
6320 print_error('accessdenied', 'admin');
6324 // $PAGE->set_extra_button($extrabutton); TODO
6327 $actualurl = $extpage->url
;
6330 $PAGE->set_url($actualurl, $extraurlparams);
6331 if (strpos($PAGE->pagetype
, 'admin-') !== 0) {
6332 $PAGE->set_pagetype('admin-' . $PAGE->pagetype
);
6335 if (empty($SITE->fullname
) ||
empty($SITE->shortname
)) {
6336 // During initial install.
6337 $strinstallation = get_string('installation', 'install');
6338 $strsettings = get_string('settings');
6339 $PAGE->navbar
->add($strsettings);
6340 $PAGE->set_title($strinstallation);
6341 $PAGE->set_heading($strinstallation);
6342 $PAGE->set_cacheable(false);
6346 // Locate the current item on the navigation and make it active when found.
6347 $path = $extpage->path
;
6348 $node = $PAGE->settingsnav
;
6349 while ($node && count($path) > 0) {
6350 $node = $node->get(array_pop($path));
6353 $node->make_active();
6357 $adminediting = optional_param('adminedit', -1, PARAM_BOOL
);
6358 if ($PAGE->user_allowed_editing() && $adminediting != -1) {
6359 $USER->editing
= $adminediting;
6362 $visiblepathtosection = array_reverse($extpage->visiblepath
);
6364 if ($PAGE->user_allowed_editing()) {
6365 if ($PAGE->user_is_editing()) {
6366 $caption = get_string('blockseditoff');
6367 $url = new moodle_url($PAGE->url
, array('adminedit'=>'0'));
6369 $caption = get_string('blocksediton');
6370 $url = new moodle_url($PAGE->url
, array('adminedit'=>'1'));
6372 $PAGE->set_button($OUTPUT->single_button($url, $caption, 'get'));
6375 $PAGE->set_title("$SITE->shortname: " . implode(": ", $visiblepathtosection));
6376 $PAGE->set_heading($SITE->fullname
);
6378 // prevent caching in nav block
6379 $PAGE->navigation
->clear_cache();
6383 * Returns the reference to admin tree root
6385 * @return object admin_root object
6387 function admin_get_root($reload=false, $requirefulltree=true) {
6388 global $CFG, $DB, $OUTPUT;
6390 static $ADMIN = NULL;
6392 if (is_null($ADMIN)) {
6393 // create the admin tree!
6394 $ADMIN = new admin_root($requirefulltree);
6397 if ($reload or ($requirefulltree and !$ADMIN->fulltree
)) {
6398 $ADMIN->purge_children($requirefulltree);
6401 if (!$ADMIN->loaded
) {
6402 // we process this file first to create categories first and in correct order
6403 require($CFG->dirroot
.'/'.$CFG->admin
.'/settings/top.php');
6405 // now we process all other files in admin/settings to build the admin tree
6406 foreach (glob($CFG->dirroot
.'/'.$CFG->admin
.'/settings/*.php') as $file) {
6407 if ($file == $CFG->dirroot
.'/'.$CFG->admin
.'/settings/top.php') {
6410 if ($file == $CFG->dirroot
.'/'.$CFG->admin
.'/settings/plugins.php') {
6411 // plugins are loaded last - they may insert pages anywhere
6416 require($CFG->dirroot
.'/'.$CFG->admin
.'/settings/plugins.php');
6418 $ADMIN->loaded
= true;
6424 /// settings utility functions
6427 * This function applies default settings.
6429 * @param object $node, NULL means complete tree, null by default
6430 * @param bool $unconditional if true overrides all values with defaults, null buy default
6432 function admin_apply_default_settings($node=NULL, $unconditional=true) {
6435 if (is_null($node)) {
6436 $node = admin_get_root(true, true);
6439 if ($node instanceof admin_category
) {
6440 $entries = array_keys($node->children
);
6441 foreach ($entries as $entry) {
6442 admin_apply_default_settings($node->children
[$entry], $unconditional);
6445 } else if ($node instanceof admin_settingpage
) {
6446 foreach ($node->settings
as $setting) {
6447 if (!$unconditional and !is_null($setting->get_setting())) {
6448 //do not override existing defaults
6451 $defaultsetting = $setting->get_defaultsetting();
6452 if (is_null($defaultsetting)) {
6453 // no value yet - default maybe applied after admin user creation or in upgradesettings
6456 $setting->write_setting($defaultsetting);
6462 * Store changed settings, this function updates the errors variable in $ADMIN
6464 * @param object $formdata from form
6465 * @return int number of changed settings
6467 function admin_write_settings($formdata) {
6468 global $CFG, $SITE, $DB;
6470 $olddbsessions = !empty($CFG->dbsessions
);
6471 $formdata = (array)$formdata;
6474 foreach ($formdata as $fullname=>$value) {
6475 if (strpos($fullname, 's_') !== 0) {
6476 continue; // not a config value
6478 $data[$fullname] = $value;
6481 $adminroot = admin_get_root();
6482 $settings = admin_find_write_settings($adminroot, $data);
6485 foreach ($settings as $fullname=>$setting) {
6486 /** @var $setting admin_setting */
6487 $original = $setting->get_setting();
6488 $error = $setting->write_setting($data[$fullname]);
6489 if ($error !== '') {
6490 $adminroot->errors
[$fullname] = new stdClass();
6491 $adminroot->errors
[$fullname]->data
= $data[$fullname];
6492 $adminroot->errors
[$fullname]->id
= $setting->get_id();
6493 $adminroot->errors
[$fullname]->error
= $error;
6495 if ($setting->post_write_settings($original)) {
6500 if ($olddbsessions != !empty($CFG->dbsessions
)) {
6504 // Now update $SITE - just update the fields, in case other people have a
6505 // a reference to it (e.g. $PAGE, $COURSE).
6506 $newsite = $DB->get_record('course', array('id'=>$SITE->id
));
6507 foreach (get_object_vars($newsite) as $field => $value) {
6508 $SITE->$field = $value;
6511 // now reload all settings - some of them might depend on the changed
6512 admin_get_root(true);
6517 * Internal recursive function - finds all settings from submitted form
6519 * @param object $node Instance of admin_category, or admin_settingpage
6520 * @param array $data
6523 function admin_find_write_settings($node, $data) {
6530 if ($node instanceof admin_category
) {
6531 $entries = array_keys($node->children
);
6532 foreach ($entries as $entry) {
6533 $return = array_merge($return, admin_find_write_settings($node->children
[$entry], $data));
6536 } else if ($node instanceof admin_settingpage
) {
6537 foreach ($node->settings
as $setting) {
6538 $fullname = $setting->get_full_name();
6539 if (array_key_exists($fullname, $data)) {
6540 $return[$fullname] = $setting;
6550 * Internal function - prints the search results
6552 * @param string $query String to search for
6553 * @return string empty or XHTML
6555 function admin_search_settings_html($query) {
6556 global $CFG, $OUTPUT;
6558 if (textlib
::strlen($query) < 2) {
6561 $query = textlib
::strtolower($query);
6563 $adminroot = admin_get_root();
6564 $findings = $adminroot->search($query);
6566 $savebutton = false;
6568 foreach ($findings as $found) {
6569 $page = $found->page
;
6570 $settings = $found->settings
;
6571 if ($page->is_hidden()) {
6572 // hidden pages are not displayed in search results
6575 if ($page instanceof admin_externalpage
) {
6576 $return .= $OUTPUT->heading(get_string('searchresults','admin').' - <a href="'.$page->url
.'">'.highlight($query, $page->visiblename
).'</a>', 2, 'main');
6577 } else if ($page instanceof admin_settingpage
) {
6578 $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');
6582 if (!empty($settings)) {
6583 $return .= '<fieldset class="adminsettings">'."\n";
6584 foreach ($settings as $setting) {
6585 if (empty($setting->nosave
)) {
6588 $return .= '<div class="clearer"><!-- --></div>'."\n";
6589 $fullname = $setting->get_full_name();
6590 if (array_key_exists($fullname, $adminroot->errors
)) {
6591 $data = $adminroot->errors
[$fullname]->data
;
6593 $data = $setting->get_setting();
6594 // do not use defaults if settings not available - upgradesettings handles the defaults!
6596 $return .= $setting->output_html($data, $query);
6598 $return .= '</fieldset>';
6603 $return .= '<div class="form-buttons"><input class="form-submit" type="submit" value="'.get_string('savechanges','admin').'" /></div>';
6610 * Internal function - returns arrays of html pages with uninitialised settings
6612 * @param object $node Instance of admin_category or admin_settingpage
6615 function admin_output_new_settings_by_page($node) {
6619 if ($node instanceof admin_category
) {
6620 $entries = array_keys($node->children
);
6621 foreach ($entries as $entry) {
6622 $return +
= admin_output_new_settings_by_page($node->children
[$entry]);
6625 } else if ($node instanceof admin_settingpage
) {
6626 $newsettings = array();
6627 foreach ($node->settings
as $setting) {
6628 if (is_null($setting->get_setting())) {
6629 $newsettings[] = $setting;
6632 if (count($newsettings) > 0) {
6633 $adminroot = admin_get_root();
6634 $page = $OUTPUT->heading(get_string('upgradesettings','admin').' - '.$node->visiblename
, 2, 'main');
6635 $page .= '<fieldset class="adminsettings">'."\n";
6636 foreach ($newsettings as $setting) {
6637 $fullname = $setting->get_full_name();
6638 if (array_key_exists($fullname, $adminroot->errors
)) {
6639 $data = $adminroot->errors
[$fullname]->data
;
6641 $data = $setting->get_setting();
6642 if (is_null($data)) {
6643 $data = $setting->get_defaultsetting();
6646 $page .= '<div class="clearer"><!-- --></div>'."\n";
6647 $page .= $setting->output_html($data);
6649 $page .= '</fieldset>';
6650 $return[$node->name
] = $page;
6658 * Format admin settings
6660 * @param object $setting
6661 * @param string $title label element
6662 * @param string $form form fragment, html code - not highlighted automatically
6663 * @param string $description
6664 * @param bool $label link label to id, true by default
6665 * @param string $warning warning text
6666 * @param sting $defaultinfo defaults info, null means nothing, '' is converted to "Empty" string, defaults to null
6667 * @param string $query search query to be highlighted
6668 * @return string XHTML
6670 function format_admin_setting($setting, $title='', $form='', $description='', $label=true, $warning='', $defaultinfo=NULL, $query='') {
6673 $name = empty($setting->plugin
) ?
$setting->name
: "$setting->plugin | $setting->name";
6674 $fullname = $setting->get_full_name();
6676 // sometimes the id is not id_s_name, but id_s_name_m or something, and this does not validate
6678 $labelfor = 'for = "'.$setting->get_id().'"';
6684 if (empty($setting->plugin
)) {
6685 if (array_key_exists($setting->name
, $CFG->config_php_settings
)) {
6686 $override = '<div class="form-overridden">'.get_string('configoverride', 'admin').'</div>';
6689 if (array_key_exists($setting->plugin
, $CFG->forced_plugin_settings
) and array_key_exists($setting->name
, $CFG->forced_plugin_settings
[$setting->plugin
])) {
6690 $override = '<div class="form-overridden">'.get_string('configoverride', 'admin').'</div>';
6694 if ($warning !== '') {
6695 $warning = '<div class="form-warning">'.$warning.'</div>';
6698 if (is_null($defaultinfo)) {
6701 if ($defaultinfo === '') {
6702 $defaultinfo = get_string('emptysettingvalue', 'admin');
6704 $defaultinfo = highlight($query, nl2br(s($defaultinfo)));
6705 $defaultinfo = '<div class="form-defaultinfo">'.get_string('defaultsettinginfo', 'admin', $defaultinfo).'</div>';
6710 <div class="form-item clearfix" id="admin-'.$setting->name
.'">
6711 <div class="form-label">
6712 <label '.$labelfor.'>'.highlightfast($query, $title).$override.$warning.'</label>
6713 <span class="form-shortname">'.highlightfast($query, $name).'</span>
6715 <div class="form-setting">'.$form.$defaultinfo.'</div>
6716 <div class="form-description">'.highlight($query, markdown_to_html($description)).'</div>
6719 $adminroot = admin_get_root();
6720 if (array_key_exists($fullname, $adminroot->errors
)) {
6721 $str = '<fieldset class="error"><legend>'.$adminroot->errors
[$fullname]->error
.'</legend>'.$str.'</fieldset>';
6728 * Based on find_new_settings{@link ()} in upgradesettings.php
6729 * Looks to find any admin settings that have not been initialized. Returns 1 if it finds any.
6731 * @param object $node Instance of admin_category, or admin_settingpage
6732 * @return boolean true if any settings haven't been initialised, false if they all have
6734 function any_new_admin_settings($node) {
6736 if ($node instanceof admin_category
) {
6737 $entries = array_keys($node->children
);
6738 foreach ($entries as $entry) {
6739 if (any_new_admin_settings($node->children
[$entry])) {
6744 } else if ($node instanceof admin_settingpage
) {
6745 foreach ($node->settings
as $setting) {
6746 if ($setting->get_setting() === NULL) {
6756 * Moved from admin/replace.php so that we can use this in cron
6758 * @param string $search string to look for
6759 * @param string $replace string to replace
6760 * @return bool success or fail
6762 function db_replace($search, $replace) {
6763 global $DB, $CFG, $OUTPUT;
6765 // TODO: this is horrible hack, we should do whitelisting and each plugin should be responsible for proper replacing...
6766 $skiptables = array('config', 'config_plugins', 'config_log', 'upgrade_log', 'log',
6767 'filter_config', 'sessions', 'events_queue', 'repository_instance_config',
6768 'block_instances', '');
6770 // Turn off time limits, sometimes upgrades can be slow.
6773 if (!$tables = $DB->get_tables() ) { // No tables yet at all.
6776 foreach ($tables as $table) {
6778 if (in_array($table, $skiptables)) { // Don't process these
6782 if ($columns = $DB->get_columns($table)) {
6783 $DB->set_debug(true);
6784 foreach ($columns as $column => $data) {
6785 if (in_array($data->meta_type
, array('C', 'X'))) { // Text stuff only
6786 //TODO: this should be definitively moved to DML driver to do the actual replace, this is not going to work for MSSQL and Oracle...
6787 $DB->execute("UPDATE {".$table."} SET $column = REPLACE($column, ?, ?)", array($search, $replace));
6790 $DB->set_debug(false);
6794 // delete modinfo caches
6795 rebuild_course_cache(0, true);
6797 // TODO: we should ask all plugins to do the search&replace, for now let's do only blocks...
6798 $blocks = get_plugin_list('block');
6799 foreach ($blocks as $blockname=>$fullblock) {
6800 if ($blockname === 'NEWBLOCK') { // Someone has unzipped the template, ignore it
6804 if (!is_readable($fullblock.'/lib.php')) {
6808 $function = 'block_'.$blockname.'_global_db_replace';
6809 include_once($fullblock.'/lib.php');
6810 if (!function_exists($function)) {
6814 echo $OUTPUT->notification("Replacing in $blockname blocks...", 'notifysuccess');
6815 $function($search, $replace);
6816 echo $OUTPUT->notification("...finished", 'notifysuccess');
6823 * Manage repository settings
6825 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
6827 class admin_setting_managerepository
extends admin_setting
{
6832 * calls parent::__construct with specific arguments
6834 public function __construct() {
6836 parent
::__construct('managerepository', get_string('manage', 'repository'), '', '');
6837 $this->baseurl
= $CFG->wwwroot
. '/' . $CFG->admin
. '/repository.php?sesskey=' . sesskey();
6841 * Always returns true, does nothing
6845 public function get_setting() {
6850 * Always returns true does nothing
6854 public function get_defaultsetting() {
6859 * Always returns s_managerepository
6861 * @return string Always return 's_managerepository'
6863 public function get_full_name() {
6864 return 's_managerepository';
6868 * Always returns '' doesn't do anything
6870 public function write_setting($data) {
6871 $url = $this->baseurl
. '&new=' . $data;
6874 // Should not use redirect and exit here
6875 // Find a better way to do this.
6881 * Searches repository plugins for one that matches $query
6883 * @param string $query The string to search for
6884 * @return bool true if found, false if not
6886 public function is_related($query) {
6887 if (parent
::is_related($query)) {
6891 $repositories= get_plugin_list('repository');
6892 foreach ($repositories as $p => $dir) {
6893 if (strpos($p, $query) !== false) {
6897 foreach (repository
::get_types() as $instance) {
6898 $title = $instance->get_typename();
6899 if (strpos(textlib
::strtolower($title), $query) !== false) {
6907 * Helper function that generates a moodle_url object
6908 * relevant to the repository
6911 function repository_action_url($repository) {
6912 return new moodle_url($this->baseurl
, array('sesskey'=>sesskey(), 'repos'=>$repository));
6916 * Builds XHTML to display the control
6918 * @param string $data Unused
6919 * @param string $query
6920 * @return string XHTML
6922 public function output_html($data, $query='') {
6923 global $CFG, $USER, $OUTPUT;
6925 // Get strings that are used
6926 $strshow = get_string('on', 'repository');
6927 $strhide = get_string('off', 'repository');
6928 $strdelete = get_string('disabled', 'repository');
6930 $actionchoicesforexisting = array(
6933 'delete' => $strdelete
6936 $actionchoicesfornew = array(
6937 'newon' => $strshow,
6938 'newoff' => $strhide,
6939 'delete' => $strdelete
6943 $return .= $OUTPUT->box_start('generalbox');
6945 // Set strings that are used multiple times
6946 $settingsstr = get_string('settings');
6947 $disablestr = get_string('disable');
6949 // Table to list plug-ins
6950 $table = new html_table();
6951 $table->head
= array(get_string('name'), get_string('isactive', 'repository'), get_string('order'), $settingsstr);
6952 $table->align
= array('left', 'center', 'center', 'center', 'center');
6953 $table->data
= array();
6955 // Get list of used plug-ins
6956 $repositorytypes = repository
::get_types();
6957 if (!empty($repositorytypes)) {
6958 // Array to store plugins being used
6959 $alreadyplugins = array();
6960 $totalrepositorytypes = count($repositorytypes);
6962 foreach ($repositorytypes as $i) {
6964 $typename = $i->get_typename();
6965 // Display edit link only if you can config the type or if it has multiple instances (e.g. has instance config)
6966 $typeoptionnames = repository
::static_function($typename, 'get_type_option_names');
6967 $instanceoptionnames = repository
::static_function($typename, 'get_instance_option_names');
6969 if (!empty($typeoptionnames) ||
!empty($instanceoptionnames)) {
6970 // Calculate number of instances in order to display them for the Moodle administrator
6971 if (!empty($instanceoptionnames)) {
6973 $params['context'] = array(get_system_context());
6974 $params['onlyvisible'] = false;
6975 $params['type'] = $typename;
6976 $admininstancenumber = count(repository
::static_function($typename, 'get_instances', $params));
6978 $admininstancenumbertext = get_string('instancesforsite', 'repository', $admininstancenumber);
6979 $params['context'] = array();
6980 $instances = repository
::static_function($typename, 'get_instances', $params);
6981 $courseinstances = array();
6982 $userinstances = array();
6984 foreach ($instances as $instance) {
6985 $repocontext = context
::instance_by_id($instance->instance
->contextid
);
6986 if ($repocontext->contextlevel
== CONTEXT_COURSE
) {
6987 $courseinstances[] = $instance;
6988 } else if ($repocontext->contextlevel
== CONTEXT_USER
) {
6989 $userinstances[] = $instance;
6993 $instancenumber = count($courseinstances);
6994 $courseinstancenumbertext = get_string('instancesforcourses', 'repository', $instancenumber);
6996 // user private instances
6997 $instancenumber = count($userinstances);
6998 $userinstancenumbertext = get_string('instancesforusers', 'repository', $instancenumber);
7000 $admininstancenumbertext = "";
7001 $courseinstancenumbertext = "";
7002 $userinstancenumbertext = "";
7005 $settings .= '<a href="' . $this->baseurl
. '&action=edit&repos=' . $typename . '">' . $settingsstr .'</a>';
7007 $settings .= $OUTPUT->container_start('mdl-left');
7008 $settings .= '<br/>';
7009 $settings .= $admininstancenumbertext;
7010 $settings .= '<br/>';
7011 $settings .= $courseinstancenumbertext;
7012 $settings .= '<br/>';
7013 $settings .= $userinstancenumbertext;
7014 $settings .= $OUTPUT->container_end();
7016 // Get the current visibility
7017 if ($i->get_visible()) {
7018 $currentaction = 'show';
7020 $currentaction = 'hide';
7023 $select = new single_select($this->repository_action_url($typename, 'repos'), 'action', $actionchoicesforexisting, $currentaction, null, 'applyto' . basename($typename));
7025 // Display up/down link
7027 // Should be done with CSS instead.
7028 $spacer = $OUTPUT->spacer(array('height' => 15, 'width' => 15, 'class' => 'smallicon'));
7030 if ($updowncount > 1) {
7031 $updown .= "<a href=\"$this->baseurl&action=moveup&repos=".$typename."\">";
7032 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/up') . "\" alt=\"up\" class=\"iconsmall\" /></a> ";
7037 if ($updowncount < $totalrepositorytypes) {
7038 $updown .= "<a href=\"$this->baseurl&action=movedown&repos=".$typename."\">";
7039 $updown .= "<img src=\"" . $OUTPUT->pix_url('t/down') . "\" alt=\"down\" class=\"iconsmall\" /></a>";
7047 $table->data
[] = array($i->get_readablename(), $OUTPUT->render($select), $updown, $settings);
7049 if (!in_array($typename, $alreadyplugins)) {
7050 $alreadyplugins[] = $typename;
7055 // Get all the plugins that exist on disk
7056 $plugins = get_plugin_list('repository');
7057 if (!empty($plugins)) {
7058 foreach ($plugins as $plugin => $dir) {
7059 // Check that it has not already been listed
7060 if (!in_array($plugin, $alreadyplugins)) {
7061 $select = new single_select($this->repository_action_url($plugin, 'repos'), 'action', $actionchoicesfornew, 'delete', null, 'applyto' . basename($plugin));
7062 $table->data
[] = array(get_string('pluginname', 'repository_'.$plugin), $OUTPUT->render($select), '', '');
7067 $return .= html_writer
::table($table);
7068 $return .= $OUTPUT->box_end();
7069 return highlight($query, $return);
7074 * Special checkbox for enable mobile web service
7075 * If enable then we store the service id of the mobile service into config table
7076 * If disable then we unstore the service id from the config table
7078 class admin_setting_enablemobileservice
extends admin_setting_configcheckbox
{
7080 /** @var boolean True means that the capability 'webservice/xmlrpc:use' is set for authenticated user role */
7082 /** @var boolean True means that the capability 'webservice/rest:use' is set for authenticated user role */
7086 * Return true if Authenticated user role has the capability 'webservice/xmlrpc:use' and 'webservice/rest:use', otherwise false.
7090 private function is_protocol_cap_allowed() {
7093 // We keep xmlrpc enabled for backward compatibility.
7094 // If the $this->xmlrpcuse variable is not set, it needs to be set.
7095 if (empty($this->xmlrpcuse
) and $this->xmlrpcuse
!==false) {
7097 $params['permission'] = CAP_ALLOW
;
7098 $params['roleid'] = $CFG->defaultuserroleid
;
7099 $params['capability'] = 'webservice/xmlrpc:use';
7100 $this->xmlrpcuse
= $DB->record_exists('role_capabilities', $params);
7103 // If the $this->restuse variable is not set, it needs to be set.
7104 if (empty($this->restuse
) and $this->restuse
!==false) {
7106 $params['permission'] = CAP_ALLOW
;
7107 $params['roleid'] = $CFG->defaultuserroleid
;
7108 $params['capability'] = 'webservice/rest:use';
7109 $this->restuse
= $DB->record_exists('role_capabilities', $params);
7112 return ($this->xmlrpcuse
&& $this->restuse
);
7116 * Set the 'webservice/xmlrpc:use'/'webservice/rest:use' to the Authenticated user role (allow or not)
7117 * @param type $status true to allow, false to not set
7119 private function set_protocol_cap($status) {
7121 if ($status and !$this->is_protocol_cap_allowed()) {
7122 //need to allow the cap
7123 $permission = CAP_ALLOW
;
7125 } else if (!$status and $this->is_protocol_cap_allowed()){
7126 //need to disallow the cap
7127 $permission = CAP_INHERIT
;
7130 if (!empty($assign)) {
7131 $systemcontext = get_system_context();
7132 assign_capability('webservice/xmlrpc:use', $permission, $CFG->defaultuserroleid
, $systemcontext->id
, true);
7133 assign_capability('webservice/rest:use', $permission, $CFG->defaultuserroleid
, $systemcontext->id
, true);
7138 * Builds XHTML to display the control.
7139 * The main purpose of this overloading is to display a warning when https
7140 * is not supported by the server
7141 * @param string $data Unused
7142 * @param string $query
7143 * @return string XHTML
7145 public function output_html($data, $query='') {
7146 global $CFG, $OUTPUT;
7147 $html = parent
::output_html($data, $query);
7149 if ((string)$data === $this->yes
) {
7150 require_once($CFG->dirroot
. "/lib/filelib.php");
7152 $httpswwwroot = str_replace('http:', 'https:', $CFG->wwwroot
); //force https url
7153 $curl->head($httpswwwroot . "/login/index.php");
7154 $info = $curl->get_info();
7155 if (empty($info['http_code']) or ($info['http_code'] >= 400)) {
7156 $html .= $OUTPUT->notification(get_string('nohttpsformobilewarning', 'admin'));
7164 * Retrieves the current setting using the objects name
7168 public function get_setting() {
7171 // For install cli script, $CFG->defaultuserroleid is not set so return 0
7172 // Or if web services aren't enabled this can't be,
7173 if (empty($CFG->defaultuserroleid
) ||
empty($CFG->enablewebservices
)) {
7177 require_once($CFG->dirroot
. '/webservice/lib.php');
7178 $webservicemanager = new webservice();
7179 $mobileservice = $webservicemanager->get_external_service_by_shortname(MOODLE_OFFICIAL_MOBILE_SERVICE
);
7180 if ($mobileservice->enabled
and $this->is_protocol_cap_allowed()) {
7181 return $this->config_read($this->name
); //same as returning 1
7188 * Save the selected setting
7190 * @param string $data The selected site
7191 * @return string empty string or error message
7193 public function write_setting($data) {
7196 //for install cli script, $CFG->defaultuserroleid is not set so do nothing
7197 if (empty($CFG->defaultuserroleid
)) {
7201 $servicename = MOODLE_OFFICIAL_MOBILE_SERVICE
;
7203 require_once($CFG->dirroot
. '/webservice/lib.php');
7204 $webservicemanager = new webservice();
7206 $updateprotocol = false;
7207 if ((string)$data === $this->yes
) {
7208 //code run when enable mobile web service
7209 //enable web service systeme if necessary
7210 set_config('enablewebservices', true);
7212 //enable mobile service
7213 $mobileservice = $webservicemanager->get_external_service_by_shortname(MOODLE_OFFICIAL_MOBILE_SERVICE
);
7214 $mobileservice->enabled
= 1;
7215 $webservicemanager->update_external_service($mobileservice);
7217 //enable xml-rpc server
7218 $activeprotocols = empty($CFG->webserviceprotocols
) ?
array() : explode(',', $CFG->webserviceprotocols
);
7220 if (!in_array('xmlrpc', $activeprotocols)) {
7221 $activeprotocols[] = 'xmlrpc';
7222 $updateprotocol = true;
7225 if (!in_array('rest', $activeprotocols)) {
7226 $activeprotocols[] = 'rest';
7227 $updateprotocol = true;
7230 if ($updateprotocol) {
7231 set_config('webserviceprotocols', implode(',', $activeprotocols));
7234 //allow xml-rpc:use capability for authenticated user
7235 $this->set_protocol_cap(true);
7238 //disable web service system if no other services are enabled
7239 $otherenabledservices = $DB->get_records_select('external_services',
7240 'enabled = :enabled AND (shortname != :shortname OR shortname IS NULL)', array('enabled' => 1,
7241 'shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE
));
7242 if (empty($otherenabledservices)) {
7243 set_config('enablewebservices', false);
7245 //also disable xml-rpc server
7246 $activeprotocols = empty($CFG->webserviceprotocols
) ?
array() : explode(',', $CFG->webserviceprotocols
);
7247 $protocolkey = array_search('xmlrpc', $activeprotocols);
7248 if ($protocolkey !== false) {
7249 unset($activeprotocols[$protocolkey]);
7250 $updateprotocol = true;
7253 $protocolkey = array_search('rest', $activeprotocols);
7254 if ($protocolkey !== false) {
7255 unset($activeprotocols[$protocolkey]);
7256 $updateprotocol = true;
7259 if ($updateprotocol) {
7260 set_config('webserviceprotocols', implode(',', $activeprotocols));
7263 //disallow xml-rpc:use capability for authenticated user
7264 $this->set_protocol_cap(false);
7267 //disable the mobile service
7268 $mobileservice = $webservicemanager->get_external_service_by_shortname(MOODLE_OFFICIAL_MOBILE_SERVICE
);
7269 $mobileservice->enabled
= 0;
7270 $webservicemanager->update_external_service($mobileservice);
7273 return (parent
::write_setting($data));
7278 * Special class for management of external services
7280 * @author Petr Skoda (skodak)
7282 class admin_setting_manageexternalservices
extends admin_setting
{
7284 * Calls parent::__construct with specific arguments
7286 public function __construct() {
7287 $this->nosave
= true;
7288 parent
::__construct('webservicesui', get_string('externalservices', 'webservice'), '', '');
7292 * Always returns true, does nothing
7296 public function get_setting() {
7301 * Always returns true, does nothing
7305 public function get_defaultsetting() {
7310 * Always returns '', does not write anything
7312 * @return string Always returns ''
7314 public function write_setting($data) {
7315 // do not write any setting
7320 * Checks if $query is one of the available external services
7322 * @param string $query The string to search for
7323 * @return bool Returns true if found, false if not
7325 public function is_related($query) {
7328 if (parent
::is_related($query)) {
7332 $services = $DB->get_records('external_services', array(), 'id, name');
7333 foreach ($services as $service) {
7334 if (strpos(textlib
::strtolower($service->name
), $query) !== false) {
7342 * Builds the XHTML to display the control
7344 * @param string $data Unused
7345 * @param string $query
7348 public function output_html($data, $query='') {
7349 global $CFG, $OUTPUT, $DB;
7352 $stradministration = get_string('administration');
7353 $stredit = get_string('edit');
7354 $strservice = get_string('externalservice', 'webservice');
7355 $strdelete = get_string('delete');
7356 $strplugin = get_string('plugin', 'admin');
7357 $stradd = get_string('add');
7358 $strfunctions = get_string('functions', 'webservice');
7359 $strusers = get_string('users');
7360 $strserviceusers = get_string('serviceusers', 'webservice');
7362 $esurl = "$CFG->wwwroot/$CFG->admin/webservice/service.php";
7363 $efurl = "$CFG->wwwroot/$CFG->admin/webservice/service_functions.php";
7364 $euurl = "$CFG->wwwroot/$CFG->admin/webservice/service_users.php";
7366 // built in services
7367 $services = $DB->get_records_select('external_services', 'component IS NOT NULL', null, 'name');
7369 if (!empty($services)) {
7370 $return .= $OUTPUT->heading(get_string('servicesbuiltin', 'webservice'), 3, 'main');
7374 $table = new html_table();
7375 $table->head
= array($strservice, $strplugin, $strfunctions, $strusers, $stredit);
7376 $table->colclasses
= array('leftalign service', 'leftalign plugin', 'centeralign functions', 'centeralign users', 'centeralign ');
7377 $table->id
= 'builtinservices';
7378 $table->attributes
['class'] = 'admintable externalservices generaltable';
7379 $table->data
= array();
7381 // iterate through auth plugins and add to the display table
7382 foreach ($services as $service) {
7383 $name = $service->name
;
7386 if ($service->enabled
) {
7387 $displayname = "<span>$name</span>";
7389 $displayname = "<span class=\"dimmed_text\">$name</span>";
7392 $plugin = $service->component
;
7394 $functions = "<a href=\"$efurl?id=$service->id\">$strfunctions</a>";
7396 if ($service->restrictedusers
) {
7397 $users = "<a href=\"$euurl?id=$service->id\">$strserviceusers</a>";
7399 $users = get_string('allusers', 'webservice');
7402 $edit = "<a href=\"$esurl?id=$service->id\">$stredit</a>";
7404 // add a row to the table
7405 $table->data
[] = array($displayname, $plugin, $functions, $users, $edit);
7407 $return .= html_writer
::table($table);
7411 $return .= $OUTPUT->heading(get_string('servicescustom', 'webservice'), 3, 'main');
7412 $services = $DB->get_records_select('external_services', 'component IS NULL', null, 'name');
7414 $table = new html_table();
7415 $table->head
= array($strservice, $strdelete, $strfunctions, $strusers, $stredit);
7416 $table->colclasses
= array('leftalign service', 'leftalign plugin', 'centeralign functions', 'centeralign users', 'centeralign ');
7417 $table->id
= 'customservices';
7418 $table->attributes
['class'] = 'admintable externalservices generaltable';
7419 $table->data
= array();
7421 // iterate through auth plugins and add to the display table
7422 foreach ($services as $service) {
7423 $name = $service->name
;
7426 if ($service->enabled
) {
7427 $displayname = "<span>$name</span>";
7429 $displayname = "<span class=\"dimmed_text\">$name</span>";
7433 $delete = "<a href=\"$esurl?action=delete&sesskey=".sesskey()."&id=$service->id\">$strdelete</a>";
7435 $functions = "<a href=\"$efurl?id=$service->id\">$strfunctions</a>";
7437 if ($service->restrictedusers
) {
7438 $users = "<a href=\"$euurl?id=$service->id\">$strserviceusers</a>";
7440 $users = get_string('allusers', 'webservice');
7443 $edit = "<a href=\"$esurl?id=$service->id\">$stredit</a>";
7445 // add a row to the table
7446 $table->data
[] = array($displayname, $delete, $functions, $users, $edit);
7448 // add new custom service option
7449 $return .= html_writer
::table($table);
7451 $return .= '<br />';
7452 // add a token to the table
7453 $return .= "<a href=\"$esurl?id=0\">$stradd</a>";
7455 return highlight($query, $return);
7460 * Special class for overview of external services
7462 * @author Jerome Mouneyrac
7464 class admin_setting_webservicesoverview
extends admin_setting
{
7467 * Calls parent::__construct with specific arguments
7469 public function __construct() {
7470 $this->nosave
= true;
7471 parent
::__construct('webservicesoverviewui',
7472 get_string('webservicesoverview', 'webservice'), '', '');
7476 * Always returns true, does nothing
7480 public function get_setting() {
7485 * Always returns true, does nothing
7489 public function get_defaultsetting() {
7494 * Always returns '', does not write anything
7496 * @return string Always returns ''
7498 public function write_setting($data) {
7499 // do not write any setting
7504 * Builds the XHTML to display the control
7506 * @param string $data Unused
7507 * @param string $query
7510 public function output_html($data, $query='') {
7511 global $CFG, $OUTPUT;
7514 $brtag = html_writer
::empty_tag('br');
7516 // Enable mobile web service
7517 $enablemobile = new admin_setting_enablemobileservice('enablemobilewebservice',
7518 get_string('enablemobilewebservice', 'admin'),
7519 get_string('configenablemobilewebservice',
7520 'admin', ''), 0); //we don't want to display it but to know the ws mobile status
7521 $manageserviceurl = new moodle_url("/admin/settings.php?section=externalservices");
7522 $wsmobileparam = new stdClass();
7523 $wsmobileparam->enablemobileservice
= get_string('enablemobilewebservice', 'admin');
7524 $wsmobileparam->manageservicelink
= html_writer
::link($manageserviceurl,
7525 get_string('externalservices', 'webservice'));
7526 $mobilestatus = $enablemobile->get_setting()?
get_string('mobilewsenabled', 'webservice'):get_string('mobilewsdisabled', 'webservice');
7527 $wsmobileparam->wsmobilestatus
= html_writer
::tag('strong', $mobilestatus);
7528 $return .= $OUTPUT->heading(get_string('enablemobilewebservice', 'admin'), 3, 'main');
7529 $return .= $brtag . get_string('enablemobilewsoverview', 'webservice', $wsmobileparam)
7532 /// One system controlling Moodle with Token
7533 $return .= $OUTPUT->heading(get_string('onesystemcontrolling', 'webservice'), 3, 'main');
7534 $table = new html_table();
7535 $table->head
= array(get_string('step', 'webservice'), get_string('status'),
7536 get_string('description'));
7537 $table->colclasses
= array('leftalign step', 'leftalign status', 'leftalign description');
7538 $table->id
= 'onesystemcontrol';
7539 $table->attributes
['class'] = 'admintable wsoverview generaltable';
7540 $table->data
= array();
7542 $return .= $brtag . get_string('onesystemcontrollingdescription', 'webservice')
7545 /// 1. Enable Web Services
7547 $url = new moodle_url("/admin/search.php?query=enablewebservices");
7548 $row[0] = "1. " . html_writer
::tag('a', get_string('enablews', 'webservice'),
7549 array('href' => $url));
7550 $status = html_writer
::tag('span', get_string('no'), array('class' => 'statuscritical'));
7551 if ($CFG->enablewebservices
) {
7552 $status = get_string('yes');
7555 $row[2] = get_string('enablewsdescription', 'webservice');
7556 $table->data
[] = $row;
7558 /// 2. Enable protocols
7560 $url = new moodle_url("/admin/settings.php?section=webserviceprotocols");
7561 $row[0] = "2. " . html_writer
::tag('a', get_string('enableprotocols', 'webservice'),
7562 array('href' => $url));
7563 $status = html_writer
::tag('span', get_string('none'), array('class' => 'statuscritical'));
7564 //retrieve activated protocol
7565 $active_protocols = empty($CFG->webserviceprotocols
) ?
7566 array() : explode(',', $CFG->webserviceprotocols
);
7567 if (!empty($active_protocols)) {
7569 foreach ($active_protocols as $protocol) {
7570 $status .= $protocol . $brtag;
7574 $row[2] = get_string('enableprotocolsdescription', 'webservice');
7575 $table->data
[] = $row;
7577 /// 3. Create user account
7579 $url = new moodle_url("/user/editadvanced.php?id=-1");
7580 $row[0] = "3. " . html_writer
::tag('a', get_string('createuser', 'webservice'),
7581 array('href' => $url));
7583 $row[2] = get_string('createuserdescription', 'webservice');
7584 $table->data
[] = $row;
7586 /// 4. Add capability to users
7588 $url = new moodle_url("/admin/roles/check.php?contextid=1");
7589 $row[0] = "4. " . html_writer
::tag('a', get_string('checkusercapability', 'webservice'),
7590 array('href' => $url));
7592 $row[2] = get_string('checkusercapabilitydescription', 'webservice');
7593 $table->data
[] = $row;
7595 /// 5. Select a web service
7597 $url = new moodle_url("/admin/settings.php?section=externalservices");
7598 $row[0] = "5. " . html_writer
::tag('a', get_string('selectservice', 'webservice'),
7599 array('href' => $url));
7601 $row[2] = get_string('createservicedescription', 'webservice');
7602 $table->data
[] = $row;
7604 /// 6. Add functions
7606 $url = new moodle_url("/admin/settings.php?section=externalservices");
7607 $row[0] = "6. " . html_writer
::tag('a', get_string('addfunctions', 'webservice'),
7608 array('href' => $url));
7610 $row[2] = get_string('addfunctionsdescription', 'webservice');
7611 $table->data
[] = $row;
7613 /// 7. Add the specific user
7615 $url = new moodle_url("/admin/settings.php?section=externalservices");
7616 $row[0] = "7. " . html_writer
::tag('a', get_string('selectspecificuser', 'webservice'),
7617 array('href' => $url));
7619 $row[2] = get_string('selectspecificuserdescription', 'webservice');
7620 $table->data
[] = $row;
7622 /// 8. Create token for the specific user
7624 $url = new moodle_url("/admin/webservice/tokens.php?sesskey=" . sesskey() . "&action=create");
7625 $row[0] = "8. " . html_writer
::tag('a', get_string('createtokenforuser', 'webservice'),
7626 array('href' => $url));
7628 $row[2] = get_string('createtokenforuserdescription', 'webservice');
7629 $table->data
[] = $row;
7631 /// 9. Enable the documentation
7633 $url = new moodle_url("/admin/search.php?query=enablewsdocumentation");
7634 $row[0] = "9. " . html_writer
::tag('a', get_string('enabledocumentation', 'webservice'),
7635 array('href' => $url));
7636 $status = '<span class="warning">' . get_string('no') . '</span>';
7637 if ($CFG->enablewsdocumentation
) {
7638 $status = get_string('yes');
7641 $row[2] = get_string('enabledocumentationdescription', 'webservice');
7642 $table->data
[] = $row;
7644 /// 10. Test the service
7646 $url = new moodle_url("/admin/webservice/testclient.php");
7647 $row[0] = "10. " . html_writer
::tag('a', get_string('testwithtestclient', 'webservice'),
7648 array('href' => $url));
7650 $row[2] = get_string('testwithtestclientdescription', 'webservice');
7651 $table->data
[] = $row;
7653 $return .= html_writer
::table($table);
7655 /// Users as clients with token
7656 $return .= $brtag . $brtag . $brtag;
7657 $return .= $OUTPUT->heading(get_string('userasclients', 'webservice'), 3, 'main');
7658 $table = new html_table();
7659 $table->head
= array(get_string('step', 'webservice'), get_string('status'),
7660 get_string('description'));
7661 $table->colclasses
= array('leftalign step', 'leftalign status', 'leftalign description');
7662 $table->id
= 'userasclients';
7663 $table->attributes
['class'] = 'admintable wsoverview generaltable';
7664 $table->data
= array();
7666 $return .= $brtag . get_string('userasclientsdescription', 'webservice') .
7669 /// 1. Enable Web Services
7671 $url = new moodle_url("/admin/search.php?query=enablewebservices");
7672 $row[0] = "1. " . html_writer
::tag('a', get_string('enablews', 'webservice'),
7673 array('href' => $url));
7674 $status = html_writer
::tag('span', get_string('no'), array('class' => 'statuscritical'));
7675 if ($CFG->enablewebservices
) {
7676 $status = get_string('yes');
7679 $row[2] = get_string('enablewsdescription', 'webservice');
7680 $table->data
[] = $row;
7682 /// 2. Enable protocols
7684 $url = new moodle_url("/admin/settings.php?section=webserviceprotocols");
7685 $row[0] = "2. " . html_writer
::tag('a', get_string('enableprotocols', 'webservice'),
7686 array('href' => $url));
7687 $status = html_writer
::tag('span', get_string('none'), array('class' => 'statuscritical'));
7688 //retrieve activated protocol
7689 $active_protocols = empty($CFG->webserviceprotocols
) ?
7690 array() : explode(',', $CFG->webserviceprotocols
);
7691 if (!empty($active_protocols)) {
7693 foreach ($active_protocols as $protocol) {
7694 $status .= $protocol . $brtag;
7698 $row[2] = get_string('enableprotocolsdescription', 'webservice');
7699 $table->data
[] = $row;
7702 /// 3. Select a web service
7704 $url = new moodle_url("/admin/settings.php?section=externalservices");
7705 $row[0] = "3. " . html_writer
::tag('a', get_string('selectservice', 'webservice'),
7706 array('href' => $url));
7708 $row[2] = get_string('createserviceforusersdescription', 'webservice');
7709 $table->data
[] = $row;
7711 /// 4. Add functions
7713 $url = new moodle_url("/admin/settings.php?section=externalservices");
7714 $row[0] = "4. " . html_writer
::tag('a', get_string('addfunctions', 'webservice'),
7715 array('href' => $url));
7717 $row[2] = get_string('addfunctionsdescription', 'webservice');
7718 $table->data
[] = $row;
7720 /// 5. Add capability to users
7722 $url = new moodle_url("/admin/roles/check.php?contextid=1");
7723 $row[0] = "5. " . html_writer
::tag('a', get_string('addcapabilitytousers', 'webservice'),
7724 array('href' => $url));
7726 $row[2] = get_string('addcapabilitytousersdescription', 'webservice');
7727 $table->data
[] = $row;
7729 /// 6. Test the service
7731 $url = new moodle_url("/admin/webservice/testclient.php");
7732 $row[0] = "6. " . html_writer
::tag('a', get_string('testwithtestclient', 'webservice'),
7733 array('href' => $url));
7735 $row[2] = get_string('testauserwithtestclientdescription', 'webservice');
7736 $table->data
[] = $row;
7738 $return .= html_writer
::table($table);
7740 return highlight($query, $return);
7747 * Special class for web service protocol administration.
7749 * @author Petr Skoda (skodak)
7751 class admin_setting_managewebserviceprotocols
extends admin_setting
{
7754 * Calls parent::__construct with specific arguments
7756 public function __construct() {
7757 $this->nosave
= true;
7758 parent
::__construct('webservicesui', get_string('manageprotocols', 'webservice'), '', '');
7762 * Always returns true, does nothing
7766 public function get_setting() {
7771 * Always returns true, does nothing
7775 public function get_defaultsetting() {
7780 * Always returns '', does not write anything
7782 * @return string Always returns ''
7784 public function write_setting($data) {
7785 // do not write any setting
7790 * Checks if $query is one of the available webservices
7792 * @param string $query The string to search for
7793 * @return bool Returns true if found, false if not
7795 public function is_related($query) {
7796 if (parent
::is_related($query)) {
7800 $protocols = get_plugin_list('webservice');
7801 foreach ($protocols as $protocol=>$location) {
7802 if (strpos($protocol, $query) !== false) {
7805 $protocolstr = get_string('pluginname', 'webservice_'.$protocol);
7806 if (strpos(textlib
::strtolower($protocolstr), $query) !== false) {
7814 * Builds the XHTML to display the control
7816 * @param string $data Unused
7817 * @param string $query
7820 public function output_html($data, $query='') {
7821 global $CFG, $OUTPUT;
7824 $stradministration = get_string('administration');
7825 $strsettings = get_string('settings');
7826 $stredit = get_string('edit');
7827 $strprotocol = get_string('protocol', 'webservice');
7828 $strenable = get_string('enable');
7829 $strdisable = get_string('disable');
7830 $strversion = get_string('version');
7831 $struninstall = get_string('uninstallplugin', 'admin');
7833 $protocols_available = get_plugin_list('webservice');
7834 $active_protocols = empty($CFG->webserviceprotocols
) ?
array() : explode(',', $CFG->webserviceprotocols
);
7835 ksort($protocols_available);
7837 foreach ($active_protocols as $key=>$protocol) {
7838 if (empty($protocols_available[$protocol])) {
7839 unset($active_protocols[$key]);
7843 $return = $OUTPUT->heading(get_string('actwebserviceshhdr', 'webservice'), 3, 'main');
7844 $return .= $OUTPUT->box_start('generalbox webservicesui');
7846 $table = new html_table();
7847 $table->head
= array($strprotocol, $strversion, $strenable, $struninstall, $strsettings);
7848 $table->colclasses
= array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign');
7849 $table->id
= 'webserviceprotocols';
7850 $table->attributes
['class'] = 'admintable generaltable';
7851 $table->data
= array();
7853 // iterate through auth plugins and add to the display table
7854 $url = "$CFG->wwwroot/$CFG->admin/webservice/protocols.php?sesskey=" . sesskey();
7855 foreach ($protocols_available as $protocol => $location) {
7856 $name = get_string('pluginname', 'webservice_'.$protocol);
7858 $plugin = new stdClass();
7859 if (file_exists($CFG->dirroot
.'/webservice/'.$protocol.'/version.php')) {
7860 include($CFG->dirroot
.'/webservice/'.$protocol.'/version.php');
7862 $version = isset($plugin->version
) ?
$plugin->version
: '';
7865 if (in_array($protocol, $active_protocols)) {
7866 $hideshow = "<a href=\"$url&action=disable&webservice=$protocol\">";
7867 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('t/hide') . "\" class=\"iconsmall\" alt=\"$strdisable\" /></a>";
7868 $displayname = "<span>$name</span>";
7870 $hideshow = "<a href=\"$url&action=enable&webservice=$protocol\">";
7871 $hideshow .= "<img src=\"" . $OUTPUT->pix_url('t/show') . "\" class=\"iconsmall\" alt=\"$strenable\" /></a>";
7872 $displayname = "<span class=\"dimmed_text\">$name</span>";
7876 $uninstall = "<a href=\"$url&action=uninstall&webservice=$protocol\">$struninstall</a>";
7879 if (file_exists($CFG->dirroot
.'/webservice/'.$protocol.'/settings.php')) {
7880 $settings = "<a href=\"settings.php?section=webservicesetting$protocol\">$strsettings</a>";
7885 // add a row to the table
7886 $table->data
[] = array($displayname, $version, $hideshow, $uninstall, $settings);
7888 $return .= html_writer
::table($table);
7889 $return .= get_string('configwebserviceplugins', 'webservice');
7890 $return .= $OUTPUT->box_end();
7892 return highlight($query, $return);
7898 * Special class for web service token administration.
7900 * @author Jerome Mouneyrac
7902 class admin_setting_managewebservicetokens
extends admin_setting
{
7905 * Calls parent::__construct with specific arguments
7907 public function __construct() {
7908 $this->nosave
= true;
7909 parent
::__construct('webservicestokenui', get_string('managetokens', 'webservice'), '', '');
7913 * Always returns true, does nothing
7917 public function get_setting() {
7922 * Always returns true, does nothing
7926 public function get_defaultsetting() {
7931 * Always returns '', does not write anything
7933 * @return string Always returns ''
7935 public function write_setting($data) {
7936 // do not write any setting
7941 * Builds the XHTML to display the control
7943 * @param string $data Unused
7944 * @param string $query
7947 public function output_html($data, $query='') {
7948 global $CFG, $OUTPUT, $DB, $USER;
7951 $stroperation = get_string('operation', 'webservice');
7952 $strtoken = get_string('token', 'webservice');
7953 $strservice = get_string('service', 'webservice');
7954 $struser = get_string('user');
7955 $strcontext = get_string('context', 'webservice');
7956 $strvaliduntil = get_string('validuntil', 'webservice');
7957 $striprestriction = get_string('iprestriction', 'webservice');
7959 $return = $OUTPUT->box_start('generalbox webservicestokenui');
7961 $table = new html_table();
7962 $table->head
= array($strtoken, $struser, $strservice, $striprestriction, $strvaliduntil, $stroperation);
7963 $table->colclasses
= array('leftalign', 'leftalign', 'leftalign', 'centeralign', 'centeralign', 'centeralign');
7964 $table->id
= 'webservicetokens';
7965 $table->attributes
['class'] = 'admintable generaltable';
7966 $table->data
= array();
7968 $tokenpageurl = "$CFG->wwwroot/$CFG->admin/webservice/tokens.php?sesskey=" . sesskey();
7970 //TODO: in order to let the administrator delete obsolete token, split this request in multiple request or use LEFT JOIN
7972 //here retrieve token list (including linked users firstname/lastname and linked services name)
7973 $sql = "SELECT t.id, t.token, u.id AS userid, u.firstname, u.lastname, s.name, t.iprestriction, t.validuntil, s.id AS serviceid
7974 FROM {external_tokens} t, {user} u, {external_services} s
7975 WHERE t.creatorid=? AND t.tokentype = ? AND s.id = t.externalserviceid AND t.userid = u.id";
7976 $tokens = $DB->get_records_sql($sql, array($USER->id
, EXTERNAL_TOKEN_PERMANENT
));
7977 if (!empty($tokens)) {
7978 foreach ($tokens as $token) {
7979 //TODO: retrieve context
7981 $delete = "<a href=\"".$tokenpageurl."&action=delete&tokenid=".$token->id
."\">";
7982 $delete .= get_string('delete')."</a>";
7985 if (!empty($token->validuntil
)) {
7986 $validuntil = userdate($token->validuntil
, get_string('strftimedatetime', 'langconfig'));
7989 $iprestriction = '';
7990 if (!empty($token->iprestriction
)) {
7991 $iprestriction = $token->iprestriction
;
7994 $userprofilurl = new moodle_url('/user/profile.php?id='.$token->userid
);
7995 $useratag = html_writer
::start_tag('a', array('href' => $userprofilurl));
7996 $useratag .= $token->firstname
." ".$token->lastname
;
7997 $useratag .= html_writer
::end_tag('a');
7999 //check user missing capabilities
8000 require_once($CFG->dirroot
. '/webservice/lib.php');
8001 $webservicemanager = new webservice();
8002 $usermissingcaps = $webservicemanager->get_missing_capabilities_by_users(
8003 array(array('id' => $token->userid
)), $token->serviceid
);
8005 if (!is_siteadmin($token->userid
) and
8006 array_key_exists($token->userid
, $usermissingcaps)) {
8007 $missingcapabilities = implode(', ',
8008 $usermissingcaps[$token->userid
]);
8009 if (!empty($missingcapabilities)) {
8010 $useratag .= html_writer
::tag('div',
8011 get_string('usermissingcaps', 'webservice',
8012 $missingcapabilities)
8013 . ' ' . $OUTPUT->help_icon('missingcaps', 'webservice'),
8014 array('class' => 'missingcaps'));
8018 $table->data
[] = array($token->token
, $useratag, $token->name
, $iprestriction, $validuntil, $delete);
8021 $return .= html_writer
::table($table);
8023 $return .= get_string('notoken', 'webservice');
8026 $return .= $OUTPUT->box_end();
8027 // add a token to the table
8028 $return .= "<a href=\"".$tokenpageurl."&action=create\">";
8029 $return .= get_string('add')."</a>";
8031 return highlight($query, $return);
8039 * @copyright 2010 Sam Hemelryk
8040 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
8042 class admin_setting_configcolourpicker
extends admin_setting
{
8045 * Information for previewing the colour
8049 protected $previewconfig = null;
8053 * @param string $name
8054 * @param string $visiblename
8055 * @param string $description
8056 * @param string $defaultsetting
8057 * @param array $previewconfig Array('selector'=>'.some .css .selector','style'=>'backgroundColor');
8059 public function __construct($name, $visiblename, $description, $defaultsetting, array $previewconfig=null) {
8060 $this->previewconfig
= $previewconfig;
8061 parent
::__construct($name, $visiblename, $description, $defaultsetting);
8065 * Return the setting
8067 * @return mixed returns config if successful else null
8069 public function get_setting() {
8070 return $this->config_read($this->name
);
8076 * @param string $data
8079 public function write_setting($data) {
8080 $data = $this->validate($data);
8081 if ($data === false) {
8082 return get_string('validateerror', 'admin');
8084 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
8088 * Validates the colour that was entered by the user
8090 * @param string $data
8091 * @return string|false
8093 protected function validate($data) {
8095 * List of valid HTML colour names
8099 $colornames = array(
8100 'aliceblue', 'antiquewhite', 'aqua', 'aquamarine', 'azure',
8101 'beige', 'bisque', 'black', 'blanchedalmond', 'blue',
8102 'blueviolet', 'brown', 'burlywood', 'cadetblue', 'chartreuse',
8103 'chocolate', 'coral', 'cornflowerblue', 'cornsilk', 'crimson',
8104 'cyan', 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray',
8105 'darkgrey', 'darkgreen', 'darkkhaki', 'darkmagenta',
8106 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred',
8107 'darksalmon', 'darkseagreen', 'darkslateblue', 'darkslategray',
8108 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink',
8109 'deepskyblue', 'dimgray', 'dimgrey', 'dodgerblue', 'firebrick',
8110 'floralwhite', 'forestgreen', 'fuchsia', 'gainsboro',
8111 'ghostwhite', 'gold', 'goldenrod', 'gray', 'grey', 'green',
8112 'greenyellow', 'honeydew', 'hotpink', 'indianred', 'indigo',
8113 'ivory', 'khaki', 'lavender', 'lavenderblush', 'lawngreen',
8114 'lemonchiffon', 'lightblue', 'lightcoral', 'lightcyan',
8115 'lightgoldenrodyellow', 'lightgray', 'lightgrey', 'lightgreen',
8116 'lightpink', 'lightsalmon', 'lightseagreen', 'lightskyblue',
8117 'lightslategray', 'lightslategrey', 'lightsteelblue', 'lightyellow',
8118 'lime', 'limegreen', 'linen', 'magenta', 'maroon',
8119 'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple',
8120 'mediumseagreen', 'mediumslateblue', 'mediumspringgreen',
8121 'mediumturquoise', 'mediumvioletred', 'midnightblue', 'mintcream',
8122 'mistyrose', 'moccasin', 'navajowhite', 'navy', 'oldlace', 'olive',
8123 'olivedrab', 'orange', 'orangered', 'orchid', 'palegoldenrod',
8124 'palegreen', 'paleturquoise', 'palevioletred', 'papayawhip',
8125 'peachpuff', 'peru', 'pink', 'plum', 'powderblue', 'purple', 'red',
8126 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown',
8127 'seagreen', 'seashell', 'sienna', 'silver', 'skyblue', 'slateblue',
8128 'slategray', 'slategrey', 'snow', 'springgreen', 'steelblue', 'tan',
8129 'teal', 'thistle', 'tomato', 'turquoise', 'violet', 'wheat', 'white',
8130 'whitesmoke', 'yellow', 'yellowgreen'
8133 if (preg_match('/^#?([[:xdigit:]]{3}){1,2}$/', $data)) {
8134 if (strpos($data, '#')!==0) {
8138 } else if (in_array(strtolower($data), $colornames)) {
8140 } else if (preg_match('/rgb\(\d{0,3}%?\, ?\d{0,3}%?, ?\d{0,3}%?\)/i', $data)) {
8142 } else if (preg_match('/rgba\(\d{0,3}%?\, ?\d{0,3}%?, ?\d{0,3}%?\, ?\d(\.\d)?\)/i', $data)) {
8144 } else if (preg_match('/hsl\(\d{0,3}\, ?\d{0,3}%, ?\d{0,3}%\)/i', $data)) {
8146 } else if (preg_match('/hsla\(\d{0,3}\, ?\d{0,3}%,\d{0,3}%\, ?\d(\.\d)?\)/i', $data)) {
8148 } else if (($data == 'transparent') ||
($data == 'currentColor') ||
($data == 'inherit')) {
8150 } else if (empty($data)) {
8151 return $this->defaultsetting
;
8158 * Generates the HTML for the setting
8160 * @global moodle_page $PAGE
8161 * @global core_renderer $OUTPUT
8162 * @param string $data
8163 * @param string $query
8165 public function output_html($data, $query = '') {
8166 global $PAGE, $OUTPUT;
8167 $PAGE->requires
->js_init_call('M.util.init_colour_picker', array($this->get_id(), $this->previewconfig
));
8168 $content = html_writer
::start_tag('div', array('class'=>'form-colourpicker defaultsnext'));
8169 $content .= html_writer
::tag('div', $OUTPUT->pix_icon('i/loading', get_string('loading', 'admin'), 'moodle', array('class'=>'loadingicon')), array('class'=>'admin_colourpicker clearfix'));
8170 $content .= html_writer
::empty_tag('input', array('type'=>'text','id'=>$this->get_id(), 'name'=>$this->get_full_name(), 'value'=>$data, 'size'=>'12'));
8171 if (!empty($this->previewconfig
)) {
8172 $content .= html_writer
::empty_tag('input', array('type'=>'button','id'=>$this->get_id().'_preview', 'value'=>get_string('preview'), 'class'=>'admin_colourpicker_preview'));
8174 $content .= html_writer
::end_tag('div');
8175 return format_admin_setting($this, $this->visiblename
, $content, $this->description
, false, '', $this->get_defaultsetting(), $query);
8181 * Class used for uploading of one file into file storage,
8182 * the file name is stored in config table.
8184 * Please note you need to implement your own '_pluginfile' callback function,
8185 * this setting only stores the file, it does not deal with file serving.
8187 * @copyright 2013 Petr Skoda {@link http://skodak.org}
8188 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
8190 class admin_setting_configstoredfile
extends admin_setting
{
8191 /** @var array file area options - should be one file only */
8193 /** @var string name of the file area */
8194 protected $filearea;
8195 /** @var int intemid */
8197 /** @var string used for detection of changes */
8198 protected $oldhashes;
8201 * Create new stored file setting.
8203 * @param string $name low level setting name
8204 * @param string $visiblename human readable setting name
8205 * @param string $description description of setting
8206 * @param mixed $filearea file area for file storage
8207 * @param int $itemid itemid for file storage
8208 * @param array $options file area options
8210 public function __construct($name, $visiblename, $description, $filearea, $itemid = 0, array $options = null) {
8211 parent
::__construct($name, $visiblename, $description, '');
8212 $this->filearea
= $filearea;
8213 $this->itemid
= $itemid;
8214 $this->options
= (array)$options;
8218 * Applies defaults and returns all options.
8221 protected function get_options() {
8224 require_once("$CFG->libdir/filelib.php");
8225 require_once("$CFG->dirroot/repository/lib.php");
8227 'mainfile' => '', 'subdirs' => 0, 'maxbytes' => -1, 'maxfiles' => 1,
8228 'accepted_types' => '*', 'return_types' => FILE_INTERNAL
, 'areamaxbytes' => FILE_AREA_MAX_BYTES_UNLIMITED
,
8229 'context' => context_system
::instance());
8230 foreach($this->options
as $k => $v) {
8237 public function get_setting() {
8238 return $this->config_read($this->name
);
8241 public function write_setting($data) {
8244 // Let's not deal with validation here, this is for admins only.
8245 $current = $this->get_setting();
8247 // Most probably applying default settings.
8248 if ($current === null) {
8249 return ($this->config_write($this->name
, '') ?
'' : get_string('errorsetting', 'admin'));
8252 } else if (!is_number($data)) {
8253 // Draft item id is expected here!
8254 return get_string('errorsetting', 'admin');
8257 $options = $this->get_options();
8258 $fs = get_file_storage();
8259 $component = is_null($this->plugin
) ?
'core' : $this->plugin
;
8261 $this->oldhashes
= null;
8263 $hash = sha1('/'.$options['context']->id
.'/'.$component.'/'.$this->filearea
.'/'.$this->itemid
.$current);
8264 if ($file = $fs->get_file_by_hash($hash)) {
8265 $this->oldhashes
= $file->get_contenthash().$file->get_pathnamehash();
8270 if ($fs->file_exists($options['context']->id
, $component, $this->filearea
, $this->itemid
, '/', '.')) {
8271 // Make sure the settings form was not open for more than 4 days and draft areas deleted in the meantime.
8272 $usercontext = context_user
::instance($USER->id
);
8273 if (!$fs->file_exists($usercontext->id
, 'user', 'draft', $data, '/', '.')) {
8274 return get_string('errorsetting', 'admin');
8278 file_save_draft_area_files($data, $options['context']->id
, $component, $this->filearea
, $this->itemid
, $options);
8279 $files = $fs->get_area_files($options['context']->id
, $component, $this->filearea
, $this->itemid
, 'sortorder,filepath,filename', false);
8283 /** @var stored_file $file */
8284 $file = reset($files);
8285 $filepath = $file->get_filepath().$file->get_filename();
8288 return ($this->config_write($this->name
, $filepath) ?
'' : get_string('errorsetting', 'admin'));
8291 public function post_write_settings($original) {
8292 $options = $this->get_options();
8293 $fs = get_file_storage();
8294 $component = is_null($this->plugin
) ?
'core' : $this->plugin
;
8296 $current = $this->get_setting();
8299 $hash = sha1('/'.$options['context']->id
.'/'.$component.'/'.$this->filearea
.'/'.$this->itemid
.$current);
8300 if ($file = $fs->get_file_by_hash($hash)) {
8301 $newhashes = $file->get_contenthash().$file->get_pathnamehash();
8306 if ($this->oldhashes
=== $newhashes) {
8307 $this->oldhashes
= null;
8310 $this->oldhashes
= null;
8312 $callbackfunction = $this->updatedcallback
;
8313 if (!empty($callbackfunction) and function_exists($callbackfunction)) {
8314 $callbackfunction($this->get_full_name());
8319 public function output_html($data, $query = '') {
8322 $options = $this->get_options();
8323 $id = $this->get_id();
8324 $elname = $this->get_full_name();
8325 $draftitemid = file_get_submitted_draft_itemid($elname);
8326 $component = is_null($this->plugin
) ?
'core' : $this->plugin
;
8327 file_prepare_draft_area($draftitemid, $options['context']->id
, $component, $this->filearea
, $this->itemid
, $options);
8329 // Filemanager form element implementation is far from optimal, we need to rework this if we ever fix it...
8330 require_once("$CFG->dirroot/lib/form/filemanager.php");
8332 $fmoptions = new stdClass();
8333 $fmoptions->mainfile
= $options['mainfile'];
8334 $fmoptions->maxbytes
= $options['maxbytes'];
8335 $fmoptions->maxfiles
= $options['maxfiles'];
8336 $fmoptions->client_id
= uniqid();
8337 $fmoptions->itemid
= $draftitemid;
8338 $fmoptions->subdirs
= $options['subdirs'];
8339 $fmoptions->target
= $id;
8340 $fmoptions->accepted_types
= $options['accepted_types'];
8341 $fmoptions->return_types
= $options['return_types'];
8342 $fmoptions->context
= $options['context'];
8343 $fmoptions->areamaxbytes
= $options['areamaxbytes'];
8345 $fm = new form_filemanager($fmoptions);
8346 $output = $PAGE->get_renderer('core', 'files');
8347 $html = $output->render($fm);
8349 $html .= '<input value="'.$draftitemid.'" name="'.$elname.'" type="hidden" />';
8350 $html .= '<input value="" id="'.$id.'" type="hidden" />';
8352 return format_admin_setting($this, $this->visiblename
,
8353 '<div class="form-filemanager">'.$html.'</div>', $this->description
, true, '', '', $query);
8359 * Administration interface for user specified regular expressions for device detection.
8361 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
8363 class admin_setting_devicedetectregex
extends admin_setting
{
8366 * Calls parent::__construct with specific args
8368 * @param string $name
8369 * @param string $visiblename
8370 * @param string $description
8371 * @param mixed $defaultsetting
8373 public function __construct($name, $visiblename, $description, $defaultsetting = '') {
8375 parent
::__construct($name, $visiblename, $description, $defaultsetting);
8379 * Return the current setting(s)
8381 * @return array Current settings array
8383 public function get_setting() {
8386 $config = $this->config_read($this->name
);
8387 if (is_null($config)) {
8391 return $this->prepare_form_data($config);
8395 * Save selected settings
8397 * @param array $data Array of settings to save
8400 public function write_setting($data) {
8405 if ($this->config_write($this->name
, $this->process_form_data($data))) {
8406 return ''; // success
8408 return get_string('errorsetting', 'admin') . $this->visiblename
. html_writer
::empty_tag('br');
8413 * Return XHTML field(s) for regexes
8415 * @param array $data Array of options to set in HTML
8416 * @return string XHTML string for the fields and wrapping div(s)
8418 public function output_html($data, $query='') {
8421 $out = html_writer
::start_tag('table', array('border' => 1, 'class' => 'generaltable'));
8422 $out .= html_writer
::start_tag('thead');
8423 $out .= html_writer
::start_tag('tr');
8424 $out .= html_writer
::tag('th', get_string('devicedetectregexexpression', 'admin'));
8425 $out .= html_writer
::tag('th', get_string('devicedetectregexvalue', 'admin'));
8426 $out .= html_writer
::end_tag('tr');
8427 $out .= html_writer
::end_tag('thead');
8428 $out .= html_writer
::start_tag('tbody');
8433 $looplimit = (count($data)/2)+
1;
8436 for ($i=0; $i<$looplimit; $i++
) {
8437 $out .= html_writer
::start_tag('tr');
8439 $expressionname = 'expression'.$i;
8441 if (!empty($data[$expressionname])){
8442 $expression = $data[$expressionname];
8447 $out .= html_writer
::tag('td',
8448 html_writer
::empty_tag('input',
8451 'class' => 'form-text',
8452 'name' => $this->get_full_name().'[expression'.$i.']',
8453 'value' => $expression,
8455 ), array('class' => 'c'.$i)
8458 $valuename = 'value'.$i;
8460 if (!empty($data[$valuename])){
8461 $value = $data[$valuename];
8466 $out .= html_writer
::tag('td',
8467 html_writer
::empty_tag('input',
8470 'class' => 'form-text',
8471 'name' => $this->get_full_name().'[value'.$i.']',
8474 ), array('class' => 'c'.$i)
8477 $out .= html_writer
::end_tag('tr');
8480 $out .= html_writer
::end_tag('tbody');
8481 $out .= html_writer
::end_tag('table');
8483 return format_admin_setting($this, $this->visiblename
, $out, $this->description
, false, '', null, $query);
8487 * Converts the string of regexes
8489 * @see self::process_form_data()
8490 * @param $regexes string of regexes
8491 * @return array of form fields and their values
8493 protected function prepare_form_data($regexes) {
8495 $regexes = json_decode($regexes);
8501 foreach ($regexes as $value => $regex) {
8502 $expressionname = 'expression'.$i;
8503 $valuename = 'value'.$i;
8505 $form[$expressionname] = $regex;
8506 $form[$valuename] = $value;
8514 * Converts the data from admin settings form into a string of regexes
8516 * @see self::prepare_form_data()
8517 * @param array $data array of admin form fields and values
8518 * @return false|string of regexes
8520 protected function process_form_data(array $form) {
8522 $count = count($form); // number of form field values
8525 // we must get five fields per expression
8530 for ($i = 0; $i < $count / 2; $i++
) {
8531 $expressionname = "expression".$i;
8532 $valuename = "value".$i;
8534 $expression = trim($form['expression'.$i]);
8535 $value = trim($form['value'.$i]);
8537 if (empty($expression)){
8541 $regexes[$value] = $expression;
8544 $regexes = json_encode($regexes);
8551 * Multiselect for current modules
8553 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
8555 class admin_setting_configmultiselect_modules
extends admin_setting_configmultiselect
{
8556 private $excludesystem;
8559 * Calls parent::__construct - note array $choices is not required
8561 * @param string $name setting name
8562 * @param string $visiblename localised setting name
8563 * @param string $description setting description
8564 * @param array $defaultsetting a plain array of default module ids
8565 * @param bool $excludesystem If true, excludes modules with 'system' archetype
8567 public function __construct($name, $visiblename, $description, $defaultsetting = array(),
8568 $excludesystem = true) {
8569 parent
::__construct($name, $visiblename, $description, $defaultsetting, null);
8570 $this->excludesystem
= $excludesystem;
8574 * Loads an array of current module choices
8576 * @return bool always return true
8578 public function load_choices() {
8579 if (is_array($this->choices
)) {
8582 $this->choices
= array();
8585 $records = $DB->get_records('modules', array('visible'=>1), 'name');
8586 foreach ($records as $record) {
8587 // Exclude modules if the code doesn't exist
8588 if (file_exists("$CFG->dirroot/mod/$record->name/lib.php")) {
8589 // Also exclude system modules (if specified)
8590 if (!($this->excludesystem
&&
8591 plugin_supports('mod', $record->name
, FEATURE_MOD_ARCHETYPE
) ===
8592 MOD_ARCHETYPE_SYSTEM
)) {
8593 $this->choices
[$record->id
] = $record->name
;