New assignment module finally complete!
[moodle.git] / lib / moodlelib.php
CommitLineData
f9903ed0 1<?PHP // $Id$
2
3//
4// moodlelib.php
5//
6// Large collection of useful functions used by many parts of Moodle.
7//
8// Martin Dougiamas, 2000
9//
10
11
12/// STANDARD WEB PAGE PARTS ///////////////////////////////////////////////////
13
c7e3ac2a 14function print_header ($title="", $heading="", $navigation="", $focus="", $meta="", $cache=true, $button="") {
f9903ed0 15// $title - appears top of window
16// $heading - appears top of page
17// $navigation - premade navigation string
18// $focus - indicates form element eg inputform.password
19// $meta - meta tags in the header
c7e3ac2a 20// $cache - should this page be cacheable?
21// $button - code for a button in the top-right
f9903ed0 22 global $USER, $CFG, $THEME;
23
24 if (file_exists("$CFG->dirroot/theme/$CFG->theme/styles.css")) {
25 $styles = "$CFG->wwwroot/theme/$CFG->theme/styles.css";
26 } else {
27 $styles = "$CFG->wwwroot/theme/standard/styles.css";
28 }
29
30 if (!$cache) { // Do everything we can to prevent clients and proxies caching
31 @header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
32 @header("Pragma: no-cache");
33 $meta .= "\n<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">";
34 $meta .= "\n<META HTTP-EQUIV=\"Expires\" CONTENT=\"0\">";
35 }
36
37 include ("$CFG->dirroot/theme/$CFG->theme/header.html");
38}
39
40function print_footer ($course=NULL) {
41// Can provide a course object to make the footer contain a link to
42// to the course home page, otherwise the link will go to the site home
43 global $USER, $CFG, $THEME;
44
45 if ($course) {
46 $homelink = "<A TARGET=_top HREF=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</A>";
47 } else {
48 $homelink = "<A TARGET=_top HREF=\"$CFG->wwwroot\">Home</A>";
49 }
50 include ("$CFG->dirroot/theme/$CFG->theme/footer.html");
51}
52
53function print_navigation ($navigation) {
54 global $CFG;
55
56 if ($navigation) {
a83fded1 57 if (! $site = get_site()) {
bcc83c41 58 $site->shortname = get_string("home");;
59 }
a2eaeb91 60 echo "<A TARGET=_top HREF=\"$CFG->wwwroot/\">$site->shortname</A> -> $navigation";
f9903ed0 61 }
62}
63
2a46a71b 64function print_heading($text, $align="CENTER", $size=3) {
65 echo "<P ALIGN=\"$align\"><FONT SIZE=\"$size\"><B>$text</B></FONT></P>";
f9903ed0 66}
67
dbcb136a 68function print_continue($link) {
69 global $HTTP_REFERER;
70
71 if (!$link) {
72 $link = $HTTP_REFERER;
73 }
74
75 print_heading("<A HREF=\"$link\">".get_string("continue")."</A>");
76}
77
78
4216daa6 79function print_simple_box($message, $align="", $width="", $color="#FFFFFF", $padding=5, $border=1) {
80 print_simple_box_start($align, $width, $color, $padding, $border);
f9903ed0 81 echo "<P>$message</P>";
82 print_simple_box_end();
83}
84
4216daa6 85function print_simple_box_start($align="", $width="", $color="#FFFFFF", $padding=5, $border=1) {
f9903ed0 86 global $THEME;
87
88 if ($align) {
89 $tablealign = "ALIGN=\"$align\"";
90 }
91 if ($width) {
92 $tablewidth = "WIDTH=\"$width\"";
93 $innertablewidth = "WIDTH=\"100%\"";
94 }
4216daa6 95 echo "<TABLE $tablealign $tablewidth BORDER=0 CELLPADDING=\"$border\" CELLSPACING=0>";
f9903ed0 96 echo "<TR><TD BGCOLOR=\"$THEME->borders\">\n";
97 echo "<TABLE $innertablewidth BORDER=0 CELLPADDING=\"$padding\" CELLSPACING=0><TR><TD BGCOLOR=\"$color\">";
98}
99
100function print_simple_box_end() {
101 echo "</TD></TR></TABLE>";
102 echo "</TD></TR></TABLE>";
103}
104
105function print_single_button($link, $options, $label="OK") {
106 echo "<FORM ACTION=\"$link\" METHOD=GET>";
dbcb136a 107 if ($options) {
108 foreach ($options as $name => $value) {
109 echo "<INPUT TYPE=hidden NAME=\"$name\" VALUE=\"$value\">";
110 }
f9903ed0 111 }
112 echo "<INPUT TYPE=submit VALUE=\"$label\"></FORM>";
113}
114
136dabd8 115function print_user_picture($userid, $courseid, $picture, $large=false, $returnstring=false) {
f9903ed0 116 global $CFG;
117
136dabd8 118 $output = "<A HREF=\"$CFG->wwwroot/user/view.php?id=$userid&course=$courseid\">";
f9903ed0 119 if ($large) {
120 $file = "f1.jpg";
121 $size = 100;
122 } else {
123 $file = "f2.jpg";
124 $size = 35;
125 }
126 if ($picture) {
136dabd8 127 $output .= "<IMG SRC=\"$CFG->wwwroot/user/pix.php/$userid/$file\" BORDER=0 WIDTH=$size HEIGHT=$size ALT=\"\">";
f9903ed0 128 } else {
136dabd8 129 $output .= "<IMG SRC=\"$CFG->wwwroot/user/default/$file\" BORDER=0 WIDTH=$size HEIGHT=$size ALT=\"\">";
130 }
131 $output .= "</A>";
132
133 if ($returnstring) {
134 return $output;
135 } else {
136 echo $output;
f9903ed0 137 }
f9903ed0 138}
139
140function print_table($table) {
141// Prints a nicely formatted table.
142// $table is an object with three properties.
143// $table->head is an array of heading names.
144// $table->align is an array of column alignments
145// $table->data[] is an array of arrays containing the data.
146
37b15514 147 if ($table->align) {
f9903ed0 148 foreach ($table->align as $key => $aa) {
149 if ($aa) {
150 $align[$key] = "ALIGN=\"$aa\"";
151 } else {
152 $align[$key] = "";
153 }
154 }
155 }
156
37b15514 157 print_simple_box_start("CENTER", "80%", "#FFFFFF", 0);
158 echo "<TABLE WIDTH=100% BORDER=0 valign=top align=center cellpadding=10 cellspacing=1>\n";
f9903ed0 159
160 if ($table->head) {
161 echo "<TR>";
162 foreach ($table->head as $heading) {
163 echo "<TH>$heading</TH>";
164 }
165 echo "</TR>\n";
166 }
167
168 foreach ($table->data as $row) {
169 echo "<TR VALIGN=TOP>";
170 foreach ($row as $key => $item) {
171 echo "<TD ".$align[$key].">$item</TD>";
172 }
173 echo "</TR>\n";
174 }
175 echo "</TABLE>\n";
176 print_simple_box_end();
177
178 return true;
179}
180
21ddaf60 181function print_editing_switch($courseid) {
182 global $CFG, $USER;
183
c7e3ac2a 184 if (isteacher($courseid)) {
21ddaf60 185 if ($USER->editing) {
186 echo "<A HREF=\"$CFG->wwwroot/course/view.php?id=$courseid&edit=off\">Turn editing off</A>";
187 } else {
188 echo "<A HREF=\"$CFG->wwwroot/course/view.php?id=$courseid&edit=on\">Turn editing on</A>";
189 }
190 }
191}
192
39917a09 193function print_date_selector($day, $month, $year, $currenttime=0) {
194// Currenttime is a default timestamp in GMT
195// Prints form items with the names $day, $month and $year
196
197 if (!$currenttime) {
198 $currenttime = time();
199 }
200 $currentdate = usergetdate($currenttime);
201
202 for ($i=1; $i<=31; $i++) {
203 $days[$i] = "$i";
204 }
205 for ($i=1; $i<=12; $i++) {
206 $months[$i] = date("F", mktime(0,0,0,$i,1,2000));
207 }
208 for ($i=2000; $i<=2010; $i++) {
209 $years[$i] = $i;
210 }
211 choose_from_menu($days, $day, $currentdate[mday], "");
212 choose_from_menu($months, $month, $currentdate[mon], "");
213 choose_from_menu($years, $year, $currentdate[year], "");
214}
215
216function print_time_selector($hour, $minute, $currenttime=0) {
217// Currenttime is a default timestamp in GMT
218// Prints form items with the names $hour and $minute
219
220 if (!$currenttime) {
221 $currenttime = time();
222 }
223 $currentdate = usergetdate($currenttime);
224 for ($i=0; $i<=23; $i++) {
225 $hours[$i] = sprintf("%02d",$i);
226 }
227 for ($i=0; $i<=59; $i++) {
228 $minutes[$i] = sprintf("%02d",$i);
229 }
230 choose_from_menu($hours, $hour, $currentdate[hours], "");
231 choose_from_menu($minutes, $minute, $currentdate[minutes], "");
232}
233
234function make_timestamp($year, $month=1, $day=1, $hour=0, $minute=0, $second=0) {
235// Given date parts in user time, produce a GMT timestamp
236
237 return mktime((int)$hour,(int)$minute,(int)$second,(int)$month,(int)$day,(int)$year);
238}
239
c7e3ac2a 240function update_course_icon($courseid) {
241 global $CFG, $USER;
242
243 if (isteacher($courseid)) {
244 if ($USER->editing) {
245 return "<A TITLE=\"Turn editing OFF\" HREF=\"$CFG->wwwroot/course/view.php?id=$courseid&edit=off\"
246 TARGET=_top><IMG SRC=\"$CFG->wwwroot/pix/i/edit.gif\" ALIGN=right BORDER=0></A>";
247 } else {
248 return "<A TITLE=\"Turn editing ON\" HREF=\"$CFG->wwwroot/course/view.php?id=$courseid&edit=on\"
249 TARGET=_top><IMG SRC=\"$CFG->wwwroot/pix/i/edit.gif\" ALIGN=right BORDER=0></A>";
250 }
251 }
252}
253
bcc83c41 254function update_module_icon($moduleid, $courseid) {
c7e3ac2a 255 global $CFG;
256
257 if (isteacher($courseid)) {
e07635f4 258 return "<A TITLE=\"Edit this activity\" HREF=\"$CFG->wwwroot/course/mod.php?update=$moduleid&return=true\" TARGET=_top><IMG
c7e3ac2a 259 SRC=\"$CFG->wwwroot/pix/i/edit.gif\" ALIGN=right BORDER=0></A>";
260 }
261}
262
f9903ed0 263
5fa51a39 264function userdate($date, $format="", $timezone=99) {
d552ead0 265// Returns a formatted string that represents a date in user time
7a302afc 266// WARNING: note that the format is for strftime(), not date().
267
873960de 268 global $USER;
269
5fa51a39 270 if ($format == "") {
7a302afc 271 $format = "%A, %e %B %Y, %I:%M %p";
5fa51a39 272 }
273 if ($timezone == 99) {
274 $timezone = (float)$USER->timezone;
275 }
276 if (abs($timezone) > 12) {
6d9d8344 277 return strftime("$format", $date);
873960de 278 }
7a302afc 279 return gmstrftime($format, $date + (int)($timezone * 3600));
873960de 280}
281
5fa51a39 282function usergetdate($date, $timezone=99) {
d552ead0 283// Returns an array that represents a date in user time
873960de 284 global $USER;
285
5fa51a39 286 if ($timezone == 99) {
287 $timezone = (float)$USER->timezone;
288 }
289 if (abs($timezone) > 12) {
873960de 290 return getdate($date);
291 }
d2d6171f 292 //There is no gmgetdate so I have to fake it...
293 $date = $date + (int)($timezone * 3600);
294 $getdate["seconds"] = gmstrftime("%S", $date);
295 $getdate["minutes"] = gmstrftime("%M", $date);
296 $getdate["hours"] = gmstrftime("%H", $date);
297 $getdate["mday"] = gmstrftime("%d", $date);
298 $getdate["wday"] = gmstrftime("%u", $date);
299 $getdate["mon"] = gmstrftime("%m", $date);
300 $getdate["year"] = gmstrftime("%Y", $date);
301 $getdate["yday"] = gmstrftime("%j", $date);
302 $getdate["weekday"] = gmstrftime("%A", $date);
303 $getdate["month"] = gmstrftime("%B", $date);
304 return $getdate;
d552ead0 305}
306
307function usertime($date, $timezone=99) {
308// Given a GMT timestamp (seconds since epoch), offsets it by
309// the timezone. eg 3pm in India is 3pm GMT - 7 * 3600 seconds
310 global $USER;
311
312 if ($timezone == 99) {
313 $timezone = (float)$USER->timezone;
314 }
315 if (abs($timezone) > 12) {
316 return $date;
317 }
318 return $date - (int)($timezone * 3600);
319}
320
edf7fe8c 321function usergetmidnight($date, $timezone=99) {
322// Given a time, return the GMT timestamp of the most recent midnight
323// for the current user.
324
325 global $USER;
326
edf7fe8c 327 $userdate = usergetdate($date, $timezone);
328 $timemidnight = gmmktime (0, 0, 0, $userdate["mon"], $userdate["mday"], $userdate["year"]);
329 return usertime($timemidnight, $timezone); // Time of midnight of this user's day, in GMT
330
331}
332
d552ead0 333function usertimezone($timezone=99) {
334// returns a string that prints the user's timezone
335 global $USER;
336
337 if ($timezone == 99) {
338 $timezone = (float)$USER->timezone;
339 }
340 if (abs($timezone) > 12) {
341 return "server time";
342 }
343 if (abs($timezone) < 0.5) {
344 return "GMT";
345 }
346 if ($timezone > 0) {
347 return "GMT+$timezone";
348 } else {
349 return "GMT$timezone";
350 }
f9903ed0 351}
352
353
354function error ($message, $link="") {
355 global $CFG, $SESSION;
356
357 print_header("Error");
358 echo "<BR>";
359 print_simple_box($message, "center", "", "#FFBBBB");
360
361 if (!$link) {
362 if ( !empty($SESSION->fromurl) ) {
363 $link = "$SESSION->fromurl";
364 unset($SESSION->fromurl);
365 } else {
366 $link = "$CFG->wwwroot";
367 }
368 }
dbcb136a 369 print_continue($link);
f9903ed0 370 print_footer();
371 die;
372}
373
65cf9fc3 374function helpbutton ($page, $title="", $module="moodle", $image=true, $text="") {
375 // $page = the keyword that defines a help page
376 // $title = the title of links, rollover tips, alt tags etc
377 // $module = which module is the page defined in
378 // $image = use a help image for the link? (otherwise uses text)
379 // $text = if defined then this text is used in the page, and
380 // the $page variable is ignored.
34c8915d 381 global $CFG;
65cf9fc3 382 if ($module == "") {
383 $module = "moodle";
384 }
385 if ($image) {
386 $linkobject = "<IMG BORDER=0 ALT=\"$title\" SRC=\"$CFG->wwwroot/pix/help.gif\">";
387 } else {
388 $linkobject = $title;
389 }
390 if ($text) {
391 $url = "/help.php?module=$module&text=$text";
392 } else {
393 $url = "/help.php?module=$module&file=help.$page.php";
394 }
395 link_to_popup_window ($url, "popup", $linkobject, 400, 500, $title);
34c8915d 396}
397
f9903ed0 398function notice ($message, $link="") {
399 global $THEME, $HTTP_REFERER;
400
401 if (!$link) {
402 $link = $HTTP_REFERER;
403 }
404
405 echo "<BR>";
406 print_simple_box($message, "center", "", "$THEME->cellheading");
407 print_heading("<A HREF=\"$link\">Continue</A>");
408 print_footer();
409 die;
410}
411
412function notice_yesno ($message, $linkyes, $linkno) {
413 global $THEME;
414
415 print_simple_box_start("center", "", "$THEME->cellheading");
416 echo "<P ALIGN=CENTER><FONT SIZE=3>$message</FONT></P>";
417 echo "<P ALIGN=CENTER><FONT SIZE=3><B>";
418 echo "<A HREF=\"$linkyes\">Yes</A>";
419 echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
420 echo "<A HREF=\"$linkno\">No</A>";
421 echo "</B></FONT></P>";
422 print_simple_box_end();
423}
424
425function redirect($url, $message="", $delay=0) {
426// Uses META tags to redirect the user, after printing a notice
427 global $THEME;
428
429 echo "<META HTTP-EQUIV='Refresh' CONTENT='$delay; URL=$url'>";
430
431 if (!empty($message)) {
432 print_header();
433 echo "<CENTER>";
434 echo "<P>$message</P>";
435 echo "<P>( <A HREF=\"$url\">Continue</A> )</P>";
436 echo "</CENTER>";
437 }
438 die;
439}
440
441function notify ($message) {
442 echo "<P align=center><B><FONT COLOR=#FF0000>$message</FONT></B></P>\n";
443}
444
445
446
447/// PARAMETER HANDLING ////////////////////////////////////////////////////
448
449function require_variable($var) {
f9903ed0 450 if (! isset($var)) {
451 error("A required parameter was missing");
452 }
453}
454
455function optional_variable(&$var, $default=0) {
456 if (! isset($var)) {
457 $var = $default;
458 }
459}
460
461
462
463
464/// DATABASE HANDLING ////////////////////////////////////////////////
465
466function execute_sql($command) {
467// Completely general
468
469 global $db;
470
471 $result = $db->Execute("$command");
472
473 if ($result) {
501cdbd8 474 echo "<P><FONT COLOR=green>SUCCESS</FONT></P>";
f9903ed0 475 return true;
476 } else {
501cdbd8 477 echo "<P><FONT COLOR=red>ERROR</FONT></P>";
f9903ed0 478 return false;
479 }
480}
481
482function modify_database($sqlfile) {
483// Assumes that the input text file consists of a number
484// of SQL statements ENDING WITH SEMICOLONS. The semicolons
485// MUST be the last character in a line.
486// Lines that are blank or that start with "#" are ignored.
487// Only tested with mysql dump files (mysqldump -p -d moodle)
488
489
490 if (file_exists($sqlfile)) {
491 $success = true;
492 $lines = file($sqlfile);
493 $command = "";
494
495 while ( list($i, $line) = each($lines) ) {
496 $line = chop($line);
497 $length = strlen($line);
498
499 if ($length && substr($line, 0, 1) <> "#") {
500 if (substr($line, $length-1, 1) == ";") {
501 $line = substr($line, 0, $length-1); // strip ;
502 $command .= $line;
503 if (! execute_sql($command)) {
504 $success = false;
505 }
506 $command = "";
507 } else {
508 $command .= $line;
509 }
510 }
511 }
512
513 } else {
514 $success = false;
515 echo "<P>Tried to modify database, but \"$sqlfile\" doesn't exist!</P>";
516 }
517
518 return $success;
519}
520
521
522function record_exists($table, $field, $value) {
523 global $db;
524
525 $rs = $db->Execute("SELECT * FROM $table WHERE $field = '$value' LIMIT 1");
526 if (!$rs) return false;
527
528 if ( $rs->RecordCount() ) {
529 return true;
530 } else {
531 return false;
532 }
533}
534
535function record_exists_sql($sql) {
536 global $db;
537
538 $rs = $db->Execute($sql);
539 if (!$rs) return false;
540
541 if ( $rs->RecordCount() ) {
542 return true;
543 } else {
544 return false;
545 }
546}
547
548
549function count_records($table, $selector, $value) {
550// Get all the records and count them
551 global $db;
552
553 $rs = $db->Execute("SELECT COUNT(*) FROM $table WHERE $selector = '$value'");
554 if (!$rs) return 0;
555
556 return $rs->fields[0];
557}
558
559function count_records_sql($sql) {
560// Get all the records and count them
561 global $db;
562
563 $rs = $db->Execute("$sql");
564 if (!$rs) return 0;
565
566 return $rs->fields[0];
567}
568
569function get_record($table, $selector, $value) {
570// Get a single record as an object
571 global $db;
572
573 $rs = $db->Execute("SELECT * FROM $table WHERE $selector = '$value'");
574 if (!$rs) return false;
575
576 if ( $rs->RecordCount() == 1 ) {
577 return (object)$rs->fields;
578 } else {
579 return false;
580 }
581}
582
583function get_record_sql($sql) {
584// Get a single record as an object
585// The sql statement is provided as a string.
586
587 global $db;
588
589 $rs = $db->Execute("$sql");
590 if (!$rs) return false;
591
592 if ( $rs->RecordCount() == 1 ) {
593 return (object)$rs->fields;
594 } else {
595 return false;
596 }
597}
598
599function get_records($table, $selector, $value, $sort="") {
600// Get a number of records as an array of objects
601// Can optionally be sorted eg "time ASC" or "time DESC"
602// The "key" is the first column returned, eg usually "id"
603 global $db;
604
605 if ($sort) {
606 $sortorder = "ORDER BY $sort";
607 }
608 $sql = "SELECT * FROM $table WHERE $selector = '$value' $sortorder";
609
610 return get_records_sql($sql);
611}
612
613function get_records_sql($sql) {
614// Get a number of records as an array of objects
615// The "key" is the first column returned, eg usually "id"
616// The sql statement is provided as a string.
617
618 global $db;
619
620 $rs = $db->Execute("$sql");
621 if (!$rs) return false;
622
623 if ( $rs->RecordCount() > 0 ) {
5c0bef5d 624 if ($records = $rs->GetAssoc(true)) {
625 foreach ($records as $key => $record) {
626 $objects[$key] = (object) $record;
627 }
628 return $objects;
629 } else {
630 return false;
f9903ed0 631 }
f9903ed0 632 } else {
633 return false;
634 }
635}
636
637function get_records_sql_menu($sql) {
638// Given an SQL select, this function returns an associative
639// array of the first two columns. This is most useful in
640// combination with the choose_from_menu function to create
641// a form menu.
642
643 global $db;
644
645 $rs = $db->Execute("$sql");
646 if (!$rs) return false;
647
648 if ( $rs->RecordCount() > 0 ) {
649 while (!$rs->EOF) {
650 $menu[$rs->fields[0]] = $rs->fields[1];
651 $rs->MoveNext();
652 }
653 return $menu;
654
655 } else {
656 return false;
657 }
658}
659
660function get_field($table, $field, $selector, $value) {
661 global $db;
662
663 $rs = $db->Execute("SELECT $field FROM $table WHERE $selector = '$value'");
664 if (!$rs) return false;
665
666 if ( $rs->RecordCount() == 1 ) {
667 return $rs->fields["$field"];
668 } else {
669 return false;
670 }
671}
672
673function set_field($table, $field, $newvalue, $selector, $value) {
674 global $db;
675
676 return $db->Execute("UPDATE $table SET $field = '$newvalue' WHERE $selector = '$value'");
677}
678
679
680function delete_records($table, $selector, $value) {
681// Delete one or more records from a table
682 global $db;
683
684 return $db->Execute("DELETE FROM $table WHERE $selector = '$value'");
685}
686
687function insert_record($table, $dataobject) {
688// Insert a record into a table and return the "id" field
689// $dataobject is an object containing needed data
690
691 global $db;
692
693 // Determine all the fields needed
694 if (! $columns = $db->MetaColumns("$table")) {
695 return false;
696 }
697
698 $data = (array)$dataobject;
699
700 // Pull out data matching these fields
701 foreach ($columns as $column) {
702 if ($column->name <> "id" && $data[$column->name] ) {
703 $ddd[$column->name] = $data[$column->name];
704 }
705 }
706
707 // Construct SQL queries
708 if (! $numddd = count($ddd)) {
709 return 0;
710 }
711
712 $count = 0;
713 $insert = "";
714 $select = "";
715
716 foreach ($ddd as $key => $value) {
717 $count++;
718 $insert .= "$key = '$value'";
719 $select .= "$key = '$value'";
720 if ($count < $numddd) {
721 $insert .= ", ";
722 $select .= " AND ";
723 }
724 }
725
726 if (! $rs = $db->Execute("INSERT INTO $table SET $insert")) {
727 return false;
728 }
729
730 // Pull it out again to find the id. This is the most cross-platform method.
731 if ($rs = $db->Execute("SELECT id FROM $table WHERE $select")) {
732 return $rs->fields[0];
733 } else {
734 return false;
735 }
736}
737
738
739function update_record($table, $dataobject) {
740// Update a record in a table
741// $dataobject is an object containing needed data
742
743 global $db;
744
5c0bef5d 745 if (! isset($dataobject->id) ) {
f9903ed0 746 return false;
747 }
748
749 // Determine all the fields in the table
1afd014e 750 if (!$columns = $db->MetaColumns($table)) {
751 return false;
752 }
f9903ed0 753 $data = (array)$dataobject;
754
755 // Pull out data matching these fields
756 foreach ($columns as $column) {
5c0bef5d 757 if ($column->name <> "id" && isset($data[$column->name]) ) {
f9903ed0 758 $ddd[$column->name] = $data[$column->name];
759 }
760 }
761
762 // Construct SQL queries
763 $numddd = count($ddd);
764 $count = 0;
765 $update = "";
766
767 foreach ($ddd as $key => $value) {
768 $count++;
769 $update .= "$key = '$value'";
770 if ($count < $numddd) {
771 $update .= ", ";
772 }
773 }
774
775 if ($rs = $db->Execute("UPDATE $table SET $update WHERE id = '$dataobject->id'")) {
776 return true;
777 } else {
778 return false;
779 }
780}
781
782
f93f848a 783function print_object($object) {
784// Mostly just for debugging
785
786 $array = (array)$object;
787 foreach ($array as $key => $item) {
788 echo "$key -> $item <BR>";
789 }
790}
791
792
f9903ed0 793
794/// USER DATABASE ////////////////////////////////////////////////
795
796function get_user_info_from_db($field, $value) {
797
798 global $db;
799
800 if (!$field || !$value)
801 return false;
802
803 $result = $db->Execute("SELECT * FROM user WHERE $field = '$value'");
804
805 if ( $result->RecordCount() == 1 ) {
806 $user = (object)$result->fields;
807
808 $rs = $db->Execute("SELECT course FROM user_students WHERE user = '$user->id' ");
809 while (!$rs->EOF) {
810 $course = $rs->fields["course"];
811 $user->student["$course"] = true;
812 $rs->MoveNext();
813 }
814
815 $rs = $db->Execute("SELECT course FROM user_teachers WHERE user = '$user->id' ");
816 while (!$rs->EOF) {
817 $course = $rs->fields["course"];
818 $user->teacher["$course"] = true;
819 $rs->MoveNext();
820 }
821
822 $rs = $db->Execute("SELECT * FROM user_admins WHERE user = '$user->id' ");
823 while (!$rs->EOF) {
824 $user->admin = true;
825 $rs->MoveNext();
826 }
827
a83fded1 828 if ($course = get_site()) {
f9903ed0 829 // Everyone is always a member of the top course
830 $user->student["$course->id"] = true;
831 }
832
833 return $user;
834
835 } else {
836 return false;
837 }
838}
839
840function update_user_in_db() {
841
842 global $db, $USER, $REMOTE_ADDR;
843
844 if (!isset($USER->id))
845 return false;
846
847 $timenow = time();
848 if ($db->Execute("UPDATE LOW_PRIORITY user SET lastIP='$REMOTE_ADDR', lastaccess='$timenow'
849 WHERE id = '$USER->id' ")) {
850 return true;
851 } else {
852 return false;
853 }
854}
855
da5c172a 856function require_login($courseid=0) {
857// This function checks that the current user is logged in, and optionally
858// whether they are "logged in" or allowed to be in a particular course.
859// If not, then it redirects them to the site login or course enrolment.
f9903ed0 860
861 global $CFG, $SESSION, $USER, $FULLME, $HTTP_REFERER, $PHPSESSID;
862
da5c172a 863 // First check that the user is logged in to the site.
f9903ed0 864 if (! (isset( $USER->loggedin ) && $USER->confirmed) ) {
865 $SESSION->wantsurl = $FULLME;
866 $SESSION->fromurl = $HTTP_REFERER;
867 if ($PHPSESSID) { // Cookies not enabled.
868 redirect("$CFG->wwwroot/login/?PHPSESSID=$PHPSESSID");
869 } else {
870 redirect("$CFG->wwwroot/login/");
871 }
872 die;
f9903ed0 873 }
da5c172a 874
875 // Next, check if the user can be in a particular course
876 if ($courseid) {
877 if ($USER->student[$courseid] || $USER->teacher[$courseid] || $USER->admin) {
878 update_user_in_db();
879 return; // user is a member of this course.
880 }
881 if (! $course = get_record("course", "id", $courseid)) {
882 error("That course doesn't exist");
883 }
884 if ($course->guest && ($USER->username == "guest")) {
885 update_user_in_db();
886 return; // user is a guest and this course allows guests
887 }
f9903ed0 888
da5c172a 889 // Not allowed in the course, so see if they want to enrol
890
891 $SESSION->wantsurl = $FULLME;
892 redirect("$CFG->wwwroot/course/enrol.php?id=$courseid");
893 die;
894 }
f9903ed0 895}
896
897
898
899function update_login_count() {
900 global $SESSION;
901
902 $max_logins = 10;
903
904 if (empty($SESSION->logincount)) {
905 $SESSION->logincount = 1;
906 } else {
907 $SESSION->logincount++;
908 }
909
910 if ($SESSION->logincount > $max_logins) {
911 unset($SESSION->wantsurl);
912 error("Sorry, you have exceeded the allowed number of login attempts. Restart your browser.");
913 }
914}
915
916
917function isadmin($userid=0) {
918 global $USER;
919
920 if (!$userid) {
921 return $USER->admin;
922 }
923
924 return record_exists_sql("SELECT * FROM user_admins WHERE user='$userid'");
925}
926
8a9e3fd7 927function isteacher($courseid, $userid=0) {
f9903ed0 928 global $USER;
929
d115a57f 930 if (isadmin($userid)) { // admins can do anything the teacher can
931 return true;
932 }
933
f9903ed0 934 if (!$userid) {
8a9e3fd7 935 return $USER->teacher[$courseid];
f9903ed0 936 }
937
8a9e3fd7 938 return record_exists_sql("SELECT * FROM user_teachers WHERE user='$userid' AND course='$courseid'");
f9903ed0 939}
940
941
8a9e3fd7 942function isstudent($courseid, $userid=0) {
f9903ed0 943 global $USER;
944
945 if (!$userid) {
8a9e3fd7 946 return $USER->student[$courseid];
f9903ed0 947 }
948
949 $timenow = time(); // todo: add time check below
950
8a9e3fd7 951 return record_exists_sql("SELECT * FROM user_students WHERE user='$userid' AND course='$courseid'");
f9903ed0 952}
953
da5c172a 954function isguest($userid=0) {
955 global $USER;
956
957 if (!$userid) {
958 return ($USER->username == "guest");
959 }
960
961 return record_exists_sql("SELECT * FROM user WHERE user='$userid' AND username = 'guest' ");
962}
963
2c309dc2 964function isediting($courseid, $user=NULL) {
965 global $USER;
966 if (!$user){
967 $user = $USER;
968 }
969 return ($user->editing and isteacher($courseid, $user->id));
970}
971
f9903ed0 972function reset_login_count() {
973 global $SESSION;
974
975 $SESSION->logincount = 0;
976}
977
978
979function set_moodle_cookie($thing) {
980
981 $days = 60;
982 $seconds = 60*60*24*$days;
983
d115a57f 984 setCookie ('MOODLEID', "", time() - 3600, "/");
f9903ed0 985 setCookie ('MOODLEID', rc4encrypt($thing), time()+$seconds, "/");
986}
987
988
989function get_moodle_cookie() {
990 global $MOODLEID;
991 return rc4decrypt($MOODLEID);
992}
993
994
995
996function verify_login($username, $password) {
997
998 $user = get_user_info_from_db("username", $username);
999
1000 if (! $user) {
1001 return false;
1002 } else if ( $user->password == md5($password) ) {
1003 return $user;
1004 } else {
1005 return false;
1006 }
1007}
1008
1009function get_site () {
1010// Returns $course object of the top-level site.
1011 if ( $course = get_record("course", "category", 0)) {
1012 return $course;
1013 } else {
1014 return false;
1015 }
1016}
1017
1018function get_admin () {
1019// Returns $user object of the main admin user
1020
1021 if ( $admins = get_records_sql("SELECT u.* FROM user u, user_admins a WHERE a.user = u.id ORDER BY u.id ASC")) {
1022 foreach ($admins as $admin) {
1023 return $admin; // ie the first one (yeah I know it's bodgy)
1024 }
1025 } else {
1026 return false;
1027 }
1028}
1029
1030function get_teacher($courseid) {
1031// Returns $user object of the main teacher for a course
1032 if ( $teachers = get_records_sql("SELECT u.* FROM user u, user_teachers t
1033 WHERE t.user = u.id AND t.course = '$courseid'
1034 ORDER BY t.authority ASC")) {
1035 foreach ($teachers as $teacher) {
1036 return $teacher; // ie the first one (yeah I know it's bodgy)
1037 }
1038 } else {
1039 return false;
1040 }
1041}
1042
3c720cce 1043function get_course_students($courseid, $sort="u.lastaccess DESC") {
1044 return get_records_sql("SELECT u.* FROM user u, user_students s
1045 WHERE s.course = '$courseid' AND s.user = u.id
1046 ORDER BY $sort");
1047}
1048
1049function get_course_teachers($courseid, $sort="t.authority ASC") {
1050 return get_records_sql("SELECT u.* FROM user u, user_teachers t
1051 WHERE t.course = '$courseid' AND t.user = u.id
1052 ORDER BY $sort");
1053}
1054
1055function get_course_users($courseid, $sort="u.lastaccess DESC") {
57507290 1056// Using this method because the direct SQL just would not always work!
1057
1058 $teachers = get_course_teachers($courseid, $sort);
1059 $students = get_course_students($courseid, $sort);
1060
1061 if ($teachers and $students) {
1062 return array_merge($teachers, $students);
1063 } else if ($teachers) {
1064 return $teachers;
1065 } else {
1066 return $students;
1067 }
1068
1069// return get_records_sql("SELECT u.* FROM user u, user_students s, user_teachers t
1070// WHERE (s.course = '$courseid' AND s.user = u.id) OR
1071// (t.course = '$courseid' AND t.user = u.id)
1072// ORDER BY $sort");
3c720cce 1073}
1074
f9903ed0 1075
1076
1077/// MODULE FUNCTIONS /////////////////////////////////////////////////
1078
1ea8303c 1079function get_coursemodule_from_instance($modulename, $instance, $courseid) {
f9903ed0 1080// Given an instance of a module, finds the coursemodule description
1081
1082 return get_record_sql("SELECT cm.*, m.name
1083 FROM course_modules cm, modules md, $modulename m
1ea8303c 1084 WHERE cm.course = '$courseid' AND
f9903ed0 1085 cm.deleted = '0' AND
1086 cm.instance = m.id AND
1087 md.name = '$modulename' AND
1088 md.id = cm.module AND
1089 m.id = '$instance'");
1090
1091}
1092
1ea8303c 1093function get_all_instances_in_course($modulename, $courseid, $sort="cw.section") {
f9903ed0 1094// Returns an array of all the active instances of a particular
1095// module in a given course. Returns false on any errors.
1096
9ccbad71 1097 return get_records_sql("SELECT m.*,cw.section,cm.id as coursemodule
1098 FROM course_modules cm, course_sections cw, modules md, $modulename m
1ea8303c 1099 WHERE cm.course = '$courseid' AND
f9903ed0 1100 cm.instance = m.id AND
1101 cm.deleted = '0' AND
9ccbad71 1102 cm.section = cw.id AND
f9903ed0 1103 md.name = '$modulename' AND
1104 md.id = cm.module
1105 ORDER BY $sort");
1106
1107}
1108
f9903ed0 1109
1110
1111
f9903ed0 1112/// CORRESPONDENCE ////////////////////////////////////////////////
1113
5fa51a39 1114function email_to_user($user, $from, $subject, $messagetext, $messagehtml="", $attachment="", $attachname="") {
1115// user - a user record as an object
1116// from - a user record as an object
1117// subject - plain text subject line of the email
136dabd8 1118// messagetext - plain text version of the message
1119// messagehtml - complete html version of the message (optional)
1120// attachment - a file on the filesystem, relative to $CFG->dataroot
1121// attachname - the name of the file (extension indicates MIME)
f9903ed0 1122
4216daa6 1123 global $CFG, $_SERVER;
f9903ed0 1124
136dabd8 1125 include_once("$CFG->libdir/phpmailer/class.phpmailer.php");
f9903ed0 1126
5fa51a39 1127 if (!$user) {
f9903ed0 1128 return false;
1129 }
1130
f9903ed0 1131 $mail = new phpmailer;
1132
1e411ffc 1133 $mail->Version = "Moodle $CFG->moodleversion"; // mailer version
136dabd8 1134 $mail->PluginDir = "$CFG->libdir/phpmailer/"; // plugin directory (eg smtp plugin)
7f86ce17 1135 if ($CFG->smtphosts) {
1e411ffc 1136 $mail->IsSMTP(); // use SMTP directly
1137 $mail->Host = "$CFG->smtphosts"; // specify main and backup servers
7f86ce17 1138 } else {
1e411ffc 1139 $mail->IsMail(); // use PHP mail() = sendmail
7f86ce17 1140 }
f9903ed0 1141
136dabd8 1142 $mail->From = "$from->email";
1143 $mail->FromName = "$from->firstname $from->lastname";
1144 $mail->Subject = stripslashes($subject);
f9903ed0 1145
e84ef824 1146 $mail->AddAddress("$user->email","$user->firstname $user->lastname");
f9903ed0 1147
f9903ed0 1148 $mail->WordWrap = 70; // set word wrap
f9903ed0 1149
136dabd8 1150 if ($messagehtml) {
1151 $mail->IsHTML(true);
1152 $mail->Body = $messagehtml;
78681899 1153 $mail->AltBody = "\n$messagetext\n";
136dabd8 1154 } else {
1155 $mail->IsHTML(false);
78681899 1156 $mail->Body = "\n$messagetext\n";
f9903ed0 1157 }
1158
136dabd8 1159 if ($attachment && $attachname) {
1160 if (ereg( "\\.\\." ,$attachment )) { // Security check for ".." in dir path
4216daa6 1161 $adminuser = get_admin();
1162 $mail->AddAddress("$adminuser->email", "$adminuser->firstname $adminuser->lastname");
1163 $mail->AddStringAttachment("Error in attachment. User attempted to attach a filename with a unsafe name.", "error.txt", "8bit", "text/plain");
136dabd8 1164 } else {
1165 include_once("$CFG->dirroot/files/mimetypes.php");
1166 $mimetype = mimeinfo("type", $attachname);
1167 $mail->AddAttachment("$CFG->dataroot/$attachment", "$attachname", "base64", "$mimetype");
1168 }
f9903ed0 1169 }
1170
136dabd8 1171 if ($mail->Send()) {
1172 return true;
1173 } else {
4216daa6 1174 echo "ERROR: $mail->ErrorInfo\n";
1175 $site = get_site();
1176 add_to_log($site->id, "library", "mailer", $_SERVER["REQUEST_URI"], "ERROR: $mail->ErrorInfo");
f9903ed0 1177 return false;
1178 }
f9903ed0 1179}
1180
136dabd8 1181
f9903ed0 1182/// FILE HANDLING /////////////////////////////////////////////
1183
1184function get_directory_list( $rootdir ) {
1185// Returns an array with all the filenames in
1186// all subdirectories, relative to the given rootdir.
1187
1188 $dirs = array();
1189
1190 $dir = opendir( $rootdir );
1191
1192 while( $file = readdir( $dir ) ) {
1193 $fullfile = $rootdir."/".$file;
1194 if ($file != "." and $file != "..") {
1195 if (filetype($fullfile) == "dir") {
1196 $subdirs = get_directory_list($fullfile);
1197 foreach ($subdirs as $subdir) {
1198 $dirs[] = $file."/".$subdir;
1199 }
1200 } else {
1201 $dirs[] = $file;
1202 }
1203 }
1204 }
1205
1206 return $dirs;
1207}
1208
1180c6dc 1209/// STRING TRANSLATION ////////////////////////////////////////
1210
a83fded1 1211function print_string($identifier, $module="", $a=NULL) {
1212 echo get_string($identifier, $module, $a);
bcc83c41 1213}
1214
1215
a83fded1 1216function get_string($identifier, $module="", $a=NULL) {
1180c6dc 1217// Return the translated string specified by $identifier as
1218// for $module. Uses the same format files as STphp.
a83fded1 1219// $a is an object, string or number that can be used
1180c6dc 1220// within translation strings
a83fded1 1221//
1222// eg "hello \$a->firstname \$a->lastname"
1223// or "hello \$a"
1180c6dc 1224
1225 global $CFG, $USER;
1226
1227 if (isset($USER->lang)) { // User language can override site language
1228 $lang = $USER->lang;
1229 } else {
1230 $lang = $CFG->lang;
1231 }
1232
058eec18 1233 if ($module == "") {
1234 $module = "moodle";
1180c6dc 1235 }
1236
058eec18 1237 $langpath = "$CFG->dirroot/lang";
1238 $langfile = "$langpath/$lang/$module.php";
1180c6dc 1239
1240 if (!file_exists($langfile)) { // try English instead
058eec18 1241 $langfile = "$langpath/en/$module.php";
1180c6dc 1242 if (!file_exists($langfile)) {
058eec18 1243 return "ERROR: No lang file ($langpath/en/$module.php)!";
1180c6dc 1244 }
1245 }
1246
1247 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
1248
1249 eval($result);
1250 return $resultstring;
1251
1252 } else {
1253 if ($lang == "en") {
7a302afc 1254 return "ERROR: '$identifier' is missing!";
1180c6dc 1255
1256 } else { // Try looking in the english file.
058eec18 1257 $langfile = "$langpath/en/$module.php";
1180c6dc 1258 if (!file_exists($langfile)) {
058eec18 1259 return "ERROR: No lang file ($langpath/en/$module.php)!";
1180c6dc 1260 }
1261 if ($result = get_string_from_file($identifier, $langfile, "\$resultstring")) {
1262 eval($result);
1263 return $resultstring;
1264 } else {
7a302afc 1265 return "ERROR: '$identifier' is missing!";
1180c6dc 1266 }
1267 }
1268 }
1269}
1270
1271
1180c6dc 1272function get_string_from_file($identifier, $langfile, $destination) {
1273// This function is only used from get_string().
1274 include ($langfile);
1275
1276 if (!isset ($string[$identifier])) {
1277 return false;
1278 }
1279
a83fded1 1280 return "$destination = sprintf(\"".$string[$identifier]."\");";
1180c6dc 1281}
f9903ed0 1282
1283
1284/// ENCRYPTION ////////////////////////////////////////////////
1285
1286function rc4encrypt($data) {
1287 $password = "nfgjeingjk";
1288 return endecrypt($password, $data, "");
1289}
1290
1291function rc4decrypt($data) {
1292 $password = "nfgjeingjk";
1293 return endecrypt($password, $data, "de");
1294}
1295
1296function endecrypt ($pwd, $data, $case) {
1297// Based on a class by Mukul Sabharwal [mukulsabharwal@yahoo.com]
1298
1299 if ($case == 'de') {
1300 $data = urldecode($data);
1301 }
1302
1303 $key[] = "";
1304 $box[] = "";
1305 $temp_swap = "";
1306 $pwd_length = 0;
1307
1308 $pwd_length = strlen($pwd);
1309
1310 for ($i = 0; $i <= 255; $i++) {
1311 $key[$i] = ord(substr($pwd, ($i % $pwd_length), 1));
1312 $box[$i] = $i;
1313 }
1314
1315 $x = 0;
1316
1317 for ($i = 0; $i <= 255; $i++) {
1318 $x = ($x + $box[$i] + $key[$i]) % 256;
1319 $temp_swap = $box[$i];
1320 $box[$i] = $box[$x];
1321 $box[$x] = $temp_swap;
1322 }
1323
1324 $temp = "";
1325 $k = "";
1326
1327 $cipherby = "";
1328 $cipher = "";
1329
1330 $a = 0;
1331 $j = 0;
1332
1333 for ($i = 0; $i < strlen($data); $i++) {
1334 $a = ($a + 1) % 256;
1335 $j = ($j + $box[$a]) % 256;
1336 $temp = $box[$a];
1337 $box[$a] = $box[$j];
1338 $box[$j] = $temp;
1339 $k = $box[(($box[$a] + $box[$j]) % 256)];
1340 $cipherby = ord(substr($data, $i, 1)) ^ $k;
1341 $cipher .= chr($cipherby);
1342 }
1343
1344 if ($case == 'de') {
1345 $cipher = urldecode(urlencode($cipher));
1346 } else {
1347 $cipher = urlencode($cipher);
1348 }
1349
1350 return $cipher;
1351}
1352
1353
1354/// MISCELLANEOUS ////////////////////////////////////////////////////////////////////
1355
39917a09 1356function count_words($string) {
1357 $string = strip_tags($string);
1358 return count(preg_split("/\w\b/", $string)) - 1;
1359}
1360
f9903ed0 1361function getweek ($startdate, $thedate) {
1362// Given dates in seconds, how many weeks is the date from startdate
1363// The first week is 1, the second 2 etc ...
1364
1365 if ($thedate < $startdate) { // error
1366 return 0;
1367 }
1368
1369 return floor(($thedate - $startdate) / 604800.0) + 1;
1370}
1371
4216daa6 1372function add_to_log($course, $module, $action, $url="", $info="") {
1373// Add an entry to the log table. These are "action" focussed rather
1374// than web server hits, and provide a way to easily reconstruct what
1375// any particular student has been doing.
1376//
1377// course = the course id
501cdbd8 1378// module = forum, journal, reading, course, user etc
4216daa6 1379// action = view, edit, post (often but not always the same as the file.php)
1380// url = the file and parameters used to see the results of the action
1381// info = additional description information
1382
1383
f9903ed0 1384 global $db, $USER, $REMOTE_ADDR;
1385
9132e866 1386 if (isset($USER->realuser)) { // Don't log
1387 return;
1388 }
1389
f9903ed0 1390 $timenow = time();
4216daa6 1391 $info = addslashes($info);
1392
1393 $result = $db->Execute("INSERT INTO log
1394 SET time = '$timenow',
1395 user = '$USER->id',
1396 course = '$course',
1397 ip = '$REMOTE_ADDR',
1398 module = '$module',
1399 action = '$action',
1400 url = '$url',
1401 info = '$info'");
f9903ed0 1402 if (!$result) {
4216daa6 1403 echo "<P>Error: Could not insert a new entry to the Moodle log</P>"; // Don't throw an error
f9903ed0 1404 }
1405}
1406
1407function generate_password($maxlen=10) {
1408/* returns a randomly generated password of length $maxlen. inspired by
1409 * http://www.phpbuilder.com/columns/jesus19990502.php3 */
1410
1411 global $CFG;
1412
1413 $fillers = "1234567890!$-+";
1414 $wordlist = file($CFG->wordlist);
1415
1416 srand((double) microtime() * 1000000);
1417 $word1 = trim($wordlist[rand(0, count($wordlist) - 1)]);
1418 $word2 = trim($wordlist[rand(0, count($wordlist) - 1)]);
1419 $filler1 = $fillers[rand(0, strlen($fillers) - 1)];
1420
1421 return substr($word1 . $filler1 . $word2, 0, $maxlen);
1422}
1423
1424
1425function format_time($totalsecs) {
1426
1427 $days = floor($totalsecs/86400);
1428 $remainder = $totalsecs - ($days*86400);
1429 $hours = floor($remainder/3600);
1430 $remainder = $remainder - ($hours*3600);
1431 $mins = floor($remainder/60);
1432 $secs = $remainder - ($mins*60);
1433
1434 if ($secs != 1) $ss = "s";
1435 if ($mins != 1) $ms = "s";
1436 if ($hours != 1) $hs = "s";
1437 if ($days != 1) $ds = "s";
1438
1439 if ($days) $odays = "$days day$ds";
1440 if ($hours) $ohours = "$hours hr$hs";
1441 if ($mins) $omins = "$mins min$ms";
1442 if ($secs) $osecs = "$secs sec$ss";
1443
1444 if ($days) return "$odays $ohours";
1445 if ($hours) return "$ohours $omins";
1446 if ($mins) return "$omins $osecs";
1447 if ($secs) return "$osecs";
1448 return "now";
1449}
1450
f9903ed0 1451?>