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(__DIR__.'/../../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 * NOTE: do not call directly, use new /admin/plugins.php?uninstall=component instead!
120 * @param string $type The plugin type, eg. 'mod', 'qtype', 'workshopgrading' etc.
121 * @param string $name The plugin name, eg. 'forum', 'multichoice', 'accumulative' etc.
122 * @uses global $OUTPUT to produce notices and other messages
125 function uninstall_plugin($type, $name) {
126 global $CFG, $DB, $OUTPUT;
128 // This may take a long time.
129 core_php_time_limit
::raise();
131 // Recursively uninstall all subplugins first.
132 $subplugintypes = core_component
::get_plugin_types_with_subplugins();
133 if (isset($subplugintypes[$type])) {
134 $base = core_component
::get_plugin_directory($type, $name);
135 if (file_exists("$base/db/subplugins.php")) {
136 $subplugins = array();
137 include("$base/db/subplugins.php");
138 foreach ($subplugins as $subplugintype=>$dir) {
139 $instances = core_component
::get_plugin_list($subplugintype);
140 foreach ($instances as $subpluginname => $notusedpluginpath) {
141 uninstall_plugin($subplugintype, $subpluginname);
148 $component = $type . '_' . $name; // eg. 'qtype_multichoice' or 'workshopgrading_accumulative' or 'mod_forum'
150 if ($type === 'mod') {
151 $pluginname = $name; // eg. 'forum'
152 if (get_string_manager()->string_exists('modulename', $component)) {
153 $strpluginname = get_string('modulename', $component);
155 $strpluginname = $component;
159 $pluginname = $component;
160 if (get_string_manager()->string_exists('pluginname', $component)) {
161 $strpluginname = get_string('pluginname', $component);
163 $strpluginname = $component;
167 echo $OUTPUT->heading($pluginname);
169 // Delete all tag areas, collections and instances associated with this plugin.
170 core_tag_area
::uninstall($component);
172 // Custom plugin uninstall.
173 $plugindirectory = core_component
::get_plugin_directory($type, $name);
174 $uninstalllib = $plugindirectory . '/db/uninstall.php';
175 if (file_exists($uninstalllib)) {
176 require_once($uninstalllib);
177 $uninstallfunction = 'xmldb_' . $pluginname . '_uninstall'; // eg. 'xmldb_workshop_uninstall()'
178 if (function_exists($uninstallfunction)) {
179 // Do not verify result, let plugin complain if necessary.
180 $uninstallfunction();
184 // Specific plugin type cleanup.
185 $plugininfo = core_plugin_manager
::instance()->get_plugin_info($component);
187 $plugininfo->uninstall_cleanup();
188 core_plugin_manager
::reset_caches();
192 // perform clean-up task common for all the plugin/subplugin types
194 //delete the web service functions and pre-built services
195 require_once($CFG->dirroot
.'/lib/externallib.php');
196 external_delete_descriptions($component);
198 // delete calendar events
199 $DB->delete_records('event', array('modulename' => $pluginname));
201 // Delete scheduled tasks.
202 $DB->delete_records('task_scheduled', array('component' => $component));
204 // Delete Inbound Message datakeys.
205 $DB->delete_records_select('messageinbound_datakeys',
206 'handler IN (SELECT id FROM {messageinbound_handlers} WHERE component = ?)', array($component));
208 // Delete Inbound Message handlers.
209 $DB->delete_records('messageinbound_handlers', array('component' => $component));
211 // delete all the logs
212 $DB->delete_records('log', array('module' => $pluginname));
214 // delete log_display information
215 $DB->delete_records('log_display', array('component' => $component));
217 // delete the module configuration records
218 unset_all_config_for_plugin($component);
219 if ($type === 'mod') {
220 unset_all_config_for_plugin($pluginname);
223 // delete message provider
224 message_provider_uninstall($component);
226 // delete the plugin tables
227 $xmldbfilepath = $plugindirectory . '/db/install.xml';
228 drop_plugin_tables($component, $xmldbfilepath, false);
229 if ($type === 'mod' or $type === 'block') {
230 // non-frankenstyle table prefixes
231 drop_plugin_tables($name, $xmldbfilepath, false);
234 // delete the capabilities that were defined by this module
235 capabilities_cleanup($component);
237 // Delete all remaining files in the filepool owned by the component.
238 $fs = get_file_storage();
239 $fs->delete_component_files($component);
241 // Finally purge all caches.
244 // Invalidate the hash used for upgrade detections.
245 set_config('allversionshash', '');
247 echo $OUTPUT->notification(get_string('success'), 'notifysuccess');
251 * Returns the version of installed component
253 * @param string $component component name
254 * @param string $source either 'disk' or 'installed' - where to get the version information from
255 * @return string|bool version number or false if the component is not found
257 function get_component_version($component, $source='installed') {
260 list($type, $name) = core_component
::normalize_component($component);
262 // moodle core or a core subsystem
263 if ($type === 'core') {
264 if ($source === 'installed') {
265 if (empty($CFG->version
)) {
268 return $CFG->version
;
271 if (!is_readable($CFG->dirroot
.'/version.php')) {
274 $version = null; //initialize variable for IDEs
275 include($CFG->dirroot
.'/version.php');
282 if ($type === 'mod') {
283 if ($source === 'installed') {
284 if ($CFG->version
< 2013092001.02) {
285 return $DB->get_field('modules', 'version', array('name'=>$name));
287 return get_config('mod_'.$name, 'version');
291 $mods = core_component
::get_plugin_list('mod');
292 if (empty($mods[$name]) or !is_readable($mods[$name].'/version.php')) {
295 $plugin = new stdClass();
296 $plugin->version
= null;
298 include($mods[$name].'/version.php');
299 return $plugin->version
;
305 if ($type === 'block') {
306 if ($source === 'installed') {
307 if ($CFG->version
< 2013092001.02) {
308 return $DB->get_field('block', 'version', array('name'=>$name));
310 return get_config('block_'.$name, 'version');
313 $blocks = core_component
::get_plugin_list('block');
314 if (empty($blocks[$name]) or !is_readable($blocks[$name].'/version.php')) {
317 $plugin = new stdclass();
318 include($blocks[$name].'/version.php');
319 return $plugin->version
;
324 // all other plugin types
325 if ($source === 'installed') {
326 return get_config($type.'_'.$name, 'version');
328 $plugins = core_component
::get_plugin_list($type);
329 if (empty($plugins[$name])) {
332 $plugin = new stdclass();
333 include($plugins[$name].'/version.php');
334 return $plugin->version
;
340 * Delete all plugin tables
342 * @param string $name Name of plugin, used as table prefix
343 * @param string $file Path to install.xml file
344 * @param bool $feedback defaults to true
345 * @return bool Always returns true
347 function drop_plugin_tables($name, $file, $feedback=true) {
350 // first try normal delete
351 if (file_exists($file) and $DB->get_manager()->delete_tables_from_xmldb_file($file)) {
355 // then try to find all tables that start with name and are not in any xml file
356 $used_tables = get_used_table_names();
358 $tables = $DB->get_tables();
360 /// Iterate over, fixing id fields as necessary
361 foreach ($tables as $table) {
362 if (in_array($table, $used_tables)) {
366 if (strpos($table, $name) !== 0) {
370 // found orphan table --> delete it
371 if ($DB->get_manager()->table_exists($table)) {
372 $xmldb_table = new xmldb_table($table);
373 $DB->get_manager()->drop_table($xmldb_table);
381 * Returns names of all known tables == tables that moodle knows about.
383 * @return array Array of lowercase table names
385 function get_used_table_names() {
386 $table_names = array();
387 $dbdirs = get_db_directories();
389 foreach ($dbdirs as $dbdir) {
390 $file = $dbdir.'/install.xml';
392 $xmldb_file = new xmldb_file($file);
394 if (!$xmldb_file->fileExists()) {
398 $loaded = $xmldb_file->loadXMLStructure();
399 $structure = $xmldb_file->getStructure();
401 if ($loaded and $tables = $structure->getTables()) {
402 foreach($tables as $table) {
403 $table_names[] = strtolower($table->getName());
412 * Returns list of all directories where we expect install.xml files
413 * @return array Array of paths
415 function get_db_directories() {
420 /// First, the main one (lib/db)
421 $dbdirs[] = $CFG->libdir
.'/db';
423 /// Then, all the ones defined by core_component::get_plugin_types()
424 $plugintypes = core_component
::get_plugin_types();
425 foreach ($plugintypes as $plugintype => $pluginbasedir) {
426 if ($plugins = core_component
::get_plugin_list($plugintype)) {
427 foreach ($plugins as $plugin => $plugindir) {
428 $dbdirs[] = $plugindir.'/db';
437 * Try to obtain or release the cron lock.
438 * @param string $name name of lock
439 * @param int $until timestamp when this lock considered stale, null means remove lock unconditionally
440 * @param bool $ignorecurrent ignore current lock state, usually extend previous lock, defaults to false
441 * @return bool true if lock obtained
443 function set_cron_lock($name, $until, $ignorecurrent=false) {
446 debugging("Tried to get a cron lock for a null fieldname");
450 // remove lock by force == remove from config table
451 if (is_null($until)) {
452 set_config($name, null);
456 if (!$ignorecurrent) {
457 // read value from db - other processes might have changed it
458 $value = $DB->get_field('config', 'value', array('name'=>$name));
460 if ($value and $value > time()) {
466 set_config($name, $until);
471 * Test if and critical warnings are present
474 function admin_critical_warnings_present() {
477 if (!has_capability('moodle/site:config', context_system
::instance())) {
481 if (!isset($SESSION->admin_critical_warning
)) {
482 $SESSION->admin_critical_warning
= 0;
483 if (is_dataroot_insecure(true) === INSECURE_DATAROOT_ERROR
) {
484 $SESSION->admin_critical_warning
= 1;
488 return $SESSION->admin_critical_warning
;
492 * Detects if float supports at least 10 decimal digits
494 * Detects if float supports at least 10 decimal digits
495 * and also if float-->string conversion works as expected.
497 * @return bool true if problem found
499 function is_float_problem() {
500 $num1 = 2009010200.01;
501 $num2 = 2009010200.02;
503 return ((string)$num1 === (string)$num2 or $num1 === $num2 or $num2 <= (string)$num1);
507 * Try to verify that dataroot is not accessible from web.
509 * Try to verify that dataroot is not accessible from web.
510 * It is not 100% correct but might help to reduce number of vulnerable sites.
511 * Protection from httpd.conf and .htaccess is not detected properly.
513 * @uses INSECURE_DATAROOT_WARNING
514 * @uses INSECURE_DATAROOT_ERROR
515 * @param bool $fetchtest try to test public access by fetching file, default false
516 * @return mixed empty means secure, INSECURE_DATAROOT_ERROR found a critical problem, INSECURE_DATAROOT_WARNING might be problematic
518 function is_dataroot_insecure($fetchtest=false) {
521 $siteroot = str_replace('\\', '/', strrev($CFG->dirroot
.'/')); // win32 backslash workaround
523 $rp = preg_replace('|https?://[^/]+|i', '', $CFG->wwwroot
, 1);
524 $rp = strrev(trim($rp, '/'));
525 $rp = explode('/', $rp);
527 if (strpos($siteroot, '/'.$r.'/') === 0) {
528 $siteroot = substr($siteroot, strlen($r)+
1); // moodle web in subdirectory
530 break; // probably alias root
534 $siteroot = strrev($siteroot);
535 $dataroot = str_replace('\\', '/', $CFG->dataroot
.'/');
537 if (strpos($dataroot, $siteroot) !== 0) {
542 return INSECURE_DATAROOT_WARNING
;
545 // now try all methods to fetch a test file using http protocol
547 $httpdocroot = str_replace('\\', '/', strrev($CFG->dirroot
.'/'));
548 preg_match('|(https?://[^/]+)|i', $CFG->wwwroot
, $matches);
549 $httpdocroot = $matches[1];
550 $datarooturl = $httpdocroot.'/'. substr($dataroot, strlen($siteroot));
551 make_upload_directory('diag');
552 $testfile = $CFG->dataroot
.'/diag/public.txt';
553 if (!file_exists($testfile)) {
554 file_put_contents($testfile, 'test file, do not delete');
555 @chmod
($testfile, $CFG->filepermissions
);
557 $teststr = trim(file_get_contents($testfile));
558 if (empty($teststr)) {
560 return INSECURE_DATAROOT_WARNING
;
563 $testurl = $datarooturl.'/diag/public.txt';
564 if (extension_loaded('curl') and
565 !(stripos(ini_get('disable_functions'), 'curl_init') !== FALSE) and
566 !(stripos(ini_get('disable_functions'), 'curl_setop') !== FALSE) and
567 ($ch = @curl_init
($testurl)) !== false) {
568 curl_setopt($ch, CURLOPT_RETURNTRANSFER
, true);
569 curl_setopt($ch, CURLOPT_HEADER
, false);
570 $data = curl_exec($ch);
571 if (!curl_errno($ch)) {
573 if ($data === $teststr) {
575 return INSECURE_DATAROOT_ERROR
;
581 if ($data = @file_get_contents
($testurl)) {
583 if ($data === $teststr) {
584 return INSECURE_DATAROOT_ERROR
;
588 preg_match('|https?://([^/]+)|i', $testurl, $matches);
589 $sitename = $matches[1];
591 if ($fp = @fsockopen
($sitename, 80, $error)) {
592 preg_match('|https?://[^/]+(.*)|i', $testurl, $matches);
593 $localurl = $matches[1];
594 $out = "GET $localurl HTTP/1.1\r\n";
595 $out .= "Host: $sitename\r\n";
596 $out .= "Connection: Close\r\n\r\n";
602 $data .= fgets($fp, 1024);
603 } else if (@fgets
($fp, 1024) === "\r\n") {
609 if ($data === $teststr) {
610 return INSECURE_DATAROOT_ERROR
;
614 return INSECURE_DATAROOT_WARNING
;
618 * Enables CLI maintenance mode by creating new dataroot/climaintenance.html file.
620 function enable_cli_maintenance_mode() {
623 if (file_exists("$CFG->dataroot/climaintenance.html")) {
624 unlink("$CFG->dataroot/climaintenance.html");
627 if (isset($CFG->maintenance_message
) and !html_is_blank($CFG->maintenance_message
)) {
628 $data = $CFG->maintenance_message
;
629 $data = bootstrap_renderer
::early_error_content($data, null, null, null);
630 $data = bootstrap_renderer
::plain_page(get_string('sitemaintenance', 'admin'), $data);
632 } else if (file_exists("$CFG->dataroot/climaintenance.template.html")) {
633 $data = file_get_contents("$CFG->dataroot/climaintenance.template.html");
636 $data = get_string('sitemaintenance', 'admin');
637 $data = bootstrap_renderer
::early_error_content($data, null, null, null);
638 $data = bootstrap_renderer
::plain_page(get_string('sitemaintenance', 'admin'), $data);
641 file_put_contents("$CFG->dataroot/climaintenance.html", $data);
642 chmod("$CFG->dataroot/climaintenance.html", $CFG->filepermissions
);
645 /// CLASS DEFINITIONS /////////////////////////////////////////////////////////
649 * Interface for anything appearing in the admin tree
651 * The interface that is implemented by anything that appears in the admin tree
652 * block. It forces inheriting classes to define a method for checking user permissions
653 * and methods for finding something in the admin tree.
655 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
657 interface part_of_admin_tree
{
660 * Finds a named part_of_admin_tree.
662 * Used to find a part_of_admin_tree. If a class only inherits part_of_admin_tree
663 * and not parentable_part_of_admin_tree, then this function should only check if
664 * $this->name matches $name. If it does, it should return a reference to $this,
665 * otherwise, it should return a reference to NULL.
667 * If a class inherits parentable_part_of_admin_tree, this method should be called
668 * recursively on all child objects (assuming, of course, the parent object's name
669 * doesn't match the search criterion).
671 * @param string $name The internal name of the part_of_admin_tree we're searching for.
672 * @return mixed An object reference or a NULL reference.
674 public function locate($name);
677 * Removes named part_of_admin_tree.
679 * @param string $name The internal name of the part_of_admin_tree we want to remove.
680 * @return bool success.
682 public function prune($name);
686 * @param string $query
687 * @return mixed array-object structure of found settings and pages
689 public function search($query);
692 * Verifies current user's access to this part_of_admin_tree.
694 * Used to check if the current user has access to this part of the admin tree or
695 * not. If a class only inherits part_of_admin_tree and not parentable_part_of_admin_tree,
696 * then this method is usually just a call to has_capability() in the site context.
698 * If a class inherits parentable_part_of_admin_tree, this method should return the
699 * logical OR of the return of check_access() on all child objects.
701 * @return bool True if the user has access, false if she doesn't.
703 public function check_access();
706 * Mostly useful for removing of some parts of the tree in admin tree block.
708 * @return True is hidden from normal list view
710 public function is_hidden();
713 * Show we display Save button at the page bottom?
716 public function show_save();
721 * Interface implemented by any part_of_admin_tree that has children.
723 * The interface implemented by any part_of_admin_tree that can be a parent
724 * to other part_of_admin_tree's. (For now, this only includes admin_category.) Apart
725 * from ensuring part_of_admin_tree compliancy, it also ensures inheriting methods
726 * include an add method for adding other part_of_admin_tree objects as children.
728 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
730 interface parentable_part_of_admin_tree
extends part_of_admin_tree
{
733 * Adds a part_of_admin_tree object to the admin tree.
735 * Used to add a part_of_admin_tree object to this object or a child of this
736 * object. $something should only be added if $destinationname matches
737 * $this->name. If it doesn't, add should be called on child objects that are
738 * also parentable_part_of_admin_tree's.
740 * $something should be appended as the last child in the $destinationname. If the
741 * $beforesibling is specified, $something should be prepended to it. If the given
742 * sibling is not found, $something should be appended to the end of $destinationname
743 * and a developer debugging message should be displayed.
745 * @param string $destinationname The internal name of the new parent for $something.
746 * @param part_of_admin_tree $something The object to be added.
747 * @return bool True on success, false on failure.
749 public function add($destinationname, $something, $beforesibling = null);
755 * The object used to represent folders (a.k.a. categories) in the admin tree block.
757 * Each admin_category object contains a number of part_of_admin_tree objects.
759 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
761 class admin_category
implements parentable_part_of_admin_tree
{
763 /** @var part_of_admin_tree[] An array of part_of_admin_tree objects that are this object's children */
765 /** @var string An internal name for this category. Must be unique amongst ALL part_of_admin_tree objects */
767 /** @var string The displayed name for this category. Usually obtained through get_string() */
769 /** @var bool Should this category be hidden in admin tree block? */
771 /** @var mixed Either a string or an array or strings */
773 /** @var mixed Either a string or an array or strings */
776 /** @var array fast lookup category cache, all categories of one tree point to one cache */
777 protected $category_cache;
779 /** @var bool If set to true children will be sorted when calling {@link admin_category::get_children()} */
780 protected $sort = false;
781 /** @var bool If set to true children will be sorted in ascending order. */
782 protected $sortasc = true;
783 /** @var bool If set to true sub categories and pages will be split and then sorted.. */
784 protected $sortsplit = true;
785 /** @var bool $sorted True if the children have been sorted and don't need resorting */
786 protected $sorted = false;
789 * Constructor for an empty admin category
791 * @param string $name The internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
792 * @param string $visiblename The displayed named for this category. Usually obtained through get_string()
793 * @param bool $hidden hide category in admin tree block, defaults to false
795 public function __construct($name, $visiblename, $hidden=false) {
796 $this->children
= array();
798 $this->visiblename
= $visiblename;
799 $this->hidden
= $hidden;
803 * Returns a reference to the part_of_admin_tree object with internal name $name.
805 * @param string $name The internal name of the object we want.
806 * @param bool $findpath initialize path and visiblepath arrays
807 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
810 public function locate($name, $findpath=false) {
811 if (!isset($this->category_cache
[$this->name
])) {
812 // somebody much have purged the cache
813 $this->category_cache
[$this->name
] = $this;
816 if ($this->name
== $name) {
818 $this->visiblepath
[] = $this->visiblename
;
819 $this->path
[] = $this->name
;
824 // quick category lookup
825 if (!$findpath and isset($this->category_cache
[$name])) {
826 return $this->category_cache
[$name];
830 foreach($this->children
as $childid=>$unused) {
831 if ($return = $this->children
[$childid]->locate($name, $findpath)) {
836 if (!is_null($return) and $findpath) {
837 $return->visiblepath
[] = $this->visiblename
;
838 $return->path
[] = $this->name
;
847 * @param string query
848 * @return mixed array-object structure of found settings and pages
850 public function search($query) {
852 foreach ($this->get_children() as $child) {
853 $subsearch = $child->search($query);
854 if (!is_array($subsearch)) {
855 debugging('Incorrect search result from '.$child->name
);
858 $result = array_merge($result, $subsearch);
864 * Removes part_of_admin_tree object with internal name $name.
866 * @param string $name The internal name of the object we want to remove.
867 * @return bool success
869 public function prune($name) {
871 if ($this->name
== $name) {
872 return false; //can not remove itself
875 foreach($this->children
as $precedence => $child) {
876 if ($child->name
== $name) {
877 // clear cache and delete self
878 while($this->category_cache
) {
879 // delete the cache, but keep the original array address
880 array_pop($this->category_cache
);
882 unset($this->children
[$precedence]);
884 } else if ($this->children
[$precedence]->prune($name)) {
892 * Adds a part_of_admin_tree to a child or grandchild (or great-grandchild, and so forth) of this object.
894 * By default the new part of the tree is appended as the last child of the parent. You
895 * can specify a sibling node that the new part should be prepended to. If the given
896 * sibling is not found, the part is appended to the end (as it would be by default) and
897 * a developer debugging message is displayed.
899 * @throws coding_exception if the $beforesibling is empty string or is not string at all.
900 * @param string $destinationame The internal name of the immediate parent that we want for $something.
901 * @param mixed $something A part_of_admin_tree or setting instance to be added.
902 * @param string $beforesibling The name of the parent's child the $something should be prepended to.
903 * @return bool True if successfully added, false if $something can not be added.
905 public function add($parentname, $something, $beforesibling = null) {
908 $parent = $this->locate($parentname);
909 if (is_null($parent)) {
910 debugging('parent does not exist!');
914 if ($something instanceof part_of_admin_tree
) {
915 if (!($parent instanceof parentable_part_of_admin_tree
)) {
916 debugging('error - parts of tree can be inserted only into parentable parts');
919 if ($CFG->debugdeveloper
&& !is_null($this->locate($something->name
))) {
920 // The name of the node is already used, simply warn the developer that this should not happen.
921 // It is intentional to check for the debug level before performing the check.
922 debugging('Duplicate admin page name: ' . $something->name
, DEBUG_DEVELOPER
);
924 if (is_null($beforesibling)) {
925 // Append $something as the parent's last child.
926 $parent->children
[] = $something;
928 if (!is_string($beforesibling) or trim($beforesibling) === '') {
929 throw new coding_exception('Unexpected value of the beforesibling parameter');
931 // Try to find the position of the sibling.
932 $siblingposition = null;
933 foreach ($parent->children
as $childposition => $child) {
934 if ($child->name
=== $beforesibling) {
935 $siblingposition = $childposition;
939 if (is_null($siblingposition)) {
940 debugging('Sibling '.$beforesibling.' not found', DEBUG_DEVELOPER
);
941 $parent->children
[] = $something;
943 $parent->children
= array_merge(
944 array_slice($parent->children
, 0, $siblingposition),
946 array_slice($parent->children
, $siblingposition)
950 if ($something instanceof admin_category
) {
951 if (isset($this->category_cache
[$something->name
])) {
952 debugging('Duplicate admin category name: '.$something->name
);
954 $this->category_cache
[$something->name
] = $something;
955 $something->category_cache
=& $this->category_cache
;
956 foreach ($something->children
as $child) {
957 // just in case somebody already added subcategories
958 if ($child instanceof admin_category
) {
959 if (isset($this->category_cache
[$child->name
])) {
960 debugging('Duplicate admin category name: '.$child->name
);
962 $this->category_cache
[$child->name
] = $child;
963 $child->category_cache
=& $this->category_cache
;
972 debugging('error - can not add this element');
979 * Checks if the user has access to anything in this category.
981 * @return bool True if the user has access to at least one child in this category, false otherwise.
983 public function check_access() {
984 foreach ($this->children
as $child) {
985 if ($child->check_access()) {
993 * Is this category hidden in admin tree block?
995 * @return bool True if hidden
997 public function is_hidden() {
998 return $this->hidden
;
1002 * Show we display Save button at the page bottom?
1005 public function show_save() {
1006 foreach ($this->children
as $child) {
1007 if ($child->show_save()) {
1015 * Sets sorting on this category.
1017 * Please note this function doesn't actually do the sorting.
1018 * It can be called anytime.
1019 * Sorting occurs when the user calls get_children.
1020 * Code using the children array directly won't see the sorted results.
1022 * @param bool $sort If set to true children will be sorted, if false they won't be.
1023 * @param bool $asc If true sorting will be ascending, otherwise descending.
1024 * @param bool $split If true we sort pages and sub categories separately.
1026 public function set_sorting($sort, $asc = true, $split = true) {
1027 $this->sort
= (bool)$sort;
1028 $this->sortasc
= (bool)$asc;
1029 $this->sortsplit
= (bool)$split;
1033 * Returns the children associated with this category.
1035 * @return part_of_admin_tree[]
1037 public function get_children() {
1038 // If we should sort and it hasn't already been sorted.
1039 if ($this->sort
&& !$this->sorted
) {
1040 if ($this->sortsplit
) {
1041 $categories = array();
1043 foreach ($this->children
as $child) {
1044 if ($child instanceof admin_category
) {
1045 $categories[] = $child;
1050 core_collator
::asort_objects_by_property($categories, 'visiblename');
1051 core_collator
::asort_objects_by_property($pages, 'visiblename');
1052 if (!$this->sortasc
) {
1053 $categories = array_reverse($categories);
1054 $pages = array_reverse($pages);
1056 $this->children
= array_merge($pages, $categories);
1058 core_collator
::asort_objects_by_property($this->children
, 'visiblename');
1059 if (!$this->sortasc
) {
1060 $this->children
= array_reverse($this->children
);
1063 $this->sorted
= true;
1065 return $this->children
;
1069 * Magically gets a property from this object.
1072 * @return part_of_admin_tree[]
1073 * @throws coding_exception
1075 public function __get($property) {
1076 if ($property === 'children') {
1077 return $this->get_children();
1079 throw new coding_exception('Invalid property requested.');
1083 * Magically sets a property against this object.
1085 * @param string $property
1086 * @param mixed $value
1087 * @throws coding_exception
1089 public function __set($property, $value) {
1090 if ($property === 'children') {
1091 $this->sorted
= false;
1092 $this->children
= $value;
1094 throw new coding_exception('Invalid property requested.');
1099 * Checks if an inaccessible property is set.
1101 * @param string $property
1103 * @throws coding_exception
1105 public function __isset($property) {
1106 if ($property === 'children') {
1107 return isset($this->children
);
1109 throw new coding_exception('Invalid property requested.');
1115 * Root of admin settings tree, does not have any parent.
1117 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1119 class admin_root
extends admin_category
{
1120 /** @var array List of errors */
1122 /** @var string search query */
1124 /** @var bool full tree flag - true means all settings required, false only pages required */
1126 /** @var bool flag indicating loaded tree */
1128 /** @var mixed site custom defaults overriding defaults in settings files*/
1129 public $custom_defaults;
1132 * @param bool $fulltree true means all settings required,
1133 * false only pages required
1135 public function __construct($fulltree) {
1138 parent
::__construct('root', get_string('administration'), false);
1139 $this->errors
= array();
1141 $this->fulltree
= $fulltree;
1142 $this->loaded
= false;
1144 $this->category_cache
= array();
1146 // load custom defaults if found
1147 $this->custom_defaults
= null;
1148 $defaultsfile = "$CFG->dirroot/local/defaults.php";
1149 if (is_readable($defaultsfile)) {
1150 $defaults = array();
1151 include($defaultsfile);
1152 if (is_array($defaults) and count($defaults)) {
1153 $this->custom_defaults
= $defaults;
1159 * Empties children array, and sets loaded to false
1161 * @param bool $requirefulltree
1163 public function purge_children($requirefulltree) {
1164 $this->children
= array();
1165 $this->fulltree
= ($requirefulltree ||
$this->fulltree
);
1166 $this->loaded
= false;
1167 //break circular dependencies - this helps PHP 5.2
1168 while($this->category_cache
) {
1169 array_pop($this->category_cache
);
1171 $this->category_cache
= array();
1177 * Links external PHP pages into the admin tree.
1179 * See detailed usage example at the top of this document (adminlib.php)
1181 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1183 class admin_externalpage
implements part_of_admin_tree
{
1185 /** @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects */
1188 /** @var string The displayed name for this external page. Usually obtained through get_string(). */
1189 public $visiblename;
1191 /** @var string The external URL that we should link to when someone requests this external page. */
1194 /** @var string The role capability/permission a user must have to access this external page. */
1195 public $req_capability;
1197 /** @var object The context in which capability/permission should be checked, default is site context. */
1200 /** @var bool hidden in admin tree block. */
1203 /** @var mixed either string or array of string */
1206 /** @var array list of visible names of page parents */
1207 public $visiblepath;
1210 * Constructor for adding an external page into the admin tree.
1212 * @param string $name The internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects.
1213 * @param string $visiblename The displayed name for this external page. Usually obtained through get_string().
1214 * @param string $url The external URL that we should link to when someone requests this external page.
1215 * @param mixed $req_capability The role capability/permission a user must have to access this external page. Defaults to 'moodle/site:config'.
1216 * @param boolean $hidden Is this external page hidden in admin tree block? Default false.
1217 * @param stdClass $context The context the page relates to. Not sure what happens
1218 * if you specify something other than system or front page. Defaults to system.
1220 public function __construct($name, $visiblename, $url, $req_capability='moodle/site:config', $hidden=false, $context=NULL) {
1221 $this->name
= $name;
1222 $this->visiblename
= $visiblename;
1224 if (is_array($req_capability)) {
1225 $this->req_capability
= $req_capability;
1227 $this->req_capability
= array($req_capability);
1229 $this->hidden
= $hidden;
1230 $this->context
= $context;
1234 * Returns a reference to the part_of_admin_tree object with internal name $name.
1236 * @param string $name The internal name of the object we want.
1237 * @param bool $findpath defaults to false
1238 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
1240 public function locate($name, $findpath=false) {
1241 if ($this->name
== $name) {
1243 $this->visiblepath
= array($this->visiblename
);
1244 $this->path
= array($this->name
);
1254 * This function always returns false, required function by interface
1256 * @param string $name
1259 public function prune($name) {
1264 * Search using query
1266 * @param string $query
1267 * @return mixed array-object structure of found settings and pages
1269 public function search($query) {
1271 if (strpos(strtolower($this->name
), $query) !== false) {
1273 } else if (strpos(core_text
::strtolower($this->visiblename
), $query) !== false) {
1277 $result = new stdClass();
1278 $result->page
= $this;
1279 $result->settings
= array();
1280 return array($this->name
=> $result);
1287 * Determines if the current user has access to this external page based on $this->req_capability.
1289 * @return bool True if user has access, false otherwise.
1291 public function check_access() {
1293 $context = empty($this->context
) ? context_system
::instance() : $this->context
;
1294 foreach($this->req_capability
as $cap) {
1295 if (has_capability($cap, $context)) {
1303 * Is this external page hidden in admin tree block?
1305 * @return bool True if hidden
1307 public function is_hidden() {
1308 return $this->hidden
;
1312 * Show we display Save button at the page bottom?
1315 public function show_save() {
1321 * Used to store details of the dependency between two settings elements.
1323 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1324 * @copyright 2017 Davo Smith, Synergy Learning
1326 class admin_settingdependency
{
1327 /** @var string the name of the setting to be shown/hidden */
1328 public $settingname;
1329 /** @var string the setting this is dependent on */
1330 public $dependenton;
1331 /** @var string the condition to show/hide the element */
1333 /** @var string the value to compare against */
1336 /** @var string[] list of valid conditions */
1337 private static $validconditions = ['checked', 'notchecked', 'noitemselected', 'eq', 'neq', 'in'];
1340 * admin_settingdependency constructor.
1341 * @param string $settingname
1342 * @param string $dependenton
1343 * @param string $condition
1344 * @param string $value
1345 * @throws \coding_exception
1347 public function __construct($settingname, $dependenton, $condition, $value) {
1348 $this->settingname
= $this->parse_name($settingname);
1349 $this->dependenton
= $this->parse_name($dependenton);
1350 $this->condition
= $condition;
1351 $this->value
= $value;
1353 if (!in_array($this->condition
, self
::$validconditions)) {
1354 throw new coding_exception("Invalid condition '$condition'");
1359 * Convert the setting name into the form field name.
1360 * @param string $name
1363 private function parse_name($name) {
1364 $bits = explode('/', $name);
1365 $name = array_pop($bits);
1368 $plugin = array_pop($bits);
1369 if ($plugin === 'moodle') {
1373 return 's_'.$plugin.'_'.$name;
1377 * Gather together all the dependencies in a format suitable for initialising javascript
1378 * @param admin_settingdependency[] $dependencies
1381 public static function prepare_for_javascript($dependencies) {
1383 foreach ($dependencies as $d) {
1384 if (!isset($result[$d->dependenton
])) {
1385 $result[$d->dependenton
] = [];
1387 if (!isset($result[$d->dependenton
][$d->condition
])) {
1388 $result[$d->dependenton
][$d->condition
] = [];
1390 if (!isset($result[$d->dependenton
][$d->condition
][$d->value
])) {
1391 $result[$d->dependenton
][$d->condition
][$d->value
] = [];
1393 $result[$d->dependenton
][$d->condition
][$d->value
][] = $d->settingname
;
1400 * Used to group a number of admin_setting objects into a page and add them to the admin tree.
1402 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1404 class admin_settingpage
implements part_of_admin_tree
{
1406 /** @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects */
1409 /** @var string The displayed name for this external page. Usually obtained through get_string(). */
1410 public $visiblename;
1412 /** @var mixed An array of admin_setting objects that are part of this setting page. */
1415 /** @var admin_settingdependency[] list of settings to hide when certain conditions are met */
1416 protected $dependencies = [];
1418 /** @var string The role capability/permission a user must have to access this external page. */
1419 public $req_capability;
1421 /** @var object The context in which capability/permission should be checked, default is site context. */
1424 /** @var bool hidden in admin tree block. */
1427 /** @var mixed string of paths or array of strings of paths */
1430 /** @var array list of visible names of page parents */
1431 public $visiblepath;
1434 * see admin_settingpage for details of this function
1436 * @param string $name The internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects.
1437 * @param string $visiblename The displayed name for this external page. Usually obtained through get_string().
1438 * @param mixed $req_capability The role capability/permission a user must have to access this external page. Defaults to 'moodle/site:config'.
1439 * @param boolean $hidden Is this external page hidden in admin tree block? Default false.
1440 * @param stdClass $context The context the page relates to. Not sure what happens
1441 * if you specify something other than system or front page. Defaults to system.
1443 public function __construct($name, $visiblename, $req_capability='moodle/site:config', $hidden=false, $context=NULL) {
1444 $this->settings
= new stdClass();
1445 $this->name
= $name;
1446 $this->visiblename
= $visiblename;
1447 if (is_array($req_capability)) {
1448 $this->req_capability
= $req_capability;
1450 $this->req_capability
= array($req_capability);
1452 $this->hidden
= $hidden;
1453 $this->context
= $context;
1457 * see admin_category
1459 * @param string $name
1460 * @param bool $findpath
1461 * @return mixed Object (this) if name == this->name, else returns null
1463 public function locate($name, $findpath=false) {
1464 if ($this->name
== $name) {
1466 $this->visiblepath
= array($this->visiblename
);
1467 $this->path
= array($this->name
);
1477 * Search string in settings page.
1479 * @param string $query
1482 public function search($query) {
1485 foreach ($this->settings
as $setting) {
1486 if ($setting->is_related($query)) {
1487 $found[] = $setting;
1492 $result = new stdClass();
1493 $result->page
= $this;
1494 $result->settings
= $found;
1495 return array($this->name
=> $result);
1499 if (strpos(strtolower($this->name
), $query) !== false) {
1501 } else if (strpos(core_text
::strtolower($this->visiblename
), $query) !== false) {
1505 $result = new stdClass();
1506 $result->page
= $this;
1507 $result->settings
= array();
1508 return array($this->name
=> $result);
1515 * This function always returns false, required by interface
1517 * @param string $name
1518 * @return bool Always false
1520 public function prune($name) {
1525 * adds an admin_setting to this admin_settingpage
1527 * 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
1528 * n.b. each admin_setting in an admin_settingpage must have a unique internal name
1530 * @param object $setting is the admin_setting object you want to add
1531 * @return bool true if successful, false if not
1533 public function add($setting) {
1534 if (!($setting instanceof admin_setting
)) {
1535 debugging('error - not a setting instance');
1539 $name = $setting->name
;
1540 if ($setting->plugin
) {
1541 $name = $setting->plugin
. $name;
1543 $this->settings
->{$name} = $setting;
1548 * Hide the named setting if the specified condition is matched.
1550 * @param string $settingname
1551 * @param string $dependenton
1552 * @param string $condition
1553 * @param string $value
1555 public function hide_if($settingname, $dependenton, $condition = 'notchecked', $value = '1') {
1556 $this->dependencies
[] = new admin_settingdependency($settingname, $dependenton, $condition, $value);
1558 // Reformat the dependency name to the plugin | name format used in the display.
1559 $dependenton = str_replace('/', ' | ', $dependenton);
1561 // Let the setting know, so it can be displayed underneath.
1562 $findname = str_replace('/', '', $settingname);
1563 foreach ($this->settings
as $name => $setting) {
1564 if ($name === $findname) {
1565 $setting->add_dependent_on($dependenton);
1571 * see admin_externalpage
1573 * @return bool Returns true for yes false for no
1575 public function check_access() {
1577 $context = empty($this->context
) ? context_system
::instance() : $this->context
;
1578 foreach($this->req_capability
as $cap) {
1579 if (has_capability($cap, $context)) {
1587 * outputs this page as html in a table (suitable for inclusion in an admin pagetype)
1588 * @return string Returns an XHTML string
1590 public function output_html() {
1591 $adminroot = admin_get_root();
1592 $return = '<fieldset>'."\n".'<div class="clearer"><!-- --></div>'."\n";
1593 foreach($this->settings
as $setting) {
1594 $fullname = $setting->get_full_name();
1595 if (array_key_exists($fullname, $adminroot->errors
)) {
1596 $data = $adminroot->errors
[$fullname]->data
;
1598 $data = $setting->get_setting();
1599 // do not use defaults if settings not available - upgrade settings handles the defaults!
1601 $return .= $setting->output_html($data);
1603 $return .= '</fieldset>';
1608 * Is this settings page hidden in admin tree block?
1610 * @return bool True if hidden
1612 public function is_hidden() {
1613 return $this->hidden
;
1617 * Show we display Save button at the page bottom?
1620 public function show_save() {
1621 foreach($this->settings
as $setting) {
1622 if (empty($setting->nosave
)) {
1630 * Should any of the settings on this page be shown / hidden based on conditions?
1633 public function has_dependencies() {
1634 return (bool)$this->dependencies
;
1638 * Format the setting show/hide conditions ready to initialise the page javascript
1641 public function get_dependencies_for_javascript() {
1642 if (!$this->has_dependencies()) {
1645 return admin_settingdependency
::prepare_for_javascript($this->dependencies
);
1651 * Admin settings class. Only exists on setting pages.
1652 * Read & write happens at this level; no authentication.
1654 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
1656 abstract class admin_setting
{
1657 /** @var string unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins. */
1659 /** @var string localised name */
1660 public $visiblename;
1661 /** @var string localised long description in Markdown format */
1662 public $description;
1663 /** @var mixed Can be string or array of string */
1664 public $defaultsetting;
1666 public $updatedcallback;
1667 /** @var mixed can be String or Null. Null means main config table */
1668 public $plugin; // null means main config table
1669 /** @var bool true indicates this setting does not actually save anything, just information */
1670 public $nosave = false;
1671 /** @var bool if set, indicates that a change to this setting requires rebuild course cache */
1672 public $affectsmodinfo = false;
1673 /** @var array of admin_setting_flag - These are extra checkboxes attached to a setting. */
1674 private $flags = array();
1675 /** @var bool Whether this field must be forced LTR. */
1676 private $forceltr = null;
1677 /** @var array list of other settings that may cause this setting to be hidden */
1678 private $dependenton = [];
1682 * @param string $name unique ascii name, either 'mysetting' for settings that in config,
1683 * or 'myplugin/mysetting' for ones in config_plugins.
1684 * @param string $visiblename localised name
1685 * @param string $description localised long description
1686 * @param mixed $defaultsetting string or array depending on implementation
1688 public function __construct($name, $visiblename, $description, $defaultsetting) {
1689 $this->parse_setting_name($name);
1690 $this->visiblename
= $visiblename;
1691 $this->description
= $description;
1692 $this->defaultsetting
= $defaultsetting;
1696 * Generic function to add a flag to this admin setting.
1698 * @param bool $enabled - One of self::OPTION_ENABLED or self::OPTION_DISABLED
1699 * @param bool $default - The default for the flag
1700 * @param string $shortname - The shortname for this flag. Used as a suffix for the setting name.
1701 * @param string $displayname - The display name for this flag. Used as a label next to the checkbox.
1703 protected function set_flag_options($enabled, $default, $shortname, $displayname) {
1704 if (empty($this->flags
[$shortname])) {
1705 $this->flags
[$shortname] = new admin_setting_flag($enabled, $default, $shortname, $displayname);
1707 $this->flags
[$shortname]->set_options($enabled, $default);
1712 * Set the enabled options flag on this admin setting.
1714 * @param bool $enabled - One of self::OPTION_ENABLED or self::OPTION_DISABLED
1715 * @param bool $default - The default for the flag
1717 public function set_enabled_flag_options($enabled, $default) {
1718 $this->set_flag_options($enabled, $default, 'enabled', new lang_string('enabled', 'core_admin'));
1722 * Set the advanced options flag on this admin setting.
1724 * @param bool $enabled - One of self::OPTION_ENABLED or self::OPTION_DISABLED
1725 * @param bool $default - The default for the flag
1727 public function set_advanced_flag_options($enabled, $default) {
1728 $this->set_flag_options($enabled, $default, 'adv', new lang_string('advanced'));
1733 * Set the locked options flag on this admin setting.
1735 * @param bool $enabled - One of self::OPTION_ENABLED or self::OPTION_DISABLED
1736 * @param bool $default - The default for the flag
1738 public function set_locked_flag_options($enabled, $default) {
1739 $this->set_flag_options($enabled, $default, 'locked', new lang_string('locked', 'core_admin'));
1743 * Get the currently saved value for a setting flag
1745 * @param admin_setting_flag $flag - One of the admin_setting_flag for this admin_setting.
1748 public function get_setting_flag_value(admin_setting_flag
$flag) {
1749 $value = $this->config_read($this->name
. '_' . $flag->get_shortname());
1750 if (!isset($value)) {
1751 $value = $flag->get_default();
1754 return !empty($value);
1758 * Get the list of defaults for the flags on this setting.
1760 * @param array of strings describing the defaults for this setting. This is appended to by this function.
1762 public function get_setting_flag_defaults(& $defaults) {
1763 foreach ($this->flags
as $flag) {
1764 if ($flag->is_enabled() && $flag->get_default()) {
1765 $defaults[] = $flag->get_displayname();
1771 * Output the input fields for the advanced and locked flags on this setting.
1773 * @param bool $adv - The current value of the advanced flag.
1774 * @param bool $locked - The current value of the locked flag.
1775 * @return string $output - The html for the flags.
1777 public function output_setting_flags() {
1780 foreach ($this->flags
as $flag) {
1781 if ($flag->is_enabled()) {
1782 $output .= $flag->output_setting_flag($this);
1786 if (!empty($output)) {
1787 return html_writer
::tag('span', $output, array('class' => 'adminsettingsflags'));
1793 * Write the values of the flags for this admin setting.
1795 * @param array $data - The data submitted from the form or null to set the default value for new installs.
1796 * @return bool - true if successful.
1798 public function write_setting_flags($data) {
1800 foreach ($this->flags
as $flag) {
1801 $result = $result && $flag->write_setting_flag($this, $data);
1807 * Set up $this->name and potentially $this->plugin
1809 * Set up $this->name and possibly $this->plugin based on whether $name looks
1810 * like 'settingname' or 'plugin/settingname'. Also, do some sanity checking
1811 * on the names, that is, output a developer debug warning if the name
1812 * contains anything other than [a-zA-Z0-9_]+.
1814 * @param string $name the setting name passed in to the constructor.
1816 private function parse_setting_name($name) {
1817 $bits = explode('/', $name);
1818 if (count($bits) > 2) {
1819 throw new moodle_exception('invalidadminsettingname', '', '', $name);
1821 $this->name
= array_pop($bits);
1822 if (!preg_match('/^[a-zA-Z0-9_]+$/', $this->name
)) {
1823 throw new moodle_exception('invalidadminsettingname', '', '', $name);
1825 if (!empty($bits)) {
1826 $this->plugin
= array_pop($bits);
1827 if ($this->plugin
=== 'moodle') {
1828 $this->plugin
= null;
1829 } else if (!preg_match('/^[a-zA-Z0-9_]+$/', $this->plugin
)) {
1830 throw new moodle_exception('invalidadminsettingname', '', '', $name);
1836 * Returns the fullname prefixed by the plugin
1839 public function get_full_name() {
1840 return 's_'.$this->plugin
.'_'.$this->name
;
1844 * Returns the ID string based on plugin and name
1847 public function get_id() {
1848 return 'id_s_'.$this->plugin
.'_'.$this->name
;
1852 * @param bool $affectsmodinfo If true, changes to this setting will
1853 * cause the course cache to be rebuilt
1855 public function set_affects_modinfo($affectsmodinfo) {
1856 $this->affectsmodinfo
= $affectsmodinfo;
1860 * Returns the config if possible
1862 * @return mixed returns config if successful else null
1864 public function config_read($name) {
1866 if (!empty($this->plugin
)) {
1867 $value = get_config($this->plugin
, $name);
1868 return $value === false ?
NULL : $value;
1871 if (isset($CFG->$name)) {
1880 * Used to set a config pair and log change
1882 * @param string $name
1883 * @param mixed $value Gets converted to string if not null
1884 * @return bool Write setting to config table
1886 public function config_write($name, $value) {
1887 global $DB, $USER, $CFG;
1889 if ($this->nosave
) {
1893 // make sure it is a real change
1894 $oldvalue = get_config($this->plugin
, $name);
1895 $oldvalue = ($oldvalue === false) ?
null : $oldvalue; // normalise
1896 $value = is_null($value) ?
null : (string)$value;
1898 if ($oldvalue === $value) {
1903 set_config($name, $value, $this->plugin
);
1905 // Some admin settings affect course modinfo
1906 if ($this->affectsmodinfo
) {
1907 // Clear course cache for all courses
1908 rebuild_course_cache(0, true);
1911 $this->add_to_config_log($name, $oldvalue, $value);
1913 return true; // BC only
1917 * Log config changes if necessary.
1918 * @param string $name
1919 * @param string $oldvalue
1920 * @param string $value
1922 protected function add_to_config_log($name, $oldvalue, $value) {
1923 add_to_config_log($name, $oldvalue, $value, $this->plugin
);
1927 * Returns current value of this setting
1928 * @return mixed array or string depending on instance, NULL means not set yet
1930 public abstract function get_setting();
1933 * Returns default setting if exists
1934 * @return mixed array or string depending on instance; NULL means no default, user must supply
1936 public function get_defaultsetting() {
1937 $adminroot = admin_get_root(false, false);
1938 if (!empty($adminroot->custom_defaults
)) {
1939 $plugin = is_null($this->plugin
) ?
'moodle' : $this->plugin
;
1940 if (isset($adminroot->custom_defaults
[$plugin])) {
1941 if (array_key_exists($this->name
, $adminroot->custom_defaults
[$plugin])) { // null is valid value here ;-)
1942 return $adminroot->custom_defaults
[$plugin][$this->name
];
1946 return $this->defaultsetting
;
1952 * @param mixed $data string or array, must not be NULL
1953 * @return string empty string if ok, string error message otherwise
1955 public abstract function write_setting($data);
1958 * Return part of form with setting
1959 * This function should always be overwritten
1961 * @param mixed $data array or string depending on setting
1962 * @param string $query
1965 public function output_html($data, $query='') {
1966 // should be overridden
1971 * Function called if setting updated - cleanup, cache reset, etc.
1972 * @param string $functionname Sets the function name
1975 public function set_updatedcallback($functionname) {
1976 $this->updatedcallback
= $functionname;
1980 * Execute postupdatecallback if necessary.
1981 * @param mixed $original original value before write_setting()
1982 * @return bool true if changed, false if not.
1984 public function post_write_settings($original) {
1985 // Comparison must work for arrays too.
1986 if (serialize($original) === serialize($this->get_setting())) {
1990 $callbackfunction = $this->updatedcallback
;
1991 if (!empty($callbackfunction) and is_callable($callbackfunction)) {
1992 $callbackfunction($this->get_full_name());
1998 * Is setting related to query text - used when searching
1999 * @param string $query
2002 public function is_related($query) {
2003 if (strpos(strtolower($this->name
), $query) !== false) {
2006 if (strpos(core_text
::strtolower($this->visiblename
), $query) !== false) {
2009 if (strpos(core_text
::strtolower($this->description
), $query) !== false) {
2012 $current = $this->get_setting();
2013 if (!is_null($current)) {
2014 if (is_string($current)) {
2015 if (strpos(core_text
::strtolower($current), $query) !== false) {
2020 $default = $this->get_defaultsetting();
2021 if (!is_null($default)) {
2022 if (is_string($default)) {
2023 if (strpos(core_text
::strtolower($default), $query) !== false) {
2032 * Get whether this should be displayed in LTR mode.
2036 public function get_force_ltr() {
2037 return $this->forceltr
;
2041 * Set whether to force LTR or not.
2043 * @param bool $value True when forced, false when not force, null when unknown.
2045 public function set_force_ltr($value) {
2046 $this->forceltr
= $value;
2050 * Add a setting to the list of those that could cause this one to be hidden
2051 * @param string $dependenton
2053 public function add_dependent_on($dependenton) {
2054 $this->dependenton
[] = $dependenton;
2058 * Get a list of the settings that could cause this one to be hidden.
2061 public function get_dependent_on() {
2062 return $this->dependenton
;
2067 * An additional option that can be applied to an admin setting.
2068 * The currently supported options are 'ADVANCED' and 'LOCKED'.
2070 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2072 class admin_setting_flag
{
2073 /** @var bool Flag to indicate if this option can be toggled for this setting */
2074 private $enabled = false;
2075 /** @var bool Flag to indicate if this option defaults to true or false */
2076 private $default = false;
2077 /** @var string Short string used to create setting name - e.g. 'adv' */
2078 private $shortname = '';
2079 /** @var string String used as the label for this flag */
2080 private $displayname = '';
2081 /** @const Checkbox for this flag is displayed in admin page */
2082 const ENABLED
= true;
2083 /** @const Checkbox for this flag is not displayed in admin page */
2084 const DISABLED
= false;
2089 * @param bool $enabled Can this option can be toggled.
2090 * Should be one of admin_setting_flag::ENABLED or admin_setting_flag::DISABLED.
2091 * @param bool $default The default checked state for this setting option.
2092 * @param string $shortname The shortname of this flag. Currently supported flags are 'locked' and 'adv'
2093 * @param string $displayname The displayname of this flag. Used as a label for the flag.
2095 public function __construct($enabled, $default, $shortname, $displayname) {
2096 $this->shortname
= $shortname;
2097 $this->displayname
= $displayname;
2098 $this->set_options($enabled, $default);
2102 * Update the values of this setting options class
2104 * @param bool $enabled Can this option can be toggled.
2105 * Should be one of admin_setting_flag::ENABLED or admin_setting_flag::DISABLED.
2106 * @param bool $default The default checked state for this setting option.
2108 public function set_options($enabled, $default) {
2109 $this->enabled
= $enabled;
2110 $this->default = $default;
2114 * Should this option appear in the interface and be toggleable?
2116 * @return bool Is it enabled?
2118 public function is_enabled() {
2119 return $this->enabled
;
2123 * Should this option be checked by default?
2125 * @return bool Is it on by default?
2127 public function get_default() {
2128 return $this->default;
2132 * Return the short name for this flag. e.g. 'adv' or 'locked'
2136 public function get_shortname() {
2137 return $this->shortname
;
2141 * Return the display name for this flag. e.g. 'Advanced' or 'Locked'
2145 public function get_displayname() {
2146 return $this->displayname
;
2150 * Save the submitted data for this flag - or set it to the default if $data is null.
2152 * @param admin_setting $setting - The admin setting for this flag
2153 * @param array $data - The data submitted from the form or null to set the default value for new installs.
2156 public function write_setting_flag(admin_setting
$setting, $data) {
2158 if ($this->is_enabled()) {
2159 if (!isset($data)) {
2160 $value = $this->get_default();
2162 $value = !empty($data[$setting->get_full_name() . '_' . $this->get_shortname()]);
2164 $result = $setting->config_write($setting->name
. '_' . $this->get_shortname(), $value);
2172 * Output the checkbox for this setting flag. Should only be called if the flag is enabled.
2174 * @param admin_setting $setting - The admin setting for this flag
2175 * @return string - The html for the checkbox.
2177 public function output_setting_flag(admin_setting
$setting) {
2180 $value = $setting->get_setting_flag_value($this);
2182 $context = new stdClass();
2183 $context->id
= $setting->get_id() . '_' . $this->get_shortname();
2184 $context->name
= $setting->get_full_name() . '_' . $this->get_shortname();
2185 $context->value
= 1;
2186 $context->checked
= $value ?
true : false;
2187 $context->label
= $this->get_displayname();
2189 return $OUTPUT->render_from_template('core_admin/setting_flag', $context);
2195 * No setting - just heading and text.
2197 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2199 class admin_setting_heading
extends admin_setting
{
2202 * not a setting, just text
2203 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2204 * @param string $heading heading
2205 * @param string $information text in box
2207 public function __construct($name, $heading, $information) {
2208 $this->nosave
= true;
2209 parent
::__construct($name, $heading, $information, '');
2213 * Always returns true
2214 * @return bool Always returns true
2216 public function get_setting() {
2221 * Always returns true
2222 * @return bool Always returns true
2224 public function get_defaultsetting() {
2229 * Never write settings
2230 * @return string Always returns an empty string
2232 public function write_setting($data) {
2233 // do not write any setting
2238 * Returns an HTML string
2239 * @return string Returns an HTML string
2241 public function output_html($data, $query='') {
2243 $context = new stdClass();
2244 $context->title
= $this->visiblename
;
2245 $context->description
= $this->description
;
2246 $context->descriptionformatted
= highlight($query, markdown_to_html($this->description
));
2247 return $OUTPUT->render_from_template('core_admin/setting_heading', $context);
2252 * No setting - just name and description in same row.
2254 * @copyright 2018 onwards Amaia Anabitarte
2255 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2257 class admin_setting_description
extends admin_setting
{
2260 * Not a setting, just text
2262 * @param string $name
2263 * @param string $visiblename
2264 * @param string $description
2266 public function __construct($name, $visiblename, $description) {
2267 $this->nosave
= true;
2268 parent
::__construct($name, $visiblename, $description, '');
2272 * Always returns true
2274 * @return bool Always returns true
2276 public function get_setting() {
2281 * Always returns true
2283 * @return bool Always returns true
2285 public function get_defaultsetting() {
2290 * Never write settings
2292 * @param mixed $data Gets converted to str for comparison against yes value
2293 * @return string Always returns an empty string
2295 public function write_setting($data) {
2296 // Do not write any setting.
2301 * Returns an HTML string
2303 * @param string $data
2304 * @param string $query
2305 * @return string Returns an HTML string
2307 public function output_html($data, $query='') {
2310 $context = new stdClass();
2311 $context->title
= $this->visiblename
;
2312 $context->description
= $this->description
;
2314 return $OUTPUT->render_from_template('core_admin/setting_description', $context);
2321 * The most flexible setting, the user enters text.
2323 * This type of field should be used for config settings which are using
2324 * English words and are not localised (passwords, database name, list of values, ...).
2326 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2328 class admin_setting_configtext
extends admin_setting
{
2330 /** @var mixed int means PARAM_XXX type, string is a allowed format in regex */
2332 /** @var int default field size */
2336 * Config text constructor
2338 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2339 * @param string $visiblename localised
2340 * @param string $description long localised info
2341 * @param string $defaultsetting
2342 * @param mixed $paramtype int means PARAM_XXX type, string is a allowed format in regex
2343 * @param int $size default field size
2345 public function __construct($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW
, $size=null) {
2346 $this->paramtype
= $paramtype;
2347 if (!is_null($size)) {
2348 $this->size
= $size;
2350 $this->size
= ($paramtype === PARAM_INT
) ?
5 : 30;
2352 parent
::__construct($name, $visiblename, $description, $defaultsetting);
2356 * Get whether this should be displayed in LTR mode.
2358 * Try to guess from the PARAM type unless specifically set.
2360 public function get_force_ltr() {
2361 $forceltr = parent
::get_force_ltr();
2362 if ($forceltr === null) {
2363 return !is_rtl_compatible($this->paramtype
);
2369 * Return the setting
2371 * @return mixed returns config if successful else null
2373 public function get_setting() {
2374 return $this->config_read($this->name
);
2377 public function write_setting($data) {
2378 if ($this->paramtype
=== PARAM_INT
and $data === '') {
2379 // do not complain if '' used instead of 0
2382 // $data is a string
2383 $validated = $this->validate($data);
2384 if ($validated !== true) {
2387 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
2391 * Validate data before storage
2392 * @param string data
2393 * @return mixed true if ok string if error found
2395 public function validate($data) {
2396 // allow paramtype to be a custom regex if it is the form of /pattern/
2397 if (preg_match('#^/.*/$#', $this->paramtype
)) {
2398 if (preg_match($this->paramtype
, $data)) {
2401 return get_string('validateerror', 'admin');
2404 } else if ($this->paramtype
=== PARAM_RAW
) {
2408 $cleaned = clean_param($data, $this->paramtype
);
2409 if ("$data" === "$cleaned") { // implicit conversion to string is needed to do exact comparison
2412 return get_string('validateerror', 'admin');
2418 * Return an XHTML string for the setting
2419 * @return string Returns an XHTML string
2421 public function output_html($data, $query='') {
2424 $default = $this->get_defaultsetting();
2425 $context = (object) [
2426 'size' => $this->size
,
2427 'id' => $this->get_id(),
2428 'name' => $this->get_full_name(),
2430 'forceltr' => $this->get_force_ltr(),
2432 $element = $OUTPUT->render_from_template('core_admin/setting_configtext', $context);
2434 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, true, '', $default, $query);
2439 * Text input with a maximum length constraint.
2441 * @copyright 2015 onwards Ankit Agarwal
2442 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2444 class admin_setting_configtext_with_maxlength
extends admin_setting_configtext
{
2446 /** @var int maximum number of chars allowed. */
2447 protected $maxlength;
2450 * Config text constructor
2452 * @param string $name unique ascii name, either 'mysetting' for settings that in config,
2453 * or 'myplugin/mysetting' for ones in config_plugins.
2454 * @param string $visiblename localised
2455 * @param string $description long localised info
2456 * @param string $defaultsetting
2457 * @param mixed $paramtype int means PARAM_XXX type, string is a allowed format in regex
2458 * @param int $size default field size
2459 * @param mixed $maxlength int maxlength allowed, 0 for infinite.
2461 public function __construct($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW
,
2462 $size=null, $maxlength = 0) {
2463 $this->maxlength
= $maxlength;
2464 parent
::__construct($name, $visiblename, $description, $defaultsetting, $paramtype, $size);
2468 * Validate data before storage
2470 * @param string $data data
2471 * @return mixed true if ok string if error found
2473 public function validate($data) {
2474 $parentvalidation = parent
::validate($data);
2475 if ($parentvalidation === true) {
2476 if ($this->maxlength
> 0) {
2477 // Max length check.
2478 $length = core_text
::strlen($data);
2479 if ($length > $this->maxlength
) {
2480 return get_string('maximumchars', 'moodle', $this->maxlength
);
2484 return true; // No max length check needed.
2487 return $parentvalidation;
2493 * General text area without html editor.
2495 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2497 class admin_setting_configtextarea
extends admin_setting_configtext
{
2502 * @param string $name
2503 * @param string $visiblename
2504 * @param string $description
2505 * @param mixed $defaultsetting string or array
2506 * @param mixed $paramtype
2507 * @param string $cols The number of columns to make the editor
2508 * @param string $rows The number of rows to make the editor
2510 public function __construct($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW
, $cols='60', $rows='8') {
2511 $this->rows
= $rows;
2512 $this->cols
= $cols;
2513 parent
::__construct($name, $visiblename, $description, $defaultsetting, $paramtype);
2517 * Returns an XHTML string for the editor
2519 * @param string $data
2520 * @param string $query
2521 * @return string XHTML string for the editor
2523 public function output_html($data, $query='') {
2526 $default = $this->get_defaultsetting();
2527 $defaultinfo = $default;
2528 if (!is_null($default) and $default !== '') {
2529 $defaultinfo = "\n".$default;
2532 $context = (object) [
2533 'cols' => $this->cols
,
2534 'rows' => $this->rows
,
2535 'id' => $this->get_id(),
2536 'name' => $this->get_full_name(),
2538 'forceltr' => $this->get_force_ltr(),
2540 $element = $OUTPUT->render_from_template('core_admin/setting_configtextarea', $context);
2542 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, true, '', $defaultinfo, $query);
2547 * General text area with html editor.
2549 class admin_setting_confightmleditor
extends admin_setting_configtextarea
{
2552 * @param string $name
2553 * @param string $visiblename
2554 * @param string $description
2555 * @param mixed $defaultsetting string or array
2556 * @param mixed $paramtype
2558 public function __construct($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW
, $cols='60', $rows='8') {
2559 parent
::__construct($name, $visiblename, $description, $defaultsetting, $paramtype, $cols, $rows);
2560 $this->set_force_ltr(false);
2561 editors_head_setup();
2565 * Returns an XHTML string for the editor
2567 * @param string $data
2568 * @param string $query
2569 * @return string XHTML string for the editor
2571 public function output_html($data, $query='') {
2572 $editor = editors_get_preferred_editor(FORMAT_HTML
);
2573 $editor->set_text($data);
2574 $editor->use_editor($this->get_id(), array('noclean'=>true));
2575 return parent
::output_html($data, $query);
2581 * Password field, allows unmasking of password
2583 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2585 class admin_setting_configpasswordunmask
extends admin_setting_configtext
{
2589 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2590 * @param string $visiblename localised
2591 * @param string $description long localised info
2592 * @param string $defaultsetting default password
2594 public function __construct($name, $visiblename, $description, $defaultsetting) {
2595 parent
::__construct($name, $visiblename, $description, $defaultsetting, PARAM_RAW
, 30);
2599 * Log config changes if necessary.
2600 * @param string $name
2601 * @param string $oldvalue
2602 * @param string $value
2604 protected function add_to_config_log($name, $oldvalue, $value) {
2605 if ($value !== '') {
2606 $value = '********';
2608 if ($oldvalue !== '' and $oldvalue !== null) {
2609 $oldvalue = '********';
2611 parent
::add_to_config_log($name, $oldvalue, $value);
2615 * Returns HTML for the field.
2617 * @param string $data Value for the field
2618 * @param string $query Passed as final argument for format_admin_setting
2619 * @return string Rendered HTML
2621 public function output_html($data, $query='') {
2623 $context = (object) [
2624 'id' => $this->get_id(),
2625 'name' => $this->get_full_name(),
2626 'size' => $this->size
,
2628 'forceltr' => $this->get_force_ltr(),
2630 $element = $OUTPUT->render_from_template('core_admin/setting_configpasswordunmask', $context);
2631 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, true, '', null, $query);
2636 * Password field, allows unmasking of password, with an advanced checkbox that controls an additional $name.'_adv' setting.
2638 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2639 * @copyright 2018 Paul Holden (pholden@greenhead.ac.uk)
2641 class admin_setting_configpasswordunmask_with_advanced
extends admin_setting_configpasswordunmask
{
2646 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2647 * @param string $visiblename localised
2648 * @param string $description long localised info
2649 * @param array $defaultsetting ('value'=>string, 'adv'=>bool)
2651 public function __construct($name, $visiblename, $description, $defaultsetting) {
2652 parent
::__construct($name, $visiblename, $description, $defaultsetting['value']);
2653 $this->set_advanced_flag_options(admin_setting_flag
::ENABLED
, !empty($defaultsetting['adv']));
2658 * Empty setting used to allow flags (advanced) on settings that can have no sensible default.
2659 * Note: Only advanced makes sense right now - locked does not.
2661 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2663 class admin_setting_configempty
extends admin_setting_configtext
{
2666 * @param string $name
2667 * @param string $visiblename
2668 * @param string $description
2670 public function __construct($name, $visiblename, $description) {
2671 parent
::__construct($name, $visiblename, $description, '', PARAM_RAW
);
2675 * Returns an XHTML string for the hidden field
2677 * @param string $data
2678 * @param string $query
2679 * @return string XHTML string for the editor
2681 public function output_html($data, $query='') {
2684 $context = (object) [
2685 'id' => $this->get_id(),
2686 'name' => $this->get_full_name()
2688 $element = $OUTPUT->render_from_template('core_admin/setting_configempty', $context);
2690 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, true, '', get_string('none'), $query);
2698 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2700 class admin_setting_configfile
extends admin_setting_configtext
{
2703 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2704 * @param string $visiblename localised
2705 * @param string $description long localised info
2706 * @param string $defaultdirectory default directory location
2708 public function __construct($name, $visiblename, $description, $defaultdirectory) {
2709 parent
::__construct($name, $visiblename, $description, $defaultdirectory, PARAM_RAW
, 50);
2713 * Returns XHTML for the field
2715 * Returns XHTML for the field and also checks whether the file
2716 * specified in $data exists using file_exists()
2718 * @param string $data File name and path to use in value attr
2719 * @param string $query
2720 * @return string XHTML field
2722 public function output_html($data, $query='') {
2723 global $CFG, $OUTPUT;
2725 $default = $this->get_defaultsetting();
2726 $context = (object) [
2727 'id' => $this->get_id(),
2728 'name' => $this->get_full_name(),
2729 'size' => $this->size
,
2731 'showvalidity' => !empty($data),
2732 'valid' => $data && file_exists($data),
2733 'readonly' => !empty($CFG->preventexecpath
),
2734 'forceltr' => $this->get_force_ltr(),
2737 if ($context->readonly
) {
2738 $this->visiblename
.= '<div class="form-overridden">'.get_string('execpathnotallowed', 'admin').'</div>';
2741 $element = $OUTPUT->render_from_template('core_admin/setting_configfile', $context);
2743 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, true, '', $default, $query);
2747 * Checks if execpatch has been disabled in config.php
2749 public function write_setting($data) {
2751 if (!empty($CFG->preventexecpath
)) {
2752 if ($this->get_setting() === null) {
2753 // Use default during installation.
2754 $data = $this->get_defaultsetting();
2755 if ($data === null) {
2762 return parent
::write_setting($data);
2769 * Path to executable file
2771 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2773 class admin_setting_configexecutable
extends admin_setting_configfile
{
2776 * Returns an XHTML field
2778 * @param string $data This is the value for the field
2779 * @param string $query
2780 * @return string XHTML field
2782 public function output_html($data, $query='') {
2783 global $CFG, $OUTPUT;
2784 $default = $this->get_defaultsetting();
2785 require_once("$CFG->libdir/filelib.php");
2787 $context = (object) [
2788 'id' => $this->get_id(),
2789 'name' => $this->get_full_name(),
2790 'size' => $this->size
,
2792 'showvalidity' => !empty($data),
2793 'valid' => $data && file_exists($data) && !is_dir($data) && file_is_executable($data),
2794 'readonly' => !empty($CFG->preventexecpath
),
2795 'forceltr' => $this->get_force_ltr()
2798 if (!empty($CFG->preventexecpath
)) {
2799 $this->visiblename
.= '<div class="form-overridden">'.get_string('execpathnotallowed', 'admin').'</div>';
2802 $element = $OUTPUT->render_from_template('core_admin/setting_configexecutable', $context);
2804 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, true, '', $default, $query);
2812 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2814 class admin_setting_configdirectory
extends admin_setting_configfile
{
2817 * Returns an XHTML field
2819 * @param string $data This is the value for the field
2820 * @param string $query
2821 * @return string XHTML
2823 public function output_html($data, $query='') {
2824 global $CFG, $OUTPUT;
2825 $default = $this->get_defaultsetting();
2827 $context = (object) [
2828 'id' => $this->get_id(),
2829 'name' => $this->get_full_name(),
2830 'size' => $this->size
,
2832 'showvalidity' => !empty($data),
2833 'valid' => $data && file_exists($data) && is_dir($data),
2834 'readonly' => !empty($CFG->preventexecpath
),
2835 'forceltr' => $this->get_force_ltr()
2838 if (!empty($CFG->preventexecpath
)) {
2839 $this->visiblename
.= '<div class="form-overridden">'.get_string('execpathnotallowed', 'admin').'</div>';
2842 $element = $OUTPUT->render_from_template('core_admin/setting_configdirectory', $context);
2844 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, true, '', $default, $query);
2852 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2854 class admin_setting_configcheckbox
extends admin_setting
{
2855 /** @var string Value used when checked */
2857 /** @var string Value used when not checked */
2862 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2863 * @param string $visiblename localised
2864 * @param string $description long localised info
2865 * @param string $defaultsetting
2866 * @param string $yes value used when checked
2867 * @param string $no value used when not checked
2869 public function __construct($name, $visiblename, $description, $defaultsetting, $yes='1', $no='0') {
2870 parent
::__construct($name, $visiblename, $description, $defaultsetting);
2871 $this->yes
= (string)$yes;
2872 $this->no
= (string)$no;
2876 * Retrieves the current setting using the objects name
2880 public function get_setting() {
2881 return $this->config_read($this->name
);
2885 * Sets the value for the setting
2887 * Sets the value for the setting to either the yes or no values
2888 * of the object by comparing $data to yes
2890 * @param mixed $data Gets converted to str for comparison against yes value
2891 * @return string empty string or error
2893 public function write_setting($data) {
2894 if ((string)$data === $this->yes
) { // convert to strings before comparison
2899 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
2903 * Returns an XHTML checkbox field
2905 * @param string $data If $data matches yes then checkbox is checked
2906 * @param string $query
2907 * @return string XHTML field
2909 public function output_html($data, $query='') {
2912 $context = (object) [
2913 'id' => $this->get_id(),
2914 'name' => $this->get_full_name(),
2916 'value' => $this->yes
,
2917 'checked' => (string) $data === $this->yes
,
2920 $default = $this->get_defaultsetting();
2921 if (!is_null($default)) {
2922 if ((string)$default === $this->yes
) {
2923 $defaultinfo = get_string('checkboxyes', 'admin');
2925 $defaultinfo = get_string('checkboxno', 'admin');
2928 $defaultinfo = NULL;
2931 $element = $OUTPUT->render_from_template('core_admin/setting_configcheckbox', $context);
2933 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, true, '', $defaultinfo, $query);
2939 * Multiple checkboxes, each represents different value, stored in csv format
2941 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2943 class admin_setting_configmulticheckbox
extends admin_setting
{
2944 /** @var array Array of choices value=>label */
2948 * Constructor: uses parent::__construct
2950 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
2951 * @param string $visiblename localised
2952 * @param string $description long localised info
2953 * @param array $defaultsetting array of selected
2954 * @param array $choices array of $value=>$label for each checkbox
2956 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
2957 $this->choices
= $choices;
2958 parent
::__construct($name, $visiblename, $description, $defaultsetting);
2962 * This public function may be used in ancestors for lazy loading of choices
2964 * @todo Check if this function is still required content commented out only returns true
2965 * @return bool true if loaded, false if error
2967 public function load_choices() {
2969 if (is_array($this->choices)) {
2972 .... load choices here
2978 * Is setting related to query text - used when searching
2980 * @param string $query
2981 * @return bool true on related, false on not or failure
2983 public function is_related($query) {
2984 if (!$this->load_choices() or empty($this->choices
)) {
2987 if (parent
::is_related($query)) {
2991 foreach ($this->choices
as $desc) {
2992 if (strpos(core_text
::strtolower($desc), $query) !== false) {
3000 * Returns the current setting if it is set
3002 * @return mixed null if null, else an array
3004 public function get_setting() {
3005 $result = $this->config_read($this->name
);
3007 if (is_null($result)) {
3010 if ($result === '') {
3013 $enabled = explode(',', $result);
3015 foreach ($enabled as $option) {
3016 $setting[$option] = 1;
3022 * Saves the setting(s) provided in $data
3024 * @param array $data An array of data, if not array returns empty str
3025 * @return mixed empty string on useless data or bool true=success, false=failed
3027 public function write_setting($data) {
3028 if (!is_array($data)) {
3029 return ''; // ignore it
3031 if (!$this->load_choices() or empty($this->choices
)) {
3034 unset($data['xxxxx']);
3036 foreach ($data as $key => $value) {
3037 if ($value and array_key_exists($key, $this->choices
)) {
3041 return $this->config_write($this->name
, implode(',', $result)) ?
'' : get_string('errorsetting', 'admin');
3045 * Returns XHTML field(s) as required by choices
3047 * Relies on data being an array should data ever be another valid vartype with
3048 * acceptable value this may cause a warning/error
3049 * if (!is_array($data)) would fix the problem
3051 * @todo Add vartype handling to ensure $data is an array
3053 * @param array $data An array of checked values
3054 * @param string $query
3055 * @return string XHTML field
3057 public function output_html($data, $query='') {
3060 if (!$this->load_choices() or empty($this->choices
)) {
3064 $default = $this->get_defaultsetting();
3065 if (is_null($default)) {
3068 if (is_null($data)) {
3072 $context = (object) [
3073 'id' => $this->get_id(),
3074 'name' => $this->get_full_name(),
3078 $defaults = array();
3079 foreach ($this->choices
as $key => $description) {
3080 if (!empty($default[$key])) {
3081 $defaults[] = $description;
3086 'checked' => !empty($data[$key]),
3087 'label' => highlightfast($query, $description)
3091 if (is_null($default)) {
3092 $defaultinfo = null;
3093 } else if (!empty($defaults)) {
3094 $defaultinfo = implode(', ', $defaults);
3096 $defaultinfo = get_string('none');
3099 $context->options
= $options;
3100 $context->hasoptions
= !empty($options);
3102 $element = $OUTPUT->render_from_template('core_admin/setting_configmulticheckbox', $context);
3104 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, false, '', $defaultinfo, $query);
3111 * Multiple checkboxes 2, value stored as string 00101011
3113 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3115 class admin_setting_configmulticheckbox2
extends admin_setting_configmulticheckbox
{
3118 * Returns the setting if set
3120 * @return mixed null if not set, else an array of set settings
3122 public function get_setting() {
3123 $result = $this->config_read($this->name
);
3124 if (is_null($result)) {
3127 if (!$this->load_choices()) {
3130 $result = str_pad($result, count($this->choices
), '0');
3131 $result = preg_split('//', $result, -1, PREG_SPLIT_NO_EMPTY
);
3133 foreach ($this->choices
as $key=>$unused) {
3134 $value = array_shift($result);
3143 * Save setting(s) provided in $data param
3145 * @param array $data An array of settings to save
3146 * @return mixed empty string for bad data or bool true=>success, false=>error
3148 public function write_setting($data) {
3149 if (!is_array($data)) {
3150 return ''; // ignore it
3152 if (!$this->load_choices() or empty($this->choices
)) {
3156 foreach ($this->choices
as $key=>$unused) {
3157 if (!empty($data[$key])) {
3163 return $this->config_write($this->name
, $result) ?
'' : get_string('errorsetting', 'admin');
3169 * Select one value from list
3171 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3173 class admin_setting_configselect
extends admin_setting
{
3174 /** @var array Array of choices value=>label */
3176 /** @var array Array of choices grouped using optgroups */
3181 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
3182 * @param string $visiblename localised
3183 * @param string $description long localised info
3184 * @param string|int $defaultsetting
3185 * @param array $choices array of $value=>$label for each selection
3187 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
3188 // Look for optgroup and single options.
3189 if (is_array($choices)) {
3190 $this->choices
= [];
3191 foreach ($choices as $key => $val) {
3192 if (is_array($val)) {
3193 $this->optgroups
[$key] = $val;
3194 $this->choices
= array_merge($this->choices
, $val);
3196 $this->choices
[$key] = $val;
3201 parent
::__construct($name, $visiblename, $description, $defaultsetting);
3205 * This function may be used in ancestors for lazy loading of choices
3207 * Override this method if loading of choices is expensive, such
3208 * as when it requires multiple db requests.
3210 * @return bool true if loaded, false if error
3212 public function load_choices() {
3214 if (is_array($this->choices)) {
3217 .... load choices here
3223 * Check if this is $query is related to a choice
3225 * @param string $query
3226 * @return bool true if related, false if not
3228 public function is_related($query) {
3229 if (parent
::is_related($query)) {
3232 if (!$this->load_choices()) {
3235 foreach ($this->choices
as $key=>$value) {
3236 if (strpos(core_text
::strtolower($key), $query) !== false) {
3239 if (strpos(core_text
::strtolower($value), $query) !== false) {
3247 * Return the setting
3249 * @return mixed returns config if successful else null
3251 public function get_setting() {
3252 return $this->config_read($this->name
);
3258 * @param string $data
3259 * @return string empty of error string
3261 public function write_setting($data) {
3262 if (!$this->load_choices() or empty($this->choices
)) {
3265 if (!array_key_exists($data, $this->choices
)) {
3266 return ''; // ignore it
3269 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
3273 * Returns XHTML select field
3275 * Ensure the options are loaded, and generate the XHTML for the select
3276 * element and any warning message. Separating this out from output_html
3277 * makes it easier to subclass this class.
3279 * @param string $data the option to show as selected.
3280 * @param string $current the currently selected option in the database, null if none.
3281 * @param string $default the default selected option.
3282 * @return array the HTML for the select element, and a warning message.
3283 * @deprecated since Moodle 3.2
3285 public function output_select_html($data, $current, $default, $extraname = '') {
3286 debugging('The method admin_setting_configselect::output_select_html is depreacted, do not use any more.', DEBUG_DEVELOPER
);
3290 * Returns XHTML select field and wrapping div(s)
3292 * @see output_select_html()
3294 * @param string $data the option to show as selected
3295 * @param string $query
3296 * @return string XHTML field and wrapping div
3298 public function output_html($data, $query='') {
3301 $default = $this->get_defaultsetting();
3302 $current = $this->get_setting();
3304 if (!$this->load_choices() ||
empty($this->choices
)) {
3308 $context = (object) [
3309 'id' => $this->get_id(),
3310 'name' => $this->get_full_name(),
3313 if (!is_null($default) && array_key_exists($default, $this->choices
)) {
3314 $defaultinfo = $this->choices
[$default];
3316 $defaultinfo = NULL;
3321 if ($current === null) {
3323 } else if (empty($current) && (array_key_exists('', $this->choices
) ||
array_key_exists(0, $this->choices
))) {
3325 } else if (!array_key_exists($current, $this->choices
)) {
3326 $warning = get_string('warningcurrentsetting', 'admin', $current);
3327 if (!is_null($default) && $data == $current) {
3328 $data = $default; // Use default instead of first value when showing the form.
3333 $template = 'core_admin/setting_configselect';
3335 if (!empty($this->optgroups
)) {
3337 foreach ($this->optgroups
as $label => $choices) {
3338 $optgroup = array('label' => $label, 'options' => []);
3339 foreach ($choices as $value => $name) {
3340 $optgroup['options'][] = [
3343 'selected' => (string) $value == $data
3345 unset($this->choices
[$value]);
3347 $optgroups[] = $optgroup;
3349 $context->options
= $options;
3350 $context->optgroups
= $optgroups;
3351 $template = 'core_admin/setting_configselect_optgroup';
3354 foreach ($this->choices
as $value => $name) {
3358 'selected' => (string) $value == $data
3361 $context->options
= $options;
3363 $element = $OUTPUT->render_from_template($template, $context);
3365 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, true, $warning, $defaultinfo, $query);
3371 * Select multiple items from list
3373 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3375 class admin_setting_configmultiselect
extends admin_setting_configselect
{
3378 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
3379 * @param string $visiblename localised
3380 * @param string $description long localised info
3381 * @param array $defaultsetting array of selected items
3382 * @param array $choices array of $value=>$label for each list item
3384 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
3385 parent
::__construct($name, $visiblename, $description, $defaultsetting, $choices);
3389 * Returns the select setting(s)
3391 * @return mixed null or array. Null if no settings else array of setting(s)
3393 public function get_setting() {
3394 $result = $this->config_read($this->name
);
3395 if (is_null($result)) {
3398 if ($result === '') {
3401 return explode(',', $result);
3405 * Saves setting(s) provided through $data
3407 * Potential bug in the works should anyone call with this function
3408 * using a vartype that is not an array
3410 * @param array $data
3412 public function write_setting($data) {
3413 if (!is_array($data)) {
3414 return ''; //ignore it
3416 if (!$this->load_choices() or empty($this->choices
)) {
3420 unset($data['xxxxx']);
3423 foreach ($data as $value) {
3424 if (!array_key_exists($value, $this->choices
)) {
3425 continue; // ignore it
3430 return ($this->config_write($this->name
, implode(',', $save)) ?
'' : get_string('errorsetting', 'admin'));
3434 * Is setting related to query text - used when searching
3436 * @param string $query
3437 * @return bool true if related, false if not
3439 public function is_related($query) {
3440 if (!$this->load_choices() or empty($this->choices
)) {
3443 if (parent
::is_related($query)) {
3447 foreach ($this->choices
as $desc) {
3448 if (strpos(core_text
::strtolower($desc), $query) !== false) {
3456 * Returns XHTML multi-select field
3458 * @todo Add vartype handling to ensure $data is an array
3459 * @param array $data Array of values to select by default
3460 * @param string $query
3461 * @return string XHTML multi-select field
3463 public function output_html($data, $query='') {
3466 if (!$this->load_choices() or empty($this->choices
)) {
3470 $default = $this->get_defaultsetting();
3471 if (is_null($default)) {
3474 if (is_null($data)) {
3478 $context = (object) [
3479 'id' => $this->get_id(),
3480 'name' => $this->get_full_name(),
3481 'size' => min(10, count($this->choices
))
3486 $template = 'core_admin/setting_configmultiselect';
3488 if (!empty($this->optgroups
)) {
3490 foreach ($this->optgroups
as $label => $choices) {
3491 $optgroup = array('label' => $label, 'options' => []);
3492 foreach ($choices as $value => $name) {
3493 if (in_array($value, $default)) {
3494 $defaults[] = $name;
3496 $optgroup['options'][] = [
3499 'selected' => in_array($value, $data)
3501 unset($this->choices
[$value]);
3503 $optgroups[] = $optgroup;
3505 $context->optgroups
= $optgroups;
3506 $template = 'core_admin/setting_configmultiselect_optgroup';
3509 foreach ($this->choices
as $value => $name) {
3510 if (in_array($value, $default)) {
3511 $defaults[] = $name;
3516 'selected' => in_array($value, $data)
3519 $context->options
= $options;
3521 if (is_null($default)) {
3522 $defaultinfo = NULL;
3523 } if (!empty($defaults)) {
3524 $defaultinfo = implode(', ', $defaults);
3526 $defaultinfo = get_string('none');
3529 $element = $OUTPUT->render_from_template($template, $context);
3531 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, true, '', $defaultinfo, $query);
3538 * This is a liiitle bit messy. we're using two selects, but we're returning
3539 * them as an array named after $name (so we only use $name2 internally for the setting)
3541 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3543 class admin_setting_configtime
extends admin_setting
{
3544 /** @var string Used for setting second select (minutes) */
3549 * @param string $hoursname setting for hours
3550 * @param string $minutesname setting for hours
3551 * @param string $visiblename localised
3552 * @param string $description long localised info
3553 * @param array $defaultsetting array representing default time 'h'=>hours, 'm'=>minutes
3555 public function __construct($hoursname, $minutesname, $visiblename, $description, $defaultsetting) {
3556 $this->name2
= $minutesname;
3557 parent
::__construct($hoursname, $visiblename, $description, $defaultsetting);
3561 * Get the selected time
3563 * @return mixed An array containing 'h'=>xx, 'm'=>xx, or null if not set
3565 public function get_setting() {
3566 $result1 = $this->config_read($this->name
);
3567 $result2 = $this->config_read($this->name2
);
3568 if (is_null($result1) or is_null($result2)) {
3572 return array('h' => $result1, 'm' => $result2);
3576 * Store the time (hours and minutes)
3578 * @param array $data Must be form 'h'=>xx, 'm'=>xx
3579 * @return bool true if success, false if not
3581 public function write_setting($data) {
3582 if (!is_array($data)) {
3586 $result = $this->config_write($this->name
, (int)$data['h']) && $this->config_write($this->name2
, (int)$data['m']);
3587 return ($result ?
'' : get_string('errorsetting', 'admin'));
3591 * Returns XHTML time select fields
3593 * @param array $data Must be form 'h'=>xx, 'm'=>xx
3594 * @param string $query
3595 * @return string XHTML time select fields and wrapping div(s)
3597 public function output_html($data, $query='') {
3600 $default = $this->get_defaultsetting();
3601 if (is_array($default)) {
3602 $defaultinfo = $default['h'].':'.$default['m'];
3604 $defaultinfo = NULL;
3607 $context = (object) [
3608 'id' => $this->get_id(),
3609 'name' => $this->get_full_name(),
3610 'hours' => array_map(function($i) use ($data) {
3614 'selected' => $i == $data['h']
3617 'minutes' => array_map(function($i) use ($data) {
3621 'selected' => $i == $data['m']
3626 $element = $OUTPUT->render_from_template('core_admin/setting_configtime', $context);
3628 return format_admin_setting($this, $this->visiblename
, $element, $this->description
,
3629 $this->get_id() . 'h', '', $defaultinfo, $query);
3636 * Seconds duration setting.
3638 * @copyright 2012 Petr Skoda (http://skodak.org)
3639 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3641 class admin_setting_configduration
extends admin_setting
{
3643 /** @var int default duration unit */
3644 protected $defaultunit;
3648 * @param string $name unique ascii name, either 'mysetting' for settings that in config,
3649 * or 'myplugin/mysetting' for ones in config_plugins.
3650 * @param string $visiblename localised name
3651 * @param string $description localised long description
3652 * @param mixed $defaultsetting string or array depending on implementation
3653 * @param int $defaultunit - day, week, etc. (in seconds)
3655 public function __construct($name, $visiblename, $description, $defaultsetting, $defaultunit = 86400) {
3656 if (is_number($defaultsetting)) {
3657 $defaultsetting = self
::parse_seconds($defaultsetting);
3659 $units = self
::get_units();
3660 if (isset($units[$defaultunit])) {
3661 $this->defaultunit
= $defaultunit;
3663 $this->defaultunit
= 86400;
3665 parent
::__construct($name, $visiblename, $description, $defaultsetting);
3669 * Returns selectable units.
3673 protected static function get_units() {
3675 604800 => get_string('weeks'),
3676 86400 => get_string('days'),
3677 3600 => get_string('hours'),
3678 60 => get_string('minutes'),
3679 1 => get_string('seconds'),
3684 * Converts seconds to some more user friendly string.
3686 * @param int $seconds
3689 protected static function get_duration_text($seconds) {
3690 if (empty($seconds)) {
3691 return get_string('none');
3693 $data = self
::parse_seconds($seconds);
3694 switch ($data['u']) {
3696 return get_string('numweeks', '', $data['v']);
3698 return get_string('numdays', '', $data['v']);
3700 return get_string('numhours', '', $data['v']);
3702 return get_string('numminutes', '', $data['v']);
3704 return get_string('numseconds', '', $data['v']*$data['u']);
3709 * Finds suitable units for given duration.
3711 * @param int $seconds
3714 protected static function parse_seconds($seconds) {
3715 foreach (self
::get_units() as $unit => $unused) {
3716 if ($seconds %
$unit === 0) {
3717 return array('v'=>(int)($seconds/$unit), 'u'=>$unit);
3720 return array('v'=>(int)$seconds, 'u'=>1);
3724 * Get the selected duration as array.
3726 * @return mixed An array containing 'v'=>xx, 'u'=>xx, or null if not set
3728 public function get_setting() {
3729 $seconds = $this->config_read($this->name
);
3730 if (is_null($seconds)) {
3734 return self
::parse_seconds($seconds);
3738 * Store the duration as seconds.
3740 * @param array $data Must be form 'h'=>xx, 'm'=>xx
3741 * @return bool true if success, false if not
3743 public function write_setting($data) {
3744 if (!is_array($data)) {
3748 $seconds = (int)($data['v']*$data['u']);
3750 return get_string('errorsetting', 'admin');
3753 $result = $this->config_write($this->name
, $seconds);
3754 return ($result ?
'' : get_string('errorsetting', 'admin'));
3758 * Returns duration text+select fields.
3760 * @param array $data Must be form 'v'=>xx, 'u'=>xx
3761 * @param string $query
3762 * @return string duration text+select fields and wrapping div(s)
3764 public function output_html($data, $query='') {
3767 $default = $this->get_defaultsetting();
3768 if (is_number($default)) {
3769 $defaultinfo = self
::get_duration_text($default);
3770 } else if (is_array($default)) {
3771 $defaultinfo = self
::get_duration_text($default['v']*$default['u']);
3773 $defaultinfo = null;
3776 $inputid = $this->get_id() . 'v';
3777 $units = self
::get_units();
3778 $defaultunit = $this->defaultunit
;
3780 $context = (object) [
3781 'id' => $this->get_id(),
3782 'name' => $this->get_full_name(),
3783 'value' => $data['v'],
3784 'options' => array_map(function($unit) use ($units, $data, $defaultunit) {
3787 'name' => $units[$unit],
3788 'selected' => ($data['v'] == 0 && $unit == $defaultunit) ||
$unit == $data['u']
3790 }, array_keys($units))
3793 $element = $OUTPUT->render_from_template('core_admin/setting_configduration', $context);
3795 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, $inputid, '', $defaultinfo, $query);
3801 * Seconds duration setting with an advanced checkbox, that controls a additional
3802 * $name.'_adv' setting.
3804 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3805 * @copyright 2014 The Open University
3807 class admin_setting_configduration_with_advanced
extends admin_setting_configduration
{
3810 * @param string $name unique ascii name, either 'mysetting' for settings that in config,
3811 * or 'myplugin/mysetting' for ones in config_plugins.
3812 * @param string $visiblename localised name
3813 * @param string $description localised long description
3814 * @param array $defaultsetting array of int value, and bool whether it is
3815 * is advanced by default.
3816 * @param int $defaultunit - day, week, etc. (in seconds)
3818 public function __construct($name, $visiblename, $description, $defaultsetting, $defaultunit = 86400) {
3819 parent
::__construct($name, $visiblename, $description, $defaultsetting['value'], $defaultunit);
3820 $this->set_advanced_flag_options(admin_setting_flag
::ENABLED
, !empty($defaultsetting['adv']));
3826 * Used to validate a textarea used for ip addresses
3828 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3829 * @copyright 2011 Petr Skoda (http://skodak.org)
3831 class admin_setting_configiplist
extends admin_setting_configtextarea
{
3834 * Validate the contents of the textarea as IP addresses
3836 * Used to validate a new line separated list of IP addresses collected from
3837 * a textarea control
3839 * @param string $data A list of IP Addresses separated by new lines
3840 * @return mixed bool true for success or string:error on failure
3842 public function validate($data) {
3844 $lines = explode("\n", $data);
3850 foreach ($lines as $line) {
3851 $tokens = explode('#', $line);
3852 $ip = trim($tokens[0]);
3856 if (preg_match('#^(\d{1,3})(\.\d{1,3}){0,3}$#', $ip, $match) ||
3857 preg_match('#^(\d{1,3})(\.\d{1,3}){0,3}(\/\d{1,2})$#', $ip, $match) ||
3858 preg_match('#^(\d{1,3})(\.\d{1,3}){3}(-\d{1,3})$#', $ip, $match)) {
3867 return get_string('validateiperror', 'admin', join(', ', $badips));
3873 * Used to validate a textarea used for domain names, wildcard domain names and IP addresses/ranges (both IPv4 and IPv6 format).
3875 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3876 * @copyright 2016 Jake Dallimore (jrhdallimore@gmail.com)
3878 class admin_setting_configmixedhostiplist
extends admin_setting_configtextarea
{
3881 * Validate the contents of the textarea as either IP addresses, domain name or wildcard domain name (RFC 4592).
3882 * Used to validate a new line separated list of entries collected from a textarea control.
3884 * This setting provides support for internationalised domain names (IDNs), however, such UTF-8 names will be converted to
3885 * their ascii-compatible encoding (punycode) on save, and converted back to their UTF-8 representation when fetched
3886 * via the get_setting() method, which has been overriden.
3888 * @param string $data A list of FQDNs, DNS wildcard format domains, and IP addresses, separated by new lines.
3889 * @return mixed bool true for success or string:error on failure
3891 public function validate($data) {
3895 $entries = explode("\n", $data);
3898 foreach ($entries as $key => $entry) {
3899 $entry = trim($entry);
3900 if (empty($entry)) {
3901 return get_string('validateemptylineerror', 'admin');
3904 // Validate each string entry against the supported formats.
3905 if (\core\ip_utils
::is_ip_address($entry) || \core\ip_utils
::is_ipv6_range($entry)
3906 || \core\ip_utils
::is_ipv4_range($entry) || \core\ip_utils
::is_domain_name($entry)
3907 || \core\ip_utils
::is_domain_matching_pattern($entry)) {
3911 // Otherwise, the entry is invalid.
3912 $badentries[] = $entry;
3916 return get_string('validateerrorlist', 'admin', join(', ', $badentries));
3922 * Convert any lines containing international domain names (IDNs) to their ascii-compatible encoding (ACE).
3924 * @param string $data the setting data, as sent from the web form.
3925 * @return string $data the setting data, with all IDNs converted (using punycode) to their ascii encoded version.
3927 protected function ace_encode($data) {
3931 $entries = explode("\n", $data);
3932 foreach ($entries as $key => $entry) {
3933 $entry = trim($entry);
3934 // This regex matches any string that has non-ascii character.
3935 if (preg_match('/[^\x00-\x7f]/', $entry)) {
3936 // If we can convert the unicode string to an idn, do so.
3937 // Otherwise, leave the original unicode string alone and let the validation function handle it (it will fail).
3938 $val = idn_to_ascii($entry, IDNA_NONTRANSITIONAL_TO_ASCII
, INTL_IDNA_VARIANT_UTS46
);
3939 $entries[$key] = $val ?
$val : $entry;
3942 return implode("\n", $entries);
3946 * Decode any ascii-encoded domain names back to their utf-8 representation for display.
3948 * @param string $data the setting data, as found in the database.
3949 * @return string $data the setting data, with all ascii-encoded IDNs decoded back to their utf-8 representation.
3951 protected function ace_decode($data) {
3952 $entries = explode("\n", $data);
3953 foreach ($entries as $key => $entry) {
3954 $entry = trim($entry);
3955 if (strpos($entry, 'xn--') !== false) {
3956 $entries[$key] = idn_to_utf8($entry, IDNA_NONTRANSITIONAL_TO_ASCII
, INTL_IDNA_VARIANT_UTS46
);
3959 return implode("\n", $entries);
3963 * Override, providing utf8-decoding for ascii-encoded IDN strings.
3965 * @return mixed returns punycode-converted setting string if successful, else null.
3967 public function get_setting() {
3968 // Here, we need to decode any ascii-encoded IDNs back to their native, utf-8 representation.
3969 $data = $this->config_read($this->name
);
3970 if (function_exists('idn_to_utf8') && !is_null($data)) {
3971 $data = $this->ace_decode($data);
3977 * Override, providing ascii-encoding for utf8 (native) IDN strings.
3979 * @param string $data
3982 public function write_setting($data) {
3983 if ($this->paramtype
=== PARAM_INT
and $data === '') {
3984 // Do not complain if '' used instead of 0.
3988 // Try to convert any non-ascii domains to ACE prior to validation - we can't modify anything in validate!
3989 if (function_exists('idn_to_ascii')) {
3990 $data = $this->ace_encode($data);
3993 $validated = $this->validate($data);
3994 if ($validated !== true) {
3997 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
4002 * Used to validate a textarea used for port numbers.
4004 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4005 * @copyright 2016 Jake Dallimore (jrhdallimore@gmail.com)
4007 class admin_setting_configportlist
extends admin_setting_configtextarea
{
4010 * Validate the contents of the textarea as port numbers.
4011 * Used to validate a new line separated list of ports collected from a textarea control.
4013 * @param string $data A list of ports separated by new lines
4014 * @return mixed bool true for success or string:error on failure
4016 public function validate($data) {
4020 $ports = explode("\n", $data);
4022 foreach ($ports as $port) {
4023 $port = trim($port);
4025 return get_string('validateemptylineerror', 'admin');
4028 // Is the string a valid integer number?
4029 if (strval(intval($port)) !== $port ||
intval($port) <= 0) {
4030 $badentries[] = $port;
4034 return get_string('validateerrorlist', 'admin', $badentries);
4042 * An admin setting for selecting one or more users who have a capability
4043 * in the system context
4045 * An admin setting for selecting one or more users, who have a particular capability
4046 * in the system context. Warning, make sure the list will never be too long. There is
4047 * no paging or searching of this list.
4049 * To correctly get a list of users from this config setting, you need to call the
4050 * get_users_from_config($CFG->mysetting, $capability); function in moodlelib.php.
4052 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4054 class admin_setting_users_with_capability
extends admin_setting_configmultiselect
{
4055 /** @var string The capabilities name */
4056 protected $capability;
4057 /** @var int include admin users too */
4058 protected $includeadmins;
4063 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
4064 * @param string $visiblename localised name
4065 * @param string $description localised long description
4066 * @param array $defaultsetting array of usernames
4067 * @param string $capability string capability name.
4068 * @param bool $includeadmins include administrators
4070 function __construct($name, $visiblename, $description, $defaultsetting, $capability, $includeadmins = true) {
4071 $this->capability
= $capability;
4072 $this->includeadmins
= $includeadmins;
4073 parent
::__construct($name, $visiblename, $description, $defaultsetting, NULL);
4077 * Load all of the uses who have the capability into choice array
4079 * @return bool Always returns true
4081 function load_choices() {
4082 if (is_array($this->choices
)) {
4085 list($sort, $sortparams) = users_order_by_sql('u');
4086 if (!empty($sortparams)) {
4087 throw new coding_exception('users_order_by_sql returned some query parameters. ' .
4088 'This is unexpected, and a problem because there is no way to pass these ' .
4089 'parameters to get_users_by_capability. See MDL-34657.');
4091 $userfields = 'u.id, u.username, ' . get_all_user_name_fields(true, 'u');
4092 $users = get_users_by_capability(context_system
::instance(), $this->capability
, $userfields, $sort);
4093 $this->choices
= array(
4094 '$@NONE@$' => get_string('nobody'),
4095 '$@ALL@$' => get_string('everyonewhocan', 'admin', get_capability_string($this->capability
)),
4097 if ($this->includeadmins
) {
4098 $admins = get_admins();
4099 foreach ($admins as $user) {
4100 $this->choices
[$user->id
] = fullname($user);
4103 if (is_array($users)) {
4104 foreach ($users as $user) {
4105 $this->choices
[$user->id
] = fullname($user);
4112 * Returns the default setting for class
4114 * @return mixed Array, or string. Empty string if no default
4116 public function get_defaultsetting() {
4117 $this->load_choices();
4118 $defaultsetting = parent
::get_defaultsetting();
4119 if (empty($defaultsetting)) {
4120 return array('$@NONE@$');
4121 } else if (array_key_exists($defaultsetting, $this->choices
)) {
4122 return $defaultsetting;
4129 * Returns the current setting
4131 * @return mixed array or string
4133 public function get_setting() {
4134 $result = parent
::get_setting();
4135 if ($result === null) {
4136 // this is necessary for settings upgrade
4139 if (empty($result)) {
4140 $result = array('$@NONE@$');
4146 * Save the chosen setting provided as $data
4148 * @param array $data
4149 * @return mixed string or array
4151 public function write_setting($data) {
4152 // If all is selected, remove any explicit options.
4153 if (in_array('$@ALL@$', $data)) {
4154 $data = array('$@ALL@$');
4156 // None never needs to be written to the DB.
4157 if (in_array('$@NONE@$', $data)) {
4158 unset($data[array_search('$@NONE@$', $data)]);
4160 return parent
::write_setting($data);
4166 * Special checkbox for calendar - resets SESSION vars.
4168 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4170 class admin_setting_special_adminseesall
extends admin_setting_configcheckbox
{
4172 * Calls the parent::__construct with default values
4174 * name => calendar_adminseesall
4175 * visiblename => get_string('adminseesall', 'admin')
4176 * description => get_string('helpadminseesall', 'admin')
4177 * defaultsetting => 0
4179 public function __construct() {
4180 parent
::__construct('calendar_adminseesall', get_string('adminseesall', 'admin'),
4181 get_string('helpadminseesall', 'admin'), '0');
4185 * Stores the setting passed in $data
4187 * @param mixed gets converted to string for comparison
4188 * @return string empty string or error message
4190 public function write_setting($data) {
4192 return parent
::write_setting($data);
4197 * Special select for settings that are altered in setup.php and can not be altered on the fly
4199 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4201 class admin_setting_special_selectsetup
extends admin_setting_configselect
{
4203 * Reads the setting directly from the database
4207 public function get_setting() {
4208 // read directly from db!
4209 return get_config(NULL, $this->name
);
4213 * Save the setting passed in $data
4215 * @param string $data The setting to save
4216 * @return string empty or error message
4218 public function write_setting($data) {
4220 // do not change active CFG setting!
4221 $current = $CFG->{$this->name
};
4222 $result = parent
::write_setting($data);
4223 $CFG->{$this->name
} = $current;
4230 * Special select for frontpage - stores data in course table
4232 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4234 class admin_setting_sitesetselect
extends admin_setting_configselect
{
4236 * Returns the site name for the selected site
4239 * @return string The site name of the selected site
4241 public function get_setting() {
4242 $site = course_get_format(get_site())->get_course();
4243 return $site->{$this->name
};
4247 * Updates the database and save the setting
4249 * @param string data
4250 * @return string empty or error message
4252 public function write_setting($data) {
4253 global $DB, $SITE, $COURSE;
4254 if (!in_array($data, array_keys($this->choices
))) {
4255 return get_string('errorsetting', 'admin');
4257 $record = new stdClass();
4258 $record->id
= SITEID
;
4259 $temp = $this->name
;
4260 $record->$temp = $data;
4261 $record->timemodified
= time();
4263 course_get_format($SITE)->update_course_format_options($record);
4264 $DB->update_record('course', $record);
4267 $SITE = $DB->get_record('course', array('id'=>$SITE->id
), '*', MUST_EXIST
);
4268 if ($SITE->id
== $COURSE->id
) {
4271 format_base
::reset_course_cache($SITE->id
);
4280 * Select for blog's bloglevel setting: if set to 0, will set blog_menu
4283 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4285 class admin_setting_bloglevel
extends admin_setting_configselect
{
4287 * Updates the database and save the setting
4289 * @param string data
4290 * @return string empty or error message
4292 public function write_setting($data) {
4295 $blogblocks = $DB->get_records_select('block', "name LIKE 'blog_%' AND visible = 1");
4296 foreach ($blogblocks as $block) {
4297 $DB->set_field('block', 'visible', 0, array('id' => $block->id
));
4300 // reenable all blocks only when switching from disabled blogs
4301 if (isset($CFG->bloglevel
) and $CFG->bloglevel
== 0) {
4302 $blogblocks = $DB->get_records_select('block', "name LIKE 'blog_%' AND visible = 0");
4303 foreach ($blogblocks as $block) {
4304 $DB->set_field('block', 'visible', 1, array('id' => $block->id
));
4308 return parent
::write_setting($data);
4314 * Special select - lists on the frontpage - hacky
4316 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4318 class admin_setting_courselist_frontpage
extends admin_setting
{
4319 /** @var array Array of choices value=>label */
4323 * Construct override, requires one param
4325 * @param bool $loggedin Is the user logged in
4327 public function __construct($loggedin) {
4329 require_once($CFG->dirroot
.'/course/lib.php');
4330 $name = 'frontpage'.($loggedin ?
'loggedin' : '');
4331 $visiblename = get_string('frontpage'.($loggedin ?
'loggedin' : ''),'admin');
4332 $description = get_string('configfrontpage'.($loggedin ?
'loggedin' : ''),'admin');
4333 $defaults = array(FRONTPAGEALLCOURSELIST
);
4334 parent
::__construct($name, $visiblename, $description, $defaults);
4338 * Loads the choices available
4340 * @return bool always returns true
4342 public function load_choices() {
4343 if (is_array($this->choices
)) {
4346 $this->choices
= array(FRONTPAGENEWS
=> get_string('frontpagenews'),
4347 FRONTPAGEALLCOURSELIST
=> get_string('frontpagecourselist'),
4348 FRONTPAGEENROLLEDCOURSELIST
=> get_string('frontpageenrolledcourselist'),
4349 FRONTPAGECATEGORYNAMES
=> get_string('frontpagecategorynames'),
4350 FRONTPAGECATEGORYCOMBO
=> get_string('frontpagecategorycombo'),
4351 FRONTPAGECOURSESEARCH
=> get_string('frontpagecoursesearch'),
4352 'none' => get_string('none'));
4353 if ($this->name
=== 'frontpage') {
4354 unset($this->choices
[FRONTPAGEENROLLEDCOURSELIST
]);
4360 * Returns the selected settings
4362 * @param mixed array or setting or null
4364 public function get_setting() {
4365 $result = $this->config_read($this->name
);
4366 if (is_null($result)) {
4369 if ($result === '') {
4372 return explode(',', $result);
4376 * Save the selected options
4378 * @param array $data
4379 * @return mixed empty string (data is not an array) or bool true=success false=failure
4381 public function write_setting($data) {
4382 if (!is_array($data)) {
4385 $this->load_choices();
4387 foreach($data as $datum) {
4388 if ($datum == 'none' or !array_key_exists($datum, $this->choices
)) {
4391 $save[$datum] = $datum; // no duplicates
4393 return ($this->config_write($this->name
, implode(',', $save)) ?
'' : get_string('errorsetting', 'admin'));
4397 * Return XHTML select field and wrapping div
4399 * @todo Add vartype handling to make sure $data is an array
4400 * @param array $data Array of elements to select by default
4401 * @return string XHTML select field and wrapping div
4403 public function output_html($data, $query='') {
4406 $this->load_choices();
4407 $currentsetting = array();
4408 foreach ($data as $key) {
4409 if ($key != 'none' and array_key_exists($key, $this->choices
)) {
4410 $currentsetting[] = $key; // already selected first
4414 $context = (object) [
4415 'id' => $this->get_id(),
4416 'name' => $this->get_full_name(),
4419 $options = $this->choices
;
4421 for ($i = 0; $i < count($this->choices
) - 1; $i++
) {
4422 if (!array_key_exists($i, $currentsetting)) {
4423 $currentsetting[$i] = 'none';
4427 'options' => array_map(function($option) use ($options, $currentsetting, $i) {
4429 'name' => $options[$option],
4431 'selected' => $currentsetting[$i] == $option
4433 }, array_keys($options))
4436 $context->selects
= $selects;
4438 $element = $OUTPUT->render_from_template('core_admin/setting_courselist_frontpage', $context);
4440 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, false, '', null, $query);
4446 * Special checkbox for frontpage - stores data in course table
4448 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4450 class admin_setting_sitesetcheckbox
extends admin_setting_configcheckbox
{
4452 * Returns the current sites name
4456 public function get_setting() {
4457 $site = course_get_format(get_site())->get_course();
4458 return $site->{$this->name
};
4462 * Save the selected setting
4464 * @param string $data The selected site
4465 * @return string empty string or error message
4467 public function write_setting($data) {
4468 global $DB, $SITE, $COURSE;
4469 $record = new stdClass();
4470 $record->id
= $SITE->id
;
4471 $record->{$this->name
} = ($data == '1' ?
1 : 0);
4472 $record->timemodified
= time();
4474 course_get_format($SITE)->update_course_format_options($record);
4475 $DB->update_record('course', $record);
4478 $SITE = $DB->get_record('course', array('id'=>$SITE->id
), '*', MUST_EXIST
);
4479 if ($SITE->id
== $COURSE->id
) {
4482 format_base
::reset_course_cache($SITE->id
);
4489 * Special text for frontpage - stores data in course table.
4490 * Empty string means not set here. Manual setting is required.
4492 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4494 class admin_setting_sitesettext
extends admin_setting_configtext
{
4499 public function __construct() {
4500 call_user_func_array(['parent', '__construct'], func_get_args());
4501 $this->set_force_ltr(false);
4505 * Return the current setting
4507 * @return mixed string or null
4509 public function get_setting() {
4510 $site = course_get_format(get_site())->get_course();
4511 return $site->{$this->name
} != '' ?
$site->{$this->name
} : NULL;
4515 * Validate the selected data
4517 * @param string $data The selected value to validate
4518 * @return mixed true or message string
4520 public function validate($data) {
4522 $cleaned = clean_param($data, PARAM_TEXT
);
4523 if ($cleaned === '') {
4524 return get_string('required');
4526 if ($this->name
==='shortname' &&
4527 $DB->record_exists_sql('SELECT id from {course} WHERE shortname = ? AND id <> ?', array($data, $SITE->id
))) {
4528 return get_string('shortnametaken', 'error', $data);
4530 if ("$data" == "$cleaned") { // implicit conversion to string is needed to do exact comparison
4533 return get_string('validateerror', 'admin');
4538 * Save the selected setting
4540 * @param string $data The selected value
4541 * @return string empty or error message
4543 public function write_setting($data) {
4544 global $DB, $SITE, $COURSE;
4545 $data = trim($data);
4546 $validated = $this->validate($data);
4547 if ($validated !== true) {
4551 $record = new stdClass();
4552 $record->id
= $SITE->id
;
4553 $record->{$this->name
} = $data;
4554 $record->timemodified
= time();
4556 course_get_format($SITE)->update_course_format_options($record);
4557 $DB->update_record('course', $record);
4560 $SITE = $DB->get_record('course', array('id'=>$SITE->id
), '*', MUST_EXIST
);
4561 if ($SITE->id
== $COURSE->id
) {
4564 format_base
::reset_course_cache($SITE->id
);
4572 * Special text editor for site description.
4574 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4576 class admin_setting_special_frontpagedesc
extends admin_setting_confightmleditor
{
4579 * Calls parent::__construct with specific arguments
4581 public function __construct() {
4582 parent
::__construct('summary', get_string('frontpagedescription'), get_string('frontpagedescriptionhelp'), null,
4587 * Return the current setting
4588 * @return string The current setting
4590 public function get_setting() {
4591 $site = course_get_format(get_site())->get_course();
4592 return $site->{$this->name
};
4596 * Save the new setting
4598 * @param string $data The new value to save
4599 * @return string empty or error message
4601 public function write_setting($data) {
4602 global $DB, $SITE, $COURSE;
4603 $record = new stdClass();
4604 $record->id
= $SITE->id
;
4605 $record->{$this->name
} = $data;
4606 $record->timemodified
= time();
4608 course_get_format($SITE)->update_course_format_options($record);
4609 $DB->update_record('course', $record);
4612 $SITE = $DB->get_record('course', array('id'=>$SITE->id
), '*', MUST_EXIST
);
4613 if ($SITE->id
== $COURSE->id
) {
4616 format_base
::reset_course_cache($SITE->id
);
4624 * Administration interface for emoticon_manager settings.
4626 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4628 class admin_setting_emoticons
extends admin_setting
{
4631 * Calls parent::__construct with specific args
4633 public function __construct() {
4636 $manager = get_emoticon_manager();
4637 $defaults = $this->prepare_form_data($manager->default_emoticons());
4638 parent
::__construct('emoticons', get_string('emoticons', 'admin'), get_string('emoticons_desc', 'admin'), $defaults);
4642 * Return the current setting(s)
4644 * @return array Current settings array
4646 public function get_setting() {
4649 $manager = get_emoticon_manager();
4651 $config = $this->config_read($this->name
);
4652 if (is_null($config)) {
4656 $config = $manager->decode_stored_config($config);
4657 if (is_null($config)) {
4661 return $this->prepare_form_data($config);
4665 * Save selected settings
4667 * @param array $data Array of settings to save
4670 public function write_setting($data) {
4672 $manager = get_emoticon_manager();
4673 $emoticons = $this->process_form_data($data);
4675 if ($emoticons === false) {
4679 if ($this->config_write($this->name
, $manager->encode_stored_config($emoticons))) {
4680 return ''; // success
4682 return get_string('errorsetting', 'admin') . $this->visiblename
. html_writer
::empty_tag('br');
4687 * Return XHTML field(s) for options
4689 * @param array $data Array of options to set in HTML
4690 * @return string XHTML string for the fields and wrapping div(s)
4692 public function output_html($data, $query='') {
4695 $context = (object) [
4696 'name' => $this->get_full_name(),
4702 foreach ($data as $field => $value) {
4704 // When $i == 0: text.
4705 // When $i == 1: imagename.
4706 // When $i == 2: imagecomponent.
4707 // When $i == 3: altidentifier.
4708 // When $i == 4: altcomponent.
4709 $fields[$i] = (object) [
4718 if (!empty($fields[1]->value
)) {
4719 if (get_string_manager()->string_exists($fields[3]->value
, $fields[4]->value
)) {
4720 $alt = get_string($fields[3]->value
, $fields[4]->value
);
4722 $alt = $fields[0]->value
;
4724 $icon = new pix_emoticon($fields[1]->value
, $alt, $fields[2]->value
);
4726 $context->emoticons
[] = [
4727 'fields' => $fields,
4728 'icon' => $icon ?
$icon->export_for_template($OUTPUT) : null
4735 $context->reseturl
= new moodle_url('/admin/resetemoticons.php');
4736 $element = $OUTPUT->render_from_template('core_admin/setting_emoticons', $context);
4737 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, false, '', NULL, $query);
4741 * Converts the array of emoticon objects provided by {@see emoticon_manager} into admin settings form data
4743 * @see self::process_form_data()
4744 * @param array $emoticons array of emoticon objects as returned by {@see emoticon_manager}
4745 * @return array of form fields and their values
4747 protected function prepare_form_data(array $emoticons) {
4751 foreach ($emoticons as $emoticon) {
4752 $form['text'.$i] = $emoticon->text
;
4753 $form['imagename'.$i] = $emoticon->imagename
;
4754 $form['imagecomponent'.$i] = $emoticon->imagecomponent
;
4755 $form['altidentifier'.$i] = $emoticon->altidentifier
;
4756 $form['altcomponent'.$i] = $emoticon->altcomponent
;
4759 // add one more blank field set for new object
4760 $form['text'.$i] = '';
4761 $form['imagename'.$i] = '';
4762 $form['imagecomponent'.$i] = '';
4763 $form['altidentifier'.$i] = '';
4764 $form['altcomponent'.$i] = '';
4770 * Converts the data from admin settings form into an array of emoticon objects
4772 * @see self::prepare_form_data()
4773 * @param array $data array of admin form fields and values
4774 * @return false|array of emoticon objects
4776 protected function process_form_data(array $form) {
4778 $count = count($form); // number of form field values
4781 // we must get five fields per emoticon object
4785 $emoticons = array();
4786 for ($i = 0; $i < $count / 5; $i++
) {
4787 $emoticon = new stdClass();
4788 $emoticon->text
= clean_param(trim($form['text'.$i]), PARAM_NOTAGS
);
4789 $emoticon->imagename
= clean_param(trim($form['imagename'.$i]), PARAM_PATH
);
4790 $emoticon->imagecomponent
= clean_param(trim($form['imagecomponent'.$i]), PARAM_COMPONENT
);
4791 $emoticon->altidentifier
= clean_param(trim($form['altidentifier'.$i]), PARAM_STRINGID
);
4792 $emoticon->altcomponent
= clean_param(trim($form['altcomponent'.$i]), PARAM_COMPONENT
);
4794 if (strpos($emoticon->text
, ':/') !== false or strpos($emoticon->text
, '//') !== false) {
4795 // prevent from breaking http://url.addresses by accident
4796 $emoticon->text
= '';
4799 if (strlen($emoticon->text
) < 2) {
4800 // do not allow single character emoticons
4801 $emoticon->text
= '';
4804 if (preg_match('/^[a-zA-Z]+[a-zA-Z0-9]*$/', $emoticon->text
)) {
4805 // emoticon text must contain some non-alphanumeric character to prevent
4806 // breaking HTML tags
4807 $emoticon->text
= '';
4810 if ($emoticon->text
!== '' and $emoticon->imagename
!== '' and $emoticon->imagecomponent
!== '') {
4811 $emoticons[] = $emoticon;
4821 * Special setting for limiting of the list of available languages.
4823 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4825 class admin_setting_langlist
extends admin_setting_configtext
{
4827 * Calls parent::__construct with specific arguments
4829 public function __construct() {
4830 parent
::__construct('langlist', get_string('langlist', 'admin'), get_string('configlanglist', 'admin'), '', PARAM_NOTAGS
);
4834 * Save the new setting
4836 * @param string $data The new setting
4839 public function write_setting($data) {
4840 $return = parent
::write_setting($data);
4841 get_string_manager()->reset_caches();
4848 * Selection of one of the recognised countries using the list
4849 * returned by {@link get_list_of_countries()}.
4851 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4853 class admin_settings_country_select
extends admin_setting_configselect
{
4854 protected $includeall;
4855 public function __construct($name, $visiblename, $description, $defaultsetting, $includeall=false) {
4856 $this->includeall
= $includeall;
4857 parent
::__construct($name, $visiblename, $description, $defaultsetting, null);
4861 * Lazy-load the available choices for the select box
4863 public function load_choices() {
4865 if (is_array($this->choices
)) {
4868 $this->choices
= array_merge(
4869 array('0' => get_string('choosedots')),
4870 get_string_manager()->get_list_of_countries($this->includeall
));
4877 * admin_setting_configselect for the default number of sections in a course,
4878 * simply so we can lazy-load the choices.
4880 * @copyright 2011 The Open University
4881 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4883 class admin_settings_num_course_sections
extends admin_setting_configselect
{
4884 public function __construct($name, $visiblename, $description, $defaultsetting) {
4885 parent
::__construct($name, $visiblename, $description, $defaultsetting, array());
4888 /** Lazy-load the available choices for the select box */
4889 public function load_choices() {
4890 $max = get_config('moodlecourse', 'maxsections');
4891 if (!isset($max) ||
!is_numeric($max)) {
4894 for ($i = 0; $i <= $max; $i++
) {
4895 $this->choices
[$i] = "$i";
4903 * Course category selection
4905 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4907 class admin_settings_coursecat_select
extends admin_setting_configselect
{
4909 * Calls parent::__construct with specific arguments
4911 public function __construct($name, $visiblename, $description, $defaultsetting) {
4912 parent
::__construct($name, $visiblename, $description, $defaultsetting, NULL);
4916 * Load the available choices for the select box
4920 public function load_choices() {
4922 require_once($CFG->dirroot
.'/course/lib.php');
4923 if (is_array($this->choices
)) {
4926 $this->choices
= make_categories_options();
4933 * Special control for selecting days to backup
4935 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4937 class admin_setting_special_backupdays
extends admin_setting_configmulticheckbox2
{
4939 * Calls parent::__construct with specific arguments
4941 public function __construct() {
4942 parent
::__construct('backup_auto_weekdays', get_string('automatedbackupschedule','backup'), get_string('automatedbackupschedulehelp','backup'), array(), NULL);
4943 $this->plugin
= 'backup';
4947 * Load the available choices for the select box
4949 * @return bool Always returns true
4951 public function load_choices() {
4952 if (is_array($this->choices
)) {
4955 $this->choices
= array();
4956 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
4957 foreach ($days as $day) {
4958 $this->choices
[$day] = get_string($day, 'calendar');
4965 * Special setting for backup auto destination.
4969 * @copyright 2014 Frédéric Massart - FMCorz.net
4970 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4972 class admin_setting_special_backup_auto_destination
extends admin_setting_configdirectory
{
4975 * Calls parent::__construct with specific arguments.
4977 public function __construct() {
4978 parent
::__construct('backup/backup_auto_destination', new lang_string('saveto'), new lang_string('backupsavetohelp'), '');
4982 * Check if the directory must be set, depending on backup/backup_auto_storage.
4984 * Note: backup/backup_auto_storage must be specified BEFORE this setting otherwise
4985 * there will be conflicts if this validation happens before the other one.
4987 * @param string $data Form data.
4988 * @return string Empty when no errors.
4990 public function write_setting($data) {
4991 $storage = (int) get_config('backup', 'backup_auto_storage');
4992 if ($storage !== 0) {
4993 if (empty($data) ||
!file_exists($data) ||
!is_dir($data) ||
!is_writable($data) ) {
4994 // The directory must exist and be writable.
4995 return get_string('backuperrorinvaliddestination');
4998 return parent
::write_setting($data);
5004 * Special debug setting
5006 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5008 class admin_setting_special_debug
extends admin_setting_configselect
{
5010 * Calls parent::__construct with specific arguments
5012 public function __construct() {
5013 parent
::__construct('debug', get_string('debug', 'admin'), get_string('configdebug', 'admin'), DEBUG_NONE
, NULL);
5017 * Load the available choices for the select box
5021 public function load_choices() {
5022 if (is_array($this->choices
)) {
5025 $this->choices
= array(DEBUG_NONE
=> get_string('debugnone', 'admin'),
5026 DEBUG_MINIMAL
=> get_string('debugminimal', 'admin'),
5027 DEBUG_NORMAL
=> get_string('debugnormal', 'admin'),
5028 DEBUG_ALL
=> get_string('debugall', 'admin'),
5029 DEBUG_DEVELOPER
=> get_string('debugdeveloper', 'admin'));
5036 * Special admin control
5038 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5040 class admin_setting_special_calendar_weekend
extends admin_setting
{
5042 * Calls parent::__construct with specific arguments
5044 public function __construct() {
5045 $name = 'calendar_weekend';
5046 $visiblename = get_string('calendar_weekend', 'admin');
5047 $description = get_string('helpweekenddays', 'admin');
5048 $default = array ('0', '6'); // Saturdays and Sundays
5049 parent
::__construct($name, $visiblename, $description, $default);
5053 * Gets the current settings as an array
5055 * @return mixed Null if none, else array of settings
5057 public function get_setting() {
5058 $result = $this->config_read($this->name
);
5059 if (is_null($result)) {
5062 if ($result === '') {
5065 $settings = array();
5066 for ($i=0; $i<7; $i++
) {
5067 if ($result & (1 << $i)) {
5075 * Save the new settings
5077 * @param array $data Array of new settings
5080 public function write_setting($data) {
5081 if (!is_array($data)) {
5084 unset($data['xxxxx']);
5086 foreach($data as $index) {
5087 $result |
= 1 << $index;
5089 return ($this->config_write($this->name
, $result) ?
'' : get_string('errorsetting', 'admin'));
5093 * Return XHTML to display the control
5095 * @param array $data array of selected days
5096 * @param string $query
5097 * @return string XHTML for display (field + wrapping div(s)
5099 public function output_html($data, $query='') {
5102 // The order matters very much because of the implied numeric keys.
5103 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
5104 $context = (object) [
5105 'name' => $this->get_full_name(),
5106 'id' => $this->get_id(),
5107 'days' => array_map(function($index) use ($days, $data) {
5110 'label' => get_string($days[$index], 'calendar'),
5111 'checked' => in_array($index, $data)
5113 }, array_keys($days))
5116 $element = $OUTPUT->render_from_template('core_admin/setting_special_calendar_weekend', $context);
5118 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, false, '', NULL, $query);
5125 * Admin setting that allows a user to pick a behaviour.
5127 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5129 class admin_setting_question_behaviour
extends admin_setting_configselect
{
5131 * @param string $name name of config variable
5132 * @param string $visiblename display name
5133 * @param string $description description
5134 * @param string $default default.
5136 public function __construct($name, $visiblename, $description, $default) {
5137 parent
::__construct($name, $visiblename, $description, $default, null);
5141 * Load list of behaviours as choices
5142 * @return bool true => success, false => error.
5144 public function load_choices() {
5146 require_once($CFG->dirroot
. '/question/engine/lib.php');
5147 $this->choices
= question_engine
::get_behaviour_options('');
5154 * Admin setting that allows a user to pick appropriate roles for something.
5156 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5158 class admin_setting_pickroles
extends admin_setting_configmulticheckbox
{
5159 /** @var array Array of capabilities which identify roles */
5163 * @param string $name Name of config variable
5164 * @param string $visiblename Display name
5165 * @param string $description Description
5166 * @param array $types Array of archetypes which identify
5167 * roles that will be enabled by default.
5169 public function __construct($name, $visiblename, $description, $types) {
5170 parent
::__construct($name, $visiblename, $description, NULL, NULL);
5171 $this->types
= $types;
5175 * Load roles as choices
5177 * @return bool true=>success, false=>error
5179 public function load_choices() {
5181 if (during_initial_install()) {
5184 if (is_array($this->choices
)) {
5187 if ($roles = get_all_roles()) {
5188 $this->choices
= role_fix_names($roles, null, ROLENAME_ORIGINAL
, true);
5196 * Return the default setting for this control
5198 * @return array Array of default settings
5200 public function get_defaultsetting() {
5203 if (during_initial_install()) {
5207 foreach($this->types
as $archetype) {
5208 if ($caproles = get_archetype_roles($archetype)) {
5209 foreach ($caproles as $caprole) {
5210 $result[$caprole->id
] = 1;
5220 * Admin setting that is a list of installed filter plugins.
5222 * @copyright 2015 The Open University
5223 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5225 class admin_setting_pickfilters
extends admin_setting_configmulticheckbox
{
5230 * @param string $name unique ascii name, either 'mysetting' for settings
5231 * that in config, or 'myplugin/mysetting' for ones in config_plugins.
5232 * @param string $visiblename localised name
5233 * @param string $description localised long description
5234 * @param array $default the default. E.g. array('urltolink' => 1, 'emoticons' => 1)
5236 public function __construct($name, $visiblename, $description, $default) {
5237 if (empty($default)) {
5240 $this->load_choices();
5241 foreach ($default as $plugin) {
5242 if (!isset($this->choices
[$plugin])) {
5243 unset($default[$plugin]);
5246 parent
::__construct($name, $visiblename, $description, $default, null);
5249 public function load_choices() {
5250 if (is_array($this->choices
)) {
5253 $this->choices
= array();
5255 foreach (core_component
::get_plugin_list('filter') as $plugin => $unused) {
5256 $this->choices
[$plugin] = filter_get_name($plugin);
5264 * Text field with an advanced checkbox, that controls a additional $name.'_adv' setting.
5266 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5268 class admin_setting_configtext_with_advanced
extends admin_setting_configtext
{
5271 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
5272 * @param string $visiblename localised
5273 * @param string $description long localised info
5274 * @param array $defaultsetting ('value'=>string, '__construct'=>bool)
5275 * @param mixed $paramtype int means PARAM_XXX type, string is a allowed format in regex
5276 * @param int $size default field size
5278 public function __construct($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW
, $size=null) {
5279 parent
::__construct($name, $visiblename, $description, $defaultsetting['value'], $paramtype, $size);
5280 $this->set_advanced_flag_options(admin_setting_flag
::ENABLED
, !empty($defaultsetting['adv']));
5286 * Checkbox with an advanced checkbox that controls an additional $name.'_adv' config setting.
5288 * @copyright 2009 Petr Skoda (http://skodak.org)
5289 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5291 class admin_setting_configcheckbox_with_advanced
extends admin_setting_configcheckbox
{
5295 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
5296 * @param string $visiblename localised
5297 * @param string $description long localised info
5298 * @param array $defaultsetting ('value'=>string, 'adv'=>bool)
5299 * @param string $yes value used when checked
5300 * @param string $no value used when not checked
5302 public function __construct($name, $visiblename, $description, $defaultsetting, $yes='1', $no='0') {
5303 parent
::__construct($name, $visiblename, $description, $defaultsetting['value'], $yes, $no);
5304 $this->set_advanced_flag_options(admin_setting_flag
::ENABLED
, !empty($defaultsetting['adv']));
5311 * Checkbox with an advanced checkbox that controls an additional $name.'_locked' config setting.
5313 * This is nearly a copy/paste of admin_setting_configcheckbox_with_adv
5315 * @copyright 2010 Sam Hemelryk
5316 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5318 class admin_setting_configcheckbox_with_lock
extends admin_setting_configcheckbox
{
5321 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins.
5322 * @param string $visiblename localised
5323 * @param string $description long localised info
5324 * @param array $defaultsetting ('value'=>string, 'locked'=>bool)
5325 * @param string $yes value used when checked
5326 * @param string $no value used when not checked
5328 public function __construct($name, $visiblename, $description, $defaultsetting, $yes='1', $no='0') {
5329 parent
::__construct($name, $visiblename, $description, $defaultsetting['value'], $yes, $no);
5330 $this->set_locked_flag_options(admin_setting_flag
::ENABLED
, !empty($defaultsetting['locked']));
5337 * Dropdown menu with an advanced checkbox, that controls a additional $name.'_adv' setting.
5339 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5341 class admin_setting_configselect_with_advanced
extends admin_setting_configselect
{
5343 * Calls parent::__construct with specific arguments
5345 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
5346 parent
::__construct($name, $visiblename, $description, $defaultsetting['value'], $choices);
5347 $this->set_advanced_flag_options(admin_setting_flag
::ENABLED
, !empty($defaultsetting['adv']));
5353 * Select with an advanced checkbox that controls an additional $name.'_locked' config setting.
5355 * @copyright 2017 Marina Glancy
5356 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5358 class admin_setting_configselect_with_lock
extends admin_setting_configselect
{
5361 * @param string $name unique ascii name, either 'mysetting' for settings that in config,
5362 * or 'myplugin/mysetting' for ones in config_plugins.
5363 * @param string $visiblename localised
5364 * @param string $description long localised info
5365 * @param array $defaultsetting ('value'=>string, 'locked'=>bool)
5366 * @param array $choices array of $value=>$label for each selection
5368 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
5369 parent
::__construct($name, $visiblename, $description, $defaultsetting['value'], $choices);
5370 $this->set_locked_flag_options(admin_setting_flag
::ENABLED
, !empty($defaultsetting['locked']));
5376 * Graded roles in gradebook
5378 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5380 class admin_setting_special_gradebookroles
extends admin_setting_pickroles
{
5382 * Calls parent::__construct with specific arguments
5384 public function __construct() {
5385 parent
::__construct('gradebookroles', get_string('gradebookroles', 'admin'),
5386 get_string('configgradebookroles', 'admin'),
5394 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5396 class admin_setting_regradingcheckbox
extends admin_setting_configcheckbox
{
5398 * Saves the new settings passed in $data
5400 * @param string $data
5401 * @return mixed string or Array
5403 public function write_setting($data) {
5406 $oldvalue = $this->config_read($this->name
);
5407 $return = parent
::write_setting($data);
5408 $newvalue = $this->config_read($this->name
);
5410 if ($oldvalue !== $newvalue) {
5411 // force full regrading
5412 $DB->set_field('grade_items', 'needsupdate', 1, array('needsupdate'=>0));
5421 * Which roles to show on course description page
5423 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5425 class admin_setting_special_coursecontact
extends admin_setting_pickroles
{
5427 * Calls parent::__construct with specific arguments
5429 public function __construct() {
5430 parent
::__construct('coursecontact', get_string('coursecontact', 'admin'),
5431 get_string('coursecontact_desc', 'admin'),
5432 array('editingteacher'));
5433 $this->set_updatedcallback(function (){
5434 cache
::make('core', 'coursecontacts')->purge();
5442 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5444 class admin_setting_special_gradelimiting
extends admin_setting_configcheckbox
{
5446 * Calls parent::__construct with specific arguments
5448 public function __construct() {
5449 parent
::__construct('unlimitedgrades', get_string('unlimitedgrades', 'grades'),
5450 get_string('unlimitedgrades_help', 'grades'), '0', '1', '0');
5454 * Old syntax of class constructor. Deprecated in PHP7.
5456 * @deprecated since Moodle 3.1
5458 public function admin_setting_special_gradelimiting() {
5459 debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER
);
5460 self
::__construct();
5464 * Force site regrading
5466 function regrade_all() {
5468 require_once("$CFG->libdir/gradelib.php");
5469 grade_force_site_regrading();
5473 * Saves the new settings
5475 * @param mixed $data
5476 * @return string empty string or error message
5478 function write_setting($data) {
5479 $previous = $this->get_setting();
5481 if ($previous === null) {
5483 $this->regrade_all();
5486 if ($data != $previous) {
5487 $this->regrade_all();
5490 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
5496 * Special setting for $CFG->grade_minmaxtouse.
5499 * @copyright 2015 Frédéric Massart - FMCorz.net
5500 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5502 class admin_setting_special_grademinmaxtouse
extends admin_setting_configselect
{
5507 public function __construct() {
5508 parent
::__construct('grade_minmaxtouse', new lang_string('minmaxtouse', 'grades'),
5509 new lang_string('minmaxtouse_desc', 'grades'), GRADE_MIN_MAX_FROM_GRADE_ITEM
,
5511 GRADE_MIN_MAX_FROM_GRADE_ITEM
=> get_string('gradeitemminmax', 'grades'),
5512 GRADE_MIN_MAX_FROM_GRADE_GRADE
=> get_string('gradegrademinmax', 'grades')
5518 * Saves the new setting.
5520 * @param mixed $data
5521 * @return string empty string or error message
5523 function write_setting($data) {
5526 $previous = $this->get_setting();
5527 $result = parent
::write_setting($data);
5529 // If saved and the value has changed.
5530 if (empty($result) && $previous != $data) {
5531 require_once($CFG->libdir
. '/gradelib.php');
5532 grade_force_site_regrading();
5542 * Primary grade export plugin - has state tracking.
5544 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5546 class admin_setting_special_gradeexport
extends admin_setting_configmulticheckbox
{
5548 * Calls parent::__construct with specific arguments
5550 public function __construct() {
5551 parent
::__construct('gradeexport', get_string('gradeexport', 'admin'),
5552 get_string('configgradeexport', 'admin'), array(), NULL);
5556 * Load the available choices for the multicheckbox
5558 * @return bool always returns true
5560 public function load_choices() {
5561 if (is_array($this->choices
)) {
5564 $this->choices
= array();
5566 if ($plugins = core_component
::get_plugin_list('gradeexport')) {
5567 foreach($plugins as $plugin => $unused) {
5568 $this->choices
[$plugin] = get_string('pluginname', 'gradeexport_'.$plugin);
5577 * A setting for setting the default grade point value. Must be an integer between 1 and $CFG->gradepointmax.
5579 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5581 class admin_setting_special_gradepointdefault
extends admin_setting_configtext
{
5583 * Config gradepointmax constructor
5585 * @param string $name Overidden by "gradepointmax"
5586 * @param string $visiblename Overridden by "gradepointmax" language string.
5587 * @param string $description Overridden by "gradepointmax_help" language string.
5588 * @param string $defaultsetting Not used, overridden by 100.
5589 * @param mixed $paramtype Overridden by PARAM_INT.
5590 * @param int $size Overridden by 5.
5592 public function __construct($name = '', $visiblename = '', $description = '', $defaultsetting = '', $paramtype = PARAM_INT
, $size = 5) {
5593 $name = 'gradepointdefault';
5594 $visiblename = get_string('gradepointdefault', 'grades');
5595 $description = get_string('gradepointdefault_help', 'grades');
5596 $defaultsetting = 100;
5597 $paramtype = PARAM_INT
;
5599 parent
::__construct($name, $visiblename, $description, $defaultsetting, $paramtype, $size);
5603 * Validate data before storage
5604 * @param string $data The submitted data
5605 * @return bool|string true if ok, string if error found
5607 public function validate($data) {
5609 if (((string)(int)$data === (string)$data && $data > 0 && $data <= $CFG->gradepointmax
)) {
5612 return get_string('gradepointdefault_validateerror', 'grades');
5619 * A setting for setting the maximum grade value. Must be an integer between 1 and 10000.
5621 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5623 class admin_setting_special_gradepointmax
extends admin_setting_configtext
{
5626 * Config gradepointmax constructor
5628 * @param string $name Overidden by "gradepointmax"
5629 * @param string $visiblename Overridden by "gradepointmax" language string.
5630 * @param string $description Overridden by "gradepointmax_help" language string.
5631 * @param string $defaultsetting Not used, overridden by 100.
5632 * @param mixed $paramtype Overridden by PARAM_INT.
5633 * @param int $size Overridden by 5.
5635 public function __construct($name = '', $visiblename = '', $description = '', $defaultsetting = '', $paramtype = PARAM_INT
, $size = 5) {
5636 $name = 'gradepointmax';
5637 $visiblename = get_string('gradepointmax', 'grades');
5638 $description = get_string('gradepointmax_help', 'grades');
5639 $defaultsetting = 100;
5640 $paramtype = PARAM_INT
;
5642 parent
::__construct($name, $visiblename, $description, $defaultsetting, $paramtype, $size);
5646 * Save the selected setting
5648 * @param string $data The selected site
5649 * @return string empty string or error message
5651 public function write_setting($data) {
5653 $data = (int)$this->defaultsetting
;
5657 return parent
::write_setting($data);
5661 * Validate data before storage
5662 * @param string $data The submitted data
5663 * @return bool|string true if ok, string if error found
5665 public function validate($data) {
5666 if (((string)(int)$data === (string)$data && $data > 0 && $data <= 10000)) {
5669 return get_string('gradepointmax_validateerror', 'grades');
5674 * Return an XHTML string for the setting
5675 * @param array $data Associative array of value=>xx, forced=>xx, adv=>xx
5676 * @param string $query search query to be highlighted
5677 * @return string XHTML to display control
5679 public function output_html($data, $query = '') {
5682 $default = $this->get_defaultsetting();
5683 $context = (object) [
5684 'size' => $this->size
,
5685 'id' => $this->get_id(),
5686 'name' => $this->get_full_name(),
5691 'forceltr' => $this->get_force_ltr()
5693 $element = $OUTPUT->render_from_template('core_admin/setting_configtext', $context);
5695 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, true, '', $default, $query);
5701 * Grade category settings
5703 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5705 class admin_setting_gradecat_combo
extends admin_setting
{
5706 /** @var array Array of choices */
5710 * Sets choices and calls parent::__construct with passed arguments
5711 * @param string $name
5712 * @param string $visiblename
5713 * @param string $description
5714 * @param mixed $defaultsetting string or array depending on implementation
5715 * @param array $choices An array of choices for the control
5717 public function __construct($name, $visiblename, $description, $defaultsetting, $choices) {
5718 $this->choices
= $choices;
5719 parent
::__construct($name, $visiblename, $description, $defaultsetting);
5723 * Return the current setting(s) array
5725 * @return array Array of value=>xx, forced=>xx, adv=>xx
5727 public function get_setting() {
5730 $value = $this->config_read($this->name
);
5731 $flag = $this->config_read($this->name
.'_flag');
5733 if (is_null($value) or is_null($flag)) {
5738 $forced = (boolean
)(1 & $flag); // first bit
5739 $adv = (boolean
)(2 & $flag); // second bit
5741 return array('value' => $value, 'forced' => $forced, 'adv' => $adv);
5745 * Save the new settings passed in $data
5747 * @todo Add vartype handling to ensure $data is array
5748 * @param array $data Associative array of value=>xx, forced=>xx, adv=>xx
5749 * @return string empty or error message
5751 public function write_setting($data) {
5754 $value = $data['value'];
5755 $forced = empty($data['forced']) ?
0 : 1;
5756 $adv = empty($data['adv']) ?
0 : 2;
5757 $flag = ($forced |
$adv); //bitwise or
5759 if (!in_array($value, array_keys($this->choices
))) {
5760 return 'Error setting ';
5763 $oldvalue = $this->config_read($this->name
);
5764 $oldflag = (int)$this->config_read($this->name
.'_flag');
5765 $oldforced = (1 & $oldflag); // first bit
5767 $result1 = $this->config_write($this->name
, $value);
5768 $result2 = $this->config_write($this->name
.'_flag', $flag);
5770 // force regrade if needed
5771 if ($oldforced != $forced or ($forced and $value != $oldvalue)) {
5772 require_once($CFG->libdir
.'/gradelib.php');
5773 grade_category
::updated_forced_settings();
5776 if ($result1 and $result2) {
5779 return get_string('errorsetting', 'admin');
5784 * Return XHTML to display the field and wrapping div
5786 * @todo Add vartype handling to ensure $data is array
5787 * @param array $data Associative array of value=>xx, forced=>xx, adv=>xx
5788 * @param string $query
5789 * @return string XHTML to display control
5791 public function output_html($data, $query='') {
5794 $value = $data['value'];
5796 $default = $this->get_defaultsetting();
5797 if (!is_null($default)) {
5798 $defaultinfo = array();
5799 if (isset($this->choices
[$default['value']])) {
5800 $defaultinfo[] = $this->choices
[$default['value']];
5802 if (!empty($default['forced'])) {
5803 $defaultinfo[] = get_string('force');
5805 if (!empty($default['adv'])) {
5806 $defaultinfo[] = get_string('advanced');
5808 $defaultinfo = implode(', ', $defaultinfo);
5811 $defaultinfo = NULL;
5814 $options = $this->choices
;
5815 $context = (object) [
5816 'id' => $this->get_id(),
5817 'name' => $this->get_full_name(),
5818 'forced' => !empty($data['forced']),
5819 'advanced' => !empty($data['adv']),
5820 'options' => array_map(function($option) use ($options, $value) {
5823 'name' => $options[$option],
5824 'selected' => $option == $value
5826 }, array_keys($options)),
5829 $element = $OUTPUT->render_from_template('core_admin/setting_gradecat_combo', $context);
5831 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, true, '', $defaultinfo, $query);
5837 * Selection of grade report in user profiles
5839 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5841 class admin_setting_grade_profilereport
extends admin_setting_configselect
{
5843 * Calls parent::__construct with specific arguments
5845 public function __construct() {
5846 parent
::__construct('grade_profilereport', get_string('profilereport', 'grades'), get_string('profilereport_help', 'grades'), 'user', null);
5850 * Loads an array of choices for the configselect control
5852 * @return bool always return true
5854 public function load_choices() {
5855 if (is_array($this->choices
)) {
5858 $this->choices
= array();
5861 require_once($CFG->libdir
.'/gradelib.php');
5863 foreach (core_component
::get_plugin_list('gradereport') as $plugin => $plugindir) {
5864 if (file_exists($plugindir.'/lib.php')) {
5865 require_once($plugindir.'/lib.php');
5866 $functionname = 'grade_report_'.$plugin.'_profilereport';
5867 if (function_exists($functionname)) {
5868 $this->choices
[$plugin] = get_string('pluginname', 'gradereport_'.$plugin);
5877 * Provides a selection of grade reports to be used for "grades".
5879 * @copyright 2015 Adrian Greeve <adrian@moodle.com>
5880 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5882 class admin_setting_my_grades_report
extends admin_setting_configselect
{
5885 * Calls parent::__construct with specific arguments.
5887 public function __construct() {
5888 parent
::__construct('grade_mygrades_report', new lang_string('mygrades', 'grades'),
5889 new lang_string('mygrades_desc', 'grades'), 'overview', null);
5893 * Loads an array of choices for the configselect control.
5895 * @return bool always returns true.
5897 public function load_choices() {
5898 global $CFG; // Remove this line and behold the horror of behat test failures!
5899 $this->choices
= array();
5900 foreach (core_component
::get_plugin_list('gradereport') as $plugin => $plugindir) {
5901 if (file_exists($plugindir . '/lib.php')) {
5902 require_once($plugindir . '/lib.php');
5903 // Check to see if the class exists. Check the correct plugin convention first.
5904 if (class_exists('gradereport_' . $plugin)) {
5905 $classname = 'gradereport_' . $plugin;
5906 } else if (class_exists('grade_report_' . $plugin)) {
5907 // We are using the old plugin naming convention.
5908 $classname = 'grade_report_' . $plugin;
5912 if ($classname::supports_mygrades()) {
5913 $this->choices
[$plugin] = get_string('pluginname', 'gradereport_' . $plugin);
5917 // Add an option to specify an external url.
5918 $this->choices
['external'] = get_string('externalurl', 'grades');
5924 * Special class for register auth selection
5926 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5928 class admin_setting_special_registerauth
extends admin_setting_configselect
{
5930 * Calls parent::__construct with specific arguments
5932 public function __construct() {
5933 parent
::__construct('registerauth', get_string('selfregistration', 'auth'), get_string('selfregistration_help', 'auth'), '', null);
5937 * Returns the default option
5939 * @return string empty or default option
5941 public function get_defaultsetting() {
5942 $this->load_choices();
5943 $defaultsetting = parent
::get_defaultsetting();
5944 if (array_key_exists($defaultsetting, $this->choices
)) {
5945 return $defaultsetting;
5952 * Loads the possible choices for the array
5954 * @return bool always returns true
5956 public function load_choices() {
5959 if (is_array($this->choices
)) {
5962 $this->choices
= array();
5963 $this->choices
[''] = get_string('disable');
5965 $authsenabled = get_enabled_auth_plugins(true);
5967 foreach ($authsenabled as $auth) {
5968 $authplugin = get_auth_plugin($auth);
5969 if (!$authplugin->can_signup()) {
5972 // Get the auth title (from core or own auth lang files)
5973 $authtitle = $authplugin->get_title();
5974 $this->choices
[$auth] = $authtitle;
5982 * General plugins manager
5984 class admin_page_pluginsoverview
extends admin_externalpage
{
5987 * Sets basic information about the external page
5989 public function __construct() {
5991 parent
::__construct('pluginsoverview', get_string('pluginsoverview', 'core_admin'),
5992 "$CFG->wwwroot/$CFG->admin/plugins.php");
5997 * Module manage page
5999 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
6001 class admin_page_managemods
extends admin_externalpage
{
6003 * Calls parent::__construct with specific arguments
6005 public function __construct() {
6007 parent
::__construct('managemodules', get_string('modsettings', 'admin'), "$CFG->wwwroot/$CFG->admin/modules.php");
6011 * Try to find the specified module
6013 * @param string $query The module to search for
6016 public function search($query) {
6018 if ($result = parent
::search($query)) {
6023 if ($modules = $DB->get_records('modules')) {
6024 foreach ($modules as $module) {
6025 if (!file_exists("$CFG->dirroot/mod/$module->name/lib.php")) {
6028 if (strpos($module->name
, $query) !== false) {
6032 $strmodulename = get_string('modulename', $module->name
);
6033 if (strpos(core_text
::strtolower($strmodulename), $query) !== false) {
6040 $result = new stdClass();
6041 $result->page
= $this;
6042 $result->settings
= array();
6043 return array($this->name
=> $result);
6052 * Special class for enrol plugins management.
6054 * @copyright 2010 Petr Skoda {@link http://skodak.org}
6055 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
6057 class admin_setting_manageenrols
extends admin_setting
{
6059 * Calls parent::__construct with specific arguments
6061 public function __construct() {
6062 $this->nosave
= true;
6063 parent
::__construct('enrolsui', get_string('manageenrols', 'enrol'), '', '');
6067 * Always returns true, does nothing
6071 public function get_setting() {
6076 * Always returns true, does nothing
6080 public function get_defaultsetting() {
6085 * Always returns '', does not write anything
6087 * @return string Always returns ''
6089 public function write_setting($data) {
6090 // do not write any setting
6095 * Checks if $query is one of the available enrol plugins
6097 * @param string $query The string to search for
6098 * @return bool Returns true if found, false if not
6100 public function is_related($query) {
6101 if (parent
::is_related($query)) {
6105 $query = core_text
::strtolower($query);
6106 $enrols = enrol_get_plugins(false);
6107 foreach ($enrols as $name=>$enrol) {
6108 $localised = get_string('pluginname', 'enrol_'.$name);
6109 if (strpos(core_text
::strtolower($name), $query) !== false) {
6112 if (strpos(core_text
::strtolower($localised), $query) !== false) {
6120 * Builds the XHTML to display the control
6122 * @param string $data Unused
6123 * @param string $query
6126 public function output_html($data, $query='') {
6127 global $CFG, $OUTPUT, $DB, $PAGE;
6130 $strup = get_string('up');
6131 $strdown = get_string('down');
6132 $strsettings = get_string('settings');
6133 $strenable = get_string('enable');
6134 $strdisable = get_string('disable');
6135 $struninstall = get_string('uninstallplugin', 'core_admin');
6136 $strusage = get_string('enrolusage', 'enrol');
6137 $strversion = get_string('version');
6138 $strtest = get_string('testsettings', 'core_enrol');
6140 $pluginmanager = core_plugin_manager
::instance();
6142 $enrols_available = enrol_get_plugins(false);
6143 $active_enrols = enrol_get_plugins(true);
6145 $allenrols = array();
6146 foreach ($active_enrols as $key=>$enrol) {
6147 $allenrols[$key] = true;
6149 foreach ($enrols_available as $key=>$enrol) {
6150 $allenrols[$key] = true;
6152 // Now find all borked plugins and at least allow then to uninstall.
6153 $condidates = $DB->get_fieldset_sql("SELECT DISTINCT enrol FROM {enrol}");
6154 foreach ($condidates as $candidate) {
6155 if (empty($allenrols[$candidate])) {
6156 $allenrols[$candidate] = true;
6160 $return = $OUTPUT->heading(get_string('actenrolshhdr', 'enrol'), 3, 'main', true);
6161 $return .= $OUTPUT->box_start('generalbox enrolsui');
6163 $table = new html_table();
6164 $table->head
= array(get_string('name'), $strusage, $strversion, $strenable, $strup.'/'.$strdown, $strsettings, $strtest, $struninstall);
6165 $table->colclasses
= array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign', 'centeralign', 'centeralign', 'centeralign');
6166 $table->id
= 'courseenrolmentplugins';
6167 $table->attributes
['class'] = 'admintable generaltable';
6168 $table->data
= array();
6170 // Iterate through enrol plugins and add to the display table.
6172 $enrolcount = count($active_enrols);
6173 $url = new moodle_url('/admin/enrol.php', array('sesskey'=>sesskey()));
6175 foreach($allenrols as $enrol => $unused) {
6176 $plugininfo = $pluginmanager->get_plugin_info('enrol_'.$enrol);
6177 $version = get_config('enrol_'.$enrol, 'version');
6178 if ($version === false) {
6182 if (get_string_manager()->string_exists('pluginname', 'enrol_'.$enrol)) {
6183 $name = get_string('pluginname', 'enrol_'.$enrol);
6188 $ci = $DB->count_records('enrol', array('enrol'=>$enrol));
6189 $cp = $DB->count_records_select('user_enrolments', "enrolid IN (SELECT id FROM {enrol} WHERE enrol = ?)", array($enrol));
6190 $usage = "$ci / $cp";
6194 if (isset($active_enrols[$enrol])) {
6195 $aurl = new moodle_url($url, array('action'=>'disable', 'enrol'=>$enrol));
6196 $hideshow = "<a href=\"$aurl\">";
6197 $hideshow .= $OUTPUT->pix_icon('t/hide', $strdisable) . '</a>';
6199 $displayname = $name;
6200 } else if (isset($enrols_available[$enrol])) {
6201 $aurl = new moodle_url($url, array('action'=>'enable', 'enrol'=>$enrol));
6202 $hideshow = "<a href=\"$aurl\">";
6203 $hideshow .= $OUTPUT->pix_icon('t/show', $strenable) . '</a>';
6205 $displayname = $name;
6206 $class = 'dimmed_text';
6210 $displayname = '<span class="notifyproblem">'.$name.'</span>';
6212 if ($PAGE->theme
->resolve_image_location('icon', 'enrol_' . $name, false)) {
6213 $icon = $OUTPUT->pix_icon('icon', '', 'enrol_' . $name, array('class' => 'icon pluginicon'));
6215 $icon = $OUTPUT->pix_icon('spacer', '', 'moodle', array('class' => 'icon pluginicon noicon'));
6218 // Up/down link (only if enrol is enabled).
6221 if ($updowncount > 1) {
6222 $aurl = new moodle_url($url, array('action'=>'up', 'enrol'=>$enrol));
6223 $updown .= "<a href=\"$aurl\">";
6224 $updown .= $OUTPUT->pix_icon('t/up', $strup) . '</a> ';
6226 $updown .= $OUTPUT->spacer() . ' ';
6228 if ($updowncount < $enrolcount) {
6229 $aurl = new moodle_url($url, array('action'=>'down', 'enrol'=>$enrol));
6230 $updown .= "<a href=\"$aurl\">";
6231 $updown .= $OUTPUT->pix_icon('t/down', $strdown) . '</a> ';
6233 $updown .= $OUTPUT->spacer() . ' ';
6238 // Add settings link.
6241 } else if ($surl = $plugininfo->get_settings_url()) {
6242 $settings = html_writer
::link($surl, $strsettings);
6247 // Add uninstall info.
6249 if ($uninstallurl = core_plugin_manager
::instance()->get_uninstall_url('enrol_'.$enrol, 'manage')) {
6250 $uninstall = html_writer
::link($uninstallurl, $struninstall);
6254 if (!empty($enrols_available[$enrol]) and method_exists($enrols_available[$enrol], 'test_settings')) {
6255 $testsettingsurl = new moodle_url('/enrol/test_settings.php', array('enrol'=>$enrol, 'sesskey'=>sesskey()));
6256 $test = html_writer
::link($testsettingsurl, $strtest);
6259 // Add a row to the table.
6260 $row = new html_table_row(array($icon.$displayname, $usage, $version, $hideshow, $updown, $settings, $test, $uninstall));
6262 $row->attributes
['class'] = $class;
6264 $table->data
[] = $row;
6266 $printed[$enrol] = true;
6269 $return .= html_writer
::table($table);
6270 $return .= get_string('configenrolplugins', 'enrol').'<br />'.get_string('tablenosave', 'admin');
6271 $return .= $OUTPUT->box_end();
6272 return highlight($query, $return);
6278 * Blocks manage page
6280 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
6282 class admin_page_manageblocks
extends admin_externalpage
{
6284 * Calls parent::__construct with specific arguments
6286 public function __construct() {
6288 parent
::__construct('manageblocks', get_string('blocksettings', 'admin'), "$CFG->wwwroot/$CFG->admin/blocks.php");
6292 * Search for a specific block
6294 * @param string $query The string to search for
6297 public function search($query) {
6299 if ($result = parent
::search($query)) {
6304 if ($blocks = $DB->get_records('block')) {
6305 foreach ($blocks as $block) {
6306 if (!file_exists("$CFG->dirroot/blocks/$block->name/")) {
6309 if (strpos($block->name
, $query) !== false) {
6313 $strblockname = get_string('pluginname', 'block_'.$block->name
);
6314 if (strpos(core_text
::strtolower($strblockname), $query) !== false) {
6321 $result = new stdClass();
6322 $result->page
= $this;
6323 $result->settings
= array();
6324 return array($this->name
=> $result);
6332 * Message outputs configuration
6334 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
6336 class admin_page_managemessageoutputs
extends admin_externalpage
{
6338 * Calls parent::__construct with specific arguments
6340 public function __construct() {
6342 parent
::__construct('managemessageoutputs',
6343 get_string('defaultmessageoutputs', 'message'),
6344 new moodle_url('/admin/message.php')
6349 * Search for a specific message processor
6351 * @param string $query The string to search for
6354 public function search($query) {
6356 if ($result = parent
::search($query)) {
6361 if ($processors = get_message_processors()) {
6362 foreach ($processors as $processor) {
6363 if (!$processor->available
) {
6366 if (strpos($processor->name
, $query) !== false) {
6370 $strprocessorname = get_string('pluginname', 'message_'.$processor->name
);
6371 if (strpos(core_text
::strtolower($strprocessorname), $query) !== false) {
6378 $result = new stdClass();
6379 $result->page
= $this;
6380 $result->settings
= array();
6381 return array($this->name
=> $result);
6389 * Default message outputs configuration
6391 * @deprecated since Moodle 3.7 MDL-64495. Please use admin_page_managemessageoutputs instead.
6392 * @todo MDL-64866 This will be deleted in Moodle 4.1.
6394 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
6396 class admin_page_defaultmessageoutputs
extends admin_page_managemessageoutputs
{
6398 * Calls parent::__construct with specific arguments
6400 * @deprecated since Moodle 3.7 MDL-64495. Please use admin_page_managemessageoutputs instead.
6401 * @todo MDL-64866 This will be deleted in Moodle 4.1.
6403 public function __construct() {
6406 debugging('admin_page_defaultmessageoutputs class is deprecated. Please use admin_page_managemessageoutputs instead.',
6409 admin_externalpage
::__construct('defaultmessageoutputs', get_string('defaultmessageoutputs', 'message'), new moodle_url('/message/defaultoutputs.php'));
6415 * Manage question behaviours page
6417 * @copyright 2011 The Open University
6418 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
6420 class admin_page_manageqbehaviours
extends admin_externalpage
{
6424 public function __construct() {
6426 parent
::__construct('manageqbehaviours', get_string('manageqbehaviours', 'admin'),
6427 new moodle_url('/admin/qbehaviours.php'));
6431 * Search question behaviours for the specified string
6433 * @param string $query The string to search for in question behaviours
6436 public function search($query) {
6438 if ($result = parent
::search($query)) {
6443 require_once($CFG->dirroot
. '/question/engine/lib.php');
6444 foreach (core_component
::get_plugin_list('qbehaviour') as $behaviour => $notused) {
6445 if (strpos(core_text
::strtolower(question_engine
::get_behaviour_name($behaviour)),
6446 $query) !== false) {
6452 $result = new stdClass();
6453 $result->page
= $this;
6454 $result->settings
= array();
6455 return array($this->name
=> $result);
6464 * Question type manage page
6466 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
6468 class admin_page_manageqtypes
extends admin_externalpage
{
6470 * Calls parent::__construct with specific arguments
6472 public function __construct() {
6474 parent
::__construct('manageqtypes', get_string('manageqtypes', 'admin'),
6475 new moodle_url('/admin/qtypes.php'));
6479 * Search question types for the specified string
6481 * @param string $query The string to search for in question types
6484 public function search($query) {
6486 if ($result = parent
::search($query)) {
6491 require_once($CFG->dirroot
. '/question/engine/bank.php');
6492 foreach (question_bank
::get_all_qtypes() as $qtype) {
6493 if (strpos(core_text
::strtolower($qtype->local_name()), $query) !== false) {
6499 $result = new stdClass();
6500 $result->page
= $this;
6501 $result->settings
= array();
6502 return array($this->name
=> $result);
6510 class admin_page_manageportfolios
extends admin_externalpage
{
6512 * Calls parent::__construct with specific arguments
6514 public function __construct() {
6516 parent
::__construct('manageportfolios', get_string('manageportfolios', 'portfolio'),
6517 "$CFG->wwwroot/$CFG->admin/portfolio.php");
6521 * Searches page for the specified string.
6522 * @param string $query The string to search for
6523 * @return bool True if it is found on this page
6525 public function search($query) {
6527 if ($result = parent
::search($query)) {
6532 $portfolios = core_component
::get_plugin_list('portfolio');
6533 foreach ($portfolios as $p => $dir) {
6534 if (strpos($p, $query) !== false) {
6540 foreach (portfolio_instances(false, false) as $instance) {
6541 $title = $instance->get('name');
6542 if (strpos(core_text
::strtolower($title), $query) !== false) {
6550 $result = new stdClass();
6551 $result->page
= $this;
6552 $result->settings
= array();
6553 return array($this->name
=> $result);
6561 class admin_page_managerepositories
extends admin_externalpage
{
6563 * Calls parent::__construct with specific arguments
6565 public function __construct() {
6567 parent
::__construct('managerepositories', get_string('manage',
6568 'repository'), "$CFG->wwwroot/$CFG->admin/repository.php");
6572 * Searches page for the specified string.
6573 * @param string $query The string to search for
6574 * @return bool True if it is found on this page
6576 public function search($query) {
6578 if ($result = parent
::search($query)) {
6583 $repositories= core_component
::get_plugin_list('repository');
6584 foreach ($repositories as $p => $dir) {
6585 if (strpos($p, $query) !== false) {
6591 foreach (repository
::get_types() as $instance) {
6592 $title = $instance->get_typename();
6593 if (strpos(core_text
::strtolower($title), $query) !== false) {
6601 $result = new stdClass();
6602 $result->page
= $this;
6603 $result->settings
= array();
6604 return array($this->name
=> $result);
6613 * Special class for authentication administration.
6615 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
6617 class admin_setting_manageauths
extends admin_setting
{
6619 * Calls parent::__construct with specific arguments
6621 public function __construct() {
6622 $this->nosave
= true;
6623 parent
::__construct('authsui', get_string('authsettings', 'admin'), '', '');
6627 * Always returns true
6631 public function get_setting() {
6636 * Always returns true
6640 public function get_defaultsetting() {
6645 * Always returns '' and doesn't write anything
6647 * @return string Always returns ''
6649 public function write_setting($data) {
6650 // do not write any setting
6655 * Search to find if Query is related to auth plugin
6657 * @param string $query The string to search for
6658 * @return bool true for related false for not
6660 public function is_related($query) {
6661 if (parent
::is_related($query)) {
6665 $authsavailable = core_component
::get_plugin_list('auth');
6666 foreach ($authsavailable as $auth => $dir) {
6667 if (strpos($auth, $query) !== false) {
6670 $authplugin = get_auth_plugin($auth);
6671 $authtitle = $authplugin->get_title();
6672 if (strpos(core_text
::strtolower($authtitle), $query) !== false) {
6680 * Return XHTML to display control
6682 * @param mixed $data Unused
6683 * @param string $query
6684 * @return string highlight
6686 public function output_html($data, $query='') {
6687 global $CFG, $OUTPUT, $DB;
6690 $txt = get_strings(array('authenticationplugins', 'users', 'administration',
6691 'settings', 'edit', 'name', 'enable', 'disable',
6692 'up', 'down', 'none', 'users'));
6693 $txt->updown
= "$txt->up/$txt->down";
6694 $txt->uninstall
= get_string('uninstallplugin', 'core_admin');
6695 $txt->testsettings
= get_string('testsettings', 'core_auth');
6697 $authsavailable = core_component
::get_plugin_list('auth');
6698 get_enabled_auth_plugins(true); // fix the list of enabled auths
6699 if (empty($CFG->auth
)) {
6700 $authsenabled = array();
6702 $authsenabled = explode(',', $CFG->auth
);
6705 // construct the display array, with enabled auth plugins at the top, in order
6706 $displayauths = array();
6707 $registrationauths = array();
6708 $registrationauths[''] = $txt->disable
;
6709 $authplugins = array();
6710 foreach ($authsenabled as $auth) {
6711 $authplugin = get_auth_plugin($auth);
6712 $authplugins[$auth] = $authplugin;
6713 /// Get the auth title (from core or own auth lang files)
6714 $authtitle = $authplugin->get_title();
6716 $displayauths[$auth] = $authtitle;
6717 if ($authplugin->can_signup()) {
6718 $registrationauths[$auth] = $authtitle;
6722 foreach ($authsavailable as $auth => $dir) {
6723 if (array_key_exists($auth, $displayauths)) {
6724 continue; //already in the list
6726 $authplugin = get_auth_plugin($auth);
6727 $authplugins[$auth] = $authplugin;
6728 /// Get the auth title (from core or own auth lang files)
6729 $authtitle = $authplugin->get_title();
6731 $displayauths[$auth] = $authtitle;
6732 if ($authplugin->can_signup()) {
6733 $registrationauths[$auth] = $authtitle;
6737 $return = $OUTPUT->heading(get_string('actauthhdr', 'auth'), 3, 'main');
6738 $return .= $OUTPUT->box_start('generalbox authsui');
6740 $table = new html_table();
6741 $table->head
= array($txt->name
, $txt->users
, $txt->enable
, $txt->updown
, $txt->settings
, $txt->testsettings
, $txt->uninstall
);
6742 $table->colclasses
= array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign', 'centeralign', 'centeralign');
6743 $table->data
= array();
6744 $table->attributes
['class'] = 'admintable generaltable';
6745 $table->id
= 'manageauthtable';
6747 //add always enabled plugins first
6748 $displayname = $displayauths['manual'];
6749 $settings = "<a href=\"settings.php?section=authsettingmanual\">{$txt->settings}</a>";
6750 $usercount = $DB->count_records('user', array('auth'=>'manual', 'deleted'=>0));
6751 $table->data
[] = array($displayname, $usercount, '', '', $settings, '', '');
6752 $displayname = $displayauths['nologin'];
6753 $usercount = $DB->count_records('user', array('auth'=>'nologin', 'deleted'=>0));
6754 $table->data
[] = array($displayname, $usercount, '', '', '', '', '');
6757 // iterate through auth plugins and add to the display table
6759 $authcount = count($authsenabled);
6760 $url = "auth.php?sesskey=" . sesskey();
6761 foreach ($displayauths as $auth => $name) {
6762 if ($auth == 'manual' or $auth == 'nologin') {
6767 if (in_array($auth, $authsenabled)) {
6768 $hideshow = "<a href=\"$url&action=disable&auth=$auth\">";
6769 $hideshow .= $OUTPUT->pix_icon('t/hide', get_string('disable')) . '</a>';
6771 $displayname = $name;
6774 $hideshow = "<a href=\"$url&action=enable&auth=$auth\">";
6775 $hideshow .= $OUTPUT->pix_icon('t/show', get_string('enable')) . '</a>';
6777 $displayname = $name;
6778 $class = 'dimmed_text';
6781 $usercount = $DB->count_records('user', array('auth'=>$auth, 'deleted'=>0));
6783 // up/down link (only if auth is enabled)
6786 if ($updowncount > 1) {
6787 $updown .= "<a href=\"$url&action=up&auth=$auth\">";
6788 $updown .= $OUTPUT->pix_icon('t/up', get_string('moveup')) . '</a> ';
6791 $updown .= $OUTPUT->spacer() . ' ';
6793 if ($updowncount < $authcount) {
6794 $updown .= "<a href=\"$url&action=down&auth=$auth\">";
6795 $updown .= $OUTPUT->pix_icon('t/down', get_string('movedown')) . '</a> ';
6798 $updown .= $OUTPUT->spacer() . ' ';
6804 if (file_exists($CFG->dirroot
.'/auth/'.$auth.'/settings.php')) {
6805 $settings = "<a href=\"settings.php?section=authsetting$auth\">{$txt->settings}</a>";
6806 } else if (file_exists($CFG->dirroot
.'/auth/'.$auth.'/config.html')) {
6807 $settings = "<a href=\"auth_config.php?auth=$auth\">{$txt->settings}</a>";
6814 if ($uninstallurl = core_plugin_manager
::instance()->get_uninstall_url('auth_'.$auth, 'manage')) {
6815 $uninstall = html_writer
::link($uninstallurl, $txt->uninstall
);
6819 if (!empty($authplugins[$auth]) and method_exists($authplugins[$auth], 'test_settings')) {
6820 $testurl = new moodle_url('/auth/test_settings.php', array('auth'=>$auth, 'sesskey'=>sesskey()));
6821 $test = html_writer
::link($testurl, $txt->testsettings
);
6824 // Add a row to the table.
6825 $row = new html_table_row(array($displayname, $usercount, $hideshow, $updown, $settings, $test, $uninstall));
6827 $row->attributes
['class'] = $class;
6829 $table->data
[] = $row;
6831 $return .= html_writer
::table($table);
6832 $return .= get_string('configauthenticationplugins', 'admin').'<br />'.get_string('tablenosave', 'filters');
6833 $return .= $OUTPUT->box_end();
6834 return highlight($query, $return);
6840 * Special class for authentication administration.
6842 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
6844 class admin_setting_manageeditors
extends admin_setting
{
6846 * Calls parent::__construct with specific arguments
6848 public function __construct() {
6849 $this->nosave
= true;
6850 parent
::__construct('editorsui', get_string('editorsettings', 'editor'), '', '');
6854 * Always returns true, does nothing
6858 public function get_setting() {
6863 * Always returns true, does nothing
6867 public function get_defaultsetting() {
6872 * Always returns '', does not write anything
6874 * @return string Always returns ''
6876 public function write_setting($data) {
6877 // do not write any setting
6882 * Checks if $query is one of the available editors
6884 * @param string $query The string to search for
6885 * @return bool Returns true if found, false if not
6887 public function is_related($query) {
6888 if (parent
::is_related($query)) {
6892 $editors_available = editors_get_available();
6893 foreach ($editors_available as $editor=>$editorstr) {
6894 if (strpos($editor, $query) !== false) {
6897 if (strpos(core_text
::strtolower($editorstr), $query) !== false) {
6905 * Builds the XHTML to display the control
6907 * @param string $data Unused
6908 * @param string $query
6911 public function output_html($data, $query='') {
6912 global $CFG, $OUTPUT;
6915 $txt = get_strings(array('administration', 'settings', 'edit', 'name', 'enable', 'disable',
6916 'up', 'down', 'none'));
6917 $struninstall = get_string('uninstallplugin', 'core_admin');
6919 $txt->updown
= "$txt->up/$txt->down";
6921 $editors_available = editors_get_available();
6922 $active_editors = explode(',', $CFG->texteditors
);
6924 $active_editors = array_reverse($active_editors);
6925 foreach ($active_editors as $key=>$editor) {
6926 if (empty($editors_available[$editor])) {
6927 unset($active_editors[$key]);
6929 $name = $editors_available[$editor];
6930 unset($editors_available[$editor]);
6931 $editors_available[$editor] = $name;
6934 if (empty($active_editors)) {
6935 //$active_editors = array('textarea');
6937 $editors_available = array_reverse($editors_available, true);
6938 $return = $OUTPUT->heading(get_string('acteditorshhdr', 'editor'), 3, 'main', true);
6939 $return .= $OUTPUT->box_start('generalbox editorsui');
6941 $table = new html_table();
6942 $table->head
= array($txt->name
, $txt->enable
, $txt->updown
, $txt->settings
, $struninstall);
6943 $table->colclasses
= array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign');
6944 $table->id
= 'editormanagement';
6945 $table->attributes
['class'] = 'admintable generaltable';
6946 $table->data
= array();
6948 // iterate through auth plugins and add to the display table
6950 $editorcount = count($active_editors);
6951 $url = "editors.php?sesskey=" . sesskey();
6952 foreach ($editors_available as $editor => $name) {
6955 if (in_array($editor, $active_editors)) {
6956 $hideshow = "<a href=\"$url&action=disable&editor=$editor\">";
6957 $hideshow .= $OUTPUT->pix_icon('t/hide', get_string('disable')) . '</a>';
6959 $displayname = $name;
6962 $hideshow = "<a href=\"$url&action=enable&editor=$editor\">";
6963 $hideshow .= $OUTPUT->pix_icon('t/show', get_string('enable')) . '</a>';
6965 $displayname = $name;
6966 $class = 'dimmed_text';
6969 // up/down link (only if auth is enabled)
6972 if ($updowncount > 1) {
6973 $updown .= "<a href=\"$url&action=up&editor=$editor\">";
6974 $updown .= $OUTPUT->pix_icon('t/up', get_string('moveup')) . '</a> ';
6977 $updown .= $OUTPUT->spacer() . ' ';
6979 if ($updowncount < $editorcount) {
6980 $updown .= "<a href=\"$url&action=down&editor=$editor\">";
6981 $updown .= $OUTPUT->pix_icon('t/down', get_string('movedown')) . '</a> ';
6984 $updown .= $OUTPUT->spacer() . ' ';
6990 if (file_exists($CFG->dirroot
.'/lib/editor/'.$editor.'/settings.php')) {
6991 $eurl = new moodle_url('/admin/settings.php', array('section'=>'editorsettings'.$editor));
6992 $settings = "<a href='$eurl'>{$txt->settings}</a>";
6998 if ($uninstallurl = core_plugin_manager
::instance()->get_uninstall_url('editor_'.$editor, 'manage')) {
6999 $uninstall = html_writer
::link($uninstallurl, $struninstall);
7002 // Add a row to the table.
7003 $row = new html_table_row(array($displayname, $hideshow, $updown, $settings, $uninstall));
7005 $row->attributes
['class'] = $class;
7007 $table->data
[] = $row;
7009 $return .= html_writer
::table($table);
7010 $return .= get_string('configeditorplugins', 'editor').'<br />'.get_string('tablenosave', 'admin');
7011 $return .= $OUTPUT->box_end();
7012 return highlight($query, $return);
7017 * Special class for antiviruses administration.
7019 * @copyright 2015 Ruslan Kabalin, Lancaster University.
7020 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
7022 class admin_setting_manageantiviruses
extends admin_setting
{
7024 * Calls parent::__construct with specific arguments
7026 public function __construct() {
7027 $this->nosave
= true;
7028 parent
::__construct('antivirusesui', get_string('antivirussettings', 'antivirus'), '', '');
7032 * Always returns true, does nothing
7036 public function get_setting() {
7041 * Always returns true, does nothing
7045 public function get_defaultsetting() {
7050 * Always returns '', does not write anything
7052 * @param string $data Unused
7053 * @return string Always returns ''
7055 public function write_setting($data) {
7056 // Do not write any setting.
7061 * Checks if $query is one of the available editors
7063 * @param string $query The string to search for
7064 * @return bool Returns true if found, false if not
7066 public function is_related($query) {
7067 if (parent
::is_related($query)) {
7071 $antivirusesavailable = \core\antivirus\manager
::get_available();
7072 foreach ($antivirusesavailable as $antivirus => $antivirusstr) {
7073 if (strpos($antivirus, $query) !== false) {
7076 if (strpos(core_text
::strtolower($antivirusstr), $query) !== false) {
7084 * Builds the XHTML to display the control
7086 * @param string $data Unused
7087 * @param string $query
7090 public function output_html($data, $query='') {
7091 global $CFG, $OUTPUT;
7094 $txt = get_strings(array('administration', 'settings', 'edit', 'name', 'enable', 'disable',
7095 'up', 'down', 'none'));
7096 $struninstall = get_string('uninstallplugin', 'core_admin');
7098 $txt->updown
= "$txt->up/$txt->down";
7100 $antivirusesavailable = \core\antivirus\manager
::get_available();
7101 $activeantiviruses = explode(',', $CFG->antiviruses
);
7103 $activeantiviruses = array_reverse($activeantiviruses);
7104 foreach ($activeantiviruses as $key => $antivirus) {
7105 if (empty($antivirusesavailable[$antivirus])) {
7106 unset($activeantiviruses[$key]);
7108 $name = $antivirusesavailable[$antivirus];
7109 unset($antivirusesavailable[$antivirus]);
7110 $antivirusesavailable[$antivirus] = $name;
7113 $antivirusesavailable = array_reverse($antivirusesavailable, true);
7114 $return = $OUTPUT->heading(get_string('actantivirushdr', 'antivirus'), 3, 'main', true);
7115 $return .= $OUTPUT->box_start('generalbox antivirusesui');
7117 $table = new html_table();
7118 $table->head
= array($txt->name
, $txt->enable
, $txt->updown
, $txt->settings
, $struninstall);
7119 $table->colclasses
= array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign');
7120 $table->id
= 'antivirusmanagement';
7121 $table->attributes
['class'] = 'admintable generaltable';
7122 $table->data
= array();
7124 // Iterate through auth plugins and add to the display table.
7126 $antiviruscount = count($activeantiviruses);
7127 $baseurl = new moodle_url('/admin/antiviruses.php', array('sesskey' => sesskey()));
7128 foreach ($antivirusesavailable as $antivirus => $name) {
7131 if (in_array($antivirus, $activeantiviruses)) {
7132 $hideshowurl = $baseurl;
7133 $hideshowurl->params(array('action' => 'disable', 'antivirus' => $antivirus));
7134 $hideshowimg = $OUTPUT->pix_icon('t/hide', get_string('disable'));
7135 $hideshow = html_writer
::link($hideshowurl, $hideshowimg);
7137 $displayname = $name;
7139 $hideshowurl = $baseurl;
7140 $hideshowurl->params(array('action' => 'enable', 'antivirus' => $antivirus));
7141 $hideshowimg = $OUTPUT->pix_icon('t/show', get_string('enable'));
7142 $hideshow = html_writer
::link($hideshowurl, $hideshowimg);
7144 $displayname = $name;
7145 $class = 'dimmed_text';
7151 if ($updowncount > 1) {
7152 $updownurl = $baseurl;
7153 $updownurl->params(array('action' => 'up', 'antivirus' => $antivirus));
7154 $updownimg = $OUTPUT->pix_icon('t/up', get_string('moveup'));
7155 $updown = html_writer
::link($updownurl, $updownimg);
7157 $updownimg = $OUTPUT->spacer();
7159 if ($updowncount < $antiviruscount) {
7160 $updownurl = $baseurl;
7161 $updownurl->params(array('action' => 'down', 'antivirus' => $antivirus));
7162 $updownimg = $OUTPUT->pix_icon('t/down', get_string('movedown'));
7163 $updown = html_writer
::link($updownurl, $updownimg);
7165 $updownimg = $OUTPUT->spacer();
7171 if (file_exists($CFG->dirroot
.'/lib/antivirus/'.$antivirus.'/settings.php')) {
7172 $eurl = new moodle_url('/admin/settings.php', array('section' => 'antivirussettings'.$antivirus));
7173 $settings = html_writer
::link($eurl, $txt->settings
);
7179 if ($uninstallurl = core_plugin_manager
::instance()->get_uninstall_url('antivirus_'.$antivirus, 'manage')) {
7180 $uninstall = html_writer
::link($uninstallurl, $struninstall);
7183 // Add a row to the table.
7184 $row = new html_table_row(array($displayname, $hideshow, $updown, $settings, $uninstall));
7186 $row->attributes
['class'] = $class;
7188 $table->data
[] = $row;
7190 $return .= html_writer
::table($table);
7191 $return .= get_string('configantivirusplugins', 'antivirus') . html_writer
::empty_tag('br') . get_string('tablenosave', 'admin');
7192 $return .= $OUTPUT->box_end();
7193 return highlight($query, $return);
7198 * Special class for license administration.
7200 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
7202 class admin_setting_managelicenses
extends admin_setting
{
7204 * Calls parent::__construct with specific arguments
7206 public function __construct() {
7207 $this->nosave
= true;
7208 parent
::__construct('licensesui', get_string('licensesettings', 'admin'), '', '');
7212 * Always returns true, does nothing
7216 public function get_setting() {
7221 * Always returns true, does nothing
7225 public function get_defaultsetting() {
7230 * Always returns '', does not write anything
7232 * @return string Always returns ''
7234 public function write_setting($data) {
7235 // do not write any setting
7240 * Builds the XHTML to display the control
7242 * @param string $data Unused
7243 * @param string $query
7246 public function output_html($data, $query='') {
7247 global $CFG, $OUTPUT;
7248 require_once($CFG->libdir
. '/licenselib.php');
7249 $url = "licenses.php?sesskey=" . sesskey();
7252 $txt = get_strings(array('administration', 'settings', 'name', 'enable', 'disable', 'none'));
7253 $licenses = license_manager
::get_licenses();
7255 $return = $OUTPUT->heading(get_string('availablelicenses', 'admin'), 3, 'main', true);
7257 $return .= $OUTPUT->box_start('generalbox editorsui');
7259 $table = new html_table();
7260 $table->head
= array($txt->name
, $txt->enable
);
7261 $table->colclasses
= array('leftalign', 'centeralign');
7262 $table->id
= 'availablelicenses';
7263 $table->attributes
['class'] = 'admintable generaltable';
7264 $table->data
= array();
7266 foreach ($licenses as $value) {
7267 $displayname = html_writer
::link($value->source
, get_string($value->shortname
, 'license'), array('target'=>'_blank'));
7269 if ($value->enabled
== 1) {
7270 $hideshow = html_writer
::link($url.'&action=disable&license='.$value->shortname
,
7271 $OUTPUT->pix_icon('t/hide', get_string('disable')));
7273 $hideshow = html_writer
::link($url.'&action=enable&license='.$value->shortname
,
7274 $OUTPUT->pix_icon('t/show', get_string('enable')));
7277 if ($value->shortname
== $CFG->sitedefaultlicense
) {
7278 $displayname .= ' '.$OUTPUT->pix_icon('t/locked', get_string('default'));
7284 $table->data
[] =array($displayname, $hideshow);
7286 $return .= html_writer
::table($table);
7287 $return .= $OUTPUT->box_end();
7288 return highlight($query, $return);
7293 * Course formats manager. Allows to enable/disable formats and jump to settings
7295 class admin_setting_manageformats
extends admin_setting
{
7298 * Calls parent::__construct with specific arguments
7300 public function __construct() {
7301 $this->nosave
= true;
7302 parent
::__construct('formatsui', new lang_string('manageformats', 'core_admin'), '', '');
7306 * Always returns true
7310 public function get_setting() {
7315 * Always returns true
7319 public function get_defaultsetting() {
7324 * Always returns '' and doesn't write anything
7326 * @param mixed $data string or array, must not be NULL
7327 * @return string Always returns ''
7329 public function write_setting($data) {
7330 // do not write any setting
7335 * Search to find if Query is related to format plugin
7337 * @param string $query The string to search for
7338 * @return bool true for related false for not
7340 public function is_related($query) {
7341 if (parent
::is_related($query)) {
7344 $formats = core_plugin_manager
::instance()->get_plugins_of_type('format');
7345 foreach ($formats as $format) {
7346 if (strpos($format->component
, $query) !== false ||
7347 strpos(core_text
::strtolower($format->displayname
), $query) !== false) {
7355 * Return XHTML to display control
7357 * @param mixed $data Unused
7358 * @param string $query
7359 * @return string highlight
7361 public function output_html($data, $query='') {
7362 global $CFG, $OUTPUT;
7364 $return = $OUTPUT->heading(new lang_string('courseformats'), 3, 'main');
7365 $return .= $OUTPUT->box_start('generalbox formatsui');
7367 $formats = core_plugin_manager
::instance()->get_plugins_of_type('format');
7370 $txt = get_strings(array('settings', 'name', 'enable', 'disable', 'up', 'down', 'default'));
7371 $txt->uninstall
= get_string('uninstallplugin', 'core_admin');
7372 $txt->updown
= "$txt->up/$txt->down";
7374 $table = new html_table();
7375 $table->head
= array($txt->name
, $txt->enable
, $txt->updown
, $txt->uninstall
, $txt->settings
);
7376 $table->align
= array('left', 'center', 'center', 'center', 'center');
7377 $table->attributes
['class'] = 'manageformattable generaltable admintable';
7378 $table->data
= array();
7381 $defaultformat = get_config('moodlecourse', 'format');
7382 $spacer = $OUTPUT->pix_icon('spacer', '', 'moodle', array('class' => 'iconsmall'));
7383 foreach ($formats as $format) {
7384 $url = new moodle_url('/admin/courseformats.php',
7385 array('sesskey' => sesskey(), 'format' => $format->name
));
7388 if ($format->is_enabled()) {
7389 $strformatname = $format->displayname
;
7390 if ($defaultformat === $format->name
) {
7391 $hideshow = $txt->default;
7393 $hideshow = html_writer
::link($url->out(false, array('action' => 'disable')),
7394 $OUTPUT->pix_icon('t/hide', $txt->disable
, 'moodle', array('class' => 'iconsmall')));
7397 $strformatname = $format->displayname
;
7398 $class = 'dimmed_text';
7399 $hideshow = html_writer
::link($url->out(false, array('action' => 'enable')),
7400 $OUTPUT->pix_icon('t/show', $txt->enable
, 'moodle', array('class' => 'iconsmall')));
7404 $updown .= html_writer
::link($url->out(false, array('action' => 'up')),
7405 $OUTPUT->pix_icon('t/up', $txt->up
, 'moodle', array('class' => 'iconsmall'))). '';
7409 if ($cnt < count($formats) - 1) {
7410 $updown .= ' '.html_writer
::link($url->out(false, array('action' => 'down')),
7411 $OUTPUT->pix_icon('t/down', $txt->down
, 'moodle', array('class' => 'iconsmall')));
7417 if ($format->get_settings_url()) {
7418 $settings = html_writer
::link($format->get_settings_url(), $txt->settings
);
7421 if ($uninstallurl = core_plugin_manager
::instance()->get_uninstall_url('format_'.$format->name
, 'manage')) {
7422 $uninstall = html_writer
::link($uninstallurl, $txt->uninstall
);
7424 $row = new html_table_row(array($strformatname, $hideshow, $updown, $uninstall, $settings));
7426 $row->attributes
['class'] = $class;
7428 $table->data
[] = $row;
7430 $return .= html_writer
::table($table);
7431 $link = html_writer
::link(new moodle_url('/admin/settings.php', array('section' => 'coursesettings')), new lang_string('coursesettings'));
7432 $return .= html_writer
::tag('p', get_string('manageformatsgotosettings', 'admin', $link));
7433 $return .= $OUTPUT->box_end();
7434 return highlight($query, $return);
7439 * Custom fields manager. Allows to enable/disable custom fields and jump to settings.
7442 * @copyright 2018 Toni Barbera
7443 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
7445 class admin_setting_managecustomfields
extends admin_setting
{
7448 * Calls parent::__construct with specific arguments
7450 public function __construct() {
7451 $this->nosave
= true;
7452 parent
::__construct('customfieldsui', new lang_string('managecustomfields', 'core_admin'), '', '');
7456 * Always returns true
7460 public function get_setting() {
7465 * Always returns true
7469 public function get_defaultsetting() {
7474 * Always returns '' and doesn't write anything
7476 * @param mixed $data string or array, must not be NULL
7477 * @return string Always returns ''
7479 public function write_setting($data) {
7480 // Do not write any setting.
7485 * Search to find if Query is related to format plugin
7487 * @param string $query The string to search for
7488 * @return bool true for related false for not
7490 public function is_related($query) {
7491 if (parent
::is_related($query)) {
7494 $formats = core_plugin_manager
::instance()->get_plugins_of_type('customfield');
7495 foreach ($formats as $format) {
7496 if (strpos($format->component
, $query) !== false ||
7497 strpos(core_text
::strtolower($format->displayname
), $query) !== false) {
7505 * Return XHTML to display control
7507 * @param mixed $data Unused
7508 * @param string $query
7509 * @return string highlight
7511 public function output_html($data, $query='') {
7512 global $CFG, $OUTPUT;
7514 $return = $OUTPUT->heading(new lang_string('customfields', 'core_customfield'), 3, 'main');
7515 $return .= $OUTPUT->box_start('generalbox customfieldsui');
7517 $fields = core_plugin_manager
::instance()->get_plugins_of_type('customfield');
7519 $txt = get_strings(array('settings', 'name', 'enable', 'disable', 'up', 'down'));
7520 $txt->uninstall
= get_string('uninstallplugin', 'core_admin');
7521 $txt->updown
= "$txt->up/$txt->down";
7523 $table = new html_table();
7524 $table->head
= array($txt->name
, $txt->enable
, $txt->uninstall
, $txt->settings
);
7525 $table->align
= array('left', 'center', 'center', 'center');
7526 $table->attributes
['class'] = 'managecustomfieldtable generaltable admintable';
7527 $table->data
= array();
7529 $spacer = $OUTPUT->pix_icon('spacer', '', 'moodle', array('class' => 'iconsmall'));
7530 foreach ($fields as $field) {
7531 $url = new moodle_url('/admin/customfields.php',
7532 array('sesskey' => sesskey(), 'field' => $field->name
));
7534 if ($field->is_enabled()) {
7535 $strfieldname = $field->displayname
;
7536 $hideshow = html_writer
::link($url->out(false, array('action' => 'disable')),
7537 $OUTPUT->pix_icon('t/hide', $txt->disable
, 'moodle', array('class' => 'iconsmall')));
7539 $strfieldname = $field->displayname
;
7540 $class = 'dimmed_text';
7541 $hideshow = html_writer
::link($url->out(false, array('action' => 'enable')),
7542 $OUTPUT->pix_icon('t/show', $txt->enable
, 'moodle', array('class' => 'iconsmall')));
7545 if ($field->get_settings_url()) {
7546 $settings = html_writer
::link($field->get_settings_url(), $txt->settings
);
7549 if ($uninstallurl = core_plugin_manager
::instance()->get_uninstall_url('customfield_'.$field->name
, 'manage')) {
7550 $uninstall = html_writer
::link($uninstallurl, $txt->uninstall
);
7552 $row = new html_table_row(array($strfieldname, $hideshow, $uninstall, $settings));
7553 $table->data
[] = $row;
7555 $return .= html_writer
::table($table);
7556 $return .= $OUTPUT->box_end();
7557 return highlight($query, $return);
7562 * Data formats manager. Allow reorder and to enable/disable data formats and jump to settings
7564 * @copyright 2016 Brendan Heywood (brendan@catalyst-au.net)
7565 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
7567 class admin_setting_managedataformats
extends admin_setting
{
7570 * Calls parent::__construct with specific arguments
7572 public function __construct() {
7573 $this->nosave
= true;
7574 parent
::__construct('managedataformats', new lang_string('managedataformats'), '', '');
7578 * Always returns true
7582 public function get_setting() {
7587 * Always returns true
7591 public function get_defaultsetting() {
7596 * Always returns '' and doesn't write anything
7598 * @param mixed $data string or array, must not be NULL
7599 * @return string Always returns ''
7601 public function write_setting($data) {
7602 // Do not write any setting.
7607 * Search to find if Query is related to format plugin
7609 * @param string $query The string to search for
7610 * @return bool true for related false for not
7612 public function is_related($query) {
7613 if (parent
::is_related($query)) {
7616 $formats = core_plugin_manager
::instance()->get_plugins_of_type('dataformat');
7617 foreach ($formats as $format) {
7618 if (strpos($format->component
, $query) !== false ||
7619 strpos(core_text
::strtolower($format->displayname
), $query) !== false) {
7627 * Return XHTML to display control
7629 * @param mixed $data Unused
7630 * @param string $query
7631 * @return string highlight
7633 public function output_html($data, $query='') {
7634 global $CFG, $OUTPUT;
7637 $formats = core_plugin_manager
::instance()->get_plugins_of_type('dataformat');
7639 $txt = get_strings(array('settings', 'name', 'enable', 'disable', 'up', 'down', 'default'));
7640 $txt->uninstall
= get_string('uninstallplugin', 'core_admin');
7641 $txt->updown
= "$txt->up/$txt->down";
7643 $table = new html_table();
7644 $table->head
= array($txt->name
, $txt->enable
, $txt->updown
, $txt->uninstall
, $txt->settings
);
7645 $table->align
= array('left', 'center', 'center', 'center', 'center');
7646 $table->attributes
['class'] = 'manageformattable generaltable admintable';
7647 $table->data
= array();
7650 $spacer = $OUTPUT->pix_icon('spacer', '', 'moodle', array('class' => 'iconsmall'));
7652 foreach ($formats as $format) {
7653 if ($format->is_enabled() && $format->is_installed_and_upgraded()) {
7657 foreach ($formats as $format) {
7658 $status = $format->get_status();
7659 $url = new moodle_url('/admin/dataformats.php',
7660 array('sesskey' => sesskey(), 'name' => $format->name
));
7663 if ($format->is_enabled()) {
7664 $strformatname = $format->displayname
;
7665 if ($totalenabled == 1&& $format->is_enabled()) {
7668 $hideshow = html_writer
::link($url->out(false, array('action' => 'disable')),
7669 $OUTPUT->pix_icon('t/hide', $txt->disable
, 'moodle', array('class' => 'iconsmall')));
7672 $class = 'dimmed_text';
7673 $strformatname = $format->displayname
;
7674 $hideshow = html_writer
::link($url->out(false, array('action' => 'enable')),
7675 $OUTPUT->pix_icon('t/show', $txt->enable
, 'moodle', array('class' => 'iconsmall')));
7680 $updown .= html_writer
::link($url->out(false, array('action' => 'up')),
7681 $OUTPUT->pix_icon('t/up', $txt->up
, 'moodle', array('class' => 'iconsmall'))). '';
7685 if ($cnt < count($formats) - 1) {
7686 $updown .= ' '.html_writer
::link($url->out(false, array('action' => 'down')),
7687 $OUTPUT->pix_icon('t/down', $txt->down
, 'moodle', array('class' => 'iconsmall')));
7693 if ($status === core_plugin_manager
::PLUGIN_STATUS_MISSING
) {
7694 $uninstall = get_string('status_missing', 'core_plugin');
7695 } else if ($status === core_plugin_manager
::PLUGIN_STATUS_NEW
) {
7696 $uninstall = get_string('status_new', 'core_plugin');
7697 } else if ($uninstallurl = core_plugin_manager
::instance()->get_uninstall_url('dataformat_'.$format->name
, 'manage')) {
7698 if ($totalenabled != 1 ||
!$format->is_enabled()) {
7699 $uninstall = html_writer
::link($uninstallurl, $txt->uninstall
);
7704 if ($format->get_settings_url()) {
7705 $settings = html_writer
::link($format->get_settings_url(), $txt->settings
);
7708 $row = new html_table_row(array($strformatname, $hideshow, $updown, $uninstall, $settings));
7710 $row->attributes
['class'] = $class;
7712 $table->data
[] = $row;
7715 $return .= html_writer
::table($table);
7716 return highlight($query, $return);
7721 * Special class for filter administration.
7723 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
7725 class admin_page_managefilters
extends admin_externalpage
{
7727 * Calls parent::__construct with specific arguments
7729 public function __construct() {
7731 parent
::__construct('managefilters', get_string('filtersettings', 'admin'), "$CFG->wwwroot/$CFG->admin/filters.php");
7735 * Searches all installed filters for specified filter
7737 * @param string $query The filter(string) to search for
7738 * @param string $query
7740 public function search($query) {
7742 if ($result = parent
::search($query)) {
7747 $filternames = filter_get_all_installed();
7748 foreach ($filternames as $path => $strfiltername) {
7749 if (strpos(core_text
::strtolower($strfiltername), $query) !== false) {
7753 if (strpos($path, $query) !== false) {
7760 $result = new stdClass
;
7761 $result->page
= $this;
7762 $result->settings
= array();
7763 return array($this->name
=> $result);
7771 * Generic class for managing plugins in a table that allows re-ordering and enable/disable of each plugin.
7772 * Requires a get_rank method on the plugininfo class for sorting.
7774 * @copyright 2017 Damyon Wiese
7775 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
7777 abstract class admin_setting_manage_plugins
extends admin_setting
{
7780 * Get the admin settings section name (just a unique string)
7784 public function get_section_name() {
7785 return 'manage' . $this->get_plugin_type() . 'plugins';
7789 * Get the admin settings section title (use get_string).
7793 abstract public function get_section_title();
7796 * Get the type of plugin to manage.
7800 abstract public function get_plugin_type();
7803 * Get the name of the second column.
7807 public function get_info_column_name() {
7812 * Get the type of plugin to manage.
7814 * @param plugininfo The plugin info class.
7817 abstract public function get_info_column($plugininfo);
7820 * Calls parent::__construct with specific arguments
7822 public function __construct() {
7823 $this->nosave
= true;
7824 parent
::__construct($this->get_section_name(), $this->get_section_title(), '', '');
7828 * Always returns true, does nothing
7832 public function get_setting() {
7837 * Always returns true, does nothing
7841 public function get_defaultsetting() {
7846 * Always returns '', does not write anything
7848 * @param mixed $data
7849 * @return string Always returns ''
7851 public function write_setting($data) {
7852 // Do not write any setting.
7857 * Checks if $query is one of the available plugins of this type
7859 * @param string $query The string to search for
7860 * @return bool Returns true if found, false if not
7862 public function is_related($query) {
7863 if (parent
::is_related($query)) {
7867 $query = core_text
::strtolower($query);
7868 $plugins = core_plugin_manager
::instance()->get_plugins_of_type($this->get_plugin_type());
7869 foreach ($plugins as $name => $plugin) {
7870 $localised = $plugin->displayname
;
7871 if (strpos(core_text
::strtolower($name), $query) !== false) {
7874 if (strpos(core_text
::strtolower($localised), $query) !== false) {
7882 * The URL for the management page for this plugintype.
7884 * @return moodle_url
7886 protected function get_manage_url() {
7887 return new moodle_url('/admin/updatesetting.php');
7891 * Builds the HTML to display the control.
7893 * @param string $data Unused
7894 * @param string $query
7897 public function output_html($data, $query = '') {
7898 global $CFG, $OUTPUT, $DB, $PAGE;
7900 $context = (object) [
7901 'manageurl' => new moodle_url($this->get_manage_url(), [
7902 'type' => $this->get_plugin_type(),
7903 'sesskey' => sesskey(),
7905 'infocolumnname' => $this->get_info_column_name(),
7909 $pluginmanager = core_plugin_manager
::instance();
7910 $allplugins = $pluginmanager->get_plugins_of_type($this->get_plugin_type());
7911 $enabled = $pluginmanager->get_enabled_plugins($this->get_plugin_type());
7912 $plugins = array_merge($enabled, $allplugins);
7913 foreach ($plugins as $key => $plugin) {
7914 $pluginlink = new moodle_url($context->manageurl
, ['plugin' => $key]);
7916 $pluginkey = (object) [
7917 'plugin' => $plugin->displayname
,
7918 'enabled' => $plugin->is_enabled(),
7921 'movedownlink' => '',
7922 'settingslink' => $plugin->get_settings_url(),
7923 'uninstalllink' => '',
7927 // Enable/Disable link.
7928 $togglelink = new moodle_url($pluginlink);
7929 if ($plugin->is_enabled()) {
7930 $toggletarget = false;
7931 $togglelink->param('action', 'disable');
7933 if (count($context->plugins
)) {
7934 // This is not the first plugin.
7935 $pluginkey->moveuplink
= new moodle_url($pluginlink, ['action' => 'up']);
7938 if (count($enabled) > count($context->plugins
) +
1) {
7939 // This is not the last plugin.
7940 $pluginkey->movedownlink
= new moodle_url($pluginlink, ['action' => 'down']);
7943 $pluginkey->info
= $this->get_info_column($plugin);
7945 $toggletarget = true;
7946 $togglelink->param('action', 'enable');
7949 $pluginkey->toggletarget
= $toggletarget;
7950 $pluginkey->togglelink
= $togglelink;
7952 $frankenstyle = $plugin->type
. '_' . $plugin->name
;
7953 if ($uninstalllink = core_plugin_manager
::instance()->get_uninstall_url($frankenstyle, 'manage')) {
7954 // This plugin supports uninstallation.
7955 $pluginkey->uninstalllink
= $uninstalllink;
7958 if (!empty($this->get_info_column_name())) {
7959 // This plugintype has an info column.
7960 $pluginkey->info
= $this->get_info_column($plugin);
7963 $context->plugins
[] = $pluginkey;
7966 $str = $OUTPUT->render_from_template('core_admin/setting_manage_plugins', $context);
7967 return highlight($query, $str);
7972 * Generic class for managing plugins in a table that allows re-ordering and enable/disable of each plugin.
7973 * Requires a get_rank method on the plugininfo class for sorting.
7975 * @copyright 2017 Andrew Nicols <andrew@nicols.co.uk>
7976 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
7978 class admin_setting_manage_fileconverter_plugins
extends admin_setting_manage_plugins
{
7979 public function get_section_title() {
7980 return get_string('type_fileconverter_plural', 'plugin');
7983 public function get_plugin_type() {
7984 return 'fileconverter';
7987 public function get_info_column_name() {
7988 return get_string('supportedconversions', 'plugin');
7991 public function get_info_column($plugininfo) {
7992 return $plugininfo->get_supported_conversions();
7997 * Special class for media player plugins management.
7999 * @copyright 2016 Marina Glancy
8000 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
8002 class admin_setting_managemediaplayers
extends admin_setting
{
8004 * Calls parent::__construct with specific arguments
8006 public function __construct() {
8007 $this->nosave
= true;
8008 parent
::__construct('managemediaplayers', get_string('managemediaplayers', 'media'), '', '');
8012 * Always returns true, does nothing
8016 public function get_setting() {
8021 * Always returns true, does nothing
8025 public function get_defaultsetting() {
8030 * Always returns '', does not write anything
8032 * @param mixed $data
8033 * @return string Always returns ''
8035 public function write_setting($data) {
8036 // Do not write any setting.
8041 * Checks if $query is one of the available enrol plugins
8043 * @param string $query The string to search for
8044 * @return bool Returns true if found, false if not
8046 public function is_related($query) {
8047 if (parent
::is_related($query)) {
8051 $query = core_text
::strtolower($query);
8052 $plugins = core_plugin_manager
::instance()->get_plugins_of_type('media');
8053 foreach ($plugins as $name => $plugin) {
8054 $localised = $plugin->displayname
;
8055 if (strpos(core_text
::strtolower($name), $query) !== false) {
8058 if (strpos(core_text
::strtolower($localised), $query) !== false) {
8066 * Sort plugins so enabled plugins are displayed first and all others are displayed in the end sorted by rank.
8067 * @return \core\plugininfo\media[]
8069 protected function get_sorted_plugins() {
8070 $pluginmanager = core_plugin_manager
::instance();
8072 $plugins = $pluginmanager->get_plugins_of_type('media');
8073 $enabledplugins = $pluginmanager->get_enabled_plugins('media');
8075 // Sort plugins so enabled plugins are displayed first and all others are displayed in the end sorted by rank.
8076 \core_collator
::asort_objects_by_method($plugins, 'get_rank', \core_collator
::SORT_NUMERIC
);
8078 $order = array_values($enabledplugins);
8079 $order = array_merge($order, array_diff(array_reverse(array_keys($plugins)), $order));
8081 $sortedplugins = array();
8082 foreach ($order as $name) {
8083 $sortedplugins[$name] = $plugins[$name];
8086 return $sortedplugins;
8090 * Builds the XHTML to display the control
8092 * @param string $data Unused
8093 * @param string $query
8096 public function output_html($data, $query='') {
8097 global $CFG, $OUTPUT, $DB, $PAGE;
8100 $strup = get_string('up');
8101 $strdown = get_string('down');
8102 $strsettings = get_string('settings');
8103 $strenable = get_string('enable');
8104 $strdisable = get_string('disable');
8105 $struninstall = get_string('uninstallplugin', 'core_admin');
8106 $strversion = get_string('version');
8107 $strname = get_string('name');
8108 $strsupports = get_string('supports', 'core_media');
8110 $pluginmanager = core_plugin_manager
::instance();
8112 $plugins = $this->get_sorted_plugins();
8113 $enabledplugins = $pluginmanager->get_enabled_plugins('media');
8115 $return = $OUTPUT->box_start('generalbox mediaplayersui');
8117 $table = new html_table();
8118 $table->head
= array($strname, $strsupports, $strversion,
8119 $strenable, $strup.'/'.$strdown, $strsettings, $struninstall);
8120 $table->colclasses
= array('leftalign', 'leftalign', 'centeralign',
8121 'centeralign', 'centeralign', 'centeralign', 'centeralign');
8122 $table->id
= 'mediaplayerplugins';
8123 $table->attributes
['class'] = 'admintable generaltable';
8124 $table->data
= array();
8126 // Iterate through media plugins and add to the display table.
8128 $url = new moodle_url('/admin/media.php', array('sesskey' => sesskey()));
8130 $spacer = $OUTPUT->pix_icon('spacer', '', 'moodle', array('class' => 'iconsmall'));
8132 $usedextensions = [];
8133 foreach ($plugins as $name => $plugin) {
8134 $url->param('media', $name);
8135 $plugininfo = $pluginmanager->get_plugin_info('media_'.$name);
8136 $version = $plugininfo->versiondb
;
8137 $supports = $plugininfo->supports($usedextensions);
8141 if (!$plugininfo->is_installed_and_upgraded()) {
8144 $displayname = '<span class="notifyproblem">'.$name.'</span>';
8146 $enabled = $plugininfo->is_enabled();
8148 $hideshow = html_writer
::link(new moodle_url($url, array('action' => 'disable')),
8149 $OUTPUT->pix_icon('t/hide', $strdisable, 'moodle', array('class' => 'iconsmall')));
8151 $hideshow = html_writer
::link(new moodle_url($url, array('action' => 'enable')),
8152 $OUTPUT->pix_icon('t/show', $strenable, 'moodle', array('class' => 'iconsmall')));
8153 $class = 'dimmed_text';
8155 $displayname = $plugin->displayname
;
8156 if (get_string_manager()->string_exists('pluginname_help', 'media_' . $name)) {
8157 $displayname .= ' ' . $OUTPUT->help_icon('pluginname', 'media_' . $name);
8160 if ($PAGE->theme
->resolve_image_location('icon', 'media_' . $name, false)) {
8161 $icon = $OUTPUT->pix_icon('icon', '', 'media_' . $name, array('class' => 'icon pluginicon'));
8163 $icon = $OUTPUT->pix_icon('spacer', '', 'moodle', array('class' => 'icon pluginicon noicon'));
8166 // Up/down link (only if enrol is enabled).
8169 if ($updowncount > 1) {
8170 $updown = html_writer
::link(new moodle_url($url, array('action' => 'up')),
8171 $OUTPUT->pix_icon('t/up', $strup, 'moodle', array('class' => 'iconsmall')));
8175 if ($updowncount < count($enabledplugins)) {
8176 $updown .= html_writer
::link(new moodle_url($url, array('action' => 'down')),
8177 $OUTPUT->pix_icon('t/down', $strdown, 'moodle', array('class' => 'iconsmall')));
8185 $status = $plugininfo->get_status();
8186 if ($status === core_plugin_manager
::PLUGIN_STATUS_MISSING
) {
8187 $uninstall = get_string('status_missing', 'core_plugin') . '<br/>';
8189 if ($status === core_plugin_manager
::PLUGIN_STATUS_NEW
) {
8190 $uninstall = get_string('status_new', 'core_plugin');
8191 } else if ($uninstallurl = $pluginmanager->get_uninstall_url('media_'.$name, 'manage')) {
8192 $uninstall .= html_writer
::link($uninstallurl, $struninstall);
8196 if ($plugininfo->get_settings_url()) {
8197 $settings = html_writer
::link($plugininfo->get_settings_url(), $strsettings);
8200 // Add a row to the table.
8201 $row = new html_table_row(array($icon.$displayname, $supports, $version, $hideshow, $updown, $settings, $uninstall));
8203 $row->attributes
['class'] = $class;
8205 $table->data
[] = $row;
8207 $printed[$name] = true;
8210 $return .= html_writer
::table($table);
8211 $return .= $OUTPUT->box_end();
8212 return highlight($query, $return);
8217 * Initialise admin page - this function does require login and permission
8218 * checks specified in page definition.
8220 * This function must be called on each admin page before other code.
8222 * @global moodle_page $PAGE
8224 * @param string $section name of page
8225 * @param string $extrabutton extra HTML that is added after the blocks editing on/off button.
8226 * @param array $extraurlparams an array paramname => paramvalue, or parameters that need to be
8227 * added to the turn blocks editing on/off form, so this page reloads correctly.
8228 * @param string $actualurl if the actual page being viewed is not the normal one for this
8229 * page (e.g. admin/roles/allow.php, instead of admin/roles/manage.php, you can pass the alternate URL here.
8230 * @param array $options Additional options that can be specified for page setup.
8231 * pagelayout - This option can be used to set a specific pagelyaout, admin is default.
8233 function admin_externalpage_setup($section, $extrabutton = '', array $extraurlparams = null, $actualurl = '', array $options = array()) {
8234 global $CFG, $PAGE, $USER, $SITE, $OUTPUT;
8236 $PAGE->set_context(null); // hack - set context to something, by default to system context
8241 if (!empty($options['pagelayout'])) {
8242 // A specific page layout has been requested.
8243 $PAGE->set_pagelayout($options['pagelayout']);
8244 } else if ($section === 'upgradesettings') {
8245 $PAGE->set_pagelayout('maintenance');
8247 $PAGE->set_pagelayout('admin');
8250 $adminroot = admin_get_root(false, false); // settings not required for external pages
8251 $extpage = $adminroot->locate($section, true);
8253 if (empty($extpage) or !($extpage instanceof admin_externalpage
)) {
8254 // The requested section isn't in the admin tree
8255 // It could be because the user has inadequate capapbilities or because the section doesn't exist
8256 if (!has_capability('moodle/site:config', context_system
::instance())) {
8257 // The requested section could depend on a different capability
8258 // but most likely the user has inadequate capabilities
8259 print_error('accessdenied', 'admin');
8261 print_error('sectionerror', 'admin', "$CFG->wwwroot/$CFG->admin/");
8265 // this eliminates our need to authenticate on the actual pages
8266 if (!$extpage->check_access()) {
8267 print_error('accessdenied', 'admin');
8271 navigation_node
::require_admin_tree();
8273 // $PAGE->set_extra_button($extrabutton); TODO
8276 $actualurl = $extpage->url
;
8279 $PAGE->set_url($actualurl, $extraurlparams);
8280 if (strpos($PAGE->pagetype
, 'admin-') !== 0) {
8281 $PAGE->set_pagetype('admin-' . $PAGE->pagetype
);
8284 if (empty($SITE->fullname
) ||
empty($SITE->shortname
)) {
8285 // During initial install.
8286 $strinstallation = get_string('installation', 'install');
8287 $strsettings = get_string('settings');
8288 $PAGE->navbar
->add($strsettings);
8289 $PAGE->set_title($strinstallation);
8290 $PAGE->set_heading($strinstallation);
8291 $PAGE->set_cacheable(false);
8295 // Locate the current item on the navigation and make it active when found.
8296 $path = $extpage->path
;
8297 $node = $PAGE->settingsnav
;
8298 while ($node && count($path) > 0) {
8299 $node = $node->get(array_pop($path));
8302 $node->make_active();
8306 $adminediting = optional_param('adminedit', -1, PARAM_BOOL
);
8307 if ($PAGE->user_allowed_editing() && $adminediting != -1) {
8308 $USER->editing
= $adminediting;
8311 $visiblepathtosection = array_reverse($extpage->visiblepath
);
8313 if ($PAGE->user_allowed_editing()) {
8314 if ($PAGE->user_is_editing()) {
8315 $caption = get_string('blockseditoff');
8316 $url = new moodle_url($PAGE->url
, array('adminedit'=>'0', 'sesskey'=>sesskey()));
8318 $caption = get_string('blocksediton');
8319 $url = new moodle_url($PAGE->url
, array('adminedit'=>'1', 'sesskey'=>sesskey()));
8321 $PAGE->set_button($OUTPUT->single_button($url, $caption, 'get'));
8324 $PAGE->set_title("$SITE->shortname: " . implode(": ", $visiblepathtosection));
8325 $PAGE->set_heading($SITE->fullname
);
8327 // prevent caching in nav block
8328 $PAGE->navigation
->clear_cache();
8332 * Returns the reference to admin tree root
8334 * @return object admin_root object
8336 function admin_get_root($reload=false, $requirefulltree=true) {
8337 global $CFG, $DB, $OUTPUT, $ADMIN;
8339 if (is_null($ADMIN)) {
8340 // create the admin tree!
8341 $ADMIN = new admin_root($requirefulltree);
8344 if ($reload or ($requirefulltree and !$ADMIN->fulltree
)) {
8345 $ADMIN->purge_children($requirefulltree);
8348 if (!$ADMIN->loaded
) {
8349 // we process this file first to create categories first and in correct order
8350 require($CFG->dirroot
.'/'.$CFG->admin
.'/settings/top.php');
8352 // now we process all other files in admin/settings to build the admin tree
8353 foreach (glob($CFG->dirroot
.'/'.$CFG->admin
.'/settings/*.php') as $file) {
8354 if ($file == $CFG->dirroot
.'/'.$CFG->admin
.'/settings/top.php') {
8357 if ($file == $CFG->dirroot
.'/'.$CFG->admin
.'/settings/plugins.php') {
8358 // plugins are loaded last - they may insert pages anywhere
8363 require($CFG->dirroot
.'/'.$CFG->admin
.'/settings/plugins.php');
8365 $ADMIN->loaded
= true;
8371 /// settings utility functions
8374 * This function applies default settings.
8375 * Because setting the defaults of some settings can enable other settings,
8376 * this function is called recursively until no more new settings are found.
8378 * @param object $node, NULL means complete tree, null by default
8379 * @param bool $unconditional if true overrides all values with defaults, true by default
8380 * @param array $admindefaultsettings default admin settings to apply. Used recursively
8381 * @param array $settingsoutput The names and values of the changed settings. Used recursively
8382 * @return array $settingsoutput The names and values of the changed settings
8384 function admin_apply_default_settings($node=null, $unconditional=true, $admindefaultsettings=array(), $settingsoutput=array()) {
8386 if (is_null($node)) {
8387 core_plugin_manager
::reset_caches();
8388 $node = admin_get_root(true, true);
8391 if ($node instanceof admin_category
) {
8392 $entries = array_keys($node->children
);
8393 foreach ($entries as $entry) {
8394 $settingsoutput = admin_apply_default_settings(
8395 $node->children
[$entry], $unconditional, $admindefaultsettings, $settingsoutput
8399 } else if ($node instanceof admin_settingpage
) {
8400 foreach ($node->settings
as $setting) {
8401 if (!$unconditional and !is_null($setting->get_setting())) {
8402 // Do not override existing defaults.
8405 $defaultsetting = $setting->get_defaultsetting();
8406 if (is_null($defaultsetting)) {
8407 // No value yet - default maybe applied after admin user creation or in upgradesettings.
8411 $settingname = $node->name
. '_' . $setting->name
; // Get a unique name for the setting.
8413 if (!array_key_exists($settingname, $admindefaultsettings)) { // Only update a setting if not already processed.
8414 $admindefaultsettings[$settingname] = $settingname;
8415 $settingsoutput[$settingname] = $defaultsetting;
8417 // Set the default for this setting.
8418 $setting->write_setting($defaultsetting);
8419 $setting->write_setting_flags(null);
8421 unset($admindefaultsettings[$settingname]); // Remove processed settings.
8426 // Call this function recursively until all settings are processed.
8427 if (($node instanceof admin_root
) && (!empty($admindefaultsettings))) {
8428 $settingsoutput = admin_apply_default_settings(null, $unconditional, $admindefaultsettings, $settingsoutput);
8430 // Just in case somebody modifies the list of active plugins directly.
8431 core_plugin_manager
::reset_caches();
8433 return $settingsoutput;
8437 * Store changed settings, this function updates the errors variable in $ADMIN
8439 * @param object $formdata from form
8440 * @return int number of changed settings
8442 function admin_write_settings($formdata) {
8443 global $CFG, $SITE, $DB;
8445 $olddbsessions = !empty($CFG->dbsessions
);
8446 $formdata = (array)$formdata;
8449 foreach ($formdata as $fullname=>$value) {
8450 if (strpos($fullname, 's_') !== 0) {
8451 continue; // not a config value
8453 $data[$fullname] = $value;
8456 $adminroot = admin_get_root();
8457 $settings = admin_find_write_settings($adminroot, $data);
8460 foreach ($settings as $fullname=>$setting) {
8461 /** @var $setting admin_setting */
8462 $original = $setting->get_setting();
8463 $error = $setting->write_setting($data[$fullname]);
8464 if ($error !== '') {
8465 $adminroot->errors
[$fullname] = new stdClass();
8466 $adminroot->errors
[$fullname]->data
= $data[$fullname];
8467 $adminroot->errors
[$fullname]->id
= $setting->get_id();
8468 $adminroot->errors
[$fullname]->error
= $error;
8470 $setting->write_setting_flags($data);
8472 if ($setting->post_write_settings($original)) {
8477 if ($olddbsessions != !empty($CFG->dbsessions
)) {
8481 // Now update $SITE - just update the fields, in case other people have a
8482 // a reference to it (e.g. $PAGE, $COURSE).
8483 $newsite = $DB->get_record('course', array('id'=>$SITE->id
));
8484 foreach (get_object_vars($newsite) as $field => $value) {
8485 $SITE->$field = $value;
8488 // now reload all settings - some of them might depend on the changed
8489 admin_get_root(true);
8494 * Internal recursive function - finds all settings from submitted form
8496 * @param object $node Instance of admin_category, or admin_settingpage
8497 * @param array $data
8500 function admin_find_write_settings($node, $data) {
8507 if ($node instanceof admin_category
) {
8508 if ($node->check_access()) {
8509 $entries = array_keys($node->children
);
8510 foreach ($entries as $entry) {
8511 $return = array_merge($return, admin_find_write_settings($node->children
[$entry], $data));
8515 } else if ($node instanceof admin_settingpage
) {
8516 if ($node->check_access()) {
8517 foreach ($node->settings
as $setting) {
8518 $fullname = $setting->get_full_name();
8519 if (array_key_exists($fullname, $data)) {
8520 $return[$fullname] = $setting;
8531 * Internal function - prints the search results
8533 * @param string $query String to search for
8534 * @return string empty or XHTML
8536 function admin_search_settings_html($query) {
8537 global $CFG, $OUTPUT, $PAGE;
8539 if (core_text
::strlen($query) < 2) {
8542 $query = core_text
::strtolower($query);
8544 $adminroot = admin_get_root();
8545 $findings = $adminroot->search($query);
8546 $savebutton = false;
8548 $tpldata = (object) [
8549 'actionurl' => $PAGE->url
->out(false),
8551 'sesskey' => sesskey(),
8554 foreach ($findings as $found) {
8555 $page = $found->page
;
8556 $settings = $found->settings
;
8557 if ($page->is_hidden()) {
8558 // hidden pages are not displayed in search results
8562 $heading = highlight($query, $page->visiblename
);
8564 if ($page instanceof admin_externalpage
) {
8565 $headingurl = new moodle_url($page->url
);
8566 } else if ($page instanceof admin_settingpage
) {
8567 $headingurl = new moodle_url('/admin/settings.php', ['section' => $page->name
]);
8572 // Locate the page in the admin root and populate its visiblepath attribute.
8574 $located = $adminroot->locate($page->name
, true);
8576 foreach ($located->visiblepath
as $pathitem) {
8577 array_unshift($path, (string) $pathitem);
8581 $sectionsettings = [];
8582 if (!empty($settings)) {
8583 foreach ($settings as $setting) {
8584 if (empty($setting->nosave
)) {
8587 $fullname = $setting->get_full_name();
8588 if (array_key_exists($fullname, $adminroot->errors
)) {
8589 $data = $adminroot->errors
[$fullname]->data
;
8591 $data = $setting->get_setting();
8592 $data = $setting->get_setting();
8593 // do not use defaults if settings not available - upgradesettings handles the defaults!
8595 $sectionsettings[] = $setting->output_html($data, $query);
8599 $tpldata->results
[] = (object) [
8600 'title' => $heading,
8602 'url' => $headingurl->out(false),
8603 'settings' => $sectionsettings
8607 $tpldata->showsave
= $savebutton;
8608 $tpldata->hasresults
= !empty($tpldata->results
);
8610 return $OUTPUT->render_from_template('core_admin/settings_search_results', $tpldata);
8614 * Internal function - returns arrays of html pages with uninitialised settings
8616 * @param object $node Instance of admin_category or admin_settingpage
8619 function admin_output_new_settings_by_page($node) {
8623 if ($node instanceof admin_category
) {
8624 $entries = array_keys($node->children
);
8625 foreach ($entries as $entry) {
8626 $return +
= admin_output_new_settings_by_page($node->children
[$entry]);
8629 } else if ($node instanceof admin_settingpage
) {
8630 $newsettings = array();
8631 foreach ($node->settings
as $setting) {
8632 if (is_null($setting->get_setting())) {
8633 $newsettings[] = $setting;
8636 if (count($newsettings) > 0) {
8637 $adminroot = admin_get_root();
8638 $page = $OUTPUT->heading(get_string('upgradesettings','admin').' - '.$node->visiblename
, 2, 'main');
8639 $page .= '<fieldset class="adminsettings">'."\n";
8640 foreach ($newsettings as $setting) {
8641 $fullname = $setting->get_full_name();
8642 if (array_key_exists($fullname, $adminroot->errors
)) {
8643 $data = $adminroot->errors
[$fullname]->data
;
8645 $data = $setting->get_setting();
8646 if (is_null($data)) {
8647 $data = $setting->get_defaultsetting();
8650 $page .= '<div class="clearer"><!-- --></div>'."\n";
8651 $page .= $setting->output_html($data);
8653 $page .= '</fieldset>';
8654 $return[$node->name
] = $page;
8662 * Format admin settings
8664 * @param object $setting
8665 * @param string $title label element
8666 * @param string $form form fragment, html code - not highlighted automatically
8667 * @param string $description
8668 * @param mixed $label link label to id, true by default or string being the label to connect it to
8669 * @param string $warning warning text
8670 * @param sting $defaultinfo defaults info, null means nothing, '' is converted to "Empty" string, defaults to null
8671 * @param string $query search query to be highlighted
8672 * @return string XHTML
8674 function format_admin_setting($setting, $title='', $form='', $description='', $label=true, $warning='', $defaultinfo=NULL, $query='') {
8675 global $CFG, $OUTPUT;
8677 $context = (object) [
8678 'name' => empty($setting->plugin
) ?
$setting->name
: "$setting->plugin | $setting->name",
8679 'fullname' => $setting->get_full_name(),
8682 // Sometimes the id is not id_s_name, but id_s_name_m or something, and this does not validate.
8683 if ($label === true) {
8684 $context->labelfor
= $setting->get_id();
8685 } else if ($label === false) {
8686 $context->labelfor
= '';
8688 $context->labelfor
= $label;
8691 $form .= $setting->output_setting_flags();
8693 $context->warning
= $warning;
8694 $context->override
= '';
8695 if (empty($setting->plugin
)) {
8696 if (array_key_exists($setting->name
, $CFG->config_php_settings
)) {
8697 $context->override
= get_string('configoverride', 'admin');
8700 if (array_key_exists($setting->plugin
, $CFG->forced_plugin_settings
) and array_key_exists($setting->name
, $CFG->forced_plugin_settings
[$setting->plugin
])) {
8701 $context->override
= get_string('configoverride', 'admin');
8705 $defaults = array();
8706 if (!is_null($defaultinfo)) {
8707 if ($defaultinfo === '') {
8708 $defaultinfo = get_string('emptysettingvalue', 'admin');
8710 $defaults[] = $defaultinfo;
8713 $context->default = null;
8714 $setting->get_setting_flag_defaults($defaults);
8715 if (!empty($defaults)) {
8716 $defaultinfo = implode(', ', $defaults);
8717 $defaultinfo = highlight($query, nl2br(s($defaultinfo)));
8718 $context->default = get_string('defaultsettinginfo', 'admin', $defaultinfo);
8722 $context->error
= '';
8723 $adminroot = admin_get_root();
8724 if (array_key_exists($context->fullname
, $adminroot->errors
)) {
8725 $context->error
= $adminroot->errors
[$context->fullname
]->error
;
8728 if ($dependenton = $setting->get_dependent_on()) {
8729 $context->dependenton
= get_string('settingdependenton', 'admin', implode(', ', $dependenton));
8732 $context->id
= 'admin-' . $setting->name
;
8733 $context->title
= highlightfast($query, $title);
8734 $context->name
= highlightfast($query, $context->name
);
8735 $context->description
= highlight($query, markdown_to_html($description));
8736 $context->element
= $form;
8737 $context->forceltr
= $setting->get_force_ltr();
8739 return $OUTPUT->render_from_template('core_admin/setting', $context);
8743 * Based on find_new_settings{@link ()} in upgradesettings.php
8744 * Looks to find any admin settings that have not been initialized. Returns 1 if it finds any.
8746 * @param object $node Instance of admin_category, or admin_settingpage
8747 * @return boolean true if any settings haven't been initialised, false if they all have
8749 function any_new_admin_settings($node) {
8751 if ($node instanceof admin_category
) {
8752 $entries = array_keys($node->children
);
8753 foreach ($entries as $entry) {
8754 if (any_new_admin_settings($node->children
[$entry])) {
8759 } else if ($node instanceof admin_settingpage
) {
8760 foreach ($node->settings
as $setting) {
8761 if ($setting->get_setting() === NULL) {
8771 * Moved from admin/replace.php so that we can use this in cron
8773 * @param string $search string to look for
8774 * @param string $replace string to replace
8775 * @return bool success or fail
8777 function db_replace($search, $replace) {
8778 global $DB, $CFG, $OUTPUT;
8780 // TODO: this is horrible hack, we should do whitelisting and each plugin should be responsible for proper replacing...
8781 $skiptables = array('config', 'config_plugins', 'config_log', 'upgrade_log', 'log',
8782 'filter_config', 'sessions', 'events_queue', 'repository_instance_config',
8783 'block_instances', '');
8785 // Turn off time limits, sometimes upgrades can be slow.
8786 core_php_time_limit
::raise();
8788 if (!$tables = $DB->get_tables() ) { // No tables yet at all.
8791 foreach ($tables as $table) {
8793 if (in_array($table, $skiptables)) { // Don't process these
8797 if ($columns = $DB->get_columns($table)) {
8798 $DB->set_debug(true);
8799 foreach ($columns as $column) {
8800 $DB->replace_all_text($table, $column, $search, $replace);
8802 $DB->set_debug(false);
8806 // delete modinfo caches
8807 rebuild_course_cache(0, true);
8809 // TODO: we should ask all plugins to do the search&replace, for now let's do only blocks...
8810 $blocks = core_component
::get_plugin_list('block');
8811 foreach ($blocks as $blockname=>$fullblock) {
8812 if ($blockname === 'NEWBLOCK') { // Someone has unzipped the template, ignore it
8816 if (!is_readable($fullblock.'/lib.php')) {
8820 $function = 'block_'.$blockname.'_global_db_replace';
8821 include_once($fullblock.'/lib.php');
8822 if (!function_exists($function)) {
8826 echo $OUTPUT->notification("Replacing in $blockname blocks...", 'notifysuccess');
8827 $function($search, $replace);
8828 echo $OUTPUT->notification("...finished", 'notifysuccess');
8837 * Manage repository settings
8839 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
8841 class admin_setting_managerepository
extends admin_setting
{
8846 * calls parent::__construct with specific arguments
8848 public function __construct() {
8850 parent
::__construct('managerepository', get_string('manage', 'repository'), '', '');
8851 $this->baseurl
= $CFG->wwwroot
. '/' . $CFG->admin
. '/repository.php?sesskey=' . sesskey();
8855 * Always returns true, does nothing
8859 public function get_setting() {
8864 * Always returns true does nothing
8868 public function get_defaultsetting() {
8873 * Always returns s_managerepository
8875 * @return string Always return 's_managerepository'
8877 public function get_full_name() {
8878 return 's_managerepository';
8882 * Always returns '' doesn't do anything
8884 public function write_setting($data) {
8885 $url = $this->baseurl
. '&new=' . $data;
8888 // Should not use redirect and exit here
8889 // Find a better way to do this.
8895 * Searches repository plugins for one that matches $query
8897 * @param string $query The string to search for
8898 * @return bool true if found, false if not
8900 public function is_related($query) {
8901 if (parent
::is_related($query)) {
8905 $repositories= core_component
::get_plugin_list('repository');
8906 foreach ($repositories as $p => $dir) {
8907 if (strpos($p, $query) !== false) {
8911 foreach (repository
::get_types() as $instance) {
8912 $title = $instance->get_typename();
8913 if (strpos(core_text
::strtolower($title), $query) !== false) {
8921 * Helper function that generates a moodle_url object
8922 * relevant to the repository
8925 function repository_action_url($repository) {
8926 return new moodle_url($this->baseurl
, array('sesskey'=>sesskey(), 'repos'=>$repository));
8930 * Builds XHTML to display the control
8932 * @param string $data Unused
8933 * @param string $query
8934 * @return string XHTML
8936 public function output_html($data, $query='') {
8937 global $CFG, $USER, $OUTPUT;
8939 // Get strings that are used
8940 $strshow = get_string('on', 'repository');
8941 $strhide = get_string('off', 'repository');
8942 $strdelete = get_string('disabled', 'repository');
8944 $actionchoicesforexisting = array(
8947 'delete' => $strdelete
8950 $actionchoicesfornew = array(
8951 'newon' => $strshow,
8952 'newoff' => $strhide,
8953 'delete' => $strdelete
8957 $return .= $OUTPUT->box_start('generalbox');
8959 // Set strings that are used multiple times
8960 $settingsstr = get_string('settings');
8961 $disablestr = get_string('disable');
8963 // Table to list plug-ins
8964 $table = new html_table();
8965 $table->head
= array(get_string('name'), get_string('isactive', 'repository'), get_string('order'), $settingsstr);
8966 $table->align
= array('left', 'center', 'center', 'center', 'center');
8967 $table->data
= array();
8969 // Get list of used plug-ins
8970 $repositorytypes = repository
::get_types();
8971 if (!empty($repositorytypes)) {
8972 // Array to store plugins being used
8973 $alreadyplugins = array();
8974 $totalrepositorytypes = count($repositorytypes);
8976 foreach ($repositorytypes as $i) {
8978 $typename = $i->get_typename();
8979 // Display edit link only if you can config the type or if it has multiple instances (e.g. has instance config)
8980 $typeoptionnames = repository
::static_function($typename, 'get_type_option_names');
8981 $instanceoptionnames = repository
::static_function($typename, 'get_instance_option_names');
8983 if (!empty($typeoptionnames) ||
!empty($instanceoptionnames)) {
8984 // Calculate number of instances in order to display them for the Moodle administrator
8985 if (!empty($instanceoptionnames)) {
8987 $params['context'] = array(context_system
::instance());
8988 $params['onlyvisible'] = false;
8989 $params['type'] = $typename;
8990 $admininstancenumber = count(repository
::static_function($typename, 'get_instances', $params));
8992 $admininstancenumbertext = get_string('instancesforsite', 'repository', $admininstancenumber);
8993 $params['context'] = array();
8994 $instances = repository
::static_function($typename, 'get_instances', $params);
8995 $courseinstances = array();
8996 $userinstances = array();
8998 foreach ($instances as $instance) {
8999 $repocontext = context
::instance_by_id($instance->instance
->contextid
);
9000 if ($repocontext->contextlevel
== CONTEXT_COURSE
) {
9001 $courseinstances[] = $instance;
9002 } else if ($repocontext->contextlevel
== CONTEXT_USER
) {
9003 $userinstances[] = $instance;
9007 $instancenumber = count($courseinstances);
9008 $courseinstancenumbertext = get_string('instancesforcourses', 'repository', $instancenumber);
9010 // user private instances
9011 $instancenumber = count($userinstances);
9012 $userinstancenumbertext = get_string('instancesforusers', 'repository', $instancenumber);
9014 $admininstancenumbertext = "";
9015 $courseinstancenumbertext = "";
9016 $userinstancenumbertext = "";
9019 $settings .= '<a href="' . $this->baseurl
. '&action=edit&repos=' . $typename . '">' . $settingsstr .'</a>';
9021 $settings .= $OUTPUT->container_start('mdl-left');
9022 $settings .= '<br/>';
9023 $settings .= $admininstancenumbertext;
9024 $settings .= '<br/>';
9025 $settings .= $courseinstancenumbertext;
9026 $settings .= '<br/>';
9027 $settings .= $userinstancenumbertext;
9028 $settings .= $OUTPUT->container_end();
9030 // Get the current visibility
9031 if ($i->get_visible()) {
9032 $currentaction = 'show';
9034 $currentaction = 'hide';
9037 $select = new single_select($this->repository_action_url($typename, 'repos'), 'action', $actionchoicesforexisting, $currentaction, null, 'applyto' . basename($typename));
9039 // Display up/down link
9041 // Should be done with CSS instead.
9042 $spacer = $OUTPUT->spacer(array('height' => 15, 'width' => 15, 'class' => 'smallicon'));
9044 if ($updowncount > 1) {
9045 $updown .= "<a href=\"$this->baseurl&action=moveup&repos=".$typename."\">";
9046 $updown .= $OUTPUT->pix_icon('t/up', get_string('moveup')) . '</a> ';
9051 if ($updowncount < $totalrepositorytypes) {
9052 $updown .= "<a href=\"$this->baseurl&action=movedown&repos=".$typename."\">";
9053 $updown .= $OUTPUT->pix_icon('t/down', get_string('movedown')) . '</a> ';
9061 $table->data
[] = array($i->get_readablename(), $OUTPUT->render($select), $updown, $settings);
9063 if (!in_array($typename, $alreadyplugins)) {
9064 $alreadyplugins[] = $typename;
9069 // Get all the plugins that exist on disk
9070 $plugins = core_component
::get_plugin_list('repository');
9071 if (!empty($plugins)) {
9072 foreach ($plugins as $plugin => $dir) {
9073 // Check that it has not already been listed
9074 if (!in_array($plugin, $alreadyplugins)) {
9075 $select = new single_select($this->repository_action_url($plugin, 'repos'), 'action', $actionchoicesfornew, 'delete', null, 'applyto' . basename($plugin));
9076 $table->data
[] = array(get_string('pluginname', 'repository_'.$plugin), $OUTPUT->render($select), '', '');
9081 $return .= html_writer
::table($table);
9082 $return .= $OUTPUT->box_end();
9083 return highlight($query, $return);
9088 * Special checkbox for enable mobile web service
9089 * If enable then we store the service id of the mobile service into config table
9090 * If disable then we unstore the service id from the config table
9092 class admin_setting_enablemobileservice
extends admin_setting_configcheckbox
{
9094 /** @var boolean True means that the capability 'webservice/rest:use' is set for authenticated user role */
9098 * Return true if Authenticated user role has the capability 'webservice/rest:use', otherwise false.
9102 private function is_protocol_cap_allowed() {
9105 // If the $this->restuse variable is not set, it needs to be set.
9106 if (empty($this->restuse
) and $this->restuse
!==false) {
9108 $params['permission'] = CAP_ALLOW
;
9109 $params['roleid'] = $CFG->defaultuserroleid
;
9110 $params['capability'] = 'webservice/rest:use';
9111 $this->restuse
= $DB->record_exists('role_capabilities', $params);
9114 return $this->restuse
;
9118 * Set the 'webservice/rest:use' to the Authenticated user role (allow or not)
9119 * @param type $status true to allow, false to not set
9121 private function set_protocol_cap($status) {
9123 if ($status and !$this->is_protocol_cap_allowed()) {
9124 //need to allow the cap
9125 $permission = CAP_ALLOW
;
9127 } else if (!$status and $this->is_protocol_cap_allowed()){
9128 //need to disallow the cap
9129 $permission = CAP_INHERIT
;
9132 if (!empty($assign)) {
9133 $systemcontext = context_system
::instance();
9134 assign_capability('webservice/rest:use', $permission, $CFG->defaultuserroleid
, $systemcontext->id
, true);
9139 * Builds XHTML to display the control.
9140 * The main purpose of this overloading is to display a warning when https
9141 * is not supported by the server
9142 * @param string $data Unused
9143 * @param string $query
9144 * @return string XHTML
9146 public function output_html($data, $query='') {
9148 $html = parent
::output_html($data, $query);
9150 if ((string)$data === $this->yes
) {
9151 $notifications = tool_mobile\api
::get_potential_config_issues(); // Safe to call, plugin available if we reach here.
9152 foreach ($notifications as $notification) {
9153 $message = get_string($notification[0], $notification[1]);
9154 $html .= $OUTPUT->notification($message, \core\output\notification
::NOTIFY_WARNING
);
9162 * Retrieves the current setting using the objects name
9166 public function get_setting() {
9169 // First check if is not set.
9170 $result = $this->config_read($this->name
);
9171 if (is_null($result)) {
9175 // For install cli script, $CFG->defaultuserroleid is not set so return 0
9176 // Or if web services aren't enabled this can't be,
9177 if (empty($CFG->defaultuserroleid
) ||
empty($CFG->enablewebservices
)) {
9181 require_once($CFG->dirroot
. '/webservice/lib.php');
9182 $webservicemanager = new webservice();
9183 $mobileservice = $webservicemanager->get_external_service_by_shortname(MOODLE_OFFICIAL_MOBILE_SERVICE
);
9184 if ($mobileservice->enabled
and $this->is_protocol_cap_allowed()) {
9192 * Save the selected setting
9194 * @param string $data The selected site
9195 * @return string empty string or error message
9197 public function write_setting($data) {
9200 //for install cli script, $CFG->defaultuserroleid is not set so do nothing
9201 if (empty($CFG->defaultuserroleid
)) {
9205 $servicename = MOODLE_OFFICIAL_MOBILE_SERVICE
;
9207 require_once($CFG->dirroot
. '/webservice/lib.php');
9208 $webservicemanager = new webservice();
9210 $updateprotocol = false;
9211 if ((string)$data === $this->yes
) {
9212 //code run when enable mobile web service
9213 //enable web service systeme if necessary
9214 set_config('enablewebservices', true);
9216 //enable mobile service
9217 $mobileservice = $webservicemanager->get_external_service_by_shortname(MOODLE_OFFICIAL_MOBILE_SERVICE
);
9218 $mobileservice->enabled
= 1;
9219 $webservicemanager->update_external_service($mobileservice);
9221 // Enable REST server.
9222 $activeprotocols = empty($CFG->webserviceprotocols
) ?
array() : explode(',', $CFG->webserviceprotocols
);
9224 if (!in_array('rest', $activeprotocols)) {
9225 $activeprotocols[] = 'rest';
9226 $updateprotocol = true;
9229 if ($updateprotocol) {
9230 set_config('webserviceprotocols', implode(',', $activeprotocols));
9233 // Allow rest:use capability for authenticated user.
9234 $this->set_protocol_cap(true);
9237 //disable web service system if no other services are enabled
9238 $otherenabledservices = $DB->get_records_select('external_services',
9239 'enabled = :enabled AND (shortname != :shortname OR shortname IS NULL)', array('enabled' => 1,
9240 'shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE
));
9241 if (empty($otherenabledservices)) {
9242 set_config('enablewebservices', false);
9244 // Also disable REST server.
9245 $activeprotocols = empty($CFG->webserviceprotocols
) ?
array() : explode(',', $CFG->webserviceprotocols
);
9247 $protocolkey = array_search('rest', $activeprotocols);
9248 if ($protocolkey !== false) {
9249 unset($activeprotocols[$protocolkey]);
9250 $updateprotocol = true;
9253 if ($updateprotocol) {
9254 set_config('webserviceprotocols', implode(',', $activeprotocols));
9257 // Disallow rest:use capability for authenticated user.
9258 $this->set_protocol_cap(false);
9261 //disable the mobile service
9262 $mobileservice = $webservicemanager->get_external_service_by_shortname(MOODLE_OFFICIAL_MOBILE_SERVICE
);
9263 $mobileservice->enabled
= 0;
9264 $webservicemanager->update_external_service($mobileservice);
9267 return (parent
::write_setting($data));
9272 * Special class for management of external services
9274 * @author Petr Skoda (skodak)
9276 class admin_setting_manageexternalservices
extends admin_setting
{
9278 * Calls parent::__construct with specific arguments
9280 public function __construct() {
9281 $this->nosave
= true;
9282 parent
::__construct('webservicesui', get_string('externalservices', 'webservice'), '', '');
9286 * Always returns true, does nothing
9290 public function get_setting() {
9295 * Always returns true, does nothing
9299 public function get_defaultsetting() {
9304 * Always returns '', does not write anything
9306 * @return string Always returns ''
9308 public function write_setting($data) {
9309 // do not write any setting
9314 * Checks if $query is one of the available external services
9316 * @param string $query The string to search for
9317 * @return bool Returns true if found, false if not
9319 public function is_related($query) {
9322 if (parent
::is_related($query)) {
9326 $services = $DB->get_records('external_services', array(), 'id, name');
9327 foreach ($services as $service) {
9328 if (strpos(core_text
::strtolower($service->name
), $query) !== false) {
9336 * Builds the XHTML to display the control
9338 * @param string $data Unused
9339 * @param string $query
9342 public function output_html($data, $query='') {
9343 global $CFG, $OUTPUT, $DB;
9346 $stradministration = get_string('administration');
9347 $stredit = get_string('edit');
9348 $strservice = get_string('externalservice', 'webservice');
9349 $strdelete = get_string('delete');
9350 $strplugin = get_string('plugin', 'admin');
9351 $stradd = get_string('add');
9352 $strfunctions = get_string('functions', 'webservice');
9353 $strusers = get_string('users');
9354 $strserviceusers = get_string('serviceusers', 'webservice');
9356 $esurl = "$CFG->wwwroot/$CFG->admin/webservice/service.php";
9357 $efurl = "$CFG->wwwroot/$CFG->admin/webservice/service_functions.php";
9358 $euurl = "$CFG->wwwroot/$CFG->admin/webservice/service_users.php";
9360 // built in services
9361 $services = $DB->get_records_select('external_services', 'component IS NOT NULL', null, 'name');
9363 if (!empty($services)) {
9364 $return .= $OUTPUT->heading(get_string('servicesbuiltin', 'webservice'), 3, 'main');
9368 $table = new html_table();
9369 $table->head
= array($strservice, $strplugin, $strfunctions, $strusers, $stredit);
9370 $table->colclasses
= array('leftalign service', 'leftalign plugin', 'centeralign functions', 'centeralign users', 'centeralign ');
9371 $table->id
= 'builtinservices';
9372 $table->attributes
['class'] = 'admintable externalservices generaltable';
9373 $table->data
= array();
9375 // iterate through auth plugins and add to the display table
9376 foreach ($services as $service) {
9377 $name = $service->name
;
9380 if ($service->enabled
) {
9381 $displayname = "<span>$name</span>";
9383 $displayname = "<span class=\"dimmed_text\">$name</span>";
9386 $plugin = $service->component
;
9388 $functions = "<a href=\"$efurl?id=$service->id\">$strfunctions</a>";
9390 if ($service->restrictedusers
) {
9391 $users = "<a href=\"$euurl?id=$service->id\">$strserviceusers</a>";
9393 $users = get_string('allusers', 'webservice');
9396 $edit = "<a href=\"$esurl?id=$service->id\">$stredit</a>";
9398 // add a row to the table
9399 $table->data
[] = array($displayname, $plugin, $functions, $users, $edit);
9401 $return .= html_writer
::table($table);
9405 $return .= $OUTPUT->heading(get_string('servicescustom', 'webservice'), 3, 'main');
9406 $services = $DB->get_records_select('external_services', 'component IS NULL', null, 'name');
9408 $table = new html_table();
9409 $table->head
= array($strservice, $strdelete, $strfunctions, $strusers, $stredit);
9410 $table->colclasses
= array('leftalign service', 'leftalign plugin', 'centeralign functions', 'centeralign users', 'centeralign ');
9411 $table->id
= 'customservices';
9412 $table->attributes
['class'] = 'admintable externalservices generaltable';
9413 $table->data
= array();
9415 // iterate through auth plugins and add to the display table
9416 foreach ($services as $service) {
9417 $name = $service->name
;
9420 if ($service->enabled
) {
9421 $displayname = "<span>$name</span>";
9423 $displayname = "<span class=\"dimmed_text\">$name</span>";
9427 $delete = "<a href=\"$esurl?action=delete&sesskey=".sesskey()."&id=$service->id\">$strdelete</a>";
9429 $functions = "<a href=\"$efurl?id=$service->id\">$strfunctions</a>";
9431 if ($service->restrictedusers
) {
9432 $users = "<a href=\"$euurl?id=$service->id\">$strserviceusers</a>";
9434 $users = get_string('allusers', 'webservice');
9437 $edit = "<a href=\"$esurl?id=$service->id\">$stredit</a>";
9439 // add a row to the table
9440 $table->data
[] = array($displayname, $delete, $functions, $users, $edit);
9442 // add new custom service option
9443 $return .= html_writer
::table($table);
9445 $return .= '<br />';
9446 // add a token to the table
9447 $return .= "<a href=\"$esurl?id=0\">$stradd</a>";
9449 return highlight($query, $return);
9454 * Special class for overview of external services
9456 * @author Jerome Mouneyrac
9458 class admin_setting_webservicesoverview
extends admin_setting
{
9461 * Calls parent::__construct with specific arguments
9463 public function __construct() {
9464 $this->nosave
= true;
9465 parent
::__construct('webservicesoverviewui',
9466 get_string('webservicesoverview', 'webservice'), '', '');
9470 * Always returns true, does nothing
9474 public function get_setting() {
9479 * Always returns true, does nothing
9483 public function get_defaultsetting() {
9488 * Always returns '', does not write anything
9490 * @return string Always returns ''
9492 public function write_setting($data) {
9493 // do not write any setting
9498 * Builds the XHTML to display the control
9500 * @param string $data Unused
9501 * @param string $query
9504 public function output_html($data, $query='') {
9505 global $CFG, $OUTPUT;
9508 $brtag = html_writer
::empty_tag('br');
9510 /// One system controlling Moodle with Token
9511 $return .= $OUTPUT->heading(get_string('onesystemcontrolling', 'webservice'), 3, 'main');
9512 $table = new html_table();
9513 $table->head
= array(get_string('step', 'webservice'), get_string('status'),
9514 get_string('description'));
9515 $table->colclasses
= array('leftalign step', 'leftalign status', 'leftalign description');
9516 $table->id
= 'onesystemcontrol';
9517 $table->attributes
['class'] = 'admintable wsoverview generaltable';
9518 $table->data
= array();
9520 $return .= $brtag . get_string('onesystemcontrollingdescription', 'webservice')
9523 /// 1. Enable Web Services
9525 $url = new moodle_url("/admin/search.php?query=enablewebservices");
9526 $row[0] = "1. " . html_writer
::tag('a', get_string('enablews', 'webservice'),
9527 array('href' => $url));
9528 $status = html_writer
::tag('span', get_string('no'), array('class' => 'statuscritical'));
9529 if ($CFG->enablewebservices
) {
9530 $status = get_string('yes');
9533 $row[2] = get_string('enablewsdescription', 'webservice');
9534 $table->data
[] = $row;
9536 /// 2. Enable protocols
9538 $url = new moodle_url("/admin/settings.php?section=webserviceprotocols");
9539 $row[0] = "2. " . html_writer
::tag('a', get_string('enableprotocols', 'webservice'),
9540 array('href' => $url));
9541 $status = html_writer
::tag('span', get_string('none'), array('class' => 'statuscritical'));
9542 //retrieve activated protocol
9543 $active_protocols = empty($CFG->webserviceprotocols
) ?
9544 array() : explode(',', $CFG->webserviceprotocols
);
9545 if (!empty($active_protocols)) {
9547 foreach ($active_protocols as $protocol) {
9548 $status .= $protocol . $brtag;
9552 $row[2] = get_string('enableprotocolsdescription', 'webservice');
9553 $table->data
[] = $row;
9555 /// 3. Create user account
9557 $url = new moodle_url("/user/editadvanced.php?id=-1");
9558 $row[0] = "3. " . html_writer
::tag('a', get_string('createuser', 'webservice'),
9559 array('href' => $url));
9561 $row[2] = get_string('createuserdescription', 'webservice');
9562 $table->data
[] = $row;
9564 /// 4. Add capability to users
9566 $url = new moodle_url("/admin/roles/check.php?contextid=1");
9567 $row[0] = "4. " . html_writer
::tag('a', get_string('checkusercapability', 'webservice'),
9568 array('href' => $url));
9570 $row[2] = get_string('checkusercapabilitydescription', 'webservice');
9571 $table->data
[] = $row;
9573 /// 5. Select a web service
9575 $url = new moodle_url("/admin/settings.php?section=externalservices");
9576 $row[0] = "5. " . html_writer
::tag('a', get_string('selectservice', 'webservice'),
9577 array('href' => $url));
9579 $row[2] = get_string('createservicedescription', 'webservice');
9580 $table->data
[] = $row;
9582 /// 6. Add functions
9584 $url = new moodle_url("/admin/settings.php?section=externalservices");
9585 $row[0] = "6. " . html_writer
::tag('a', get_string('addfunctions', 'webservice'),
9586 array('href' => $url));
9588 $row[2] = get_string('addfunctionsdescription', 'webservice');
9589 $table->data
[] = $row;
9591 /// 7. Add the specific user
9593 $url = new moodle_url("/admin/settings.php?section=externalservices");
9594 $row[0] = "7. " . html_writer
::tag('a', get_string('selectspecificuser', 'webservice'),
9595 array('href' => $url));
9597 $row[2] = get_string('selectspecificuserdescription', 'webservice');
9598 $table->data
[] = $row;
9600 /// 8. Create token for the specific user
9602 $url = new moodle_url("/admin/webservice/tokens.php?sesskey=" . sesskey() . "&action=create");
9603 $row[0] = "8. " . html_writer
::tag('a', get_string('createtokenforuser', 'webservice'),
9604 array('href' => $url));
9606 $row[2] = get_string('createtokenforuserdescription', 'webservice');
9607 $table->data
[] = $row;
9609 /// 9. Enable the documentation
9611 $url = new moodle_url("/admin/search.php?query=enablewsdocumentation");
9612 $row[0] = "9. " . html_writer
::tag('a', get_string('enabledocumentation', 'webservice'),
9613 array('href' => $url));
9614 $status = '<span class="warning">' . get_string('no') . '</span>';
9615 if ($CFG->enablewsdocumentation
) {
9616 $status = get_string('yes');
9619 $row[2] = get_string('enabledocumentationdescription', 'webservice');
9620 $table->data
[] = $row;
9622 /// 10. Test the service
9624 $url = new moodle_url("/admin/webservice/testclient.php");
9625 $row[0] = "10. " . html_writer
::tag('a', get_string('testwithtestclient', 'webservice'),
9626 array('href' => $url));
9628 $row[2] = get_string('testwithtestclientdescription', 'webservice');
9629 $table->data
[] = $row;
9631 $return .= html_writer
::table($table);
9633 /// Users as clients with token
9634 $return .= $brtag . $brtag . $brtag;
9635 $return .= $OUTPUT->heading(get_string('userasclients', 'webservice'), 3, 'main');
9636 $table = new html_table();
9637 $table->head
= array(get_string('step', 'webservice'), get_string('status'),
9638 get_string('description'));
9639 $table->colclasses
= array('leftalign step', 'leftalign status', 'leftalign description');
9640 $table->id
= 'userasclients';
9641 $table->attributes
['class'] = 'admintable wsoverview generaltable';
9642 $table->data
= array();
9644 $return .= $brtag . get_string('userasclientsdescription', 'webservice') .
9647 /// 1. Enable Web Services
9649 $url = new moodle_url("/admin/search.php?query=enablewebservices");
9650 $row[0] = "1. " . html_writer
::tag('a', get_string('enablews', 'webservice'),
9651 array('href' => $url));
9652 $status = html_writer
::tag('span', get_string('no'), array('class' => 'statuscritical'));
9653 if ($CFG->enablewebservices
) {
9654 $status = get_string('yes');
9657 $row[2] = get_string('enablewsdescription', 'webservice');
9658 $table->data
[] = $row;
9660 /// 2. Enable protocols
9662 $url = new moodle_url("/admin/settings.php?section=webserviceprotocols");
9663 $row[0] = "2. " . html_writer
::tag('a', get_string('enableprotocols', 'webservice'),
9664 array('href' => $url));
9665 $status = html_writer
::tag('span', get_string('none'), array('class' => 'statuscritical'));
9666 //retrieve activated protocol
9667 $active_protocols = empty($CFG->webserviceprotocols
) ?
9668 array() : explode(',', $CFG->webserviceprotocols
);
9669 if (!empty($active_protocols)) {
9671 foreach ($active_protocols as $protocol) {
9672 $status .= $protocol . $brtag;
9676 $row[2] = get_string('enableprotocolsdescription', 'webservice');
9677 $table->data
[] = $row;
9680 /// 3. Select a web service
9682 $url = new moodle_url("/admin/settings.php?section=externalservices");
9683 $row[0] = "3. " . html_writer
::tag('a', get_string('selectservice', 'webservice'),
9684 array('href' => $url));
9686 $row[2] = get_string('createserviceforusersdescription', 'webservice');
9687 $table->data
[] = $row;
9689 /// 4. Add functions
9691 $url = new moodle_url("/admin/settings.php?section=externalservices");
9692 $row[0] = "4. " . html_writer
::tag('a', get_string('addfunctions', 'webservice'),
9693 array('href' => $url));
9695 $row[2] = get_string('addfunctionsdescription', 'webservice');
9696 $table->data
[] = $row;
9698 /// 5. Add capability to users
9700 $url = new moodle_url("/admin/roles/check.php?contextid=1");
9701 $row[0] = "5. " . html_writer
::tag('a', get_string('addcapabilitytousers', 'webservice'),
9702 array('href' => $url));
9704 $row[2] = get_string('addcapabilitytousersdescription', 'webservice');
9705 $table->data
[] = $row;
9707 /// 6. Test the service
9709 $url = new moodle_url("/admin/webservice/testclient.php");
9710 $row[0] = "6. " . html_writer
::tag('a', get_string('testwithtestclient', 'webservice'),
9711 array('href' => $url));
9713 $row[2] = get_string('testauserwithtestclientdescription', 'webservice');
9714 $table->data
[] = $row;
9716 $return .= html_writer
::table($table);
9718 return highlight($query, $return);
9725 * Special class for web service protocol administration.
9727 * @author Petr Skoda (skodak)
9729 class admin_setting_managewebserviceprotocols
extends admin_setting
{
9732 * Calls parent::__construct with specific arguments
9734 public function __construct() {
9735 $this->nosave
= true;
9736 parent
::__construct('webservicesui', get_string('manageprotocols', 'webservice'), '', '');
9740 * Always returns true, does nothing
9744 public function get_setting() {
9749 * Always returns true, does nothing
9753 public function get_defaultsetting() {
9758 * Always returns '', does not write anything
9760 * @return string Always returns ''
9762 public function write_setting($data) {
9763 // do not write any setting
9768 * Checks if $query is one of the available webservices
9770 * @param string $query The string to search for
9771 * @return bool Returns true if found, false if not
9773 public function is_related($query) {
9774 if (parent
::is_related($query)) {
9778 $protocols = core_component
::get_plugin_list('webservice');
9779 foreach ($protocols as $protocol=>$location) {
9780 if (strpos($protocol, $query) !== false) {
9783 $protocolstr = get_string('pluginname', 'webservice_'.$protocol);
9784 if (strpos(core_text
::strtolower($protocolstr), $query) !== false) {
9792 * Builds the XHTML to display the control
9794 * @param string $data Unused
9795 * @param string $query
9798 public function output_html($data, $query='') {
9799 global $CFG, $OUTPUT;
9802 $stradministration = get_string('administration');
9803 $strsettings = get_string('settings');
9804 $stredit = get_string('edit');
9805 $strprotocol = get_string('protocol', 'webservice');
9806 $strenable = get_string('enable');
9807 $strdisable = get_string('disable');
9808 $strversion = get_string('version');
9810 $protocols_available = core_component
::get_plugin_list('webservice');
9811 $active_protocols = empty($CFG->webserviceprotocols
) ?
array() : explode(',', $CFG->webserviceprotocols
);
9812 ksort($protocols_available);
9814 foreach ($active_protocols as $key=>$protocol) {
9815 if (empty($protocols_available[$protocol])) {
9816 unset($active_protocols[$key]);
9820 $return = $OUTPUT->heading(get_string('actwebserviceshhdr', 'webservice'), 3, 'main');
9821 $return .= $OUTPUT->box_start('generalbox webservicesui');
9823 $table = new html_table();
9824 $table->head
= array($strprotocol, $strversion, $strenable, $strsettings);
9825 $table->colclasses
= array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign');
9826 $table->id
= 'webserviceprotocols';
9827 $table->attributes
['class'] = 'admintable generaltable';
9828 $table->data
= array();
9830 // iterate through auth plugins and add to the display table
9831 $url = "$CFG->wwwroot/$CFG->admin/webservice/protocols.php?sesskey=" . sesskey();
9832 foreach ($protocols_available as $protocol => $location) {
9833 $name = get_string('pluginname', 'webservice_'.$protocol);
9835 $plugin = new stdClass();
9836 if (file_exists($CFG->dirroot
.'/webservice/'.$protocol.'/version.php')) {
9837 include($CFG->dirroot
.'/webservice/'.$protocol.'/version.php');
9839 $version = isset($plugin->version
) ?
$plugin->version
: '';
9842 if (in_array($protocol, $active_protocols)) {
9843 $hideshow = "<a href=\"$url&action=disable&webservice=$protocol\">";
9844 $hideshow .= $OUTPUT->pix_icon('t/hide', $strdisable) . '</a>';
9845 $displayname = "<span>$name</span>";
9847 $hideshow = "<a href=\"$url&action=enable&webservice=$protocol\">";
9848 $hideshow .= $OUTPUT->pix_icon('t/show', $strenable) . '</a>';
9849 $displayname = "<span class=\"dimmed_text\">$name</span>";
9853 if (file_exists($CFG->dirroot
.'/webservice/'.$protocol.'/settings.php')) {
9854 $settings = "<a href=\"settings.php?section=webservicesetting$protocol\">$strsettings</a>";
9859 // add a row to the table
9860 $table->data
[] = array($displayname, $version, $hideshow, $settings);
9862 $return .= html_writer
::table($table);
9863 $return .= get_string('configwebserviceplugins', 'webservice');
9864 $return .= $OUTPUT->box_end();
9866 return highlight($query, $return);
9872 * Special class for web service token administration.
9874 * @author Jerome Mouneyrac
9876 class admin_setting_managewebservicetokens
extends admin_setting
{
9879 * Calls parent::__construct with specific arguments
9881 public function __construct() {
9882 $this->nosave
= true;
9883 parent
::__construct('webservicestokenui', get_string('managetokens', 'webservice'), '', '');
9887 * Always returns true, does nothing
9891 public function get_setting() {
9896 * Always returns true, does nothing
9900 public function get_defaultsetting() {
9905 * Always returns '', does not write anything
9907 * @return string Always returns ''
9909 public function write_setting($data) {
9910 // do not write any setting
9915 * Builds the XHTML to display the control
9917 * @param string $data Unused
9918 * @param string $query
9921 public function output_html($data, $query='') {
9922 global $CFG, $OUTPUT;
9924 require_once($CFG->dirroot
. '/webservice/classes/token_table.php');
9925 $baseurl = new moodle_url('/' . $CFG->admin
. '/settings.php?section=webservicetokens');
9927 $return = $OUTPUT->box_start('generalbox webservicestokenui');
9929 if (has_capability('moodle/webservice:managealltokens', context_system
::instance())) {
9930 $return .= \html_writer
::div(get_string('onlyseecreatedtokens', 'webservice'));
9933 $table = new \webservice\token_table
('webservicetokens');
9934 $table->define_baseurl($baseurl);
9935 $table->attributes
['class'] = 'admintable generaltable'; // Any need changing?
9936 $table->data
= array();
9938 $table->out(10, false);
9939 $tablehtml = ob_get_contents();
9941 $return .= $tablehtml;
9943 $tokenpageurl = "$CFG->wwwroot/$CFG->admin/webservice/tokens.php?sesskey=" . sesskey();
9945 $return .= $OUTPUT->box_end();
9946 // add a token to the table
9947 $return .= "<a href=\"".$tokenpageurl."&action=create\">";
9948 $return .= get_string('add')."</a>";
9950 return highlight($query, $return);
9958 * @copyright 2010 Sam Hemelryk
9959 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
9961 class admin_setting_configcolourpicker
extends admin_setting
{
9964 * Information for previewing the colour
9968 protected $previewconfig = null;
9971 * Use default when empty.
9973 protected $usedefaultwhenempty = true;
9977 * @param string $name
9978 * @param string $visiblename
9979 * @param string $description
9980 * @param string $defaultsetting
9981 * @param array $previewconfig Array('selector'=>'.some .css .selector','style'=>'backgroundColor');
9983 public function __construct($name, $visiblename, $description, $defaultsetting, array $previewconfig = null,
9984 $usedefaultwhenempty = true) {
9985 $this->previewconfig
= $previewconfig;
9986 $this->usedefaultwhenempty
= $usedefaultwhenempty;
9987 parent
::__construct($name, $visiblename, $description, $defaultsetting);
9988 $this->set_force_ltr(true);
9992 * Return the setting
9994 * @return mixed returns config if successful else null
9996 public function get_setting() {
9997 return $this->config_read($this->name
);
10001 * Saves the setting
10003 * @param string $data
10006 public function write_setting($data) {
10007 $data = $this->validate($data);
10008 if ($data === false) {
10009 return get_string('validateerror', 'admin');
10011 return ($this->config_write($this->name
, $data) ?
'' : get_string('errorsetting', 'admin'));
10015 * Validates the colour that was entered by the user
10017 * @param string $data
10018 * @return string|false
10020 protected function validate($data) {
10022 * List of valid HTML colour names
10026 $colornames = array(
10027 'aliceblue', 'antiquewhite', 'aqua', 'aquamarine', 'azure',
10028 'beige', 'bisque', 'black', 'blanchedalmond', 'blue',
10029 'blueviolet', 'brown', 'burlywood', 'cadetblue', 'chartreuse',
10030 'chocolate', 'coral', 'cornflowerblue', 'cornsilk', 'crimson',
10031 'cyan', 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray',
10032 'darkgrey', 'darkgreen', 'darkkhaki', 'darkmagenta',
10033 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred',
10034 'darksalmon', 'darkseagreen', 'darkslateblue', 'darkslategray',
10035 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink',
10036 'deepskyblue', 'dimgray', 'dimgrey', 'dodgerblue', 'firebrick',
10037 'floralwhite', 'forestgreen', 'fuchsia', 'gainsboro',
10038 'ghostwhite', 'gold', 'goldenrod', 'gray', 'grey', 'green',
10039 'greenyellow', 'honeydew', 'hotpink', 'indianred', 'indigo',
10040 'ivory', 'khaki', 'lavender', 'lavenderblush', 'lawngreen',
10041 'lemonchiffon', 'lightblue', 'lightcoral', 'lightcyan',
10042 'lightgoldenrodyellow', 'lightgray', 'lightgrey', 'lightgreen',
10043 'lightpink', 'lightsalmon', 'lightseagreen', 'lightskyblue',
10044 'lightslategray', 'lightslategrey', 'lightsteelblue', 'lightyellow',
10045 'lime', 'limegreen', 'linen', 'magenta', 'maroon',
10046 'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple',
10047 'mediumseagreen', 'mediumslateblue', 'mediumspringgreen',
10048 'mediumturquoise', 'mediumvioletred', 'midnightblue', 'mintcream',
10049 'mistyrose', 'moccasin', 'navajowhite', 'navy', 'oldlace', 'olive',
10050 'olivedrab', 'orange', 'orangered', 'orchid', 'palegoldenrod',
10051 'palegreen', 'paleturquoise', 'palevioletred', 'papayawhip',
10052 'peachpuff', 'peru', 'pink', 'plum', 'powderblue', 'purple', 'red',
10053 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown',
10054 'seagreen', 'seashell', 'sienna', 'silver', 'skyblue', 'slateblue',
10055 'slategray', 'slategrey', 'snow', 'springgreen', 'steelblue', 'tan',
10056 'teal', 'thistle', 'tomato', 'turquoise', 'violet', 'wheat', 'white',
10057 'whitesmoke', 'yellow', 'yellowgreen'
10060 if (preg_match('/^#?([[:xdigit:]]{3}){1,2}$/', $data)) {
10061 if (strpos($data, '#')!==0) {
10065 } else if (in_array(strtolower($data), $colornames)) {
10067 } else if (preg_match('/rgb\(\d{0,3}%?\, ?\d{0,3}%?, ?\d{0,3}%?\)/i', $data)) {
10069 } else if (preg_match('/rgba\(\d{0,3}%?\, ?\d{0,3}%?, ?\d{0,3}%?\, ?\d(\.\d)?\)/i', $data)) {
10071 } else if (preg_match('/hsl\(\d{0,3}\, ?\d{0,3}%, ?\d{0,3}%\)/i', $data)) {
10073 } else if (preg_match('/hsla\(\d{0,3}\, ?\d{0,3}%,\d{0,3}%\, ?\d(\.\d)?\)/i', $data)) {
10075 } else if (($data == 'transparent') ||
($data == 'currentColor') ||
($data == 'inherit')) {
10077 } else if (empty($data)) {
10078 if ($this->usedefaultwhenempty
){
10079 return $this->defaultsetting
;
10089 * Generates the HTML for the setting
10091 * @global moodle_page $PAGE
10092 * @global core_renderer $OUTPUT
10093 * @param string $data
10094 * @param string $query
10096 public function output_html($data, $query = '') {
10097 global $PAGE, $OUTPUT;
10099 $icon = new pix_icon('i/loading', get_string('loading', 'admin'), 'moodle', ['class' => 'loadingicon']);
10100 $context = (object) [
10101 'id' => $this->get_id(),
10102 'name' => $this->get_full_name(),
10104 'icon' => $icon->export_for_template($OUTPUT),
10105 'haspreviewconfig' => !empty($this->previewconfig
),
10106 'forceltr' => $this->get_force_ltr()
10109 $element = $OUTPUT->render_from_template('core_admin/setting_configcolourpicker', $context);
10110 $PAGE->requires
->js_init_call('M.util.init_colour_picker', array($this->get_id(), $this->previewconfig
));
10112 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, true, '',
10113 $this->get_defaultsetting(), $query);
10120 * Class used for uploading of one file into file storage,
10121 * the file name is stored in config table.
10123 * Please note you need to implement your own '_pluginfile' callback function,
10124 * this setting only stores the file, it does not deal with file serving.
10126 * @copyright 2013 Petr Skoda {@link http://skodak.org}
10127 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
10129 class admin_setting_configstoredfile
extends admin_setting
{
10130 /** @var array file area options - should be one file only */
10131 protected $options;
10132 /** @var string name of the file area */
10133 protected $filearea;
10134 /** @var int intemid */
10136 /** @var string used for detection of changes */
10137 protected $oldhashes;
10140 * Create new stored file setting.
10142 * @param string $name low level setting name
10143 * @param string $visiblename human readable setting name
10144 * @param string $description description of setting
10145 * @param mixed $filearea file area for file storage
10146 * @param int $itemid itemid for file storage
10147 * @param array $options file area options
10149 public function __construct($name, $visiblename, $description, $filearea, $itemid = 0, array $options = null) {
10150 parent
::__construct($name, $visiblename, $description, '');
10151 $this->filearea
= $filearea;
10152 $this->itemid
= $itemid;
10153 $this->options
= (array)$options;
10157 * Applies defaults and returns all options.
10160 protected function get_options() {
10163 require_once("$CFG->libdir/filelib.php");
10164 require_once("$CFG->dirroot/repository/lib.php");
10166 'mainfile' => '', 'subdirs' => 0, 'maxbytes' => -1, 'maxfiles' => 1,
10167 'accepted_types' => '*', 'return_types' => FILE_INTERNAL
, 'areamaxbytes' => FILE_AREA_MAX_BYTES_UNLIMITED
,
10168 'context' => context_system
::instance());
10169 foreach($this->options
as $k => $v) {
10170 $defaults[$k] = $v;
10176 public function get_setting() {
10177 return $this->config_read($this->name
);
10180 public function write_setting($data) {
10183 // Let's not deal with validation here, this is for admins only.
10184 $current = $this->get_setting();
10185 if (empty($data) && $current === null) {
10186 // This will be the case when applying default settings (installation).
10187 return ($this->config_write($this->name
, '') ?
'' : get_string('errorsetting', 'admin'));
10188 } else if (!is_number($data)) {
10189 // Draft item id is expected here!
10190 return get_string('errorsetting', 'admin');
10193 $options = $this->get_options();
10194 $fs = get_file_storage();
10195 $component = is_null($this->plugin
) ?
'core' : $this->plugin
;
10197 $this->oldhashes
= null;
10199 $hash = sha1('/'.$options['context']->id
.'/'.$component.'/'.$this->filearea
.'/'.$this->itemid
.$current);
10200 if ($file = $fs->get_file_by_hash($hash)) {
10201 $this->oldhashes
= $file->get_contenthash().$file->get_pathnamehash();
10206 if ($fs->file_exists($options['context']->id
, $component, $this->filearea
, $this->itemid
, '/', '.')) {
10207 // Make sure the settings form was not open for more than 4 days and draft areas deleted in the meantime.
10208 // But we can safely ignore that if the destination area is empty, so that the user is not prompt
10209 // with an error because the draft area does not exist, as he did not use it.
10210 $usercontext = context_user
::instance($USER->id
);
10211 if (!$fs->file_exists($usercontext->id
, 'user', 'draft', $data, '/', '.') && $current !== '') {
10212 return get_string('errorsetting', 'admin');
10216 file_save_draft_area_files($data, $options['context']->id
, $component, $this->filearea
, $this->itemid
, $options);
10217 $files = $fs->get_area_files($options['context']->id
, $component, $this->filearea
, $this->itemid
, 'sortorder,filepath,filename', false);
10221 /** @var stored_file $file */
10222 $file = reset($files);
10223 $filepath = $file->get_filepath().$file->get_filename();
10226 return ($this->config_write($this->name
, $filepath) ?
'' : get_string('errorsetting', 'admin'));
10229 public function post_write_settings($original) {
10230 $options = $this->get_options();
10231 $fs = get_file_storage();
10232 $component = is_null($this->plugin
) ?
'core' : $this->plugin
;
10234 $current = $this->get_setting();
10237 $hash = sha1('/'.$options['context']->id
.'/'.$component.'/'.$this->filearea
.'/'.$this->itemid
.$current);
10238 if ($file = $fs->get_file_by_hash($hash)) {
10239 $newhashes = $file->get_contenthash().$file->get_pathnamehash();
10244 if ($this->oldhashes
=== $newhashes) {
10245 $this->oldhashes
= null;
10248 $this->oldhashes
= null;
10250 $callbackfunction = $this->updatedcallback
;
10251 if (!empty($callbackfunction) and function_exists($callbackfunction)) {
10252 $callbackfunction($this->get_full_name());
10257 public function output_html($data, $query = '') {
10258 global $PAGE, $CFG;
10260 $options = $this->get_options();
10261 $id = $this->get_id();
10262 $elname = $this->get_full_name();
10263 $draftitemid = file_get_submitted_draft_itemid($elname);
10264 $component = is_null($this->plugin
) ?
'core' : $this->plugin
;
10265 file_prepare_draft_area($draftitemid, $options['context']->id
, $component, $this->filearea
, $this->itemid
, $options);
10267 // Filemanager form element implementation is far from optimal, we need to rework this if we ever fix it...
10268 require_once("$CFG->dirroot/lib/form/filemanager.php");
10270 $fmoptions = new stdClass();
10271 $fmoptions->mainfile
= $options['mainfile'];
10272 $fmoptions->maxbytes
= $options['maxbytes'];
10273 $fmoptions->maxfiles
= $options['maxfiles'];
10274 $fmoptions->client_id
= uniqid();
10275 $fmoptions->itemid
= $draftitemid;
10276 $fmoptions->subdirs
= $options['subdirs'];
10277 $fmoptions->target
= $id;
10278 $fmoptions->accepted_types
= $options['accepted_types'];
10279 $fmoptions->return_types
= $options['return_types'];
10280 $fmoptions->context
= $options['context'];
10281 $fmoptions->areamaxbytes
= $options['areamaxbytes'];
10283 $fm = new form_filemanager($fmoptions);
10284 $output = $PAGE->get_renderer('core', 'files');
10285 $html = $output->render($fm);
10287 $html .= '<input value="'.$draftitemid.'" name="'.$elname.'" type="hidden" />';
10288 $html .= '<input value="" id="'.$id.'" type="hidden" />';
10290 return format_admin_setting($this, $this->visiblename
,
10291 '<div class="form-filemanager" data-fieldtype="filemanager">'.$html.'</div>',
10292 $this->description
, true, '', '', $query);
10298 * Administration interface for user specified regular expressions for device detection.
10300 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
10302 class admin_setting_devicedetectregex
extends admin_setting
{
10305 * Calls parent::__construct with specific args
10307 * @param string $name
10308 * @param string $visiblename
10309 * @param string $description
10310 * @param mixed $defaultsetting
10312 public function __construct($name, $visiblename, $description, $defaultsetting = '') {
10314 parent
::__construct($name, $visiblename, $description, $defaultsetting);
10318 * Return the current setting(s)
10320 * @return array Current settings array
10322 public function get_setting() {
10325 $config = $this->config_read($this->name
);
10326 if (is_null($config)) {
10330 return $this->prepare_form_data($config);
10334 * Save selected settings
10336 * @param array $data Array of settings to save
10339 public function write_setting($data) {
10340 if (empty($data)) {
10344 if ($this->config_write($this->name
, $this->process_form_data($data))) {
10345 return ''; // success
10347 return get_string('errorsetting', 'admin') . $this->visiblename
. html_writer
::empty_tag('br');
10352 * Return XHTML field(s) for regexes
10354 * @param array $data Array of options to set in HTML
10355 * @return string XHTML string for the fields and wrapping div(s)
10357 public function output_html($data, $query='') {
10360 $context = (object) [
10361 'expressions' => [],
10362 'name' => $this->get_full_name()
10365 if (empty($data)) {
10368 $looplimit = (count($data)/2)+
1;
10371 for ($i=0; $i<$looplimit; $i++
) {
10373 $expressionname = 'expression'.$i;
10375 if (!empty($data[$expressionname])){
10376 $expression = $data[$expressionname];
10381 $valuename = 'value'.$i;
10383 if (!empty($data[$valuename])){
10384 $value = $data[$valuename];
10389 $context->expressions
[] = [
10391 'expression' => $expression,
10396 $element = $OUTPUT->render_from_template('core_admin/setting_devicedetectregex', $context);
10398 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, false, '', null, $query);
10402 * Converts the string of regexes
10404 * @see self::process_form_data()
10405 * @param $regexes string of regexes
10406 * @return array of form fields and their values
10408 protected function prepare_form_data($regexes) {
10410 $regexes = json_decode($regexes);
10416 foreach ($regexes as $value => $regex) {
10417 $expressionname = 'expression'.$i;
10418 $valuename = 'value'.$i;
10420 $form[$expressionname] = $regex;
10421 $form[$valuename] = $value;
10429 * Converts the data from admin settings form into a string of regexes
10431 * @see self::prepare_form_data()
10432 * @param array $data array of admin form fields and values
10433 * @return false|string of regexes
10435 protected function process_form_data(array $form) {
10437 $count = count($form); // number of form field values
10440 // we must get five fields per expression
10444 $regexes = array();
10445 for ($i = 0; $i < $count / 2; $i++
) {
10446 $expressionname = "expression".$i;
10447 $valuename = "value".$i;
10449 $expression = trim($form['expression'.$i]);
10450 $value = trim($form['value'.$i]);
10452 if (empty($expression)){
10456 $regexes[$value] = $expression;
10459 $regexes = json_encode($regexes);
10467 * Multiselect for current modules
10469 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
10471 class admin_setting_configmultiselect_modules
extends admin_setting_configmultiselect
{
10472 private $excludesystem;
10475 * Calls parent::__construct - note array $choices is not required
10477 * @param string $name setting name
10478 * @param string $visiblename localised setting name
10479 * @param string $description setting description
10480 * @param array $defaultsetting a plain array of default module ids
10481 * @param bool $excludesystem If true, excludes modules with 'system' archetype
10483 public function __construct($name, $visiblename, $description, $defaultsetting = array(),
10484 $excludesystem = true) {
10485 parent
::__construct($name, $visiblename, $description, $defaultsetting, null);
10486 $this->excludesystem
= $excludesystem;
10490 * Loads an array of current module choices
10492 * @return bool always return true
10494 public function load_choices() {
10495 if (is_array($this->choices
)) {
10498 $this->choices
= array();
10501 $records = $DB->get_records('modules', array('visible'=>1), 'name');
10502 foreach ($records as $record) {
10503 // Exclude modules if the code doesn't exist
10504 if (file_exists("$CFG->dirroot/mod/$record->name/lib.php")) {
10505 // Also exclude system modules (if specified)
10506 if (!($this->excludesystem
&&
10507 plugin_supports('mod', $record->name
, FEATURE_MOD_ARCHETYPE
) ===
10508 MOD_ARCHETYPE_SYSTEM
)) {
10509 $this->choices
[$record->id
] = $record->name
;
10518 * Admin setting to show if a php extension is enabled or not.
10520 * @copyright 2013 Damyon Wiese
10521 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
10523 class admin_setting_php_extension_enabled
extends admin_setting
{
10525 /** @var string The name of the extension to check for */
10526 private $extension;
10529 * Calls parent::__construct with specific arguments
10531 public function __construct($name, $visiblename, $description, $extension) {
10532 $this->extension
= $extension;
10533 $this->nosave
= true;
10534 parent
::__construct($name, $visiblename, $description, '');
10538 * Always returns true, does nothing
10542 public function get_setting() {
10547 * Always returns true, does nothing
10551 public function get_defaultsetting() {
10556 * Always returns '', does not write anything
10558 * @return string Always returns ''
10560 public function write_setting($data) {
10561 // Do not write any setting.
10566 * Outputs the html for this setting.
10567 * @return string Returns an XHTML string
10569 public function output_html($data, $query='') {
10573 if (!extension_loaded($this->extension
)) {
10574 $warning = $OUTPUT->pix_icon('i/warning', '', '', array('role' => 'presentation')) . ' ' . $this->description
;
10576 $o .= format_admin_setting($this, $this->visiblename
, $warning);
10583 * Server timezone setting.
10585 * @copyright 2015 Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
10586 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
10587 * @author Petr Skoda <petr.skoda@totaralms.com>
10589 class admin_setting_servertimezone
extends admin_setting_configselect
{
10593 public function __construct() {
10594 $default = core_date
::get_default_php_timezone();
10595 if ($default === 'UTC') {
10596 // Nobody really wants UTC, so instead default selection to the country that is confused by the UTC the most.
10597 $default = 'Europe/London';
10600 parent
::__construct('timezone',
10601 new lang_string('timezone', 'core_admin'),
10602 new lang_string('configtimezone', 'core_admin'), $default, null);
10606 * Lazy load timezone options.
10607 * @return bool true if loaded, false if error
10609 public function load_choices() {
10611 if (is_array($this->choices
)) {
10615 $current = isset($CFG->timezone
) ?
$CFG->timezone
: null;
10616 $this->choices
= core_date
::get_list_of_timezones($current, false);
10617 if ($current == 99) {
10618 // Do not show 99 unless it is current value, we want to get rid of it over time.
10619 $this->choices
['99'] = new lang_string('timezonephpdefault', 'core_admin',
10620 core_date
::get_default_php_timezone());
10628 * Forced user timezone setting.
10630 * @copyright 2015 Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
10631 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
10632 * @author Petr Skoda <petr.skoda@totaralms.com>
10634 class admin_setting_forcetimezone
extends admin_setting_configselect
{
10638 public function __construct() {
10639 parent
::__construct('forcetimezone',
10640 new lang_string('forcetimezone', 'core_admin'),
10641 new lang_string('helpforcetimezone', 'core_admin'), '99', null);
10645 * Lazy load timezone options.
10646 * @return bool true if loaded, false if error
10648 public function load_choices() {
10650 if (is_array($this->choices
)) {
10654 $current = isset($CFG->forcetimezone
) ?
$CFG->forcetimezone
: null;
10655 $this->choices
= core_date
::get_list_of_timezones($current, true);
10656 $this->choices
['99'] = new lang_string('timezonenotforced', 'core_admin');
10664 * Search setup steps info.
10667 * @copyright 2016 David Monllao {@link http://www.davidmonllao.com}
10668 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
10670 class admin_setting_searchsetupinfo
extends admin_setting
{
10673 * Calls parent::__construct with specific arguments
10675 public function __construct() {
10676 $this->nosave
= true;
10677 parent
::__construct('searchsetupinfo', '', '', '');
10681 * Always returns true, does nothing
10685 public function get_setting() {
10690 * Always returns true, does nothing
10694 public function get_defaultsetting() {
10699 * Always returns '', does not write anything
10701 * @param array $data
10702 * @return string Always returns ''
10704 public function write_setting($data) {
10705 // Do not write any setting.
10710 * Builds the HTML to display the control
10712 * @param string $data Unused
10713 * @param string $query
10716 public function output_html($data, $query='') {
10717 global $CFG, $OUTPUT;
10720 $brtag = html_writer
::empty_tag('br');
10722 $searchareas = \core_search\manager
::get_search_areas_list();
10723 $anyenabled = !empty(\core_search\manager
::get_search_areas_list(true));
10724 $anyindexed = false;
10725 foreach ($searchareas as $areaid => $searcharea) {
10726 list($componentname, $varname) = $searcharea->get_config_var_name();
10727 if (get_config($componentname, $varname . '_indexingstart')) {
10728 $anyindexed = true;
10733 $return .= $OUTPUT->heading(get_string('searchsetupinfo', 'admin'), 3, 'main');
10735 $table = new html_table();
10736 $table->head
= array(get_string('step', 'search'), get_string('status'));
10737 $table->colclasses
= array('leftalign step', 'leftalign status');
10738 $table->id
= 'searchsetup';
10739 $table->attributes
['class'] = 'admintable generaltable';
10740 $table->data
= array();
10742 $return .= $brtag . get_string('searchsetupdescription', 'search') . $brtag . $brtag;
10744 // Select a search engine.
10746 $url = new moodle_url('/admin/settings.php?section=manageglobalsearch#admin-searchengine');
10747 $row[0] = '1. ' . html_writer
::tag('a', get_string('selectsearchengine', 'admin'),
10748 array('href' => $url));
10750 $status = html_writer
::tag('span', get_string('no'), array('class' => 'statuscritical'));
10751 if (!empty($CFG->searchengine
)) {
10752 $status = html_writer
::tag('span', get_string('pluginname', 'search_' . $CFG->searchengine
),
10753 array('class' => 'statusok'));
10757 $table->data
[] = $row;
10759 // Available areas.
10761 $url = new moodle_url('/admin/searchareas.php');
10762 $row[0] = '2. ' . html_writer
::tag('a', get_string('enablesearchareas', 'admin'),
10763 array('href' => $url));
10765 $status = html_writer
::tag('span', get_string('no'), array('class' => 'statuscritical'));
10767 $status = html_writer
::tag('span', get_string('yes'), array('class' => 'statusok'));
10771 $table->data
[] = $row;
10773 // Setup search engine.
10775 if (empty($CFG->searchengine
)) {
10776 $row[0] = '3. ' . get_string('setupsearchengine', 'admin');
10777 $row[1] = html_writer
::tag('span', get_string('no'), array('class' => 'statuscritical'));
10779 $url = new moodle_url('/admin/settings.php?section=search' . $CFG->searchengine
);
10780 $row[0] = '3. ' . html_writer
::tag('a', get_string('setupsearchengine', 'admin'),
10781 array('href' => $url));
10782 // Check the engine status.
10783 $searchengine = \core_search\manager
::search_engine_instance();
10785 $serverstatus = $searchengine->is_server_ready();
10786 } catch (\moodle_exception
$e) {
10787 $serverstatus = $e->getMessage();
10789 if ($serverstatus === true) {
10790 $status = html_writer
::tag('span', get_string('yes'), array('class' => 'statusok'));
10792 $status = html_writer
::tag('span', $serverstatus, array('class' => 'statuscritical'));
10796 $table->data
[] = $row;
10800 $url = new moodle_url('/admin/searchareas.php');
10801 $row[0] = '4. ' . html_writer
::tag('a', get_string('indexdata', 'admin'), array('href' => $url));
10803 $status = html_writer
::tag('span', get_string('yes'), array('class' => 'statusok'));
10805 $status = html_writer
::tag('span', get_string('no'), array('class' => 'statuscritical'));
10808 $table->data
[] = $row;
10810 // Enable global search.
10812 $url = new moodle_url("/admin/search.php?query=enableglobalsearch");
10813 $row[0] = '5. ' . html_writer
::tag('a', get_string('enableglobalsearch', 'admin'),
10814 array('href' => $url));
10815 $status = html_writer
::tag('span', get_string('no'), array('class' => 'statuscritical'));
10816 if (\core_search\manager
::is_global_search_enabled()) {
10817 $status = html_writer
::tag('span', get_string('yes'), array('class' => 'statusok'));
10820 $table->data
[] = $row;
10822 $return .= html_writer
::table($table);
10824 return highlight($query, $return);
10830 * Used to validate the contents of SCSS code and ensuring they are parsable.
10832 * It does not attempt to detect undefined SCSS variables because it is designed
10833 * to be used without knowledge of other config/scss included.
10835 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
10836 * @copyright 2016 Dan Poltawski <dan@moodle.com>
10838 class admin_setting_scsscode
extends admin_setting_configtextarea
{
10841 * Validate the contents of the SCSS to ensure its parsable. Does not
10842 * attempt to detect undefined scss variables.
10844 * @param string $data The scss code from text field.
10845 * @return mixed bool true for success or string:error on failure.
10847 public function validate($data) {
10848 if (empty($data)) {
10852 $scss = new core_scss();
10854 $scss->compile($data);
10855 } catch (Leafo\ScssPhp\Exception\ParserException
$e) {
10856 return get_string('scssinvalid', 'admin', $e->getMessage());
10857 } catch (Leafo\ScssPhp\Exception\CompilerException
$e) {
10858 // Silently ignore this - it could be a scss variable defined from somewhere
10859 // else which we are not examining here.
10869 * Administration setting to define a list of file types.
10871 * @copyright 2016 Jonathon Fowler <fowlerj@usq.edu.au>
10872 * @copyright 2017 David Mudrák <david@moodle.com>
10873 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
10875 class admin_setting_filetypes
extends admin_setting_configtext
{
10877 /** @var array Allow selection from these file types only. */
10878 protected $onlytypes = [];
10880 /** @var bool Allow selection of 'All file types' (will be stored as '*'). */
10881 protected $allowall = true;
10883 /** @var core_form\filetypes_util instance to use as a helper. */
10884 protected $util = null;
10889 * @param string $name Unique ascii name like 'mycoresetting' or 'myplugin/mysetting'
10890 * @param string $visiblename Localised label of the setting
10891 * @param string $description Localised description of the setting
10892 * @param string $defaultsetting Default setting value.
10893 * @param array $options Setting widget options, an array with optional keys:
10894 * 'onlytypes' => array Allow selection from these file types only; for example ['onlytypes' => ['web_image']].
10895 * 'allowall' => bool Allow to select 'All file types', defaults to true. Does not apply if onlytypes are set.
10897 public function __construct($name, $visiblename, $description, $defaultsetting = '', array $options = []) {
10899 parent
::__construct($name, $visiblename, $description, $defaultsetting, PARAM_RAW
);
10901 if (array_key_exists('onlytypes', $options) && is_array($options['onlytypes'])) {
10902 $this->onlytypes
= $options['onlytypes'];
10905 if (!$this->onlytypes
&& array_key_exists('allowall', $options)) {
10906 $this->allowall
= (bool)$options['allowall'];
10909 $this->util
= new \core_form\filetypes_util
();
10913 * Normalize the user's input and write it to the database as comma separated list.
10915 * Comma separated list as a text representation of the array was chosen to
10916 * make this compatible with how the $CFG->courseoverviewfilesext values are stored.
10918 * @param string $data Value submitted by the admin.
10919 * @return string Epty string if all good, error message otherwise.
10921 public function write_setting($data) {
10922 return parent
::write_setting(implode(',', $this->util
->normalize_file_types($data)));
10926 * Validate data before storage
10928 * @param string $data The setting values provided by the admin
10929 * @return bool|string True if ok, the string if error found
10931 public function validate($data) {
10933 // No need to call parent's validation here as we are PARAM_RAW.
10935 if ($this->util
->is_whitelisted($data, $this->onlytypes
)) {
10939 $troublemakers = $this->util
->get_not_whitelisted($data, $this->onlytypes
);
10940 return get_string('filetypesnotwhitelisted', 'core_form', implode(' ', $troublemakers));
10945 * Return an HTML string for the setting element.
10947 * @param string $data The current setting value
10948 * @param string $query Admin search query to be highlighted
10949 * @return string HTML to be displayed
10951 public function output_html($data, $query='') {
10952 global $OUTPUT, $PAGE;
10954 $default = $this->get_defaultsetting();
10955 $context = (object) [
10956 'id' => $this->get_id(),
10957 'name' => $this->get_full_name(),
10959 'descriptions' => $this->util
->describe_file_types($data),
10961 $element = $OUTPUT->render_from_template('core_admin/setting_filetypes', $context);
10963 $PAGE->requires
->js_call_amd('core_form/filetypes', 'init', [
10965 $this->visiblename
->out(),
10970 return format_admin_setting($this, $this->visiblename
, $element, $this->description
, true, '', $default, $query);
10974 * Should the values be always displayed in LTR mode?
10976 * We always return true here because these values are not RTL compatible.
10978 * @return bool True because these values are not RTL compatible.
10980 public function get_force_ltr() {
10986 * Used to validate the content and format of the age of digital consent map and ensuring it is parsable.
10988 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
10989 * @copyright 2018 Mihail Geshoski <mihail@moodle.com>
10991 class admin_setting_agedigitalconsentmap
extends admin_setting_configtextarea
{
10996 * @param string $name
10997 * @param string $visiblename
10998 * @param string $description
10999 * @param mixed $defaultsetting string or array
11000 * @param mixed $paramtype
11001 * @param string $cols
11002 * @param string $rows
11004 public function __construct($name, $visiblename, $description, $defaultsetting, $paramtype = PARAM_RAW
,
11005 $cols = '60', $rows = '8') {
11006 parent
::__construct($name, $visiblename, $description, $defaultsetting, $paramtype, $cols, $rows);
11007 // Pre-set force LTR to false.
11008 $this->set_force_ltr(false);
11012 * Validate the content and format of the age of digital consent map to ensure it is parsable.
11014 * @param string $data The age of digital consent map from text field.
11015 * @return mixed bool true for success or string:error on failure.
11017 public function validate($data) {
11018 if (empty($data)) {
11023 \core_auth\digital_consent
::parse_age_digital_consent_map($data);
11024 } catch (\moodle_exception
$e) {
11025 return get_string('invalidagedigitalconsent', 'admin', $e->getMessage());
11033 * Selection of plugins that can work as site policy handlers
11035 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
11036 * @copyright 2018 Marina Glancy
11038 class admin_settings_sitepolicy_handler_select
extends admin_setting_configselect
{
11042 * @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting'
11043 * for ones in config_plugins.
11044 * @param string $visiblename localised
11045 * @param string $description long localised info
11046 * @param string $defaultsetting
11048 public function __construct($name, $visiblename, $description, $defaultsetting = '') {
11049 parent
::__construct($name, $visiblename, $description, $defaultsetting, null);
11053 * Lazy-load the available choices for the select box
11055 public function load_choices() {
11056 if (during_initial_install()) {
11059 if (is_array($this->choices
)) {
11063 $this->choices
= ['' => new lang_string('sitepolicyhandlercore', 'core_admin')];
11064 $manager = new \core_privacy\local\sitepolicy\
manager();
11065 $plugins = $manager->get_all_handlers();
11066 foreach ($plugins as $pname => $unused) {
11067 $this->choices
[$pname] = new lang_string('sitepolicyhandlerplugin', 'core_admin',
11068 ['name' => new lang_string('pluginname', $pname), 'component' => $pname]);