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