MDL-12598 use user context instead of personal; merged from MOODLE_19_STABLE
[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
8ddcdd86 12function upgrade_main_savepoint($result, $version) {
13 global $CFG;
14
15 if ($result) {
16 if ($CFG->version >= $version) {
17 // something really wrong is going on in main upgrade script
18 error("Upgrade savepoint: Can not upgrade main version from $CFG->version to $version.");
19 }
20 set_config('version', $version);
21 } else {
22 notify ("Upgrade savepoint: Error during main upgrade to version $version");
23 }
24}
25
26function upgrade_mod_savepoint($result, $version, $type) {
27 //TODO
28}
29
30function upgrade_plugin_savepoint($result, $version, $type, $dir) {
31 //TODO
32}
33
34function upgrade_backup_savepoint($result, $version) {
35 //TODO
36}
37
38function upgrade_blocks_savepoint($result, $version, $type) {
39 //TODO
40}
41
88a7228a 42/**
ead29342 43 * Upgrade plugins
88a7228a 44 *
45 * @uses $db
46 * @uses $CFG
ead29342 47 * @param string $type The type of plugins that should be updated (e.g. 'enrol', 'qtype')
48 * @param string $dir The directory where the plugins are located (e.g. 'question/questiontypes')
49 * @param string $return The url to prompt the user to continue to
eef868d1 50 */
ead29342 51function upgrade_plugins($type, $dir, $return) {
e69ef14b 52 global $CFG, $db;
173cc1c3 53
15999a93 54/// Let's know if the header has been printed, so the funcion is being called embedded in an outer page
55 $embedded = defined('HEADER_PRINTED');
56
bb7053f3 57 $plugs = get_list_of_plugins($dir);
583fad99 58 $updated_plugins = false;
59 $strpluginsetup = get_string('pluginsetup');
60
ead29342 61 foreach ($plugs as $plug) {
173cc1c3 62
ead29342 63 $fullplug = $CFG->dirroot .'/'.$dir.'/'. $plug;
173cc1c3 64
ead29342 65 unset($plugin);
173cc1c3 66
bbbf2d40 67 if (is_readable($fullplug .'/version.php')) {
ead29342 68 include_once($fullplug .'/version.php'); // defines $plugin with version etc
173cc1c3 69 } else {
70 continue; // Nothing to do.
71 }
72
e79a09a2 73 $oldupgrade = false;
74 $newupgrade = false;
7c006e34 75 if (is_readable($fullplug . '/db/'. $CFG->dbtype . '.php')) {
76 include_once($fullplug . '/db/'. $CFG->dbtype . '.php'); // defines old upgrading function
e79a09a2 77 $oldupgrade = true;
78 }
db8bd7a6 79 if (is_readable($fullplug . '/db/upgrade.php')) {
7c006e34 80 include_once($fullplug . '/db/upgrade.php'); // defines new upgrading function
e79a09a2 81 $newupgrade = true;
82 }
83
ead29342 84 if (!isset($plugin)) {
173cc1c3 85 continue;
86 }
87
ead29342 88 if (!empty($plugin->requires)) {
89 if ($plugin->requires > $CFG->version) {
acdd790f 90 $info = new object();
ead29342 91 $info->pluginname = $plug;
92 $info->pluginversion = $plugin->version;
173cc1c3 93 $info->currentmoodle = $CFG->version;
ead29342 94 $info->requiremoodle = $plugin->requires;
15999a93 95 if (!$updated_plugins && !$embedded) {
0be6f678 96 print_header($strpluginsetup, $strpluginsetup,
97 build_navigation(array(array('name' => $strpluginsetup, 'link' => null, 'type' => 'misc'))), '',
371a32e3 98 upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
583fad99 99 }
100 upgrade_log_start();
ead29342 101 notify(get_string('pluginrequirementsnotmet', 'error', $info));
583fad99 102 $updated_plugins = true;
173cc1c3 103 continue;
104 }
105 }
106
ead29342 107 $plugin->name = $plug; // The name MUST match the directory
173cc1c3 108
ead29342 109 $pluginversion = $type.'_'.$plug.'_version';
173cc1c3 110
ead29342 111 if (!isset($CFG->$pluginversion)) {
112 set_config($pluginversion, 0);
173cc1c3 113 }
eef868d1 114
ead29342 115 if ($CFG->$pluginversion == $plugin->version) {
173cc1c3 116 // do nothing
ead29342 117 } else if ($CFG->$pluginversion < $plugin->version) {
15999a93 118 if (!$updated_plugins && !$embedded) {
0be6f678 119 print_header($strpluginsetup, $strpluginsetup,
120 build_navigation(array(array('name' => $strpluginsetup, 'link' => null, 'type' => 'misc'))), '',
371a32e3 121 upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
173cc1c3 122 }
e79a09a2 123 $updated_plugins = true;
583fad99 124 upgrade_log_start();
05b42119 125 print_heading($dir.'/'. $plugin->name .' plugin needs upgrading');
e79a09a2 126 $db->debug = true;
127 @set_time_limit(0); // To allow slow databases to complete the long SQL
128
d87a9d73 129 if ($CFG->$pluginversion == 0) { // It's a new install of this plugin
e79a09a2 130 /// Both old .sql files and new install.xml are supported
131 /// but we priorize install.xml (XMLDB) if present
132 $status = false;
db8bd7a6 133 if (file_exists($fullplug . '/db/install.xml')) {
450cf307 134 $status = install_from_xmldb_file($fullplug . '/db/install.xml'); //New method
e79a09a2 135 } else if (file_exists($fullplug .'/db/'. $CFG->dbtype .'.sql')) {
136 $status = modify_database($fullplug .'/db/'. $CFG->dbtype .'.sql'); //Old method
eef868d1 137 } else {
7c006e34 138 $status = true;
d87a9d73 139 }
e79a09a2 140
141 $db->debug = false;
eef868d1 142 /// Continue with the instalation, roles and other stuff
e79a09a2 143 if ($status) {
3f59a54e 144 /// OK so far, now update the plugins record
e79a09a2 145 set_config($pluginversion, $plugin->version);
3f59a54e 146
147 /// Install capabilities
ae628043 148 if (!update_capabilities($type.'/'.$plug)) {
3f59a54e 149 error('Could not set up the capabilities for '.$plugin->name.'!');
e79a09a2 150 }
3f59a54e 151 /// Install events
0856223c 152 events_update_definition($type.'/'.$plug);
3f59a54e 153
154 /// Run local install function if there is one
155 if (is_readable($fullplug .'/lib.php')) {
9ba38673 156 include_once($fullplug .'/lib.php');
3f59a54e 157 $installfunction = $plugin->name.'_install';
158 if (function_exists($installfunction)) {
159 if (! $installfunction() ) {
160 notify('Encountered a problem running install function for '.$module->name.'!');
161 }
162 }
163 }
9ba38673 164
e79a09a2 165 notify(get_string('modulesuccess', '', $plugin->name), 'notifysuccess');
166 } else {
167 notify('Installing '. $plugin->name .' FAILED!');
168 }
d87a9d73 169 } else { // Upgrade existing install
e79a09a2 170 /// Run de old and new upgrade functions for the module
171 $oldupgrade_function = $type.'_'.$plugin->name .'_upgrade';
172 $newupgrade_function = 'xmldb_' . $type.'_'.$plugin->name .'_upgrade';
173
174 /// First, the old function if exists
175 $oldupgrade_status = true;
176 if ($oldupgrade && function_exists($oldupgrade_function)) {
177 $db->debug = true;
178 $oldupgrade_status = $oldupgrade_function($CFG->$pluginversion);
179 } else if ($oldupgrade) {
180 notify ('Upgrade function ' . $oldupgrade_function . ' was not available in ' .
181 $fullplug . '/db/' . $CFG->dbtype . '.php');
182 }
183
184 /// Then, the new function if exists and the old one was ok
185 $newupgrade_status = true;
186 if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) {
187 $db->debug = true;
188 $newupgrade_status = $newupgrade_function($CFG->$pluginversion);
189 } else if ($newupgrade) {
190 notify ('Upgrade function ' . $newupgrade_function . ' was not available in ' .
191 $fullplug . '/db/upgrade.php');
192 }
193
194 $db->debug=false;
195 /// Now analyze upgrade results
196 if ($oldupgrade_status && $newupgrade_status) { // No upgrading failed
197 // OK so far, now update the plugins record
198 set_config($pluginversion, $plugin->version);
ae628043 199 if (!update_capabilities($type.'/'.$plug)) {
e79a09a2 200 error('Could not update '.$plugin->name.' capabilities!');
d87a9d73 201 }
0856223c 202 events_update_definition($type.'/'.$plug);
e79a09a2 203 notify(get_string('modulesuccess', '', $plugin->name), 'notifysuccess');
204 } else {
205 notify('Upgrading '. $plugin->name .' from '. $CFG->$pluginversion .' to '. $plugin->version .' FAILED!');
173cc1c3 206 }
207 }
d87a9d73 208 echo '<hr />';
173cc1c3 209 } else {
583fad99 210 upgrade_log_start();
ead29342 211 error('Version mismatch: '. $plugin->name .' can\'t downgrade '. $CFG->$pluginversion .' -> '. $plugin->version .' !');
173cc1c3 212 }
213 }
214
583fad99 215 upgrade_log_finish();
216
15999a93 217 if ($updated_plugins && !$embedded) {
173cc1c3 218 print_continue($return);
acdd790f 219 print_footer('none');
173cc1c3 220 die;
221 }
222}
223
88a7228a 224/**
225 * Find and check all modules and load them up or upgrade them if necessary
226 *
227 * @uses $db
228 * @uses $CFG
229 * @param string $return The url to prompt the user to continue to
230 * @todo Finish documenting this function
eef868d1 231 */
173cc1c3 232function upgrade_activity_modules($return) {
173cc1c3 233
e69ef14b 234 global $CFG, $db;
173cc1c3 235
88a7228a 236 if (!$mods = get_list_of_plugins('mod') ) {
237 error('No modules installed!');
173cc1c3 238 }
239
583fad99 240 $updated_modules = false;
241 $strmodulesetup = get_string('modulesetup');
242
173cc1c3 243 foreach ($mods as $mod) {
244
88a7228a 245 if ($mod == 'NEWMODULE') { // Someone has unzipped the template, ignore it
173cc1c3 246 continue;
247 }
248
88a7228a 249 $fullmod = $CFG->dirroot .'/mod/'. $mod;
173cc1c3 250
251 unset($module);
252
88a7228a 253 if ( is_readable($fullmod .'/version.php')) {
254 include_once($fullmod .'/version.php'); // defines $module with version etc
173cc1c3 255 } else {
88a7228a 256 notify('Module '. $mod .': '. $fullmod .'/version.php was not readable');
173cc1c3 257 continue;
258 }
259
d6eb06b6 260 $oldupgrade = false;
261 $newupgrade = false;
7c006e34 262 if ( is_readable($fullmod .'/db/' . $CFG->dbtype . '.php')) {
263 include_once($fullmod .'/db/' . $CFG->dbtype . '.php'); // defines old upgrading function
d6eb06b6 264 $oldupgrade = true;
265 }
db8bd7a6 266 if ( is_readable($fullmod . '/db/upgrade.php')) {
7c006e34 267 include_once($fullmod . '/db/upgrade.php'); // defines new upgrading function
d6eb06b6 268 $newupgrade = true;
173cc1c3 269 }
270
271 if (!isset($module)) {
272 continue;
273 }
274
275 if (!empty($module->requires)) {
276 if ($module->requires > $CFG->version) {
acdd790f 277 $info = new object();
173cc1c3 278 $info->modulename = $mod;
279 $info->moduleversion = $module->version;
280 $info->currentmoodle = $CFG->version;
281 $info->requiremoodle = $module->requires;
583fad99 282 if (!$updated_modules) {
0be6f678 283 print_header($strmodulesetup, $strmodulesetup,
284 build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '',
371a32e3 285 upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
583fad99 286 }
287 upgrade_log_start();
173cc1c3 288 notify(get_string('modulerequirementsnotmet', 'error', $info));
583fad99 289 $updated_modules = true;
173cc1c3 290 continue;
291 }
292 }
293
294 $module->name = $mod; // The name MUST match the directory
eef868d1 295
11e4a24b 296 include_once($fullmod.'/lib.php'); // defines upgrading and/or installing functions
297
88a7228a 298 if ($currmodule = get_record('modules', 'name', $module->name)) {
173cc1c3 299 if ($currmodule->version == $module->version) {
300 // do nothing
301 } else if ($currmodule->version < $module->version) {
d6eb06b6 302 /// If versions say that we need to upgrade but no upgrade files are available, notify and continue
303 if (!$oldupgrade && !$newupgrade) {
304 notify('Upgrade files ' . $mod . ': ' . $fullmod . '/db/' . $CFG->dbtype . '.php or ' .
305 $fullmod . '/db/upgrade.php were not readable');
306 continue;
307 }
583fad99 308 if (!$updated_modules) {
0be6f678 309 print_header($strmodulesetup, $strmodulesetup,
310 build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '',
371a32e3 311 upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
173cc1c3 312 }
583fad99 313 upgrade_log_start();
88a7228a 314 print_heading($module->name .' module needs upgrading');
d6eb06b6 315
316 /// Run de old and new upgrade functions for the module
317 $oldupgrade_function = $module->name . '_upgrade';
318 $newupgrade_function = 'xmldb_' . $module->name . '_upgrade';
319
320 /// First, the old function if exists
321 $oldupgrade_status = true;
322 if ($oldupgrade && function_exists($oldupgrade_function)) {
323 $db->debug = true;
324 $oldupgrade_status = $oldupgrade_function($currmodule->version, $module);
8bc9ebc4 325 if (!$oldupgrade_status) {
326 notify ('Upgrade function ' . $oldupgrade_function .
327 ' did not complete successfully.');
328 }
ba05965e 329 } else if ($oldupgrade) {
d6eb06b6 330 notify ('Upgrade function ' . $oldupgrade_function . ' was not available in ' .
331 $mod . ': ' . $fullmod . '/db/' . $CFG->dbtype . '.php');
d6eb06b6 332 }
333
334 /// Then, the new function if exists and the old one was ok
335 $newupgrade_status = true;
ba05965e 336 if ($newupgrade && function_exists($newupgrade_function) && $oldupgrade_status) {
d6eb06b6 337 $db->debug = true;
338 $newupgrade_status = $newupgrade_function($currmodule->version, $module);
8bc9ebc4 339 } else if ($newupgrade && $oldupgrade_status) {
d6eb06b6 340 notify ('Upgrade function ' . $newupgrade_function . ' was not available in ' .
341 $mod . ': ' . $fullmod . '/db/upgrade.php');
d6eb06b6 342 }
343
e79a09a2 344 $db->debug=false;
d6eb06b6 345 /// Now analyze upgrade results
668896e5 346 if ($oldupgrade_status && $newupgrade_status) { // No upgrading failed
d6eb06b6 347 // OK so far, now update the modules record
348 $module->id = $currmodule->id;
349 if (! update_record('modules', $module)) {
350 error('Could not update '. $module->name .' record in modules table!');
173cc1c3 351 }
d6eb06b6 352 remove_dir($CFG->dataroot . '/cache', true); // flush cache
353 notify(get_string('modulesuccess', '', $module->name), 'notifysuccess');
354 echo '<hr />';
355 } else {
d6eb06b6 356 notify('Upgrading '. $module->name .' from '. $currmodule->version .' to '. $module->version .' FAILED!');
173cc1c3 357 }
bbbf2d40 358
d6eb06b6 359 /// Update the capabilities table?
bbbf2d40 360 if (!update_capabilities('mod/'.$module->name)) {
361 error('Could not update '.$module->name.' capabilities!');
362 }
0856223c 363 events_update_definition('mod/'.$module->name);
bbbf2d40 364
173cc1c3 365 $updated_modules = true;
eef868d1 366
173cc1c3 367 } else {
583fad99 368 upgrade_log_start();
88a7228a 369 error('Version mismatch: '. $module->name .' can\'t downgrade '. $currmodule->version .' -> '. $module->version .' !');
173cc1c3 370 }
eef868d1 371
173cc1c3 372 } else { // module not installed yet, so install it
583fad99 373 if (!$updated_modules) {
0be6f678 374 print_header($strmodulesetup, $strmodulesetup,
375 build_navigation(array(array('name' => $strmodulesetup, 'link' => null, 'type' => 'misc'))), '',
371a32e3 376 upgrade_get_javascript(), false, '&nbsp;', '&nbsp;');
173cc1c3 377 }
583fad99 378 upgrade_log_start();
173cc1c3 379 print_heading($module->name);
380 $updated_modules = true;
381 $db->debug = true;
382 @set_time_limit(0); // To allow slow databases to complete the long SQL
d6eb06b6 383
384 /// Both old .sql files and new install.xml are supported
385 /// but we priorize install.xml (XMLDB) if present
db8bd7a6 386 if (file_exists($fullmod . '/db/install.xml')) {
d6eb06b6 387 $status = install_from_xmldb_file($fullmod . '/db/install.xml'); //New method
388 } else {
389 $status = modify_database($fullmod .'/db/'. $CFG->dbtype .'.sql'); //Old method
390 }
391
e79a09a2 392 $db->debug = false;
11e4a24b 393
394 /// Continue with the installation, roles and other stuff
d6eb06b6 395 if ($status) {
88a7228a 396 if ($module->id = insert_record('modules', $module)) {
11e4a24b 397
9ba38673 398 /// Capabilities
bbbf2d40 399 if (!update_capabilities('mod/'.$module->name)) {
400 error('Could not set up the capabilities for '.$module->name.'!');
401 }
9ba38673 402
11e4a24b 403 /// Events
0856223c 404 events_update_definition('mod/'.$module->name);
11e4a24b 405
406 /// Run local install function if there is one
407 $installfunction = $module->name.'_install';
408 if (function_exists($installfunction)) {
409 if (! $installfunction() ) {
410 notify('Encountered a problem running install function for '.$module->name.'!');
411 }
412 }
413
a8f68426 414 notify(get_string('modulesuccess', '', $module->name), 'notifysuccess');
88a7228a 415 echo '<hr />';
173cc1c3 416 } else {
88a7228a 417 error($module->name .' module could not be added to the module list!');
173cc1c3 418 }
eef868d1 419 } else {
88a7228a 420 error($module->name .' tables could NOT be set up successfully!');
173cc1c3 421 }
422 }
e5bd4e58 423
424 /// Check submodules of this module if necessary
425
e5bd4e58 426 $submoduleupgrade = $module->name.'_upgrade_submodules';
427 if (function_exists($submoduleupgrade)) {
428 $submoduleupgrade();
429 }
430
431
432 /// Run any defaults or final code that is necessary for this module
433
a5c0990e 434 if ( is_readable($fullmod .'/defaults.php')) {
435 // Insert default values for any important configuration variables
9e6e7502 436 unset($defaults);
eef868d1 437 include_once($fullmod .'/defaults.php');
f9a2e515 438 if (!empty($defaults)) {
439 foreach ($defaults as $name => $value) {
440 if (!isset($CFG->$name)) {
441 set_config($name, $value);
442 }
a5c0990e 443 }
444 }
445 }
173cc1c3 446 }
447
583fad99 448 upgrade_log_finish(); // finish logging if started
449
450 if ($updated_modules) {
173cc1c3 451 print_continue($return);
acdd790f 452 print_footer('none');
173cc1c3 453 die;
454 }
455}
456
eef868d1 457/**
f3221af9 458 * This function will return FALSE if the lock fails to be set (ie, if it's already locked)
80be7ee3 459 *
460 * @param string $name ?
461 * @param bool $value ?
462 * @param int $staleafter ?
463 * @param bool $clobberstale ?
464 * @todo Finish documenting this function
f3221af9 465 */
466function set_cron_lock($name,$value=true,$staleafter=7200,$clobberstale=false) {
467
468 if (empty($name)) {
469 mtrace("Tried to get a cron lock for a null fieldname");
470 return false;
471 }
472
473 if (empty($value)) {
474 set_config($name,0);
475 return true;
476 }
477
478 if ($config = get_record('config','name',$name)) {
479 if (empty($config->value)) {
480 set_config($name,time());
481 } else {
482 // check for stale.
483 if ((time() - $staleafter) > $config->value) {
484 mtrace("STALE LOCKFILE FOR $name - was $config->value");
485 if (!empty($clobberstale)) {
486 set_config($name,time());
487 return true;
488 }
489 } else {
490 return false; // was not stale - ie, we're ok to still be running.
491 }
492 }
493 }
494 else {
495 set_config($name,time());
496 }
497 return true;
498}
a597f8a8 499
fb06b255 500function print_progress($done, $total, $updatetime=5, $sleeptime=1, $donetext='') {
a597f8a8 501 static $starttime;
502 static $lasttime;
503
26ea4888 504 if ($total < 2) { // No need to show anything
505 return;
506 }
507
a597f8a8 508 if (empty($starttime)) {
509 $starttime = $lasttime = time();
510 $lasttime = $starttime - $updatetime;
511 echo '<table width="500" cellpadding="0" cellspacing="0" align="center"><tr><td width="500">';
72da5046 512 echo '<div id="bar'.$total.'" style="border-style:solid;border-width:1px;width:500px;height:50px;">';
513 echo '<div id="slider'.$total.'" style="border-style:solid;border-width:1px;height:48px;width:10px;background-color:green;"></div>';
a597f8a8 514 echo '</div>';
72da5046 515 echo '<div id="text'.$total.'" align="center" style="width:500px;"></div>';
a597f8a8 516 echo '</td></tr></table>';
517 echo '</div>';
518 }
519
a597f8a8 520 $now = time();
521
522 if ($done && (($now - $lasttime) >= $updatetime)) {
523 $elapsedtime = $now - $starttime;
524 $projectedtime = (int)(((float)$total / (float)$done) * $elapsedtime) - $elapsedtime;
76317c73 525 $percentage = round((float)$done / (float)$total, 2);
a597f8a8 526 $width = (int)(500 * $percentage);
527
fb06b255 528 if ($projectedtime > 10) {
529 $projectedtext = ' Ending: '.format_time($projectedtime);
530 } else {
531 $projectedtext = '';
532 }
533
a597f8a8 534 echo '<script>';
aae37b63 535 echo 'document.getElementById("text'.$total.'").innerHTML = "'.addslashes($donetext).' ('.$done.'/'.$total.') '.$projectedtext.'";'."\n";
536 echo 'document.getElementById("slider'.$total.'").style.width = \''.$width.'px\';'."\n";
a597f8a8 537 echo '</script>';
538
539 $lasttime = $now;
540 sleep($sleeptime);
541 }
542}
583fad99 543
371a32e3 544function upgrade_get_javascript() {
545 global $CFG;
546
547 if (!empty($_SESSION['installautopilot'])) {
548 $linktoscrolltoerrors = '<script type="text/javascript">var installautopilot = true;</script>'."\n";
549 } else {
550 $linktoscrolltoerrors = '<script type="text/javascript">var installautopilot = false;</script>'."\n";
551 }
552 $linktoscrolltoerrors .= '<script type="text/javascript" src="' . $CFG->wwwroot . '/lib/scroll_to_errors.js"></script>';
553
554 return $linktoscrolltoerrors;
555}
ad6226fb 556
557function create_admin_user() {
558 global $CFG, $USER;
559
560 if (empty($CFG->rolesactive)) { // No admin user yet.
561
562 $user = new object();
563 $user->auth = 'manual';
564 $user->firstname = get_string('admin');
565 $user->lastname = get_string('user');
566 $user->username = 'admin';
567 $user->password = hash_internal_user_password('admin');
568 $user->email = 'root@localhost';
569 $user->confirmed = 1;
570 $user->mnethostid = $CFG->mnet_localhost_id;
571 $user->lang = $CFG->lang;
572 $user->maildisplay = 1;
573 $user->timemodified = time();
574
575 if (!$user->id = insert_record('user', $user)) {
576 error('SERIOUS ERROR: Could not create admin user record !!!');
577 }
578
579 if (!$user = get_record('user', 'id', $user->id)) { // Double check.
580 error('User ID was incorrect (can\'t find it)');
581 }
582
583 // Assign the default admin roles to the new user.
584 if (!$adminroles = get_roles_with_capability('moodle/legacy:admin', CAP_ALLOW)) {
585 error('No admin role could be found');
586 }
84c8ede0 587 $sitecontext = get_context_instance(CONTEXT_SYSTEM);
ad6226fb 588 foreach ($adminroles as $adminrole) {
589 role_assign($adminrole->id, $user->id, 0, $sitecontext->id);
590 }
591
592 set_config('rolesactive', 1);
593
594 // Log the user in.
595 $USER = get_complete_user_data('username', 'admin');
596 $USER->newadminuser = 1;
597 load_all_capabilities();
598
599 redirect("$CFG->wwwroot/user/editadvanced.php?id=$user->id"); // Edit thyself
600 } else {
601 error('Can not create admin!');
602 }
603}
604
583fad99 605////////////////////////////////////////////////
606/// upgrade logging functions
607////////////////////////////////////////////////
608
609$upgradeloghandle = false;
26c91c73 610$upgradelogbuffer = '';
611// I did not find out how to use static variable in callback function,
612// the problem was that I could not flush the static buffer :-(
613global $upgradeloghandle, $upgradelogbuffer;
583fad99 614
615/**
616 * Check if upgrade is already running.
617 *
618 * If anything goes wrong due to missing call to upgrade_log_finish()
619 * just restart the browser.
620 *
621 * @param string warning message indicating upgrade is already running
622 * @param int page reload timeout
623 */
624function upgrade_check_running($message, $timeout) {
625 if (!empty($_SESSION['upgraderunning'])) {
626 print_header();
627 redirect(me(), $message, $timeout);
628 }
629}
630
631/**
632 * Start logging of output into file (if not disabled) and
633 * prevent aborting and concurrent execution of upgrade script.
634 *
635 * Please note that you can not write into session variables after calling this function!
636 *
637 * This function may be called repeatedly.
638 */
639function upgrade_log_start() {
426a369b 640 global $CFG, $upgradeloghandle;
583fad99 641
642 if (!empty($_SESSION['upgraderunning'])) {
643 return; // logging already started
644 }
645
646 @ignore_user_abort(true); // ignore if user stops or otherwise aborts page loading
647 $_SESSION['upgraderunning'] = 1; // set upgrade indicator
426a369b 648 if (empty($CFG->dbsessions)) { // workaround for bug in adodb, db session can not be restarted
649 session_write_close(); // from now on user can reload page - will be displayed warning
650 }
583fad99 651 make_upload_directory('upgradelogs');
652 ob_start('upgrade_log_callback', 2); // function for logging to disk; flush each line of text ASAP
dedb2304 653 register_shutdown_function('upgrade_log_finish'); // in case somebody forgets to stop logging
583fad99 654}
655
656/**
657 * Terminate logging of output, flush all data, allow script aborting
658 * and reopen session for writing. Function error() does terminate the logging too.
659 *
660 * Please make sure that each upgrade_log_start() is properly terminated by
661 * this function or error().
662 *
663 * This function may be called repeatedly.
664 */
665function upgrade_log_finish() {
426a369b 666 global $CFG, $upgradeloghandle, $upgradelogbuffer;
583fad99 667
668 if (empty($_SESSION['upgraderunning'])) {
669 return; // logging already terminated
670 }
671
672 @ob_end_flush();
26c91c73 673 if ($upgradelogbuffer !== '') {
674 @fwrite($upgradeloghandle, $upgradelogbuffer);
40896537 675 $upgradelogbuffer = '';
26c91c73 676 }
677 if ($upgradeloghandle and ($upgradeloghandle !== 'error')) {
678 @fclose($upgradeloghandle);
40896537 679 $upgradeloghandle = false;
26c91c73 680 }
426a369b 681 if (empty($CFG->dbsessions)) {
682 @session_start(); // ignore header errors, we only need to reopen session
683 }
583fad99 684 $_SESSION['upgraderunning'] = 0; // clear upgrade indicator
685 if (connection_aborted()) {
686 die;
687 }
688 @ignore_user_abort(false);
689}
690
691/**
692 * Callback function for logging into files. Not more than one file is created per minute,
693 * upgrade session (terminated by upgrade_log_finish()) is always stored in one file.
694 *
695 * This function must not output any characters or throw warnigns and errors!
696 */
697function upgrade_log_callback($string) {
26c91c73 698 global $CFG, $upgradeloghandle, $upgradelogbuffer;
583fad99 699
700 if (empty($CFG->disableupgradelogging) and ($string != '') and ($upgradeloghandle !== 'error')) {
701 if ($upgradeloghandle or ($upgradeloghandle = @fopen($CFG->dataroot.'/upgradelogs/upg_'.date('Ymd-Hi').'.html', 'a'))) {
26c91c73 702 $upgradelogbuffer .= $string;
703 if (strlen($upgradelogbuffer) > 2048) { // 2kB write buffer
704 @fwrite($upgradeloghandle, $upgradelogbuffer);
705 $upgradelogbuffer = '';
706 }
583fad99 707 } else {
708 $upgradeloghandle = 'error';
709 }
710 }
711 return $string;
712}
713
57e35f32 714/**
715 * Try to verify that dataroot is not accessible from web.
716 * It is not 100% correct but might help to reduce number of vulnerable sites.
717 *
718 * Protection from httpd.conf and .htaccess is not detected properly.
719 */
720function is_dataroot_insecure() {
721 global $CFG;
722
723 $siteroot = str_replace('\\', '/', strrev($CFG->dirroot.'/')); // win32 backslash workaround
724
725 $rp = preg_replace('|https?://[^/]+|i', '', $CFG->wwwroot, 1);
726 $rp = strrev(trim($rp, '/'));
727 $rp = explode('/', $rp);
728 foreach($rp as $r) {
729 if (strpos($siteroot, '/'.$r.'/') === 0) {
730 $siteroot = substr($siteroot, strlen($r)+1); // moodle web in subdirectory
731 } else {
732 break; // probably alias root
733 }
734 }
735
736 $siteroot = strrev($siteroot);
737 $dataroot = str_replace('\\', '/', $CFG->dataroot.'/');
738
739 if (strpos($dataroot, $siteroot) === 0) {
740 return true;
741 }
742 return false;
743}
6e4dc10f 744
745/// =============================================================================================================
746/// administration tree classes and functions
747
748
749// n.b. documentation is still in progress for this code
750
751/// INTRODUCTION
752
753/// This file performs the following tasks:
754/// -it defines the necessary objects and interfaces to build the Moodle
755/// admin hierarchy
eef868d1 756/// -it defines the admin_externalpage_setup(), admin_externalpage_print_header(),
6e4dc10f 757/// and admin_externalpage_print_footer() functions used on admin pages
758
759/// ADMIN_SETTING OBJECTS
760
eef868d1 761/// Moodle settings are represented by objects that inherit from the admin_setting
6e4dc10f 762/// class. These objects encapsulate how to read a setting, how to write a new value
763/// to a setting, and how to appropriately display the HTML to modify the setting.
764
765/// ADMIN_SETTINGPAGE OBJECTS
766
767/// The admin_setting objects are then grouped into admin_settingpages. The latter
768/// appear in the Moodle admin tree block. All interaction with admin_settingpage
769/// objects is handled by the admin/settings.php file.
770
771/// ADMIN_EXTERNALPAGE OBJECTS
772
773/// There are some settings in Moodle that are too complex to (efficiently) handle
774/// with admin_settingpages. (Consider, for example, user management and displaying
775/// lists of users.) In this case, we use the admin_externalpage object. This object
776/// places a link to an external PHP file in the admin tree block.
777
778/// If you're using an admin_externalpage object for some settings, you can take
779/// advantage of the admin_externalpage_* functions. For example, suppose you wanted
780/// to add a foo.php file into admin. First off, you add the following line to
781/// admin/settings/first.php (at the end of the file) or to some other file in
782/// admin/settings:
783
eef868d1 784/// $ADMIN->add('userinterface', new admin_externalpage('foo', get_string('foo'),
6e4dc10f 785/// $CFG->wwwdir . '/' . '$CFG->admin . '/foo.php', 'some_role_permission'));
786
787/// Next, in foo.php, your file structure would resemble the following:
788
789/// require_once('.../config.php');
790/// require_once($CFG->libdir.'/adminlib.php');
1ae083e4 791/// admin_externalpage_setup('foo');
6e4dc10f 792/// // functionality like processing form submissions goes here
1ae083e4 793/// admin_externalpage_print_header();
6e4dc10f 794/// // your HTML goes here
1ae083e4 795/// admin_externalpage_print_footer();
6e4dc10f 796
797/// The admin_externalpage_setup() function call ensures the user is logged in,
798/// and makes sure that they have the proper role permission to access the page.
799
800/// The admin_externalpage_print_header() function prints the header (it figures
801/// out what category and subcategories the page is classified under) and ensures
802/// that you're using the admin pagelib (which provides the admin tree block and
803/// the admin bookmarks block).
804
805/// The admin_externalpage_print_footer() function properly closes the tables
806/// opened up by the admin_externalpage_print_header() function and prints the
807/// standard Moodle footer.
808
809/// ADMIN_CATEGORY OBJECTS
810
811/// Above and beyond all this, we have admin_category objects. These objects
812/// appear as folders in the admin tree block. They contain admin_settingpage's,
813/// admin_externalpage's, and other admin_category's.
814
815/// OTHER NOTES
816
817/// admin_settingpage's, admin_externalpage's, and admin_category's all inherit
818/// from part_of_admin_tree (a pseudointerface). This interface insists that
819/// a class has a check_access method for access permissions, a locate method
820/// used to find a specific node in the admin tree, and a path method used
821/// to determine the path to a specific node in the $ADMIN tree.
822
823/// admin_category's inherit from parentable_part_of_admin_tree. This pseudo-
824/// interface ensures that the class implements a recursive add function which
825/// accepts a part_of_admin_tree object and searches for the proper place to
826/// put it. parentable_part_of_admin_tree implies part_of_admin_tree.
827
828/// Please note that the $this->name field of any part_of_admin_tree must be
829/// UNIQUE throughout the ENTIRE admin tree.
830
831/// The $this->name field of an admin_setting object (which is *not* part_of_
832/// admin_tree) must be unique on the respective admin_settingpage where it is
833/// used.
834
835
836/// MISCELLANEOUS STUFF (used by classes defined below) ///////////////////////
837include_once($CFG->dirroot . '/backup/lib.php');
838
839/// CLASS DEFINITIONS /////////////////////////////////////////////////////////
840
841/**
842 * Pseudointerface for anything appearing in the admin tree
843 *
844 * The pseudointerface that is implemented by anything that appears in the admin tree
845 * block. It forces inheriting classes to define a method for checking user permissions
846 * and methods for finding something in the admin tree.
847 *
848 * @author Vincenzo K. Marcovecchio
849 * @package admin
850 */
851class part_of_admin_tree {
852
853 /**
854 * Finds a named part_of_admin_tree.
855 *
856 * Used to find a part_of_admin_tree. If a class only inherits part_of_admin_tree
857 * and not parentable_part_of_admin_tree, then this function should only check if
858 * $this->name matches $name. If it does, it should return a reference to $this,
859 * otherwise, it should return a reference to NULL.
860 *
861 * If a class inherits parentable_part_of_admin_tree, this method should be called
862 * recursively on all child objects (assuming, of course, the parent object's name
863 * doesn't match the search criterion).
864 *
865 * @param string $name The internal name of the part_of_admin_tree we're searching for.
866 * @return mixed An object reference or a NULL reference.
867 */
eef868d1 868 function &locate($name) {
869 trigger_error('Admin class does not implement method <strong>locate()</strong>', E_USER_WARNING);
870 return;
6e4dc10f 871 }
4672d955 872
873 /**
874 * Removes named part_of_admin_tree.
875 *
876 * @param string $name The internal name of the part_of_admin_tree we want to remove.
a8a66c96 877 * @return bool success.
4672d955 878 */
879 function prune($name) {
eef868d1 880 trigger_error('Admin class does not implement method <strong>prune()</strong>', E_USER_WARNING);
4672d955 881 return;
eef868d1 882 }
4672d955 883
6e4dc10f 884 /**
885 * Verifies current user's access to this part_of_admin_tree.
886 *
887 * Used to check if the current user has access to this part of the admin tree or
888 * not. If a class only inherits part_of_admin_tree and not parentable_part_of_admin_tree,
889 * then this method is usually just a call to has_capability() in the site context.
890 *
891 * If a class inherits parentable_part_of_admin_tree, this method should return the
892 * logical OR of the return of check_access() on all child objects.
893 *
894 * @return bool True if the user has access, false if she doesn't.
895 */
eef868d1 896 function check_access() {
897 trigger_error('Admin class does not implement method <strong>check_access()</strong>', E_USER_WARNING);
898 return;
6e4dc10f 899 }
eef868d1 900
a8a66c96 901 /**
902 * Mostly usefull for removing of some parts of the tree in admin tree block.
903 *
904 * @return True is hidden from normal list view
905 */
906 function is_hidden() {
907 trigger_error('Admin class does not implement method <strong>is_hidden()</strong>', E_USER_WARNING);
908 return;
909 }
910
6e4dc10f 911 /**
912 * Determines the path to $name in the admin tree.
913 *
914 * Used to determine the path to $name in the admin tree. If a class inherits only
915 * part_of_admin_tree and not parentable_part_of_admin_tree, then this method should
916 * check if $this->name matches $name. If it does, $name is pushed onto the $path
917 * array (at the end), and $path should be returned. If it doesn't, NULL should be
918 * returned.
919 *
920 * If a class inherits parentable_part_of_admin_tree, it should do the above, but not
921 * return NULL on failure. Instead, it pushes $this->name onto $path, and then
922 * recursively calls path() on its child objects. If any are non-NULL, it should
923 * return $path (being certain that the last element of $path is equal to $name).
924 * If they are all NULL, it returns NULL.
925 *
926 * @param string $name The internal name of the part_of_admin_tree we're searching for.
927 * @param array $path Not used on external calls. Defaults to empty array.
928 * @return mixed If found, an array containing the internal names of each part_of_admin_tree that leads to $name. If not found, NULL.
929 */
eef868d1 930 function path($name, $path = array()) {
931 trigger_error('Admin class does not implement method <strong>path()</strong>', E_USER_WARNING);
932 return;
6e4dc10f 933 }
934}
935
936/**
937 * Pseudointerface implemented by any part_of_admin_tree that has children.
938 *
939 * The pseudointerface implemented by any part_of_admin_tree that can be a parent
940 * to other part_of_admin_tree's. (For now, this only includes admin_category.) Apart
eef868d1 941 * from ensuring part_of_admin_tree compliancy, it also ensures inheriting methods
6e4dc10f 942 * include an add method for adding other part_of_admin_tree objects as children.
943 *
944 * @author Vincenzo K. Marcovecchio
945 * @package admin
946 */
947class parentable_part_of_admin_tree extends part_of_admin_tree {
eef868d1 948
6e4dc10f 949 /**
950 * Adds a part_of_admin_tree object to the admin tree.
951 *
952 * Used to add a part_of_admin_tree object to this object or a child of this
953 * object. $something should only be added if $destinationname matches
954 * $this->name. If it doesn't, add should be called on child objects that are
955 * also parentable_part_of_admin_tree's.
956 *
957 * @param string $destinationname The internal name of the new parent for $something.
958 * @param part_of_admin_tree &$something The object to be added.
959 * @return bool True on success, false on failure.
960 */
eef868d1 961 function add($destinationname, &$something) {
962 trigger_error('Admin class does not implement method <strong>add()</strong>', E_USER_WARNING);
963 return;
6e4dc10f 964 }
eef868d1 965
6e4dc10f 966}
967
968/**
969 * The object used to represent folders (a.k.a. categories) in the admin tree block.
eef868d1 970 *
6e4dc10f 971 * Each admin_category object contains a number of part_of_admin_tree objects.
972 *
973 * @author Vincenzo K. Marcovecchio
974 * @package admin
975 */
976class admin_category extends parentable_part_of_admin_tree {
977
978 /**
979 * @var mixed An array of part_of_admin_tree objects that are this object's children
980 */
981 var $children;
eef868d1 982
6e4dc10f 983 /**
984 * @var string An internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
985 */
986 var $name;
eef868d1 987
6e4dc10f 988 /**
989 * @var string The displayed name for this category. Usually obtained through get_string()
990 */
991 var $visiblename;
eef868d1 992
a8a66c96 993 /**
994 * @var bool Should this category be hidden in admin tree block?
995 */
996 var $hidden;
997
6e4dc10f 998 // constructor for an empty admin category
999 // $name is the internal name of the category. it MUST be unique in the entire hierarchy
1000 // $visiblename is the displayed name of the category. use a get_string for this
1001
1002 /**
1003 * Constructor for an empty admin category
1004 *
1005 * @param string $name The internal name for this category. Must be unique amongst ALL part_of_admin_tree objects
1006 * @param string $visiblename The displayed named for this category. Usually obtained through get_string()
a8a66c96 1007 * @param bool $hidden hide category in admin tree block
6e4dc10f 1008 * @return mixed Returns the new object.
1009 */
a8a66c96 1010 function admin_category($name, $visiblename, $hidden = false) {
6e4dc10f 1011 $this->children = array();
1012 $this->name = $name;
1013 $this->visiblename = $visiblename;
a8a66c96 1014 $this->hidden = $hidden;
6e4dc10f 1015 }
eef868d1 1016
6e4dc10f 1017 /**
1018 * Finds the path to the part_of_admin_tree called $name.
1019 *
1020 * @param string $name The internal name that we're searching for.
1021 * @param array $path Used internally for recursive calls. Do not specify on external calls. Defaults to array().
1022 * @return mixed An array of internal names that leads to $name, or NULL if not found.
1023 */
1024 function path($name, $path = array()) {
eef868d1 1025
6e4dc10f 1026 $path[count($path)] = $this->name;
eef868d1 1027
6e4dc10f 1028 if ($this->name == $name) {
1029 return $path;
1030 }
eef868d1 1031
6e4dc10f 1032 foreach($this->children as $child) {
1033 if ($return = $child->path($name, $path)) {
1034 return $return;
1035 }
1036 }
eef868d1 1037
6e4dc10f 1038 return NULL;
eef868d1 1039
6e4dc10f 1040 }
1041
1042 /**
1043 * Returns a reference to the part_of_admin_tree object with internal name $name.
1044 *
1045 * @param string $name The internal name of the object we want.
1046 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
1047 */
1048 function &locate($name) {
eef868d1 1049
6e4dc10f 1050 if ($this->name == $name) {
1051 return $this;
1052 }
eef868d1 1053
6e4dc10f 1054 foreach($this->children as $child) {
1055 if ($return =& $child->locate($name)) {
1056 return $return;
1057 }
1058 }
1059 $return = NULL;
1060 return $return;
1061 }
1062
4672d955 1063 /**
1064 * Removes part_of_admin_tree object with internal name $name.
1065 *
1066 * @param string $name The internal name of the object we want to remove.
a8a66c96 1067 * @return bool success
4672d955 1068 */
1069 function prune($name) {
1070
1071 if ($this->name == $name) {
1072 return false; //can not remove itself
1073 }
1074
1075 foreach($this->children as $precedence => $child) {
1076 if ($child->name == $name) {
1077 // found it!
eef868d1 1078 unset($this->children[$precedence]);
4672d955 1079 return true;
1080 }
1081 if ($this->children[$precedence]->prune($name)) {
1082 return true;
1083 }
1084 }
1085 return false;
1086 }
1087
6e4dc10f 1088 /**
1089 * Adds a part_of_admin_tree to a child or grandchild (or great-grandchild, and so forth) of this object.
1090 *
1091 * @param string $destinationame The internal name of the immediate parent that we want for &$something.
1092 * @param mixed &$something A part_of_admin_tree object to be added.
1093 * @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".
1094 * @return bool True if successfully added, false if &$something is not a part_of_admin_tree or if $name is not found.
1095 */
1096 function add($destinationname, &$something, $precedence = '') {
eef868d1 1097
6e4dc10f 1098 if (!is_a($something, 'part_of_admin_tree')) {
1099 return false;
1100 }
1101
1102 if ($destinationname == $this->name) {
1103 if ($precedence === '') {
1104 $this->children[] = $something;
1105 } else {
1106 if (isset($this->children[$precedence])) { // this should never, ever be triggered in a release version of moodle.
1107 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 />');
1108 }
1109 $this->children[$precedence] = $something;
1110 }
1111 return true;
1112 }
eef868d1 1113
6e4dc10f 1114 unset($entries);
eef868d1 1115
6e4dc10f 1116 $entries = array_keys($this->children);
eef868d1 1117
6e4dc10f 1118 foreach($entries as $entry) {
1119 $child =& $this->children[$entry];
1120 if (is_a($child, 'parentable_part_of_admin_tree')) {
1121 if ($child->add($destinationname, $something, $precedence)) {
1122 return true;
1123 }
1124 }
1125 }
eef868d1 1126
6e4dc10f 1127 return false;
eef868d1 1128
6e4dc10f 1129 }
eef868d1 1130
6e4dc10f 1131 /**
1132 * Checks if the user has access to anything in this category.
1133 *
1134 * @return bool True if the user has access to atleast one child in this category, false otherwise.
1135 */
1136 function check_access() {
eef868d1 1137
6e4dc10f 1138 $return = false;
1139 foreach ($this->children as $child) {
1140 $return = $return || $child->check_access();
1141 }
eef868d1 1142
6e4dc10f 1143 return $return;
eef868d1 1144
6e4dc10f 1145 }
eef868d1 1146
a8a66c96 1147 /**
1148 * Is this category hidden in admin tree block?
1149 *
1150 * @return bool True if hidden
1151 */
1152 function is_hidden() {
1153 return $this->hidden;
1154 }
6e4dc10f 1155}
1156
1157/**
1158 * Links external PHP pages into the admin tree.
1159 *
1160 * See detailed usage example at the top of this document (adminlib.php)
1161 *
1162 * @author Vincenzo K. Marcovecchio
1163 * @package admin
1164 */
1165class admin_externalpage extends part_of_admin_tree {
1166
eef868d1 1167 /**
6e4dc10f 1168 * @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects
1169 */
1170 var $name;
eef868d1 1171
6e4dc10f 1172 /**
1173 * @var string The displayed name for this external page. Usually obtained through get_string().
1174 */
1175 var $visiblename;
eef868d1 1176
6e4dc10f 1177 /**
1178 * @var string The external URL that we should link to when someone requests this external page.
1179 */
1180 var $url;
eef868d1 1181
6e4dc10f 1182 /**
1183 * @var string The role capability/permission a user must have to access this external page.
1184 */
2ce38b70 1185 var $req_capability;
eef868d1 1186
84c8ede0 1187 /**
1188 * @var object The context in which capability/permission should be checked, default is site context.
1189 */
1190 var $context;
1191
a8a66c96 1192 /**
1193 * @var bool hidden in admin tree block.
1194 */
1195 var $hidden;
1196
6e4dc10f 1197 /**
1198 * Constructor for adding an external page into the admin tree.
1199 *
1200 * @param string $name The internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects.
1201 * @param string $visiblename The displayed name for this external page. Usually obtained through get_string().
1202 * @param string $url The external URL that we should link to when someone requests this external page.
38d2d43b 1203 * @param mixed $req_capability The role capability/permission a user must have to access this external page. Defaults to 'moodle/site:config'.
6e4dc10f 1204 */
01e85af9 1205 function admin_externalpage($name, $visiblename, $url, $req_capability = 'moodle/site:config', $hidden=false, $context=NULL) {
6e4dc10f 1206 $this->name = $name;
1207 $this->visiblename = $visiblename;
1208 $this->url = $url;
38d2d43b 1209 if (is_array($req_capability)) {
1210 $this->req_capability = $req_capability;
1211 } else {
1212 $this->req_capability = array($req_capability);
1213 }
a8a66c96 1214 $this->hidden = $hidden;
84c8ede0 1215 $this->context = $context;
6e4dc10f 1216 }
eef868d1 1217
6e4dc10f 1218 /**
1219 * Finds the path to the part_of_admin_tree called $name.
1220 *
1221 * @param string $name The internal name that we're searching for.
1222 * @param array $path Used internally for recursive calls. Do not specify on external calls. Defaults to array().
1223 * @return mixed An array of internal names that leads to $name, or NULL if not found.
1224 */
1225 function path($name, $path = array()) {
1226 if ($name == $this->name) {
1227 array_push($path, $this->name);
1228 return $path;
1229 } else {
1230 return NULL;
1231 }
1232 }
eef868d1 1233
6e4dc10f 1234 /**
1235 * Returns a reference to the part_of_admin_tree object with internal name $name.
1236 *
1237 * @param string $name The internal name of the object we want.
1238 * @return mixed A reference to the object with internal name $name if found, otherwise a reference to NULL.
1239 */
1240 function &locate($name) {
1241 $return = ($this->name == $name ? $this : NULL);
1242 return $return;
1243 }
4672d955 1244
1245 function prune($name) {
1246 return false;
1247 }
1248
6e4dc10f 1249 /**
2ce38b70 1250 * Determines if the current user has access to this external page based on $this->req_capability.
6e4dc10f 1251 *
1252 * @uses CONTEXT_SYSTEM
1253 * @uses SITEID
1254 * @return bool True if user has access, false otherwise.
1255 */
1256 function check_access() {
1257 if (!get_site()) {
1258 return true; // no access check before site is fully set up
1259 }
84c8ede0 1260 $context = empty($this->context) ? get_context_instance(CONTEXT_SYSTEM) : $this->context;
38d2d43b 1261 foreach($this->req_capability as $cap) {
1262 if (has_capability($cap, $context)) {
1263 return true;
1264 }
1265 }
1266 return false;
6e4dc10f 1267 }
1268
a8a66c96 1269 /**
1270 * Is this external page hidden in admin tree block?
1271 *
1272 * @return bool True if hidden
1273 */
1274 function is_hidden() {
1275 return $this->hidden;
1276 }
1277
6e4dc10f 1278}
1279
1280/**
1281 * Used to group a number of admin_setting objects into a page and add them to the admin tree.
1282 *
1283 * @author Vincenzo K. Marcovecchio
1284 * @package admin
1285 */
1286class admin_settingpage extends part_of_admin_tree {
1287
eef868d1 1288 /**
6e4dc10f 1289 * @var string An internal name for this external page. Must be unique amongst ALL part_of_admin_tree objects
1290 */
1291 var $name;
eef868d1 1292
6e4dc10f 1293 /**
1294 * @var string The displayed name for this external page. Usually obtained through get_string().
1295 */
1296 var $visiblename;
1297 /**
1298 * @var mixed An array of admin_setting objects that are part of this setting page.
1299 */
1300 var $settings;
eef868d1 1301
6e4dc10f 1302 /**
1303 * @var string The role capability/permission a user must have to access this external page.
1304 */
2ce38b70 1305 var $req_capability;
eef868d1 1306
84c8ede0 1307 /**
1308 * @var object The context in which capability/permission should be checked, default is site context.
1309 */
1310 var $context;
1311
a8a66c96 1312 /**
1313 * @var bool hidden in admin tree block.
1314 */
1315 var $hidden;
1316
6e4dc10f 1317 // see admin_category
1318 function path($name, $path = array()) {
1319 if ($name == $this->name) {
1320 array_push($path, $this->name);
1321 return $path;
1322 } else {
1323 return NULL;
1324 }
1325 }
eef868d1 1326
6e4dc10f 1327 // see admin_category
1328 function &locate($name) {
1329 $return = ($this->name == $name ? $this : NULL);
1330 return $return;
1331 }
4672d955 1332
1333 function prune($name) {
1334 return false;
1335 }
1336
6e4dc10f 1337 // see admin_externalpage
01e85af9 1338 function admin_settingpage($name, $visiblename, $req_capability = 'moodle/site:config', $hidden=false, $context=NULL) {
6e4dc10f 1339 global $CFG;
1340 $this->settings = new stdClass();
1341 $this->name = $name;
1342 $this->visiblename = $visiblename;
38d2d43b 1343 if (is_array($req_capability)) {
1344 $this->req_capability = $req_capability;
1345 } else {
1346 $this->req_capability = array($req_capability);
1347 }
a8a66c96 1348 $this->hidden = false;
84c8ede0 1349 $this->context = $context;
6e4dc10f 1350 }
eef868d1 1351
6e4dc10f 1352 // 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
1353 // n.b. each admin_setting in an admin_settingpage must have a unique internal name
1354 // &$setting is the admin_setting object you want to add
1355 // returns true if successful, false if not (will fail if &$setting is an admin_setting or child thereof)
1356 function add(&$setting) {
1357 if (is_a($setting, 'admin_setting')) {
1358 $this->settings->{$setting->name} =& $setting;
1359 return true;
1360 }
1361 return false;
1362 }
eef868d1 1363
6e4dc10f 1364 // see admin_externalpage
1365 function check_access() {
1366 if (!get_site()) {
1367 return true; // no access check before site is fully set up
1368 }
84c8ede0 1369 $context = empty($this->context) ? get_context_instance(CONTEXT_SYSTEM) : $this->context;
38d2d43b 1370 foreach($this->req_capability as $cap) {
1371 if (has_capability($cap, $context)) {
1372 return true;
1373 }
1374 }
1375 return false;
6e4dc10f 1376 }
eef868d1 1377
6e4dc10f 1378 // outputs this page as html in a table (suitable for inclusion in an admin pagetype)
1379 // returns a string of the html
1380 function output_html() {
15a16922 1381 $return = '<fieldset>' . "\n";
6153cf58 1382 $return .= '<div class="clearer"><!-- --></div>' . "\n";
6e4dc10f 1383 foreach($this->settings as $setting) {
15a16922 1384 $return .= $setting->output_html();
6e4dc10f 1385 }
6153cf58 1386 $return .= '</fieldset>';
6e4dc10f 1387 return $return;
1388 }
1389
1390 // 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
1391 // -- calls write_setting() to each child setting, sending it only the data that matches each setting's internal name
1392 // $data should be the result from data_submitted()
1393 // returns an empty string if everything went well, otherwise returns a printable error string (that's language-specific)
1394 function write_settings($data) {
1395 $return = '';
1396 foreach($this->settings as $setting) {
1397 if (isset($data['s_' . $setting->name])) {
1398 $return .= $setting->write_setting($data['s_' . $setting->name]);
1399 } else {
1400 $return .= $setting->write_setting('');
1401 }
1402 }
1403 return $return;
1404 }
1405
a8a66c96 1406 /**
1407 * Is this settigns page hidden in admin tree block?
1408 *
1409 * @return bool True if hidden
1410 */
1411 function is_hidden() {
1412 return $this->hidden;
1413 }
1414
6e4dc10f 1415}
1416
1417
1418// read & write happens at this level; no authentication
1419class admin_setting {
1420
1421 var $name;
1422 var $visiblename;
1423 var $description;
1424 var $defaultsetting;
1425
1426 function admin_setting($name, $visiblename, $description, $defaultsetting) {
1427 $this->name = $name;
1428 $this->visiblename = $visiblename;
1429 $this->description = $description;
1430 $this->defaultsetting = $defaultsetting;
1431 }
eef868d1 1432
6e4dc10f 1433 function get_setting() {
1434 return NULL; // has to be overridden
1435 }
eef868d1 1436
8e5da17a 1437 function get_defaultsetting() {
1438 return $this->defaultsetting;
1439 }
1440
6e4dc10f 1441 function write_setting($data) {
1442 return; // has to be overridden
1443 }
eef868d1 1444
6e4dc10f 1445 function output_html() {
1446 return; // has to be overridden
1447 }
eef868d1 1448
6e4dc10f 1449}
1450
1451
1452class admin_setting_configtext extends admin_setting {
1453
1454 var $paramtype;
1455
50999a0b 1456 function admin_setting_configtext($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW) {
6e4dc10f 1457 $this->paramtype = $paramtype;
1458 parent::admin_setting($name, $visiblename, $description, $defaultsetting);
1459 }
1460
cc73de71 1461 // returns a string or NULL
6e4dc10f 1462 function get_setting() {
1463 global $CFG;
c8218a42 1464 return (isset($CFG->{$this->name}) ? $CFG->{$this->name} : NULL);
6e4dc10f 1465 }
eef868d1 1466
cc73de71 1467 // $data is a string
6e4dc10f 1468 function write_setting($data) {
9e24fbd1 1469 if (!$this->validate($data)) {
1470 return get_string('validateerror', 'admin') . $this->visiblename . '<br />';
c235598d 1471 }
6e4dc10f 1472 return (set_config($this->name,$data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1473 }
1474
c235598d 1475 function validate($data) {
9e24fbd1 1476 if (is_string($this->paramtype)) {
1477 return preg_match($this->paramtype, $data);
1478 } else if ($this->paramtype === PARAM_RAW) {
1479 return true;
1480 } else {
1481 $cleaned = clean_param($data, $this->paramtype);
1482 return ("$data" == "$cleaned"); // implicit conversion to string is needed to do exact comparison
1483 }
c235598d 1484 }
1485
6e4dc10f 1486 function output_html() {
c8218a42 1487 if ($this->get_setting() === NULL) {
1488 $current = $this->defaultsetting;
1489 } else {
1490 $current = $this->get_setting();
1491 }
9e24fbd1 1492 return format_admin_setting($this->name, $this->visiblename,
5259d5d8 1493 '<input type="text" class="form-text" id="id_s_'.$this->name.'" name="s_'.$this->name.'" value="'.s($current).'" />',
6153cf58 1494 $this->description);
6e4dc10f 1495 }
1496
1497}
1498
54bb33eb 1499class admin_setting_configpasswordunmask extends admin_setting_configtext {
eba8cd63 1500
54bb33eb 1501 function admin_setting_configpasswordunmask($name, $visiblename, $description, $defaultsetting, $paramtype=PARAM_RAW) {
eba8cd63 1502 parent::admin_setting_configtext($name, $visiblename, $description, $defaultsetting, $paramtype);
1503 }
1504
1505 function output_html() {
1506 if ($this->get_setting() === NULL) {
1507 $current = $this->defaultsetting;
1508 } else {
1509 $current = $this->get_setting();
1510 }
1511 $id = 'id_s_'.$this->name;
54bb33eb 1512 $unmask = get_string('unmaskpassword', 'form');
1513 $unmaskjs = '<script type="text/javascript">
eba8cd63 1514//<![CDATA[
54bb33eb 1515document.write(\'<div class="unmask"><input id="'.$id.'unmask" value="1" type="checkbox" onclick="unmaskPassword(\\\''.$id.'\\\')"/><label for="'.$id.'unmask">'.addslashes_js($unmask).'<\/label><\/div>\');
eba8cd63 1516//]]>
1517</script>';
1518 return format_admin_setting($this->name, $this->visiblename,
54bb33eb 1519 '<input type="password" class="form-text" id="id_s_'.$this->name.'" name="s_'.$this->name.'" value="'.s($current).'" />'.$unmaskjs,
eba8cd63 1520 $this->description);
1521 }
9ba38673 1522
eba8cd63 1523}
1524
6e4dc10f 1525class admin_setting_configcheckbox extends admin_setting {
1526
1527 function admin_setting_configcheckbox($name, $visiblename, $description, $defaultsetting) {
1528 parent::admin_setting($name, $visiblename, $description, $defaultsetting);
1529 }
1530
1531 function get_setting() {
1532 global $CFG;
1533 return (isset($CFG->{$this->name}) ? $CFG->{$this->name} : NULL);
1534 }
eef868d1 1535
6e4dc10f 1536 function write_setting($data) {
1537 if ($data == '1') {
1538 return (set_config($this->name,1) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1539 } else {
1540 return (set_config($this->name,0) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1541 }
1542 }
1543
1544 function output_html() {
c8218a42 1545 if ($this->get_setting() === NULL) {
1546 $current = $this->defaultsetting;
1547 } else {
1548 $current = $this->get_setting();
1549 }
9e24fbd1 1550 return format_admin_setting($this->name, $this->visiblename,
3c6f7a78 1551 '<input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'" name="s_'. $this->name .'" value="1" ' . ($current == true ? 'checked="checked"' : '') . ' />',
6153cf58 1552 $this->description);
6e4dc10f 1553 }
1554
1555}
1556
1557class admin_setting_configselect extends admin_setting {
1558
1559 var $choices;
eef868d1 1560
6e4dc10f 1561 function admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices) {
1562 $this->choices = $choices;
1563 parent::admin_setting($name, $visiblename, $description, $defaultsetting);
1564 }
1565
0a784551 1566 /**
1567 * This function may be used in ancestors for lazy loading of choices
1568 */
1569 function load_choices() {
1570 /*
1571 if (!empty($this->choices)) {
1572 return;
1573 }
1574 .... load choices here
1575 */
1576 }
1577
6e4dc10f 1578 function get_setting() {
1579 global $CFG;
1580 return (isset($CFG->{$this->name}) ? $CFG->{$this->name} : NULL);
1581 }
eef868d1 1582
6e4dc10f 1583 function write_setting($data) {
0a784551 1584 $this->load_choices();
6e4dc10f 1585 // check that what we got was in the original choices
1586 // or that the data is the default setting - needed during install when choices can not be constructed yet
1587 if ($data != $this->defaultsetting and ! in_array($data, array_keys($this->choices))) {
1588 return 'Error setting ' . $this->visiblename . '<br />';
1589 }
eef868d1 1590
6e4dc10f 1591 return (set_config($this->name, $data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1592 }
eef868d1 1593
6e4dc10f 1594 function output_html() {
0a784551 1595 $this->load_choices();
c8218a42 1596 if ($this->get_setting() === NULL) {
1597 $current = $this->defaultsetting;
1598 } else {
1599 $current = $this->get_setting();
1600 }
afee9864 1601 $return = '<select class="form-select" id="id_s_'.$this->name.'" name="s_' . $this->name .'">';
6e4dc10f 1602 foreach ($this->choices as $key => $value) {
a1069b07 1603 // the string cast is needed because key may be integer - 0 is equal to most strings!
1604 $return .= '<option value="'.$key.'"'.((string)$key==$current ? ' selected="selected"' : '').'>'.$value.'</option>';
6e4dc10f 1605 }
6153cf58 1606 $return .= '</select>';
1607
fc52aa6e 1608 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
6e4dc10f 1609 }
1610
1611}
1612
1613// 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
1614// internally for the setting)
1615class admin_setting_configtime extends admin_setting {
1616
1617 var $name2;
1618 var $choices;
1619 var $choices2;
6e4dc10f 1620
1621 function admin_setting_configtime($hoursname, $minutesname, $visiblename, $description, $defaultsetting) {
1622 $this->name2 = $minutesname;
1623 $this->choices = array();
1624 for ($i = 0; $i < 24; $i++) {
1625 $this->choices[$i] = $i;
1626 }
1627 $this->choices2 = array();
1628 for ($i = 0; $i < 60; $i += 5) {
1629 $this->choices2[$i] = $i;
1630 }
1631 parent::admin_setting($hoursname, $visiblename, $description, $defaultsetting);
1632 }
1633
1634 function get_setting() {
1635 global $CFG;
cc73de71 1636 return (isset($CFG->{$this->name}) && isset($CFG->{$this->name2}) ? array('h' => $CFG->{$this->name}, 'm' => $CFG->{$this->name2}) : NULL);
6e4dc10f 1637 }
eef868d1 1638
6e4dc10f 1639 function write_setting($data) {
1640 // check that what we got was in the original choices
1641 if (!(in_array($data['h'], array_keys($this->choices)) && in_array($data['m'], array_keys($this->choices2)))) {
1642 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
1643 }
eef868d1 1644
6e4dc10f 1645 return (set_config($this->name, $data['h']) && set_config($this->name2, $data['m']) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1646 }
eef868d1 1647
6e4dc10f 1648 function output_html() {
cc73de71 1649 if ($this->get_setting() === NULL) {
1650 $currentsetting = $this->defaultsetting;
1651 } else {
1652 $currentsetting = $this->get_setting();
6e4dc10f 1653 }
2e0c11dd 1654 $return = '<div class="form-group">'.
1655 '<select class="form-select" id="id_s_'.$this->name.'h" name="s_' . $this->name .'[h]">';
6e4dc10f 1656 foreach ($this->choices as $key => $value) {
cc73de71 1657 $return .= '<option value="' . $key . '"' . ($key == $currentsetting['h'] ? ' selected="selected"' : '') . '>' . $value . '</option>';
6e4dc10f 1658 }
2e0c11dd 1659 $return .= '</select>:<select class="form-select" id="id_s_'.$this->name.'m" name="s_' . $this->name . '[m]">';
6e4dc10f 1660 foreach ($this->choices2 as $key => $value) {
cc73de71 1661 $return .= '<option value="' . $key . '"' . ($key == $currentsetting['m'] ? ' selected="selected"' : '') . '>' . $value . '</option>';
eef868d1 1662 }
2e0c11dd 1663 $return .= '</select></div>';
fbe31d22 1664 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
6e4dc10f 1665 }
1666
1667}
1668
1669class admin_setting_configmultiselect extends admin_setting_configselect {
1670
1671 function admin_setting_configmultiselect($name, $visiblename, $description, $defaultsetting, $choices) {
1672 parent::admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices);
1673 }
1674
1675 function get_setting() {
1676 global $CFG;
d7933a55 1677 if (isset($CFG->{$this->name})) {
1678 if ($CFG->{$this->name}) {
1679 return explode(',', $CFG->{$this->name});
1680 } else {
1681 return array();
9ba38673 1682 }
d7933a55 1683 } else {
1684 return NULL;
1685 }
6e4dc10f 1686 }
eef868d1 1687
6e4dc10f 1688 function write_setting($data) {
d7933a55 1689 if (empty($data)) {
1690 $data = array();
1691 }
6e4dc10f 1692 foreach ($data as $datum) {
1693 if (! in_array($datum, array_keys($this->choices))) {
1694 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
1695 }
1696 }
eef868d1 1697
6e4dc10f 1698 return (set_config($this->name, implode(',',$data)) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1699 }
eef868d1 1700
6e4dc10f 1701 function output_html() {
cc73de71 1702 if ($this->get_setting() === NULL) {
1703 $currentsetting = $this->defaultsetting;
0b0f7c00 1704 if (!$currentsetting) {
1705 $currentsetting = array();
1706 }
cc73de71 1707 } else {
1708 $currentsetting = $this->get_setting();
6e4dc10f 1709 }
afee9864 1710 $return = '<select class="form-select" id="id_s_'.$this->name.'" name="s_' . $this->name .'[]" size="10" multiple="multiple">';
6e4dc10f 1711 foreach ($this->choices as $key => $value) {
1712 $return .= '<option value="' . $key . '"' . (in_array($key,$currentsetting) ? ' selected="selected"' : '') . '>' . $value . '</option>';
1713 }
6153cf58 1714 $return .= '</select>';
fc52aa6e 1715 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
6e4dc10f 1716 }
1717
1718}
1719
1720class admin_setting_special_adminseesall extends admin_setting_configcheckbox {
eef868d1 1721
6e4dc10f 1722 function admin_setting_special_adminseesall() {
1723 $name = 'calendar_adminseesall';
1724 $visiblename = get_string('adminseesall', 'admin');
1725 $description = get_string('helpadminseesall', 'admin');
1726 parent::admin_setting($name, $visiblename, $description, 0);
1727 }
1728
1729 function write_setting($data) {
1730 global $SESSION;
1731 unset($SESSION->cal_courses_shown);
1732 parent::write_setting($data);
1733 }
1734}
1735
1736class admin_setting_sitesetselect extends admin_setting_configselect {
1737
1738 var $id;
1739
1740 function admin_setting_sitesetselect($name, $visiblename, $description, $defaultsetting, $choices) {
1741
1742 $this->id = SITEID;
1743 parent::admin_setting_configselect($name, $visiblename, $description, $defaultsetting, $choices);
eef868d1 1744
6e4dc10f 1745 }
eef868d1 1746
6e4dc10f 1747 function get_setting() {
1748 $site = get_site();
1749 return (isset($site->{$this->name}) ? $site->{$this->name} : NULL);
1750 }
eef868d1 1751
6e4dc10f 1752 function write_setting($data) {
1753 if (!in_array($data, array_keys($this->choices))) {
1754 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
1755 }
1756 $record = new stdClass();
1757 $record->id = $this->id;
1758 $temp = $this->name;
1759 $record->$temp = $data;
1760 $record->timemodified = time();
1761 return (update_record('course', $record) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1762 }
eef868d1 1763
6e4dc10f 1764}
1765
1766
e0f6e995 1767class admin_setting_courselist_frontpage extends admin_setting_configselect {
6e4dc10f 1768
e0f6e995 1769 function admin_setting_courselist_frontpage($loggedin) {
6e4dc10f 1770 global $CFG;
1771 require_once($CFG->dirroot . '/course/lib.php');
1772 $name = 'frontpage' . ($loggedin ? 'loggedin' : '');
1773 $visiblename = get_string('frontpage' . ($loggedin ? 'loggedin' : ''),'admin');
1774 $description = get_string('configfrontpage' . ($loggedin ? 'loggedin' : ''),'admin');
1775 $choices = array(FRONTPAGENEWS => get_string('frontpagenews'),
1776 FRONTPAGECOURSELIST => get_string('frontpagecourselist'),
1777 FRONTPAGECATEGORYNAMES => get_string('frontpagecategorynames'),
1778 FRONTPAGECATEGORYCOMBO => get_string('frontpagecategorycombo'),
1779 '' => get_string('none'));
9fec4e33 1780 if (!$loggedin and count_records("course") > FRONTPAGECOURSELIMIT) {
6e4dc10f 1781 unset($choices[FRONTPAGECOURSELIST]);
1782 }
4672d955 1783 $defaults = FRONTPAGECOURSELIST.',,,';
e0f6e995 1784 parent::admin_setting_configselect($name, $visiblename, $description, $defaults, $choices);
6e4dc10f 1785 }
eef868d1 1786
6e4dc10f 1787 function get_setting() {
1788 global $CFG;
1c1e7af4 1789 return (isset($CFG->{$this->name}) ? explode(',', $CFG->{$this->name}) : ',1,,');
6e4dc10f 1790 }
eef868d1 1791
6e4dc10f 1792 function write_setting($data) {
1793 if (empty($data)) {
1794 $data = array();
e0f6e995 1795 } if (!is_array($data)) {
1796 $data = explode(',', $data);
6e4dc10f 1797 }
1798 foreach($data as $datum) {
1799 if (! in_array($datum, array_keys($this->choices))) {
1800 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
1801 }
1802 }
1803 return (set_config($this->name, implode(',', $data)) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1804 }
eef868d1 1805
6e4dc10f 1806 function output_html() {
cc73de71 1807 if ($this->get_setting() === NULL) {
1808 $currentsetting = $this->defaultsetting;
1809 } else {
1810 $currentsetting = $this->get_setting();
6e4dc10f 1811 }
1812 for ($i = 0; $i < count($this->choices) - 1; $i++) {
1813 if (!isset($currentsetting[$i])) {
1814 $currentsetting[$i] = 0;
1815 }
1816 }
0a7e84c3 1817 $return = '<div class="form-group">';
6e4dc10f 1818 for ($i = 0; $i < count($this->choices) - 1; $i++) {
a1d52643 1819 $return .='<select class="form-select" id="id_s_'.$this->name.$i.'" name="s_' . $this->name .'[]">';
6e4dc10f 1820 foreach ($this->choices as $key => $value) {
1821 $return .= '<option value="' . $key . '"' . ($key == $currentsetting[$i] ? ' selected="selected"' : '') . '>' . $value . '</option>';
1822 }
1823 $return .= '</select>';
1824 if ($i !== count($this->choices) - 2) {
975211bb 1825 $return .= '<br />';
6e4dc10f 1826 }
1827 }
0a7e84c3 1828 $return .= '</div>';
1829
fbe31d22 1830 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
6e4dc10f 1831 }
1832}
1833
1834class admin_setting_sitesetcheckbox extends admin_setting_configcheckbox {
1835
1836 var $id;
1837
1838 function admin_setting_sitesetcheckbox($name, $visiblename, $description, $defaultsetting) {
1839
1840 $this->id = SITEID;
1841 parent::admin_setting_configcheckbox($name, $visiblename, $description, $defaultsetting);
eef868d1 1842
6e4dc10f 1843 }
eef868d1 1844
6e4dc10f 1845 function get_setting() {
1846 $site = get_site();
8e5da17a 1847 return $site->{$this->name};
6e4dc10f 1848 }
eef868d1 1849
6e4dc10f 1850 function write_setting($data) {
1851 $record = new stdClass();
1852 $record->id = $this->id;
1853 $temp = $this->name;
1854 $record->$temp = ($data == '1' ? 1 : 0);
1855 $record->timemodified = time();
1856 return (update_record('course', $record) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
1857 }
eef868d1 1858
6e4dc10f 1859}
1860
1861class admin_setting_sitesettext extends admin_setting_configtext {
1862
1863 var $id;
1864
b89639f9 1865 function admin_setting_sitesettext($name, $visiblename, $description, $defaultsetting) {
6e4dc10f 1866
1867 $this->id = SITEID;
b89639f9 1868 parent::admin_setting_configtext($name, $visiblename, $description, $defaultsetting);
eef868d1 1869
6e4dc10f 1870 }
eef868d1 1871
6e4dc10f 1872 function get_setting() {
1873 $site = get_site();
8e5da17a 1874 return $site->{$this->name} != '' ? $site->{$this->name} : NULL;
6e4dc10f 1875 }
90cfbd0a 1876
b89639f9 1877 function validate($data) {
b0abd282 1878 $cleaned = stripslashes(clean_param($data, PARAM_MULTILANG));
b89639f9 1879 if ($cleaned == '') {
1880 return false; // can not be empty
1881 }
b0abd282 1882 return ($data == $cleaned); // implicit conversion to string is needed to do exact comparison
b89639f9 1883 }
1884
6e4dc10f 1885 function write_setting($data) {
b89639f9 1886 $data = trim($data);
9e24fbd1 1887 if (!$this->validate($data)) {
1888 return get_string('validateerror', 'admin') . $this->visiblename . '<br />';
90cfbd0a 1889 }
eef868d1 1890
6e4dc10f 1891 $record = new stdClass();
1892 $record->id = $this->id;
87fa8a17 1893 $record->{$this->name} = addslashes($data);
6e4dc10f 1894 $record->timemodified = time();
23a97d83 1895 return (update_record('course', $record) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
6e4dc10f 1896 }
90cfbd0a 1897
6e4dc10f 1898}
1899
1900class admin_setting_special_frontpagedesc extends admin_setting {
1901
1902 var $id;
eef868d1 1903
6e4dc10f 1904 function admin_setting_special_frontpagedesc() {
1905 $this->id = SITEID;
1906 $name = 'summary';
1907 $visiblename = get_string('frontpagedescription');
1908 $description = get_string('frontpagedescriptionhelp');
1909 parent::admin_setting($name, $visiblename, $description, '');
1910 }
1911
1912 function output_html() {
fa040029 1913 global $CFG;
1914
fa040029 1915 $CFG->adminusehtmleditor = can_use_html_editor();
c626c2f4 1916 $return = print_textarea($CFG->adminusehtmleditor, 15, 60, 0, 0, 's_' . $this->name, $this->get_setting(), 0, true);
eef868d1 1917
fbe31d22 1918 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
6e4dc10f 1919 }
eef868d1 1920
6e4dc10f 1921 function get_setting() {
6e4dc10f 1922 $site = get_site();
c626c2f4 1923 return $site->{$this->name};
1924 }
eef868d1 1925
c626c2f4 1926 function get_defaultsetting() {
1927 return NULL;
6e4dc10f 1928 }
eef868d1 1929
6e4dc10f 1930 function write_setting($data) {
c626c2f4 1931 $record = new object();
1932 $record->id = $this->id;
1933 $record->{$this->name} = addslashes($data);
1934 $record->timemodified = time();
eef868d1 1935
6e4dc10f 1936 return(update_record('course', $record) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
6e4dc10f 1937 }
1938
1939}
1940
1941
1942class admin_setting_special_editorfontlist extends admin_setting {
1943
1944 var $items;
1945
1946 function admin_setting_special_editorfontlist() {
1947 global $CFG;
1948 $name = 'editorfontlist';
1949 $visiblename = get_string('editorfontlist', 'admin');
1950 $description = get_string('configeditorfontlist', 'admin');
6e4dc10f 1951 $defaults = array('k0' => 'Trebuchet',
1952 'v0' => 'Trebuchet MS,Verdana,Arial,Helvetica,sans-serif',
1953 'k1' => 'Arial',
1954 'v1' => 'arial,helvetica,sans-serif',
1955 'k2' => 'Courier New',
1956 'v2' => 'courier new,courier,monospace',
1957 'k3' => 'Georgia',
1958 'v3' => 'georgia,times new roman,times,serif',
1959 'k4' => 'Tahoma',
1960 'v4' => 'tahoma,arial,helvetica,sans-serif',
1961 'k5' => 'Times New Roman',
1962 'v5' => 'times new roman,times,serif',
1963 'k6' => 'Verdana',
1964 'v6' => 'verdana,arial,helvetica,sans-serif',
1965 'k7' => 'Impact',
1966 'v7' => 'impact',
1967 'k8' => 'Wingdings',
1968 'v8' => 'wingdings');
1969 parent::admin_setting($name, $visiblename, $description, $defaults);
1970 }
eef868d1 1971
6e4dc10f 1972 function get_setting() {
cc73de71 1973 global $CFG;
1974 if (isset($CFG->editorfontlist)) {
1975 $i = 0;
1976 $currentsetting = array();
1977 $items = explode(';', $CFG->editorfontlist);
1978 foreach ($items as $item) {
1979 $item = explode(':', $item);
1980 $currentsetting['k' . $i] = $item[0];
1981 $currentsetting['v' . $i] = $item[1];
1982 $i++;
1983 }
1984 return $currentsetting;
1985 } else {
1986 return NULL;
1987 }
6e4dc10f 1988 }
eef868d1 1989
6e4dc10f 1990 function write_setting($data) {
eef868d1 1991
6e4dc10f 1992 // there miiight be an easier way to do this :)
1993 // if this is changed, make sure the $defaults array above is modified so that this
1994 // function processes it correctly
eef868d1 1995
6e4dc10f 1996 $keys = array();
1997 $values = array();
eef868d1 1998
6e4dc10f 1999 foreach ($data as $key => $value) {
2000 if (substr($key,0,1) == 'k') {
2001 $keys[substr($key,1)] = $value;
2002 } elseif (substr($key,0,1) == 'v') {
2003 $values[substr($key,1)] = $value;
2004 }
2005 }
eef868d1 2006
6e4dc10f 2007 $result = '';
2008 for ($i = 0; $i < count($keys); $i++) {
2009 if (($keys[$i] !== '') && ($values[$i] !== '')) {
2010 $result .= clean_param($keys[$i],PARAM_NOTAGS) . ':' . clean_param($values[$i], PARAM_NOTAGS) . ';';
2011 }
2012 }
eef868d1 2013
6e4dc10f 2014 $result = substr($result, 0, -1); // trim the last semicolon
eef868d1 2015
6e4dc10f 2016 return (set_config($this->name, $result) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2017 }
eef868d1 2018
6e4dc10f 2019 function output_html() {
eef868d1 2020
cc73de71 2021 if ($this->get_setting() === NULL) {
2022 $currentsetting = $this->defaultsetting;
2023 } else {
2024 $currentsetting = $this->get_setting();
6e4dc10f 2025 }
eef868d1 2026
1beed35f 2027 $return = '<div class="form-group">';
cc73de71 2028 for ($i = 0; $i < count($currentsetting) / 2; $i++) {
3c6f7a78 2029 $return .= '<input type="text" class="form-text" name="s_editorfontlist[k' . $i . ']" value="' . $currentsetting['k' . $i] . '" />';
6e4dc10f 2030 $return .= '&nbsp;&nbsp;';
3c6f7a78 2031 $return .= '<input type="text" class="form-text" name="s_editorfontlist[v' . $i . ']" value="' . $currentsetting['v' . $i] . '" /><br />';
6e4dc10f 2032 }
3c6f7a78 2033 $return .= '<input type="text" class="form-text" name="s_editorfontlist[k' . $i . ']" value="" />';
6e4dc10f 2034 $return .= '&nbsp;&nbsp;';
3c6f7a78 2035 $return .= '<input type="text" class="form-text" name="s_editorfontlist[v' . $i . ']" value="" /><br />';
2036 $return .= '<input type="text" class="form-text" name="s_editorfontlist[k' . ($i + 1) . ']" value="" />';
6e4dc10f 2037 $return .= '&nbsp;&nbsp;';
3c6f7a78 2038 $return .= '<input type="text" class="form-text" name="s_editorfontlist[v' . ($i + 1) . ']" value="" />';
1beed35f 2039 $return .= '</div>';
6153cf58 2040
60a9a6ea 2041 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
6e4dc10f 2042 }
eef868d1 2043
6e4dc10f 2044}
2045
93c61c18 2046class admin_setting_emoticons extends admin_setting {
2047
2048 var $items;
2049
2050 function admin_setting_emoticons() {
2051 global $CFG;
2052 $name = 'emoticons';
2053 $visiblename = get_string('emoticons', 'admin');
2054 $description = get_string('configemoticons', 'admin');
2055 $defaults = array('k0' => ':-)',
2056 'v0' => 'smiley',
2057 'k1' => ':)',
2058 'v1' => 'smiley',
2059 'k2' => ':-D',
2060 'v2' => 'biggrin',
2061 'k3' => ';-)',
2062 'v3' => 'wink',
2063 'k4' => ':-/',
2064 'v4' => 'mixed',
2065 'k5' => 'V-.',
2066 'v5' => 'thoughtful',
2067 'k6' => ':-P',
2068 'v6' => 'tongueout',
2069 'k7' => 'B-)',
2070 'v7' => 'cool',
2071 'k8' => '^-)',
2072 'v8' => 'approve',
2073 'k9' => '8-)',
2074 'v9' => 'wideeyes',
2075 'k10' => ':o)',
2076 'v10' => 'clown',
2077 'k11' => ':-(',
2078 'v11' => 'sad',
2079 'k12' => ':(',
2080 'v12' => 'sad',
2081 'k13' => '8-.',
2082 'v13' => 'shy',
2083 'k14' => ':-I',
2084 'v14' => 'blush',
2085 'k15' => ':-X',
2086 'v15' => 'kiss',
2087 'k16' => '8-o',
2088 'v16' => 'surprise',
2089 'k17' => 'P-|',
2090 'v17' => 'blackeye',
2091 'k18' => '8-[',
2092 'v18' => 'angry',
2093 'k19' => 'xx-P',
2094 'v19' => 'dead',
2095 'k20' => '|-.',
2096 'v20' => 'sleepy',
2097 'k21' => '}-]',
2098 'v21' => 'evil',
2099 'k22' => '(h)',
2100 'v22' => 'heart',
2101 'k23' => '(heart)',
2102 'v23' => 'heart',
2103 'k24' => '(y)',
2104 'v24' => 'yes',
2105 'k25' => '(n)',
2106 'v25' => 'no',
2107 'k26' => '(martin)',
2108 'v26' => 'martin',
2109 'k27' => '( )',
2110 'v27' => 'egg');
2111 parent::admin_setting($name, $visiblename, $description, $defaults);
2112 }
2113
2114 function get_setting() {
2115 global $CFG;
2116 if (isset($CFG->emoticons)) {
2117 $i = 0;
2118 $currentsetting = array();
2119 $items = explode('{;}', $CFG->emoticons);
2120 foreach ($items as $item) {
2121 $item = explode('{:}', $item);
2122 $currentsetting['k' . $i] = $item[0];
2123 $currentsetting['v' . $i] = $item[1];
2124 $i++;
2125 }
2126 return $currentsetting;
2127 } else {
2128 return NULL;
2129 }
2130 }
2131
2132 function write_setting($data) {
2133
2134 // there miiight be an easier way to do this :)
2135 // if this is changed, make sure the $defaults array above is modified so that this
2136 // function processes it correctly
2137
2138 $keys = array();
2139 $values = array();
2140
2141 foreach ($data as $key => $value) {
2142 if (substr($key,0,1) == 'k') {
2143 $keys[substr($key,1)] = $value;
2144 } elseif (substr($key,0,1) == 'v') {
2145 $values[substr($key,1)] = $value;
2146 }
2147 }
2148
2149 $result = '';
2150 for ($i = 0; $i < count($keys); $i++) {
2151 if (($keys[$i] !== '') && ($values[$i] !== '')) {
2152 $result .= clean_param($keys[$i],PARAM_NOTAGS) . '{:}' . clean_param($values[$i], PARAM_NOTAGS) . '{;}';
2153 }
2154 }
2155
2156 $result = substr($result, 0, -3); // trim the last separator
2157
2158 return (set_config($this->name, $result) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2159 }
2160
2161 function output_html() {
2162
2163 if ($this->get_setting() === NULL) {
2164 $currentsetting = $this->defaultsetting;
2165 } else {
2166 $currentsetting = $this->get_setting();
2167 }
2168
2169 $return = '<div class="form-group">';
2170 for ($i = 0; $i < count($currentsetting) / 2; $i++) {
2171 $return .= '<input type="text" class="form-text" name="s_emoticons[k' . $i . ']" value="' . $currentsetting['k' . $i] . '" />';
2172 $return .= '&nbsp;&nbsp;';
2173 $return .= '<input type="text" class="form-text" name="s_emoticons[v' . $i . ']" value="' . $currentsetting['v' . $i] . '" /><br />';
2174 }
2175 $return .= '<input type="text" class="form-text" name="s_emoticons[k' . $i . ']" value="" />';
2176 $return .= '&nbsp;&nbsp;';
2177 $return .= '<input type="text" class="form-text" name="s_emoticons[v' . $i . ']" value="" /><br />';
2178 $return .= '<input type="text" class="form-text" name="s_emoticons[k' . ($i + 1) . ']" value="" />';
2179 $return .= '&nbsp;&nbsp;';
2180 $return .= '<input type="text" class="form-text" name="s_emoticons[v' . ($i + 1) . ']" value="" />';
2181 $return .= '</div>';
2182
2183 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
2184 }
2185
2186}
2187
6e4dc10f 2188class admin_setting_special_editordictionary extends admin_setting_configselect {
2189
2190 function admin_setting_special_editordictionary() {
2191 $name = 'editordictionary';
2192 $visiblename = get_string('editordictionary','admin');
2193 $description = get_string('configeditordictionary', 'admin');
2194 $choices = $this->editor_get_dictionaries();
2195 if (! is_array($choices)) {
2196 $choices = array('');
2197 }
eef868d1 2198
6e4dc10f 2199 parent::admin_setting_configselect($name, $visiblename, $description, '', $choices);
2200 }
2201
2202 // function borrowed from the old moodle/admin/editor.php, slightly modified
2203 function editor_get_dictionaries () {
2204 /// Get all installed dictionaries in the system
2205
2206 global $CFG;
eef868d1 2207
6e4dc10f 2208// error_reporting(E_ALL); // for debug, final version shouldn't have this...
2209 clearstatcache();
2210
2211 // If aspellpath isn't set don't even bother ;-)
2212 if (empty($CFG->aspellpath)) {
2213 return 'Empty aspell path!';
2214 }
2215
2216 // Do we have access to popen function?
2217 if (!function_exists('popen')) {
2218 return 'Popen function disabled!';
2219 }
eef868d1 2220
6e4dc10f 2221 $cmd = $CFG->aspellpath;
2222 $output = '';
2223 $dictionaries = array();
2224 $dicts = array();
2225
2226 if(!($handle = @popen(escapeshellarg($cmd) .' dump dicts', 'r'))) {
2227 return 'Couldn\'t create handle!';
2228 }
2229
2230 while(!feof($handle)) {
2231 $output .= fread($handle, 1024);
2232 }
2233 @pclose($handle);
2234
2235 $dictionaries = explode(chr(10), $output);
2236
2237 // Get rid of possible empty values
2238 if (is_array($dictionaries)) {
2239
2240 $cnt = count($dictionaries);
2241
2242 for ($i = 0; $i < $cnt; $i++) {
2243 if (!empty($dictionaries[$i])) {
2c41b2d7 2244 $dicts[$dictionaries[$i]] = $dictionaries[$i];
6e4dc10f 2245 }
2246 }
2247 }
2248
2249 if (count($dicts) >= 1) {
2250 return $dicts;
2251 }
2252
2253 return 'Error! Check your aspell installation!';
2254 }
2255
eef868d1 2256
6e4dc10f 2257
2258}
2259
2260
2261class admin_setting_special_editorhidebuttons extends admin_setting {
2262
2263 var $name;
2264 var $visiblename;
2265 var $description;
2266 var $items;
2267
2268 function admin_setting_special_editorhidebuttons() {
2269 $this->name = 'editorhidebuttons';
2270 $this->visiblename = get_string('editorhidebuttons', 'admin');
2271 $this->description = get_string('confeditorhidebuttons', 'admin');
2272 $this->defaultsetting = array();
2273 // weird array... buttonname => buttonimage (assume proper path appended). if you leave buttomimage blank, text will be printed instead
2274 $this->items = array('fontname' => '',
2275 'fontsize' => '',
2276 'formatblock' => '',
2277 'bold' => 'ed_format_bold.gif',
2278 'italic' => 'ed_format_italic.gif',
2279 'underline' => 'ed_format_underline.gif',
2280 'strikethrough' => 'ed_format_strike.gif',
2281 'subscript' => 'ed_format_sub.gif',
2282 'superscript' => 'ed_format_sup.gif',
2283 'copy' => 'ed_copy.gif',
2284 'cut' => 'ed_cut.gif',
2285 'paste' => 'ed_paste.gif',
2286 'clean' => 'ed_wordclean.gif',
2287 'undo' => 'ed_undo.gif',
2288 'redo' => 'ed_redo.gif',
2289 'justifyleft' => 'ed_align_left.gif',
2290 'justifycenter' => 'ed_align_center.gif',
2291 'justifyright' => 'ed_align_right.gif',
2292 'justifyfull' => 'ed_align_justify.gif',
2293 'lefttoright' => 'ed_left_to_right.gif',
2294 'righttoleft' => 'ed_right_to_left.gif',
2295 'insertorderedlist' => 'ed_list_num.gif',
2296 'insertunorderedlist' => 'ed_list_bullet.gif',
2297 'outdent' => 'ed_indent_less.gif',
2298 'indent' => 'ed_indent_more.gif',
2299 'forecolor' => 'ed_color_fg.gif',
2300 'hilitecolor' => 'ed_color_bg.gif',
2301 'inserthorizontalrule' => 'ed_hr.gif',
2302 'createanchor' => 'ed_anchor.gif',
2303 'createlink' => 'ed_link.gif',
2304 'unlink' => 'ed_unlink.gif',
2305 'insertimage' => 'ed_image.gif',
2306 'inserttable' => 'insert_table.gif',
2307 'insertsmile' => 'em.icon.smile.gif',
2308 'insertchar' => 'icon_ins_char.gif',
2309 'spellcheck' => 'spell-check.gif',
2310 'htmlmode' => 'ed_html.gif',
2311 'popupeditor' => 'fullscreen_maximize.gif',
2312 'search_replace' => 'ed_replace.gif');
2313 }
2314
2315 function get_setting() {
2316 global $CFG;
2317 return (isset($CFG->{$this->name}) ? explode(' ', $CFG->{$this->name}) : NULL);
2318 }
2319
2320 function write_setting($data) {
2321 $result = array();
2322 if (empty($data)) { $data = array(); }
2323 foreach ($data as $key => $value) {
2324 if (!in_array($key, array_keys($this->items))) {
2325 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2326 }
2327 if ($value == '1') {
2328 $result[] = $key;
2329 }
2330 }
2331 return (set_config($this->name, implode(' ',$result)) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2332 }
2333
2334 function output_html() {
eef868d1 2335
6e4dc10f 2336 global $CFG;
eef868d1 2337
6e4dc10f 2338 // checkboxes with input name="$this->name[$key]" value="1"
2339 // we do 15 fields per column
eef868d1 2340
cc73de71 2341 if ($this->get_setting() === NULL) {
2342 $currentsetting = $this->defaultsetting;
2343 } else {
2344 $currentsetting = $this->get_setting();
6e4dc10f 2345 }
eef868d1 2346
1beed35f 2347 $return = '<div class="form-group">';
2348 $return .= '<table><tr><td valign="top" align="right">';
eef868d1 2349
6e4dc10f 2350 $count = 0;
eef868d1 2351
6e4dc10f 2352 foreach($this->items as $key => $value) {
8ddbd7a6 2353 if ($count % 15 == 0 and $count != 0) {
2354 $return .= '</td><td valign="top" align="right">';
6e4dc10f 2355 }
eef868d1 2356
6e4dc10f 2357 $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 2358 $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 2359 $count++;
2360 if ($count % 15 != 0) {
2361 $return .= '<br /><br />';
2362 }
2363 }
eef868d1 2364
2365 $return .= '</td></tr>';
6e4dc10f 2366 $return .= '</table>';
1beed35f 2367 $return .= '</div>';
6e4dc10f 2368
60a9a6ea 2369 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
6e4dc10f 2370 }
2371
2372}
2373
4642650f 2374class admin_setting_langlist extends admin_setting_configtext {
2375 function admin_setting_langlist() {
2376 parent::admin_setting_configtext('langlist', get_string('langlist', 'admin'), get_string('configlanglist', 'admin'), '', PARAM_NOTAGS);
2377 }
2378
2379 function write_setting($data) {
2380 $return = parent::write_setting($data);
2381 get_list_of_languages(true);//refresh the list
2382 return $return;
2383 }
2384}
2385
6e4dc10f 2386class admin_setting_backupselect extends admin_setting_configselect {
2387
2388 function admin_setting_backupselect($name, $visiblename, $description, $default, $choices) {
2389 parent::admin_setting_configselect($name, $visiblename, $description, $default, $choices);
2390 }
2391
2392 function get_setting() {
2393 $backup_config = backup_get_config();
2394 return (isset($backup_config->{$this->name}) ? $backup_config->{$this->name} : NULL);
2395 }
eef868d1 2396
6e4dc10f 2397 function write_setting($data) {
2398 // check that what we got was in the original choices
2399 if (! in_array($data, array_keys($this->choices))) {
2400 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2401 }
eef868d1 2402
6e4dc10f 2403 return (backup_set_config($this->name, $data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2404 }
2405
2406}
2407
2408class admin_setting_special_backupsaveto extends admin_setting_configtext {
2409
2410 function admin_setting_special_backupsaveto() {
2411 $name = 'backup_sche_destination';
2412 $visiblename = get_string('saveto');
2413 $description = get_string('backupsavetohelp');
348d6827 2414 parent::admin_setting_configtext($name, $visiblename, $description, '');
6e4dc10f 2415 }
eef868d1 2416
6e4dc10f 2417 function get_setting() {
2418 $backup_config = backup_get_config();
2419 return (isset($backup_config->{$this->name}) ? $backup_config->{$this->name} : NULL);
2420 }
eef868d1 2421
6e4dc10f 2422 function write_setting($data) {
348d6827 2423 $data = trim($data);
2424 if (!empty($data) and !is_dir($data)) {
6e4dc10f 2425 return get_string('pathnotexists') . '<br />';
2426 }
2427 return (backup_set_config($this->name, $data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2428 }
2429
2430}
2431
2432class admin_setting_backupcheckbox extends admin_setting_configcheckbox {
2433
2434 function admin_setting_backupcheckbox($name, $visiblename, $description, $default) {
2435 parent::admin_setting_configcheckbox($name, $visiblename, $description, $default);
2436 }
2437
2438 function write_setting($data) {
2439 if ($data == '1') {
2440 return (backup_set_config($this->name, 1) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2441 } else {
2442 return (backup_set_config($this->name, 0) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2443 }
2444 }
eef868d1 2445
6e4dc10f 2446 function get_setting() {
2447 $backup_config = backup_get_config();
2448 return (isset($backup_config->{$this->name}) ? $backup_config->{$this->name} : NULL);
2449 }
2450
2451}
2452
2453class admin_setting_special_backuptime extends admin_setting_configtime {
2454
2455 function admin_setting_special_backuptime() {
2456 $name = 'backup_sche_hour';
2457 $name2 = 'backup_sche_minute';
2458 $visiblename = get_string('executeat');
2459 $description = get_string('backupexecuteathelp');
2460 $default = array('h' => 0, 'm' => 0);
2461 parent::admin_setting_configtime($name, $name2, $visiblename, $description, $default);
2462 }
eef868d1 2463
6e4dc10f 2464 function get_setting() {
2465 $backup_config = backup_get_config();
9fd9df20 2466 return (isset($backup_config->{$this->name}) && isset($backup_config->{$this->name}) ? array('h'=>$backup_config->{$this->name}, 'm'=>$backup_config->{$this->name2}) : NULL);
6e4dc10f 2467 }
eef868d1 2468
6e4dc10f 2469 function write_setting($data) {
2470 // check that what we got was in the original choices
2471 if (!(in_array($data['h'], array_keys($this->choices)) && in_array($data['m'], array_keys($this->choices2)))) {
2472 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2473 }
eef868d1 2474
2475 return (backup_set_config($this->name, $data['h']) && backup_set_config($this->name2, $data['m']) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
6e4dc10f 2476 }
eef868d1 2477
6e4dc10f 2478}
2479
2480class admin_setting_special_backupdays extends admin_setting {
2481
2482 function admin_setting_special_backupdays() {
2483 $name = 'backup_sche_weekdays';
2484 $visiblename = get_string('schedule');
2485 $description = get_string('backupschedulehelp');
6727c175 2486 $default = array('u' => 0, 'm' => 0, 't' => 0, 'w' => 0, 'r' => 0, 'f' => 0, 's' => 0);
2487 parent::admin_setting($name, $visiblename, $description, $default);
6e4dc10f 2488 }
eef868d1 2489
6e4dc10f 2490 function get_setting() {
2491 $backup_config = backup_get_config();
cc73de71 2492 if (isset($backup_config->{$this->name})) {
2493 $currentsetting = $backup_config->{$this->name};
2494 return array('u' => substr($currentsetting, 0, 1),
2495 'm' => substr($currentsetting, 1, 1),
2496 't' => substr($currentsetting, 2, 1),
2497 'w' => substr($currentsetting, 3, 1),
2498 'r' => substr($currentsetting, 4, 1),
2499 'f' => substr($currentsetting, 5, 1),
2500 's' => substr($currentsetting, 6, 1));
2501 } else {
2502 return NULL;
2503 }
6e4dc10f 2504 }
eef868d1 2505
6e4dc10f 2506 function output_html() {
eef868d1 2507
cc73de71 2508 if ($this->get_setting() === NULL) {
2509 $currentsetting = $this->defaultsetting;
2510 } else {
2511 $currentsetting = $this->get_setting();
6e4dc10f 2512 }
eef868d1 2513
cc73de71 2514 // rewrite for simplicity
eef868d1 2515 $currentsetting = $currentsetting['u'] . $currentsetting['m'] . $currentsetting['t'] . $currentsetting['w'] .
cc73de71 2516 $currentsetting['r'] . $currentsetting['f'] . $currentsetting['s'];
eef868d1 2517
60a9a6ea 2518 $return = '<table><tr><td><div style="text-align:center">&nbsp;&nbsp;' . get_string('sunday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div style="text-align:center">&nbsp;&nbsp;' .
2519 get_string('monday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div style="text-align:center">&nbsp;&nbsp;' . get_string('tuesday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div style="text-align:center">&nbsp;&nbsp;' .
2520 get_string('wednesday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div style="text-align:center">&nbsp;&nbsp;' . get_string('thursday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div style="text-align:center">&nbsp;&nbsp;' .
2521 get_string('friday', 'calendar') . '&nbsp;&nbsp;</div></td><td><div style="text-align:center">&nbsp;&nbsp;' . get_string('saturday', 'calendar') . '&nbsp;&nbsp;</div></td></tr><tr>' .
2522 '<td><div style="text-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>' .
2523 '<td><div style="text-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>' .
2524 '<td><div style="text-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>' .
2525 '<td><div style="text-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>' .
2526 '<td><div style="text-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>' .
2527 '<td><div style="text-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>' .
2528 '<td><div style="text-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 2529 '</tr></table>';
2530
60a9a6ea 2531 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
eef868d1 2532
6e4dc10f 2533 }
eef868d1 2534
6e4dc10f 2535 // 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
2536 // admin_settingpage (note that admin_settingpage only calls write_setting with the data that matches $this->name... so if we have multiple form fields,
2537 // they MUST go into an array named $this->name, or else we won't receive them here
2538 function write_setting($data) {
2539 $week = 'umtwrfs';
2540 $result = array(0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0);
9fd9df20 2541 if (!empty($data)) {
2542 foreach($data as $key => $value) {
2543 if ($value == '1') {
2544 $result[strpos($week, $key)] = 1;
2545 }
2546 }
6e4dc10f 2547 }
2548 return (backup_set_config($this->name, implode('',$result)) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2549 }
2550}
2551
ee437bbc 2552class admin_setting_special_debug extends admin_setting_configselect {
6e4dc10f 2553
2554 function admin_setting_special_debug() {
2555 $name = 'debug';
2556 $visiblename = get_string('debug', 'admin');
2557 $description = get_string('configdebug', 'admin');
7eb0b60a 2558 $choices = array( DEBUG_NONE => get_string('debugnone', 'admin'),
2559 DEBUG_MINIMAL => get_string('debugminimal', 'admin'),
2560 DEBUG_NORMAL => get_string('debugnormal', 'admin'),
38d2d43b 2561 DEBUG_ALL => get_string('debugall', 'admin'),
2562 DEBUG_DEVELOPER => get_string('debugdeveloper', 'admin')
ee437bbc 2563 );
2564 parent::admin_setting_configselect($name, $visiblename, $description, '', $choices);
6e4dc10f 2565 }
2566
ee437bbc 2567 function get_setting() {
2568 global $CFG;
cc73de71 2569 if (isset($CFG->debug)) {
cc73de71 2570 return $CFG->debug;
2571 } else {
2572 return NULL;
ee437bbc 2573 }
6e4dc10f 2574 }
2575
ee437bbc 2576 function write_setting($data) {
2577 return (set_config($this->name,$data) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
6e4dc10f 2578 }
2579
2580}
2581
2582
2583class admin_setting_special_calendar_weekend extends admin_setting {
2584
2585 function admin_setting_special_calendar_weekend() {
2586 $name = 'calendar_weekend';
2587 $visiblename = get_string('calendar_weekend', 'admin');
2588 $description = get_string('helpweekenddays', 'admin');
5eaa6aa0 2589 $default = array ('0', '6'); // Saturdays and Sundays
b91b1f92 2590 parent::admin_setting($name, $visiblename, $description, $default);
6e4dc10f 2591 }
2592
2593 function get_setting() {
2594 global $CFG;
4af8d5d3 2595 return isset($CFG->{$this->name}) ? $CFG->{$this->name} : 0;
6e4dc10f 2596 }
eef868d1 2597
6e4dc10f 2598 function write_setting($data) {
4af8d5d3 2599 $result = 0;
b91b1f92 2600 if (!empty($data)) {
4af8d5d3 2601 foreach($data as $index) {
2602 $result |= 1 << $index;
b91b1f92 2603 }
6e4dc10f 2604 }
4af8d5d3 2605 return (set_config($this->name, $result) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
6e4dc10f 2606 }
eef868d1 2607
6e4dc10f 2608 function output_html() {
cc73de71 2609 if ($this->get_setting() === NULL) {
2610 $currentsetting = $this->defaultsetting;
2611 } else {
2612 $currentsetting = $this->get_setting();
6e4dc10f 2613 }
cc73de71 2614
4af8d5d3 2615 // The order matters very much because of the implied numeric keys
2616 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
2617 $return = '<table><thead><tr>';
2618 foreach($days as $index => $day) {
2619 $return .= '<td><label for="id_s_'.$this->name.$index.'">'.get_string($day, 'calendar').'</label></td>';
2620 }
2621 $return .= '</tr></thead><tbody><tr>';
2622 foreach($days as $index => $day) {
2623 $return .= '<td><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.$index.'" name="s_'.$this->name.'[]" value="'.$index.'" '.($currentsetting & (1 << $index) ? 'checked="checked"' : '') . ' /></td>';
2624 }
2625 $return .= '</tr></tbody></table>';
6153cf58 2626
038bf621 2627 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
eef868d1 2628
6e4dc10f 2629 }
2630
2631}
2632
3d5c00b3 2633/**
2634 * this is used in config->grades
5a412dbf 2635 */
0909d44e 2636class admin_setting_special_gradebookroles extends admin_setting {
5a412dbf 2637
0909d44e 2638 function admin_setting_special_gradebookroles() {
2639 $name = 'gradebookroles';
73afaf5b 2640 $visiblename = get_string('gradebookroles', 'admin');
2641 $description = get_string('configgradebookroles', 'admin');
7aa3e196 2642 $default = array(5=>'1'); // The student role in a default install
8a2cb2fa 2643 parent::admin_setting($name, $visiblename, $description, $default);
5a412dbf 2644 }
2645
2646 function get_setting() {
2647 global $CFG;
8a2cb2fa 2648 if (!empty($CFG->{$this->name})) {
60f7d402 2649 $result = explode(',', $CFG->{$this->name});
2650 foreach ($result as $roleid) {
9ba38673 2651 $array[$roleid] = 1;
60f7d402 2652 }
2653 return $array;
5a412dbf 2654 } else {
3fae9f57 2655 return null;
5a412dbf 2656 }
2657 }
2658
2659 function write_setting($data) {
2660 if (!empty($data)) {
2661 $str = '';
0909d44e 2662 foreach ($data as $key => $value) {
5a412dbf 2663 if ($value) {
2664 $str .= $key.',';
2665 }
2666 }
2667 return set_config($this->name, rtrim($str, ","))?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2668 } else {
73afaf5b 2669 return set_config($this->name, '')?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2670 }
5a412dbf 2671 }
2672
2673 function output_html() {
2674
2675 if ($this->get_setting() === NULL) {
2676 $currentsetting = $this->defaultsetting;
2677 } else {
2678 $currentsetting = $this->get_setting();
2679 }
5a412dbf 2680 // from to process which roles to display
2681 if ($roles = get_records('role')) {
73afaf5b 2682 $return = '<div class="form-group">';
2683 $first = true;
2684 foreach ($roles as $roleid=>$role) {
60f7d402 2685 if (is_array($currentsetting) && in_array($roleid, array_keys($currentsetting))) {
fb132873 2686 $checked = ' checked="checked"';
5a412dbf 2687 } else {
73afaf5b 2688 $checked = '';
5a412dbf 2689 }
73afaf5b 2690 if ($first) {
2691 $first = false;
2692 } else {
2693 $return .= '<br />';
2694 }
b0abd282 2695 $return .= '<input type="checkbox" name="s_'.$this->name.'['.$roleid.']" value="1"'.$checked.' />&nbsp;'.format_string($role->name);
5a412dbf 2696 }
73afaf5b 2697 $return .= '</div>';
5a412dbf 2698 }
73afaf5b 2699
60a9a6ea 2700 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
5a412dbf 2701
2702 }
2703
2704}
6e4dc10f 2705
d42c64ba 2706/*
2707 * this is used in config->appearance->coursemanager
2708 * (which roles to show on course decription page)
2709 */
2710class admin_setting_special_coursemanager extends admin_setting {
2711
2712 function admin_setting_special_coursemanager() {
2713 $name = 'coursemanager';
2714 $visiblename = get_string('coursemanager', 'admin');
2715 $description = get_string('configcoursemanager', 'admin');
2716 $default = array(3=>'1'); // The teahcer role in a default install
2717 parent::admin_setting($name, $visiblename, $description, $default);
2718 }
2719
2720 function get_setting() {
2721
2722 global $CFG;
2723 if (!empty($CFG->{$this->name})) {
2724 $result = explode(',', $CFG->{$this->name});
2725 foreach ($result as $roleid) {
9ba38673 2726 $array[$roleid] = 1;
d42c64ba 2727 }
2728 return $array;
b107549c 2729 } else if (isset($CFG->{$this->name})) {
2730 return array();
d42c64ba 2731 } else {
2732 return null;
2733 }
2734 }
2735
2736 function write_setting($data) {
2737
2738 if (!empty($data)) {
2739 $str = '';
2740 foreach ($data as $key => $value) {
2741 if ($value) {
2742 $str .= $key.',';
2743 }
2744 }
2745 return set_config($this->name, rtrim($str, ","))?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2746 } else {
2747 return set_config($this->name, '')?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2748 }
2749 }
2750
2751 function output_html() {
2752
2753 if ($this->get_setting() === NULL) {
2754 $currentsetting = $this->defaultsetting;
2755 } else {
2756 $currentsetting = $this->get_setting();
2757 }
2758 // from to process which roles to display
d717df34 2759 if ($roles = get_records_select('role', '', 'sortorder')) {
d42c64ba 2760 $return = '<div class="form-group">';
2761 $first = true;
2762 foreach ($roles as $roleid=>$role) {
2763 if (is_array($currentsetting) && in_array($roleid, array_keys($currentsetting))) {
2764 $checked = 'checked="checked"';
2765 } else {
2766 $checked = '';
2767 }
2768 if ($first) {
2769 $first = false;
2770 } else {
2771 $return .= '<br />';
2772 }
7203167d 2773 $return .= '<input type="checkbox" name="s_'.$this->name.'['.$roleid.']" value="1" '.$checked.' />&nbsp;'.$role->name;
d42c64ba 2774 }
2775 $return .= '</div>';
2776 }
60a9a6ea 2777 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
d42c64ba 2778 }
2779}
2780
76127f37 2781/*
2782 * this is used in config->courses->gradeexports
2783 * (which roles to show on course decription page)
2784 */
2785class admin_setting_special_gradeexport extends admin_setting {
2786
2787 function admin_setting_special_gradeexport() {
2788 $name = 'gradeexport';
2789 $visiblename = get_string('gradeexport', 'admin');
2790 $description = get_string('configgradeexport', 'admin');
2791 $default = array(3=>'1'); // The teahcer role in a default install
2792 parent::admin_setting($name, $visiblename, $description, $default);
2793 }
2794
2795 function get_setting() {
2796
2797 global $CFG;
2798 if (!empty($CFG->{$this->name})) {
2799 $result = explode(',', $CFG->{$this->name});
2800 foreach ($result as $plugin) {
9ba38673 2801 $array[$plugin] = 1;
76127f37 2802 }
2803 return $array;
2804 } else if (isset($CFG->{$this->name})) {
2805 return array();
2806 } else {
2807 return null;
2808 }
2809 }
2810
2811 function write_setting($data) {
2812
2813 if (!empty($data)) {
2814 $str = '';
2815 foreach ($data as $key => $value) {
2816 if ($value) {
2817 $str .= $key.',';
2818 }
2819 }
2820 return set_config($this->name, rtrim($str, ","))?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2821 } else {
2822 return set_config($this->name, '')?'':get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2823 }
2824 }
2825
2826 function output_html() {
2827
2828 if ($this->get_setting() === NULL) {
2829 $currentsetting = $this->defaultsetting;
2830 } else {
2831 $currentsetting = $this->get_setting();
2832 }
2833 // from to process which roles to display
2834 if ($exports = get_list_of_plugins('grade/export')) {
2835 $return = '<div class="form-group">';
2836 $first = true;
2837 foreach ($exports as $export) {
2838 if (is_array($currentsetting) && in_array($export, array_keys($currentsetting))) {
2839 $checked = 'checked="checked"';
2840 } else {
2841 $checked = '';
2842 }
2843 if ($first) {
2844 $first = false;
2845 } else {
2846 $return .= '<br />';
2847 }
2848 $return .= '<input type="checkbox" name="s_'.$this->name.'['.$export.']" value="1" '.$checked.' />&nbsp;'.$export;
2849 }
2850 $return .= '</div>';
2851 }
2852 return format_admin_setting($this->name, $this->visiblename, $return, $this->description, false);
2853 }
2854}
2855
2856
2857
2858
6e4dc10f 2859class admin_setting_special_perfdebug extends admin_setting_configcheckbox {
2860
2861 function admin_setting_special_perfdebug() {
2862 $name = 'perfdebug';
2863 $visiblename = get_string('perfdebug', 'admin');
2864 $description = get_string('configperfdebug', 'admin');
2865 parent::admin_setting_configcheckbox($name, $visiblename, $description, '');
2866 }
2867
2868 function write_setting($data) {
d42c64ba 2869
6e4dc10f 2870 if ($data == '1') {
2871 return (set_config($this->name,15) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2872 } else {
2873 return (set_config($this->name,7) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2874 }
2875 }
2876
2877 function output_html() {
d42c64ba 2878
cc73de71 2879 if ($this->get_setting() === NULL) {
2880 $currentsetting = $this->defaultsetting;
2881 } else {
2882 $currentsetting = $this->get_setting();
2883 }
eef868d1 2884
3c6f7a78 2885 $return = '<input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'" name="s_'. $this->name .'" value="1" ' . ($currentsetting == 15 ? 'checked="checked"' : '') . ' />';
fc52aa6e 2886 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
6e4dc10f 2887 }
2888
2889}
2890
47b8b9eb 2891class admin_setting_special_debugdisplay extends admin_setting_configcheckbox {
2892
2893 function admin_setting_special_debugdisplay() {
2894 $name = 'debugdisplay';
2895 $visiblename = get_string('debugdisplay', 'admin');
2896 $description = get_string('configdebugdisplay', 'admin');
6349a3ba 2897 $default = ini_get('display_errors');
2898 parent::admin_setting_configcheckbox($name, $visiblename, $description, $default);
47b8b9eb 2899 }
2900
2901 function write_setting($data) {
2902
2903 if ($data == '1') {
2904 return (set_config($this->name,1) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2905 } else {
2906 return (set_config($this->name,0) ? '' : get_string('errorsetting', 'admin') . $this->visiblename . '<br />');
2907 }
2908 }
2909
2910 function output_html() {
2911
2912 if ($this->get_setting() === NULL) {
6349a3ba 2913 $currentsetting = $this->defaultsetting;
47b8b9eb 2914 } else {
2915 $currentsetting = $this->get_setting();
2916 }
2917
2918 $return = '<input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'" name="s_'. $this->name .'" value="1" ' . ($currentsetting == 1 ? 'checked="checked"' : '') . ' />';
2919 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
2920 }
2921
2922}
2923
89a5f827 2924
190af29f 2925class admin_setting_gradecat_combo extends admin_setting {
2926
2927 var $choices;
2928
2929 function admin_setting_gradecat_combo($name, $visiblename, $description, $defaultsetting, $choices) {
2930 $this->choices = $choices;
2931 parent::admin_setting($name, $visiblename, $description, $defaultsetting);
2932 }
2933
2934 function get_setting() {
2935 global $CFG;
2936
2937 if (!isset($CFG->{$this->name}) or !isset($CFG->{$this->name.'_flag'})) {
2938 return NULL;
2939 }
2940
2941 $flag = (int)$CFG->{$this->name.'_flag'};
2942 $forced = (boolean)(1 & $flag); // first bit
2943 $adv = (boolean)(2 & $flag); // second bit
2944
2945 return array('value' => $CFG->{$this->name}, 'forced' => $forced, 'adv' => $adv);
89a5f827 2946 }
2947
2948 function write_setting($data) {
190af29f 2949 global $CFG;
89a5f827 2950
190af29f 2951 $value = $data['value'];
2952 $forced = empty($data['forced']) ? 0 : 1;
2953 $adv = empty($data['adv']) ? 0 : 2;
2954 $flag = ($forced | $adv); //bitwise or
2955
2956 if (!in_array($value, array_keys($this->choices))) {
2957 return 'Error setting ' . $this->visiblename . '<br />';
2958 }
89a5f827 2959
190af29f 2960 $oldvalue = get_config(NULL, $this->name);
2961 $oldflag = (int)get_config(NULL, $this->name.'_flag');
2962 $oldforced = (1 & $oldflag); // first bit
89a5f827 2963
190af29f 2964 $result = (boolean)set_config($this->name, $value);
2965 $result = $result && (boolean)set_config($this->name.'_flag', $flag);
2966
2967 if ($result) {
2968 // force regrade if needed
2969 if ($oldforced != $forced or ($forced and $value != $oldvalue)) {
2970 require_once($CFG->libdir.'/gradelib.php');
2971 grade_category::updated_forced_settings();
2972 }
2973
2974 return '';
2975 } else {
2976 return get_string('errorsetting', 'admin') . $this->visiblename . '<br />';
2977 }
2978 }
2979
2980 function output_html() {
2981
2982 if ($this->get_setting() === NULL) {
2983 $current = $this->defaultsetting;
2984 } else {
2985 $current = $this->get_setting();
2986 }
2987 $value = $current['value'];
2988 $forced = !empty($current['forced']);
2989 $adv = !empty($current['adv']);
2990
2991 $return = '<select class="form-select" id="id_s_'.$this->name.'" name="s_' . $this->name .'[value]">';
2992 foreach ($this->choices as $key => $val) {
2993 // the string cast is needed because key may be integer - 0 is equal to most strings!
2994 $return .= '<option value="'.$key.'"'.((string)$key==$value ? ' selected="selected"' : '').'>'.$val.'</option>';
2995 }
3d5c00b3 2996 $return .= '</select>';
190af29f 2997 $return .= '<label for="id_s_'.$this->name.'force">'.get_string('force').'</label><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'force" name="s_'.$this->name.'[forced]" value="1" ' . ($forced ? 'checked="checked"' : '') . ' />';
2998 $return .= '<label for="id_s_'.$this->name.'adv">'.get_string('advanced').'</label><input type="checkbox" class="form-checkbox" id="id_s_'.$this->name.'adv" name="s_'.$this->name.'[adv]" value="1" ' . ($adv ? 'checked="checked"' : '') . ' />';
2999
3000 return format_admin_setting($this->name, $this->visiblename, $return, $this->description);
89a5f827 3001 }
3002}
3003
3d5c00b3 3004
0a784551 3005/**
3d5c00b3 3006 * Selection of grade report in user profile
0a784551 3007 */
3008class admin_setting_grade_profilereport extends admin_setting_configselect {
3009 function admin_setting_grade_profilereport() {
3010 parent::admin_setting_configselect('grade_profilereport', get_string('profilereport', 'grades'), get_string('configprofilereport', 'grades'), 'user', null);
3011 }
3012
3013 function load_choices() {
3014 if (!empty($this->choices)) {
3015 return;
3016 }
3017 $this->choices = array();
3018
3019 global $CFG;
3020 require_once($CFG->libdir.'/gradelib.php');
3021
3022 foreach (get_list_of_plugins('grade/report') as $plugin) {
3023 if (file_exists($CFG->dirroot.'/grade/report/'.$plugin.'/lib.php')) {
3024 require_once($CFG->dirroot.'/grade/report/'.$plugin.'/lib.php');
3025 $functionname = 'grade_report_'.$plugin.'_profilereport';
3026 if (function_exists($functionname)) {
3027 $this->choices[$plugin] = get_string('modulename', 'gradereport_'.$plugin, NULL, $CFG->dirroot.'/grade/report/'.$plugin.'/lang/');
3028 }
3029 }
3030 }
3031 }
3032}
3033
47b8b9eb 3034
6e4dc10f 3035// Code for a function that helps externalpages print proper headers and footers
3036// N.B.: THIS FUNCTION HANDLES AUTHENTICATION
1ae083e4 3037function admin_externalpage_setup($section) {
6e4dc10f 3038
3039 global $CFG, $PAGE, $USER;
eef868d1 3040
1ae083e4 3041 $adminroot = admin_get_root();
3042
6e4dc10f 3043 require_once($CFG->libdir . '/blocklib.php');
02cc05a7 3044 require_once($CFG->dirroot . '/'.$CFG->admin.'/pagelib.php');
eef868d1 3045
02cc05a7 3046 page_map_class(PAGE_ADMIN, 'page_admin');
6e4dc10f 3047
e9a20759 3048 $PAGE = page_create_object(PAGE_ADMIN, 0); // there must be any constant id number
6e4dc10f 3049
02cc05a7 3050 $PAGE->init_extra($section); // hack alert!
6e4dc10f 3051
3052 $root = $adminroot->locate($PAGE->section);
3053
3054 if ($site = get_site()) {
3055 require_login();
3056 } else {
6859360c 3057 redirect($CFG->wwwroot . '/'.$CFG->admin.'/index.php');
6e4dc10f 3058 die;
3059 }
3060
3061 if (!is_a($root, 'admin_externalpage')) {
3062 error(get_string('sectionerror','admin'));
3063 die;
3064 }
3065
3066 // this eliminates our need to authenticate on the actual pages
3067 if (!($root->check_access())) {
3068 error(get_string('accessdenied', 'admin'));
3069 die;
3070 }
eef868d1 3071
6e4dc10f 3072 $adminediting = optional_param('adminedit', -1, PARAM_BOOL);
eef868d1 3073
6e4dc10f 3074 if (!isset($USER->adminediting)) {
3075 $USER->adminediting = false;
3076 }
eef868d1 3077
6e4dc10f 3078 if ($PAGE->user_allowed_editing()) {
3079 if ($adminediting == 1) {
3080 $USER->adminediting = true;
3081 } elseif ($adminediting == 0) {
3082 $USER->adminediting = false;
3083 }
3084 }
eef868d1 3085
6e4dc10f 3086}
3087
f1af7aaa 3088/**
3089 * TODO document
3090 */
1ae083e4 3091function admin_externalpage_print_header() {
6e4dc10f 3092
ce821fda 3093 global $CFG, $PAGE, $SITE, $THEME;
9ba38673 3094
1ae083e4 3095 define('ADMIN_EXT_HEADER_PRINTED', 'true');
3096
b1ce7811 3097 if (!empty($SITE->fullname)) {
3098 $pageblocks = blocks_setup($PAGE);
6e4dc10f 3099
e524c0ed 3100 $preferred_width_left = bounded_number(BLOCK_L_MIN_WIDTH,
3101 blocks_preferred_width($pageblocks[BLOCK_POS_LEFT]),
b1ce7811 3102 BLOCK_L_MAX_WIDTH);
9f7f1a74 3103 $preferred_width_right = bounded_number(BLOCK_R_MIN_WIDTH,
3104 blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT]),
3105 BLOCK_R_MAX_WIDTH);
3106
b1ce7811 3107 $PAGE->print_header();
5577ceb3 3108 echo '<table id="layout-table" summary=""><tr>';
f1af7aaa 3109
5730bc61 3110 $lt = (empty($THEME->layouttable)) ? array('left', 'middle', 'right') : $THEME->layouttable;
3111 foreach ($lt as $column) {
3112 $lt1[] = $column;
3113 if ($column == 'middle') break;
3114 }
3115 foreach ($lt1 as $column) {
3116 switch ($column) {
3117 case 'left':
d795bfdb 3118 echo '<td style="width: '.$preferred_width_left.'px;" id="left-column">';
3119 print_container_start();
3120 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT);
3121 print_container_end();
3122 echo '</td>';
5730bc61 3123 break;
f1af7aaa 3124
5730bc61 3125 case 'middle':
d795bfdb 3126 echo '<td id="middle-column">';
3127 print_container_start(true);
3128 $THEME->open_header_containers++; // this is hacky workaround for the error()/notice() autoclosing problems on admin pages
5730bc61 3129 break;
f1af7aaa 3130
5730bc61 3131 case 'right':
d795bfdb 3132 if (blocks_have_content($pageblocks, BLOCK_POS_RIGHT)) {
3133 echo '<td style="width: '.$preferred_width_right.'px;" id="right-column">';
3134 print_container_start();
3135 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT);
3136 print_container_end();
3137 echo '</td>';
3138 }
5730bc61 3139 break;
3140 }
3141 }
b1ce7811 3142 } else {
3143 print_header();
3144 }
6e4dc10f 3145}
3146
1ae083e4 3147function admin_externalpage_print_footer() {
6e4dc10f 3148
ce821fda 3149 global $CFG, $PAGE, $SITE, $THEME;
9ba38673 3150
1ae083e4 3151 define('ADMIN_EXT_FOOTER_PRINTED', 'true');
3152
b1ce7811 3153 if (!empty($SITE->fullname)) {
3154 $pageblocks = blocks_setup($PAGE);
9f7f1a74 3155 $preferred_width_left = bounded_number(BLOCK_L_MIN_WIDTH,
3156 blocks_preferred_width($pageblocks[BLOCK_POS_LEFT]),
3157 BLOCK_L_MAX_WIDTH);
e524c0ed 3158 $preferred_width_right = bounded_number(BLOCK_R_MIN_WIDTH,
3159 blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT]),
b1ce7811 3160 BLOCK_R_MAX_WIDTH);
5730bc61 3161
3162 $lt = (empty($THEME->layouttable)) ? array('left', 'middle', 'right') : $THEME->layouttable;
3163 foreach ($lt as $column) {
3164 if ($column != 'middle') {
3165 array_shift($lt);
3166 } else if ($column == 'middle') {
3167 break;
3168 }
3169 }
3170 foreach ($lt as $column) {
3171 switch ($column) {
3172 case 'left':
d795bfdb 3173 echo '<td style="width: '.$preferred_width_left.'px;" id="left-column">';
3174 print_container_start();
3175 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT);
3176 print_container_end();
3177 echo '</td>';
5730bc61 3178 break;
f1af7aaa 3179
5730bc61 3180 case 'middle':
d795bfdb 3181 print_container_end();
3182 $THEME->open_header_containers--; // this is hacky workaround for the error()/notice() autoclosing problems on admin pages
3183 echo '</td>';
5730bc61 3184 break;
f1af7aaa 3185
5730bc61 3186 case 'right':
d795bfdb 3187 if (blocks_have_content($pageblocks, BLOCK_POS_RIGHT)) {
3188 echo '<td style="width: '.$preferred_width_right.'px;" id="right-column">';
3189 print_container_start();
3190 blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT);
3191 print_container_end();
3192 echo '</td>';
3193 }
5730bc61 3194 break;
3195 }
ce821fda 3196 }
ec3938f3 3197 echo '</tr></table>';
b1ce7811 3198 }
6e4dc10f 3199 print_footer();
6e4dc10f 3200}
3201
3202function admin_get_root() {
3203 global $CFG;
3204
3205 static $ADMIN;
3206
3207 if (!isset($ADMIN)) {
3208 // start the admin tree!
2058a0a1 3209 $ADMIN = new admin_category('root', get_string("administration"));
6e4dc10f 3210 // we process this file first to get categories up and running
6859360c 3211 include($CFG->dirroot . '/'.$CFG->admin.'/settings/top.php');
6e4dc10f 3212
3213 // now we process all other files in admin/settings to build the
3214 // admin tree
6859360c 3215 foreach (glob($CFG->dirroot . '/'.$CFG->admin.'/settings/*.php') as $file) {
3216 if ($file != $CFG->dirroot . '/'.$CFG->admin.'/settings/top.php') {
6e4dc10f 3217 include_once($file);
3218 }
3219 }
3220 }
eef868d1 3221
6e4dc10f 3222 return $ADMIN;
3223}
3224
8e5da17a 3225/// settings utility functions
6e4dc10f 3226
8e5da17a 3227/**
3228 * This function applies default settings.
3229 * @param object $node
3230 * @param bool $uncoditional if true overrides all values with defaults
3231 * @return void
3232 */
3233function apply_default_settings(&$node, $unconditional=true) {
6e4dc10f 3234
3235 global $CFG;
3236
3237 if (is_a($node, 'admin_category')) {
3238 $entries = array_keys($node->children);
3239 foreach ($entries as $entry) {
3240 apply_default_settings($node->children[$entry]);
3241 }
3242 return;
eef868d1 3243 }
6e4dc10f 3244
eef868d1 3245 if (is_a($node, 'admin_settingpage')) {
6e4dc10f 3246 foreach ($node->settings as $setting) {
8e5da17a 3247 if (!$unconditional and !is_null($setting->get_setting)) {
3248 //do not override existing defaults
3249 continue;
3250 }
3251 $defaultsetting = $setting->get_defaultsetting();
3252 if (is_null($defaultsetting)) {
3253 // no value yet - default maybe applied after admin user creation or in upgradesettings
3254 continue;
3255 }
3256 $CFG->{$setting->name} = $defaultsetting;
3257 $setting->write_setting($defaultsetting);
6e4dc10f 3258 unset($setting); // needed to prevent odd (imho) reference behaviour
3259 // see http://www.php.net/manual/en/language.references.whatdo.php#AEN6399
3260 }
3261 return;
3262 }
3263
3264 return;
3265
3266}
3267
3268// n.b. this function unconditionally applies default settings
3269function apply_default_exception_settings($defaults) {
3270
3271 global $CFG;
3272
3273 foreach($defaults as $key => $value) {
3274 $CFG->$key = $value;
3275 set_config($key, $value);
3276 }
3277
3278}
3279
fbe31d22 3280function format_admin_setting($name, $title='', $form='', $description='', $label=true) {
9ba38673 3281
fbe31d22 3282 // sometimes the id is not id_s_name, but id_s_name_m or something, and this does not validate
3283 if ($label) {
9ba38673 3284 $labelfor = 'for = "id_s_'.$name.'"';
fbe31d22 3285 } else {
9ba38673 3286 $labelfor = '';
fbe31d22 3287 }
9ba38673 3288
fbe31d22 3289 $str = "\n".
fc52aa6e 3290 '<div class="form-item" id="admin-'.$name.'">'."\n".
fbe31d22 3291 '<label '.$labelfor.'>'.$title."\n".
6153cf58 3292 ' <span class="form-shortname">'.$name.'</span>'."\n".
3293 '</label>'."\n".
3294 $form."\n".
edb6cba4 3295 '<div class="description">'.$description.'</div>'."\n".
23586aca 3296 '</div>'.
3297 "\n\n";
9ba38673 3298
fbe31d22 3299 return $str;
2c8766df 3300}
3301
9ba38673 3302/*
d210e12e 3303 * Try to upgrade the given language pack (or current language)
3304 * If it doesn't work, fail silently and return false
3305 */
3306function upgrade_language_pack($lang='') {
3307 global $CFG;
3308
3309 if (empty($lang)) {
3310 $lang = current_language();
3311 }
3312
3313 if ($lang == 'en_utf8') {
3314 return true; // Nothing to do
3315 }
3316
3317 notify(get_string('langimport', 'admin').': '.$lang.' ... ', 'notifysuccess');
3318
3319 @mkdir ($CFG->dataroot.'/temp/'); //make it in case it's a fresh install, it might not be there
3320 @mkdir ($CFG->dataroot.'/lang/');
3321
3322 require_once($CFG->libdir.'/componentlib.class.php');
3323
3324 if ($cd = new component_installer('http://download.moodle.org', 'lang16', $lang.'.zip', 'languages.md5', 'lang')) {
3325 $status = $cd->install(); //returns ERROR | UPTODATE | INSTALLED
3326
3327 if ($status == INSTALLED) {
3328 debugging('Downloading successful: '.$lang);
3329 @unlink($CFG->dataroot.'/cache/languages');
3330 return true;
3331 }
3332 }
3333
3334 return false;
3335}
3336
2acc1f96 3337/**
3338 * Based on find_new_settings{@link ()} in upgradesettings.php
3339 * Looks to find any admin settings that have not been initialized. Returns 1 if it finds any.
3340 *
9ba38673 3341 * @param string &$node The node at which to start searching.
2acc1f96 3342 * @return int Returns 1 if any settings haven't been initialised, 0 if they all have
3343 */
3344function any_new_admin_settings(&$node) {
3345
3346 if (is_a($node, 'admin_category')) {
3347 $entries = array_keys($node->children);
3348 foreach ($entries as $entry) {
3349 if( any_new_admin_settings($node->children[$entry]) ){
3350 return 1;
3351 }
3352 }
3353 }
3354
3355 if (is_a($node, 'admin_settingpage')) {
3356 foreach ($node->settings as $setting) {
3357 if ($setting->get_setting() === NULL) {
3358 return 1;
3359 }
3360 }
3361 }
3362
3363
3364 return 0;
3365
3366}
3367
8f246961 3368
3369/**
3370 * Moved from admin/replace.php so that we can use this in cron
3371 * @param string $search - string to look for
3372 * @param string $replace - string to replace
3373 * @return bool - success or fail
3374 */
3375function db_replace($search, $replace) {
3376
3377 global $db, $CFG;
3378
3379 /// Turn off time limits, sometimes upgrades can be slow.
3380 @set_time_limit(0);
3381 @ob_implicit_flush(true);
3382 while(@ob_end_flush());
3383
3384 if (!$tables = $db->Metatables() ) { // No tables yet at all.
3385 return false;
3386 }
3387 foreach ($tables as $table) {
3388
3389 if (in_array($table, array($CFG->prefix.'config'))) { // Don't process these
3390 continue;
3391 }
3392
3393 if ($columns = $db->MetaColumns($table, false)) {
3394 foreach ($columns as $column => $data) {
3395 if (in_array($data->type, array('text','mediumtext','longtext','varchar'))) { // Text stuff only
3396 $db->debug = true;
3397 execute_sql("UPDATE $table SET $column = REPLACE($column, '$search', '$replace');");
3398 $db->debug = false;
3399 }
3400 }
3401 }
3402 }
3403
3404 return true;
3405}
3406
6153cf58 3407?>