dirroot . '/backup/lib.php');
//---------------------------------------------------------------------------------------------------
// Interfaces
//---------------------------------------------------------------------------------------------------
// part_of_admin_tree indicates that a node (whether it be an admin_settingpage or an
// admin_category or an admin_externalpage) is searchable
interface part_of_admin_tree {
function &locate($name);
function check_access();
function path($name, $path = array());
}
// parentable_part_of_admin_tree indicates that a node can have children in the hierarchy. only
// admin_category implements this interface (yes, yes, theoretically admin_setting* is a child of
// admin_settingpage, but you can't navigate admin_setting*s through the hierarchy)
interface parentable_part_of_admin_tree {
function add($destinationname, &$something);
}
//---------------------------------------------------------------------------------------------------
// Classes
//---------------------------------------------------------------------------------------------------
// admin categories don't handle much... they can't be printed to the screen (except as a hierarchy), and when we
// check_access() to a category, we're actually just checking if any of its children are accessible
class admin_category implements part_of_admin_tree, parentable_part_of_admin_tree {
var $children;
var $name;
var $visiblename;
function admin_category($name, $visiblename) {
$this->children = array();
$this->name = $name;
$this->visiblename = $visiblename;
}
function path($name, $path = array()) {
$path[count($path)] = $this->name;
if ($this->name == $name) {
return $path;
}
foreach($this->children as $child) {
if ($return = $child->path($name, $path)) {
return $return;
}
}
return NULL;
}
function &locate($name) {
if ($this->name == $name) {
return $this;
}
foreach($this->children as $child) {
if ($return =& $child->locate($name)) {
return $return;
}
}
$return = NULL;
return $return;
}
function add($destinationname, &$something, $precedence = '') {
if (!($something instanceof part_of_admin_tree)) {
return false;
}
if ($destinationname == $this->name) {
if ($precedence === '') {
$this->children[] = $something;
} else {
if (isset($this->children[$precedence])) { // this should never, ever be triggered in a release version of moodle.
echo ('There is a precedence conflict in the category ' . $this->name . '. The object named ' . $something->name . ' is overwriting the object named ' . $this->children[$precedence]->name . '. ');
}
$this->children[$precedence] = $something;
}
return true;
}
foreach($this->children as $child) {
if ($child instanceof parentable_part_of_admin_tree) {
if ($child->add($destinationname, $something, $precedence)) {
return true;
}
}
}
return false;
}
function check_access() {
$return = false;
foreach ($this->children as $child) {
$return = $return || $child->check_access();
}
return $return;
}
}
// this is the class we use to add an external page to the admin hierarchy. on the
// external page (if you'd like), do the following for a consistent look & feel:
// -require_once admin/adminlib.php
// -start the page with a call to admin_externalpage_setup($name)
// -use admin_externalpage_print_header() to print the header & blocks
// -use admin_externalpage_print_footer() to print the footer
class admin_externalpage implements part_of_admin_tree {
var $name;
var $visiblename;
var $url;
var $role;
function admin_externalpage($name, $visiblename, $url, $role = 'moodle/legacy:admin') {
$this->name = $name;
$this->visiblename = $visiblename;
$this->url = $url;
$this->role = $role;
}
function path($name, $path = array()) {
if ($name == $this->name) {
array_push($path, $this->name);
return $path;
} else {
return NULL;
}
}
function &locate($name) {
$return = ($this->name == $name ? $this : NULL);
return $return;
}
function check_access() {
$context = get_context_instance(CONTEXT_SYSTEM, SITEID);
return has_capability($this->role, $context);
}
}
// authentication happens at this level
// an admin_settingpage is a LEAF of the admin_tree, it can't have children. it only contains
// an array of admin_settings that can be printed out onto a webpage
class admin_settingpage implements part_of_admin_tree {
var $name;
var $visiblename;
var $settings;
var $role;
function path($name, $path = array()) {
if ($name == $this->name) {
array_push($path, $this->name);
return $path;
} else {
return NULL;
}
}
function &locate($name) {
$return = ($this->name == $name ? $this : NULL);
return $return;
}
function admin_settingpage($name, $visiblename, $role = 'moodle/legacy:admin') {
$this->settings = new stdClass();
$this->name = $name;
$this->visiblename = $visiblename;
$this->role = $role;
}
function add(&$setting) {
if ($setting instanceof admin_setting) {
$temp = $setting->name;
$this->settings->$temp =& $setting;
return true;
}
return false;
}
function check_access() {
$context = get_context_instance(CONTEXT_SYSTEM, SITEID);
return has_capability($this->role, $context);
}
function output_html() {
$return = '
';
return $return;
}
// return '' (empty string) for successful write, otherwise return language-specific error
function write_settings($data) {
$return = '';
foreach($this->settings as $setting) {
$return .= $setting->write_setting($data['s_' . $setting->name]);
}
return $return;
}
}
// read & write happens at this level; no authentication
class admin_setting {
var $name;
var $visiblename;
var $description;
var $data;
function admin_setting($name, $visiblename, $description) {
$this->name = $name;
$this->visiblename = $visiblename;
$this->description = $description;
}
function get_setting() {
return; // has to be overridden
}
function write_setting($data) {
return; // has to be overridden
}
function output_html() {
return; // has to be overridden
}
}
class admin_setting_configtext extends admin_setting {
var $paramtype;
function admin_setting_configtext($name, $visiblename, $description, $paramtype = 'PARAM_RAW') {
$this->paramtype = $paramtype;
parent::admin_setting($name, $visiblename, $description);
}
function get_setting() {
global $CFG;
$temp = $this->name; // there's gotta be a more elegant way
return $CFG->$temp; // of doing this
}
function write_setting($data) {
$data = clean_param($data, $this->paramtype);
return (set_config($this->name,$data) ? '' : 'Error setting ' . $this->visiblename . ' ');
}
function output_html() {
return '
' . $this->visiblename . '
' .
'
' .
'
' . $this->description . '
';
}
}
class admin_setting_configcheckbox extends admin_setting {
function get_setting() {
global $CFG;
$temp = $this->name; // there's gotta be a more elegant way
return $CFG->$temp; // of doing this
}
function write_setting($data) {
if ($data == '1') {
return (set_config($this->name,1) ? '' : 'Error setting ' . $this->visiblename . ' ');
} else {
return (set_config($this->name,0) ? '' : 'Error setting ' . $this->visiblename . ' ');
}
}
function output_html() {
return '
';
}
}
class admin_setting_configselect extends admin_setting {
var $choices;
function admin_setting_configselect($name, $visiblename, $description, $choices) {
$this->choices = $choices;
parent::admin_setting($name, $visiblename, $description);
}
function get_setting() {
global $CFG;
$temp = $this->name;
return $CFG->$temp;
}
function write_setting($data) {
// check that what we got was in the original choices
if (! in_array($data, array_keys($this->choices))) {
return 'Error setting ' . $this->visiblename . ' ';
}
return (set_config($this->name, $data) ? '' : 'Error setting ' . $this->visiblename . ' ');
}
function output_html() {
$return = '
' . $this->visiblename . '
' . $this->description . '
';
return $return;
}
}
// this is a liiitle bit messy. we're using two selects, but we're returning them as an array named after $name (so we only use $name2
// internally for the setting)
class admin_setting_configtime extends admin_setting {
var $name2;
var $choices;
var $choices2;
function admin_setting_configtime($hoursname, $minutesname, $visiblename, $description) {
$this->name2 = $minutesname;
$this->choices = array();
for ($i = 0; $i < 24; $i++) {
$this->choices[$i] = $i;
}
$this->choices2 = array();
for ($i = 0; $i < 60; $i += 5) {
$this->choices2[$i] = $i;
}
parent::admin_setting($hoursname, $visiblename, $description);
}
function get_setting() {
global $CFG;
$temp = $this->name;
$temp2 = $this->name2;
return array((empty($CFG->$temp) ? 0 : $CFG->$temp), (empty($CFG->$temp2) ? 0 : $CFG->$temp2));
}
function write_setting($data) {
// check that what we got was in the original choices
if (!(in_array($data['h'], array_keys($this->choices)) && in_array($data['m'], array_keys($this->choices2)))) {
return 'Error setting ' . $this->visiblename . ' ';
}
return (set_config($this->name, $data['h']) && set_config($this->name2, $data['m']) ? '' : 'Error setting ' . $this->visiblename . ' ');
}
function output_html() {
$setvalue = $this->get_setting();
$return = '
' . $this->visiblename . '
' . $this->description . '
';
return $return;
}
}
class admin_setting_configmultiselect extends admin_setting_configselect {
function get_setting() {
global $CFG;
$temp = $this->name;
return explode(',', $CFG->$temp);
}
function write_setting($data) {
foreach ($data as $datum) {
if (! in_array($datum, array_keys($this->choices))) {
return 'Error setting ' . $this->visiblename . ' ';
}
}
return (set_config($this->name, implode(',',$data)) ? '' : 'Error setting ' . $this->visiblename . ' ');
}
function output_html() {
$return = '
';
}
// we're using the array trick (see http://ca.php.net/manual/en/faq.html.php#faq.html.arrays) to get the data passed to use without having to modify
// admin_settingpage (note that admin_settingpage only calls write_setting with the data that matches $this->name... so if we have multiple form fields,
// they MUST go into an array named $this->name, or else we won't receive them here
function write_setting($data) {
$week = 'umtwrfs';
$result = array(0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0);
foreach($data as $key => $value) {
if ($value == '1') {
$result[strpos($week, $key)] = 1;
}
}
return (backup_set_config($this->name, implode('',$result)) ? '' : 'Error setting ' . $this->visiblename . ' ');
}
}
class admin_setting_special_debug extends admin_setting_configcheckbox {
function admin_setting_special_debug() {
$name = 'debug';
$visiblename = get_string('debug', 'admin');
$description = get_string('configdebug', 'admin');
parent::admin_setting_configcheckbox($name, $visiblename, $description);
}
function write_setting($data) {
if ($data == '1') {
return (set_config($this->name,15) ? '' : 'Error setting ' . $this->visiblename . ' ');
} else {
return (set_config($this->name,7) ? '' : 'Error setting ' . $this->visiblename . ' ');
}
}
function output_html() {
return '
';
}
}
// Code for a function that helps externalpages print proper headers and footers
// N.B.: THIS FUNCTION HANDLES AUTHENTICATION
function admin_externalpage_setup($section) {
global $CFG, $ADMIN, $PAGE, $_GET, $root;
require_once($CFG->libdir . '/blocklib.php');
require_once($CFG->dirroot . '/admin/pagelib.php');
// we really shouldn't do this... but it works. and it's so elegantly simple.
// oh well :)
$_GET['section'] = $section;
define('TEMPORARY_ADMIN_PAGE_ID',26);
define('BLOCK_L_MIN_WIDTH',160);
define('BLOCK_L_MAX_WIDTH',210);
$pagetype = PAGE_ADMIN; // erm... someone should check this. does
$pageclass = 'page_admin'; // any of it duplicate the code I have in
page_map_class($pagetype, $pageclass); // admin/pagelib.php?
$PAGE = page_create_object($pagetype,TEMPORARY_ADMIN_PAGE_ID);
$PAGE->init_full();
$root = $ADMIN->locate($PAGE->section);
if ($site = get_site()) {
require_login();
} else {
redirect($CFG->wwwroot . '/admin/index.php');
die;
}
if (!($root instanceof admin_externalpage)) {
error('Section does not exist, is invalid, or should not be accessed via this URL.');
die;
}
// this eliminates our need to authenticate on the actual pages
if (!($root->check_access())) {
error('Access denied.');
die;
}
}
function admin_externalpage_print_header() {
global $CFG, $ADMIN, $PAGE, $_GET, $root;
$pageblocks = blocks_setup($PAGE);
$preferred_width_left = bounded_number(BLOCK_L_MIN_WIDTH, blocks_preferred_width($pageblocks[BLOCK_POS_LEFT]), BLOCK_L_MAX_WIDTH);
$PAGE->print_header();
echo '
';
}
function admin_externalpage_print_footer() {
echo '
';
print_footer();
}
// Code to build admin-tree ----------------------------------------------------------------------------
// hrm... gotta put this somewhere more systematic
$site = get_site();
// start the admin tree!
$ADMIN = new admin_category('root','Administration');
// we process this file first to get categories up and running
include_once($CFG->dirroot . '/admin/settings/first.php');
// now we process all other files in admin/settings to build the
// admin tree
foreach (glob($CFG->dirroot . '/admin/settings/*.php') as $file) {
if ($file != $CFG->dirroot . '/admin/settings/first.php') {
include_once($file);
}
}
?>