MDL-8262 fixed require_course_login and $COURSE logic
[moodle.git] / lib / adminlib.php
CommitLineData
a4e10845 1<?php
88a7228a 2
3/**
4 * adminlib.php - Contains functions that only administrators will ever need to use
5 *
a4e10845 6 * @author Martin Dougiamas and many others
88a7228a 7 * @version $Id$
8 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
9 * @package moodlecore
10 */
11
12/**
ead29342 13 * Upgrade plugins
88a7228a 14 *
15 * @uses $db
16 * @uses $CFG
ead29342 17 * @param string $type The type of plugins that should be updated (e.g. 'enrol', 'qtype')
18 * @param string $dir The directory where the plugins are located (e.g. 'question/questiontypes')
19 * @param string $return The url to prompt the user to continue to
eef868d1 20 */
ead29342 21function upgrade_plugins($type, $dir, $return) {
e69ef14b 22 global $CFG, $db;
173cc1c3 23
ead29342 24 if (!$plugs = get_list_of_plugins($dir) ) {
25 error('No '.$type.' plugins installed!');
173cc1c3 26 }
27
583fad99 28 $updated_plugins = false;
29 $strpluginsetup = get_string('pluginsetup');
30
ead29342 31 foreach ($plugs as $plug) {
173cc1c3 32
ead29342 33 $fullplug = $CFG->dirroot .'/'.$dir.'/'. $plug;
173cc1c3 34
ead29342 35 unset($plugin);
173cc1c3 36
bbbf2d40 37 if (is_readable($fullplug .'/version.php')) {
ead29342 38 include_once($fullplug .'/version.php'); // defines $plugin with version etc
173cc1c3 39 } else {
40 continue; // Nothing to do.
41 }
42
e79a09a2 43 $oldupgrade = false;
44 $newupgrade = false;
7c006e34 45 if (is_readable($fullplug . '/db/'. $CFG->dbtype . '.php')) {
46 include_once($fullplug . '/db/'. $CFG->dbtype . '.php'); // defines old upgrading function
e79a09a2 47 $oldupgrade = true;
48 }
db8bd7a6 49 if (is_readable($fullplug . '/db/upgrade.php')) {
7c006e34 50 include_once($fullplug . '/db/upgrade.php'); // defines new upgrading function
e79a09a2 51 $newupgrade = true;
52 }
53
ead29342 54 if (!isset($plugin)) {
173cc1c3 55 continue;
56 }
57
ead29342 58 if (!empty($plugin->requires)) {
59 if ($plugin->requires > $CFG->version) {
acdd790f 60 $info = new object();
ead29342 61 $info->pluginname = $plug;
62 $info->pluginversion = $plugin->version;
173cc1c3 63 $info->currentmoodle = $CFG->version;
ead29342 64 $info->requiremoodle = $plugin->requires;
583fad99 65 if (!$updated_plugins) {
eef868d1 66 print_header($strpluginsetup, $strpluginsetup, $strpluginsetup, '',
583fad99 67 '<script type="text/javascript" src="' . $CFG->wwwroot . '/lib/scroll_to_errors.js"></script>',
68 false, '&nbsp;', '&nbsp;');
69 }
70 upgrade_log_start();
ead29342 71 notify(get_string('pluginrequirementsnotmet', 'error', $info));
583fad99 72 $updated_plugins = true;
173cc1c3 73 continue;
74 }
75 }
76
ead29342 77 $plugin->name = $plug; // The name MUST match the directory
173cc1c3 78
ead29342 79 $pluginversion = $type.'_'.$plug.'_version';
173cc1c3 80
ead29342 81 if (!isset($CFG->$pluginversion)) {
82 set_config($pluginversion, 0);
173cc1c3 83 }
eef868d1 84
ead29342 85 if ($CFG->$pluginversion == $plugin->version) {
173cc1c3 86 // do nothing
ead29342 87 } else if ($CFG->$pluginversion < $plugin->version) {
583fad99 88 if (!$updated_plugins) {
eef868d1 89 print_header($strpluginsetup, $strpluginsetup, $strpluginsetup, '',
a36f058e 90 '<script type="text/javascript" src="' . $CFG->wwwroot . '/lib/scroll_to_errors.js"></script>',
91 false, '&nbsp;', '&nbsp;');
173cc1c3 92 }
e79a09a2 93 $updated_plugins = true;
583fad99 94 upgrade_log_start();
ead29342 95 print_heading($plugin->name .' plugin needs upgrading');
e79a09a2 96 $db->debug = true;
97 @set_time_limit(0); // To allow slow databases to complete the long SQL
98
d87a9d73 99 if ($CFG->$pluginversion == 0) { // It's a new install of this plugin
e79a09a2 100 /// Both old .sql files and new install.xml are supported
101 /// but we priorize install.xml (XMLDB) if present
102 $status = false;
db8bd7a6 103 if (file_exists($fullplug . '/db/install.xml')) {
450cf307 104 $status = install_from_xmldb_file($fullplug . '/db/install.xml'); //New method
e79a09a2 105 } else if (file_exists($fullplug .'/db/'. $CFG->dbtype .'.sql')) {
106 $status = modify_database($fullplug .'/db/'. $CFG->dbtype .'.sql'); //Old method
eef868d1 107 } else {
7c006e34 108 $status = true;
d87a9d73 109 }
e79a09a2 110
111 $db->debug = false;
eef868d1 112 /// Continue with the instalation, roles and other stuff
e79a09a2 113 if ($status) {
114 // OK so far, now update the plugins record
115 set_config($pluginversion, $plugin->version);
ae628043 116 if (!update_capabilities($type.'/'.$plug)) {
e79a09a2 117 error('Could not set up the capabilities for '.$module->name.'!');
118 }
119 notify(get_string('modulesuccess', '', $plugin->name), 'notifysuccess');
120 } else {
121 notify('Installing '. $plugin->name .' FAILED!');
122 }
d87a9d73 123 } else { // Upgrade existing install
e79a09a2 124 /// Run de old and new upgrade functions for the module
125 $oldupgrade_function = $type.'_'.$plugin->name .'_upgrade';
126 $newupgrade_function = 'xmldb_' . $type.'_'.$plugin->name .'_upgrade';
127
128 /// First, the old function if exists
129 $oldupgrade_status = true;
130 if ($oldupgrade && function_exists($oldupgrade_function)) {
131 $db->debug = true;
132 $oldupgrade_status = $oldupgrade_function($CFG->$pluginversion);
133 } else if ($oldupgrade) {
134 notify ('Upgrade function ' . $oldupgrade_function . ' was not available in ' .
135 $fullplug . '/db/' . $CFG->dbtype . '.php');
136 }
137
138 /// Then, the new function if exists and the old one was ok
139 $newupgrade_status = true;
140 if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) {
141 $db->debug = true;
142 $newupgrade_status = $newupgrade_function($CFG->$pluginversion);
143 } else if ($newupgrade) {
144 notify ('Upgrade function ' . $newupgrade_function . ' was not available in ' .
145 $fullplug . '/db/upgrade.php');
146 }
147
148 $db->debug=false;
149 /// Now analyze upgrade results
150 if ($oldupgrade_status && $newupgrade_status) { // No upgrading failed
151 // OK so far, now update the plugins record
152 set_config($pluginversion, $plugin->version);
ae628043 153 if (!update_capabilities($type.'/'.$plug)) {
e79a09a2 154 error('Could not update '.$plugin->name.' capabilities!');
d87a9d73 155 }
e79a09a2 156 notify(get_string('modulesuccess', '', $plugin->name), 'notifysuccess');
157 } else {
158 notify('Upgrading '. $plugin->name .' from '. $CFG->$pluginversion .' to '. $plugin->version .' FAILED!');
173cc1c3 159 }
160 }
d87a9d73 161 echo '<hr />';
173cc1c3 162 } else {
583fad99 163 upgrade_log_start();
ead29342 164 error('Version mismatch: '. $plugin->name .' can\'t downgrade '. $CFG->$pluginversion .' -> '. $plugin->version .' !');
173cc1c3 165 }
166 }
167
583fad99 168 upgrade_log_finish();
169
170 if ($updated_plugins) {
173cc1c3 171 print_continue($return);
acdd790f 172 print_footer('none');
173cc1c3 173 die;
174 }
175}
176
88a7228a 177/**
178 * Find and check all modules and load them up or upgrade them if necessary
179 *
180 * @uses $db
181 * @uses $CFG
182 * @param string $return The url to prompt the user to continue to
183 * @todo Finish documenting this function
eef868d1 184 */
173cc1c3 185function upgrade_activity_modules($return) {
173cc1c3 186
e69ef14b 187 global $CFG, $db;
173cc1c3 188
88a7228a 189 if (!$mods = get_list_of_plugins('mod') ) {
190 error('No modules installed!');
173cc1c3 191 }
192
583fad99 193 $updated_modules = false;
194 $strmodulesetup = get_string('modulesetup');
195
173cc1c3 196 foreach ($mods as $mod) {
197
88a7228a 198 if ($mod == 'NEWMODULE') { // Someone has unzipped the template, ignore it
173cc1c3 199 continue;
200 }
201
88a7228a 202 $fullmod = $CFG->dirroot .'/mod/'. $mod;
173cc1c3 203
204 unset($module);
205
88a7228a 206 if ( is_readable($fullmod .'/version.php')) {
207 include_once($fullmod .'/version.php'); // defines $module with version etc
173cc1c3 208 } else {
88a7228a 209 notify('Module '. $mod .': '. $fullmod .'/version.php was not readable');
173cc1c3 210 continue;
211 }
212
d6eb06b6 213 $oldupgrade = false;
214 $newupgrade = false;
7c006e34 215 if ( is_readable($fullmod .'/db/' . $CFG->dbtype . '.php')) {
216 include_once($fullmod .'/db/' . $CFG->dbtype . '.php'); // defines old upgrading function
d6eb06b6 217 $oldupgrade = true;
218 }
db8bd7a6 219 if ( is_readable($fullmod . '/db/upgrade.php')) {
7c006e34 220 include_once($fullmod . '/db/upgrade.php'); // defines new upgrading function
d6eb06b6 221 $newupgrade = true;
173cc1c3 222 }
223
224 if (!isset($module)) {
225 continue;
226 }
227
228 if (!empty($module->requires)) {
229 if ($module->requires > $CFG->version) {
acdd790f 230 $info = new object();
173cc1c3 231 $info->modulename = $mod;
232 $info->moduleversion = $module->version;
233 $info->currentmoodle = $CFG->version;
234 $info->requiremoodle = $module->requires;
583fad99 235 if (!$updated_modules) {
eef868d1 236 print_header($strmodulesetup, $strmodulesetup, $strmodulesetup, '',
583fad99 237 '<script type="text/javascript" src="' . $CFG->wwwroot . '/lib/scroll_to_errors.js"></script>',
238 false, '&nbsp;', '&nbsp;');
239 }
240 upgrade_log_start();
173cc1c3 241 notify(get_string('modulerequirementsnotmet', 'error', $info));
583fad99 242 $updated_modules = true;
173cc1c3 243 continue;
244 }
245 }
246
247 $module->name = $mod; // The name MUST match the directory
eef868d1 248
88a7228a 249 if ($currmodule = get_record('modules', 'name', $module->name)) {
173cc1c3 250 if ($currmodule->version == $module->version) {
251 // do nothing
252 } else if ($currmodule->version < $module->version) {
d6eb06b6 253 /// If versions say that we need to upgrade but no upgrade files are available, notify and continue
254 if (!$oldupgrade && !$newupgrade) {
255 notify('Upgrade files ' . $mod . ': ' . $fullmod . '/db/' . $CFG->dbtype . '.php or ' .
256 $fullmod . '/db/upgrade.php were not readable');
257 continue;
258 }
583fad99 259 if (!$updated_modules) {
eef868d1 260 print_header($strmodulesetup, $strmodulesetup, $strmodulesetup, '',
a36f058e 261 '<script type="text/javascript" src="' . $CFG->wwwroot . '/lib/scroll_to_errors.js"></script>',
262 false, '&nbsp;', '&nbsp;');
173cc1c3 263 }
583fad99 264 upgrade_log_start();
88a7228a 265 print_heading($module->name .' module needs upgrading');
d6eb06b6 266
267 /// Run de old and new upgrade functions for the module
268 $oldupgrade_function = $module->name . '_upgrade';
269 $newupgrade_function = 'xmldb_' . $module->name . '_upgrade';
270
271 /// First, the old function if exists
272 $oldupgrade_status = true;
273 if ($oldupgrade && function_exists($oldupgrade_function)) {
274 $db->debug = true;
275 $oldupgrade_status = $oldupgrade_function($currmodule->version, $module);
ba05965e 276 } else if ($oldupgrade) {
d6eb06b6 277 notify ('Upgrade function ' . $oldupgrade_function . ' was not available in ' .
278 $mod . ': ' . $fullmod . '/db/' . $CFG->dbtype . '.php');
d6eb06b6 279 }
280
281 /// Then, the new function if exists and the old one was ok
282 $newupgrade_status = true;
ba05965e 283 if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) {
d6eb06b6 284 $db->debug = true;
285 $newupgrade_status = $newupgrade_function($currmodule->version, $module);
ba05965e 286 } else if ($newupgrade) {
d6eb06b6 287 notify ('Upgrade function ' . $newupgrade_function . ' was not available in ' .
288 $mod . ': ' . $fullmod . '/db/upgrade.php');
d6eb06b6 289 }
290
e79a09a2 291 $db->debug=false;
d6eb06b6 292 /// Now analyze upgrade results
668896e5 293 if ($oldupgrade_status && $newupgrade_status) { // No upgrading failed
d6eb06b6 294 // OK so far, now update the modules record
295 $module->id = $currmodule->id;
296 if (! update_record('modules', $module)) {
297 error('Could not update '. $module->name .' record in modules table!');
173cc1c3 298 }
d6eb06b6 299 remove_dir($CFG->dataroot . '/cache', true); // flush cache
300 notify(get_string('modulesuccess', '', $module->name), 'notifysuccess');
301 echo '<hr />';
302 } else {
d6eb06b6 303 notify('Upgrading '. $module->name .' from '. $currmodule->version .' to '. $module->version .' FAILED!');
173cc1c3 304 }
bbbf2d40 305
d6eb06b6 306 /// Update the capabilities table?
bbbf2d40 307 if (!update_capabilities('mod/'.$module->name)) {
308 error('Could not update '.$module->name.' capabilities!');
309 }
310
173cc1c3 311 $updated_modules = true;
eef868d1 312
173cc1c3 313 } else {
583fad99 314 upgrade_log_start();
88a7228a 315 error('Version mismatch: '. $module->name .' can\'t downgrade '. $currmodule->version .' -> '. $module->version .' !');
173cc1c3 316 }
eef868d1 317
173cc1c3 318 } else { // module not installed yet, so install it
583fad99 319 if (!$updated_modules) {
eef868d1 320 print_header($strmodulesetup, $strmodulesetup, $strmodulesetup, '',
a36f058e 321 '<script type="text/javascript" src="' . $CFG->wwwroot . '/lib/scroll_to_errors.js"></script>',
322 false, '&nbsp;', '&nbsp;');
173cc1c3 323 }
583fad99 324 upgrade_log_start();
173cc1c3 325 print_heading($module->name);
326 $updated_modules = true;
327 $db->debug = true;
328 @set_time_limit(0); // To allow slow databases to complete the long SQL
d6eb06b6 329
330 /// Both old .sql files and new install.xml are supported
331 /// but we priorize install.xml (XMLDB) if present
db8bd7a6 332 if (file_exists($fullmod . '/db/install.xml')) {
d6eb06b6 333 $status = install_from_xmldb_file($fullmod . '/db/install.xml'); //New method
334 } else {
335 $status = modify_database($fullmod .'/db/'. $CFG->dbtype .'.sql'); //Old method
336 }
337
e79a09a2 338 $db->debug = false;
d6eb06b6 339 /// Continue with the instalation, roles and other stuff
340 if ($status) {
88a7228a 341 if ($module->id = insert_record('modules', $module)) {
bbbf2d40 342 if (!update_capabilities('mod/'.$module->name)) {
343 error('Could not set up the capabilities for '.$module->name.'!');
344 }
a8f68426 345 notify(get_string('modulesuccess', '', $module->name), 'notifysuccess');
88a7228a 346 echo '<hr />';
173cc1c3 347 } else {
88a7228a 348 error($module->name .' module could not be added to the module list!');
173cc1c3 349 }
eef868d1 350 } else {
88a7228a 351 error($module->name .' tables could NOT be set up successfully!');
173cc1c3 352 }
353 }
e5bd4e58 354
355 /// Check submodules of this module if necessary
356
357 include_once($fullmod.'/lib.php'); // defines upgrading function
358
359 $submoduleupgrade = $module->name.'_upgrade_submodules';
360 if (function_exists($submoduleupgrade)) {
361 $submoduleupgrade();
362 }
363
364
365 /// Run any defaults or final code that is necessary for this module
366
a5c0990e 367 if ( is_readable($fullmod .'/defaults.php')) {
368 // Insert default values for any important configuration variables
9e6e7502 369 unset($defaults);
eef868d1 370 include_once($fullmod .'/defaults.php');
f9a2e515 371 if (!empty($defaults)) {
372 foreach ($defaults as $name => $value) {
373 if (!isset($CFG->$name)) {
374 set_config($name, $value);
375 }
a5c0990e 376 }
377 }
378 }
173cc1c3 379 }
380
583fad99 381 upgrade_log_finish(); // finish logging if started
382
383 if ($updated_modules) {
173cc1c3 384 print_continue($return);
acdd790f 385 print_footer('none');
173cc1c3 386 die;
387 }
388}
389
eef868d1 390/**
f3221af9 391 * This function will return FALSE if the lock fails to be set (ie, if it's already locked)
80be7ee3 392 *
393 * @param string $name ?
394 * @param bool $value ?
395 * @param int $staleafter ?
396 * @param bool $clobberstale ?
397 * @todo Finish documenting this function
f3221af9 398 */
399function set_cron_lock($name,$value=true,$staleafter=7200,$clobberstale=false) {
400
401 if (empty($name)) {
402 mtrace("Tried to get a cron lock for a null fieldname");
403 return false;
404 }
405
406 if (empty($value)) {
407 set_config($name,0);
408 return true;
409 }
410
411 if ($config = get_record('config','name',$name)) {
412 if (empty($config->value)) {
413 set_config($name,time());
414 } else {
415 // check for stale.
416 if ((time() - $staleafter) > $config->value) {
417 mtrace("STALE LOCKFILE FOR $name - was $config->value");
418 if (!empty($clobberstale)) {
419 set_config($name,time());
420 return true;
421 }
422 } else {
423 return false; // was not stale - ie, we're ok to still be running.
424 }
425 }
426 }
427 else {
428 set_config($name,time());
429 }
430 return true;
431}
a597f8a8 432
fb06b255 433function print_progress($done, $total, $updatetime=5, $sleeptime=1, $donetext='') {
a597f8a8 434 static $starttime;
435 static $lasttime;
436
26ea4888 437 if ($total < 2) { // No need to show anything
438 return;
439 }
440
a597f8a8 441 if (empty($starttime)) {
442 $starttime = $lasttime = time();
443 $lasttime = $starttime - $updatetime;
444 echo '<table width="500" cellpadding="0" cellspacing="0" align="center"><tr><td width="500">';
72da5046 445 echo '<div id="bar'.$total.'" style="border-style:solid;border-width:1px;width:500px;height:50px;">';
446 echo '<div id="slider'.$total.'" style="border-style:solid;border-width:1px;height:48px;width:10px;background-color:green;"></div>';
a597f8a8 447 echo '</div>';
72da5046 448 echo '<div id="text'.$total.'" align="center" style="width:500px;"></div>';
a597f8a8 449 echo '</td></tr></table>';
450 echo '</div>';
451 }
452
a597f8a8 453 $now = time();
454
455 if ($done && (($now - $lasttime) >= $updatetime)) {
456 $elapsedtime = $now - $starttime;
457 $projectedtime = (int)(((float)$total / (float)$done) * $elapsedtime) - $elapsedtime;
458 $percentage = format_float((float)$done / (float)$total, 2);
459 $width = (int)(500 * $percentage);
460
fb06b255 461 if ($projectedtime > 10) {
462 $projectedtext = ' Ending: '.format_time($projectedtime);
463 } else {
464 $projectedtext = '';
465 }
466
a597f8a8 467 echo '<script>';
aae37b63 468 echo 'document.getElementById("text'.$total.'").innerHTML = "'.addslashes($donetext).' ('.$done.'/'.$total.') '.$projectedtext.'";'."\n";
469 echo 'document.getElementById("slider'.$total.'").style.width = \''.$width.'px\';'."\n";
a597f8a8 470 echo '</script>';
471
472 $lasttime = $now;
473 sleep($sleeptime);
474 }
475}
583fad99 476
477////////////////////////////////////////////////
478/// upgrade logging functions
479////////////////////////////////////////////////
480
481$upgradeloghandle = false;
26c91c73 482$upgradelogbuffer = '';
483// I did not find out how to use static variable in callback function,
484// the problem was that I could not flush the static buffer :-(
485global $upgradeloghandle, $upgradelogbuffer;
583fad99 486
487/**
488 * Check if upgrade is already running.
489 *
490 * If anything goes wrong due to missing call to upgrade_log_finish()
491 * just restart the browser.
492 *
493 * @param string warning message indicating upgrade is already running
494 * @param int page reload timeout
495 */
496function upgrade_check_running($message, $timeout) {
497 if (!empty($_SESSION['upgraderunning'])) {
498 print_header();
499 redirect(me(), $message, $timeout);
500 }
501}
502
503/**
504 * Start logging of output into file (if not disabled) and
505 * prevent aborting and concurrent execution of upgrade script.
506 *
507 * Please note that you can not write into session variables after calling this function!
508 *
509 * This function may be called repeatedly.
510 */
511function upgrade_log_start() {
426a369b 512 global $CFG, $upgradeloghandle;
583fad99 513
514 if (!empty($_SESSION['upgraderunning'])) {
515 return; // logging already started
516 }
517
518 @ignore_user_abort(true); // ignore if user stops or otherwise aborts page loading
519 $_SESSION['upgraderunning'] = 1; // set upgrade indicator
426a369b 520 if (empty($CFG->dbsessions)) { // workaround for bug in adodb, db session can not be restarted
521 session_write_close(); // from now on user can reload page - will be displayed warning
522 }
583fad99 523 make_upload_directory('upgradelogs');
524 ob_start('upgrade_log_callback', 2); // function for logging to disk; flush each line of text ASAP
dedb2304 525 register_shutdown_function('upgrade_log_finish'); // in case somebody forgets to stop logging
583fad99 526}
527
528/**
529 * Terminate logging of output, flush all data, allow script aborting
530 * and reopen session for writing. Function error() does terminate the logging too.
531 *
532 * Please make sure that each upgrade_log_start() is properly terminated by
533 * this function or error().
534 *
535 * This function may be called repeatedly.
536 */
537function upgrade_log_finish() {
426a369b 538 global $CFG, $upgradeloghandle, $upgradelogbuffer;
583fad99 539
540 if (empty($_SESSION['upgraderunning'])) {
541 return; // logging already terminated
542 }
543
544 @ob_end_flush();
26c91c73 545 if ($upgradelogbuffer !== '') {
546 @fwrite($upgradeloghandle, $upgradelogbuffer);
40896537 547 $upgradelogbuffer = '';
26c91c73 548 }
549 if ($upgradeloghandle and ($upgradeloghandle !== 'error')) {
550 @fclose($upgradeloghandle);
40896537 551 $upgradeloghandle = false;
26c91c73 552 }
426a369b 553 if (empty($CFG->dbsessions)) {
554 @session_start(); // ignore header errors, we only need to reopen session
555 }
583fad99 556 $_SESSION['upgraderunning'] = 0; // clear upgrade indicator
557 if (connection_aborted()) {
558 die;
559 }
560 @ignore_user_abort(false);
561}
562
563/**
564 * Callback function for logging into files. Not more than one file is created per minute,
565 * upgrade session (terminated by upgrade_log_finish()) is always stored in one file.
566 *
567 * This function must not output any characters or throw warnigns and errors!
568 */
569function upgrade_log_callback($string) {
26c91c73 570 global $CFG, $upgradeloghandle, $upgradelogbuffer;
583fad99 571
572 if (empty($CFG->disableupgradelogging) and ($string != '') and ($upgradeloghandle !== 'error')) {
573 if ($upgradeloghandle or ($upgradeloghandle = @fopen($CFG->dataroot.'/upgradelogs/upg_'.date('Ymd-Hi').'.html', 'a'))) {
26c91c73 574 $upgradelogbuffer .= $string;
575 if (strlen($upgradelogbuffer) > 2048) { // 2kB write buffer
576 @fwrite($upgradeloghandle, $upgradelogbuffer);
577 $upgradelogbuffer = '';
578 }
583fad99 579 } else {
580 $upgradeloghandle = 'error';
581 }
582 }
583 return $string;
584}
585
57e35f32 586/**
587 * Try to verify that dataroot is not accessible from web.
588 * It is not 100% correct but might help to reduce number of vulnerable sites.
589 *
590 * Protection from httpd.conf and .htaccess is not detected properly.
591 */
592function is_dataroot_insecure() {
593 global $CFG;
594
595 $siteroot = str_replace('\\', '/', strrev($CFG->dirroot.'/')); // win32 backslash workaround
596
597 $rp = preg_replace('|https?://[^/]+|i', '', $CFG->wwwroot, 1);
598 $rp = strrev(trim($rp, '/'));
599 $rp = explode('/', $rp);
600 foreach($rp as $r) {
601 if (strpos($siteroot, '/'.$r.'/') === 0) {
602 $siteroot = substr($siteroot, strlen($r)+1); // moodle web in subdirectory
603 } else {
604 break; // probably alias root
605 }
606 }
607
608 $siteroot = strrev($siteroot);
609 $dataroot = str_replace('\\', '/', $CFG->dataroot.'/');
610
611 if (strpos($dataroot, $siteroot) === 0) {
612 return true;
613 }
614 return false;
615}
6e4dc10f 616
617/// =============================================================================================================
618/// administration tree classes and functions
619
620
621// n.b. documentation is still in progress for this code
622
623/// INTRODUCTION
624
625/// This file performs the following tasks:
626/// -it defines the necessary objects and interfaces to build the Moodle
627/// admin hierarchy
eef868d1 628/// -it defines the admin_externalpage_setup(), admin_externalpage_print_header(),
6e4dc10f 629/// and admin_externalpage_print_footer() functions used on admin pages
630
631/// ADMIN_SETTING OBJECTS
632
eef868d1 633/// Moodle settings are represented by objects that inherit from the admin_setting
6e4dc10f 634/// class. These objects encapsulate how to read a setting, how to write a new value
635/// to a setting, and how to appropriately display the HTML to modify the setting.
636
637/// ADMIN_SETTINGPAGE OBJECTS
638
639/// The admin_setting objects are then grouped into admin_settingpages. The latter
640/// appear in the Moodle admin tree block. All interaction with admin_settingpage
641/// objects is handled by the admin/settings.php file.
642
643/// ADMIN_EXTERNALPAGE OBJECTS
644
645/// There are some settings in Moodle that are too complex to (efficiently) handle
646/// with admin_settingpages. (Consider, for example, user management and displaying
647/// lists of users.) In this case, we use the admin_externalpage object. This object
648/// places a link to an external PHP file in the admin tree block.
649
650/// If you're using an admin_externalpage object for some settings, you can take
651/// advantage of the admin_externalpage_* functions. For example, suppose you wanted
652/// to add a foo.php file into admin. First off, you add the following line to
653/// admin/settings/first.php (at the end of the file) or to some other file in
654/// admin/settings:
655
eef868d1 656/// $ADMIN->add('userinterface', new admin_externalpage('foo', get_string('foo'),
6e4dc10f 657/// $CFG->wwwdir . '/' . '$CFG->admin . '/foo.php', 'some_role_permission'));
658
659/// Next, in foo.php, your file structure would resemble the following:
660
661/// require_once('.../config.php');
662/// require_once($CFG->libdir.'/adminlib.php');
663/// $adminroot = admin_get_root();
664/// admin_externalpage_setup('foo', $adminroot);
665/// // functionality like processing form submissions goes here
666/// admin_externalpage_print_header($adminroot);
667/// // your HTML goes here
668/// admin_externalpage_print_footer($adminroot);
669
670/// The admin_externalpage_setup() function call ensures the user is logged in,
671/// and makes sure that they have the proper role permission to access the page.
672
673/// The admin_externalpage_print_header() function prints the header (it figures
674/// out what category and subcategories the page is classified under) and ensures
675/// that you're using the admin pagelib (which provides the admin tree block and
676/// the admin bookmarks block).
677
678/// The admin_externalpage_print_footer() function properly closes the tables
679/// opened up by the admin_externalpage_print_header() function and prints the
680/// standard Moodle footer.
681
682/// ADMIN_CATEGORY OBJECTS
683
684/// Above and beyond all this, we have admin_category objects. These objects
685/// appear as folders in the admin tree block. They contain admin_settingpage's,
686/// admin_externalpage's, and other admin_category's.
687
688/// OTHER NOTES
689
690/// admin_settingpage's, admin_externalpage's, and admin_category's all inherit
691/// from part_of_admin_tree (a pseudointerface). This interface insists that
692/// a class has a check_access method for access permissions, a locate method
693/// used to find a specific node in the admin tree, and a path method used
694/// to determine the path to a specific node in the $ADMIN tree.
695
696/// admin_category's inherit from parentable_part_of_admin_tree. This pseudo-
697/// interface ensures that the class implements a recursive add function which
698/// accepts a part_of_admin_tree object and searches for the proper place to
699/// put it. parentable_part_of_admin_tree implies part_of_admin_tree.
700
701/// Please note that the $this->name field of any part_of_admin_tree must be
702/// UNIQUE throughout the ENTIRE admin tree.
703
704/// The $this->name field of an admin_setting object (which is *not* part_of_
705/// admin_tree) must be unique on the respective admin_settingpage where it is
706/// used.
707
708
709/// MISCELLANEOUS STUFF (used by classes defined below) ///////////////////////
710include_once($CFG->dirroot . '/backup/lib.php');
711
712/// CLASS DEFINITIONS /////////////////////////////////////////////////////////
713
714/**
715 * Pseudointerface for anything appearing in the admin tree
716 *
717 * The pseudointerface that is implemented by anything that appears in the admin tree
718 * block. It forces inheriting classes to define a method for checking user permissions
719 * and methods for finding something in the admin tree.
720 *
721 * @author Vincenzo K. Marcovecchio
722 * @package admin
723 */
724class part_of_admin_tree {
725
726 /**
727 * Finds a named part_of_admin_tree.
728 *
729 * Used to find a part_of_admin_tree. If a class only inherits part_of_admin_tree
730 * and not parentable_part_of_admin_tree, then this function should only check if
731 * $this->name matches $name. If it does, it should return a reference to $this,
732 * otherwise, it should return a reference to NULL.
733 *
734 * If a class inherits parentable_part_of_admin_tree, this method should be called
735 * recursively on all child objects (assuming, of course, the parent object's name
736 * doesn't match the search criterion).
737 *
738 * @param string $name The internal name of the part_of_admin_tree we're searching for.
739 * @return mixed An object reference or a NULL reference.
740 */
eef868d1 741 function &locate($name) {
742 trigger_error('Admin class does not implement method <strong>locate()</strong>', E_USER_WARNING);
743 return;
6e4dc10f 744 }
4672d955 745
746 /**
747 * Removes named part_of_admin_tree.
748 *
749 * @param string $name The internal name of the part_of_admin_tree we want to remove.
a8a66c96 750 * @return bool success.
4672d955 751 */
752 function prune($name) {
eef868d1 753 trigger_error('Admin class does not implement method <strong>prune()</strong>', E_USER_WARNING);
4672d955 754 return;
eef868d1 755 }
4672d955 756
6e4dc10f 757 /**
758 * Verifies current user's access to this part_of_admin_tree.
759 *
760 * Used to check if the current user has access to this part of the admin tree or
761 * not. If a class only inherits part_of_admin_tree and not parentable_part_of_admin_tree,
762 * then this method is usually just a call to has_capability() in the site context.
763 *
764 * If a class inherits parentable_part_of_admin_tree, this method should return the
765 * logical OR of the return of check_access() on all child objects.
766 *
767 * @return bool True if the user has access, false if she doesn't.
768 */
eef868d1 769 function check_access() {
770 trigger_error('Admin class does not implement method <strong>check_access()</strong>', E_USER_WARNING);
771 return;
6e4dc10f 772 }
eef868d1 773
a8a66c96 774 /**
775 * Mostly usefull for removing of some parts of the tree in admin tree block.
776 *
777 * @return True is hidden from normal list view
778 */
779 function is_hidden() {
780 trigger_error('Admin class does not implement method <strong>is_hidden()</strong>', E_USER_WARNING);
781 return;
782 }
783
6e4dc10f 784 /**
785 * Determines the path to $name in the admin tree.
786 *
787 * Used to determine the path to $name in the admin tree. If a class inherits only
788 * part_of_admin_tree and not parentable_part_of_admin_tree, then this method should
789 * check if $this->name matches $name. If it does, $name is pushed onto the $path
790 * array (at the end), and $path should be returned. If it doesn't, NULL should be
791 * returned.
792 *
793 * If a class inherits parentable_part_of_admin_tree, it should do the above, but not
794 * return NULL on failure. Instead, it pushes $this->name onto $path, and then
795 * recursively calls path() on its child objects. If any are non-NULL, it should
796 * return $path (being certain that the last element of $path is equal to $name).
797 * If they are all NULL, it returns NULL.
798 *
799 * @param string $name The internal name of the part_of_admin_tree we're searching for.
800 * @param array $path Not used on external calls. Defaults to empty array.
801 * @return mixed If found, an array containing the internal names of each part_of_admin_tree that leads to $name. If not found, NULL.
802 */
eef868d1 803 function path($name, $path = array()) {
804 trigger_error('Admin class does not implement method <strong>path()</strong>', E_USER_WARNING);
805 return;
6e4dc10f 806 }
807}
808
809/**
810 * Pseudointerface implemented by any part_of_admin_tree that has children.
811 *
812 * The pseudointerface implemented by any part_of_admin_tree that can be a parent
813 * to other part_of_admin_tree's. (For now, this only includes admin_category.) Apart
eef868d1 814 * from ensuring part_of_admin_tree compliancy, it also ensures inheriting methods
6e4dc10f 815 * include an add method for adding other part_of_admin_tree objects as children.
816 *
817 * @author Vincenzo K. Marcovecchio
818 * @package admin
819 */
820class parentable_part_of_admin_tree extends part_of_admin_tree {
eef868d1 821
6e4dc10f 822 /**
823 * Adds a part_of_admin_tree object to the admin tree.
824 *
825 * Used to add a part_of_admin_tree object to this object or a child of this
826 * object. $something should only be added if $destinationname matches
827 * $this->name. If it doesn't, add should be called on child objects that are
828 * also parentable_part_of_admin_tree's.
829 *
830 * @param string $destinationname The internal name of the new parent for $something.
831 * @param part_of_admin_tree &$something The object to be added.
832 * @return bool True on success, false on failure.
833 */
eef868d1 834 function add($destinationname, &$something) {
835 trigger_error('Admin class does not implement method <strong>add()</strong>', E_USER_WARNING);
836 return;
6e4dc10f 837 }
eef868d1 838
6e4dc10f 839}
840
841/**
842 * The object used to represent folders (a.k.a. categories) in the admin tree block.
eef868d1 843 *
6e4dc10f 844 * Each admin_category object contains a number of part_of_admin_tree objects.
845 *
846 * @author Vincenzo K. Marcovecchio
847 * @package admin
848 */
849class admin_category extends parentable_part_of_admin_tree {
850
851 /**
852 * @var mixed An array of part_of_admin_tree objects that are this object's children
853 */
854 var $children;
eef868d1 855
6e4dc10f 856 /**
857 * @var string An internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
858 */
859 var $name;
eef868d1 860
6e4dc10f 861 /**
862 * @var string The displayed name for this category. Usually obtained through get_string()
863 */
864 var $visiblename;
eef868d1 865
a8a66c96 866 /**
867 * @var bool Should this category be hidden in admin tree block?
868 */
869 var $hidden;
870
6e4dc10f 871 // constructor for an empty admin category
872 // $name is the internal name of the category. it MUST be unique in the entire hierarchy
873 // $visiblename is the displayed name of the category. use a get_string for this
874
875 /**
876 * Constructor for an empty admin category
877 *
878 * @param string $name The internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
879 * @param string $visiblename The displayed named for this category. Usually obtained through get_string()
a8a66c96 880 * @param bool $hidden hide category in admin tree block
6e4dc10f 881 * @return mixed Returns the new object.
882 */
a8a66c96 883 function admin_category($name, $visiblename, $hidden = false) {
6e4dc10f 884 $this->children = array();
885 $this->name = $name;
886 $this->visiblename = $visiblename;
a8a66c96 887 $this->hidden = $hidden;
6e4dc10f 888 }
eef868d1 889
6e4dc10f 890 /**
891 * Finds the path to the part_of_admin_tree called $name.
892 *
893 * @param string $name The internal name that we're searching for.
894 * @param array $path Used internally for recursive calls. Do not specify on external calls. Defaults to array().
895 * @return mixed An array of internal names that leads to $name, or NULL if not found.
896 */
897 function path($name, $path = array()) {
eef868d1 898
6e4dc10f 899 $path[count($path)] = $this->name;
eef868d1 900
6e4dc10f 901 if ($this->name == $name) {
902 return $path;
903 }
eef868d1 904
6e4dc10f 905 foreach($this->children as $child) {
906 if ($return = $child->path($name, $path)) {
907 return $return;
908 }
909 }
eef868d1 910
6e4dc10f 911 return NULL;
eef868d1 912
6e4dc10f 913 }
914
915 /**
916 * Returns a reference to the part_of_admin_tree object with internal name $name.
917 *
918 * @param string $name The internal name of the object we want.
919 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
920 */
921 function &locate($name) {
eef868d1 922
6e4dc10f 923 if ($this->name == $name) {
924 return $this;
925 }
eef868d1 926
6e4dc10f 927 foreach($this->children as $child) {
928 if ($return =& $child->locate($name)) {
929 return $return;
930 }
931 }
932 $return = NULL;
933 return $return;
934 }
935
4672d955 936 /**
937 * Removes part_of_admin_tree object with internal name $name.
938 *
939 * @param string $name The internal name of the object we want to remove.
a8a66c96 940 * @return bool success
4672d955 941 */
942 function prune($name) {
943
944 if ($this->name == $name) {
945 return false; //can not remove itself
946 }
947
948 foreach($this->children as $precedence => $child) {
949 if ($child->name == $name) {
950 // found it!
eef868d1 951 unset($this->children[$precedence]);
4672d955 952 return true;
953 }
954 if ($this->children[$precedence]->prune($name)) {
955 return true;
956 }
957 }
958 return false;
959 }
960
6e4dc10f 961 /**
962 * Adds a part_of_admin_tree to a child or grandchild (or great-grandchild, and so forth) of this object.
963 *
964 * @param string $destinationame The internal name of the immediate parent that we want for &$something.
965 * @param mixed &$something A part_of_admin_tree object to be added.
966 * @param int $precedence The precedence of &$something when displayed. Smaller numbers mean it'll be displayed higher up in the admin menu. Defaults to '', meaning "next available position".
967 * @return bool True if successfully added, false if &$something is not a part_of_admin_tree or if $name is not found.
968 */
969 function add($destinationname, &$something, $precedence = '') {
eef868d1 970
6e4dc10f 971 if (!is_a($something, 'part_of_admin_tree')) {
972 return false;
973 }
974
975 if ($destinationname == $this->name) {
976 if ($precedence === '') {
977 $this->children[] = $something;
978 } else {
979 if (isset($this->children[$precedence])) { // this should never, ever be triggered in a release version of moodle.
980 echo ('<font style="color: red;">There is a precedence conflict in the category ' . $this->name . '. The object named ' . $something->name . ' is overwriting the object named ' . $this->children[$precedence]->name . '.</font><br />');
981 }
982 $this->children[$precedence] = $something;
983 }
984 return true;
985 }
eef868d1 986
6e4dc10f 987 unset($entries);
eef868d1 988
6e4dc10f 989 $entries = array_keys($this->children);
eef868d1 990
6e4dc10f 991 foreach($entries as $entry) {
992 $child =& $this->children[$entry];
993 if (is_a($child, 'parentable_part_of_admin_tree')) {
994 if ($child->add($destinationname, $something, $precedence)) {
995 return true;
996 }
997 }
998 }
eef868d1 999
6e4dc10f 1000 return false;
eef868d1 1001
6e4dc10f 1002 }
eef868d1 1003
6e4dc10f 1004 /**
1005 * Checks if the user has access to anything in this category.
1006 *
1007 * @return bool True if the user has access to atleast one child in this category, false otherwise.
1008 */
1009 function check_access() {
eef868d1 1010
6e4dc10f 1011 $return = false;
1012 foreach ($this->children as $child) {
1013 $return = $return || $child->check_access();
1014 }
eef868d1 1015
6e4dc10f 1016 return $return;
eef868d1 1017
6e4dc10f 1018 }
eef868d1 1019
a8a66c96 1020 /**
1021 * Is this category hidden in admin tree block?
1022 *
1023 * @return bool True if hidden
1024 */
1025 function is_hidden() {
1026 return $this->hidden;
1027 }
6e4dc10f 1028}
1029
1030/**
1031 * Links external PHP pages into the admin tree.
1032 *
1033 * See detailed usage example at the top of this document (adminlib.php)
1034 *
1035 * @author Vincenzo K. Marcovecchio
1036 * @package admin
1037 */
1038class admin_externalpage extends part_of_admin_tree {
1039
eef868d1 1040 /**
6e4dc10f 1041 * @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects
1042 */
1043 var $name;
eef868d1 1044
6e4dc10f 1045 /**
1046 * @var string The displayed name for this external page. Usually obtained through get_string().
1047 */
1048 var $visiblename;
eef868d1 1049
6e4dc10f 1050 /**
1051 * @var string The external URL that we should link to when someone requests this external page.
1052 */
1053 var $url;
eef868d1 1054
6e4dc10f 1055 /**
1056 * @var string The role capability/permission a user must have to access this external page.
1057 */
2ce38b70 1058 var $req_capability;
eef868d1 1059
a8a66c96 1060 /**
1061 * @var bool hidden in admin tree block.
1062 */
1063 var $hidden;
1064
6e4dc10f 1065 /**
1066 * Constructor for adding an external page into the admin tree.
1067 *
1068 * @param string $name The internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects.
1069 * @param string $visiblename The displayed name for this external page. Usually obtained through get_string().
1070 * @param string $url The external URL that we should link to when someone requests this external page.
38d2d43b 1071 * @param mixed $req_capability The role capability/permission a user must have to access this external page. Defaults to 'moodle/site:config'.
6e4dc10f 1072 */
a8a66c96 1073 function admin_externalpage($name, $visiblename, $url, $req_capability = 'moodle/site:config', $hidden=false) {
6e4dc10f 1074 $this->name = $name;
1075 $this->visiblename = $visiblename;
1076 $this->url = $url;
38d2d43b 1077 if (is_array($req_capability)) {
1078 $this->req_capability = $req_capability;
1079 } else {
1080 $this->req_capability = array($req_capability);
1081 }
a8a66c96 1082 $this->hidden = $hidden;
6e4dc10f 1083 }
eef868d1 1084
6e4dc10f 1085 /**
1086 * Finds the path to the part_of_admin_tree called $name.
1087 *
1088 * @param string $name The internal name that we're searching for.
1089 * @param array $path Used internally for recursive calls. Do not specify on external calls. Defaults to array().
1090 * @return mixed An array of internal names that leads to $name, or NULL if not found.
1091 */
1092 function path($name, $path = array()) {
1093 if ($name == $this->name) {
1094 array_push($path, $this->name);
1095 return $path;
1096 } else {
1097 return NULL;
1098 }
1099 }
eef868d1 1100
6e4dc10f 1101 /**
1102 * Returns a reference to the part_of_admin_tree object with internal name $name.
1103 *
1104 * @param string $name The internal name of the object we want.
1105 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
1106 */
1107 function &locate($name) {
1108 $return = ($this->name == $name ? $this : NULL);
1109 return $return;
1110 }
4672d955 1111
1112 function prune($name) {
1113 return false;
1114 }
1115
6e4dc10f 1116 /**
2ce38b70 1117 * Determines if the current user has access to this external page based on $this->req_capability.
6e4dc10f 1118 *
1119 * @uses CONTEXT_SYSTEM
1120 * @uses SITEID
1121 * @return bool True if user has access, false otherwise.
1122 */
1123 function check_access() {
1124 if (!get_site()) {
1125 return true; // no access check before site is fully set up
1126 }
eef868d1 1127 $context = get_context_instance(CONTEXT_SYSTEM, SITEID);
38d2d43b 1128 foreach($this->req_capability as $cap) {
1129 if (has_capability($cap, $context)) {
1130 return true;
1131 }
1132 }
1133 return false;
6e4dc10f 1134 }
1135
a8a66c96 1136 /**
1137 * Is this external page hidden in admin tree block?
1138 *
1139 * @return bool True if hidden
1140 */
1141 function is_hidden() {
1142 return $this->hidden;
1143 }
1144
6e4dc10f 1145}
1146
1147/**
1148 * Used to group a number of admin_setting objects into a page and add them to the admin tree.
1149 *
1150 * @author Vincenzo K. Marcovecchio
1151 * @package admin
1152 */
1153class admin_settingpage extends part_of_admin_tree {
1154
eef868d1 1155 /**
6e4dc10f 1156 * @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects
1157 */
1158 var $name;
eef868d1 1159
6e4dc10f 1160 /**
1161 * @var string The displayed name for this external page. Usually obtained through get_string().
1162 */
1163 var $visiblename;
1164 /**
1165 * @var mixed An array of admin_setting objects that are part of this setting page.
1166 */
1167 var $settings;
eef868d1 1168
6e4dc10f 1169 /**
1170 * @var string The role capability/permission a user must have to access this external page.
1171 */
2ce38b70 1172 var $req_capability;
eef868d1 1173
a8a66c96 1174 /**
1175 * @var bool hidden in admin tree block.
1176 */
1177 var $hidden;
1178
6e4dc10f 1179 // see admin_category
1180 function path($name, $path = array()) {
1181 if ($name == $this->name) {
1182 array_push($path, $this->name);
1183 return $path;
1184 } else {
1185 return NULL;
1186 }
1187 }
eef868d1 1188
6e4dc10f 1189 // see admin_category
1190 function &locate($name) {
1191 $return = ($this->name == $name ? $this : NULL);
1192 return $return;
1193 }
4672d955 1194
1195 function prune($name) {
1196 return false;
1197 }
1198
6e4dc10f 1199 // see admin_externalpage
a8a66c96 1200 function admin_settingpage($name, $visiblename, $req_capability = 'moodle/site:config', $hidden=false) {
6e4dc10f 1201 global $CFG;
1202 $this->settings = new stdClass();
1203 $this->name = $name;
1204 $this->visiblename = $visiblename;
38d2d43b 1205 if (is_array($req_capability)) {
1206 $this->req_capability = $req_capability;
1207 } else {
1208 $this->req_capability = array($req_capability);
1209 }
a8a66c96 1210 $this->hidden = false;
6e4dc10f 1211 }
eef868d1 1212
6e4dc10f 1213 // 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
1214 // n.b. each admin_setting in an admin_settingpage must have a unique internal name
1215 // &$setting is the admin_setting object you want to add
1216 // returns true if successful, false if not (will fail if &$setting is an admin_setting or child thereof)
1217 function add(&$setting) {
1218 if (is_a($setting, 'admin_setting')) {
1219 $this->settings->{$setting->name} =& $setting;
1220 return true;
1221 }
1222 return false;
1223 }
eef868d1 1224
6e4dc10f 1225 // see admin_externalpage
1226 function check_access() {
1227 if (!get_site()) {
1228 return true; // no access check before site is fully set up
1229 }
eef868d1 1230 $context = get_context_instance(CONTEXT_SYSTEM, SITEID);
38d2d43b 1231 foreach($this->req_capability as $cap) {
1232 if (has_capability($cap, $context)) {
1233 return true;
1234 }
1235 }
1236 return false;
6e4dc10f 1237 }
eef868d1 1238
6e4dc10f 1239 // outputs this page as html in a table (suitable for inclusion in an admin pagetype)
1240 // returns a string of the html
1241 function output_html() {
15a16922 1242 $return = '<fieldset>' . "\n";
6153cf58 1243 $return .= '<div class="clearer"><!-- --></div>' . "\n";
6e4dc10f 1244 foreach($this->settings as $setting) {
15a16922 1245 $return .= $setting->output_html();
6e4dc10f 1246 }
6153cf58 1247 $return .= '</fieldset>';
6e4dc10f 1248 return $return;
1249 }
1250
1251 // writes settings (the ones that have been added to this admin_settingpage) to the database, or wherever else they're supposed to be written to
1252 // -- calls write_setting() to each child setting, sending it only the data that matches each setting's internal name
1253 // $data should be the result from data_submitted()
1254 // returns an empty string if everything went well, otherwise returns a printable error string (that's language-specific)
1255 function write_settings($data) {
1256 $return = '';
1257 foreach($this->settings as $setting) {
1258 if (isset($data['s_' . $setting->name])) {
1259 $return .= $setting->write_setting($data['s_' . $setting->name]);
1260 } else {
1261 $return .= $setting->write_setting('');
1262 }
1263 }
1264 return $return;
1265 }
1266
a8a66c96 1267 /**
1268 * Is this settigns page hidden in admin tree block?
1269 *
1270 * @return bool True if hidden
1271 */
1272 function is_hidden() {
1273 return $this->hidden;
1274 }
1275
6e4dc10f 1276}
1277
1278
1279// read & write happens at this level; no authentication
1280class admin_setting {
1281
1282 var $name;
1283 var $visiblename;
1284 var $description;
1285 var $defaultsetting;
1286
1287 function admin_setting($name, $visiblename, $description, $defaultsetting) {
1288 $this->name = $name;
1289 $this->visiblename = $visiblename;
1290 $this->description = $description;
1291 $this->defaultsetting = $defaultsetting;
1292 }
eef868d1 1293
6e4dc10f 1294 function get_setting() {
1295 return NULL; // has to be overridden
1296 }
eef868d1 1297
6e4dc10f 1298 function write_setting($data) {
1299 return; // has to be overridden
1300 }
eef868d1 1301
6e4dc10f 1302 function output_html() {
1303 return; // has to be overridden
1304 }
eef868d1 1305
6e4dc10f 1306}
1307
1308
1309class admin_setting_configtext extends admin_setting {
1310
1311 var $paramtype;
1312
50999a0b 1313 function admin_setting_configtext($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW) {
6e4dc10f 1314 $this->paramtype = $paramtype;
1315 parent::admin_setting($name, $visiblename, $description, $defaultsetting);
1316 }
1317
cc73de71 1318 // returns a string or NULL
6e4dc10f 1319 function get_setting() {
1320 global $CFG;
c8218a42 1321 return (isset($CFG->{$this->name}) ? $CFG->{$this->name} : NULL);
6e4dc10f 1322 }
eef868d1 1323
cc73de71 1324 // $data is a string
6e4dc10f 1325 function write_setting($data) {
9e24fbd1 1326 if (!$this->validate($data)) {
1327 return get_string('validateerror', 'admin') . $this->visiblename . '<br />';
c235598d 1328 }
6e4dc10f 1329 return (set_config($this->name,$data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1330 }
1331
c235598d 1332 function validate($data) {
9e24fbd1 1333 if (is_string($this->paramtype)) {
1334 return preg_match($this->paramtype, $data);
1335 } else if ($this->paramtype === PARAM_RAW) {
1336 return true;
1337 } else {
1338 $cleaned = clean_param($data, $this->paramtype);
1339 return ("$data" == "$cleaned"); // implicit conversion to string is needed to do exact comparison
1340 }
c235598d 1341 }
1342
6e4dc10f 1343 function output_html() {
c8218a42 1344 if ($this->get_setting() === NULL) {
1345 $current = $this->defaultsetting;
1346 } else {
1347 $current = $this->get_setting();
1348 }
9e24fbd1 1349 return format_admin_setting($this->name, $this->visiblename,
5259d5d8 1350 '<input type="text" class="form-text" id="id_s_'.$this->name.'" name="s_'.$this->name.'" value="'.s($current).'" />',
6153cf58 1351 $this->description);
6e4dc10f 1352 }
1353
1354}
1355
1356class admin_setting_configcheckbox extends admin_setting {
1357
1358 function admin_setting_configcheckbox($name, $visiblename, $description, $defaultsetting) {
1359 parent::admin_setting($name, $visiblename, $description, $defaultsetting);
1360 }
1361
1362 function get_setting() {
1363 global $CFG;
1364 return (isset($CFG->{$this->name}) ? $CFG->{$this->name} : NULL);
1365 }
eef868d1 1366
6e4dc10f 1367 function write_setting($data) {
1368 if ($data == '1') {
1369 return (set_config($this->name,1) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1370 } else {
1371 return (set_config($this->name,0) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1372 }
1373 }
1374
1375 function output_html() {
c8218a42 1376 if ($this->get_setting() === NULL) {
1377 $current = $this->defaultsetting;
1378 } else {
1379 $current = $this->get_setting();
1380 }
9e24fbd1 1381 return format_admin_setting($this->name, $this->visiblename,
3c6f7a78 1382 '<input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'" name="s_'. $this->name .'" value="1" ' . ($current == true ? 'checked="checked"' : '') . ' />',
6153cf58 1383 $this->description);
6e4dc10f 1384 }
1385
1386}
1387
1388class admin_setting_configselect extends admin_setting {
1389
1390 var $choices;
eef868d1 1391
6e4dc10f 1392 function admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices) {
1393 $this->choices = $choices;
1394 parent::admin_setting($name, $visiblename, $description, $defaultsetting);
1395 }
1396
1397 function get_setting() {
1398 global $CFG;
1399 return (isset($CFG->{$this->name}) ? $CFG->{$this->name} : NULL);
1400 }
eef868d1 1401
6e4dc10f 1402 function write_setting($data) {
1403 // check that what we got was in the original choices
1404 // or that the data is the default setting - needed during install when choices can not be constructed yet
1405 if ($data != $this->defaultsetting and ! in_array($data, array_keys($this->choices))) {
1406 return 'Error setting ' . $this->visiblename . '<br />';
1407 }
eef868d1 1408
6e4dc10f 1409 return (set_config($this->name, $data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1410 }
eef868d1 1411
6e4dc10f 1412 function output_html() {
c8218a42 1413 if ($this->get_setting() === NULL) {
1414 $current = $this->defaultsetting;
1415 } else {
1416 $current = $this->get_setting();
1417 }
afee9864 1418 $return = '<select class="form-select" id="id_s_'.$this->name.'" name="s_' . $this->name .'">';
6e4dc10f 1419 foreach ($this->choices as $key => $value) {
a1069b07 1420 // the string cast is needed because key may be integer - 0 is equal to most strings!
1421 $return .= '<option value="'.$key.'"'.((string)$key==$current ? ' selected="selected"' : '').'>'.$value.'</option>';
6e4dc10f 1422 }
6153cf58 1423 $return .= '</select>';
1424
fc52aa6e 1425 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
6e4dc10f 1426 }
1427
1428}
1429
1430// 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
1431// internally for the setting)
1432class admin_setting_configtime extends admin_setting {
1433
1434 var $name2;
1435 var $choices;
1436 var $choices2;
6e4dc10f 1437
1438 function admin_setting_configtime($hoursname, $minutesname, $visiblename, $description, $defaultsetting) {
1439 $this->name2 = $minutesname;
1440 $this->choices = array();
1441 for ($i = 0; $i < 24; $i++) {
1442 $this->choices[$i] = $i;
1443 }
1444 $this->choices2 = array();
1445 for ($i = 0; $i < 60; $i += 5) {
1446 $this->choices2[$i] = $i;
1447 }
1448 parent::admin_setting($hoursname, $visiblename, $description, $defaultsetting);
1449 }
1450
1451 function get_setting() {
1452 global $CFG;
cc73de71 1453 return (isset($CFG->{$this->name}) && isset($CFG->{$this->name2}) ? array('h' => $CFG->{$this->name}, 'm' => $CFG->{$this->name2}) : NULL);
6e4dc10f 1454 }
eef868d1 1455
6e4dc10f 1456 function write_setting($data) {
1457 // check that what we got was in the original choices
1458 if (!(in_array($data['h'], array_keys($this->choices)) && in_array($data['m'], array_keys($this->choices2)))) {
1459 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
1460 }
eef868d1 1461
6e4dc10f 1462 return (set_config($this->name, $data['h']) && set_config($this->name2, $data['m']) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1463 }
eef868d1 1464
6e4dc10f 1465 function output_html() {
cc73de71 1466 if ($this->get_setting() === NULL) {
1467 $currentsetting = $this->defaultsetting;
1468 } else {
1469 $currentsetting = $this->get_setting();
6e4dc10f 1470 }
2e0c11dd 1471 $return = '<div class="form-group">'.
1472 '<select class="form-select" id="id_s_'.$this->name.'h" name="s_' . $this->name .'[h]">';
6e4dc10f 1473 foreach ($this->choices as $key => $value) {
cc73de71 1474 $return .= '<option value="' . $key . '"' . ($key == $currentsetting['h'] ? ' selected="selected"' : '') . '>' . $value . '</option>';
6e4dc10f 1475 }
2e0c11dd 1476 $return .= '</select>:<select class="form-select" id="id_s_'.$this->name.'m" name="s_' . $this->name . '[m]">';
6e4dc10f 1477 foreach ($this->choices2 as $key => $value) {
cc73de71 1478 $return .= '<option value="' . $key . '"' . ($key == $currentsetting['m'] ? ' selected="selected"' : '') . '>' . $value . '</option>';
eef868d1 1479 }
2e0c11dd 1480 $return .= '</select></div>';
fc52aa6e 1481 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
6e4dc10f 1482 }
1483
1484}
1485
1486class admin_setting_configmultiselect extends admin_setting_configselect {
1487
1488 function admin_setting_configmultiselect($name, $visiblename, $description, $defaultsetting, $choices) {
1489 parent::admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices);
1490 }
1491
1492 function get_setting() {
1493 global $CFG;
d7933a55 1494 if (isset($CFG->{$this->name})) {
1495 if ($CFG->{$this->name}) {
1496 return explode(',', $CFG->{$this->name});
1497 } else {
1498 return array();
1499 }
1500 } else {
1501 return NULL;
1502 }
6e4dc10f 1503 }
eef868d1 1504
6e4dc10f 1505 function write_setting($data) {
d7933a55 1506 if (empty($data)) {
1507 $data = array();
1508 }
6e4dc10f 1509 foreach ($data as $datum) {
1510 if (! in_array($datum, array_keys($this->choices))) {
1511 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
1512 }
1513 }
eef868d1 1514
6e4dc10f 1515 return (set_config($this->name, implode(',',$data)) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1516 }
eef868d1 1517
6e4dc10f 1518 function output_html() {
cc73de71 1519 if ($this->get_setting() === NULL) {
1520 $currentsetting = $this->defaultsetting;
0b0f7c00 1521 if (!$currentsetting) {
1522 $currentsetting = array();
1523 }
cc73de71 1524 } else {
1525 $currentsetting = $this->get_setting();
6e4dc10f 1526 }
afee9864 1527 $return = '<select class="form-select" id="id_s_'.$this->name.'" name="s_' . $this->name .'[]" size="10" multiple="multiple">';
6e4dc10f 1528 foreach ($this->choices as $key => $value) {
1529 $return .= '<option value="' . $key . '"' . (in_array($key,$currentsetting) ? ' selected="selected"' : '') . '>' . $value . '</option>';
1530 }
6153cf58 1531 $return .= '</select>';
fc52aa6e 1532 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
6e4dc10f 1533 }
1534
1535}
1536
1537class admin_setting_special_adminseesall extends admin_setting_configcheckbox {
eef868d1 1538
6e4dc10f 1539 function admin_setting_special_adminseesall() {
1540 $name = 'calendar_adminseesall';
1541 $visiblename = get_string('adminseesall', 'admin');
1542 $description = get_string('helpadminseesall', 'admin');
1543 parent::admin_setting($name, $visiblename, $description, 0);
1544 }
1545
1546 function write_setting($data) {
1547 global $SESSION;
1548 unset($SESSION->cal_courses_shown);
1549 parent::write_setting($data);
1550 }
1551}
1552
1553class admin_setting_sitesetselect extends admin_setting_configselect {
1554
1555 var $id;
1556
1557 function admin_setting_sitesetselect($name, $visiblename, $description, $defaultsetting, $choices) {
1558
1559 $this->id = SITEID;
1560 parent::admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices);
eef868d1 1561
6e4dc10f 1562 }
eef868d1 1563
6e4dc10f 1564 function get_setting() {
1565 $site = get_site();
1566 return (isset($site->{$this->name}) ? $site->{$this->name} : NULL);
1567 }
eef868d1 1568
6e4dc10f 1569 function write_setting($data) {
1570 if (!in_array($data, array_keys($this->choices))) {
1571 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
1572 }
1573 $record = new stdClass();
1574 $record->id = $this->id;
1575 $temp = $this->name;
1576 $record->$temp = $data;
1577 $record->timemodified = time();
1578 return (update_record('course', $record) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1579 }
eef868d1 1580
6e4dc10f 1581}
1582
1583
e0f6e995 1584class admin_setting_courselist_frontpage extends admin_setting_configselect {
6e4dc10f 1585
e0f6e995 1586 function admin_setting_courselist_frontpage($loggedin) {
6e4dc10f 1587 global $CFG;
1588 require_once($CFG->dirroot . '/course/lib.php');
1589 $name = 'frontpage' . ($loggedin ? 'loggedin' : '');
1590 $visiblename = get_string('frontpage' . ($loggedin ? 'loggedin' : ''),'admin');
1591 $description = get_string('configfrontpage' . ($loggedin ? 'loggedin' : ''),'admin');
1592 $choices = array(FRONTPAGENEWS => get_string('frontpagenews'),
1593 FRONTPAGECOURSELIST => get_string('frontpagecourselist'),
1594 FRONTPAGECATEGORYNAMES => get_string('frontpagecategorynames'),
1595 FRONTPAGECATEGORYCOMBO => get_string('frontpagecategorycombo'),
1596 '' => get_string('none'));
1597 if (count_records("course") > FRONTPAGECOURSELIMIT) {
1598 unset($choices[FRONTPAGECOURSELIST]);
1599 }
4672d955 1600 $defaults = FRONTPAGECOURSELIST.',,,';
e0f6e995 1601 parent::admin_setting_configselect($name, $visiblename, $description, $defaults, $choices);
6e4dc10f 1602 }
eef868d1 1603
6e4dc10f 1604 function get_setting() {
1605 global $CFG;
1c1e7af4 1606 return (isset($CFG->{$this->name}) ? explode(',', $CFG->{$this->name}) : ',1,,');
6e4dc10f 1607 }
eef868d1 1608
6e4dc10f 1609 function write_setting($data) {
1610 if (empty($data)) {
1611 $data = array();
e0f6e995 1612 } if (!is_array($data)) {
1613 $data = explode(',', $data);
6e4dc10f 1614 }
1615 foreach($data as $datum) {
1616 if (! in_array($datum, array_keys($this->choices))) {
1617 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
1618 }
1619 }
1620 return (set_config($this->name, implode(',', $data)) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1621 }
eef868d1 1622
6e4dc10f 1623 function output_html() {
cc73de71 1624 if ($this->get_setting() === NULL) {
1625 $currentsetting = $this->defaultsetting;
1626 } else {
1627 $currentsetting = $this->get_setting();
6e4dc10f 1628 }
1629 for ($i = 0; $i < count($this->choices) - 1; $i++) {
1630 if (!isset($currentsetting[$i])) {
1631 $currentsetting[$i] = 0;
1632 }
1633 }
0a7e84c3 1634 $return = '<div class="form-group">';
6e4dc10f 1635 for ($i = 0; $i < count($this->choices) - 1; $i++) {
a1d52643 1636 $return .='<select class="form-select" id="id_s_'.$this->name.$i.'" name="s_' . $this->name .'[]">';
6e4dc10f 1637 foreach ($this->choices as $key => $value) {
1638 $return .= '<option value="' . $key . '"' . ($key == $currentsetting[$i] ? ' selected="selected"' : '') . '>' . $value . '</option>';
1639 }
1640 $return .= '</select>';
1641 if ($i !== count($this->choices) - 2) {
975211bb 1642 $return .= '<br />';
6e4dc10f 1643 }
1644 }
0a7e84c3 1645 $return .= '</div>';
1646
fc52aa6e 1647 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
6e4dc10f 1648 }
1649}
1650
1651class admin_setting_sitesetcheckbox extends admin_setting_configcheckbox {
1652
1653 var $id;
1654
1655 function admin_setting_sitesetcheckbox($name, $visiblename, $description, $defaultsetting) {
1656
1657 $this->id = SITEID;
1658 parent::admin_setting_configcheckbox($name, $visiblename, $description, $defaultsetting);
eef868d1 1659
6e4dc10f 1660 }
eef868d1 1661
6e4dc10f 1662 function get_setting() {
1663 $site = get_site();
1664 return (isset($site->{$this->name}) ? $site->{$this->name} : NULL);
1665 }
eef868d1 1666
6e4dc10f 1667 function write_setting($data) {
1668 $record = new stdClass();
1669 $record->id = $this->id;
1670 $temp = $this->name;
1671 $record->$temp = ($data == '1' ? 1 : 0);
1672 $record->timemodified = time();
1673 return (update_record('course', $record) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1674 }
eef868d1 1675
6e4dc10f 1676}
1677
1678class admin_setting_sitesettext extends admin_setting_configtext {
1679
1680 var $id;
1681
b89639f9 1682 function admin_setting_sitesettext($name, $visiblename, $description, $defaultsetting) {
6e4dc10f 1683
1684 $this->id = SITEID;
b89639f9 1685 parent::admin_setting_configtext($name, $visiblename, $description, $defaultsetting);
eef868d1 1686
6e4dc10f 1687 }
eef868d1 1688
6e4dc10f 1689 function get_setting() {
1690 $site = get_site();
1691 return (isset($site->{$this->name}) ? $site->{$this->name} : NULL);
1692 }
90cfbd0a 1693
b89639f9 1694 function validate($data) {
1695 $cleaned = clean_param($data, PARAM_NOTAGS);
1696 if ($cleaned == '') {
1697 return false; // can not be empty
1698 }
1699 return ("$data" == "$cleaned"); // implicit conversion to string is needed to do exact comparison
1700 }
1701
6e4dc10f 1702 function write_setting($data) {
b89639f9 1703 $data = trim($data);
9e24fbd1 1704 if (!$this->validate($data)) {
1705 return get_string('validateerror', 'admin') . $this->visiblename . '<br />';
90cfbd0a 1706 }
eef868d1 1707
6e4dc10f 1708 $record = new stdClass();
1709 $record->id = $this->id;
90cfbd0a 1710 $record->{$this->name} = $data;
6e4dc10f 1711 $record->timemodified = time();
23a97d83 1712 return (update_record('course', $record) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
6e4dc10f 1713 }
90cfbd0a 1714
6e4dc10f 1715}
1716
1717class admin_setting_special_frontpagedesc extends admin_setting {
1718
1719 var $id;
eef868d1 1720
6e4dc10f 1721 function admin_setting_special_frontpagedesc() {
1722 $this->id = SITEID;
1723 $name = 'summary';
1724 $visiblename = get_string('frontpagedescription');
1725 $description = get_string('frontpagedescriptionhelp');
1726 parent::admin_setting($name, $visiblename, $description, '');
1727 }
1728
1729 function output_html() {
eef868d1 1730
fa040029 1731 global $CFG;
1732
cc73de71 1733 if ($this->get_setting() === NULL) {
1734 $currentsetting = $this->defaultsetting;
1735 } else {
1736 $currentsetting = $this->get_setting();
1737 }
eef868d1 1738
fa040029 1739 $CFG->adminusehtmleditor = can_use_html_editor();
eef868d1 1740
fa040029 1741 $return = print_textarea($CFG->adminusehtmleditor, 15, 60, 0, 0, 's_' . $this->name, $currentsetting, 0, true);
eef868d1 1742
fc52aa6e 1743 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
6e4dc10f 1744 }
eef868d1 1745
6e4dc10f 1746 function get_setting() {
eef868d1 1747
6e4dc10f 1748 $site = get_site();
1749 return (isset($site->{$this->name}) ? $site->{$this->name} : NULL);
eef868d1 1750
6e4dc10f 1751 }
eef868d1 1752
6e4dc10f 1753 function write_setting($data) {
eef868d1 1754
6e4dc10f 1755 $data = addslashes(clean_param($data, PARAM_CLEANHTML));
eef868d1 1756
6e4dc10f 1757 $record = new stdClass();
1758 $record->id = $this->id;
1759 $temp = $this->name;
1760 $record->$temp = $data;
1761 $record->timemodified = time();
eef868d1 1762
6e4dc10f 1763 return(update_record('course', $record) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
eef868d1 1764
6e4dc10f 1765 }
1766
1767}
1768
1769
1770class admin_setting_special_editorfontlist extends admin_setting {
1771
1772 var $items;
1773
1774 function admin_setting_special_editorfontlist() {
1775 global $CFG;
1776 $name = 'editorfontlist';
1777 $visiblename = get_string('editorfontlist', 'admin');
1778 $description = get_string('configeditorfontlist', 'admin');
6e4dc10f 1779 $defaults = array('k0' => 'Trebuchet',
1780 'v0' => 'Trebuchet MS,Verdana,Arial,Helvetica,sans-serif',
1781 'k1' => 'Arial',
1782 'v1' => 'arial,helvetica,sans-serif',
1783 'k2' => 'Courier New',
1784 'v2' => 'courier new,courier,monospace',
1785 'k3' => 'Georgia',
1786 'v3' => 'georgia,times new roman,times,serif',
1787 'k4' => 'Tahoma',
1788 'v4' => 'tahoma,arial,helvetica,sans-serif',
1789 'k5' => 'Times New Roman',
1790 'v5' => 'times new roman,times,serif',
1791 'k6' => 'Verdana',
1792 'v6' => 'verdana,arial,helvetica,sans-serif',
1793 'k7' => 'Impact',
1794 'v7' => 'impact',
1795 'k8' => 'Wingdings',
1796 'v8' => 'wingdings');
1797 parent::admin_setting($name, $visiblename, $description, $defaults);
1798 }
eef868d1 1799
6e4dc10f 1800 function get_setting() {
cc73de71 1801 global $CFG;
1802 if (isset($CFG->editorfontlist)) {
1803 $i = 0;
1804 $currentsetting = array();
1805 $items = explode(';', $CFG->editorfontlist);
1806 foreach ($items as $item) {
1807 $item = explode(':', $item);
1808 $currentsetting['k' . $i] = $item[0];
1809 $currentsetting['v' . $i] = $item[1];
1810 $i++;
1811 }
1812 return $currentsetting;
1813 } else {
1814 return NULL;
1815 }
6e4dc10f 1816 }
eef868d1 1817
6e4dc10f 1818 function write_setting($data) {
eef868d1 1819
6e4dc10f 1820 // there miiight be an easier way to do this :)
1821 // if this is changed, make sure the $defaults array above is modified so that this
1822 // function processes it correctly
eef868d1 1823
6e4dc10f 1824 $keys = array();
1825 $values = array();
eef868d1 1826
6e4dc10f 1827 foreach ($data as $key => $value) {
1828 if (substr($key,0,1) == 'k') {
1829 $keys[substr($key,1)] = $value;
1830 } elseif (substr($key,0,1) == 'v') {
1831 $values[substr($key,1)] = $value;
1832 }
1833 }
eef868d1 1834
6e4dc10f 1835 $result = '';
1836 for ($i = 0; $i < count($keys); $i++) {
1837 if (($keys[$i] !== '') && ($values[$i] !== '')) {
1838 $result .= clean_param($keys[$i],PARAM_NOTAGS) . ':' . clean_param($values[$i], PARAM_NOTAGS) . ';';
1839 }
1840 }
eef868d1 1841
6e4dc10f 1842 $result = substr($result, 0, -1); // trim the last semicolon
eef868d1 1843
6e4dc10f 1844 return (set_config($this->name, $result) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1845 }
eef868d1 1846
6e4dc10f 1847 function output_html() {
eef868d1 1848
cc73de71 1849 if ($this->get_setting() === NULL) {
1850 $currentsetting = $this->defaultsetting;
1851 } else {
1852 $currentsetting = $this->get_setting();
6e4dc10f 1853 }
eef868d1 1854
1beed35f 1855 $return = '<div class="form-group">';
cc73de71 1856 for ($i = 0; $i < count($currentsetting) / 2; $i++) {
3c6f7a78 1857 $return .= '<input type="text" class="form-text" name="s_editorfontlist[k' . $i . ']" value="' . $currentsetting['k' . $i] . '" />';
6e4dc10f 1858 $return .= '&nbsp;&nbsp;';
3c6f7a78 1859 $return .= '<input type="text" class="form-text" name="s_editorfontlist[v' . $i . ']" value="' . $currentsetting['v' . $i] . '" /><br />';
6e4dc10f 1860 }
3c6f7a78 1861 $return .= '<input type="text" class="form-text" name="s_editorfontlist[k' . $i . ']" value="" />';
6e4dc10f 1862 $return .= '&nbsp;&nbsp;';
3c6f7a78 1863 $return .= '<input type="text" class="form-text" name="s_editorfontlist[v' . $i . ']" value="" /><br />';
1864 $return .= '<input type="text" class="form-text" name="s_editorfontlist[k' . ($i + 1) . ']" value="" />';
6e4dc10f 1865 $return .= '&nbsp;&nbsp;';
3c6f7a78 1866 $return .= '<input type="text" class="form-text" name="s_editorfontlist[v' . ($i + 1) . ']" value="" />';
1beed35f 1867 $return .= '</div>';
6153cf58 1868
fc52aa6e 1869 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
6e4dc10f 1870 }
eef868d1 1871
6e4dc10f 1872}
1873
1874class admin_setting_special_editordictionary extends admin_setting_configselect {
1875
1876 function admin_setting_special_editordictionary() {
1877 $name = 'editordictionary';
1878 $visiblename = get_string('editordictionary','admin');
1879 $description = get_string('configeditordictionary', 'admin');
1880 $choices = $this->editor_get_dictionaries();
1881 if (! is_array($choices)) {
1882 $choices = array('');
1883 }
eef868d1 1884
6e4dc10f 1885 parent::admin_setting_configselect($name, $visiblename, $description, '', $choices);
1886 }
1887
1888 // function borrowed from the old moodle/admin/editor.php, slightly modified
1889 function editor_get_dictionaries () {
1890 /// Get all installed dictionaries in the system
1891
1892 global $CFG;
eef868d1 1893
6e4dc10f 1894// error_reporting(E_ALL); // for debug, final version shouldn't have this...
1895 clearstatcache();
1896
1897 // If aspellpath isn't set don't even bother ;-)
1898 if (empty($CFG->aspellpath)) {
1899 return 'Empty aspell path!';
1900 }
1901
1902 // Do we have access to popen function?
1903 if (!function_exists('popen')) {
1904 return 'Popen function disabled!';
1905 }
eef868d1 1906
6e4dc10f 1907 $cmd = $CFG->aspellpath;
1908 $output = '';
1909 $dictionaries = array();
1910 $dicts = array();
1911
1912 if(!($handle = @popen(escapeshellarg($cmd) .' dump dicts', 'r'))) {
1913 return 'Couldn\'t create handle!';
1914 }
1915
1916 while(!feof($handle)) {
1917 $output .= fread($handle, 1024);
1918 }
1919 @pclose($handle);
1920
1921 $dictionaries = explode(chr(10), $output);
1922
1923 // Get rid of possible empty values
1924 if (is_array($dictionaries)) {
1925
1926 $cnt = count($dictionaries);
1927
1928 for ($i = 0; $i < $cnt; $i++) {
1929 if (!empty($dictionaries[$i])) {
2c41b2d7 1930 $dicts[$dictionaries[$i]] = $dictionaries[$i];
6e4dc10f 1931 }
1932 }
1933 }
1934
1935 if (count($dicts) >= 1) {
1936 return $dicts;
1937 }
1938
1939 return 'Error! Check your aspell installation!';
1940 }
1941
eef868d1 1942
6e4dc10f 1943
1944}
1945
1946
1947class admin_setting_special_editorhidebuttons extends admin_setting {
1948
1949 var $name;
1950 var $visiblename;
1951 var $description;
1952 var $items;
1953
1954 function admin_setting_special_editorhidebuttons() {
1955 $this->name = 'editorhidebuttons';
1956 $this->visiblename = get_string('editorhidebuttons', 'admin');
1957 $this->description = get_string('confeditorhidebuttons', 'admin');
1958 $this->defaultsetting = array();
1959 // weird array... buttonname => buttonimage (assume proper path appended). if you leave buttomimage blank, text will be printed instead
1960 $this->items = array('fontname' => '',
1961 'fontsize' => '',
1962 'formatblock' => '',
1963 'bold' => 'ed_format_bold.gif',
1964 'italic' => 'ed_format_italic.gif',
1965 'underline' => 'ed_format_underline.gif',
1966 'strikethrough' => 'ed_format_strike.gif',
1967 'subscript' => 'ed_format_sub.gif',
1968 'superscript' => 'ed_format_sup.gif',
1969 'copy' => 'ed_copy.gif',
1970 'cut' => 'ed_cut.gif',
1971 'paste' => 'ed_paste.gif',
1972 'clean' => 'ed_wordclean.gif',
1973 'undo' => 'ed_undo.gif',
1974 'redo' => 'ed_redo.gif',
1975 'justifyleft' => 'ed_align_left.gif',
1976 'justifycenter' => 'ed_align_center.gif',
1977 'justifyright' => 'ed_align_right.gif',
1978 'justifyfull' => 'ed_align_justify.gif',
1979 'lefttoright' => 'ed_left_to_right.gif',
1980 'righttoleft' => 'ed_right_to_left.gif',
1981 'insertorderedlist' => 'ed_list_num.gif',
1982 'insertunorderedlist' => 'ed_list_bullet.gif',
1983 'outdent' => 'ed_indent_less.gif',
1984 'indent' => 'ed_indent_more.gif',
1985 'forecolor' => 'ed_color_fg.gif',
1986 'hilitecolor' => 'ed_color_bg.gif',
1987 'inserthorizontalrule' => 'ed_hr.gif',
1988 'createanchor' => 'ed_anchor.gif',
1989 'createlink' => 'ed_link.gif',
1990 'unlink' => 'ed_unlink.gif',
1991 'insertimage' => 'ed_image.gif',
1992 'inserttable' => 'insert_table.gif',
1993 'insertsmile' => 'em.icon.smile.gif',
1994 'insertchar' => 'icon_ins_char.gif',
1995 'spellcheck' => 'spell-check.gif',
1996 'htmlmode' => 'ed_html.gif',
1997 'popupeditor' => 'fullscreen_maximize.gif',
1998 'search_replace' => 'ed_replace.gif');
1999 }
2000
2001 function get_setting() {
2002 global $CFG;
2003 return (isset($CFG->{$this->name}) ? explode(' ', $CFG->{$this->name}) : NULL);
2004 }
2005
2006 function write_setting($data) {
2007 $result = array();
2008 if (empty($data)) { $data = array(); }
2009 foreach ($data as $key => $value) {
2010 if (!in_array($key, array_keys($this->items))) {
2011 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2012 }
2013 if ($value == '1') {
2014 $result[] = $key;
2015 }
2016 }
2017 return (set_config($this->name, implode(' ',$result)) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2018 }
2019
2020 function output_html() {
eef868d1 2021
6e4dc10f 2022 global $CFG;
eef868d1 2023
6e4dc10f 2024 // checkboxes with input name="$this->name[$key]" value="1"
2025 // we do 15 fields per column
eef868d1 2026
cc73de71 2027 if ($this->get_setting() === NULL) {
2028 $currentsetting = $this->defaultsetting;
2029 } else {
2030 $currentsetting = $this->get_setting();
6e4dc10f 2031 }
eef868d1 2032
1beed35f 2033 $return = '<div class="form-group">';
2034 $return .= '<table><tr><td valign="top" align="right">';
eef868d1 2035
6e4dc10f 2036 $count = 0;
eef868d1 2037
6e4dc10f 2038 foreach($this->items as $key => $value) {
8ddbd7a6 2039 if ($count % 15 == 0 and $count != 0) {
2040 $return .= '</td><td valign="top" align="right">';
6e4dc10f 2041 }
eef868d1 2042
6e4dc10f 2043 $return .= ($value == '' ? get_string($key,'editor') : '<img width="18" height="18" src="' . $CFG->wwwroot . '/lib/editor/htmlarea/images/' . $value . '" alt="' . get_string($key,'editor') . '" title="' . get_string($key,'editor') . '" />') . '&nbsp;';
afee9864 2044 $return .= '<input type="checkbox" class="form-checkbox" value="1" id="id_s_'.$this->name.$key.'" name="s_' . $this->name . '[' . $key . ']"' . (in_array($key,$currentsetting) ? ' checked="checked"' : '') . ' />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
6e4dc10f 2045 $count++;
2046 if ($count % 15 != 0) {
2047 $return .= '<br /><br />';
2048 }
2049 }
eef868d1 2050
2051 $return .= '</td></tr>';
6e4dc10f 2052 $return .= '</table>';
1beed35f 2053 $return .= '</div>';
6e4dc10f 2054
fc52aa6e 2055 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
6e4dc10f 2056 }
2057
2058}
2059
2060class admin_setting_backupselect extends admin_setting_configselect {
2061
2062 function admin_setting_backupselect($name, $visiblename, $description, $default, $choices) {
2063 parent::admin_setting_configselect($name, $visiblename, $description, $default, $choices);
2064 }
2065
2066 function get_setting() {
2067 $backup_config = backup_get_config();
2068 return (isset($backup_config->{$this->name}) ? $backup_config->{$this->name} : NULL);
2069 }
eef868d1 2070
6e4dc10f 2071 function write_setting($data) {
2072 // check that what we got was in the original choices
2073 if (! in_array($data, array_keys($this->choices))) {
2074 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2075 }
eef868d1 2076
6e4dc10f 2077 return (backup_set_config($this->name, $data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2078 }
2079
2080}
2081
2082class admin_setting_special_backupsaveto extends admin_setting_configtext {
2083
2084 function admin_setting_special_backupsaveto() {
2085 $name = 'backup_sche_destination';
2086 $visiblename = get_string('saveto');
2087 $description = get_string('backupsavetohelp');
2088 parent::admin_setting_configtext($name, $visiblename, $description, '', PARAM_PATH);
2089 }
eef868d1 2090
6e4dc10f 2091 function get_setting() {
2092 $backup_config = backup_get_config();
2093 return (isset($backup_config->{$this->name}) ? $backup_config->{$this->name} : NULL);
2094 }
eef868d1 2095
6e4dc10f 2096 function write_setting($data) {
2097 $data = clean_param($data, PARAM_PATH);
2098 if (!empty($data) and (substr($data,-1) == '/' or substr($data,-1) == '\\')) {
2099 return get_string('pathslasherror') . '<br />';
2100 } else if (!empty($data) and !is_dir($data)) {
2101 return get_string('pathnotexists') . '<br />';
2102 }
2103 return (backup_set_config($this->name, $data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2104 }
2105
2106}
2107
2108class admin_setting_backupcheckbox extends admin_setting_configcheckbox {
2109
2110 function admin_setting_backupcheckbox($name, $visiblename, $description, $default) {
2111 parent::admin_setting_configcheckbox($name, $visiblename, $description, $default);
2112 }
2113
2114 function write_setting($data) {
2115 if ($data == '1') {
2116 return (backup_set_config($this->name, 1) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2117 } else {
2118 return (backup_set_config($this->name, 0) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2119 }
2120 }
eef868d1 2121
6e4dc10f 2122 function get_setting() {
2123 $backup_config = backup_get_config();
2124 return (isset($backup_config->{$this->name}) ? $backup_config->{$this->name} : NULL);
2125 }
2126
2127}
2128
2129class admin_setting_special_backuptime extends admin_setting_configtime {
2130
2131 function admin_setting_special_backuptime() {
2132 $name = 'backup_sche_hour';
2133 $name2 = 'backup_sche_minute';
2134 $visiblename = get_string('executeat');
2135 $description = get_string('backupexecuteathelp');
2136 $default = array('h' => 0, 'm' => 0);
2137 parent::admin_setting_configtime($name, $name2, $visiblename, $description, $default);
2138 }
eef868d1 2139
6e4dc10f 2140 function get_setting() {
2141 $backup_config = backup_get_config();
9fd9df20 2142 return (isset($backup_config->{$this->name}) && isset($backup_config->{$this->name}) ? array('h'=>$backup_config->{$this->name}, 'm'=>$backup_config->{$this->name2}) : NULL);
6e4dc10f 2143 }
eef868d1 2144
6e4dc10f 2145 function write_setting($data) {
2146 // check that what we got was in the original choices
2147 if (!(in_array($data['h'], array_keys($this->choices)) && in_array($data['m'], array_keys($this->choices2)))) {
2148 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2149 }
eef868d1 2150
2151 return (backup_set_config($this->name, $data['h']) && backup_set_config($this->name2, $data['m']) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
6e4dc10f 2152 }
eef868d1 2153
6e4dc10f 2154}
2155
2156class admin_setting_special_backupdays extends admin_setting {
2157
2158 function admin_setting_special_backupdays() {
2159 $name = 'backup_sche_weekdays';
2160 $visiblename = get_string('schedule');
2161 $description = get_string('backupschedulehelp');
6727c175 2162 $default = array('u' => 0, 'm' => 0, 't' => 0, 'w' => 0, 'r' => 0, 'f' => 0, 's' => 0);
2163 parent::admin_setting($name, $visiblename, $description, $default);
6e4dc10f 2164 }
eef868d1 2165
6e4dc10f 2166 function get_setting() {
2167 $backup_config = backup_get_config();
cc73de71 2168 if (isset($backup_config->{$this->name})) {
2169 $currentsetting = $backup_config->{$this->name};
2170 return array('u' => substr($currentsetting, 0, 1),
2171 'm' => substr($currentsetting, 1, 1),
2172 't' => substr($currentsetting, 2, 1),
2173 'w' => substr($currentsetting, 3, 1),
2174 'r' => substr($currentsetting, 4, 1),
2175 'f' => substr($currentsetting, 5, 1),
2176 's' => substr($currentsetting, 6, 1));
2177 } else {
2178 return NULL;
2179 }
6e4dc10f 2180 }
eef868d1 2181
6e4dc10f 2182 function output_html() {
eef868d1 2183
cc73de71 2184 if ($this->get_setting() === NULL) {
2185 $currentsetting = $this->defaultsetting;
2186 } else {
2187 $currentsetting = $this->get_setting();
6e4dc10f 2188 }
eef868d1 2189
cc73de71 2190 // rewrite for simplicity
eef868d1 2191 $currentsetting = $currentsetting['u'] . $currentsetting['m'] . $currentsetting['t'] . $currentsetting['w'] .
cc73de71 2192 $currentsetting['r'] . $currentsetting['f'] . $currentsetting['s'];
eef868d1 2193
6153cf58 2194 $return = '<table><tr><td><div align="center">&nbsp;&nbsp;' . get_string('sunday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div align="center">&nbsp;&nbsp;' .
6e4dc10f 2195 get_string('monday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div align="center">&nbsp;&nbsp;' . get_string('tuesday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div align="center">&nbsp;&nbsp;' .
2196 get_string('wednesday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div align="center">&nbsp;&nbsp;' . get_string('thursday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div align="center">&nbsp;&nbsp;' .
2197 get_string('friday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div align="center">&nbsp;&nbsp;' . get_string('saturday', 'calendar') . '&nbsp;&nbsp;</div></td></tr><tr>' .
afee9864 2198 '<td><div align="center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'u" name="s_'. $this->name .'[u]" value="1" ' . (substr($currentsetting,0,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2199 '<td><div align="center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'m" name="s_'. $this->name .'[m]" value="1" ' . (substr($currentsetting,1,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2200 '<td><div align="center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'t" name="s_'. $this->name .'[t]" value="1" ' . (substr($currentsetting,2,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2201 '<td><div align="center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'w" name="s_'. $this->name .'[w]" value="1" ' . (substr($currentsetting,3,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2202 '<td><div align="center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'r" name="s_'. $this->name .'[r]" value="1" ' . (substr($currentsetting,4,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2203 '<td><div align="center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'f" name="s_'. $this->name .'[f]" value="1" ' . (substr($currentsetting,5,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2204 '<td><div align="center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'s" name="s_'. $this->name .'[s]" value="1" ' . (substr($currentsetting,6,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
6153cf58 2205 '</tr></table>';
2206
fc52aa6e 2207 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
eef868d1 2208
6e4dc10f 2209 }
eef868d1 2210
6e4dc10f 2211 // 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
2212 // admin_settingpage (note that admin_settingpage only calls write_setting with the data that matches $this->name... so if we have multiple form fields,
2213 // they MUST go into an array named $this->name, or else we won't receive them here
2214 function write_setting($data) {
2215 $week = 'umtwrfs';
2216 $result = array(0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0);
9fd9df20 2217 if (!empty($data)) {
2218 foreach($data as $key => $value) {
2219 if ($value == '1') {
2220 $result[strpos($week, $key)] = 1;
2221 }
2222 }
6e4dc10f 2223 }
2224 return (backup_set_config($this->name, implode('',$result)) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2225 }
2226}
2227
ee437bbc 2228class admin_setting_special_debug extends admin_setting_configselect {
6e4dc10f 2229
2230 function admin_setting_special_debug() {
2231 $name = 'debug';
2232 $visiblename = get_string('debug', 'admin');
2233 $description = get_string('configdebug', 'admin');
7eb0b60a 2234 $choices = array( DEBUG_NONE => get_string('debugnone', 'admin'),
2235 DEBUG_MINIMAL => get_string('debugminimal', 'admin'),
2236 DEBUG_NORMAL => get_string('debugnormal', 'admin'),
38d2d43b 2237 DEBUG_ALL => get_string('debugall', 'admin'),
2238 DEBUG_DEVELOPER => get_string('debugdeveloper', 'admin')
ee437bbc 2239 );
2240 parent::admin_setting_configselect($name, $visiblename, $description, '', $choices);
6e4dc10f 2241 }
2242
ee437bbc 2243 function get_setting() {
2244 global $CFG;
cc73de71 2245 if (isset($CFG->debug)) {
cc73de71 2246 return $CFG->debug;
2247 } else {
2248 return NULL;
ee437bbc 2249 }
6e4dc10f 2250 }
2251
ee437bbc 2252 function write_setting($data) {
2253 return (set_config($this->name,$data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
6e4dc10f 2254 }
2255
2256}
2257
2258
2259class admin_setting_special_calendar_weekend extends admin_setting {
2260
2261 function admin_setting_special_calendar_weekend() {
2262 $name = 'calendar_weekend';
2263 $visiblename = get_string('calendar_weekend', 'admin');
2264 $description = get_string('helpweekenddays', 'admin');
b91b1f92 2265 $default = array('u' => 1, 'm' => 0, 't' => 0, 'w' => 0, 'r' => 0, 'f' => 0, 's' => 1);
2266 parent::admin_setting($name, $visiblename, $description, $default);
6e4dc10f 2267 }
2268
2269 function get_setting() {
2270 global $CFG;
2271 if (isset($CFG->{$this->name})) {
b91b1f92 2272 $currentsetting = decbin($CFG->{$this->name});
2273 $currentsetting = str_pad($currentsetting, 7, '0', STR_PAD_LEFT);
2274 return array('u' => substr($currentsetting, 0, 1),
2275 'm' => substr($currentsetting, 1, 1),
2276 't' => substr($currentsetting, 2, 1),
2277 'w' => substr($currentsetting, 3, 1),
2278 'r' => substr($currentsetting, 4, 1),
2279 'f' => substr($currentsetting, 5, 1),
2280 's' => substr($currentsetting, 6, 1));
6e4dc10f 2281 } else {
2282 return NULL;
2283 }
2284 }
eef868d1 2285
6e4dc10f 2286 function write_setting($data) {
2287 $week = 'umtwrfs';
2288 $result = array(0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0);
b91b1f92 2289 if (!empty($data)) {
2290 foreach($data as $key => $value) {
2291 if ($value == '1') {
2292 $result[strpos($week, $key)] = 1;
2293 }
2294 }
6e4dc10f 2295 }
2296 return (set_config($this->name, bindec(implode('',$result))) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2297 }
eef868d1 2298
6e4dc10f 2299 function output_html() {
2300
cc73de71 2301 if ($this->get_setting() === NULL) {
2302 $currentsetting = $this->defaultsetting;
2303 } else {
2304 $currentsetting = $this->get_setting();
6e4dc10f 2305 }
cc73de71 2306
b91b1f92 2307 // rewrite for simplicity
2308 $currentsetting = $currentsetting['u'] . $currentsetting['m'] . $currentsetting['t'] . $currentsetting['w'] .
2309 $currentsetting['r'] . $currentsetting['f'] . $currentsetting['s'];
3b904bc9 2310
6153cf58 2311 $return = '<table><tr><td><div align="center">&nbsp;&nbsp;' . get_string('sunday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div align="center">&nbsp;&nbsp;' .
6e4dc10f 2312 get_string('monday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div align="center">&nbsp;&nbsp;' . get_string('tuesday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div align="center">&nbsp;&nbsp;' .
2313 get_string('wednesday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div align="center">&nbsp;&nbsp;' . get_string('thursday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div align="center">&nbsp;&nbsp;' .
2314 get_string('friday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div align="center">&nbsp;&nbsp;' . get_string('saturday', 'calendar') . '&nbsp;&nbsp;</div></td></tr><tr>' .
b91b1f92 2315 '<td><div align="center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'u" name="s_'. $this->name .'[u]" value="1" ' . (substr($currentsetting,0,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2316 '<td><div align="center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'m" name="s_'. $this->name .'[m]" value="1" ' . (substr($currentsetting,1,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2317 '<td><div align="center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'t" name="s_'. $this->name .'[t]" value="1" ' . (substr($currentsetting,2,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2318 '<td><div align="center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'w" name="s_'. $this->name .'[w]" value="1" ' . (substr($currentsetting,3,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2319 '<td><div align="center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'r" name="s_'. $this->name .'[r]" value="1" ' . (substr($currentsetting,4,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2320 '<td><div align="center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'f" name="s_'. $this->name .'[f]" value="1" ' . (substr($currentsetting,5,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
2321 '<td><div align="center"><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'s" name="s_'. $this->name .'[s]" value="1" ' . (substr($currentsetting,6,1) == '1' ? 'checked="checked"' : '') . ' /></div></td>' .
6153cf58 2322 '</tr></table>';
2323
fc52aa6e 2324 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
eef868d1 2325
6e4dc10f 2326 }
2327
2328}
2329
73afaf5b 2330/*
2331 * this is used in config->appearance->gradeconfig
5a412dbf 2332 */
0909d44e 2333class admin_setting_special_gradebookroles extends admin_setting {
5a412dbf 2334
0909d44e 2335 function admin_setting_special_gradebookroles() {
2336 $name = 'gradebookroles';
73afaf5b 2337 $visiblename = get_string('gradebookroles', 'admin');
2338 $description = get_string('configgradebookroles', 'admin');
7aa3e196 2339 $default = array(5=>'1'); // The student role in a default install
8a2cb2fa 2340 parent::admin_setting($name, $visiblename, $description, $default);
5a412dbf 2341 }
2342
2343 function get_setting() {
2344 global $CFG;
8a2cb2fa 2345 if (!empty($CFG->{$this->name})) {
60f7d402 2346 $result = explode(',', $CFG->{$this->name});
2347 foreach ($result as $roleid) {
2348 $array[$roleid] = 1;
2349 }
2350 return $array;
5a412dbf 2351 } else {
3fae9f57 2352 return null;
5a412dbf 2353 }
2354 }
2355
2356 function write_setting($data) {
2357 if (!empty($data)) {
2358 $str = '';
0909d44e 2359 foreach ($data as $key => $value) {
5a412dbf 2360 if ($value) {
2361 $str .= $key.',';
2362 }
2363 }
2364 return set_config($this->name, rtrim($str, ","))?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2365 } else {
73afaf5b 2366 return set_config($this->name, '')?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2367 }
5a412dbf 2368 }
2369
2370 function output_html() {
2371
2372 if ($this->get_setting() === NULL) {
2373 $currentsetting = $this->defaultsetting;
2374 } else {
2375 $currentsetting = $this->get_setting();
2376 }
5a412dbf 2377 // from to process which roles to display
2378 if ($roles = get_records('role')) {
73afaf5b 2379 $return = '<div class="form-group">';
2380 $first = true;
2381 foreach ($roles as $roleid=>$role) {
60f7d402 2382 if (is_array($currentsetting) && in_array($roleid, array_keys($currentsetting))) {
fb132873 2383 $checked = ' checked="checked"';
5a412dbf 2384 } else {
73afaf5b 2385 $checked = '';
5a412dbf 2386 }
73afaf5b 2387 if ($first) {
2388 $first = false;
2389 } else {
2390 $return .= '<br />';
2391 }
4eb777c2 2392 $return .= '<input type="checkbox" name="s_'.$this->name.'['.$roleid.']" value="1"'.$checked.' />&nbsp;'.$role->name;
5a412dbf 2393 }
73afaf5b 2394 $return .= '</div>';
5a412dbf 2395 }
73afaf5b 2396
5a412dbf 2397 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
2398
2399 }
2400
2401}
6e4dc10f 2402
d42c64ba 2403/*
2404 * this is used in config->appearance->coursemanager
2405 * (which roles to show on course decription page)
2406 */
2407class admin_setting_special_coursemanager extends admin_setting {
2408
2409 function admin_setting_special_coursemanager() {
2410 $name = 'coursemanager';
2411 $visiblename = get_string('coursemanager', 'admin');
2412 $description = get_string('configcoursemanager', 'admin');
2413 $default = array(3=>'1'); // The teahcer role in a default install
2414 parent::admin_setting($name, $visiblename, $description, $default);
2415 }
2416
2417 function get_setting() {
2418
2419 global $CFG;
2420 if (!empty($CFG->{$this->name})) {
2421 $result = explode(',', $CFG->{$this->name});
2422 foreach ($result as $roleid) {
2423 $array[$roleid] = 1;
2424 }
2425 return $array;
2426 } else {
2427 return null;
2428 }
2429 }
2430
2431 function write_setting($data) {
2432
2433 if (!empty($data)) {
2434 $str = '';
2435 foreach ($data as $key => $value) {
2436 if ($value) {
2437 $str .= $key.',';
2438 }
2439 }
2440 return set_config($this->name, rtrim($str, ","))?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2441 } else {
2442 return set_config($this->name, '')?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2443 }
2444 }
2445
2446 function output_html() {
2447
2448 if ($this->get_setting() === NULL) {
2449 $currentsetting = $this->defaultsetting;
2450 } else {
2451 $currentsetting = $this->get_setting();
2452 }
2453 // from to process which roles to display
2454 if ($roles = get_records('role')) {
2455 $return = '<div class="form-group">';
2456 $first = true;
2457 foreach ($roles as $roleid=>$role) {
2458 if (is_array($currentsetting) && in_array($roleid, array_keys($currentsetting))) {
2459 $checked = 'checked="checked"';
2460 } else {
2461 $checked = '';
2462 }
2463 if ($first) {
2464 $first = false;
2465 } else {
2466 $return .= '<br />';
2467 }
7203167d 2468 $return .= '<input type="checkbox" name="s_'.$this->name.'['.$roleid.']" value="1" '.$checked.' />&nbsp;'.$role->name;
d42c64ba 2469 }
2470 $return .= '</div>';
2471 }
2472 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
2473 }
2474}
2475
6e4dc10f 2476class admin_setting_special_perfdebug extends admin_setting_configcheckbox {
2477
2478 function admin_setting_special_perfdebug() {
2479 $name = 'perfdebug';
2480 $visiblename = get_string('perfdebug', 'admin');
2481 $description = get_string('configperfdebug', 'admin');
2482 parent::admin_setting_configcheckbox($name, $visiblename, $description, '');
2483 }
2484
2485 function write_setting($data) {
d42c64ba 2486
6e4dc10f 2487 if ($data == '1') {
2488 return (set_config($this->name,15) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2489 } else {
2490 return (set_config($this->name,7) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2491 }
2492 }
2493
2494 function output_html() {
d42c64ba 2495
cc73de71 2496 if ($this->get_setting() === NULL) {
2497 $currentsetting = $this->defaultsetting;
2498 } else {
2499 $currentsetting = $this->get_setting();
2500 }
eef868d1 2501
3c6f7a78 2502 $return = '<input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'" name="s_'. $this->name .'" value="1" ' . ($currentsetting == 15 ? 'checked="checked"' : '') . ' />';
fc52aa6e 2503 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
6e4dc10f 2504 }
2505
2506}
2507
47b8b9eb 2508class admin_setting_special_debugdisplay extends admin_setting_configcheckbox {
2509
2510 function admin_setting_special_debugdisplay() {
2511 $name = 'debugdisplay';
2512 $visiblename = get_string('debugdisplay', 'admin');
2513 $description = get_string('configdebugdisplay', 'admin');
2514 parent::admin_setting_configcheckbox($name, $visiblename, $description, '');
2515 }
2516
2517 function write_setting($data) {
2518
2519 if ($data == '1') {
2520 return (set_config($this->name,1) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2521 } else {
2522 return (set_config($this->name,0) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2523 }
2524 }
2525
2526 function output_html() {
2527
2528 if ($this->get_setting() === NULL) {
2529 $currentsetting = ini_get('display_error');
2530 } else {
2531 $currentsetting = $this->get_setting();
2532 }
2533
2534 $return = '<input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'" name="s_'. $this->name .'" value="1" ' . ($currentsetting == 1 ? 'checked="checked"' : '') . ' />';
2535 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
2536 }
2537
2538}
2539
2540
6e4dc10f 2541// Code for a function that helps externalpages print proper headers and footers
2542// N.B.: THIS FUNCTION HANDLES AUTHENTICATION
2543function admin_externalpage_setup($section, $adminroot) {
2544
2545 global $CFG, $PAGE, $USER;
eef868d1 2546
6e4dc10f 2547 require_once($CFG->libdir . '/blocklib.php');
02cc05a7 2548 require_once($CFG->dirroot . '/'.$CFG->admin.'/pagelib.php');
eef868d1 2549
02cc05a7 2550 page_map_class(PAGE_ADMIN, 'page_admin');
6e4dc10f 2551
e9a20759 2552 $PAGE = page_create_object(PAGE_ADMIN, 0); // there must be any constant id number
6e4dc10f 2553
02cc05a7 2554 $PAGE->init_extra($section); // hack alert!
6e4dc10f 2555
2556 $root = $adminroot->locate($PAGE->section);
2557
2558 if ($site = get_site()) {
2559 require_login();
2560 } else {
6859360c 2561 redirect($CFG->wwwroot . '/'.$CFG->admin.'/index.php');
6e4dc10f 2562 die;
2563 }
2564
2565 if (!is_a($root, 'admin_externalpage')) {
2566 error(get_string('sectionerror','admin'));
2567 die;
2568 }
2569
2570 // this eliminates our need to authenticate on the actual pages
2571 if (!($root->check_access())) {
2572 error(get_string('accessdenied', 'admin'));
2573 die;
2574 }
eef868d1 2575
6e4dc10f 2576 $adminediting = optional_param('adminedit', -1, PARAM_BOOL);
eef868d1 2577
6e4dc10f 2578 if (!isset($USER->adminediting)) {
2579 $USER->adminediting = false;
2580 }
eef868d1 2581
6e4dc10f 2582 if ($PAGE->user_allowed_editing()) {
2583 if ($adminediting == 1) {
2584 $USER->adminediting = true;
2585 } elseif ($adminediting == 0) {
2586 $USER->adminediting = false;
2587 }
2588 }
eef868d1 2589
6e4dc10f 2590}
2591
2592function admin_externalpage_print_header($adminroot) {
2593
b1ce7811 2594 global $CFG, $PAGE, $SITE;
eef868d1 2595
b1ce7811 2596 if (!empty($SITE->fullname)) {
2597 $pageblocks = blocks_setup($PAGE);
6e4dc10f 2598
e524c0ed 2599 $preferred_width_left = bounded_number(BLOCK_L_MIN_WIDTH,
2600 blocks_preferred_width($pageblocks[BLOCK_POS_LEFT]),
b1ce7811 2601 BLOCK_L_MAX_WIDTH);
b1ce7811 2602 $PAGE->print_header();
5577ceb3 2603 echo '<table id="layout-table" summary=""><tr>';
b1ce7811 2604 echo '<td style="width: ' . $preferred_width_left . 'px;" id="left-column">';
2605 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT);
2606 echo '</td>';
a06c8c2c 2607 echo '<td id="middle-column">';
b1ce7811 2608 } else {
2609 print_header();
2610 }
6e4dc10f 2611}
2612
2613function admin_externalpage_print_footer($adminroot) {
2614
b1ce7811 2615 global $CFG, $PAGE, $SITE;
2616
2617 if (!empty($SITE->fullname)) {
2618 $pageblocks = blocks_setup($PAGE);
e524c0ed 2619 $preferred_width_right = bounded_number(BLOCK_R_MIN_WIDTH,
2620 blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT]),
b1ce7811 2621 BLOCK_R_MAX_WIDTH);
2622 echo '</td>';
2623 echo '<td style="width: ' . $preferred_width_right . 'px;" id="right-column">';
2624 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT);
2625 echo '</td></tr></table>';
2626 }
6e4dc10f 2627 print_footer();
6e4dc10f 2628}
2629
2630function admin_get_root() {
2631 global $CFG;
2632
2633 static $ADMIN;
2634
2635 if (!isset($ADMIN)) {
2636 // start the admin tree!
2058a0a1 2637 $ADMIN = new admin_category('root', get_string("administration"));
6e4dc10f 2638 // we process this file first to get categories up and running
6859360c 2639 include($CFG->dirroot . '/'.$CFG->admin.'/settings/top.php');
6e4dc10f 2640
2641 // now we process all other files in admin/settings to build the
2642 // admin tree
6859360c 2643 foreach (glob($CFG->dirroot . '/'.$CFG->admin.'/settings/*.php') as $file) {
2644 if ($file != $CFG->dirroot . '/'.$CFG->admin.'/settings/top.php') {
6e4dc10f 2645 include_once($file);
2646 }
2647 }
2648 }
eef868d1 2649
6e4dc10f 2650 return $ADMIN;
2651}
2652
2653/// settings utiliti functions
2654
2655// n.b. this function unconditionally applies default settings
2656function apply_default_settings(&$node) {
2657
2658 global $CFG;
2659
2660 if (is_a($node, 'admin_category')) {
2661 $entries = array_keys($node->children);
2662 foreach ($entries as $entry) {
2663 apply_default_settings($node->children[$entry]);
2664 }
2665 return;
eef868d1 2666 }
6e4dc10f 2667
eef868d1 2668 if (is_a($node, 'admin_settingpage')) {
6e4dc10f 2669 foreach ($node->settings as $setting) {
2670 $CFG->{$setting->name} = $setting->defaultsetting;
2671 $setting->write_setting($setting->defaultsetting);
2672 unset($setting); // needed to prevent odd (imho) reference behaviour
2673 // see http://www.php.net/manual/en/language.references.whatdo.php#AEN6399
2674 }
2675 return;
2676 }
2677
2678 return;
2679
2680}
2681
2682// n.b. this function unconditionally applies default settings
2683function apply_default_exception_settings($defaults) {
2684
2685 global $CFG;
2686
2687 foreach($defaults as $key => $value) {
2688 $CFG->$key = $value;
2689 set_config($key, $value);
2690 }
2691
2692}
2693
fc52aa6e 2694function format_admin_setting($name, $title='', $form='', $description='') {
6153cf58 2695 return "\n".
fc52aa6e 2696 '<div class="form-item" id="admin-'.$name.'">'."\n".
6153cf58 2697 '<label for="id_s_'.$name.'">'.$title."\n".
2698 ' <span class="form-shortname">'.$name.'</span>'."\n".
2699 '</label>'."\n".
2700 $form."\n".
edb6cba4 2701 '<div class="description">'.$description.'</div>'."\n".
23586aca 2702 '</div>'.
2703 "\n\n";
2c8766df 2704}
2705
d210e12e 2706/*
2707 * Try to upgrade the given language pack (or current language)
2708 * If it doesn't work, fail silently and return false
2709 */
2710function upgrade_language_pack($lang='') {
2711 global $CFG;
2712
2713 if (empty($lang)) {
2714 $lang = current_language();
2715 }
2716
2717 if ($lang == 'en_utf8') {
2718 return true; // Nothing to do
2719 }
2720
2721 notify(get_string('langimport', 'admin').': '.$lang.' ... ', 'notifysuccess');
2722
2723 @mkdir ($CFG->dataroot.'/temp/'); //make it in case it's a fresh install, it might not be there
2724 @mkdir ($CFG->dataroot.'/lang/');
2725
2726 require_once($CFG->libdir.'/componentlib.class.php');
2727
2728 if ($cd = new component_installer('http://download.moodle.org', 'lang16', $lang.'.zip', 'languages.md5', 'lang')) {
2729 $status = $cd->install(); //returns ERROR | UPTODATE | INSTALLED
2730
2731 if ($status == INSTALLED) {
2732 debugging('Downloading successful: '.$lang);
2733 @unlink($CFG->dataroot.'/cache/languages');
2734 return true;
2735 }
2736 }
2737
2738 return false;
2739}
2740
6153cf58 2741?>