FIxed counting of submissions
[moodle.git] / lib / moodlelib.php
CommitLineData
f9903ed0 1<?PHP // $Id$
2
9fa49e22 3///////////////////////////////////////////////////////////////////////////
4// //
5// moodlelib.php //
6// //
7// Main library file of miscellaneous general-purpose Moodle functions //
8// //
9// Other main libraries: //
10// //
11// weblib.php - functions that produce web output //
12// datalib.php - functions that access the database //
13// //
14///////////////////////////////////////////////////////////////////////////
15// //
16// NOTICE OF COPYRIGHT //
17// //
18// Moodle - Modular Object-Oriented Dynamic Learning Environment //
19// http://moodle.com //
20// //
21// Copyright (C) 2001-2003 Martin Dougiamas http://dougiamas.com //
22// //
23// This program is free software; you can redistribute it and/or modify //
24// it under the terms of the GNU General Public License as published by //
25// the Free Software Foundation; either version 2 of the License, or //
26// (at your option) any later version. //
27// //
28// This program is distributed in the hope that it will be useful, //
29// but WITHOUT ANY WARRANTY; without even the implied warranty of //
30// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
31// GNU General Public License for more details: //
32// //
33// http://www.gnu.org/copyleft/gpl.html //
34// //
35///////////////////////////////////////////////////////////////////////////
65ccdd8c 36
f374fb10 37/// CONSTANTS /////////////////////////////////////////////////////////////
38
39define('NOGROUPS', 0);
40define('SEPARATEGROUPS', 1);
41define('VISIBLEGROUPS', 2);
42
f9903ed0 43
9fa49e22 44/// PARAMETER HANDLING ////////////////////////////////////////////////////
6b174680 45
9fa49e22 46function require_variable($var) {
47/// Variable must be present
48 if (! isset($var)) {
49 error("A required parameter was missing");
6b174680 50 }
51}
52
9fa49e22 53function optional_variable(&$var, $default=0) {
54/// Variable may be present, if not then set a default
55 if (! isset($var)) {
56 $var = $default;
6b174680 57 }
58}
59
60
9fa49e22 61function set_config($name, $value) {
62/// No need for get_config because they are usually always available in $CFG
42282810 63 global $CFG;
64
65 $CFG->$name = $value; // So it's defined for this invocation at least
dfc9ba9b 66
9fa49e22 67 if (get_field("config", "name", "name", $name)) {
68 return set_field("config", "value", $value, "name", $name);
d897cae4 69 } else {
9fa49e22 70 $config->name = $name;
71 $config->value = $value;
72 return insert_record("config", $config);
39917a09 73 }
39917a09 74}
75
39917a09 76
9fa49e22 77/// FUNCTIONS FOR HANDLING TIME ////////////////////////////////////////////
39917a09 78
3db75c62 79function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0, $timezone=99) {
9fa49e22 80/// Given date parts in user time, produce a GMT timestamp
39917a09 81
94e34118 82 global $USER;
83
03c17ddf 84 if ($timezone == 99) {
94e34118 85 $timezone = (float)$USER->timezone;
86 }
87
88 if (abs($timezone) > 13) {
03c17ddf 89 return mktime((int)$hour,(int)$minute,(int)$second,(int)$month,(int)$day,(int)$year);
90 } else {
91 $time = gmmktime((int)$hour,(int)$minute,(int)$second,(int)$month,(int)$day,(int)$year);
92 return usertime($time, $timezone); // This is GMT
93 }
39917a09 94}
95
8dbed6be 96function format_time($totalsecs, $str=NULL) {
9fa49e22 97/// Given an amount of time in seconds, returns string
98/// formatted nicely as months, days, hours etc as needed
c7e3ac2a 99
6b174680 100 $totalsecs = abs($totalsecs);
c7e3ac2a 101
8dbed6be 102 if (!$str) { // Create the str structure the slow way
103 $str->day = get_string("day");
104 $str->days = get_string("days");
105 $str->hour = get_string("hour");
106 $str->hours = get_string("hours");
107 $str->min = get_string("min");
108 $str->mins = get_string("mins");
109 $str->sec = get_string("sec");
110 $str->secs = get_string("secs");
111 }
112
113 $days = floor($totalsecs/86400);
6b174680 114 $remainder = $totalsecs - ($days*86400);
8dbed6be 115 $hours = floor($remainder/3600);
6b174680 116 $remainder = $remainder - ($hours*3600);
8dbed6be 117 $mins = floor($remainder/60);
118 $secs = $remainder - ($mins*60);
119
120 $ss = ($secs == 1) ? $str->sec : $str->secs;
121 $sm = ($mins == 1) ? $str->min : $str->mins;
122 $sh = ($hours == 1) ? $str->hour : $str->hours;
123 $sd = ($days == 1) ? $str->day : $str->days;
124
9c9f7d77 125 $odays = "";
126 $ohours = "";
127 $omins = "";
128 $osecs = "";
129
8dbed6be 130 if ($days) $odays = "$days $sd";
131 if ($hours) $ohours = "$hours $sh";
132 if ($mins) $omins = "$mins $sm";
133 if ($secs) $osecs = "$secs $ss";
6b174680 134
135 if ($days) return "$odays $ohours";
136 if ($hours) return "$ohours $omins";
137 if ($mins) return "$omins $osecs";
138 if ($secs) return "$osecs";
139 return get_string("now");
140}
f9903ed0 141
61ae5d36 142function userdate($date, $format="", $timezone=99, $fixday = true) {
9fa49e22 143/// Returns a formatted string that represents a date in user time
144/// WARNING: note that the format is for strftime(), not date().
145/// Because of a bug in most Windows time libraries, we can't use
146/// the nicer %e, so we have to use %d which has leading zeroes.
147/// A lot of the fuss below is just getting rid of these leading
148/// zeroes as efficiently as possible.
61ae5d36 149///
150/// If parammeter fixday = true (default), then take off leading
151/// zero from %d, else mantain it.
7a302afc 152
873960de 153 global $USER;
154
5fa51a39 155 if ($format == "") {
dcde9f02 156 $format = get_string("strftimedaydatetime");
5fa51a39 157 }
035cdbff 158
dcde9f02 159 $formatnoday = str_replace("%d", "DD", $format);
61ae5d36 160 if ($fixday) {
161 $fixday = ($formatnoday != $format);
162 }
dcde9f02 163
5fa51a39 164 if ($timezone == 99) {
ab247495 165 if (isset($USER->timezone)) {
166 $timezone = (float)$USER->timezone;
167 }
5fa51a39 168 }
0431bd7c 169 if (abs($timezone) > 13) {
035cdbff 170 if ($fixday) {
171 $datestring = strftime($formatnoday, $date);
172 $daystring = str_replace(" 0", "", strftime(" %d", $date));
173 $datestring = str_replace("DD", $daystring, $datestring);
174 } else {
175 $datestring = strftime($format, $date);
176 }
bea7a51e 177 } else {
70d4cf82 178 $date = $date + (int)($timezone * 3600);
035cdbff 179 if ($fixday) {
70d4cf82 180 $datestring = gmstrftime($formatnoday, $date);
9fa49e22 181 $daystring = str_replace(" 0", "", gmstrftime(" %d", $date));
035cdbff 182 $datestring = str_replace("DD", $daystring, $datestring);
183 } else {
70d4cf82 184 $datestring = gmstrftime($format, $date);
035cdbff 185 }
873960de 186 }
bea7a51e 187
035cdbff 188 return $datestring;
873960de 189}
190
5fa51a39 191function usergetdate($date, $timezone=99) {
9fa49e22 192/// Given a $date timestamp in GMT, returns an array
193/// that represents the date in user time
6b174680 194
873960de 195 global $USER;
196
5fa51a39 197 if ($timezone == 99) {
198 $timezone = (float)$USER->timezone;
199 }
0431bd7c 200 if (abs($timezone) > 13) {
873960de 201 return getdate($date);
202 }
d2d6171f 203 //There is no gmgetdate so I have to fake it...
204 $date = $date + (int)($timezone * 3600);
205 $getdate["seconds"] = gmstrftime("%S", $date);
206 $getdate["minutes"] = gmstrftime("%M", $date);
207 $getdate["hours"] = gmstrftime("%H", $date);
208 $getdate["mday"] = gmstrftime("%d", $date);
209 $getdate["wday"] = gmstrftime("%u", $date);
210 $getdate["mon"] = gmstrftime("%m", $date);
211 $getdate["year"] = gmstrftime("%Y", $date);
212 $getdate["yday"] = gmstrftime("%j", $date);
213 $getdate["weekday"] = gmstrftime("%A", $date);
214 $getdate["month"] = gmstrftime("%B", $date);
215 return $getdate;
d552ead0 216}
217
218function usertime($date, $timezone=99) {
9fa49e22 219/// Given a GMT timestamp (seconds since epoch), offsets it by
220/// the timezone. eg 3pm in India is 3pm GMT - 7 * 3600 seconds
d552ead0 221 global $USER;
222
223 if ($timezone == 99) {
224 $timezone = (float)$USER->timezone;
225 }
0431bd7c 226 if (abs($timezone) > 13) {
d552ead0 227 return $date;
228 }
229 return $date - (int)($timezone * 3600);
230}
231
edf7fe8c 232function usergetmidnight($date, $timezone=99) {
9fa49e22 233/// Given a time, return the GMT timestamp of the most recent midnight
234/// for the current user.
edf7fe8c 235 global $USER;
236
4606d9bb 237 if ($timezone == 99) {
238 $timezone = (float)$USER->timezone;
239 }
240
edf7fe8c 241 $userdate = usergetdate($date, $timezone);
4606d9bb 242
0431bd7c 243 if (abs($timezone) > 13) {
4606d9bb 244 return mktime(0, 0, 0, $userdate["mon"], $userdate["mday"], $userdate["year"]);
245 }
246
edf7fe8c 247 $timemidnight = gmmktime (0, 0, 0, $userdate["mon"], $userdate["mday"], $userdate["year"]);
248 return usertime($timemidnight, $timezone); // Time of midnight of this user's day, in GMT
249
250}
251
d552ead0 252function usertimezone($timezone=99) {
9fa49e22 253/// Returns a string that prints the user's timezone
d552ead0 254 global $USER;
255
256 if ($timezone == 99) {
257 $timezone = (float)$USER->timezone;
258 }
0431bd7c 259 if (abs($timezone) > 13) {
d552ead0 260 return "server time";
261 }
262 if (abs($timezone) < 0.5) {
263 return "GMT";
264 }
265 if ($timezone > 0) {
266 return "GMT+$timezone";
267 } else {
268 return "GMT$timezone";
269 }
f9903ed0 270}
271
272
9fa49e22 273/// USER AUTHENTICATION AND LOGIN ////////////////////////////////////////
f9903ed0 274
da5c172a 275function require_login($courseid=0) {
9fa49e22 276/// This function checks that the current user is logged in, and optionally
277/// whether they are "logged in" or allowed to be in a particular course.
278/// If not, then it redirects them to the site login or course enrolment.
f9903ed0 279
73047f2f 280 global $CFG, $SESSION, $USER, $FULLME, $MoodleSession;
f9903ed0 281
da5c172a 282 // First check that the user is logged in to the site.
c21c671d 283 if (! (isset($USER->loggedin) and $USER->confirmed and ($USER->site == $CFG->wwwroot)) ) { // They're not
f9903ed0 284 $SESSION->wantsurl = $FULLME;
9f44d972 285 if (!empty($_SERVER["HTTP_REFERER"])) {
286 $SESSION->fromurl = $_SERVER["HTTP_REFERER"];
287 }
c21c671d 288 $USER = NULL;
73047f2f 289 redirect("$CFG->wwwroot/login/index.php");
f9903ed0 290 die;
f9903ed0 291 }
808a3baa 292
293 // Check that the user account is properly set up
294 if (user_not_fully_set_up($USER)) {
295 $site = get_site();
296 redirect("$CFG->wwwroot/user/edit.php?id=$USER->id&course=$site->id");
297 die;
298 }
da5c172a 299
300 // Next, check if the user can be in a particular course
301 if ($courseid) {
9c9f7d77 302 if (!empty($USER->student[$courseid]) or !empty($USER->teacher[$courseid]) or !empty($USER->admin)) {
cb909d74 303 if (isset($USER->realuser)) { // Make sure the REAL person can also access this course
304 if (!isteacher($courseid, $USER->realuser)) {
305 print_header();
0b4c5822 306 notice(get_string("studentnotallowed", "", fullname($USER, true)), $CFG->wwwroot);
cb909d74 307 }
308
309 } else { // just update their last login time
3ce2f1e0 310 update_user_in_db();
311 }
da5c172a 312 return; // user is a member of this course.
313 }
314 if (! $course = get_record("course", "id", $courseid)) {
315 error("That course doesn't exist");
316 }
1efa27fd 317 if (!$course->visible) {
318 print_header();
0b4c5822 319 notice(get_string("studentnotallowed", "", fullname($USER, true)), $CFG->wwwroot);
1efa27fd 320 }
7363ff91 321 if ($USER->username == "guest") {
322 switch ($course->guest) {
323 case 0: // Guests not allowed
324 print_header();
325 notice(get_string("guestsnotallowed", "", $course->fullname));
326 break;
327 case 1: // Guests allowed
328 update_user_in_db();
329 return;
330 case 2: // Guests allowed with key (drop through)
331 break;
332 }
da5c172a 333 }
f9903ed0 334
7363ff91 335 // Currently not enrolled in the course, so see if they want to enrol
da5c172a 336 $SESSION->wantsurl = $FULLME;
337 redirect("$CFG->wwwroot/course/enrol.php?id=$courseid");
338 die;
339 }
f9903ed0 340}
341
1d881d92 342function update_user_login_times() {
343 global $USER;
344
345 $USER->lastlogin = $user->lastlogin = $USER->currentlogin;
346 $USER->currentlogin = $user->currentlogin = time();
1d881d92 347
348 $user->id = $USER->id;
349
350 return update_record("user", $user);
351}
352
808a3baa 353function user_not_fully_set_up($user) {
ac5d88eb 354 return ($user->username != "guest" and (empty($user->firstname) or empty($user->lastname) or empty($user->email)));
808a3baa 355}
f9903ed0 356
f9903ed0 357function update_login_count() {
9fa49e22 358/// Keeps track of login attempts
359
f9903ed0 360 global $SESSION;
361
362 $max_logins = 10;
363
364 if (empty($SESSION->logincount)) {
365 $SESSION->logincount = 1;
366 } else {
367 $SESSION->logincount++;
368 }
369
370 if ($SESSION->logincount > $max_logins) {
9fa49e22 371 unset($SESSION->wantsurl);
1d881d92 372 error(get_string("errortoomanylogins"));
d578afc8 373 }
374}
375
9fa49e22 376function reset_login_count() {
377/// Resets login attempts
378 global $SESSION;
d578afc8 379
9fa49e22 380 $SESSION->logincount = 0;
d578afc8 381}
382
581d7b49 383function isadmin($userid=0) {
9fa49e22 384/// Is the user an admin?
f9903ed0 385 global $USER;
aa095969 386 static $admins = array();
387 static $nonadmins = array();
f9903ed0 388
581d7b49 389 if (!$userid){
390 if (empty($USER->id)) {
391 return false;
392 }
393 $userid = $USER->id;
9bd2c874 394 }
395
581d7b49 396 if (in_array($userid, $admins)) {
aa095969 397 return true;
581d7b49 398 } else if (in_array($userid, $nonadmins)) {
aa095969 399 return false;
581d7b49 400 } else if (record_exists("user_admins", "userid", $userid)){
401 $admins[] = $userid;
aa095969 402 return true;
403 } else {
581d7b49 404 $nonadmins[] = $userid;
aa095969 405 return false;
f9903ed0 406 }
f9903ed0 407}
408
9788367b 409function isteacher($courseid, $userid=0, $includeadmin=true) {
9fa49e22 410/// Is the user a teacher or admin?
f9903ed0 411 global $USER;
412
9788367b 413 if ($includeadmin and isadmin($userid)) { // admins can do anything the teacher can
d115a57f 414 return true;
415 }
416
f9903ed0 417 if (!$userid) {
9bd2c874 418 return !empty($USER->teacher[$courseid]);
f9903ed0 419 }
420
ebc3bd2b 421 return record_exists("user_teachers", "userid", $userid, "course", $courseid);
f9903ed0 422}
423
73047f2f 424function isteacheredit($courseid, $userid=0) {
425/// Is the user allowed to edit this course?
426 global $USER;
427
428 if (isadmin($userid)) { // admins can do anything
429 return true;
430 }
431
432 if (!$userid) {
433 return !empty($USER->teacheredit[$courseid]);
434 }
435
436 return get_field("user_teachers", "editall", "userid", $userid, "course", $courseid);
437}
438
1924074c 439function iscreator ($userid=0) {
440/// Can user create new courses?
441 global $USER;
8a205861 442 if (empty($USER->id)) {
443 return false;
444 }
1924074c 445 if (isadmin($userid)) { // admins can do anything
446 return true;
447 }
8a205861 448 if (empty($userid)) {
1924074c 449 return record_exists("user_coursecreators", "userid", $USER->id);
450 }
451
452 return record_exists("user_coursecreators", "userid", $userid);
453}
454
8a9e3fd7 455function isstudent($courseid, $userid=0) {
9fa49e22 456/// Is the user a student in this course?
f9903ed0 457 global $USER;
458
459 if (!$userid) {
346b1a24 460 return !empty($USER->student[$courseid]);
f9903ed0 461 }
462
ebc3bd2b 463 // $timenow = time(); // todo: add time check below
f9903ed0 464
ebc3bd2b 465 return record_exists("user_students", "userid", $userid, "course", $courseid);
f9903ed0 466}
467
da5c172a 468function isguest($userid=0) {
9fa49e22 469/// Is the user a guest?
da5c172a 470 global $USER;
471
472 if (!$userid) {
b35e8568 473 if (empty($USER->username)) {
474 return false;
475 }
da5c172a 476 return ($USER->username == "guest");
477 }
478
9fa49e22 479 return record_exists("user", "id", $userid, "username", "guest");
da5c172a 480}
481
9fa49e22 482
2c309dc2 483function isediting($courseid, $user=NULL) {
9fa49e22 484/// Is the current user in editing mode?
2c309dc2 485 global $USER;
486 if (!$user){
487 $user = $USER;
488 }
9c9f7d77 489 if (empty($user->editing)) {
490 return false;
491 }
2c309dc2 492 return ($user->editing and isteacher($courseid, $user->id));
493}
494
7977cffd 495function ismoving($courseid) {
496/// Is the current user currently moving an activity?
497 global $USER;
498
499 if (!empty($USER->activitycopy)) {
500 return ($USER->activitycopycourse == $courseid);
501 }
502 return false;
503}
504
e2cd5065 505function fullname($user, $override=false) {
b5cbb64d 506/// Given an object containing firstname and lastname
507/// values, this function returns a string with the
508/// full name of the person.
e2cd5065 509/// The result may depend on system settings
b5cbb64d 510/// or language. 'override' will force both names
e2cd5065 511/// to be used even if system settings specify one.
b5cbb64d 512
f374fb10 513 global $CFG, $SESSION;
514
515 if (!empty($SESSION->fullnamedisplay)) {
516 $CFG->fullnamedisplay = $SESSION->fullnamedisplay;
517 }
e2cd5065 518
b5cbb64d 519 if ($CFG->fullnamedisplay == 'firstname lastname') {
520 return "$user->firstname $user->lastname";
521
522 } else if ($CFG->fullnamedisplay == 'lastname firstname') {
523 return "$user->lastname $user->firstname";
e2cd5065 524
b5cbb64d 525 } else if ($CFG->fullnamedisplay == 'firstname') {
526 if ($override) {
527 return get_string('fullnamedisplay', '', $user);
528 } else {
529 return $user->firstname;
530 }
531 }
e2cd5065 532
b5cbb64d 533 return get_string('fullnamedisplay', '', $user);
e2cd5065 534}
535
f9903ed0 536
537function set_moodle_cookie($thing) {
9fa49e22 538/// Sets a moodle cookie with an encrypted string
7185e073 539 global $CFG;
482b6e6e 540
541 $cookiename = 'MOODLEID_'.$CFG->sessioncookie;
f9903ed0 542
543 $days = 60;
544 $seconds = 60*60*24*$days;
545
7185e073 546 setCookie($cookiename, "", time() - 3600, "/");
547 setCookie($cookiename, rc4encrypt($thing), time()+$seconds, "/");
f9903ed0 548}
549
550
551function get_moodle_cookie() {
9fa49e22 552/// Gets a moodle cookie with an encrypted string
7185e073 553 global $CFG;
554
482b6e6e 555 $cookiename = 'MOODLEID_'.$CFG->sessioncookie;
7185e073 556
1079c8a8 557 if (empty($_COOKIE[$cookiename])) {
558 return "";
559 } else {
560 return rc4decrypt($_COOKIE[$cookiename]);
561 }
f9903ed0 562}
563
ba7166c3 564function is_internal_auth() {
565/// Returns true if an internal authentication method is being used.
566
567 global $CFG;
568
569 return ($CFG->auth == "email" || $CFG->auth == "none" || $CFG->auth == "manual");
570}
f9903ed0 571
faebaf0f 572function create_user_record($username, $password) {
9fa49e22 573/// Creates a bare-bones user record
e858f9da 574 global $REMOTE_ADDR, $CFG;
1e22bc9c 575 //just in case check text case
576 $username = trim(moodle_strtolower($username));
6ae24de0 577 if (function_exists(auth_get_userinfo)) {
e858f9da 578 if ($newinfo = auth_get_userinfo($username)) {
34daec9b 579 foreach ($newinfo as $key => $value){
9f44d972 580 $newuser->$key = addslashes(stripslashes($value)); // Just in case
e858f9da 581 }
582 }
583 }
f9903ed0 584
faebaf0f 585 $newuser->username = $username;
586 $newuser->password = md5($password);
a0bac19d 587 $newuser->lang = $CFG->lang;
faebaf0f 588 $newuser->confirmed = 1;
589 $newuser->lastIP = $REMOTE_ADDR;
590 $newuser->timemodified = time();
f9903ed0 591
faebaf0f 592 if (insert_record("user", $newuser)) {
593 return get_user_info_from_db("username", $username);
594 }
595 return false;
596}
597
0609562b 598
599function guest_user() {
600 global $CFG;
601
602 if ($newuser = get_record("user", "username", "guest")) {
603 $newuser->loggedin = true;
604 $newuser->confirmed = 1;
605 $newuser->site = $CFG->wwwroot;
606 $newuser->lang = $CFG->lang;
607 }
608
609 return $newuser;
610}
611
faebaf0f 612function authenticate_user_login($username, $password) {
9fa49e22 613/// Given a username and password, this function looks them
614/// up using the currently selected authentication mechanism,
615/// and if the authentication is successful, it returns a
616/// valid $user object from the 'user' table.
617///
618/// Uses auth_ functions from the currently active auth module
faebaf0f 619
620 global $CFG;
621
466558e3 622 $md5password = md5($password);
623
14217044 624 if (empty($CFG->auth)) {
faebaf0f 625 $CFG->auth = "email"; // Default authentication module
626 }
627
466558e3 628 if ($username == "guest") {
629 $CFG->auth = "none"; // Guest account always internal
630 }
631
632 // If this is the admin, then just use internal methods
92710226 633 // Doing this first (even though it's less efficient) because
634 // the chosen authentication method might hang and lock the
635 // admin out.
9fa49e22 636 if (adminlogin($username, $md5password)) {
466558e3 637 return get_user_info_from_db("username", $username);
638 }
639
92710226 640 // OK, the user is a normal user, so try and authenticate them
e858f9da 641 require_once("$CFG->dirroot/auth/$CFG->auth/lib.php");
faebaf0f 642
643 if (auth_user_login($username, $password)) { // Successful authentication
faebaf0f 644 if ($user = get_user_info_from_db("username", $username)) {
92710226 645 if ($md5password <> $user->password) { // Update local copy of password for reference
466558e3 646 set_field("user", "password", $md5password, "username", $username);
faebaf0f 647 }
faebaf0f 648 } else {
e582b65e 649 $user = create_user_record($username, $password);
faebaf0f 650 }
89b54325 651
e582b65e 652 if (function_exists('auth_iscreator')) { // Check if the user is a creator
653 if (auth_iscreator($username)) {
654 if (! record_exists("user_coursecreators", "userid", $user->id)) {
655 $cdata['userid']=$user->id;
656 $creator = insert_record("user_coursecreators",$cdata);
657 if (! $creator) {
658 error("Cannot add user to course creators.");
659 }
660 }
661 } else {
662 if ( record_exists("user_coursecreators", "userid", $user->id)) {
f5cdd4d1 663 $creator = delete_records("user_coursecreators", "userid", $user->id);
e582b65e 664 if (! $creator) {
665 error("Cannot remove user from course creators.");
666 }
667 }
668 }
669 }
670
671 return $user;
672 } else {
673 return false;
674 }
f9903ed0 675}
676
4d312bbe 677function enrol_student($userid, $courseid) {
9fa49e22 678/// Enrols a student in a given course
f9903ed0 679
4d312bbe 680 if (!record_exists("user_students", "userid", $userid, "course", $courseid)) {
3041b0f8 681 if (record_exists("user", "id", $userid)) {
682 $student->userid = $userid;
683 $student->course = $courseid;
684 $student->start = 0;
685 $student->end = 0;
686 $student->time = time();
687 return insert_record("user_students", $student);
688 }
689 return false;
4d312bbe 690 }
691 return true;
d7facad8 692}
693
9fa49e22 694function unenrol_student($user, $course=0) {
695/// Unenrols a student from a given course
d7facad8 696
9fa49e22 697 if ($course) {
698 /// First delete any crucial stuff that might still send mail
699 if ($forums = get_records("forum", "course", $course)) {
700 foreach ($forums as $forum) {
ebc3bd2b 701 delete_records("forum_subscriptions", "forum", $forum->id, "userid", $user);
bb09fb11 702 }
f9903ed0 703 }
ebc3bd2b 704 return delete_records("user_students", "userid", $user, "course", $course);
9fa49e22 705
f9903ed0 706 } else {
ebc3bd2b 707 delete_records("forum_subscriptions", "userid", $user);
708 return delete_records("user_students", "userid", $user);
f9903ed0 709 }
710}
711
3041b0f8 712function add_teacher($userid, $courseid) {
713/// Add a teacher to a given course
714
715 if (!record_exists("user_teachers", "userid", $userid, "course", $courseid)) {
716 if (record_exists("user", "id", $userid)) {
717 $teacher->userid = $userid;
718 $teacher->course = $courseid;
719 $teacher->editall = 1;
720 $teacher->role = "";
721 if (record_exists("user_teachers", "course", $courseid)) {
722 $teacher->authority = 2;
723 } else {
724 $teacher->authority = 1;
725 }
726 return insert_record("user_teachers", $teacher);
727 }
728 return false;
729 }
730 return true;
731}
732
733function remove_teacher($userid, $courseid=0) {
9fa49e22 734/// Removes a teacher from a given course (or ALL courses)
735/// Does not delete the user account
3041b0f8 736 if ($courseid) {
9fa49e22 737 /// First delete any crucial stuff that might still send mail
3041b0f8 738 if ($forums = get_records("forum", "course", $courseid)) {
9fa49e22 739 foreach ($forums as $forum) {
3041b0f8 740 delete_records("forum_subscriptions", "forum", $forum->id, "userid", $userid);
9fa49e22 741 }
742 }
3041b0f8 743 return delete_records("user_teachers", "userid", $userid, "course", $courseid);
57507290 744 } else {
3041b0f8 745 delete_records("forum_subscriptions", "userid", $userid);
746 return delete_records("user_teachers", "userid", $userid);
57507290 747 }
f9903ed0 748}
749
3041b0f8 750
751function add_creator($userid) {
752/// Add a creator to the site
753
754 if (!record_exists("user_admins", "userid", $userid)) {
755 if (record_exists("user", "id", $userid)) {
756 $creator->userid = $userid;
757 return insert_record("user_coursecreators", $creator);
758 }
759 return false;
760 }
761 return true;
762}
763
764function remove_creator($userid) {
765/// Removes a creator from a site
766 global $db;
767
768 return delete_records("user_coursecreators", "userid", $userid);
769}
770
771function add_admin($userid) {
772/// Add an admin to the site
773
774 if (!record_exists("user_admins", "userid", $userid)) {
775 if (record_exists("user", "id", $userid)) {
776 $admin->userid = $userid;
777 return insert_record("user_admins", $admin);
778 }
779 return false;
780 }
781 return true;
782}
783
784function remove_admin($userid) {
9fa49e22 785/// Removes an admin from a site
786 global $db;
f9903ed0 787
3041b0f8 788 return delete_records("user_admins", "userid", $userid);
f9903ed0 789}
790
f9903ed0 791
07aeb7b0 792function remove_course_contents($courseid, $showfeedback=true) {
793/// Clear a course out completely, deleting all content
794/// but don't delete the course itself
795
ee23f384 796 global $CFG, $THEME, $USER, $SESSION;
07aeb7b0 797
798 $result = true;
799
800 if (! $course = get_record("course", "id", $courseid)) {
801 error("Course ID was incorrect (can't find it)");
802 }
803
804 $strdeleted = get_string("deleted");
805
806 // First delete every instance of every module
807
808 if ($allmods = get_records("modules") ) {
809 foreach ($allmods as $mod) {
810 $modname = $mod->name;
811 $modfile = "$CFG->dirroot/mod/$modname/lib.php";
ca952b03 812 $moddelete = $modname."_delete_instance"; // Delete everything connected to an instance
813 $moddeletecourse = $modname."_delete_course"; // Delete other stray stuff (uncommon)
07aeb7b0 814 $count=0;
815 if (file_exists($modfile)) {
816 include_once($modfile);
817 if (function_exists($moddelete)) {
818 if ($instances = get_records($modname, "course", $course->id)) {
819 foreach ($instances as $instance) {
820 if ($moddelete($instance->id)) {
821 $count++;
822 } else {
823 notify("Could not delete $modname instance $instance->id ($instance->name)");
824 $result = false;
825 }
826 }
827 }
828 } else {
829 notify("Function $moddelete() doesn't exist!");
830 $result = false;
831 }
832
ca952b03 833 if (function_exists($moddeletecourse)) {
834 $moddeletecourse($course);
835 }
07aeb7b0 836 }
837 if ($showfeedback) {
838 notify("$strdeleted $count x $modname");
839 }
840 }
841 } else {
842 error("No modules are installed!");
843 }
844
845 // Delete any user stuff
846
847 if (delete_records("user_students", "course", $course->id)) {
848 if ($showfeedback) {
849 notify("$strdeleted user_students");
850 }
851 } else {
852 $result = false;
853 }
854
855 if (delete_records("user_teachers", "course", $course->id)) {
856 if ($showfeedback) {
857 notify("$strdeleted user_teachers");
858 }
859 } else {
860 $result = false;
861 }
862
863 // Delete logs
864
865 if (delete_records("log", "course", $course->id)) {
866 if ($showfeedback) {
867 notify("$strdeleted log");
868 }
869 } else {
870 $result = false;
871 }
872
873 // Delete any course stuff
874
875 if (delete_records("course_sections", "course", $course->id)) {
876 if ($showfeedback) {
877 notify("$strdeleted course_sections");
878 }
879 } else {
880 $result = false;
881 }
882
883 if (delete_records("course_modules", "course", $course->id)) {
884 if ($showfeedback) {
885 notify("$strdeleted course_modules");
886 }
887 } else {
888 $result = false;
889 }
890
891 return $result;
892
893}
894
f9903ed0 895
f374fb10 896/// GROUPS /////////////////////////////////////////////////////////
0d67c514 897
f374fb10 898
899/**
900* Returns a boolean: is the user a member of the given group?
901*
902* @param type description
903*/
904function ismember($groupid, $userid=0) {
905 global $USER;
906
8a2c9076 907 if (!$groupid) { // No point doing further checks
908 return false;
909 }
910
f374fb10 911 if (!$userid) {
0d67c514 912 if (empty($USER->groupmember)) {
913 return false;
914 }
915 foreach ($USER->groupmember as $courseid => $mgroupid) {
916 if ($mgroupid == $groupid) {
917 return true;
918 }
919 }
920 return false;
f374fb10 921 }
922
0da33e07 923 return record_exists("groups_members", "groupid", $groupid, "userid", $userid);
f374fb10 924}
925
0d67c514 926/**
927* Returns the group ID of the current user in the given course
928*
929* @param type description
930*/
931function mygroupid($courseid) {
932 global $USER;
933
934 if (empty($USER->groupmember[$courseid])) {
935 return 0;
936 } else {
937 return $USER->groupmember[$courseid];
938 }
939}
940
f374fb10 941/**
942* For a given course, and possibly course module, determine
943* what the current default groupmode is:
944* NOGROUPS, SEPARATEGROUPS or VISIBLEGROUPS
945*
946* @param type description
947*/
948function groupmode($course, $cm=null) {
949
950 if ($cm and !$course->groupmodeforce) {
951 return $cm->groupmode;
952 }
953 return $course->groupmode;
954}
955
956
957/**
958* Sets the current group in the session variable
959*
960* @param type description
961*/
962function set_current_group($courseid, $groupid) {
963 global $SESSION;
964
965 return $SESSION->currentgroup[$courseid] = $groupid;
966}
967
968
969/**
970* Gets the current group for the current user as an id or an object
971*
972* @param type description
973*/
974function get_current_group($courseid, $full=false) {
975 global $SESSION, $USER;
976
977 if (empty($SESSION->currentgroup[$courseid])) {
978 if (empty($USER->groupmember[$courseid])) {
8a2c9076 979 return 0;
f374fb10 980 } else {
981 $SESSION->currentgroup[$courseid] = $USER->groupmember[$courseid];
982 }
983 }
984
985 if ($full) {
0da33e07 986 return get_record('groups', 'id', $SESSION->currentgroup[$courseid]);
f374fb10 987 } else {
988 return $SESSION->currentgroup[$courseid];
989 }
990}
991
0d67c514 992/**
993* A combination function to make it easier for modules
994* to set up groups.
995*
996* It will use a given "groupid" parameter and try to use
997* that to reset the current group for the user.
998*
999* @param type description
1000*/
1001function get_and_set_current_group($course, $groupmode, $groupid=0) {
1002
1003 if (!$groupmode) { // Groups don't even apply
1004 return false;
1005 }
1006
1007 $currentgroupid = get_current_group($course->id);
1008
1009 if ($groupid) { // Try to change the current group
1010 if ($group = get_record('groups', 'id', $groupid, 'courseid', $course->id)) { // Exists
1011 if (isteacheredit($course->id)) { // Sets current default group
1012 $currentgroupid = set_current_group($course->id, $group->id);
1013
1014 } else if ($groupmode == VISIBLEGROUPS) { // All groups are visible
1015 $currentgroupid = $group->id;
1016 }
1017 }
1018 }
1019
1020 return $currentgroupid;
1021}
1022
1023
1024
f374fb10 1025
1026
f9903ed0 1027/// CORRESPONDENCE ////////////////////////////////////////////////
1028
5fa51a39 1029function email_to_user($user, $from, $subject, $messagetext, $messagehtml="", $attachment="", $attachname="") {
9fa49e22 1030/// user - a user record as an object
1031/// from - a user record as an object
1032/// subject - plain text subject line of the email
1033/// messagetext - plain text version of the message
1034/// messagehtml - complete html version of the message (optional)
1035/// attachment - a file on the filesystem, relative to $CFG->dataroot
1036/// attachname - the name of the file (extension indicates MIME)
f9903ed0 1037
4216daa6 1038 global $CFG, $_SERVER;
f9903ed0 1039
136dabd8 1040 include_once("$CFG->libdir/phpmailer/class.phpmailer.php");
f9903ed0 1041
5fa51a39 1042 if (!$user) {
f9903ed0 1043 return false;
1044 }
1045
f9903ed0 1046 $mail = new phpmailer;
1047
72c578ca 1048 $mail->Version = "Moodle $CFG->version"; // mailer version
136dabd8 1049 $mail->PluginDir = "$CFG->libdir/phpmailer/"; // plugin directory (eg smtp plugin)
562bbe90 1050
98c4eae3 1051
d483bcd3 1052 if (current_language() != "en") {
1053 $mail->CharSet = get_string("thischarset");
98c4eae3 1054 }
1055
62740736 1056 if ($CFG->smtphosts == "qmail") {
1057 $mail->IsQmail(); // use Qmail system
1058
1059 } else if (empty($CFG->smtphosts)) {
1060 $mail->IsMail(); // use PHP mail() = sendmail
1061
1062 } else {
1e411ffc 1063 $mail->IsSMTP(); // use SMTP directly
57ef3480 1064 if ($CFG->debug > 7) {
1065 echo "<pre>\n";
1066 $mail->SMTPDebug = true;
1067 }
1e411ffc 1068 $mail->Host = "$CFG->smtphosts"; // specify main and backup servers
9f58537a 1069
1070 if ($CFG->smtpuser) { // Use SMTP authentication
1071 $mail->SMTPAuth = true;
1072 $mail->Username = $CFG->smtpuser;
1073 $mail->Password = $CFG->smtppass;
1074 }
7f86ce17 1075 }
f9903ed0 1076
2b97bd71 1077 $adminuser = get_admin();
1078
1079 $mail->Sender = "$adminuser->email";
1080
136dabd8 1081 $mail->From = "$from->email";
0b4c5822 1082 $mail->FromName = fullname($from);
136dabd8 1083 $mail->Subject = stripslashes($subject);
f9903ed0 1084
0b4c5822 1085 $mail->AddAddress("$user->email", fullname($user) );
f9903ed0 1086
f9903ed0 1087 $mail->WordWrap = 70; // set word wrap
f9903ed0 1088
136dabd8 1089 if ($messagehtml) {
1090 $mail->IsHTML(true);
125898af 1091 $mail->Encoding = "quoted-printable"; // Encoding to use
136dabd8 1092 $mail->Body = $messagehtml;
78681899 1093 $mail->AltBody = "\n$messagetext\n";
136dabd8 1094 } else {
1095 $mail->IsHTML(false);
78681899 1096 $mail->Body = "\n$messagetext\n";
f9903ed0 1097 }
1098
136dabd8 1099 if ($attachment && $attachname) {
1100 if (ereg( "\\.\\." ,$attachment )) { // Security check for ".." in dir path
0b4c5822 1101 $mail->AddAddress("$adminuser->email", fullname($adminuser) );
4216daa6 1102 $mail->AddStringAttachment("Error in attachment. User attempted to attach a filename with a unsafe name.", "error.txt", "8bit", "text/plain");
136dabd8 1103 } else {
1104 include_once("$CFG->dirroot/files/mimetypes.php");
1105 $mimetype = mimeinfo("type", $attachname);
1106 $mail->AddAttachment("$CFG->dataroot/$attachment", "$attachname", "base64", "$mimetype");
1107 }
f9903ed0 1108 }
1109
136dabd8 1110 if ($mail->Send()) {
1111 return true;
1112 } else {
4216daa6 1113 echo "ERROR: $mail->ErrorInfo\n";
1114 $site = get_site();
1115 add_to_log($site->id, "library", "mailer", $_SERVER["REQUEST_URI"], "ERROR: $mail->ErrorInfo");
f9903ed0 1116 return false;
1117 }
f9903ed0 1118}
1119
1d881d92 1120function reset_password_and_mail($user) {
1121
1122 global $CFG;
1123
1124 $site = get_site();
1125 $from = get_admin();
1126
1127 $newpassword = generate_password();
1128
1129 if (! set_field("user", "password", md5($newpassword), "id", $user->id) ) {
1130 error("Could not set user password!");
1131 }
1132
1133 $a->firstname = $user->firstname;
1134 $a->sitename = $site->fullname;
1135 $a->username = $user->username;
1136 $a->newpassword = $newpassword;
1137 $a->link = "$CFG->wwwroot/login/change_password.php";
0b4c5822 1138 $a->signoff = fullname($from, true)." ($from->email)";
1d881d92 1139
1140 $message = get_string("newpasswordtext", "", $a);
1141
1142 $subject = "$site->fullname: ".get_string("changedpassword");
1143
1144 return email_to_user($user, $from, $subject, $message);
1145
1146}
1147
1148function send_confirmation_email($user) {
1149
1150 global $CFG;
1151
1152 $site = get_site();
1153 $from = get_admin();
1154
1155 $data->firstname = $user->firstname;
1156 $data->sitename = $site->fullname;
1157 $data->link = "$CFG->wwwroot/login/confirm.php?p=$user->secret&s=$user->username";
0b4c5822 1158 $data->admin = fullname($from)." ($from->email)";
1d881d92 1159
1160 $message = get_string("emailconfirmation", "", $data);
eb347b6b 1161 $subject = get_string("emailconfirmationsubject", "", $site->fullname);
1d881d92 1162
1163 return email_to_user($user, $from, $subject, $message);
1164
1165}
1166
eb347b6b 1167function send_password_change_confirmation_email($user) {
1168
1169 global $CFG;
1170
1171 $site = get_site();
1172 $from = get_admin();
1173
1174 $data->firstname = $user->firstname;
1175 $data->sitename = $site->fullname;
1176 $data->link = "$CFG->wwwroot/login/forgot_password.php?p=$user->secret&s=$user->username";
0b4c5822 1177 $data->admin = fullname($from)." ($from->email)";
eb347b6b 1178
1179 $message = get_string("emailpasswordconfirmation", "", $data);
1180 $subject = get_string("emailpasswordconfirmationsubject", "", $site->fullname);
1181
1182 return email_to_user($user, $from, $subject, $message);
1183
1184}
1185
1186
1d881d92 1187
136dabd8 1188
f9903ed0 1189/// FILE HANDLING /////////////////////////////////////////////
1190
6b174680 1191function make_upload_directory($directory) {
9fa49e22 1192/// $directory = a string of directory names under $CFG->dataroot
1193/// eg stuff/assignment/1
1194/// Returns full directory if successful, false if not
6b174680 1195
1196 global $CFG;
1197
1198 $currdir = $CFG->dataroot;
fe287429 1199
2e6d4273 1200 umask(0000);
1201
6b174680 1202 if (!file_exists($currdir)) {
2e6d4273 1203 if (! mkdir($currdir, $CFG->directorypermissions)) {
6b174680 1204 notify("ERROR: You need to create the directory $currdir with web server write access");
1205 return false;
1206 }
1207 }
1208
1209 $dirarray = explode("/", $directory);
1210
1211 foreach ($dirarray as $dir) {
1212 $currdir = "$currdir/$dir";
1213 if (! file_exists($currdir)) {
2e6d4273 1214 if (! mkdir($currdir, $CFG->directorypermissions)) {
6b174680 1215 notify("ERROR: Could not find or create a directory ($currdir)");
1216 return false;
1217 }
feffa4e6 1218 @chmod($currdir, $CFG->directorypermissions); // Just in case mkdir didn't do it
6b174680 1219 }
1220 }
1221
1222 return $currdir;
1223}
1224
ca4f8eb8 1225function make_mod_upload_directory($courseid) {
9fa49e22 1226/// Makes an upload directory for a particular module
ca4f8eb8 1227 global $CFG;
1228
1229 if (! $moddata = make_upload_directory("$courseid/$CFG->moddata")) {
1230 return false;
1231 }
1232
1233 $strreadme = get_string("readme");
1234
1235 if (file_exists("$CFG->dirroot/lang/$CFG->lang/docs/module_files.txt")) {
1236 copy("$CFG->dirroot/lang/$CFG->lang/docs/module_files.txt", "$moddata/$strreadme.txt");
1237 } else {
1238 copy("$CFG->dirroot/lang/en/docs/module_files.txt", "$moddata/$strreadme.txt");
1239 }
1240 return $moddata;
1241}
1242
6b174680 1243
44e2d2bb 1244function valid_uploaded_file($newfile) {
9fa49e22 1245/// Returns current name of file on disk if true
9c9f7d77 1246 if (empty($newfile)) {
1247 return "";
1248 }
44e2d2bb 1249 if (is_uploaded_file($newfile['tmp_name']) and $newfile['size'] > 0) {
1250 return $newfile['tmp_name'];
1251 } else {
1252 return "";
1253 }
1254}
1255
4909e176 1256function get_max_upload_file_size($sitebytes=0, $coursebytes=0, $modulebytes=0) {
9fa49e22 1257/// Returns the maximum size for uploading files
316ebf78 1258/// There are seven possible upload limits:
4909e176 1259///
1260/// 1) in Apache using LimitRequestBody (no way of checking or changing this)
1261/// 2) in php.ini for 'upload_max_filesize' (can not be changed inside PHP)
1262/// 3) in .htaccess for 'upload_max_filesize' (can not be changed inside PHP)
316ebf78 1263/// 4) in php.ini for 'post_max_size' (can not be changed inside PHP)
1264/// 5) by the Moodle admin in $CFG->maxbytes
1265/// 6) by the teacher in the current course $course->maxbytes
1266/// 7) by the teacher for the current module, eg $assignment->maxbytes
4909e176 1267///
1268/// These last two are passed to this function as arguments (in bytes).
1269/// Anything defined as 0 is ignored.
1270/// The smallest of all the non-zero numbers is returned.
1271
44e2d2bb 1272 if (! $filesize = ini_get("upload_max_filesize")) {
1273 $filesize = "5M";
1274 }
4909e176 1275 $minimumsize = get_real_size($filesize);
1276
316ebf78 1277 if ($postsize = ini_get("post_max_size")) {
1278 $postsize = get_real_size($postsize);
1279 if ($postsize < $minimumsize) {
1280 $minimumsize = $postsize;
1281 }
1282 }
1283
4909e176 1284 if ($sitebytes and $sitebytes < $minimumsize) {
1285 $minimumsize = $sitebytes;
1286 }
1287
1288 if ($coursebytes and $coursebytes < $minimumsize) {
1289 $minimumsize = $coursebytes;
1290 }
1291
1292 if ($modulebytes and $modulebytes < $minimumsize) {
1293 $minimumsize = $modulebytes;
1294 }
1295
1296 return $minimumsize;
1297}
1298
1299function get_max_upload_sizes($sitebytes=0, $coursebytes=0, $modulebytes=0) {
1300/// Related to the above function - this function returns an
1301/// array of possible sizes in an array, translated to the
1302/// local language.
1303
1304 if (!$maxsize = get_max_upload_file_size($sitebytes, $coursebytes, $modulebytes)) {
1305 return array();
1306 }
1307
1308 $filesize[$maxsize] = display_size($maxsize);
1309
1310 $sizelist = array(10240, 51200, 102400, 512000, 1048576, 2097152,
1311 5242880, 10485760, 20971520, 52428800, 104857600);
1312
1313 foreach ($sizelist as $sizebytes) {
1314 if ($sizebytes < $maxsize) {
1315 $filesize[$sizebytes] = display_size($sizebytes);
1316 }
1317 }
1318
1319 krsort($filesize, SORT_NUMERIC);
1320
1321 return $filesize;
44e2d2bb 1322}
1323
774ab660 1324function get_directory_list($rootdir, $excludefile="", $descend=true) {
9fa49e22 1325/// Returns an array with all the filenames in
1326/// all subdirectories, relative to the given rootdir.
1327/// If excludefile is defined, then that file/directory is ignored
f9903ed0 1328
1329 $dirs = array();
f9903ed0 1330
12407705 1331 if (!is_dir($rootdir)) {
1332 return $dirs;
1333 }
1334
487c1711 1335 if (!$dir = opendir($rootdir)) {
d897cae4 1336 return $dirs;
1337 }
1338
ca4f8eb8 1339 while ($file = readdir($dir)) {
b35e8568 1340 $firstchar = substr($file, 0, 1);
1341 if ($firstchar == "." or $file == "CVS" or $file == $excludefile) {
1342 continue;
1343 }
1344 $fullfile = $rootdir."/".$file;
1345 if ($descend and filetype($fullfile) == "dir") {
1346 $subdirs = get_directory_list($fullfile, $excludefile, $descend);
1347 foreach ($subdirs as $subdir) {
1348 $dirs[] = $file."/".$subdir;
f9903ed0 1349 }
b35e8568 1350 } else {
1351 $dirs[] = $file;
f9903ed0 1352 }
1353 }
44e2d2bb 1354 closedir($dir);
f9903ed0 1355
774ab660 1356 asort($dirs);
1357
f9903ed0 1358 return $dirs;
1359}
1360
989bfa9d 1361function get_real_size($size=0) {
9fa49e22 1362/// Converts numbers like 10M into bytes
989bfa9d 1363 if (!$size) {
1364 return 0;
1365 }
1366 $scan['MB'] = 1048576;
64efda84 1367 $scan['Mb'] = 1048576;
989bfa9d 1368 $scan['M'] = 1048576;
266a416e 1369 $scan['m'] = 1048576;
989bfa9d 1370 $scan['KB'] = 1024;
64efda84 1371 $scan['Kb'] = 1024;
989bfa9d 1372 $scan['K'] = 1024;
266a416e 1373 $scan['k'] = 1024;
989bfa9d 1374
1375 while (list($key) = each($scan)) {
1376 if ((strlen($size)>strlen($key))&&(substr($size, strlen($size) - strlen($key))==$key)) {
1377 $size = substr($size, 0, strlen($size) - strlen($key)) * $scan[$key];
1378 break;
1379 }
1380 }
1381 return $size;
1382}
1383
44e2d2bb 1384function display_size($size) {
9fa49e22 1385/// Converts bytes into display form
4909e176 1386
1387 static $gb,$mb,$kb,$b;
1388
1389 if (empty($gb)) {
1390 $gb = get_string('sizegb');
1391 $mb = get_string('sizemb');
1392 $kb = get_string('sizekb');
1393 $b = get_string('sizeb');
1394 }
1395
44e2d2bb 1396 if ($size >= 1073741824) {
4909e176 1397 $size = round($size / 1073741824 * 10) / 10 . $gb;
44e2d2bb 1398 } else if ($size >= 1048576) {
4909e176 1399 $size = round($size / 1048576 * 10) / 10 . $mb;
44e2d2bb 1400 } else if ($size >= 1024) {
4909e176 1401 $size = round($size / 1024 * 10) / 10 . $kb;
44e2d2bb 1402 } else {
4909e176 1403 $size = $size ." $b";
44e2d2bb 1404 }
1405 return $size;
1406}
1407
6b174680 1408function clean_filename($string) {
9fa49e22 1409/// Cleans a given filename by removing suspicious or troublesome characters
fc05fccb 1410 $string = stripslashes($string);
6b174680 1411 $string = eregi_replace("\.\.", "", $string);
5c219ea4 1412 $string = eregi_replace("[^(-|[:alnum:]|\.)]", "_", $string);
e9f3e715 1413 $string = eregi_replace(",", "_", $string);
6b174680 1414 return eregi_replace("_+", "_", $string);
1415}
1416
1417
1180c6dc 1418/// STRING TRANSLATION ////////////////////////////////////////
1419
4bfa92e7 1420function current_language() {
9fa49e22 1421/// Returns the code for the current language
3db3acfb 1422 global $CFG, $USER, $SESSION;
4bfa92e7 1423
3db3acfb 1424 if (isset($SESSION->lang)) { // Session language can override other settings
1425 return $SESSION->lang;
1426
1427 } else if (isset($USER->lang)) { // User language can override site language
4bfa92e7 1428 return $USER->lang;
3db3acfb 1429
4bfa92e7 1430 } else {
1431 return $CFG->lang;
1432 }
1433}
bcc83c41 1434
9fa49e22 1435function print_string($identifier, $module="", $a=NULL) {
1436/// Given a string to translate - prints it out.
1437 echo get_string($identifier, $module, $a);
1438}
1439
a83fded1 1440function get_string($identifier, $module="", $a=NULL) {
9fa49e22 1441/// Return the translated string specified by $identifier as
1442/// for $module. Uses the same format files as STphp.
1443/// $a is an object, string or number that can be used
1444/// within translation strings
1445///
1446/// eg "hello \$a->firstname \$a->lastname"
1447/// or "hello \$a"
1180c6dc 1448
4bfa92e7 1449 global $CFG;
1180c6dc 1450
4bfa92e7 1451 $lang = current_language();
1180c6dc 1452
058eec18 1453 if ($module == "") {
1454 $module = "moodle";
1180c6dc 1455 }
1456
058eec18 1457 $langpath = "$CFG->dirroot/lang";
1458 $langfile = "$langpath/$lang/$module.php";
1180c6dc 1459
b947c69a 1460 // Look for the string - if found then return it
1461
1462 if (file_exists($langfile)) {
1463 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
1464 eval($result);
1465 return $resultstring;
1180c6dc 1466 }
1467 }
1468
b947c69a 1469 // If the preferred language was English we can abort now
1180c6dc 1470
b947c69a 1471 if ($lang == "en") {
1472 return "[[$identifier]]";
1473 }
1180c6dc 1474
b947c69a 1475 // Is a parent language defined? If so, try it.
1476
1477 if ($result = get_string_from_file("parentlanguage", "$langpath/$lang/moodle.php", "\$parentlang")) {
1478 eval($result);
1479 if (!empty($parentlang)) {
1480 $langfile = "$langpath/$parentlang/$module.php";
1481 if (file_exists($langfile)) {
1482 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
1483 eval($result);
1484 return $resultstring;
1485 }
1180c6dc 1486 }
1487 }
1488 }
b947c69a 1489
1490 // Our only remaining option is to try English
1491
1492 $langfile = "$langpath/en/$module.php";
1493 if (!file_exists($langfile)) {
1494 return "ERROR: No lang file ($langpath/en/$module.php)!";
1495 }
1496 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
1497 eval($result);
1498 return $resultstring;
1499 }
1500
1501 return "[[$identifier]]"; // Last resort
1180c6dc 1502}
1503
1504
1180c6dc 1505function get_string_from_file($identifier, $langfile, $destination) {
9fa49e22 1506/// This function is only used from get_string().
2b32bddd 1507
1508 static $strings; // Keep the strings cached in memory.
1509
1510 if (empty($strings[$langfile])) {
1511 include ($langfile);
1512 $strings[$langfile] = $string;
1513 } else {
1514 $string = &$strings[$langfile];
1515 }
1180c6dc 1516
1517 if (!isset ($string[$identifier])) {
1518 return false;
1519 }
1520
a83fded1 1521 return "$destination = sprintf(\"".$string[$identifier]."\");";
1180c6dc 1522}
f9903ed0 1523
1524
1a72314d 1525function get_list_of_languages() {
1526/// Returns a list of language codes and their full names
1527 global $CFG;
1528
984a8bf3 1529 $languages = array();
1530
1531 if (!empty($CFG->langlist)) { // use admin's list of languages
1532 $langlist = explode(',', $CFG->langlist);
1533 foreach ($langlist as $lang) {
1534 if (file_exists("$CFG->dirroot/lang/$lang/moodle.php")) {
1535 include("$CFG->dirroot/lang/$lang/moodle.php");
1536 $languages[$lang] = $string["thislanguage"]." ($lang)";
1537 unset($string);
1538 }
1539 }
1540 } else {
1541 if (!$langdirs = get_list_of_plugins("lang")) {
1542 return false;
1543 }
1544 foreach ($langdirs as $lang) {
1545 include("$CFG->dirroot/lang/$lang/moodle.php");
1546 $languages[$lang] = $string["thislanguage"]." ($lang)";
1547 unset($string);
1548 }
1a72314d 1549 }
1550
1a72314d 1551 return $languages;
1552}
1553
5833a6c8 1554function get_list_of_countries() {
1555/// Returns a list of country names in the current language
1556 global $CFG, $USER;
1557
1558 $lang = current_language();
1559
1560 if (!file_exists("$CFG->dirroot/lang/$lang/countries.php")) {
aa3eb050 1561 if ($parentlang = get_string("parentlanguage")) {
1562 if (file_exists("$CFG->dirroot/lang/$parentlang/countries.php")) {
1563 $lang = $parentlang;
1564 } else {
1565 $lang = "en"; // countries.php must exist in this pack
1566 }
1567 } else {
1568 $lang = "en"; // countries.php must exist in this pack
1569 }
5833a6c8 1570 }
1571
82196932 1572 include_once("$CFG->dirroot/lang/$lang/countries.php");
5833a6c8 1573
f8dbffb1 1574 if (!empty($string)) {
1575 asort($string);
1576 }
5833a6c8 1577
1578 return $string;
1579}
1580
82196932 1581function get_list_of_pixnames() {
1582/// Returns a list of picture names in the current language
1583 global $CFG;
1584
1585 $lang = current_language();
1586
1587 if (!file_exists("$CFG->dirroot/lang/$lang/pix.php")) {
1588 if ($parentlang = get_string("parentlanguage")) {
1589 if (file_exists("$CFG->dirroot/lang/$parentlang/pix.php")) {
1590 $lang = $parentlang;
1591 } else {
1592 $lang = "en"; // countries.php must exist in this pack
1593 }
1594 } else {
1595 $lang = "en"; // countries.php must exist in this pack
1596 }
1597 }
1598
1599 include_once("$CFG->dirroot/lang/$lang/pix.php");
1600
1601 return $string;
1602}
1603
9bd2c874 1604function document_file($file, $include=true) {
1605/// Can include a given document file (depends on second
1606/// parameter) or just return info about it
1607
c9d4e6da 1608 global $CFG;
9bd2c874 1609
db356340 1610 $file = clean_filename($file);
1611
9bd2c874 1612 if (empty($file)) {
9bd2c874 1613 return false;
1614 }
1615
db356340 1616 $langs = array(current_language(), get_string("parentlanguage"), "en");
9bd2c874 1617
db356340 1618 foreach ($langs as $lang) {
1619 $info->filepath = "$CFG->dirroot/lang/$lang/docs/$file";
1620 $info->urlpath = "$CFG->wwwroot/lang/$lang/docs/$file";
9bd2c874 1621
db356340 1622 if (file_exists($info->filepath)) {
1623 if ($include) {
1624 include($info->filepath);
1625 }
1626 return $info;
0c106cd3 1627 }
9bd2c874 1628 }
1629
db356340 1630 return false;
9bd2c874 1631}
1632
1a72314d 1633
f9903ed0 1634/// ENCRYPTION ////////////////////////////////////////////////
1635
1636function rc4encrypt($data) {
1637 $password = "nfgjeingjk";
1638 return endecrypt($password, $data, "");
1639}
1640
1641function rc4decrypt($data) {
1642 $password = "nfgjeingjk";
1643 return endecrypt($password, $data, "de");
1644}
1645
1646function endecrypt ($pwd, $data, $case) {
9fa49e22 1647/// Based on a class by Mukul Sabharwal [mukulsabharwal@yahoo.com]
f9903ed0 1648
1649 if ($case == 'de') {
1650 $data = urldecode($data);
1651 }
1652
1653 $key[] = "";
1654 $box[] = "";
1655 $temp_swap = "";
1656 $pwd_length = 0;
1657
1658 $pwd_length = strlen($pwd);
1659
1660 for ($i = 0; $i <= 255; $i++) {
1661 $key[$i] = ord(substr($pwd, ($i % $pwd_length), 1));
1662 $box[$i] = $i;
1663 }
1664
1665 $x = 0;
1666
1667 for ($i = 0; $i <= 255; $i++) {
1668 $x = ($x + $box[$i] + $key[$i]) % 256;
1669 $temp_swap = $box[$i];
1670 $box[$i] = $box[$x];
1671 $box[$x] = $temp_swap;
1672 }
1673
1674 $temp = "";
1675 $k = "";
1676
1677 $cipherby = "";
1678 $cipher = "";
1679
1680 $a = 0;
1681 $j = 0;
1682
1683 for ($i = 0; $i < strlen($data); $i++) {
1684 $a = ($a + 1) % 256;
1685 $j = ($j + $box[$a]) % 256;
1686 $temp = $box[$a];
1687 $box[$a] = $box[$j];
1688 $box[$j] = $temp;
1689 $k = $box[(($box[$a] + $box[$j]) % 256)];
1690 $cipherby = ord(substr($data, $i, 1)) ^ $k;
1691 $cipher .= chr($cipherby);
1692 }
1693
1694 if ($case == 'de') {
1695 $cipher = urldecode(urlencode($cipher));
1696 } else {
1697 $cipher = urlencode($cipher);
1698 }
1699
1700 return $cipher;
1701}
1702
1703
5fba04fb 1704/// CALENDAR MANAGEMENT ////////////////////////////////////////////////////////////////
1705
1706
1707function add_event($event) {
1708/// call this function to add an event to the calendar table
1709/// and to call any calendar plugins
1710/// The function returns the id number of the resulting record
1711/// The object event should include the following:
1712/// $event->name Name for the event
1713/// $event->description Description of the event (defaults to '')
1714/// $event->courseid The id of the course this event belongs to (0 = all courses)
1715/// $event->groupid The id of the group this event belongs to (0 = no group)
1716/// $event->userid The id of the user this event belongs to (0 = no user)
1717/// $event->modulename Name of the module that creates this event
1718/// $event->instance Instance of the module that owns this event
1719/// $event->eventtype The type info together with the module info could
1720/// be used by calendar plugins to decide how to display event
1721/// $event->timestart Timestamp for start of event
1722/// $event->timeduration Duration (defaults to zero)
1723
1724 global $CFG;
1725
1726 $event->timemodified = time();
1727
1728 if (!$event->id = insert_record("event", $event)) {
1729 return false;
1730 }
1731
1732 if (!empty($CFG->calendar)) { // call the add_event function of the selected calendar
1733 if (file_exists("$CFG->dirroot/calendar/$CFG->calendar/lib.php")) {
1734 include_once("$CFG->dirroot/calendar/$CFG->calendar/lib.php");
1735 $calendar_add_event = $CFG->calendar.'_add_event';
1736 if (function_exists($calendar_add_event)) {
1737 $calendar_add_event($event);
1738 }
1739 }
1740 }
1741
1742 return $event->id;
1743}
1744
1745
1746function update_event($event) {
1747/// call this function to update an event in the calendar table
1748/// the event will be identified by the id field of the $event object
1749
1750 global $CFG;
1751
1752 $event->timemodified = time();
1753
1754 if (!empty($CFG->calendar)) { // call the update_event function of the selected calendar
1755 if (file_exists("$CFG->dirroot/calendar/$CFG->calendar/lib.php")) {
1756 include_once("$CFG->dirroot/calendar/$CFG->calendar/lib.php");
1757 $calendar_update_event = $CFG->calendar.'_update_event';
1758 if (function_exists($calendar_update_event)) {
1759 $calendar_update_event($event);
1760 }
1761 }
1762 }
1763 return update_record("event", $event);
1764}
1765
1766
1767function delete_event($id) {
1768/// call this function to delete the event with id $id from calendar table
1769
1770 global $CFG;
1771
1772 if (!empty($CFG->calendar)) { // call the delete_event function of the selected calendar
1773 if (file_exists("$CFG->dirroot/calendar/$CFG->calendar/lib.php")) {
1774 include_once("$CFG->dirroot/calendar/$CFG->calendar/lib.php");
1775 $calendar_delete_event = $CFG->calendar.'_delete_event';
1776 if (function_exists($calendar_delete_event)) {
1777 $calendar_delete_event($id);
1778 }
1779 }
1780 }
1781 return delete_records("event", 'id', $id);
1782}
1783
1784
1785
1786
9fa49e22 1787/// ENVIRONMENT CHECKING ////////////////////////////////////////////////////////////
1e3e716f 1788
1d881d92 1789function get_list_of_plugins($plugin="mod") {
1790/// Lists plugin directories within some directory
1791
1792 global $CFG;
1793
1794 $basedir = opendir("$CFG->dirroot/$plugin");
1795 while ($dir = readdir($basedir)) {
b35e8568 1796 $firstchar = substr($dir, 0, 1);
bb9cf93d 1797 if ($firstchar == "." or $dir == "CVS" or $dir == "_vti_cnf") {
1d881d92 1798 continue;
1799 }
1800 if (filetype("$CFG->dirroot/$plugin/$dir") != "dir") {
1801 continue;
1802 }
1803 $plugins[] = $dir;
1804 }
1805 if ($plugins) {
1806 asort($plugins);
1807 }
1808 return $plugins;
1809}
1810
b0cb5e22 1811function check_php_version($version="4.1.0") {
9fa49e22 1812/// Returns true is the current version of PHP is greater that the specified one
b0cb5e22 1813 $minversion = intval(str_replace(".", "", $version));
1814 $curversion = intval(str_replace(".", "", phpversion()));
1815 return ($curversion >= $minversion);
1816}
1817
0095d5cd 1818function check_browser_version($brand="MSIE", $version=5.5) {
9fa49e22 1819/// Checks to see if is a browser matches the specified
1820/// brand and is equal or better version.
0095d5cd 1821
4c46c425 1822 $agent = $_SERVER["HTTP_USER_AGENT"];
1823
1824 if (empty($agent)) {
0095d5cd 1825 return false;
1826 }
4c46c425 1827
1828 switch ($brand) {
1829
1830 case "Gecko": /// Gecko based browsers
1831
1832 if (substr_count($agent, "Camino")) { // MacOS X Camino not supported.
1833 return false;
1834 }
1835
1836 // the proper string - Gecko/CCYYMMDD Vendor/Version
1837 if (ereg("^([a-zA-Z]+)/([0-9]+\.[0-9]+) \((.*)\) (.*)$", $agent, $match)) {
1838 if (ereg("^([Gecko]+)/([0-9]+)",$match[4], $reldate)) {
1839 if ($reldate[2] > $version) {
1840 return true;
1841 }
1842 }
1843 }
1844 break;
1845
1846
1847 case "MSIE": /// Internet Explorer
1848
1849 $string = explode(";", $agent);
1850 if (!isset($string[1])) {
1851 return false;
1852 }
1853 $string = explode(" ", trim($string[1]));
1854 if (!isset($string[0]) and !isset($string[1])) {
1855 return false;
1856 }
1857 if ($string[0] == $brand and (float)$string[1] >= $version ) {
1858 return true;
1859 }
1860 break;
1861
0095d5cd 1862 }
4c46c425 1863
0095d5cd 1864 return false;
1865}
1866
4c46c425 1867
c39c66a5 1868function ini_get_bool($ini_get_arg) {
1869/// This function makes the return value of ini_get consistent if you are
1870/// setting server directives through the .htaccess file in apache.
1871/// Current behavior for value set from php.ini On = 1, Off = [blank]
1872/// Current behavior for value set from .htaccess On = On, Off = Off
1873/// Contributed by jdell@unr.edu
1874
1875 $temp = ini_get($ini_get_arg);
1876
1877 if ($temp == "1" or strtolower($temp) == "on") {
1878 return true;
1879 }
1880 return false;
1881}
1882
0095d5cd 1883function can_use_richtext_editor() {
47037513 1884/// Compatibility stub to provide backward compatibility
1885 return can_use_html_editor();
1886}
1887
1888function can_use_html_editor() {
4c46c425 1889/// Is the HTML editor enabled? This depends on site and user
1890/// settings, as well as the current browser being used.
47037513 1891/// Returns false is editor is not being used, otherwise
1892/// returns "MSIE" or "Gecko"
4c46c425 1893
0095d5cd 1894 global $USER, $CFG;
4c46c425 1895
ce78926d 1896 if (!empty($USER->htmleditor) and !empty($CFG->htmleditor)) {
4c46c425 1897 if (check_browser_version("MSIE", 5.5)) {
47037513 1898 return "MSIE";
1899 } else if (check_browser_version("Gecko", 20030516)) {
1900 return "Gecko";
4c46c425 1901 }
7ce20f09 1902 }
1903 return false;
0095d5cd 1904}
1905
47037513 1906
74944b73 1907function check_gd_version() {
9fa49e22 1908/// Hack to find out the GD version by parsing phpinfo output
aa095969 1909 $gdversion = 0;
74944b73 1910
aa095969 1911 if (function_exists('gd_info')){
1912 $gd_info = gd_info();
3ee23682 1913 if (substr_count($gd_info['GD Version'], "2.")) {
aa095969 1914 $gdversion = 2;
3ee23682 1915 } else if (substr_count($gd_info['GD Version'], "1.")) {
1916 $gdversion = 1;
aa095969 1917 }
3ee23682 1918
aa095969 1919 } else {
1920 ob_start();
1921 phpinfo(8);
1922 $phpinfo = ob_get_contents();
1923 ob_end_clean();
74944b73 1924
aa095969 1925 $phpinfo = explode("\n",$phpinfo);
74944b73 1926
92a4b0f1 1927
aa095969 1928 foreach ($phpinfo as $text) {
1929 $parts = explode('</td>',$text);
1930 foreach ($parts as $key => $val) {
1931 $parts[$key] = trim(strip_tags($val));
1932 }
1933 if ($parts[0] == "GD Version") {
1934 if (substr_count($parts[1], "2.0")) {
1935 $parts[1] = "2.0";
1936 }
1937 $gdversion = intval($parts[1]);
92a4b0f1 1938 }
74944b73 1939 }
1940 }
1941
1942 return $gdversion; // 1, 2 or 0
1943}
f9903ed0 1944
0095d5cd 1945
9fa49e22 1946function moodle_needs_upgrading() {
1947/// Checks version numbers of Main code and all modules to see
1948/// if there are any mismatches ... returns true or false
1949 global $CFG;
1950
1951 include_once("$CFG->dirroot/version.php"); # defines $version and upgrades
1952 if ($CFG->version) {
1953 if ($version > $CFG->version) {
1954 return true;
1955 }
1956 if ($mods = get_list_of_plugins("mod")) {
1957 foreach ($mods as $mod) {
1958 $fullmod = "$CFG->dirroot/mod/$mod";
1959 unset($module);
1079c8a8 1960 if (!is_readable("$fullmod/version.php")) {
1961 notify("Module '$mod' is not readable - check permissions");
1962 continue;
1963 }
9fa49e22 1964 include_once("$fullmod/version.php"); # defines $module with version etc
1965 if ($currmodule = get_record("modules", "name", $mod)) {
1966 if ($module->version > $currmodule->version) {
1967 return true;
1968 }
1969 }
1970 }
1971 }
1972 } else {
1973 return true;
1974 }
1975 return false;
1976}
1977
1978
1979/// MISCELLANEOUS ////////////////////////////////////////////////////////////////////
1980
7d6cac54 1981function moodle_strtolower ($string, $encoding='') {
1982/// Converts string to lowercase using most compatible function available
1983 if (function_exists('mb_strtolower')) {
1984 if($encoding===''){
1985 return mb_strtolower($string); //use multibyte support with default encoding
1986 } else {
dbe0be00 1987 return mb_strtolower($string,$encoding); //use given encoding
7d6cac54 1988 }
1989 } else {
1990 return strtolower($string); // use common function what rely on current locale setting
1991 }
1992}
1993
9fa49e22 1994function count_words($string) {
1995/// Words are defined as things between whitespace
1996 $string = strip_tags($string);
1997 return count(preg_split("/\w\b/", $string)) - 1;
1998}
1999
1d881d92 2000function random_string ($length=15) {
2001 $pool = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
2002 $pool .= "abcdefghijklmnopqrstuvwxyz";
2003 $pool .= "0123456789";
2004 $poollen = strlen($pool);
2005 mt_srand ((double) microtime() * 1000000);
2006 $string = "";
2007 for ($i = 0; $i < $length; $i++) {
2008 $string .= substr($pool, (mt_rand()%($poollen)), 1);
2009 }
2010 return $string;
2011}
2012
2013
9fa49e22 2014function getweek ($startdate, $thedate) {
2015/// Given dates in seconds, how many weeks is the date from startdate
2016/// The first week is 1, the second 2 etc ...
2017
2018 if ($thedate < $startdate) { // error
2019 return 0;
2020 }
2021
2022 return floor(($thedate - $startdate) / 604800.0) + 1;
2023}
2024
2025function generate_password($maxlen=10) {
2026/// returns a randomly generated password of length $maxlen. inspired by
2027/// http://www.phpbuilder.com/columns/jesus19990502.php3
2028
2029 global $CFG;
2030
2031 $fillers = "1234567890!$-+";
2032 $wordlist = file($CFG->wordlist);
2033
2034 srand((double) microtime() * 1000000);
2035 $word1 = trim($wordlist[rand(0, count($wordlist) - 1)]);
2036 $word2 = trim($wordlist[rand(0, count($wordlist) - 1)]);
2037 $filler1 = $fillers[rand(0, strlen($fillers) - 1)];
2038
2039 return substr($word1 . $filler1 . $word2, 0, $maxlen);
2040}
2041
2042function format_float($num, $places=0) {
2043/// Given a float, prints it nicely
2044 return sprintf("%.$places"."f", $num);
2045}
2046
ee0e5d57 2047function swapshuffle($array) {
2048/// Given a simple array, this shuffles it up just like shuffle()
2049/// Unlike PHP's shuffle() ihis function works on any machine.
2050
2051 srand ((double) microtime() * 10000000);
2052 $last = count($array) - 1;
2053 for ($i=0;$i<=$last;$i++) {
2054 $from = rand(0,$last);
2055 $curr = $array[$i];
2056 $array[$i] = $array[$from];
2057 $array[$from] = $curr;
2058 }
2059 return $array;
2060}
2061
bc700e65 2062function swapshuffle_assoc($array) {
2063/// Like swapshuffle, but works on associative arrays
2064
2065 $newkeys = swapshuffle(array_keys($array));
2066 foreach ($newkeys as $newkey) {
2067 $newarray[$newkey] = $array[$newkey];
2068 }
2069 return $newarray;
2070}
2071
ee0e5d57 2072function draw_rand_array($array, $draws) {
2073/// Given an arbitrary array, and a number of draws,
2074/// this function returns an array with that amount
2075/// of items. The indexes are retained.
2076
2077 srand ((double) microtime() * 10000000);
2078
2079 $return = array();
2080
2081 $last = count($array);
2082
2083 if ($draws > $last) {
2084 $draws = $last;
2085 }
2086
2087 while ($draws > 0) {
2088 $last--;
2089
2090 $keys = array_keys($array);
2091 $rand = rand(0, $last);
2092
2093 $return[$keys[$rand]] = $array[$keys[$rand]];
2094 unset($array[$keys[$rand]]);
2095
2096 $draws--;
2097 }
2098
2099 return $return;
2100}
9fa49e22 2101
f5e82bc7 2102function microtime_diff($a, $b) {
2103 list($a_dec, $a_sec) = explode(" ", $a);
2104 list($b_dec, $b_sec) = explode(" ", $b);
2105 return $b_sec - $a_sec + $b_dec - $a_dec;
2106}
2107
02ebf404 2108function make_menu_from_list($list, $separator=",") {
2109/// Given a list (eg a,b,c,d,e) this function returns
2110/// an array of 1->a, 2->b, 3->c etc
2111
2112 $array = array_reverse(explode($separator, $list), true);
2113 foreach ($array as $key => $item) {
2114 $outarray[$key+1] = trim($item);
2115 }
2116 return $outarray;
2117}
2118
fdc47ee6 2119function make_grades_menu($gradingtype) {
2120/// Creates an array that represents all the current grades that
2121/// can be chosen using the given grading type. Negative numbers
2122/// are scales, zero is no grade, and positive numbers are maximum
2123/// grades.
2124
2125 $grades = array();
2126 if ($gradingtype < 0) {
2127 if ($scale = get_record("scale", "id", - $gradingtype)) {
2128 return make_menu_from_list($scale->scale);
2129 }
2130 } else if ($gradingtype > 0) {
2131 for ($i=$gradingtype; $i>=0; $i--) {
62ca135d 2132 $grades[$i] = "$i / $gradingtype";
fdc47ee6 2133 }
2134 return $grades;
2135 }
2136 return $grades;
2137}
2138
757a0abd 2139function make_unique_id_code($extra="") {
280faf9f 2140
2141 $hostname = "unknownhost";
2142 if (!empty($_SERVER["HTTP_HOST"])) {
2143 $hostname = $_SERVER["HTTP_HOST"];
2144 } else if (!empty($_ENV["HTTP_HOST"])) {
2145 $hostname = $_ENV["HTTP_HOST"];
2146 } else if (!empty($_SERVER["SERVER_NAME"])) {
2147 $hostname = $_SERVER["SERVER_NAME"];
2148 } else if (!empty($_ENV["SERVER_NAME"])) {
2149 $hostname = $_ENV["SERVER_NAME"];
2150 }
2151
1ccc73ac 2152 $date = gmdate("ymdHis");
280faf9f 2153
2154 $random = random_string(6);
2155
757a0abd 2156 if ($extra) {
2157 return "$hostname+$date+$random+$extra";
2158 } else {
2159 return "$hostname+$date+$random";
2160 }
280faf9f 2161}
2162
0095d5cd 2163
9d5b689c 2164// vim:autoindent:expandtab:shiftwidth=4:tabstop=4:tw=140:
f9903ed0 2165?>