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