3 include_once("$CFG->dirroot/files/mimetypes.php");
5 /// CONSTANTS ///////////////////////////////////////////////////////////
7 $FORUM_DEFAULT_DISPLAY_MODE = 3;
9 $FORUM_LAYOUT_MODES = array ( "1" => get_string("modeflatoldestfirst", "forum"),
10 "-1" => get_string("modeflatnewestfirst", "forum"),
11 "2" => get_string("modethreaded", "forum"),
12 "3" => get_string("modenested", "forum") );
14 // These are course content forums that can be added to the course manually
15 $FORUM_TYPES = array ("general" => get_string("generalforum", "forum"),
16 "eachuser" => get_string("eachuserforum", "forum"),
17 "single" => get_string("singleforum", "forum") );
19 $FORUM_POST_RATINGS = array ("3" => get_string("postrating3", "forum"),
20 "2" => get_string("postrating2", "forum"),
21 "1" => get_string("postrating1", "forum") );
23 $FORUM_OPEN_MODES = array ("2" => get_string("openmode2", "forum"),
24 "1" => get_string("openmode1", "forum"),
25 "0" => get_string("openmode0", "forum") );
28 define("FORUM_SHORT_POST", 300); // Less non-HTML characters than this is short
30 define("FORUM_LONG_POST", 600); // More non-HTML characters than this is long
32 define("FORUM_MANY_DISCUSSIONS", 10);
35 /// STANDARD FUNCTIONS ///////////////////////////////////////////////////////////
37 function forum_add_instance($forum) {
38 // Given an object containing all the necessary data,
39 // (defined by the form in mod.html) this function
40 // will create a new instance and return the id number
41 // of the new instance.
45 $forum->timemodified = time();
47 if (! $forum->id = insert_record("forum", $forum)) {
51 if ($forum->type == "single") { // Create related discussion.
53 $discussion->course = $forum->course;
54 $discussion->forum = $forum->id;
55 $discussion->name = $forum->name;
56 $discussion->intro = $forum->intro;
57 $discussion->assessed = $forum->assessed;
59 if (! forum_add_discussion($discussion)) {
60 error("Could not add the discussion for this forum");
63 add_to_log($forum->course, "forum", "add", "index.php?f=$forum->id", "$forum->id");
69 function forum_update_instance($forum) {
70 // Given an object containing all the necessary data,
71 // (defined by the form in mod.html) this function
72 // will update an existing instance with new data.
74 $forum->timemodified = time();
75 $forum->id = $forum->instance;
77 if ($forum->type == "single") { // Update related discussion and post.
78 if (! $discussion = get_record("forum_discussions", "forum", $forum->id)) {
79 if ($discussions = get_records("forum_discussions", "forum", $forum->id, "timemodified ASC")) {
80 notify("Warning! There is more than one discussion in this forum - using the most recent");
81 $discussion = array_pop($discussions);
83 error("Could not find the discussion in this forum");
86 if (! $post = get_record("forum_posts", "id", $discussion->firstpost)) {
87 error("Could not find the first post in this forum discussion");
90 $post->subject = $forum->name;
91 $post->message = $forum->intro;
92 $post->modified = $forum->timemodified;
94 if (! update_record("forum_posts", $post)) {
95 error("Could not update the first post");
98 $discussion->name = $forum->name;
100 if (! update_record("forum_discussions", $discussion)) {
101 error("Could not update the discussion");
105 if (update_record("forum", $forum)) {
106 add_to_log($forum->course, "forum", "update", "index.php?f=$forum->id", "$forum->id");
114 function forum_delete_instance($id) {
115 // Given an ID of an instance of this module,
116 // this function will permanently delete the instance
117 // and any data that depends on it.
119 if (! $forum = get_record("forum", "id", "$id")) {
125 if ($discussions = get_records("forum_discussions", "forum", $forum->id)) {
126 foreach ($discussions as $discussion) {
127 if (! forum_delete_discussion($discussion)) {
133 if (! delete_records("forum_subscriptions", "forum", "$forum->id")) {
137 if (! delete_records("forum", "id", "$forum->id")) {
145 function forum_cron () {
146 // Function to be run periodically according to the moodle cron
147 // Finds all posts that have yet to be mailed out, and mails them
151 $cutofftime = time() - $CFG->maxeditingtime;
153 if ($posts = get_records_sql("SELECT p.*, d.course FROM forum_posts p, forum_discussions d
154 WHERE p.mailed = '0' AND p.created < '$cutofftime' AND p.discussion = d.id")) {
158 foreach ($posts as $post) {
160 print_string("processingpost", "forum", $post->id);
163 if (! $userfrom = get_record("user", "id", "$post->user")) {
164 echo "Could not find user $post->user\n";
168 if (! $discussion = get_record("forum_discussions", "id", "$post->discussion")) {
169 echo "Could not find discussion $post->discussion\n";
173 if (! $forum = get_record("forum", "id", "$discussion->forum")) {
174 echo "Could not find forum $discussion->forum\n";
178 if (! $course = get_record("course", "id", "$forum->course")) {
179 echo "Could not find course $forum->course\n";
183 if ($users = forum_subscribed_users($course, $forum)) {
184 $canunsubscribe = ! forum_is_forcesubscribed($forum->id);
187 foreach ($users as $userto) {
188 $USER->lang = $userto->lang; // Affects the language of get_string
189 $canreply = forum_user_can_post($forum, $userto);
192 $by->name = "$userfrom->firstname $userfrom->lastname";
193 $by->date = userdate($post->created, "", $userto->timezone);
194 $strbynameondate = get_string("bynameondate", "forum", $by);
196 $strforums = get_string("forums", "forum");
198 $postsubject = "$course->shortname: $post->subject";
199 $posttext = "$course->shortname -> $strforums -> $forum->name";
201 if ($discussion->name == $forum->name) {
204 $posttext .= " -> $discussion->name\n";
206 $posttext .= "---------------------------------------------------------------------\n";
207 $posttext .= "$post->subject\n";
208 $posttext .= $strbynameondate."\n";
209 $posttext .= "---------------------------------------------------------------------\n";
210 $posttext .= strip_tags($post->message);
212 if ($post->attachment) {
213 $post->course = $course->id;
214 $post->forum = $forum->id;
215 $posttext .= forum_print_attachments($post, "text");
218 $posttext .= "---------------------------------------------------------------------\n";
219 $posttext .= get_string("postmailinfo", "forum", $course->shortname)."\n";
220 $posttext .= "$CFG->wwwroot/mod/forum/post.php?reply=$post->id\n";
222 if ($canunsubscribe) {
223 $posttext .= "\n---------------------------------------------------------------------\n";
224 $posttext .= get_string("unsubscribe", "forum");
225 $posttext .= ": $CFG->wwwroot/mod/forum/subscribe.php?id=$forum->id\n";
228 if ($userto->mailformat == 1) { // HTML
229 $posthtml = "<P><FONT FACE=sans-serif>".
230 "<A TARGET=\"_blank\" HREF=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</A> -> ".
231 "<A TARGET=\"_blank\" HREF=\"$CFG->wwwroot/mod/forum/index.php?id=$course->id\">$strforums</A> -> ".
232 "<A TARGET=\"_blank\" HREF=\"$CFG->wwwroot/mod/forum/view.php?f=$forum->id\">$forum->name</A>";
233 if ($discussion->name == $forum->name) {
234 $posthtml .= "</FONT></P>";
236 $posthtml .= " -> <A TARGET=\"_blank\" HREF=\"$CFG->wwwroot/mod/forum/discuss.php?d=$discussion->id\">$discussion->name</A></FONT></P>";
238 $posthtml .= forum_make_mail_post($post, $userfrom, $userto, $course, false, $canreply, false, false);
240 if ($canunsubscribe) {
241 $posthtml .= "\n<BR><HR SIZE=1 NOSHADE><P ALIGN=RIGHT><FONT SIZE=1><A HREF=\"$CFG->wwwroot/mod/forum/subscribe.php?id=$forum->id\">".get_string("unsubscribe", "forum")."</A></FONT></P>";
248 if (! email_to_user($userto, $userfrom, $postsubject, $posttext, $posthtml)) {
249 echo "Error: mod/forum/cron.php: Could not send out mail for id $post->id to user $userto->id ($userto->email)\n";
254 echo "mailed to $mailcount users ...";
257 if (! set_field("forum_posts", "mailed", "1", "id", "$post->id")) {
258 echo "Could not update the mailed field for id $post->id\n";
267 function forum_user_outline($course, $user, $mod, $forum) {
269 if ($posts = get_records_sql("SELECT p.*, u.id as userid, u.firstname, u.lastname, u.email, u.picture
270 FROM forum f, forum_discussions d, forum_posts p, user u
271 WHERE f.id = '$forum->id' AND d.forum = f.id AND p.discussion = d.id
272 AND p.user = '$user->id' AND p.user = u.id
273 ORDER BY p.modified ASC")) {
275 $result->info = get_string("numposts", "forum", count($posts));
277 $lastpost = array_pop($posts);
278 $result->time = $lastpost->modified;
285 function forum_user_complete($course, $user, $mod, $forum) {
288 if ($posts = get_records_sql("SELECT p.*, u.id as userid, u.firstname, u.lastname, u.email, u.picture
289 FROM forum f, forum_discussions d, forum_posts p, user u
290 WHERE f.id = '$forum->id' AND d.forum = f.id AND p.discussion = d.id
291 AND p.user = '$user->id' AND p.user = u.id
292 ORDER BY p.modified ASC")) {
294 foreach ($posts as $post) {
296 $footer = "<A HREF=\"$CFG->wwwroot/mod/forum/discuss.php?d=$post->discussion&parent=$post->parent\">".
297 get_string("parentofthispost", "forum")."</A>";
302 forum_print_post($post, $course->id, $ownpost=false, $reply=false, $link=false, $rate=false, $footer);
306 echo "<P>".get_string("noposts", "forum")."</P>";
311 function forum_print_recent_activity(&$logs, $isteacher=false) {
312 global $CFG, $COURSE_TEACHER_COLOR;
317 foreach ($logs as $log) {
318 if ($log->module == "forum") {
321 if ($log->action == "add post") {
322 $post = get_record_sql("SELECT p.*, d.forum, u.firstname, u.lastname,
323 u.email, u.picture, u.id as userid
324 FROM forum_discussions d, forum_posts p, user u
325 WHERE p.id = '$log->info' AND d.id = p.discussion
326 AND p.user = u.id and u.deleted <> '1'");
328 } else if ($log->action == "add discussion") {
329 $post = get_record_sql("SELECT p.*, d.forum, u.firstname, u.lastname,
330 u.email, u.picture, u.id as userid
331 FROM forum_discussions d, forum_posts p, user u
332 WHERE d.id = '$log->info' AND d.firstpost = p.id
333 AND p.user = u.id and u.deleted <> '1'");
338 if ($forum = get_record("forum", "id", $post->forum) ) {
339 if ($forum->type == "teacher") {
341 $teacherpost = "COLOR=$COURSE_TEACHER_COLOR";
348 print_headline(get_string("newforumposts", "forum").":");
352 $date = userdate($post->modified, "%e %b, %H:%M");
353 echo "<P><FONT SIZE=1 $teacherpost>$date - $post->firstname $post->lastname<BR>";
354 echo "\"<A HREF=\"$CFG->wwwroot/mod/forum/$log->url\">";
355 if ($log->action == "add") {
356 echo "<B>$post->subject</B>";
358 echo "$post->subject";
360 echo "</A>\"</FONT></P>";
368 function forum_grades($forumid) {
369 /// Must return an array of grades, indexed by user, and a max grade.
370 global $FORUM_POST_RATINGS;
372 if (!$forum = get_record("forum", "id", $forumid)) {
375 if (!$forum->assessed) {
378 if ($ratings = get_records_sql("SELECT r.id, p.user, r.rating
379 FROM forum_discussions d, forum_posts p, forum_ratings r
380 WHERE d.forum = '$forumid'
381 AND p.discussion = d.id
382 AND r.post = p.id")) {
383 foreach ($ratings as $rating) {
385 $r = $rating->rating;
386 if (!isset($sumrating[$u])) {
387 $sumrating[$u][1] = 0;
388 $sumrating[$u][2] = 0;
389 $sumrating[$u][3] = 0;
391 $sumrating[$u][$r]++;
393 foreach ($sumrating as $user => $rating) {
394 $return->grades[$user] = $rating[1]."s/".$rating[2]."/".$rating[3]."c";
397 $return->grades = array();
400 $return->maxgrade = "";
405 /// OTHER FUNCTIONS ///////////////////////////////////////////////////////////
408 function forum_get_course_forum($courseid, $type) {
409 // How to set up special 1-per-course forums
410 if ($forum = get_record_sql("SELECT * from forum WHERE course = '$courseid' AND type = '$type'")) {
414 // Doesn't exist, so create one now.
415 $forum->course = $courseid;
416 $forum->type = "$type";
417 switch ($forum->type) {
419 $forum->name = get_string("namenews", "forum");
420 $forum->intro = get_string("intronews", "forum");
421 $forum->open = 1; // 0 - no, 1 - posts only, 2 - discuss and post
422 $forum->assessed = 0;
423 $forum->forcesubscribe = 1;
426 $forum->name = get_string("namesocial", "forum");
427 $forum->intro = get_string("introsocial", "forum");
428 $forum->open = 2; // 0 - no, 1 - posts only, 2 - discuss and post
429 $forum->assessed = 0;
430 $forum->forcesubscribe = 0;
433 $forum->name = get_string("nameteacher", "forum");
434 $forum->intro = get_string("introteacher", "forum");
435 $forum->open = 0; // 0 - no, 1 - posts only, 2 - discuss and post
436 $forum->assessed = 0;
437 $forum->forcesubscribe = 0;
440 notify("That forum type doesn't exist!");
445 $forum->timemodified = time();
446 $forum->id = insert_record("forum", $forum);
448 if ($forum->type != "teacher") {
449 if (! $module = get_record("modules", "name", "forum")) {
450 notify("Could not find forum module!!");
453 $mod->course = $courseid;
454 $mod->module = $module->id;
455 $mod->instance = $forum->id;
457 if (! $mod->coursemodule = add_course_module($mod) ) { // assumes course/lib.php is loaded
458 notify("Could not add a new course module to the course '$course->fullname'");
461 if (! $sectionid = add_mod_to_section($mod) ) { // assumes course/lib.php is loaded
462 notify("Could not add the new course module to that section");
465 if (! set_field("course_modules", "section", $sectionid, "id", $mod->coursemodule)) {
466 notify("Could not update the course module with the correct section");
471 return get_record("forum", "id", "$forum->id");
476 function forum_make_mail_post(&$post, $user, $touser, $course,
477 $ownpost=false, $reply=false, $link=false, $rate=false, $footer="") {
478 // Given the data about a posting, builds up the HTML to display it and
479 // returns the HTML in a string. This is designed for sending via HTML email.
486 $output .= "<TABLE BORDER=0 CELLPADDING=1 CELLSPACING=1><TR><TD BGCOLOR=#888888>";
487 $output .= "<TABLE BORDER=0 CELLPADDING=3 CELLSPACING=0>";
489 $output .= "<TABLE BORDER=0 CELLPADDING=1 CELLSPACING=1 WIDTH=100%><TR><TD BGCOLOR=#888888>";
490 $output .= "<TABLE BORDER=0 CELLPADDING=3 CELLSPACING=0 WIDTH=100%>";
493 $output .= "<TR><TD BGCOLOR=\"$THEME->body\" WIDTH=35 VALIGN=TOP>";
494 $output .= print_user_picture($user->id, $course->id, $user->picture, false, true);
498 $output .= "<TD NOWRAP BGCOLOR=\"$THEME->cellheading\">";
500 $output .= "<TD NOWRAP BGCOLOR=\"$THEME->cellheading2\">";
503 $output .= "<FONT SIZE=3><B>$post->subject</B></FONT><BR>";
504 $output .= "<FONT SIZE=2>";
505 $by->name = "<A HREF=\"$CFG->wwwroot/user/view.php?id=$user->id&course=$course->id\">$user->firstname $user->lastname</A>";
506 $by->date = userdate($post->created, "", $touser->timezone);
507 $output .= get_string("bynameondate", "forum", $by);
508 $output .= "</FONT></P></TD></TR>";
509 $output .= "<TR><TD BGCOLOR=\"$THEME->body\" WIDTH=10>";
511 $output .= "</TD><TD BGCOLOR=\"$THEME->cellcontent\">\n";
513 if ($post->attachment) {
514 $post->course = $course->id;
515 $post->forum = get_field("forum_discussions", "forum", "id", $post->discussion);
516 $output .= "<DIV ALIGN=right>";
517 $output .= forum_print_attachments($post, "html");
521 $output .= format_text($post->message, $post->format);
523 $output .= "<P ALIGN=right><FONT SIZE=-1>";
525 $age = time() - $post->created;
527 $output .= "<A HREF=\"$CFG->wwwroot/mod/forum/post.php?delete=$post->id\">".get_string("delete", "forum")."</A>";
529 $output .= " | <A TARGET=\"_blank\" HREF=\"$CFG->wwwroot/mod/forum/post.php?reply=$post->id\">".get_string("reply", "forum")."</A>";
531 $output .= " ";
534 $output .= "<A TARGET=\"_blank\" HREF=\"$CFG->wwwroot/mod/forum/post.php?reply=$post->id\">".get_string("reply", "forum")."</A> ";
539 $output .= "<DIV ALIGN=right><P ALIGN=right>";
542 if ($post->replies == 1) {
543 $replystring = get_string("repliesone", "forum", $post->replies);
545 $replystring = get_string("repliesmany", "forum", $post->replies);
547 $output .= "<A HREF=\"$CFG->wwwroot/mod/forum/discuss.php?d=$post->discussion\"><B>".get_string("discussthistopic", "forum")."</B></A> ($replystring) ";
549 $output .= "</P></DIV>";
551 $output .= "<P>$footer</P>";
553 $output .= "</TD></TR></TABLE>\n";
554 $output .= "</TD></TR></TABLE>\n\n";
560 function forum_print_post(&$post, $courseid, $ownpost=false, $reply=false, $link=false, $rate=false, $footer="") {
561 global $THEME, $USER, $CFG;
564 echo "<TABLE BORDER=0 CELLPADDING=1 CELLSPACING=1><TR><TD BGCOLOR=#888888>";
565 echo "<TABLE BORDER=0 CELLPADDING=3 CELLSPACING=0>";
567 echo "<TABLE BORDER=0 CELLPADDING=1 CELLSPACING=1 WIDTH=100%><TR><TD BGCOLOR=#888888>";
568 echo "<TABLE BORDER=0 CELLPADDING=3 CELLSPACING=0 WIDTH=100%>";
571 echo "<TR><TD BGCOLOR=\"$THEME->body\" WIDTH=35 VALIGN=TOP>";
572 print_user_picture($post->userid, $courseid, $post->picture);
576 echo "<TD NOWRAP BGCOLOR=\"$THEME->cellheading\" WIDTH=\"100%\">";
578 echo "<TD NOWRAP BGCOLOR=\"$THEME->cellheading2\" WIDTH=\"100%*\">";
581 echo "<FONT SIZE=3><B>$post->subject</B></FONT><BR>";
582 echo "<FONT SIZE=2>";
583 $by->name = "<A HREF=\"$CFG->wwwroot/user/view.php?id=$post->userid&course=$courseid\">$post->firstname $post->lastname</A>";
584 $by->date = userdate($post->created);
585 print_string("bynameondate", "forum", $by);
586 echo "</FONT></P></TD></TR>";
587 echo "<TR><TD BGCOLOR=\"$THEME->body\" WIDTH=10>";
589 echo "</TD><TD BGCOLOR=\"$THEME->cellcontent\">\n";
591 if ($post->attachment) {
592 $post->course = $courseid;
593 $post->forum = get_field("forum_discussions", "forum", "id", $post->discussion);
594 echo "<DIV ALIGN=right>";
595 forum_print_attachments($post);
599 if ($link and (strlen(strip_tags($post->message)) > FORUM_LONG_POST)) {
600 // Print shortened version
601 echo format_text(forum_shorten_post($post->message), $post->format);
602 $numwords = count_words(strip_tags($post->message));
603 echo "<P><A HREF=\"$CFG->wwwroot/mod/forum/discuss.php?d=$post->discussion\">";
604 echo get_string("readtherest", "forum");
605 echo "</A> (".get_string("numwords", "", $numwords).")...</P>";
607 // Print whole message
608 echo format_text($post->message, $post->format);
611 echo "<P ALIGN=right><FONT SIZE=-1>";
613 $age = time() - $post->created;
615 if ($age < $CFG->maxeditingtime) {
616 echo "<A HREF=\"$CFG->wwwroot/mod/forum/post.php?edit=$post->id\">".get_string("edit", "forum")."</A> | ";
619 if ($ownpost or isteacher($courseid)) {
620 echo "<A HREF=\"$CFG->wwwroot/mod/forum/post.php?delete=$post->id\">".get_string("delete", "forum")."</A>";
628 echo "<A HREF=\"$CFG->wwwroot/mod/forum/post.php?reply=$post->id\">".get_string("reply", "forum")."</A>";
633 echo "<DIV ALIGN=right><P ALIGN=right>";
634 if ($rate && $USER->id) {
635 if (isteacher($courseid)) {
636 forum_print_ratings($post->id);
637 if ($USER->id != $post->userid) {
638 forum_print_rating($post->id, $USER->id);
640 } else if ($USER->id == $post->userid) {
641 forum_print_ratings($post->id);
643 forum_print_rating($post->id, $USER->id);
648 if ($post->replies == 1) {
649 $replystring = get_string("repliesone", "forum", $post->replies);
651 $replystring = get_string("repliesmany", "forum", $post->replies);
653 echo "<A HREF=\"$CFG->wwwroot/mod/forum/discuss.php?d=$post->discussion\"><B>".get_string("discussthistopic", "forum")."</B></A> ($replystring) ";
657 echo "<P>$footer</P>";
660 echo "</TD></TR></TABLE>";
661 echo "</TD></TR>\n</TABLE>\n\n";
665 function forum_print_post_header(&$post, $courseid, $ownpost=false, $reply=false, $link=false, $rate=false, $footer="") {
666 global $THEME, $USER, $CFG;
669 echo "<TABLE BORDER=0 CELLPADDING=1 CELLSPACING=1><TR><TD BGCOLOR=#888888>";
670 echo "<TABLE BORDER=0 CELLPADDING=3 CELLSPACING=0>";
672 echo "<TABLE BORDER=0 CELLPADDING=1 CELLSPACING=1 WIDTH=100%><TR><TD BGCOLOR=#888888>";
673 echo "<TABLE BORDER=0 CELLPADDING=3 CELLSPACING=0 WIDTH=100%>";
676 echo "<TR><TD BGCOLOR=\"$THEME->body\" WIDTH=35 VALIGN=TOP>";
677 print_user_picture($post->userid, $courseid, $post->picture);
681 echo "<TD NOWRAP BGCOLOR=\"$THEME->cellheading\">";
683 echo "<TD NOWRAP BGCOLOR=\"$THEME->cellheading2\">";
686 echo "<FONT SIZE=3><B>$post->subject</B></FONT><BR>";
687 echo "<FONT SIZE=2>";
688 $by->name = "<A HREF=\"$CFG->wwwroot/user/view.php?id=$post->userid&course=$courseid\">$post->firstname $post->lastname</A>";
689 $by->date = userdate($post->created);
690 print_string("bynameondate", "forum", $by);
691 echo "</FONT></P></TD>";
694 echo "<TD VALIGN=BOTTOM BGCOLOR=\"$THEME->cellheading\">";
696 echo "<TD VALIGN=BOTTOM BGCOLOR=\"$THEME->cellheading2\">";
698 echo "<P ALIGN=right><FONT SIZE=-1>";
701 if ($post->replies == 1) {
702 $replystring = get_string("repliesone", "forum", $post->replies);
704 $replystring = get_string("repliesmany", "forum", $post->replies);
706 echo "<A HREF=\"$CFG->wwwroot/mod/forum/discuss.php?d=$post->discussion\"><B>".get_string("discussthistopic", "forum")."</B></A> ($replystring) ";
709 echo "</TD></TR></TABLE>";
710 echo "</TD></TR>\n</TABLE>\n\n";
714 function forum_shorten_post($message) {
715 // Given a post object that we already know has a long message
716 // this function truncates the message nicely to the first
717 // sane place between FORUM_LONG_POST and FORUM_SHORT_POST
721 $length = strlen($message);
726 for ($i=0; $i<$length; $i++) {
727 $char = $message[$i];
749 if ($count > FORUM_SHORT_POST) {
759 return substr($message, 0, $truncate);
763 function forum_print_ratings($post) {
764 if ($ratings = get_records_sql("SELECT * from forum_ratings WHERE post='$post'")) {
768 foreach ($ratings as $rating) {
769 $sumrating[$rating->rating]++;
771 $summary = $sumrating[1]."s/".$sumrating[2]."/".$sumrating[3]."c";
773 echo get_string("ratings", "forum").": ";
774 link_to_popup_window ("/mod/forum/report.php?id=$post", "ratings", $summary, 400, 550);
778 function forum_print_rating($post, $user) {
779 global $FORUM_POST_RATINGS;
781 if ($rs = get_record_sql("SELECT rating from forum_ratings WHERE user='$user' AND post='$post'")) {
782 if ($FORUM_POST_RATINGS[$rs->rating]) {
783 echo "<FONT SIZE=-1>".get_string("youratedthis", "forum").": <FONT COLOR=green>";
784 echo $FORUM_POST_RATINGS[$rs->rating];
785 echo "</FONT></FONT>";
789 choose_from_menu($FORUM_POST_RATINGS, $post, "", get_string("rate", "forum")."...");
792 function forum_print_mode_form($discussion, $mode) {
793 GLOBAL $FORUM_LAYOUT_MODES;
796 popup_form("discuss.php?d=$discussion&mode=", $FORUM_LAYOUT_MODES, "mode", $mode, "");
797 echo "</P></CENTER>\n";
800 function forum_print_search_form($course, $search="") {
803 echo "<TABLE BORDER=0 CELLPADDING=10 CELLSPACING=0><TR><TD ALIGN=CENTER>";
804 echo "<FORM NAME=search ACTION=\"$CFG->wwwroot/mod/forum/search.php\">";
805 echo "<INPUT NAME=search TYPE=text SIZE=15 VALUE=\"$search\"><BR>";
806 echo "<INPUT VALUE=\"".get_string("searchforums", "forum")."\" TYPE=submit>";
807 echo "<INPUT NAME=id TYPE=hidden VALUE=\"$course->id\">";
809 echo "</TD></TR></TABLE>";
813 function forum_count_discussion_replies($forum="0") {
814 // Returns an array of counts of replies to each discussion (optionally in one forum)
816 $forumselect = " AND d.forum = '$forum'";
818 return get_records_sql("SELECT p.discussion, (count(*)) as replies
819 FROM forum_posts p, forum_discussions d
820 WHERE p.parent > 0 AND p.discussion = d.id
821 GROUP BY p.discussion");
824 function forum_count_unrated_posts($discussionid, $userid) {
825 // How many unrated posts are in the given discussion for a given user?
826 if ($posts = get_record_sql("SELECT count(*) as num
829 discussion = '$discussionid' AND
830 user <> '$userid' ")) {
832 if ($rated = get_record_sql("SELECT count(*) as num
833 FROM forum_posts p, forum_ratings r
834 WHERE p.discussion = '$discussionid'
836 AND r.user = '$userid'")) {
837 $difference = $posts->num - $rated->num;
838 if ($difference > 0) {
841 return 0; // Just in case there was a counting error
852 function forum_set_return() {
853 global $CFG, $SESSION, $HTTP_REFERER;
855 if (! isset($SESSION->fromdiscussion)) {
856 // If the referer is NOT a login screen then save it.
857 if (! strncasecmp("$CFG->wwwroot/login", $HTTP_REFERER, 300)) {
858 $SESSION->fromdiscussion = $HTTP_REFERER;
859 save_session("SESSION");
865 function forum_go_back_to($default) {
868 if ($SESSION->fromdiscussion) {
869 $returnto = $SESSION->fromdiscussion;
870 unset($SESSION->fromdiscussion);
871 save_session("SESSION");
878 function forum_get_post_full($postid) {
879 return get_record_sql("SELECT p.*, u.firstname, u.lastname,
880 u.email, u.picture, u.id as userid
881 FROM forum_posts p, user u
882 WHERE p.id = '$postid' AND p.user = u.id");
885 function forum_file_area_name($post) {
886 // Creates a directory file name, suitable for make_upload_directory()
889 return "$post->course/$CFG->moddata/forum/$post->forum/$post->id";
892 function forum_file_area($post) {
893 return make_upload_directory( forum_file_area_name($post) );
896 function forum_delete_old_attachments($post, $exception="") {
897 // Deletes all the user files in the attachments area for a post
898 // EXCEPT for any file named $exception
900 if ($basedir = forum_file_area($post)) {
901 if ($files = get_directory_list($basedir)) {
902 foreach ($files as $file) {
903 if ($file != $exception) {
904 unlink("$basedir/$file");
905 notify("Existing file '$file' has been deleted!");
909 if (!$exception) { // Delete directory as well, if empty
915 function forum_print_attachments($post, $return=NULL) {
916 // if return=html, then return a html string.
917 // if return=text, then return a text-only string.
918 // otherwise, print HTML
922 $filearea = forum_file_area_name($post);
924 if ($basedir = forum_file_area($post)) {
925 if ($files = get_directory_list($basedir)) {
926 $strattachment = get_string("attachment", "forum");
927 foreach ($files as $file) {
928 $icon = mimeinfo("icon", $file);
929 if ($CFG->slasharguments) {
930 $ffurl = "file.php/$filearea/$file";
932 $ffurl = "file.php?file=/$filearea/$file";
934 $image = "<IMG BORDER=0 SRC=\"$CFG->wwwroot/files/pix/$icon\" HEIGHT=16 WIDTH=16 ALT=\"File\">";
936 if ($return == "html") {
937 $output .= "<A HREF=\"$CFG->wwwroot/$ffurl\">$image</A> ";
938 $output .= "<A HREF=\"$CFG->wwwroot/$ffurl\">$file</A><BR>";
940 } else if ($return == "text") {
941 $output .= "$strattachment $file:\n$CFG->wwwroot/$ffurl\n";
944 link_to_popup_window("/$ffurl", "attachment", $image, 500, 500, $strattachment);
945 echo "<A HREF=\"$CFG->wwwroot/$ffurl\">$file</A>";
956 function forum_add_attachment($post, $newfile) {
957 // $post is a full post record, including course and forum
958 // $newfile is a full upload array from HTTP_POST_FILES
959 // If successful, this function returns the name of the file
961 if (!isset($newfile['name'])) {
965 $newfile_name = clean_filename($newfile['name']);
967 if (valid_uploaded_file($newfile)) {
968 if (! $newfile_name) {
969 notify("This file had a wierd filename and couldn't be uploaded");
971 } else if (! $dir = forum_file_area($post)) {
972 notify("Attachment could not be stored");
976 if (move_uploaded_file($newfile['tmp_name'], "$dir/$newfile_name")) {
977 forum_delete_old_attachments($post, $newfile_name);
979 notify("An error happened while saving the file on the server");
987 return $newfile_name;
990 function forum_add_new_post($post) {
992 $post->created = $post->modified = time();
995 $newfile = $post->attachment;
996 $post->attachment = "";
998 if (! $post->id = insert_record("forum_posts", $post)) {
1002 if ($post->attachment = forum_add_attachment($post, $newfile)) {
1003 set_field("forum_posts", "attachment", $post->attachment, "id", $post->id);
1009 function forum_update_post($post) {
1011 $post->modified = time();
1013 if (!$post->parent) { // Post is a discussion starter - update discussion title too
1014 set_field("forum_discussions", "name", $post->subject, "id", $post->discussion);
1016 if ($newfilename = forum_add_attachment($post, $post->attachment)) {
1017 $post->attachment = $newfilename;
1019 unset($post->attachment);
1021 return update_record("forum_posts", $post);
1024 function forum_add_discussion($discussion) {
1025 // Given an object containing all the necessary data,
1026 // create a new discussion and return the id
1032 // The first post is stored as a real post, and linked
1033 // to from the discuss entry.
1035 $post->discussion = 0;
1037 $post->user = $USER->id;
1038 $post->created = $timenow;
1039 $post->modified = $timenow;
1041 $post->subject = $discussion->name;
1042 $post->message = $discussion->intro;
1043 $post->attachment = "";
1044 $post->forum = $discussion->forum;
1045 $post->course = $discussion->course;
1047 if (! $post->id = insert_record("forum_posts", $post) ) {
1051 if ($post->attachment = forum_add_attachment($post, $discussion->attachment)) {
1052 set_field("forum_posts", "attachment", $post->attachment, "id", $post->id); //ignore errors
1055 // Now do the real module entry
1057 $discussion->firstpost = $post->id;
1058 $discussion->timemodified = $timenow;
1060 if (! $discussion->id = insert_record("forum_discussions", $discussion) ) {
1061 delete_records("forum_posts", "id", $post->id);
1065 // Finally, set the pointer on the post.
1066 if (! set_field("forum_posts", "discussion", $discussion->id, "id", $post->id)) {
1067 delete_records("forum_posts", "id", $post->id);
1068 delete_records("forum_discussions", "id", $discussion->id);
1072 return $discussion->id;
1076 function forum_delete_discussion($discussion) {
1077 // $discussion is a discussion record object
1081 if ($posts = get_records("forum_posts", "discussion", $discussion->id)) {
1082 foreach ($posts as $post) {
1083 $post->course = $discussion->course;
1084 $post->forum = $discussion->forum;
1085 if (! delete_records("forum_ratings", "post", "$post->id")) {
1088 if (! forum_delete_post($post)) {
1094 if (! delete_records("forum_discussions", "id", "$discussion->id")) {
1102 function forum_delete_post($post) {
1103 if (delete_records("forum_posts", "id", $post->id)) {
1104 delete_records("forum_ratings", "post", $post->id); // Just in case
1105 if ($post->attachment) {
1106 $discussion = get_record("forum_discussions", "id", $post->discussion);
1107 $post->course = $discussion->course;
1108 $post->forum = $discussion->forum;
1109 forum_delete_old_attachments($post);
1117 function forum_print_user_discussions($courseid, $userid) {
1120 $discussions = get_records_sql("SELECT p.*, u.firstname, u.lastname, u.email, u.picture,
1121 u.id as userid, f.type as forumtype, f.name as forumname, f.id as forumid
1122 FROM forum_discussions d, forum_posts p, user u, forum f
1123 WHERE d.course = '$courseid' AND p.discussion = d.id AND
1124 p.parent = 0 AND p.user = u.id AND u.id = '$userid' AND
1126 ORDER BY p.created ASC");
1129 $user = get_record("user", "id", $userid);
1131 print_heading( get_string("discussionsstartedby", "forum", "$user->firstname $user->lastname") );
1132 $replies = forum_count_discussion_replies();
1133 foreach ($discussions as $discussion) {
1134 if (($discussion->forumtype == "teacher") and !isteacher($courseid)) {
1137 if ($replies[$discussion->discussion]) {
1138 $discussion->replies = $replies[$discussion->discussion]->replies;
1140 $discussion->replies = 0;
1142 $inforum = get_string("inforum", "forum", "<A HREF=\"$CFG->wwwroot/mod/forum/view.php?f=$discussion->forumid\">$discussion->forumname</A>");
1143 $discussion->subject .= " ($inforum)";
1144 $ownpost = ($discussion->userid == $USER->id);
1145 forum_print_post($discussion, $courseid, $ownpost, $reply=0, $link=1, $assessed=false);
1151 function forum_forcesubscribe($forumid, $value=1) {
1152 return set_field("forum", "forcesubscribe", $value, "id", $forumid);
1155 function forum_is_forcesubscribed($forumid) {
1156 return get_field("forum", "forcesubscribe", "id", $forumid);
1159 function forum_is_subscribed($userid, $forumid) {
1160 if (forum_is_forcesubscribed($forumid)) {
1163 return record_exists_sql("SELECT * FROM forum_subscriptions WHERE user='$userid' AND forum='$forumid'");
1166 function forum_subscribed_users($course, $forum) {
1167 // Returns list of user objects that are subscribed to this forum
1169 if ($course->category) { // normal course
1170 if ($forum->forcesubscribe) {
1171 return get_course_users($course->id);
1174 return get_records_sql("SELECT u.* FROM user u, forum_subscriptions s
1175 WHERE s.forum = '$forum->id'
1176 AND s.user = u.id AND u.deleted <> '1'");
1179 function forum_subscribe($userid, $forumid) {
1182 return $db->Execute("INSERT INTO forum_subscriptions SET user = '$userid', forum = '$forumid'");
1185 function forum_unsubscribe($userid, $forumid) {
1188 return $db->Execute("DELETE FROM forum_subscriptions WHERE user = '$userid' AND forum = '$forumid'");
1192 function forum_user_has_posted_discussion($forumid, $userid) {
1193 if ($discussions = forum_get_discussions($forumid, "DESC", $userid)) {
1200 function forum_user_can_post_discussion($forum) {
1201 // $forum is an object
1204 if ($forum->type == "eachuser") {
1205 return (! forum_user_has_posted_discussion($forum->id, $USER->id));
1206 } else if ($forum->type == "teacher") {
1207 return isteacher($forum->course);
1208 } else if (isteacher($forum->course)) {
1211 return ($forum->open == 2);
1215 function forum_user_can_post($forum, $user=NULL) {
1216 // $forum, $user are objects
1219 $isteacher = isteacher($forum->course, $user->id);
1221 $isteacher = isteacher($forum->course);
1224 if ($forum->type == "teacher") {
1226 } else if ($isteacher) {
1229 return $forum->open;
1233 function forum_get_discussions($forum="0", $forum_sort="DESC", $user=0) {
1235 $userselect = " AND u.id = '$user' ";
1239 return get_records_sql("SELECT p.*, u.firstname, u.lastname, u.email, u.picture, u.id as userid
1240 FROM forum_discussions d, forum_posts p, user u
1241 WHERE d.forum = '$forum' AND p.discussion = d.id AND
1242 p.parent= 0 AND p.user = u.id $userselect
1243 ORDER BY p.created $forum_sort");
1248 function forum_print_latest_discussions($forum_id=0, $forum_numdiscussions=5, $forum_style="plain", $forum_sort="DESC") {
1252 if (! $forum = get_record("forum", "id", $forum_id)) {
1253 error("Forum ID was incorrect");
1255 if (! $course = get_record("course", "id", $forum->course)) {
1256 error("Could not find the course this forum belongs to!");
1259 if ($course->category) {
1260 require_login($course->id);
1264 if (! $course = get_record("course", "category", 0)) {
1265 error("Could not find a top-level course!");
1267 if (! $forum = forum_get_course_forum($course->id, "news")) {
1268 error("Could not find or create a main forum in this course (id $course->id)");
1272 if (forum_user_can_post_discussion($forum)) {
1273 echo "<P ALIGN=CENTER>";
1274 echo "<A HREF=\"$CFG->wwwroot/mod/forum/post.php?forum=$forum->id\">";
1275 echo get_string("addanewdiscussion", "forum")."</A>...";
1279 if (! $discussions = forum_get_discussions($forum->id, $forum_sort) ) {
1280 echo "<P ALIGN=CENTER><B>(".get_string("nodiscussions", "forum").")</B></P>";
1285 if ((!$forum_numdiscussions) && ($forum_style == "plain") && (count($discussions) > FORUM_MANY_DISCUSSIONS) ) {
1286 $forum_style = "header"; // Abbreviate display if it's going to be long.
1289 $replies = forum_count_discussion_replies($forum->id);
1291 $canreply = forum_user_can_post($forum);
1293 $discussioncount = 0;
1295 foreach ($discussions as $discussion) {
1298 if ($forum_numdiscussions && ($discussioncount > $forum_numdiscussions)) {
1299 echo "<P ALIGN=right><A HREF=\"$CFG->wwwroot/mod/forum/view.php?f=$forum->id\">";
1300 echo get_string("olderdiscussions", "forum")."</A> ...</P>";
1303 if ($replies[$discussion->discussion]) {
1304 $discussion->replies = $replies[$discussion->discussion]->replies;
1306 $discussion->replies = 0;
1308 $ownpost = ($discussion->userid == $USER->id);
1309 switch ($forum_style) {
1311 echo "<P><FONT COLOR=#555555>".userdate($discussion->modified, "%e %b, %H:%M")." - $discussion->firstname</FONT>";
1312 echo "<BR>$discussion->subject ";
1313 echo "<A HREF=\"$CFG->wwwroot/mod/forum/discuss.php?d=$discussion->discussion\">";
1314 echo get_string("more", "forum")."...</A>";
1318 forum_print_post_header($discussion, $forum->course, $ownpost, $reply=0, $link=1, $assessed=false);
1321 if ($canreply or $discussion->replies) {
1326 forum_print_post($discussion, $forum->course, $ownpost, $reply=0, $link, $assessed=false);
1333 function forum_print_discussion($course, $forum, $discussion, $post, $mode) {
1337 $ownpost = ($USER->id == $post->user);
1338 $reply = forum_user_can_post($forum);
1340 forum_print_post($post, $course->id, $ownpost, $reply, $link=false, $rate=false);
1342 forum_print_mode_form($discussion->id, $mode);
1344 $ratingform = false;
1345 if ($forum->assessed && $USER->id) {
1346 $unrated = forum_count_unrated_posts($discussion->id, $USER->id);
1353 echo "<FORM NAME=form METHOD=POST ACTION=rate.php>";
1354 echo "<INPUT TYPE=hidden NAME=id VALUE=\"$course->id\">";
1358 case 1 : // Flat ascending
1359 case -1 : // Flat descending
1362 forum_print_posts_flat($post->discussion, $course->id, $mode, $forum->assessed, $reply);
1366 case 2 : // Threaded
1367 forum_print_posts_threaded($post->id, $course->id, 0, $forum->assessed, $reply);
1371 forum_print_posts_nested($post->id, $course->id, $forum->assessed, $reply);
1376 echo "<CENTER><P ALIGN=center><INPUT TYPE=submit VALUE=\"".get_string("sendinratings", "forum")."\">";
1377 helpbutton("ratings", get_string("separateandconnected"), "forum");
1378 echo "</P></CENTER>";
1383 function forum_print_posts_flat($discussion, $course, $direction, $assessed, $reply) {
1388 if ($direction < 0) {
1389 $sort = "ORDER BY created DESC";
1391 $sort = "ORDER BY created ASC";
1394 if ($posts = get_records_sql("SELECT p.*, u.id as userid, u.firstname, u.lastname, u.email, u.picture
1395 FROM forum_posts p, user u
1396 WHERE p.discussion = $discussion AND p.parent > 0 AND p.user = u.id $sort")) {
1398 foreach ($posts as $post) {
1399 $ownpost = ($USER->id == $post->user);
1400 forum_print_post($post, $course, $ownpost, $reply, $link, $assessed);
1407 function forum_print_posts_threaded($parent, $course, $depth, $assessed, $reply) {
1412 if ($posts = get_records_sql("SELECT p.*, u.id as userid, u.firstname, u.lastname, u.email, u.picture
1413 FROM forum_posts p, user u
1414 WHERE p.parent = '$parent' AND p.user = u.id")) {
1416 foreach ($posts as $post) {
1420 $ownpost = ($USER->id == $post->user);
1421 forum_print_post($post, $course, $ownpost, $reply, $link, $assessed); // link=true?
1424 $by->name = "$post->firstname $post->lastname";
1425 $by->date = userdate($post->created);
1426 echo "<LI><P><FONT SIZE=-1><B><A HREF=\"discuss.php?d=$post->discussion&parent=$post->id\">$post->subject</A></B> ";
1427 print_string("bynameondate", "forum", $by);
1428 echo "</FONT></P></LI>";
1431 forum_print_posts_threaded($post->id, $course, $depth-1, $assessed, $reply);
1439 function forum_print_posts_nested($parent, $course, $assessed, $reply) {
1444 if ($posts = get_records_sql("SELECT p.*, u.id as userid, u.firstname, u.lastname, u.email, u.picture
1445 FROM forum_posts p, user u
1446 WHERE p.parent = $parent AND p.user = u.id
1447 ORDER BY p.created ASC ")) {
1449 foreach ($posts as $post) {
1451 $ownpost = ($USER->id == $post->user);
1454 forum_print_post($post, $course, $ownpost, $reply, $link, $assessed);
1456 forum_print_posts_nested($post->id, $course, $assessed, $reply);
1464 function forum_set_display_mode($mode=0) {
1465 global $USER, $FORUM_DEFAULT_DISPLAY_MODE;
1468 $USER->mode = $mode;
1469 save_session("USER");
1470 } else if (!$USER->mode) {
1471 $USER->mode = $FORUM_DEFAULT_DISPLAY_MODE;
1472 save_session("USER");