6 // Large collection of useful functions used by many parts of Moodle.
8 // Martin Dougiamas, 2000
11 /// STANDARD WEB PAGE PARTS ///////////////////////////////////////////////////
13 function print_header ($title="", $heading="", $navigation="", $focus="", $meta="", $cache=true, $button="", $menu="") {
14 // $title - appears top of window
15 // $heading - appears top of page
16 // $navigation - premade navigation string
17 // $focus - indicates form element eg inputform.password
18 // $meta - meta tags in the header
19 // $cache - should this page be cacheable?
20 // $button - HTML code for a button (usually for module editing)
21 // $menu - HTML code for a popup menu
22 global $USER, $CFG, $THEME;
24 if (file_exists("$CFG->dirroot/theme/$CFG->theme/styles.css")) {
25 $styles = "$CFG->wwwroot/theme/$CFG->theme/styles.css";
27 $styles = "$CFG->wwwroot/theme/standard/styles.css";
30 if ($navigation == "home") {
35 if (!$menu and $navigation) {
36 if (isset($USER->id)) {
37 $menu = "<FONT SIZE=2><A TARGET=_parent HREF=\"$CFG->wwwroot/login/logout.php\">".get_string("logout")."</A></FONT>";
39 $menu = "<FONT SIZE=2><A TARGET=_parent HREF=\"$CFG->wwwroot/login/index.php\">".get_string("login")."</A></FONT>";
43 // Specify character set ... default is iso-8859-1 but some languages might need something else
44 // Could be optimised by carrying the charset variable around in $USER
45 if (current_language() == "en") {
46 $meta .= "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=iso-8859-1\">\n";
48 $meta .= "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=".get_string("thischarset")."\">\n";
51 if ($CFG->langdir == "RTL") {
52 $direction = " DIR=\"RTL\"";
54 $direction = " DIR=\"LTR\"";
57 if (!$cache) { // Do everything we can to prevent clients and proxies caching
58 @header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
59 @header("Pragma: no-cache");
60 $meta .= "\n<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">";
61 $meta .= "\n<META HTTP-EQUIV=\"Expires\" CONTENT=\"0\">";
64 include ("$CFG->dirroot/theme/$CFG->theme/header.html");
67 function print_footer ($course=NULL) {
68 // Can provide a course object to make the footer contain a link to
69 // to the course home page, otherwise the link will go to the site home
70 global $USER, $CFG, $THEME;
75 if ($course == "home") { // special case for site home page - please do not remove
76 $homelink = "<P ALIGN=center><A TITLE=\"Moodle $CFG->release ($CFG->version)\" HREF=\"http://moodle.com/\">";
77 $homelink .= "<BR><IMG WIDTH=130 HEIGHT=19 SRC=\"pix/madewithmoodle2.gif\" BORDER=0></A></P>";
81 $homelink = "<A TARGET=_top HREF=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</A>";
84 $homelink = "<A TARGET=_top HREF=\"$CFG->wwwroot\">".get_string("home")."</A>";
89 if ($USER->realuser) {
90 if ($realuser = get_record("user", "id", $USER->realuser)) {
91 $realuserinfo = " [<A HREF=\"$CFG->wwwroot/course/loginas.php?id=$course->id&return=$realuser->id\">$realuser->firstname $realuser->lastname</A>] ";
96 $username = "<A HREF=\"$CFG->wwwroot/user/view.php?id=$USER->id&course=$course->id\">$USER->firstname $USER->lastname</A>";
97 $loggedinas = $realuserinfo.get_string("loggedinas", "moodle", "$username").
98 " (<A HREF=\"$CFG->wwwroot/login/logout.php\">".get_string("logout")."</A>)";
100 $loggedinas = get_string("loggedinnot", "moodle").
101 " (<A HREF=\"$CFG->wwwroot/login/index.php\">".get_string("login")."</A>)";
104 include ("$CFG->dirroot/theme/$CFG->theme/footer.html");
109 function print_navigation ($navigation) {
113 if (! $site = get_site()) {
114 $site->shortname = get_string("home");;
116 echo "<A TARGET=_top HREF=\"$CFG->wwwroot/\">$site->shortname</A> -> $navigation";
120 function print_heading($text, $align="CENTER", $size=3) {
121 echo "<P ALIGN=\"$align\"><FONT SIZE=\"$size\"><B>".stripslashes($text)."</B></FONT></P>";
124 function print_heading_with_help($text, $helppage, $module="moodle") {
125 // Centered heading with attached help button (same title text)
126 echo "<P ALIGN=\"CENTER\"><FONT SIZE=\"3\"><B>".stripslashes($text);
127 helpbutton($helppage, $text, $module);
128 echo "</B></FONT></P>";
131 function print_continue($link) {
132 global $HTTP_REFERER;
135 $link = $HTTP_REFERER;
138 print_heading("<A HREF=\"$link\">".get_string("continue")."</A>");
142 function print_simple_box($message, $align="", $width="", $color="#FFFFFF", $padding=5, $border=1) {
143 print_simple_box_start($align, $width, $color, $padding, $border);
144 echo "<P>".stripslashes($message)."</P>";
145 print_simple_box_end();
148 function print_simple_box_start($align="", $width="", $color="#FFFFFF", $padding=5, $border=1) {
152 $tablealign = "ALIGN=\"$align\"";
155 $tablewidth = "WIDTH=\"$width\"";
156 $innertablewidth = "WIDTH=\"100%\"";
158 echo "<TABLE $tablealign $tablewidth BORDER=0 CELLPADDING=\"$border\" CELLSPACING=0>";
159 echo "<TR><TD BGCOLOR=\"$THEME->borders\">\n";
160 echo "<TABLE $innertablewidth BORDER=0 CELLPADDING=\"$padding\" CELLSPACING=0><TR><TD BGCOLOR=\"$color\">";
163 function print_simple_box_end() {
164 echo "</TD></TR></TABLE>";
165 echo "</TD></TR></TABLE>";
168 function print_single_button($link, $options, $label="OK") {
169 echo "<FORM ACTION=\"$link\" METHOD=GET>";
171 foreach ($options as $name => $value) {
172 echo "<INPUT TYPE=hidden NAME=\"$name\" VALUE=\"$value\">";
175 echo "<INPUT TYPE=submit VALUE=\"$label\"></FORM>";
178 function print_spacer($height=1, $width=1, $br=true) {
180 echo "<IMG HEIGHT=\"$height\" WIDTH=\"$width\" SRC=\"$CFG->wwwroot/pix/spacer.gif\" ALT=\"\">";
186 function print_file_picture($path, $courseid=0, $height="", $width="", $link="") {
187 // Given the path to a picture file in a course, or a URL,
188 // this function includes the picture in the page.
192 $height = "HEIGHT=\"$height\"";
195 $width = "WIDTH=\"$width\"";
198 echo "<A HREF=\"$link\">";
200 if (substr(strtolower($path), 0, 7) == "http://") {
201 echo "<IMG BORDER=0 $height $width SRC=\"$path\">";
203 } else if ($courseid) {
204 echo "<IMG BORDER=0 $height $width SRC=\"";
205 if ($CFG->slasharguments) { // Use this method if possible for better caching
206 echo "$CFG->wwwroot/file.php/$courseid/$path";
208 echo "$CFG->wwwroot/file.php?file=$courseid/$path";
212 echo "Error: must pass URL or course";
219 function print_user_picture($userid, $courseid, $picture, $large=false, $returnstring=false) {
222 $output = "<A HREF=\"$CFG->wwwroot/user/view.php?id=$userid&course=$courseid\">";
231 if ($CFG->slasharguments) { // Use this method if possible for better caching
232 $output .= "<IMG SRC=\"$CFG->wwwroot/user/pix.php/$userid/$file\" BORDER=0 WIDTH=$size HEIGHT=$size ALT=\"\">";
234 $output .= "<IMG SRC=\"$CFG->wwwroot/user/pix.php?file=/$userid/$file\" BORDER=0 WIDTH=$size HEIGHT=$size ALT=\"\">";
237 $output .= "<IMG SRC=\"$CFG->wwwroot/user/default/$file\" BORDER=0 WIDTH=$size HEIGHT=$size ALT=\"\">";
248 function print_table($table) {
249 // Prints a nicely formatted table.
250 // $table is an object with several properties.
251 // $table->head is an array of heading names.
252 // $table->align is an array of column alignments
253 // $table->size is an array of column sizes
254 // $table->data[] is an array of arrays containing the data.
255 // $table->width is an percentage of the page
256 // $table->cellpadding padding on each cell
257 // $table->cellspacing spacing between cells
259 if (isset($table->align)) {
260 foreach ($table->align as $key => $aa) {
262 $align[$key] = " ALIGN=\"$aa\"";
268 if (isset($table->size)) {
269 foreach ($table->size as $key => $ss) {
271 $size[$key] = " WIDTH=\"$ss\"";
278 if (!$table->width) {
279 $table->width = "80%";
282 if (!$table->cellpadding) {
283 $table->cellpadding = "5";
286 if (!$table->cellspacing) {
287 $table->cellspacing = "1";
290 print_simple_box_start("CENTER", "$table->width", "#FFFFFF", 0);
291 echo "<TABLE WIDTH=100% BORDER=0 valign=top align=center ";
292 echo " cellpadding=\"$table->cellpadding\" cellspacing=\"$table->cellspacing\">\n";
296 foreach ($table->head as $key => $heading) {
297 echo "<TH VALIGN=top ".$align[$key].$size[$key].">$heading</TH>";
302 foreach ($table->data as $row) {
303 echo "<TR VALIGN=TOP>";
304 foreach ($row as $key => $item) {
305 echo "<TD ".$align[$key].$size[$key].">$item</TD>";
310 print_simple_box_end();
315 function print_editing_switch($courseid) {
318 if (isteacher($courseid)) {
319 if ($USER->editing) {
320 echo "<A HREF=\"$CFG->wwwroot/course/view.php?id=$courseid&edit=off\">Turn editing off</A>";
322 echo "<A HREF=\"$CFG->wwwroot/course/view.php?id=$courseid&edit=on\">Turn editing on</A>";
327 function format_float($num, $places=0) {
328 return sprintf("%.$places"."f", $num);
331 function print_textarea($richedit, $rows, $cols, $width, $height, $name, $value="") {
335 echo "<object id=richedit style=\"BACKGROUND-COLOR: buttonface\"";
336 echo " data=\"$CFG->wwwroot/lib/rte/richedit.html\"";
337 echo " width=\"$width\" height=\"$height\" ";
338 echo " type=\"text/x-scriptlet\" VIEWASTEXT></object>\n";
339 echo "<TEXTAREA style=\"display:none\" NAME=\"$name\" ROWS=1 COLS=1>";
341 echo "</TEXTAREA>\n";
343 echo "<TEXTAREA name=\"$name\" rows=\"$rows\" cols=\"$cols\" wrap=virtual>";
345 echo "</TEXTAREA>\n";
349 function print_richedit_javascript($form, $name, $source="no") {
350 echo "<SCRIPT language=\"JavaScript\" event=\"onload\" for=\"window\">\n";
351 echo " document.richedit.options = \"history=no;source=$source\";";
352 echo " document.richedit.docHtml = $form.$name.innerText;";
357 function update_course_icon($courseid) {
358 // Used to be an icon, but it's now a simple form button
361 if (isteacher($courseid)) {
362 if ($USER->editing) {
363 $string = get_string("turneditingoff");
366 $string = get_string("turneditingon");
369 return "<FORM TARGET=_parent METHOD=GET ACTION=\"$CFG->wwwroot/course/view.php\">".
370 "<INPUT TYPE=hidden NAME=id VALUE=\"$courseid\">".
371 "<INPUT TYPE=hidden NAME=edit VALUE=\"$edit\">".
372 "<INPUT TYPE=submit VALUE=\"$string\"></FORM>";
376 function update_module_button($moduleid, $courseid, $string) {
377 // Prints the editing button on a module "view" page
380 if (isteacher($courseid)) {
381 $string = get_string("updatethis", "", $string);
382 return "<FORM TARGET=_parent METHOD=GET ACTION=\"$CFG->wwwroot/course/mod.php\">".
383 "<INPUT TYPE=hidden NAME=update VALUE=\"$moduleid\">".
384 "<INPUT TYPE=hidden NAME=return VALUE=\"true\">".
385 "<INPUT TYPE=submit VALUE=\"$string\"></FORM>";
390 function navmenu($course, $cm=NULL) {
391 // Given a course and a (current) coursemodule
392 // This function returns a small popup menu with all the
393 // course activity modules in it, as a navigation menu
394 // The data is taken from the serialised array stored in
403 if ($course->format == 'weeks') {
404 $strsection = get_string("week");
406 $strsection = get_string("topic");
409 if (!$array = unserialize($course->modinfo)) {
414 foreach ($array as $mod) {
415 if ($mod->section > 0 and $section <> $mod->section) {
416 $menu[] = "-------------- $strsection $mod->section --------------";
418 $section = $mod->section;
419 $url = "$mod->mod/view.php?id=$mod->cm";
420 if ($cm == $mod->cm) {
423 $mod->name = urldecode($mod->name);
424 if (strlen($mod->name) > 55) {
425 $mod->name = substr($mod->name, 0, 50)."...";
427 $menu[$url] = $mod->name;
430 return popup_form("$CFG->wwwroot/mod/", $menu, "navmenu", $selected, get_string("jumpto"), "", "", true);
434 function print_date_selector($day, $month, $year, $currenttime=0) {
435 // Currenttime is a default timestamp in GMT
436 // Prints form items with the names $day, $month and $year
439 $currenttime = time();
441 $currentdate = usergetdate($currenttime);
443 for ($i=1; $i<=31; $i++) {
446 for ($i=1; $i<=12; $i++) {
447 $months[$i] = date("F", mktime(0,0,0,$i,1,2000));
449 for ($i=2000; $i<=2010; $i++) {
452 choose_from_menu($days, $day, $currentdate[mday], "");
453 choose_from_menu($months, $month, $currentdate[mon], "");
454 choose_from_menu($years, $year, $currentdate[year], "");
457 function print_time_selector($hour, $minute, $currenttime=0) {
458 // Currenttime is a default timestamp in GMT
459 // Prints form items with the names $hour and $minute
462 $currenttime = time();
464 $currentdate = usergetdate($currenttime);
465 for ($i=0; $i<=23; $i++) {
466 $hours[$i] = sprintf("%02d",$i);
468 for ($i=0; $i<=59; $i++) {
469 $minutes[$i] = sprintf("%02d",$i);
471 choose_from_menu($hours, $hour, $currentdate[hours], "");
472 choose_from_menu($minutes, $minute, $currentdate[minutes], "");
475 function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0) {
476 // Given date parts in user time, produce a GMT timestamp
478 return mktime((int)$hour,(int)$minute,(int)$second,(int)$month,(int)$day,(int)$year);
482 function format_time($totalsecs, $str=NULL) {
483 // Given an amount of time in seconds, prints it
484 // nicely as months, days, hours etc as needed
486 $totalsecs = abs($totalsecs);
488 if (!$str) { // Create the str structure the slow way
489 $str->day = get_string("day");
490 $str->days = get_string("days");
491 $str->hour = get_string("hour");
492 $str->hours = get_string("hours");
493 $str->min = get_string("min");
494 $str->mins = get_string("mins");
495 $str->sec = get_string("sec");
496 $str->secs = get_string("secs");
499 $days = floor($totalsecs/86400);
500 $remainder = $totalsecs - ($days*86400);
501 $hours = floor($remainder/3600);
502 $remainder = $remainder - ($hours*3600);
503 $mins = floor($remainder/60);
504 $secs = $remainder - ($mins*60);
506 $ss = ($secs == 1) ? $str->sec : $str->secs;
507 $sm = ($mins == 1) ? $str->min : $str->mins;
508 $sh = ($hours == 1) ? $str->hour : $str->hours;
509 $sd = ($days == 1) ? $str->day : $str->days;
511 if ($days) $odays = "$days $sd";
512 if ($hours) $ohours = "$hours $sh";
513 if ($mins) $omins = "$mins $sm";
514 if ($secs) $osecs = "$secs $ss";
516 if ($days) return "$odays $ohours";
517 if ($hours) return "$ohours $omins";
518 if ($mins) return "$omins $osecs";
519 if ($secs) return "$osecs";
520 return get_string("now");
523 function userdate($date, $format="", $timezone=99) {
524 // Returns a formatted string that represents a date in user time
525 // WARNING: note that the format is for strftime(), not date().
530 $format = "%A, %e %B %Y, %I:%M %p";
532 if ($timezone == 99) {
533 if (isset($USER->timezone)) {
534 $timezone = (float)$USER->timezone;
537 if (abs($timezone) > 12) {
538 return strftime("$format", $date);
540 return gmstrftime($format, $date + (int)($timezone * 3600));
543 function usergetdate($date, $timezone=99) {
544 // Given a $date timestamp in GMT, returns an array
545 // that represents the date in user time
549 if ($timezone == 99) {
550 $timezone = (float)$USER->timezone;
552 if (abs($timezone) > 12) {
553 return getdate($date);
555 //There is no gmgetdate so I have to fake it...
556 $date = $date + (int)($timezone * 3600);
557 $getdate["seconds"] = gmstrftime("%S", $date);
558 $getdate["minutes"] = gmstrftime("%M", $date);
559 $getdate["hours"] = gmstrftime("%H", $date);
560 $getdate["mday"] = gmstrftime("%d", $date);
561 $getdate["wday"] = gmstrftime("%u", $date);
562 $getdate["mon"] = gmstrftime("%m", $date);
563 $getdate["year"] = gmstrftime("%Y", $date);
564 $getdate["yday"] = gmstrftime("%j", $date);
565 $getdate["weekday"] = gmstrftime("%A", $date);
566 $getdate["month"] = gmstrftime("%B", $date);
570 function usertime($date, $timezone=99) {
571 // Given a GMT timestamp (seconds since epoch), offsets it by
572 // the timezone. eg 3pm in India is 3pm GMT - 7 * 3600 seconds
575 if ($timezone == 99) {
576 $timezone = (float)$USER->timezone;
578 if (abs($timezone) > 12) {
581 return $date - (int)($timezone * 3600);
584 function usergetmidnight($date, $timezone=99) {
585 // Given a time, return the GMT timestamp of the most recent midnight
586 // for the current user.
589 if ($timezone == 99) {
590 $timezone = (float)$USER->timezone;
593 $userdate = usergetdate($date, $timezone);
595 if (abs($timezone) > 12) {
596 return mktime(0, 0, 0, $userdate["mon"], $userdate["mday"], $userdate["year"]);
599 $timemidnight = gmmktime (0, 0, 0, $userdate["mon"], $userdate["mday"], $userdate["year"]);
600 return usertime($timemidnight, $timezone); // Time of midnight of this user's day, in GMT
604 function usertimezone($timezone=99) {
605 // returns a string that prints the user's timezone
608 if ($timezone == 99) {
609 $timezone = (float)$USER->timezone;
611 if (abs($timezone) > 12) {
612 return "server time";
614 if (abs($timezone) < 0.5) {
618 return "GMT+$timezone";
620 return "GMT$timezone";
625 function error ($message, $link="") {
626 global $CFG, $SESSION;
628 print_header(get_string("error"));
630 print_simple_box($message, "center", "", "#FFBBBB");
633 if ( !empty($SESSION->fromurl) ) {
634 $link = "$SESSION->fromurl";
635 unset($SESSION->fromurl);
636 save_session("SESSION");
638 $link = "$CFG->wwwroot";
641 print_continue($link);
646 function helpbutton ($page, $title="", $module="moodle", $image=true, $text="") {
647 // $page = the keyword that defines a help page
648 // $title = the title of links, rollover tips, alt tags etc
649 // $module = which module is the page defined in
650 // $image = use a help image for the link? (otherwise uses text)
651 // $text = if defined then this text is used in the page, and
652 // the $page variable is ignored.
659 $linkobject = "<IMG BORDER=0 HEIGHT=17 WIDTH=22 ALT=\"$title\" SRC=\"$CFG->wwwroot/pix/help.gif\">";
661 $linkobject = $title;
664 $url = "/help.php?module=$module&text=$text";
666 $url = "/help.php?module=$module&file=$page.html";
668 link_to_popup_window ($url, "popup", $linkobject, 400, 500, $title);
671 function notice ($message, $link="") {
672 global $THEME, $HTTP_REFERER;
675 $link = $HTTP_REFERER;
679 print_simple_box($message, "center", "", "$THEME->cellheading");
680 print_heading("<A HREF=\"$link\">".get_string("continue")."</A>");
681 print_footer(get_site());
685 function notice_yesno ($message, $linkyes, $linkno) {
688 print_simple_box_start("center", "", "$THEME->cellheading");
689 echo "<P ALIGN=CENTER><FONT SIZE=3>$message</FONT></P>";
690 echo "<P ALIGN=CENTER><FONT SIZE=3><B>";
691 echo "<A HREF=\"$linkyes\">".get_string("yes")."</A>";
692 echo " ";
693 echo "<A HREF=\"$linkno\">".get_string("no")."</A>";
694 echo "</B></FONT></P>";
695 print_simple_box_end();
698 function redirect($url, $message="", $delay=0) {
699 // Uses META tags to redirect the user, after printing a notice
701 echo "<META HTTP-EQUIV='Refresh' CONTENT='$delay; URL=$url'>";
703 if (!empty($message)) {
706 echo "<P>$message</P>";
707 echo "<P>( <A HREF=\"$url\">".get_string("continue")."</A> )</P>";
713 function notify ($message) {
714 echo "<P align=center><B><FONT COLOR=#FF0000>$message</FONT></B></P>\n";
719 /// PARAMETER HANDLING ////////////////////////////////////////////////////
721 function require_variable($var) {
723 error("A required parameter was missing");
727 function optional_variable(&$var, $default=0) {
736 /// DATABASE HANDLING ////////////////////////////////////////////////
738 function execute_sql($command, $feedback=true) {
739 // Completely general
743 $result = $db->Execute("$command");
747 echo "<P><FONT COLOR=green><B>".get_string("success")."</B></FONT></P>";
752 echo "<P><FONT COLOR=red><B>".get_string("error")."</B></FONT></P>";
758 function modify_database($sqlfile) {
759 // Assumes that the input text file consists of a number
760 // of SQL statements ENDING WITH SEMICOLONS. The semicolons
761 // MUST be the last character in a line.
762 // Lines that are blank or that start with "#" are ignored.
763 // Only tested with mysql dump files (mysqldump -p -d moodle)
766 if (file_exists($sqlfile)) {
768 $lines = file($sqlfile);
771 while ( list($i, $line) = each($lines) ) {
773 $length = strlen($line);
775 if ($length && substr($line, 0, 1) <> "#") {
776 if (substr($line, $length-1, 1) == ";") {
777 $line = substr($line, 0, $length-1); // strip ;
779 if (! execute_sql($command)) {
791 echo "<P>Tried to modify database, but \"$sqlfile\" doesn't exist!</P>";
798 function record_exists($table, $field, $value) {
801 $rs = $db->Execute("SELECT * FROM $table WHERE $field = '$value' LIMIT 1");
802 if (!$rs) return false;
804 if ( $rs->RecordCount() ) {
811 function record_exists_sql($sql) {
814 $rs = $db->Execute($sql);
815 if (!$rs) return false;
817 if ( $rs->RecordCount() ) {
825 function count_records($table, $selector, $value) {
826 // Get all the records and count them
829 $rs = $db->Execute("SELECT COUNT(*) FROM $table WHERE $selector = '$value'");
832 return $rs->fields[0];
835 function count_records_sql($sql) {
836 // Get all the records and count them
839 $rs = $db->Execute("$sql");
842 return $rs->fields[0];
845 function get_record($table, $selector, $value) {
846 // Get a single record as an object
849 $rs = $db->Execute("SELECT * FROM $table WHERE $selector = '$value'");
850 if (!$rs) return false;
852 if ( $rs->RecordCount() == 1 ) {
853 return (object)$rs->fields;
859 function get_record_sql($sql) {
860 // Get a single record as an object
861 // The sql statement is provided as a string.
865 $rs = $db->Execute("$sql");
866 if (!$rs) return false;
868 if ( $rs->RecordCount() == 1 ) {
869 return (object)$rs->fields;
875 function get_records($table, $selector, $value, $sort="", $fields="*") {
876 // Get a number of records as an array of objects
877 // Can optionally be sorted eg "time ASC" or "time DESC"
878 // If "fields" is specified, only those fields are returned
879 // The "key" is the first column returned, eg usually "id"
883 $sortorder = "ORDER BY $sort";
885 $sql = "SELECT $fields FROM $table WHERE $selector = '$value' $sortorder";
887 return get_records_sql($sql);
891 function get_records_list($table, $selector, $values, $sort="", $fields="*") {
892 // Get a number of records as an array of objects
893 // Differs from get_records() in that the values variable
894 // can be a comma-separated list of values eg "4,5,6,10"
895 // Can optionally be sorted eg "time ASC" or "time DESC"
896 // The "key" is the first column returned, eg usually "id"
900 $sortorder = "ORDER BY $sort";
902 $sql = "SELECT $fields FROM $table WHERE $selector in ($values) $sortorder";
904 return get_records_sql($sql);
908 function get_records_sql($sql) {
909 // Get a number of records as an array of objects
910 // The "key" is the first column returned, eg usually "id"
911 // The sql statement is provided as a string.
915 $rs = $db->Execute("$sql");
916 if (!$rs) return false;
918 if ( $rs->RecordCount() > 0 ) {
919 if ($records = $rs->GetAssoc(true)) {
920 foreach ($records as $key => $record) {
921 $objects[$key] = (object) $record;
932 function get_records_sql_menu($sql) {
933 // Given an SQL select, this function returns an associative
934 // array of the first two columns. This is most useful in
935 // combination with the choose_from_menu function to create
940 $rs = $db->Execute("$sql");
941 if (!$rs) return false;
943 if ( $rs->RecordCount() > 0 ) {
945 $menu[$rs->fields[0]] = $rs->fields[1];
955 function get_field($table, $field, $selector, $value) {
958 $rs = $db->Execute("SELECT $field FROM $table WHERE $selector = '$value'");
959 if (!$rs) return false;
961 if ( $rs->RecordCount() == 1 ) {
962 return $rs->fields["$field"];
968 function set_field($table, $field, $newvalue, $selector, $value) {
971 return $db->Execute("UPDATE $table SET $field = '$newvalue' WHERE $selector = '$value'");
974 function set_config($name, $value) {
975 // No need for get_config because they are usually always available in $CFG
977 if (get_field("config", "value", "name", $name)) {
978 return set_field("config", "value", $value, "name", $name);
980 $config->name = $name;
981 $config->value = $value;
982 return insert_record("config", $config);
986 function delete_records($table, $selector, $value) {
987 // Delete one or more records from a table
990 return $db->Execute("DELETE FROM $table WHERE $selector = '$value'");
993 function insert_record($table, $dataobject) {
994 // Insert a record into a table and return the "id" field
995 // $dataobject is an object containing needed data
999 // Determine all the fields needed
1000 if (! $columns = $db->MetaColumns("$table")) {
1004 $data = (array)$dataobject;
1006 // Pull out data matching these fields
1007 foreach ($columns as $column) {
1008 if ($column->name <> "id" && isset($data[$column->name]) ) {
1009 $ddd[$column->name] = $data[$column->name];
1013 // Construct SQL queries
1014 if (! $numddd = count($ddd)) {
1022 foreach ($ddd as $key => $value) {
1024 $insert .= "$key = '$value'";
1025 $select .= "$key = '$value'";
1026 if ($count < $numddd) {
1032 if (! $rs = $db->Execute("INSERT INTO $table SET $insert")) {
1036 // Pull it out again to find the id. This is the most cross-platform method.
1037 if ($rs = $db->Execute("SELECT id FROM $table WHERE $select")) {
1038 return $rs->fields[0];
1045 function update_record($table, $dataobject) {
1046 // Update a record in a table
1047 // $dataobject is an object containing needed data
1051 if (! isset($dataobject->id) ) {
1055 // Determine all the fields in the table
1056 if (!$columns = $db->MetaColumns($table)) {
1059 $data = (array)$dataobject;
1061 // Pull out data matching these fields
1062 foreach ($columns as $column) {
1063 if ($column->name <> "id" && isset($data[$column->name]) ) {
1064 $ddd[$column->name] = $data[$column->name];
1068 // Construct SQL queries
1069 $numddd = count($ddd);
1073 foreach ($ddd as $key => $value) {
1075 $update .= "$key = '$value'";
1076 if ($count < $numddd) {
1081 if ($rs = $db->Execute("UPDATE $table SET $update WHERE id = '$dataobject->id'")) {
1089 function print_object($object) {
1090 // Mostly just for debugging
1092 $array = (array)$object;
1093 foreach ($array as $key => $item) {
1094 echo "$key -> $item <BR>";
1099 /// USER DATABASE ////////////////////////////////////////////////
1101 function get_user_info_from_db($field, $value) {
1105 if (!$field || !$value)
1108 if (! $result = $db->Execute("SELECT * FROM user WHERE $field = '$value' AND deleted <> '1'")) {
1109 error("Could not find any active users!");
1112 if ( $result->RecordCount() == 1 ) {
1113 $user = (object)$result->fields;
1115 $rs = $db->Execute("SELECT course FROM user_students WHERE user = '$user->id' ");
1117 $course = $rs->fields["course"];
1118 $user->student["$course"] = true;
1122 $rs = $db->Execute("SELECT course FROM user_teachers WHERE user = '$user->id' ");
1124 $course = $rs->fields["course"];
1125 $user->teacher["$course"] = true;
1129 $rs = $db->Execute("SELECT * FROM user_admins WHERE user = '$user->id' ");
1131 $user->admin = true;
1135 if ($course = get_site()) {
1136 // Everyone is always a member of the top course
1137 $user->student["$course->id"] = true;
1147 function update_user_in_db() {
1149 global $db, $USER, $REMOTE_ADDR;
1151 if (!isset($USER->id))
1155 if ($db->Execute("UPDATE user SET lastIP='$REMOTE_ADDR', lastaccess='$timenow' WHERE id = '$USER->id' ")) {
1162 function require_login($courseid=0) {
1163 // This function checks that the current user is logged in, and optionally
1164 // whether they are "logged in" or allowed to be in a particular course.
1165 // If not, then it redirects them to the site login or course enrolment.
1167 global $CFG, $SESSION, $USER, $FULLME, $HTTP_REFERER, $PHPSESSID;
1169 // First check that the user is logged in to the site.
1171 if (! (isset($USER->loggedin) and $USER->confirmed and ($USER->site == $CFG->wwwroot)) ) { // They're not
1172 $SESSION->wantsurl = $FULLME;
1173 $SESSION->fromurl = $HTTP_REFERER;
1174 save_session("SESSION");
1176 save_session("USER");
1177 if ($PHPSESSID) { // Cookies not enabled.
1178 redirect("$CFG->wwwroot/login/index.php?PHPSESSID=$PHPSESSID");
1180 redirect("$CFG->wwwroot/login/index.php");
1185 // Next, check if the user can be in a particular course
1187 if ($USER->student[$courseid] || $USER->teacher[$courseid] || $USER->admin) {
1188 if (isset($USER->realuser)) { // Make sure the REAL person can also access this course
1189 if (!isteacher($courseid, $USER->realuser)) {
1191 notice(get_string("studentnotallowed", "", "$USER->firstname $USER->lastname"), $CFG->wwwroot);
1194 } else { // just update their last login time
1195 update_user_in_db();
1197 if (!$USER->email) { // User logged in, but has not set up profile!
1198 // This can occur with external authentication
1199 redirect("$CFG->wwwroot/user/edit.php?id=$USER->id&course=$courseid");
1202 return; // user is a member of this course.
1204 if (! $course = get_record("course", "id", $courseid)) {
1205 error("That course doesn't exist");
1207 if ($USER->username == "guest") {
1208 switch ($course->guest) {
1209 case 0: // Guests not allowed
1211 notice(get_string("guestsnotallowed", "", $course->fullname));
1213 case 1: // Guests allowed
1214 update_user_in_db();
1216 case 2: // Guests allowed with key (drop through)
1221 // Currently not enrolled in the course, so see if they want to enrol
1222 $SESSION->wantsurl = $FULLME;
1223 save_session("SESSION");
1224 redirect("$CFG->wwwroot/course/enrol.php?id=$courseid");
1231 function update_login_count() {
1236 if (empty($SESSION->logincount)) {
1237 $SESSION->logincount = 1;
1239 $SESSION->logincount++;
1241 save_session("SESSION");
1243 if ($SESSION->logincount > $max_logins) {
1244 unset($SESSION->wantsurl);
1245 save_session("SESSION");
1246 error("Sorry, you have exceeded the allowed number of login attempts. Restart your browser.");
1250 function remove_admin($user) {
1253 return $db->Execute("DELETE FROM user_admins WHERE user = '$user'");
1256 function remove_teacher($user, $course=0) {
1260 /// First delete any crucial stuff that might still send mail
1261 if ($forums = get_records("forum", "course", $course)) {
1262 foreach ($forums as $forum) {
1263 $db->Execute("DELETE FROM forum_subscriptions WHERE forum = '$forum->id' AND user = '$user'");
1266 return $db->Execute("DELETE FROM user_teachers WHERE user = '$user' AND course = '$course'");
1268 delete_records("forum_subscriptions", "user", $user);
1269 return delete_records("user_teachers", "user", $user);
1274 function enrol_student($user, $course) {
1279 $rs = $db->Execute("INSERT INTO user_students (user, course, start, end, time)
1280 VALUES ($user, $course, 0, 0, $timenow)");
1288 function unenrol_student($user, $course=0) {
1292 /// First delete any crucial stuff that might still send mail
1293 if ($forums = get_records("forum", "course", $course)) {
1294 foreach ($forums as $forum) {
1295 $db->Execute("DELETE FROM forum_subscriptions WHERE forum = '$forum->id' AND user = '$user'");
1298 return $db->Execute("DELETE FROM user_students WHERE user = '$user' AND course = '$course'");
1301 delete_records("forum_subscriptions", "user", $user);
1302 return delete_records("user_students", "user", $user);
1307 function isadmin($userid=0) {
1311 return $USER->admin;
1314 return record_exists_sql("SELECT * FROM user_admins WHERE user='$userid'");
1317 function isteacher($courseid, $userid=0) {
1320 if (isadmin($userid)) { // admins can do anything the teacher can
1325 return $USER->teacher[$courseid];
1328 return record_exists_sql("SELECT * FROM user_teachers WHERE user='$userid' AND course='$courseid'");
1332 function isstudent($courseid, $userid=0) {
1336 return $USER->student[$courseid];
1339 $timenow = time(); // todo: add time check below
1341 return record_exists_sql("SELECT * FROM user_students WHERE user='$userid' AND course='$courseid'");
1344 function isguest($userid=0) {
1348 return ($USER->username == "guest");
1351 return record_exists_sql("SELECT * FROM user WHERE id='$userid' AND username = 'guest' ");
1354 function isediting($courseid, $user=NULL) {
1359 return ($user->editing and isteacher($courseid, $user->id));
1362 function reset_login_count() {
1365 $SESSION->logincount = 0;
1366 save_session("SESSION");
1370 function set_moodle_cookie($thing) {
1373 $seconds = 60*60*24*$days;
1375 setCookie ('MOODLEID', "", time() - 3600, "/");
1376 setCookie ('MOODLEID', rc4encrypt($thing), time()+$seconds, "/");
1380 function get_moodle_cookie() {
1382 return rc4decrypt($MOODLEID);
1386 function save_session($VAR) {
1387 // Copies temporary session variable to permanent sesson variable
1388 // eg $_SESSION["USER"] = $USER;
1390 $_SESSION[$VAR] = $$VAR;
1394 function create_user_record($username, $password) {
1395 // Creates a bare-bones user record
1396 global $REMOTE_ADDR, $CFG;
1398 if ($CFG->auth_update_userinfo and function_exists(auth_get_userinfo)) {
1399 if ($newinfo = auth_get_userinfo($username)) {
1400 foreach ($newinfo as $key=>$value){
1401 $newuser->$key = $value;
1406 $newuser->username = $username;
1407 $newuser->password = md5($password);
1408 $newuser->lang = $CFG->lang;
1409 $newuser->confirmed = 1;
1410 $newuser->lastIP = $REMOTE_ADDR;
1411 $newuser->timemodified = time();
1413 if (insert_record("user", $newuser)) {
1414 return get_user_info_from_db("username", $username);
1419 function authenticate_user_login($username, $password) {
1420 // Given a username and password, this function looks them
1421 // up using the currently selected authentication mechanism,
1422 // and if the authentication is successful, it returns a
1423 // valid $user object from the 'user' table.
1425 // Uses auth_ functions from the currently active auth module
1429 if (!isset($CFG->auth)) {
1430 $CFG->auth = "email"; // Default authentication module
1433 require_once("$CFG->dirroot/auth/$CFG->auth/lib.php");
1435 if (auth_user_login($username, $password)) { // Successful authentication
1437 if ($user = get_user_info_from_db("username", $username)) {
1438 if (md5($password) <> $user->password) {
1439 set_field("user", "password", md5($password), "username", $username);
1444 return create_user_record($username, $password);
1451 function get_site () {
1452 // Returns $course object of the top-level site.
1453 if ( $course = get_record("course", "category", 0)) {
1460 function get_admin () {
1461 // Returns $user object of the main admin user
1463 if ( $admins = get_records_sql("SELECT u.* FROM user u, user_admins a WHERE a.user = u.id ORDER BY u.id ASC")) {
1464 foreach ($admins as $admin) {
1465 return $admin; // ie the first one
1472 function get_teacher($courseid) {
1473 // Returns $user object of the main teacher for a course
1474 if ( $teachers = get_records_sql("SELECT u.* FROM user u, user_teachers t
1475 WHERE t.user = u.id AND t.course = '$courseid'
1476 ORDER BY t.authority ASC")) {
1477 foreach ($teachers as $teacher) {
1478 if ($teacher->authority) {
1479 return $teacher; // the highest authority teacher
1487 function get_course_students($courseid, $sort="u.lastaccess DESC") {
1488 return get_records_sql("SELECT u.* FROM user u, user_students s
1489 WHERE s.course = '$courseid' AND s.user = u.id AND u.deleted = '0'
1493 function get_course_teachers($courseid, $sort="t.authority ASC") {
1494 return get_records_sql("SELECT u.*,t.authority,t.role FROM user u, user_teachers t
1495 WHERE t.course = '$courseid' AND t.user = u.id AND u.deleted = '0'
1499 function get_course_users($courseid, $sort="u.lastaccess DESC") {
1500 // Using this method because the direct SQL just would not always work!
1502 $teachers = get_course_teachers($courseid, $sort);
1503 $students = get_course_students($courseid, $sort);
1505 if ($teachers and $students) {
1506 return array_merge($teachers, $students);
1507 } else if ($teachers) {
1513 // return get_records_sql("SELECT u.* FROM user u, user_students s, user_teachers t
1514 // WHERE (s.course = '$courseid' AND s.user = u.id) OR
1515 // (t.course = '$courseid' AND t.user = u.id)
1516 // ORDER BY $sort");
1521 /// MODULE FUNCTIONS /////////////////////////////////////////////////
1523 function get_coursemodule_from_instance($modulename, $instance, $courseid) {
1524 // Given an instance of a module, finds the coursemodule description
1526 return get_record_sql("SELECT cm.*, m.name
1527 FROM course_modules cm, modules md, $modulename m
1528 WHERE cm.course = '$courseid' AND
1529 cm.deleted = '0' AND
1530 cm.instance = m.id AND
1531 md.name = '$modulename' AND
1532 md.id = cm.module AND
1533 m.id = '$instance'");
1537 function get_all_instances_in_course($modulename, $courseid, $sort="cw.section") {
1538 // Returns an array of all the active instances of a particular
1539 // module in a given course. Returns false on any errors.
1541 return get_records_sql("SELECT m.*,cw.section,cm.id as coursemodule
1542 FROM course_modules cm, course_sections cw, modules md, $modulename m
1543 WHERE cm.course = '$courseid' AND
1544 cm.instance = m.id AND
1545 cm.deleted = '0' AND
1546 cm.section = cw.id AND
1547 md.name = '$modulename' AND
1556 /// CORRESPONDENCE ////////////////////////////////////////////////
1558 function email_to_user($user, $from, $subject, $messagetext, $messagehtml="", $attachment="", $attachname="") {
1559 // user - a user record as an object
1560 // from - a user record as an object
1561 // subject - plain text subject line of the email
1562 // messagetext - plain text version of the message
1563 // messagehtml - complete html version of the message (optional)
1564 // attachment - a file on the filesystem, relative to $CFG->dataroot
1565 // attachname - the name of the file (extension indicates MIME)
1567 global $CFG, $_SERVER;
1569 include_once("$CFG->libdir/phpmailer/class.phpmailer.php");
1575 $mail = new phpmailer;
1577 $mail->Version = "Moodle $CFG->version"; // mailer version
1578 $mail->PluginDir = "$CFG->libdir/phpmailer/"; // plugin directory (eg smtp plugin)
1580 if ($CFG->smtphosts) {
1581 $mail->IsSMTP(); // use SMTP directly
1582 $mail->Host = "$CFG->smtphosts"; // specify main and backup servers
1584 if ($CFG->smtpuser) { // Use SMTP authentication
1585 $mail->SMTPAuth = true;
1586 $mail->Username = $CFG->smtpuser;
1587 $mail->Password = $CFG->smtppass;
1590 $mail->IsMail(); // use PHP mail() = sendmail
1593 $mail->From = "$from->email";
1594 $mail->FromName = "$from->firstname $from->lastname";
1595 $mail->Subject = stripslashes($subject);
1597 $mail->AddAddress("$user->email", "$user->firstname $user->lastname");
1599 $mail->WordWrap = 70; // set word wrap
1602 $mail->IsHTML(true);
1603 $mail->Body = $messagehtml;
1604 $mail->AltBody = "\n$messagetext\n";
1606 $mail->IsHTML(false);
1607 $mail->Body = "\n$messagetext\n";
1610 if ($attachment && $attachname) {
1611 if (ereg( "\\.\\." ,$attachment )) { // Security check for ".." in dir path
1612 $adminuser = get_admin();
1613 $mail->AddAddress("$adminuser->email", "$adminuser->firstname $adminuser->lastname");
1614 $mail->AddStringAttachment("Error in attachment. User attempted to attach a filename with a unsafe name.", "error.txt", "8bit", "text/plain");
1616 include_once("$CFG->dirroot/files/mimetypes.php");
1617 $mimetype = mimeinfo("type", $attachname);
1618 $mail->AddAttachment("$CFG->dataroot/$attachment", "$attachname", "base64", "$mimetype");
1622 if ($mail->Send()) {
1625 echo "ERROR: $mail->ErrorInfo\n";
1627 add_to_log($site->id, "library", "mailer", $_SERVER["REQUEST_URI"], "ERROR: $mail->ErrorInfo");
1633 /// FILE HANDLING /////////////////////////////////////////////
1635 function make_upload_directory($directory) {
1636 // $directory = a string of directory names under $CFG->dataroot
1637 // eg stuff/assignment/1
1638 // Returns full directory if successful, false if not
1642 $currdir = $CFG->dataroot;
1643 if (!file_exists($currdir)) {
1644 if (! mkdir($currdir, 0750)) {
1645 notify("ERROR: You need to create the directory $currdir with web server write access");
1650 $dirarray = explode("/", $directory);
1652 foreach ($dirarray as $dir) {
1653 $currdir = "$currdir/$dir";
1654 if (! file_exists($currdir)) {
1655 if (! mkdir($currdir, 0750)) {
1656 notify("ERROR: Could not find or create a directory ($currdir)");
1665 function make_mod_upload_directory($courseid) {
1668 if (! $moddata = make_upload_directory("$courseid/$CFG->moddata")) {
1672 $strreadme = get_string("readme");
1674 if (file_exists("$CFG->dirroot/lang/$CFG->lang/docs/module_files.txt")) {
1675 copy("$CFG->dirroot/lang/$CFG->lang/docs/module_files.txt", "$moddata/$strreadme.txt");
1677 copy("$CFG->dirroot/lang/en/docs/module_files.txt", "$moddata/$strreadme.txt");
1683 function valid_uploaded_file($newfile) {
1684 // Returns current name of file on disk if true
1685 if (is_uploaded_file($newfile['tmp_name']) and $newfile['size'] > 0) {
1686 return $newfile['tmp_name'];
1692 function get_max_upload_file_size() {
1693 if (! $filesize = ini_get("upload_max_filesize")) {
1696 return get_real_size($filesize);
1699 function get_directory_list($rootdir, $excludefile="", $descend=true) {
1700 // Returns an array with all the filenames in
1701 // all subdirectories, relative to the given rootdir.
1702 // If excludefile is defined, then that file/directory is ignored
1706 $dir = opendir($rootdir);
1709 notify("Error: unable to read this directory! : $rootdir");
1713 while ($file = readdir($dir)) {
1714 if ($file != "." and $file != ".." and $file != "CVS" and $file != $excludefile) {
1715 $fullfile = $rootdir."/".$file;
1716 if ($descend and filetype($fullfile) == "dir") {
1717 $subdirs = get_directory_list($fullfile, $excludefile, $descend);
1718 foreach ($subdirs as $subdir) {
1719 $dirs[] = $file."/".$subdir;
1733 function get_real_size($size=0) {
1734 // Converts numbers like 10M into bytes
1738 $scan['MB'] = 1048576;
1739 $scan['M'] = 1048576;
1743 while (list($key) = each($scan)) {
1744 if ((strlen($size)>strlen($key))&&(substr($size, strlen($size) - strlen($key))==$key)) {
1745 $size = substr($size, 0, strlen($size) - strlen($key)) * $scan[$key];
1752 function display_size($size) {
1753 // Converts bytes into display form
1754 if ($size >= 1073741824) {
1755 $size = round($size / 1073741824 * 10) / 10 . "Gb";
1756 } else if ($size >= 1048576) {
1757 $size = round($size / 1048576 * 10) / 10 . "Mb";
1758 } else if ($size >= 1024) {
1759 $size = round($size / 1024 * 10) / 10 . "Kb";
1761 $size = $size . "b";
1766 function clean_filename($string) {
1767 $string = eregi_replace("\.\.", "", $string);
1768 $string = eregi_replace("[^([:alnum:]|\.)]", "_", $string);
1769 return eregi_replace("_+", "_", $string);
1773 /// STRING TRANSLATION ////////////////////////////////////////
1775 function print_string($identifier, $module="", $a=NULL) {
1776 echo get_string($identifier, $module, $a);
1779 function current_language() {
1780 // Returns the code for the current language
1783 if (isset($USER->lang)) { // User language can override site language
1790 function get_string($identifier, $module="", $a=NULL) {
1791 // Return the translated string specified by $identifier as
1792 // for $module. Uses the same format files as STphp.
1793 // $a is an object, string or number that can be used
1794 // within translation strings
1796 // eg "hello \$a->firstname \$a->lastname"
1801 $lang = current_language();
1803 if ($module == "") {
1807 $langpath = "$CFG->dirroot/lang";
1808 $langfile = "$langpath/$lang/$module.php";
1810 if (!file_exists($langfile)) { // try English instead
1811 $langfile = "$langpath/en/$module.php";
1812 if (!file_exists($langfile)) {
1813 return "ERROR: No lang file ($langpath/en/$module.php)!";
1817 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
1820 return $resultstring;
1823 if ($lang == "en") {
1824 return "[['$identifier']]";
1826 } else { // Try looking in the english file.
1827 $langfile = "$langpath/en/$module.php";
1828 if (!file_exists($langfile)) {
1829 return "ERROR: No lang file ($langpath/en/$module.php)!";
1831 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
1833 return $resultstring;
1835 return "[['$identifier']]";
1842 function get_string_from_file($identifier, $langfile, $destination) {
1843 // This function is only used from get_string().
1844 include ($langfile);
1846 if (!isset ($string[$identifier])) {
1850 return "$destination = sprintf(\"".$string[$identifier]."\");";
1854 function get_list_of_languages() {
1855 /// Returns a list of language codes and their full names
1858 if (!$langdirs = get_list_of_plugins("lang")) {
1862 foreach ($langdirs as $lang) {
1863 include("$CFG->dirroot/lang/$lang/moodle.php");
1864 $languages[$lang] = $string["thislanguage"]." ($lang)";
1871 /// ENCRYPTION ////////////////////////////////////////////////
1873 function rc4encrypt($data) {
1874 $password = "nfgjeingjk";
1875 return endecrypt($password, $data, "");
1878 function rc4decrypt($data) {
1879 $password = "nfgjeingjk";
1880 return endecrypt($password, $data, "de");
1883 function endecrypt ($pwd, $data, $case) {
1884 // Based on a class by Mukul Sabharwal [mukulsabharwal@yahoo.com]
1886 if ($case == 'de') {
1887 $data = urldecode($data);
1895 $pwd_length = strlen($pwd);
1897 for ($i = 0; $i <= 255; $i++) {
1898 $key[$i] = ord(substr($pwd, ($i % $pwd_length), 1));
1904 for ($i = 0; $i <= 255; $i++) {
1905 $x = ($x + $box[$i] + $key[$i]) % 256;
1906 $temp_swap = $box[$i];
1907 $box[$i] = $box[$x];
1908 $box[$x] = $temp_swap;
1920 for ($i = 0; $i < strlen($data); $i++) {
1921 $a = ($a + 1) % 256;
1922 $j = ($j + $box[$a]) % 256;
1924 $box[$a] = $box[$j];
1926 $k = $box[(($box[$a] + $box[$j]) % 256)];
1927 $cipherby = ord(substr($data, $i, 1)) ^ $k;
1928 $cipher .= chr($cipherby);
1931 if ($case == 'de') {
1932 $cipher = urldecode(urlencode($cipher));
1934 $cipher = urlencode($cipher);
1941 /// MISCELLANEOUS ////////////////////////////////////////////////////////////////////
1943 function count_words($string) {
1944 $string = strip_tags($string);
1945 return count(preg_split("/\w\b/", $string)) - 1;
1948 function getweek ($startdate, $thedate) {
1949 // Given dates in seconds, how many weeks is the date from startdate
1950 // The first week is 1, the second 2 etc ...
1952 if ($thedate < $startdate) { // error
1956 return floor(($thedate - $startdate) / 604800.0) + 1;
1959 function add_to_log($course, $module, $action, $url="", $info="") {
1960 // Add an entry to the log table. These are "action" focussed rather
1961 // than web server hits, and provide a way to easily reconstruct what
1962 // any particular student has been doing.
1964 // course = the course id
1965 // module = forum, journal, resource, course, user etc
1966 // action = view, edit, post (often but not always the same as the file.php)
1967 // url = the file and parameters used to see the results of the action
1968 // info = additional description information
1971 global $db, $USER, $REMOTE_ADDR;
1973 if (isset($USER->realuser)) { // Don't log
1978 $info = addslashes($info);
1980 $result = $db->Execute("INSERT INTO log
1981 SET time = '$timenow',
1984 ip = '$REMOTE_ADDR',
1990 echo "<P>Error: Could not insert a new entry to the Moodle log</P>"; // Don't throw an error
1994 function generate_password($maxlen=10) {
1995 // returns a randomly generated password of length $maxlen. inspired by
1996 // http://www.phpbuilder.com/columns/jesus19990502.php3
2000 $fillers = "1234567890!$-+";
2001 $wordlist = file($CFG->wordlist);
2003 srand((double) microtime() * 1000000);
2004 $word1 = trim($wordlist[rand(0, count($wordlist) - 1)]);
2005 $word2 = trim($wordlist[rand(0, count($wordlist) - 1)]);
2006 $filler1 = $fillers[rand(0, strlen($fillers) - 1)];
2008 return substr($word1 . $filler1 . $word2, 0, $maxlen);
2011 function moodle_needs_upgrading() {
2012 // Checks version numbers of Main code and all modules to see
2013 // if there are any mismatches ... returns true or false
2016 include_once("$CFG->dirroot/version.php"); # defines $version and upgrades
2017 if ($CFG->version) {
2018 if ($version > $CFG->version) {
2021 if ($mods = get_list_of_plugins("mod")) {
2022 foreach ($mods as $mod) {
2023 $fullmod = "$CFG->dirroot/mod/$mod";
2025 include_once("$fullmod/version.php"); # defines $module with version etc
2026 if ($currmodule = get_record("modules", "name", $mod)) {
2027 if ($module->version > $currmodule->version) {
2040 function get_list_of_plugins($plugin="mod") {
2041 // Lists plugin directories within some directory
2045 $basedir = opendir("$CFG->dirroot/$plugin");
2046 while ($dir = readdir($basedir)) {
2047 if ($dir == "." || $dir == ".." || $dir == "CVS") {
2050 if (filetype("$CFG->dirroot/$plugin/$dir") != "dir") {
2062 function check_php_version($version="4.1.0") {
2063 // Returns true is the current version of PHP is greater that the specified one
2064 $minversion = intval(str_replace(".", "", $version));
2065 $curversion = intval(str_replace(".", "", phpversion()));
2066 return ($curversion >= $minversion);
2069 function check_browser_version($brand="MSIE", $version=5.5) {
2070 // Checks to see if is a browser matches the specified
2071 // brand and is equal or better version.
2072 global $HTTP_USER_AGENT;
2074 if (!$HTTP_USER_AGENT) {
2077 $string = explode(";", $HTTP_USER_AGENT);
2078 if (!isset($string[1])) {
2081 $string = explode(" ", trim($string[1]));
2082 if (!isset($string[0]) and !isset($string[1])) {
2085 if ($string[0] == $brand and (float)$string[1] >= $version ) {
2091 function can_use_richtext_editor() {
2093 if ($USER->htmleditor and $CFG->htmleditor) {
2094 return check_browser_version("MSIE", 5.5);
2100 function check_gd_version() {
2103 $phpinfo = ob_get_contents();
2106 $phpinfo = explode("\n",$phpinfo);
2110 foreach ($phpinfo as $text) {
2111 $parts = explode('</b>',$text);
2112 foreach ($parts as $key => $val) {
2113 $parts[$key] = strip_tags($val);
2115 if ($parts[0]=="GD Version") {
2116 $gdversion = intval($parts[1]);
2120 return $gdversion; // 1, 2 or 0