3 require_once("$CFG->dirroot/files/mimetypes.php");
5 /// CONSTANTS ///////////////////////////////////////////////////////////
7 define("FORUM_MODE_FLATOLDEST", 1);
8 define("FORUM_MODE_FLATNEWEST", -1);
9 define("FORUM_MODE_THREADED", 2);
10 define("FORUM_MODE_NESTED", 3);
12 $FORUM_LAYOUT_MODES = array ( FORUM_MODE_FLATOLDEST
=> get_string("modeflatoldestfirst", "forum"),
13 FORUM_MODE_FLATNEWEST
=> get_string("modeflatnewestfirst", "forum"),
14 FORUM_MODE_THREADED
=> get_string("modethreaded", "forum"),
15 FORUM_MODE_NESTED
=> get_string("modenested", "forum") );
17 // These are course content forums that can be added to the course manually
18 $FORUM_TYPES = array ("general" => get_string("generalforum", "forum"),
19 "eachuser" => get_string("eachuserforum", "forum"),
20 "single" => get_string("singleforum", "forum") );
22 $FORUM_OPEN_MODES = array ("2" => get_string("openmode2", "forum"),
23 "1" => get_string("openmode1", "forum"),
24 "0" => get_string("openmode0", "forum") );
26 if (!isset($CFG->forum_displaymode
)) {
27 set_config("forum_displaymode", FORUM_MODE_NESTED
);
30 if (!isset($CFG->forum_shortpost
)) {
31 set_config("forum_shortpost", 300); // Less non-HTML characters than this is short
34 if (!isset($CFG->forum_longpost
)) {
35 set_config("forum_longpost", 600); // More non-HTML characters than this is long
38 if (!isset($CFG->forum_manydiscussions
)) {
39 set_config("forum_manydiscussions", 100); // Number of discussions on a page
42 if (!isset($CFG->forum_maxbytes
)) {
43 set_config("forum_maxbytes", 512000); // Default maximum size for all forums
48 /// STANDARD FUNCTIONS ///////////////////////////////////////////////////////////
50 function forum_add_instance($forum) {
51 // Given an object containing all the necessary data,
52 // (defined by the form in mod.html) this function
53 // will create a new instance and return the id number
54 // of the new instance.
58 $forum->timemodified
= time();
60 if (! $forum->id
= insert_record("forum", $forum)) {
64 if (!$forum->userating
) {
68 if (!empty($forum->ratingtime
)) {
69 $forum->assesstimestart
= make_timestamp($forum->startyear
, $forum->startmonth
, $forum->startday
,
70 $forum->starthour
, $forum->startminute
, 0);
71 $forum->assesstimefinish
= make_timestamp($forum->finishyear
, $forum->finishmonth
, $forum->finishday
,
72 $forum->finishhour
, $forum->finishminute
, 0);
74 $forum->assesstimestart
= 0;
75 $forum->assesstimefinish
= 0;
78 if ($forum->type
== "single") { // Create related discussion.
79 $discussion->course
= $forum->course
;
80 $discussion->forum
= $forum->id
;
81 $discussion->name
= $forum->name
;
82 $discussion->intro
= $forum->intro
;
83 $discussion->assessed
= $forum->assessed
;
85 if (! forum_add_discussion($discussion)) {
86 error("Could not add the discussion for this forum");
94 function forum_update_instance($forum) {
95 // Given an object containing all the necessary data,
96 // (defined by the form in mod.html) this function
97 // will update an existing instance with new data.
99 $forum->timemodified
= time();
100 $forum->id
= $forum->instance
;
102 if (!$forum->userating
) {
103 $forum->assessed
= 0;
106 if (!empty($forum->ratingtime
)) {
107 $forum->assesstimestart
= make_timestamp($forum->startyear
, $forum->startmonth
, $forum->startday
,
108 $forum->starthour
, $forum->startminute
, 0);
109 $forum->assesstimefinish
= make_timestamp($forum->finishyear
, $forum->finishmonth
, $forum->finishday
,
110 $forum->finishhour
, $forum->finishminute
, 0);
112 $forum->assesstimestart
= 0;
113 $forum->assesstimefinish
= 0;
116 if ($forum->type
== "single") { // Update related discussion and post.
117 if (! $discussion = get_record("forum_discussions", "forum", $forum->id
)) {
118 if ($discussions = get_records("forum_discussions", "forum", $forum->id
, "timemodified ASC")) {
119 notify("Warning! There is more than one discussion in this forum - using the most recent");
120 $discussion = array_pop($discussions);
122 error("Could not find the discussion in this forum");
125 if (! $post = get_record("forum_posts", "id", $discussion->firstpost
)) {
126 error("Could not find the first post in this forum discussion");
129 $post->subject
= $forum->name
;
130 $post->message
= $forum->intro
;
131 $post->modified
= $forum->timemodified
;
133 if (! update_record("forum_posts", $post)) {
134 error("Could not update the first post");
137 $discussion->name
= $forum->name
;
139 if (! update_record("forum_discussions", $discussion)) {
140 error("Could not update the discussion");
144 return update_record("forum", $forum);
148 function forum_delete_instance($id) {
149 // Given an ID of an instance of this module,
150 // this function will permanently delete the instance
151 // and any data that depends on it.
153 if (! $forum = get_record("forum", "id", "$id")) {
159 if ($discussions = get_records("forum_discussions", "forum", $forum->id
)) {
160 foreach ($discussions as $discussion) {
161 if (! forum_delete_discussion($discussion)) {
167 if (! delete_records("forum_subscriptions", "forum", "$forum->id")) {
171 if (! delete_records("forum", "id", "$forum->id")) {
179 function forum_cron () {
180 /// Function to be run periodically according to the moodle cron
181 /// Finds all posts that have yet to be mailed out, and mails them
182 /// out to all subscribers
186 if (!empty($USER)) { // Remember real USER account if necessary
190 $cutofftime = time() - $CFG->maxeditingtime
;
192 if ($posts = forum_get_unmailed_posts($cutofftime)) {
194 /// Mark them all now as being mailed. It's unlikely but possible there
195 /// might be an error later so that a post is NOT actually mailed out,
196 /// but since mail isn't crucial, we can accept this risk. Doing it now
197 /// prevents the risk of duplicated mails, which is a worse problem.
199 foreach ($posts as $key => $post) {
200 if (! set_field("forum_posts", "mailed", "1", "id", "$post->id")) {
201 echo "Error marking post id post->id as being mailed. This post will not be mailed.\n";
208 foreach ($posts as $post) {
211 print_string("processingpost", "forum", $post->id
);
214 if (! $userfrom = get_record("user", "id", "$post->userid")) {
215 echo "Could not find user $post->userid\n";
219 if (! $discussion = get_record("forum_discussions", "id", "$post->discussion")) {
220 echo "Could not find discussion $post->discussion\n";
224 if (! $forum = get_record("forum", "id", "$discussion->forum")) {
225 echo "Could not find forum $discussion->forum\n";
229 if (! $course = get_record("course", "id", "$forum->course")) {
230 echo "Could not find course $forum->course\n";
234 if (!empty($course->lang
)) {
235 $CFG->courselang
= $course->lang
;
237 unset($CFG->courselang
);
241 if ($cm = get_coursemodule_from_instance("forum", $forum->id
, $course->id
)) {
242 if ($groupmode = groupmode($course, $cm)) { // Groups are being used
243 if (!$group = get_record("groups", "id", $discussion->groupid
)) { // Can't find group
244 continue; // Be safe and don't send it to anyone
252 if ($users = forum_subscribed_users($course, $forum)) {
253 $canunsubscribe = ! forum_is_forcesubscribed($forum->id
);
257 foreach ($users as $userto) {
258 if ($groupmode) { // Look for a reason not to send this email
259 if (!isteacheredit($course->id
, $userto->id
)) {
260 if (!ismember($group->id
, $userto->id
)) {
266 /// GWD: reset timelimit so that script does not get timed out when posting to many users
269 /// Override the language and timezone of the "current" user, so that
270 /// mail is customised for the receiver.
271 $USER->lang
= $userto->lang
;
272 $USER->timezone
= $userto->timezone
;
274 $canreply = forum_user_can_post($forum, $userto);
276 $by->name
= fullname($userfrom, isteacher($course->id
, $userto->id
));
277 $by->date
= userdate($post->modified
, "", $userto->timezone
);
278 $strbynameondate = get_string("bynameondate", "forum", $by);
280 $strforums = get_string("forums", "forum");
282 $postsubject = "$course->shortname: $post->subject";
283 $posttext = "$course->shortname -> $strforums -> $forum->name";
285 if ($discussion->name
== $forum->name
) {
288 $posttext .= " -> $discussion->name\n";
290 $posttext .= "---------------------------------------------------------------------\n";
291 $posttext .= "$post->subject\n";
292 $posttext .= $strbynameondate."\n";
293 $posttext .= "---------------------------------------------------------------------\n";
294 $posttext .= format_text_email($post->message
, $post->format
);
296 if ($post->attachment
) {
297 $post->course
= $course->id
;
298 $post->forum
= $forum->id
;
299 $posttext .= forum_print_attachments($post, "text");
302 $posttext .= "---------------------------------------------------------------------\n";
303 $posttext .= get_string("postmailinfo", "forum", $course->shortname
)."\n";
304 $posttext .= "$CFG->wwwroot/mod/forum/post.php?reply=$post->id\n";
306 if ($canunsubscribe) {
307 $posttext .= "\n---------------------------------------------------------------------\n";
308 $posttext .= get_string("unsubscribe", "forum");
309 $posttext .= ": $CFG->wwwroot/mod/forum/subscribe.php?id=$forum->id\n";
312 if ($userto->mailformat
== 1) { // HTML
313 $posthtml = "<p><font face=\"sans-serif\">".
314 "<a target=\"_blank\" href=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</a> -> ".
315 "<a target=\"_blank\" href=\"$CFG->wwwroot/mod/forum/index.php?id=$course->id\">$strforums</a> -> ".
316 "<a target=\"_blank\" href=\"$CFG->wwwroot/mod/forum/view.php?f=$forum->id\">$forum->name</a>";
317 if ($discussion->name
== $forum->name
) {
318 $posthtml .= "</font></p>";
320 $posthtml .= " -> <a target=\"_blank\" href=\"$CFG->wwwroot/mod/forum/discuss.php?d=$discussion->id\">$discussion->name</a></font></p>";
322 $posthtml .= forum_make_mail_post($post, $userfrom, $userto, $course, false, $canreply, false, false);
324 if ($canunsubscribe) {
325 $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>";
332 if (! email_to_user($userto, $userfrom, $postsubject, $posttext, $posthtml)) {
333 echo "Error: mod/forum/cron.php: Could not send out mail for id $post->id to user $userto->id ($userto->email) .. not trying again.\n";
334 add_to_log($course->id
, 'forum', 'mail error', "discuss.php?d=$discussion->id#$post->id", substr($post->subject
,0,15), $cm->id
, $userto->id
);
341 echo ".... mailed to $mailcount users.\n";
343 set_field("forum_posts", "mailed", "2", "id", "$post->id");
349 if (!empty($realuser)) { // Restore real USER if necessary
356 function forum_user_outline($course, $user, $mod, $forum) {
358 if ($posts = forum_get_user_posts($forum->id
, $user->id
)) {
359 $result->info
= get_string("numposts", "forum", count($posts));
361 $lastpost = array_pop($posts);
362 $result->time
= $lastpost->modified
;
369 function forum_user_complete($course, $user, $mod, $forum) {
372 if ($posts = forum_get_user_posts($forum->id
, $user->id
)) {
373 foreach ($posts as $post) {
374 forum_print_post($post, $course->id
, $ownpost=false, $reply=false, $link=false, $rate=false);
378 echo "<P>".get_string("noposts", "forum")."</P>";
382 function forum_print_recent_activity($course, $isteacher, $timestart) {
383 /// Given a course and a date, prints a summary of all the new
384 /// messages posted in the course since that date
391 if (!$logs = get_records_select("log", "time > '$timestart' AND ".
392 "course = '$course->id' AND ".
393 "module = 'forum' AND ".
394 "action LIKE 'add %' ", "time ASC")){
398 $strftimerecent = get_string("strftimerecent");
400 $isteacheredit = isteacheredit($course->id
);
401 $mygroupid = mygroupid($course->id
);
403 $groupmode = array(); /// To cache group modes
405 foreach ($logs as $log) {
406 //Get post info, I'll need it later
407 $post = forum_get_post_from_log($log);
409 //Create a temp valid module structure (course,id)
410 $tempmod->course
= $log->course
;
411 $tempmod->id
= $post->forum
;
412 //Obtain the visible property from the instance
413 $modvisible = instance_is_visible($log->module
, $tempmod);
415 //Only if the mod is visible
418 /// Check whether this is for teachers only
420 if ($forum = get_record("forum", "id", $post->forum
)) {
421 if ($forum->type
== "teacher") {
423 $teacheronly = "class=\"teacheronly\"";
429 /// Check whether this is belongs to a discussion in a group that
430 /// should NOT be accessible to the current user
432 if (!$isteacheredit) { /// Because editing teachers can see everything anyway
433 if (!isset($cm[$post->forum
])) {
434 $cm[$forum->id
] = get_coursemodule_from_instance("forum", $forum->id
, $course->id
);
435 $groupmode[$forum->id
] = groupmode($course, $cm[$forum->id
]);
437 if ($groupmode[$forum->id
]) {
438 if ($mygroupid != $post->groupid
) {
445 print_headline(get_string("newforumposts", "forum").":");
449 $date = userdate($post->modified
, $strftimerecent);
450 $fullname = fullname($post, $isteacher);
451 echo "<p $teacheronly><font size=1>$date - $fullname<br>";
452 echo "\"<a href=\"$CFG->wwwroot/mod/forum/$log->url\">";
453 if (!empty($CFG->filterall
)) {
454 $post->subject
= filter_text($post->subject
, $course->id
);
456 if ($log->action
== "add discussion") {
457 echo "<b>$post->subject</b>";
459 echo "$post->subject";
461 echo "</a>\"</font></p>";
470 function forum_grades($forumid) {
471 /// Must return an array of grades, indexed by user, and a max grade.
473 if (!$forum = get_record("forum", "id", $forumid)) {
476 if (!$forum->assessed
) {
479 $scalemenu = make_grades_menu($forum->scale
);
482 $ratingsuser = array();
484 if ($ratings = forum_get_user_grades($forumid)) {
485 foreach ($ratings as $rating) { // Ordered by user
486 if ($currentuser and $rating->userid
!= $currentuser) {
487 if (!empty($ratingsuser)) {
488 if ($forum->scale
< 0) {
489 $return->grades
[$currentuser] = forum_get_ratings_mean(0, $scalemenu, $ratingsuser);
490 $return->grades
[$currentuser] .= "<br />".forum_get_ratings_summary(0, $scalemenu, $ratingsuser);
494 foreach ($ratingsuser as $ra) {
498 $return->grades
[$currentuser] = format_float($total/$count, 2);
501 $return->grades
[$currentuser] = "";
503 $ratingsuser = array();
505 $ratingsuser[] = $rating->rating
;
506 $currentuser = $rating->userid
;
508 if (!empty($ratingsuser)) {
509 if ($forum->scale
< 0) {
510 $return->grades
[$currentuser] = forum_get_ratings_mean(0, $scalemenu, $ratingsuser);
511 $return->grades
[$currentuser] .= "<br />".forum_get_ratings_summary(0, $scalemenu, $ratingsuser);
515 foreach ($ratingsuser as $ra) {
519 $return->grades
[$currentuser] = format_float((float)$total/(float)$count, 2);
522 $return->grades
[$currentuser] = "";
525 $return->grades
= array();
528 if ($forum->scale
< 0) {
529 $return->maxgrade
= "";
531 $return->maxgrade
= $forum->scale
;
536 function forum_get_participants($forumid) {
537 //Returns the users with data in one forum
538 //(users with records in forum_subscriptions, forum_posts and forum_ratings, students)
542 //Get students from forum_subscriptions
543 $st_subscriptions = get_records_sql("SELECT DISTINCT u.*
544 FROM {$CFG->prefix}user u,
545 {$CFG->prefix}forum_subscriptions s
546 WHERE s.forum = '$forumid' and
548 //Get students from forum_posts
549 $st_posts = get_records_sql("SELECT DISTINCT u.*
550 FROM {$CFG->prefix}user u,
551 {$CFG->prefix}forum_discussions d,
552 {$CFG->prefix}forum_posts p
553 WHERE d.forum = '$forumid' and
554 p.discussion = d.id and
557 //Get students from forum_ratings
558 $st_ratings = get_records_sql("SELECT DISTINCT u.*
559 FROM {$CFG->prefix}user u,
560 {$CFG->prefix}forum_discussions d,
561 {$CFG->prefix}forum_posts p,
562 {$CFG->prefix}forum_ratings r
563 WHERE d.forum = '$forumid' and
564 p.discussion = d.id and
568 //Add st_posts to st_subscriptions
570 foreach ($st_posts as $st_post) {
571 $st_subscriptions[$st_post->id
] = $st_post;
574 //Add st_ratings to st_subscriptions
576 foreach ($st_ratings as $st_rating) {
577 $st_subscriptions[$st_rating->id
] = $st_rating;
580 //Return st_subscriptions array (it contains an array of unique users)
581 return ($st_subscriptions);
584 /// SQL FUNCTIONS ///////////////////////////////////////////////////////////
586 function forum_get_post_full($postid) {
587 /// Gets a post with all info ready for forum_print_post
590 return get_record_sql("SELECT p.*, u.firstname, u.lastname, u.email, u.picture
591 FROM {$CFG->prefix}forum_posts p,
593 WHERE p.id = '$postid'
594 AND p.userid = u.id");
597 function forum_get_discussion_posts($discussion, $sort) {
598 /// Gets posts with all info ready for forum_print_post
601 return get_records_sql("SELECT p.*, u.firstname, u.lastname, u.email, u.picture
602 FROM {$CFG->prefix}forum_posts p,
604 WHERE p.discussion = $discussion
606 AND p.userid = u.id $sort");
609 function forum_get_child_posts($parent) {
610 /// Gets posts with all info ready for forum_print_post
613 return get_records_sql("SELECT p.*, u.firstname, u.lastname, u.email, u.picture
614 FROM {$CFG->prefix}forum_posts p,
616 WHERE p.parent = '$parent'
618 ORDER BY p.created ASC");
622 function forum_search_posts($searchterms, $courseid, $page=0, $recordsperpage=50, &$totalcount) {
623 /// Returns a list of posts found using an array of search terms
624 /// eg word +word -word
629 if (!isteacher($courseid)) {
630 $notteacherforum = "AND f.type <> 'teacher'";
632 $forummodule = get_record("modules", "name", "forum");
633 $onlyvisible = " AND f.id = cm.instance AND cm.visible = 1 AND cm.module = $forummodule->id";
634 $onlyvisibletable = ", {$CFG->prefix}course_modules cm";
636 $notteacherforum = "";
639 $onlyvisibletable = "";
642 switch ($CFG->dbtype
) {
644 $limit = "LIMIT $page,$recordsperpage";
647 $limit = "LIMIT $recordsperpage OFFSET ".($page * $recordsperpage);
650 $limit = "LIMIT $recordsperpage,$page";
653 /// Some differences in syntax for PostgreSQL
654 if ($CFG->dbtype
== "postgres7") {
655 $LIKE = "ILIKE"; // case-insensitive
656 $NOTLIKE = "NOT ILIKE"; // case-insensitive
661 $NOTLIKE = "NOT LIKE";
663 $NOTREGEXP = "NOT REGEXP";
670 foreach ($searchterms as $searchterm) {
671 if (strlen($searchterm) < 2) {
674 if ($messagesearch) {
675 $messagesearch .= " AND ";
677 if ($subjectsearch) {
678 $subjectsearch .= " AND ";
681 if (substr($searchterm,0,1) == "+") {
682 $searchterm = substr($searchterm,1);
683 $messagesearch .= " p.message $REGEXP '(^|[^a-zA-Z0-9])$searchterm([^a-zA-Z0-9]|$)' ";
684 $subjectsearch .= " p.subject $REGEXP '(^|[^a-zA-Z0-9])$searchterm([^a-zA-Z0-9]|$)' ";
685 } else if (substr($searchterm,0,1) == "-") {
686 $searchterm = substr($searchterm,1);
687 $messagesearch .= " p.message $NOTREGEXP '(^|[^a-zA-Z0-9])$searchterm([^a-zA-Z0-9]|$)' ";
688 $subjectsearch .= " p.subject $NOTREGEXP '(^|[^a-zA-Z0-9])$searchterm([^a-zA-Z0-9]|$)' ";
690 $messagesearch .= " p.message $LIKE '%$searchterm%' ";
691 $subjectsearch .= " p.subject $LIKE '%$searchterm%' ";
695 $selectsql = "{$CFG->prefix}forum_posts p,
696 {$CFG->prefix}forum_discussions d,
697 {$CFG->prefix}user u,
698 {$CFG->prefix}forum f $onlyvisibletable
699 WHERE ($messagesearch OR $subjectsearch)
701 AND p.discussion = d.id
702 AND d.course = '$courseid'
703 AND d.forum = f.id $notteacherforum $onlyvisible";
705 $totalcount = count_records_sql("SELECT COUNT(*) FROM $selectsql");
707 return get_records_sql("SELECT p.*,u.firstname,u.lastname,u.email,u.picture FROM
708 $selectsql ORDER BY p.modified DESC $limit");
712 function forum_get_ratings($postid, $sort="u.firstname ASC") {
713 /// Returns a list of ratings for a particular post - sorted.
715 return get_records_sql("SELECT u.*, r.rating, r.time
716 FROM {$CFG->prefix}forum_ratings r,
718 WHERE r.post = '$postid'
723 function forum_get_unmailed_posts($cutofftime) {
724 /// Returns a list of all new posts that have not been mailed yet
726 return get_records_sql("SELECT p.*, d.course
727 FROM {$CFG->prefix}forum_posts p,
728 {$CFG->prefix}forum_discussions d
730 AND p.created < '$cutofftime'
731 AND p.discussion = d.id");
734 function forum_get_user_posts($forumid, $userid) {
735 /// Get all the posts for a user in a forum suitable for forum_print_post
738 return get_records_sql("SELECT p.*, u.firstname, u.lastname, u.email, u.picture
739 FROM {$CFG->prefix}forum f,
740 {$CFG->prefix}forum_discussions d,
741 {$CFG->prefix}forum_posts p,
743 WHERE f.id = '$forumid'
745 AND p.discussion = d.id
746 AND p.userid = '$userid'
748 ORDER BY p.modified ASC");
751 function forum_get_post_from_log($log) {
752 /// Given a log entry, return the forum post details for it.
755 if ($log->action
== "add post") {
757 return get_record_sql("SELECT p.*, d.forum, d.groupid, u.firstname, u.lastname, u.email, u.picture
758 FROM {$CFG->prefix}forum_discussions d,
759 {$CFG->prefix}forum_posts p,
761 WHERE p.id = '$log->info'
762 AND d.id = p.discussion
764 AND u.deleted <> '1'");
767 } else if ($log->action
== "add discussion") {
769 return get_record_sql("SELECT p.*, d.forum, d.groupid, u.firstname, u.lastname, u.email, u.picture
770 FROM {$CFG->prefix}forum_discussions d,
771 {$CFG->prefix}forum_posts p,
773 WHERE d.id = '$log->info'
774 AND d.firstpost = p.id
776 AND u.deleted <> '1'");
781 function forum_get_firstpost_from_discussion($discussionid) {
782 /// Given a discussion id, return the first post from the discussion
785 return get_record_sql("SELECT p.*
786 FROM {$CFG->prefix}forum_discussions d,
787 {$CFG->prefix}forum_posts p
788 WHERE d.id = '$discussionid'
789 AND d.firstpost = p.id ");
793 function forum_get_user_grades($forumid) {
794 /// Get all user grades for a forum
797 return get_records_sql("SELECT r.id, p.userid, r.rating
798 FROM {$CFG->prefix}forum_discussions d,
799 {$CFG->prefix}forum_posts p,
800 {$CFG->prefix}forum_ratings r
801 WHERE d.forum = '$forumid'
802 AND p.discussion = d.id
804 ORDER by p.userid ");
808 function forum_count_discussion_replies($forum="0") {
809 // Returns an array of counts of replies to each discussion (optionally in one forum)
813 $forumselect = " AND d.forum = '$forum'";
815 return get_records_sql("SELECT p.discussion, (count(*)) as replies
816 FROM {$CFG->prefix}forum_posts p,
817 {$CFG->prefix}forum_discussions d
819 AND p.discussion = d.id
820 GROUP BY p.discussion");
823 function forum_count_unrated_posts($discussionid, $userid) {
824 // How many unrated posts are in the given discussion for a given user?
826 if ($posts = get_record_sql("SELECT count(*) as num
827 FROM {$CFG->prefix}forum_posts
829 AND discussion = '$discussionid'
830 AND userid <> '$userid' ")) {
832 if ($rated = get_record_sql("SELECT count(*) as num
833 FROM {$CFG->prefix}forum_posts p,
834 {$CFG->prefix}forum_ratings r
835 WHERE p.discussion = '$discussionid'
837 AND r.userid = '$userid'")) {
838 $difference = $posts->num
- $rated->num
;
839 if ($difference > 0) {
842 return 0; // Just in case there was a counting error
852 function forum_get_discussions($forum="0", $forumsort="d.timemodified DESC",
853 $user=0, $fullpost=true, $currentgroup=0) {
854 /// Get all discussions in a forum
858 $userselect = " AND u.id = '$user' ";
863 $groupselect = " AND d.groupid = '$currentgroup' ";
867 if (empty($forumsort)) {
868 $forumsort = "d.timemodified DESC";
870 if (empty($fullpost)) {
871 $postdata = "p.id,p.subject,p.modified,p.discussion,p.userid";
876 return get_records_sql("SELECT $postdata, d.timemodified, d.usermodified,
877 u.firstname, u.lastname, u.email, u.picture
878 FROM {$CFG->prefix}forum_discussions d,
879 {$CFG->prefix}forum_posts p,
881 WHERE d.forum = '$forum'
882 AND p.discussion = d.id
884 AND p.userid = u.id $groupselect $userselect
885 ORDER BY $forumsort");
890 function forum_get_user_discussions($courseid, $userid) {
891 /// Get all discussions started by a particular user in a course
894 return get_records_sql("SELECT p.*, u.firstname, u.lastname, u.email, u.picture,
895 f.type as forumtype, f.name as forumname, f.id as forumid
896 FROM {$CFG->prefix}forum_discussions d,
897 {$CFG->prefix}forum_posts p,
898 {$CFG->prefix}user u,
899 {$CFG->prefix}forum f
900 WHERE d.course = '$courseid'
901 AND p.discussion = d.id
906 ORDER BY p.created DESC");
910 function forum_subscribed_users($course, $forum) {
911 /// Returns list of user objects that are subscribed to this forum
914 if ($forum->forcesubscribe
) {
915 if ($course->category
) {
916 if ($forum->type
== "teacher") {
917 return get_course_teachers($course->id
); // Only teachers can be subscribed to teacher forums
919 return get_course_users($course->id
); // Otherwise get everyone in the course
922 return get_site_users();
925 return get_records_sql("SELECT u.id, u.username, u.firstname, u.lastname, u.maildisplay, u.mailformat, u.emailstop,
926 u.email, u.city, u.country, u.lastaccess, u.lastlogin, u.picture, u.timezone, u.lang
927 FROM {$CFG->prefix}user u,
928 {$CFG->prefix}forum_subscriptions s
929 WHERE s.forum = '$forum->id'
932 ORDER BY u.email ASC");
935 /// OTHER FUNCTIONS ///////////////////////////////////////////////////////////
938 function forum_get_course_forum($courseid, $type) {
939 // How to set up special 1-per-course forums
942 if ($forums = get_records_select("forum", "course = '$courseid' AND type = '$type'", "id ASC")) {
943 // There should always only be ONE, but with the right combination of
944 // errors there might be more. In this case, just return the oldest one (lowest ID).
945 foreach ($forums as $forum) {
946 return $forum; // ie the first one
950 // Doesn't exist, so create one now.
951 $forum->course
= $courseid;
952 $forum->type
= "$type";
953 switch ($forum->type
) {
955 $forum->name
= addslashes(get_string("namenews", "forum"));
956 $forum->intro
= addslashes(get_string("intronews", "forum"));
957 $forum->forcesubscribe
= 1;
958 $forum->open
= 1; // 0 - no, 1 - posts only, 2 - discuss and post
959 $forum->assessed
= 0;
960 if ($site = get_site()) {
961 if ($courseid == $site->id
) {
962 $forum->name
= get_string("sitenews");
963 $forum->forcesubscribe
= 0;
968 $forum->name
= addslashes(get_string("namesocial", "forum"));
969 $forum->intro
= addslashes(get_string("introsocial", "forum"));
970 $forum->open
= 2; // 0 - no, 1 - posts only, 2 - discuss and post
971 $forum->assessed
= 0;
972 $forum->forcesubscribe
= 0;
975 $forum->name
= addslashes(get_string("nameteacher", "forum"));
976 $forum->intro
= addslashes(get_string("introteacher", "forum"));
977 $forum->open
= 0; // 0 - no, 1 - posts only, 2 - discuss and post
978 $forum->assessed
= 0;
979 $forum->forcesubscribe
= 0;
982 notify("That forum type doesn't exist!");
987 $forum->timemodified
= time();
988 $forum->id
= insert_record("forum", $forum);
990 if ($forum->type
!= "teacher") {
991 if (! $module = get_record("modules", "name", "forum")) {
992 notify("Could not find forum module!!");
995 $mod->course
= $courseid;
996 $mod->module
= $module->id
;
997 $mod->instance
= $forum->id
;
999 if (! $mod->coursemodule
= add_course_module($mod) ) { // assumes course/lib.php is loaded
1000 notify("Could not add a new course module to the course '$course->fullname'");
1003 if (! $sectionid = add_mod_to_section($mod) ) { // assumes course/lib.php is loaded
1004 notify("Could not add the new course module to that section");
1007 if (! set_field("course_modules", "section", $sectionid, "id", $mod->coursemodule
)) {
1008 notify("Could not update the course module with the correct section");
1011 include_once("$CFG->dirroot/course/lib.php");
1012 rebuild_course_cache($courseid);
1015 return get_record("forum", "id", "$forum->id");
1019 function forum_make_mail_post(&$post, $user, $touser, $course,
1020 $ownpost=false, $reply=false, $link=false, $rate=false, $footer="") {
1021 // Given the data about a posting, builds up the HTML to display it and
1022 // returns the HTML in a string. This is designed for sending via HTML email.
1024 global $THEME, $CFG;
1026 static $formattedtext; // Cached version of formatted text for a post
1027 static $formattedtextid; // The ID number of the post
1029 if (empty($formattedtextid) or $formattedtextid != $post->id
) { // Recalculate the formatting
1030 $formattedtext = format_text($post->message
, $post->format
, NULL, $course->id
);
1031 $formattedtextid = $post->id
;
1036 $output .= "<style> <!--"; /// Styles for autolinks
1037 $output .= "a.autolink:link {text-decoration: none; color: black; background-color: $THEME->autolink}\n";
1038 $output .= "a.autolink:visited {text-decoration: none; color: black; background-color: $THEME->autolink}\n";
1039 $output .= "a.autolink:hover {text-decoration: underline; color: red}\n";
1040 $output .= "--> </style>\n\n";
1042 if ($post->parent
) {
1043 $output .= '<table border="0" cellpadding="1" cellspacing="1"><tr><td bgcolor="#888888">';
1044 $output .= '<table border="0" cellpadding="3" cellspacing="0">';
1046 $output .= '<table border="0" cellpadding="1" cellspacing="1" width="100%"><tr><td bgcolor="#888888">';
1047 $output .= '<table border="0" cellpadding="3" cellspacing="0" width="100%">';
1050 $output .= "<tr><td bgcolor=\"$THEME->cellcontent2\" width=\"35\" valign=\"top\">";
1051 $output .= print_user_picture($user->id
, $course->id
, $user->picture
, false, true);
1054 if ($post->parent
) {
1055 $output .= "<td nowrap bgcolor=\"$THEME->cellheading\">";
1057 $output .= "<td nowrap bgcolor=\"$THEME->cellheading2\">";
1060 $output .= "<font size=3><b>$post->subject</b></font><br />";
1061 $output .= "<font size=2>";
1063 $fullname = fullname($user, isteacher($course->id
));
1064 $by->name
= "<a href=\"$CFG->wwwroot/user/view.php?id=$user->id&course=$course->id\">$fullname</a>";
1065 $by->date
= userdate($post->modified
, "", $touser->timezone
);
1066 $output .= get_string("bynameondate", "forum", $by);
1068 $output .= "</font></p></td></tr>";
1069 $output .= "<tr><td bgcolor=\"$THEME->cellcontent2\" width=10>";
1070 $output .= " ";
1071 $output .= "</td><td bgcolor=\"$THEME->cellcontent\">\n";
1073 if ($post->attachment
) {
1074 $post->course
= $course->id
;
1075 $post->forum
= get_field("forum_discussions", "forum", "id", $post->discussion
);
1076 $output .= "<div align=right>";
1077 $output .= forum_print_attachments($post, "html");
1078 $output .= "</div>";
1081 $output .= $formattedtext;
1083 $output .= "<p align=right><font size=-1>";
1085 if ($post->parent
) {
1086 $output .= "<a href=\"$CFG->wwwroot/mod/forum/discuss.php?d=$post->discussion&parent=$post->parent\">".get_string("parent", "forum")."</a> | ";
1089 $age = time() - $post->created
;
1091 $output .= "<a href=\"$CFG->wwwroot/mod/forum/post.php?delete=$post->id\">".get_string("delete", "forum")."</a>";
1093 $output .= " | <a target=\"_blank\" href=\"$CFG->wwwroot/mod/forum/post.php?reply=$post->id\">".get_string("replyforum", "forum")."</a>";
1095 $output .= " ";
1098 $output .= "<a target=\"_blank\" href=\"$CFG->wwwroot/mod/forum/post.php?reply=$post->id\">".get_string("replyforum", "forum")."</a> ";
1103 $output .= "<div align=right><p align=right>";
1106 if ($post->replies
== 1) {
1107 $replystring = get_string("repliesone", "forum", $post->replies
);
1109 $replystring = get_string("repliesmany", "forum", $post->replies
);
1111 $output .= "<a href=\"$CFG->wwwroot/mod/forum/discuss.php?d=$post->discussion\"><B>".get_string("discussthistopic", "forum")."</b></a> ($replystring) ";
1113 $output .= "</p></div>";
1115 $output .= "<p>$footer</p>";
1117 $output .= "</td></tr></table>\n";
1118 $output .= "</td></tr></table>\n\n";
1124 function forum_print_post(&$post, $courseid, $ownpost=false, $reply=false, $link=false,
1125 $ratings=NULL, $footer="", $highlight="") {
1127 global $THEME, $USER, $CFG;
1129 static $stredit, $strdelete, $strreply, $strparent, $threadedmode, $isteacher, $adminedit;
1131 if (empty($stredit)) {
1132 $stredit = get_string("edit", "forum");
1133 $strdelete = get_string("delete", "forum");
1134 $strreply = get_string("reply", "forum");
1135 $strparent = get_string("parent", "forum");
1136 $threadedmode = (!empty($USER->mode
) and ($USER->mode
== FORUM_MODE_THREADED
));
1137 $isteacher = isteacher($courseid);
1138 $adminedit = (isadmin() and !empty($CFG->admineditalways
));
1141 echo "<a name=\"$post->id\"></a>";
1142 if ($post->parent
) {
1143 echo '<table border="0" cellpadding="3" cellspacing="0" class="forumpost">';
1145 echo '<table border="0" cellpadding="3" cellspacing="0" class="forumpost" width="100%">';
1148 echo "<tr><td bgcolor=\"$THEME->cellcontent2\" class=\"forumpostpicture\" width=\"35\" valign=\"top\">";
1149 print_user_picture($post->userid
, $courseid, $post->picture
);
1152 if ($post->parent
) {
1153 echo "<td bgcolor=\"$THEME->cellheading\" class=\"forumpostheader\" width=\"100%\">";
1155 echo "<td bgcolor=\"$THEME->cellheading2\" class=\"forumpostheadertopic\" width=\"100%\">";
1158 if (!empty($CFG->filterall
)) { /// Put the subject through the filters
1159 $post->subject
= filter_text($post->subject
, $courseid);
1162 echo "<font size=3><b>$post->subject</b></font><br />";
1163 echo "<font size=2>";
1165 $fullname = fullname($post, $isteacher);
1166 $by->name
= "<a href=\"$CFG->wwwroot/user/view.php?id=$post->userid&course=$courseid\">$fullname</a>";
1167 $by->date
= userdate($post->modified
);
1168 print_string("bynameondate", "forum", $by);
1170 echo "</font></p></td></tr>";
1171 echo "<tr><td bgcolor=\"$THEME->cellcontent2\" valign=\"top\" class=\"forumpostside\" width=\"10\">";
1172 if ($group = user_group($courseid, $post->userid
)) {
1173 print_group_picture($group, $courseid, false, false, false);
1177 echo "</td><td bgcolor=\"$THEME->cellcontent\" class=\"forumpostmessage\">\n";
1179 if ($post->attachment
) {
1180 $post->course
= $courseid;
1181 $post->forum
= get_field("forum_discussions", "forum", "id", $post->discussion
);
1182 echo "<div align=\"right\">";
1183 $attachedimages = forum_print_attachments($post);
1186 $attachedimages = "";
1189 if ($link and (strlen(strip_tags($post->message
)) > $CFG->forum_longpost
)) {
1190 // Print shortened version
1191 echo format_text(forum_shorten_post($post->message
), $post->format
, NULL, $courseid);
1192 $numwords = count_words(strip_tags($post->message
));
1193 echo "<p><a href=\"$CFG->wwwroot/mod/forum/discuss.php?d=$post->discussion\">";
1194 echo get_string("readtherest", "forum");
1195 echo "</a> (".get_string("numwords", "", $numwords).")...</p>";
1197 // Print whole message
1199 echo highlight($highlight, format_text($post->message
, $post->format
, NULL, $courseid));
1201 echo format_text($post->message
, $post->format
, NULL, $courseid);
1203 echo $attachedimages;
1206 echo "<p align=right><font size=-1>";
1208 if ($post->parent
) {
1209 if ($threadedmode) {
1210 echo "<a href=\"$CFG->wwwroot/mod/forum/discuss.php?d=$post->discussion&parent=$post->parent\">$strparent</a> | ";
1212 echo "<a href=\"$CFG->wwwroot/mod/forum/discuss.php?d=$post->discussion#$post->parent\">$strparent</a> | ";
1216 $age = time() - $post->created
;
1217 if ($ownpost or $adminedit) {
1218 if (($age < $CFG->maxeditingtime
) or $adminedit) {
1219 echo "<a href=\"$CFG->wwwroot/mod/forum/post.php?edit=$post->id\">$stredit</a> | ";
1222 if ($ownpost or $isteacher) {
1223 echo "<a href=\"$CFG->wwwroot/mod/forum/post.php?delete=$post->id\">$strdelete</a>";
1227 echo " ";
1231 echo "<a href=\"$CFG->wwwroot/mod/forum/post.php?reply=$post->id\">$strreply</a>";
1232 echo " ";
1236 echo "<div align=right><p align=right>";
1238 $ratingsmenuused = false;
1239 if (!empty($ratings) and !empty($USER->id
)) {
1241 if ($ratings->assesstimestart
and $ratings->assesstimefinish
) {
1242 if ($post->created
< $ratings->assesstimestart
or $post->created
> $ratings->assesstimefinish
) {
1243 $useratings = false;
1247 $mypost = ($USER->id
== $post->userid
);
1249 if (($isteacher or $ratings->assesspublic
) and !$mypost) {
1250 forum_print_ratings_mean($post->id
, $ratings->scale
, $isteacher);
1251 forum_print_rating_menu($post->id
, $USER->id
, $ratings->scale
);
1252 $ratingsmenuused = true;
1254 } else if ($mypost) {
1255 forum_print_ratings_mean($post->id
, $ratings->scale
, true);
1257 } else if (!empty($ratings->allow
) ) {
1258 forum_print_rating_menu($post->id
, $USER->id
, $ratings->scale
);
1259 $ratingsmenuused = true;
1265 if ($post->replies
== 1) {
1266 $replystring = get_string("repliesone", "forum", $post->replies
);
1268 $replystring = get_string("repliesmany", "forum", $post->replies
);
1270 echo "<a href=\"$CFG->wwwroot/mod/forum/discuss.php?d=$post->discussion\"><b>".
1271 get_string("discussthistopic", "forum")."</b></a> ($replystring) ";
1275 echo "<p>$footer</p>";
1278 echo "</td></tr>\n</table>\n\n";
1280 return $ratingsmenuused;
1284 function forum_print_discussion_header(&$post, $courseid, $datestring="") {
1285 global $THEME, $USER, $CFG;
1287 if (!empty($CFG->filterall
)) {
1288 $post->subject
= filter_text($post->subject
, $courseid);
1291 echo "<tr class=\"forumpostheader\">";
1294 echo "<td bgcolor=\"$THEME->cellheading2\" class=\"forumpostheadertopic\" width=\"100%\">";
1295 echo "<a href=\"$CFG->wwwroot/mod/forum/discuss.php?d=$post->discussion\">$post->subject</a>";
1299 echo "<td bgcolor=\"$THEME->cellcontent2\" class=\"forumpostheaderpicture\" width=35>";
1300 print_user_picture($post->userid
, $courseid, $post->picture
);
1304 $fullname = fullname($post, isteacher($courseid));
1305 echo "<td bgcolor=\"$THEME->cellcontent2\" class=\"forumpostheadername\" align=left nowrap>";
1306 echo "<a href=\"$CFG->wwwroot/user/view.php?id=$post->userid&course=$courseid\">$fullname</a>";
1310 echo "<td bgcolor=\"$THEME->cellcontent2\" class=\"forumpostheaderreplies\" align=center nowrap>";
1311 echo "<a href=\"$CFG->wwwroot/mod/forum/discuss.php?d=$post->discussion\">$post->replies</a>";
1314 echo "<td bgcolor=\"$THEME->cellcontent2\" class=\"forumpostheaderdate\" align=right nowrap>";
1315 if (!empty($post->timemodified
)) {
1316 echo userdate($post->timemodified
, $datestring);
1318 echo userdate($post->modified
, $datestring);
1327 function forum_shorten_post($message) {
1328 // Given a post object that we already know has a long message
1329 // this function truncates the message nicely to the first
1330 // sane place between $CFG->forum_longpost and $CFG->forum_shortpost
1336 $length = strlen($message);
1341 for ($i=0; $i<$length; $i++
) {
1342 $char = $message[$i];
1364 if ($count > $CFG->forum_shortpost
) {
1374 return substr($message, 0, $truncate);
1378 function forum_print_ratings_mean($postid, $scale, $link=true) {
1379 /// Print the multiple ratings on a post given to the current user by others.
1380 /// Scale is an array of ratings
1384 $mean = forum_get_ratings_mean($postid, $scale);
1388 if (empty($strratings)) {
1389 $strratings = get_string("ratings", "forum");
1392 echo "$strratings: ";
1394 link_to_popup_window ("/mod/forum/report.php?id=$postid", "ratings", $mean, 400, 600);
1402 function forum_get_ratings_mean($postid, $scale, $ratings=NULL) {
1403 /// Return the mean rating of a post given to the current user by others.
1404 /// Scale is an array of possible ratings in the scale
1405 /// Ratings is an optional simple array of actual ratings (just integers)
1409 if ($rates = get_records("forum_ratings", "post", $postid)) {
1410 foreach ($rates as $rate) {
1411 $ratings[] = $rate->rating
;
1416 $count = count($ratings);
1421 } else if ($count == 1) {
1422 return $scale[$ratings[0]];
1426 foreach ($ratings as $rating) {
1429 $mean = round( ((float)$total/(float)$count) +
0.001); // Little fudge factor so that 0.5 goes UP
1431 if (isset($scale[$mean])) {
1432 return $scale[$mean]." ($count)";
1434 return "$mean ($count)"; // Should never happen, hopefully
1439 function forum_get_ratings_summary($postid, $scale, $ratings=NULL) {
1440 /// Return a summary of post ratings given to the current user by others.
1441 /// Scale is an array of possible ratings in the scale
1442 /// Ratings is an optional simple array of actual ratings (just integers)
1446 if ($rates = get_records("forum_ratings", "post", $postid)) {
1447 foreach ($rates as $rate) {
1448 $rating[] = $rate->rating
;
1454 if (!$count = count($ratings)) {
1459 foreach ($scale as $key => $scaleitem) {
1460 $sumrating[$key] = 0;
1463 foreach ($ratings as $rating) {
1464 $sumrating[$rating]++
;
1468 foreach ($scale as $key => $scaleitem) {
1469 $summary = $sumrating[$key].$summary;
1471 $summary = "/$summary";
1477 function forum_print_rating_menu($postid, $userid, $scale) {
1478 /// Print the menu of ratings as part of a larger form.
1479 /// If the post has already been - set that value.
1480 /// Scale is an array of ratings
1484 if (!$rating = get_record("forum_ratings", "userid", $userid, "post", $postid)) {
1485 $rating->rating
= 0;
1488 if (empty($strrate)) {
1489 $strrate = get_string("rate", "forum");
1492 choose_from_menu($scale, $postid, $rating->rating
, "$strrate...");
1495 function forum_print_mode_form($discussion, $mode) {
1496 GLOBAL $FORUM_LAYOUT_MODES;
1499 popup_form("discuss.php?d=$discussion&mode=", $FORUM_LAYOUT_MODES, "mode", $mode, "");
1500 echo "</p></center>\n";
1503 function forum_print_search_form($course, $search="", $return=false, $type="") {
1506 if ($type == "plain") {
1507 $output = "<table border=0 cellpadding=0 cellspacing=0><tr><td nowrap>";
1508 $output .= "<form name=search action=\"$CFG->wwwroot/mod/forum/search.php\">";
1509 $output .= "<font size=\"-1\">";
1510 $output .= "<input name=search type=text size=20 value=\"$search\">";
1511 $output .= "<input value=\"".get_string("searchforums", "forum")."\" type=submit>";
1512 $output .= "</font>";
1513 $output .= "<input name=id type=hidden value=\"$course->id\">";
1514 $output .= "</form>";
1515 $output .= "</td></tr></table>";
1517 $output = "<table border=0 cellpadding=10 cellspacing=0><tr><td align=center>";
1518 $output .= "<form name=search action=\"$CFG->wwwroot/mod/forum/search.php\">";
1519 $output .= "<font size=\"-1\">";
1520 $output .= "<input name=search type=text size=20 value=\"$search\"><br>";
1521 $output .= "<input value=\"".get_string("searchforums", "forum")."\" type=submit>";
1522 $output .= "</font>";
1523 $output .= "<input name=id type=hidden value=\"$course->id\">";
1524 $output .= "</form>";
1525 $output .= "</td></tr></table>";
1535 function forum_set_return() {
1536 global $CFG, $SESSION;
1538 if (! isset($SESSION->fromdiscussion
)) {
1539 if (!empty($_SERVER['HTTP_REFERER'])) {
1540 $referer = $_SERVER['HTTP_REFERER'];
1544 // If the referer is NOT a login screen then save it.
1545 if (! strncasecmp("$CFG->wwwroot/login", $referer, 300)) {
1546 $SESSION->fromdiscussion
= $_SERVER["HTTP_REFERER"];
1552 function forum_go_back_to($default) {
1555 if (!empty($SESSION->fromdiscussion
)) {
1556 $returnto = $SESSION->fromdiscussion
;
1557 unset($SESSION->fromdiscussion
);
1564 function forum_file_area_name($post) {
1565 // Creates a directory file name, suitable for make_upload_directory()
1568 return "$post->course/$CFG->moddata/forum/$post->forum/$post->id";
1571 function forum_file_area($post) {
1572 return make_upload_directory( forum_file_area_name($post) );
1575 function forum_delete_old_attachments($post, $exception="") {
1576 // Deletes all the user files in the attachments area for a post
1577 // EXCEPT for any file named $exception
1579 if ($basedir = forum_file_area($post)) {
1580 if ($files = get_directory_list($basedir)) {
1581 foreach ($files as $file) {
1582 if ($file != $exception) {
1583 unlink("$basedir/$file");
1584 notify("Existing file '$file' has been deleted!");
1588 if (!$exception) { // Delete directory as well, if empty
1594 function forum_move_attachments($discussion, $forumid) {
1595 /// Given a discussion object that is being moved to forumid,
1596 /// this function checks all posts in that discussion
1597 /// for attachments, and if any are found, these are
1598 /// moved to the new forum directory.
1604 if ($posts = get_records_select("forum_posts", "discussion = '$discussion->id' AND attachment <> ''")) {
1605 foreach ($posts as $oldpost) {
1606 $oldpost->course
= $discussion->course
;
1607 $oldpost->forum
= $discussion->forum
;
1608 $oldpostdir = "$CFG->dataroot/".forum_file_area_name($oldpost);
1609 if (is_dir($oldpostdir)) {
1610 $newpost = $oldpost;
1611 $newpost->forum
= $forumid;
1612 $newpostdir = forum_file_area($newpost);
1613 if (! @rename
($oldpostdir, $newpostdir)) {
1622 function forum_print_attachments($post, $return=NULL) {
1623 // if return=html, then return a html string.
1624 // if return=text, then return a text-only string.
1625 // otherwise, print HTML for non-images, and return image HTML
1629 $filearea = forum_file_area_name($post);
1634 if ($basedir = forum_file_area($post)) {
1635 if ($files = get_directory_list($basedir)) {
1636 $strattachment = get_string("attachment", "forum");
1637 $strpopupwindow = get_string("popupwindow");
1638 foreach ($files as $file) {
1639 $icon = mimeinfo("icon", $file);
1640 if ($CFG->slasharguments
) {
1641 $ffurl = "file.php/$filearea/$file";
1643 $ffurl = "file.php?file=/$filearea/$file";
1645 $image = "<img border=\"0\" src=\"$CFG->pixpath/f/$icon\" height=\"16\" width=\"16\" alt=\"$strpopupwindow\">";
1647 if ($return == "html") {
1648 $output .= "<a href=\"$CFG->wwwroot/$ffurl\">$image</a> ";
1649 $output .= "<a href=\"$CFG->wwwroot/$ffurl\">$file</a><br />";
1651 } else if ($return == "text") {
1652 $output .= "$strattachment $file:\n$CFG->wwwroot/$ffurl\n";
1655 if ($icon == "image.gif") { // Image attachments don't get printed as links
1656 $imagereturn .= "<br /><img src=\"$CFG->wwwroot/$ffurl\">";
1658 link_to_popup_window("/$ffurl", "attachment", $image, 500, 500, $strattachment);
1659 echo "<a href=\"$CFG->wwwroot/$ffurl\">$file</a>";
1671 return $imagereturn;
1674 function forum_add_attachment($post, $newfile) {
1675 // $post is a full post record, including course and forum
1676 // $newfile is a full upload array from $_FILES
1677 // If successful, this function returns the name of the file
1681 if (empty($newfile['name'])) {
1685 if (!$forum = get_record("forum", "id", $post->forum
)) {
1689 if (!$course = get_record("course", "id", $forum->course
)) {
1693 $maxbytes = get_max_upload_file_size($CFG->maxbytes
, $course->maxbytes
, $forum->maxbytes
);
1695 $newfile_name = clean_filename($newfile['name']);
1697 if (valid_uploaded_file($newfile)) {
1698 if ($maxbytes and $newfile['size'] > $maxbytes) {
1701 if (! $newfile_name) {
1702 notify("This file had a wierd filename and couldn't be uploaded");
1704 } else if (! $dir = forum_file_area($post)) {
1705 notify("Attachment could not be stored");
1709 if (move_uploaded_file($newfile['tmp_name'], "$dir/$newfile_name")) {
1710 chmod("$dir/$newfile_name", $CFG->directorypermissions
);
1711 forum_delete_old_attachments($post, $newfile_name);
1713 notify("An error happened while saving the file on the server");
1721 return $newfile_name;
1724 function forum_add_new_post($post) {
1726 $post->created
= $post->modified
= time();
1727 $post->mailed
= "0";
1729 $newfile = $post->attachment
;
1730 $post->attachment
= "";
1732 if (! $post->id
= insert_record("forum_posts", $post)) {
1736 if ($post->attachment
= forum_add_attachment($post, $newfile)) {
1737 set_field("forum_posts", "attachment", $post->attachment
, "id", $post->id
);
1740 // Update discussion modified date
1741 set_field("forum_discussions", "timemodified", $post->modified
, "id", $post->discussion
);
1742 set_field("forum_discussions", "usermodified", $post->userid
, "id", $post->discussion
);
1747 function forum_update_post($post) {
1749 $post->modified
= time();
1751 if (!$post->parent
) { // Post is a discussion starter - update discussion title too
1752 set_field("forum_discussions", "name", $post->subject
, "id", $post->discussion
);
1755 if ($newfilename = forum_add_attachment($post, $post->attachment
)) {
1756 $post->attachment
= $newfilename;
1758 unset($post->attachment
);
1761 // Update discussion modified date
1762 set_field("forum_discussions", "timemodified", $post->modified
, "id", $post->discussion
);
1763 set_field("forum_discussions", "usermodified", $post->userid
, "id", $post->discussion
);
1765 return update_record("forum_posts", $post);
1768 function forum_add_discussion($discussion) {
1769 // Given an object containing all the necessary data,
1770 // create a new discussion and return the id
1776 // The first post is stored as a real post, and linked
1777 // to from the discuss entry.
1779 $post->discussion
= 0;
1781 $post->userid
= $USER->id
;
1782 $post->created
= $timenow;
1783 $post->modified
= $timenow;
1785 $post->subject
= $discussion->name
;
1786 $post->message
= $discussion->intro
;
1787 $post->attachment
= "";
1788 $post->forum
= $discussion->forum
;
1789 $post->course
= $discussion->course
;
1790 $post->format
= $discussion->format
;
1792 if (! $post->id
= insert_record("forum_posts", $post) ) {
1796 if ($post->attachment
= forum_add_attachment($post, $discussion->attachment
)) {
1797 set_field("forum_posts", "attachment", $post->attachment
, "id", $post->id
); //ignore errors
1800 // Now do the main entry for the discussion,
1801 // linking to this first post
1803 $discussion->firstpost
= $post->id
;
1804 $discussion->timemodified
= $timenow;
1805 $discussion->usermodified
= $post->userid
;
1807 if (! $discussion->id
= insert_record("forum_discussions", $discussion) ) {
1808 delete_records("forum_posts", "id", $post->id
);
1812 // Finally, set the pointer on the post.
1813 if (! set_field("forum_posts", "discussion", $discussion->id
, "id", $post->id
)) {
1814 delete_records("forum_posts", "id", $post->id
);
1815 delete_records("forum_discussions", "id", $discussion->id
);
1819 return $discussion->id
;
1823 function forum_delete_discussion($discussion) {
1824 // $discussion is a discussion record object
1828 if ($posts = get_records("forum_posts", "discussion", $discussion->id
)) {
1829 foreach ($posts as $post) {
1830 $post->course
= $discussion->course
;
1831 $post->forum
= $discussion->forum
;
1832 if (! delete_records("forum_ratings", "post", "$post->id")) {
1835 if (! forum_delete_post($post)) {
1841 if (! delete_records("forum_discussions", "id", "$discussion->id")) {
1849 function forum_delete_post($post) {
1850 if (delete_records("forum_posts", "id", $post->id
)) {
1851 delete_records("forum_ratings", "post", $post->id
); // Just in case
1852 if ($post->attachment
) {
1853 $discussion = get_record("forum_discussions", "id", $post->discussion
);
1854 $post->course
= $discussion->course
;
1855 $post->forum
= $discussion->forum
;
1856 forum_delete_old_attachments($post);
1864 function forum_print_user_discussions($courseid, $userid) {
1867 $maxdiscussions = 10;
1868 $countdiscussions = 0;
1871 if ($discussions = forum_get_user_discussions($courseid, $userid)) {
1872 $user = get_record("user", "id", $userid);
1874 $fullname = fullname($user, isteacher($courseid));
1875 print_heading( get_string("discussionsstartedbyrecent", "forum", $fullname) );
1876 $replies = forum_count_discussion_replies();
1877 foreach ($discussions as $discussion) {
1878 $countdiscussions++
;
1879 if ($countdiscussions > $maxdiscussions) {
1882 if (($discussion->forumtype
== "teacher") and !isteacher($courseid)) {
1885 if (!empty($replies[$discussion->discussion
])) {
1886 $discussion->replies
= $replies[$discussion->discussion
]->replies
;
1888 $discussion->replies
= 0;
1890 $inforum = get_string("inforum", "forum", "<A HREF=\"$CFG->wwwroot/mod/forum/view.php?f=$discussion->forumid\">$discussion->forumname</A>");
1891 $discussion->subject
.= " ($inforum)";
1892 if (!empty($USER->id
)) {
1893 $ownpost = ($discussion->userid
== $USER->id
);
1897 forum_print_post($discussion, $courseid, $ownpost, $reply=0, $link=1, $assessed=false);
1903 function forum_forcesubscribe($forumid, $value=1) {
1904 return set_field("forum", "forcesubscribe", $value, "id", $forumid);
1907 function forum_is_forcesubscribed($forumid) {
1908 return get_field("forum", "forcesubscribe", "id", $forumid);
1911 function forum_is_subscribed($userid, $forumid) {
1912 if (forum_is_forcesubscribed($forumid)) {
1915 return record_exists("forum_subscriptions", "userid", $userid, "forum", $forumid);
1918 function forum_subscribe($userid, $forumid) {
1919 /// Adds user to the subscriber list
1921 $sub->userid
= $userid;
1922 $sub->forum
= $forumid;
1924 return insert_record("forum_subscriptions", $sub);
1927 function forum_unsubscribe($userid, $forumid) {
1928 /// Removes user from the subscriber list
1929 return delete_records("forum_subscriptions", "userid", $userid, "forum", $forumid);
1932 function forum_post_subscription($post) {
1933 /// Given a new post, subscribes or unsubscribes as appropriate.
1934 /// Returns some text which describes what happened.
1938 if (empty($post->subscribe
) and empty($post->unsubscribe
)) {
1942 if (!$forum = get_record("forum", "id", $post->forum
)) {
1946 $info->name
= "$USER->firstname $USER->lastname";
1947 $info->forum
= $forum->name
;
1949 if (!empty($post->subscribe
)) {
1950 forum_subscribe($USER->id
, $post->forum
);
1951 return "<p>".get_string("nowsubscribed", "forum", $info)."</p>";
1954 forum_unsubscribe($USER->id
, $post->forum
);
1955 return "<p>".get_string("nownotsubscribed", "forum", $info)."</p>";
1959 function forum_user_has_posted_discussion($forumid, $userid) {
1960 if ($discussions = forum_get_discussions($forumid, "", $userid)) {
1967 function forum_user_can_post_discussion($forum, $currentgroup=false) {
1968 // $forum is an object
1971 if ($forum->type
== "eachuser") {
1972 return (! forum_user_has_posted_discussion($forum->id
, $USER->id
));
1973 } else if ($forum->type
== "teacher") {
1974 return isteacher($forum->course
);
1975 } else if ($currentgroup) {
1976 return (isteacheredit($forum->course
) or ismember($currentgroup));
1977 } else if (isteacher($forum->course
)) {
1980 return ($forum->open
== 2);
1984 function forum_user_can_post($forum, $user=NULL) {
1985 // $forum, $user are objects
1988 $isteacher = isteacher($forum->course
, $user->id
);
1990 $isteacher = isteacher($forum->course
);
1993 if ($forum->type
== "teacher") {
1995 } else if ($isteacher) {
1998 return $forum->open
;
2003 function forum_print_latest_discussions($forum_id=0, $forum_numdiscussions=5,
2004 $forum_style="plain", $forum_sort="",
2009 if (! $forum = get_record("forum", "id", $forum_id)) {
2010 error("Forum ID was incorrect");
2012 if (! $course = get_record("course", "id", $forum->course
)) {
2013 error("Could not find the course this forum belongs to!");
2016 if ($course->category
) {
2017 require_login($course->id
);
2021 if (! $course = get_record("course", "category", 0)) {
2022 error("Could not find a top-level course!");
2024 if (! $forum = forum_get_course_forum($course->id
, "news")) {
2025 error("Could not find or create a main forum in this course (id $course->id)");
2029 if (forum_user_can_post_discussion($forum, $currentgroup)) {
2030 echo "<p align=center>";
2031 echo "<a href=\"$CFG->wwwroot/mod/forum/post.php?forum=$forum->id\">";
2032 if ($forum->type
== "news") {
2033 echo get_string("addanewtopic", "forum")."</a>...";
2035 echo get_string("addanewdiscussion", "forum")."</a>...";
2040 if ((!$forum_numdiscussions) && ($forum_style == "plain")) {
2041 $forum_style = "header"; // Abbreviate display by default
2044 if ($forum_style == "minimal") {
2045 $forum_sort = "p.modified DESC";
2049 if ($forum_style == "plain") {
2053 if (! $discussions = forum_get_discussions($forum->id
, $forum_sort, 0, $fullpost, $currentgroup) ) {
2054 if ($forum->type
== "news") {
2055 echo "<p align=center><b>(".get_string("nonews", "forum").")</b></p>";
2057 echo "<p align=center><b>(".get_string("nodiscussions", "forum").")</b></p>";
2062 $replies = forum_count_discussion_replies($forum->id
);
2064 $canreply = forum_user_can_post($forum);
2066 $discussioncount = 0;
2067 $olddiscussionlink = false;
2068 $strdatestring = get_string("strftimedaydatetime");
2070 if ($forum_style == "minimal") {
2071 $strftimerecent = get_string("strftimerecent");
2072 $strmore = get_string("more", "forum");
2075 if ($forum_style == "header") {
2076 echo "<table width=\"100%\" border=0 cellpadding=3 cellspacing=1 class=\"forumheaderlist\">";
2077 echo "<tr class=\"forumpostheader\">";
2078 echo "<th>".get_string("discussion", "forum")."</th>";
2079 echo "<th colspan=2>".get_string("startedby", "forum")."</th>";
2080 echo "<th>".get_string("replies", "forum")."</th>";
2081 echo "<th>".get_string("lastpost", "forum")."</th>";
2085 foreach ($discussions as $discussion) {
2088 if ($forum_numdiscussions && ($discussioncount > $forum_numdiscussions)) {
2089 $olddiscussionlink = true;
2092 if (!empty($replies[$discussion->discussion
])) {
2093 $discussion->replies
= $replies[$discussion->discussion
]->replies
;
2095 $discussion->replies
= 0;
2097 if (!empty($USER->id
)) {
2098 $ownpost = ($discussion->userid
== $USER->id
);
2102 switch ($forum_style) {
2104 if (!empty($CFG->filterall
)) {
2105 $discussion->subject
= filter_text($discussion->subject
, $forum->course
);
2107 echo "<p><span class=\"smallinfohead\">".userdate($discussion->modified
, $strftimerecent)." - $discussion->firstname</span><br />";
2108 echo "<span class=\"smallinfo\">$discussion->subject ";
2109 echo "<a href=\"$CFG->wwwroot/mod/forum/discuss.php?d=$discussion->discussion\">";
2110 echo $strmore."...</a></span>";
2114 forum_print_discussion_header($discussion, $forum->course
, $strdatestring);
2117 if ($canreply or $discussion->replies
) {
2122 forum_print_post($discussion, $forum->course
, $ownpost, $reply=0, $link, $assessed=false);
2128 if ($forum_style == "header") {
2132 if ($olddiscussionlink) {
2133 echo "<p align=right><a href=\"$CFG->wwwroot/mod/forum/view.php?f=$forum->id&showall=1\">";
2134 echo get_string("olderdiscussions", "forum")."</a> ...</p>";
2138 function forum_print_discussion($course, $forum, $discussion, $post, $mode, $canreply=NULL) {
2142 if (!empty($USER->id
)) {
2143 $ownpost = ($USER->id
== $post->userid
);
2147 if ($canreply === NULL) {
2148 $reply = forum_user_can_post($forum);
2154 $ratingsmenuused = false;
2155 if ($forum->assessed
and !empty($USER->id
)) {
2156 if ($ratings->scale
= make_grades_menu($forum->scale
)) {
2157 $ratings->assesspublic
= $forum->assesspublic
;
2158 $ratings->assesstimestart
= $forum->assesstimestart
;
2159 $ratings->assesstimefinish
= $forum->assesstimefinish
;
2160 $ratings->allow
= ($forum->assessed
!= 2 or isteacher($course->id
));
2162 echo "<form name=form method=post action=rate.php>";
2163 echo "<input type=hidden name=id value=\"$course->id\">";
2167 if (forum_print_post($post, $course->id
, $ownpost, $reply, $link=false, $ratings)) {
2168 $ratingsmenuused = true;
2172 case FORUM_MODE_FLATOLDEST
:
2173 case FORUM_MODE_FLATNEWEST
:
2176 if (forum_print_posts_flat($post->discussion
, $course->id
, $mode, $ratings, $reply)) {
2177 $ratingsmenuused = true;
2182 case FORUM_MODE_THREADED
:
2183 if (forum_print_posts_threaded($post->id
, $course->id
, 0, $ratings, $reply)) {
2184 $ratingsmenuused = true;
2188 case FORUM_MODE_NESTED
:
2189 if (forum_print_posts_nested($post->id
, $course->id
, $ratings, $reply)) {
2190 $ratingsmenuused = true;
2195 if ($ratingsmenuused) {
2196 echo "<center><input type=\"submit\" value=\"".get_string("sendinratings", "forum")."\">";
2197 if ($forum->scale
< 0) {
2198 if ($scale = get_record("scale", "id", abs($forum->scale
))) {
2199 print_scale_menu_helpbutton($course->id
, $scale );
2207 function forum_print_posts_flat($discussion, $course, $direction, $ratings, $reply) {
2211 $ratingsmenuused = false;
2213 if ($direction < 0) {
2214 $sort = "ORDER BY created DESC";
2216 $sort = "ORDER BY created ASC";
2219 if ($posts = forum_get_discussion_posts($discussion, $sort)) {
2220 foreach ($posts as $post) {
2221 $ownpost = ($USER->id
== $post->userid
);
2222 if (forum_print_post($post, $course, $ownpost, $reply, $link, $ratings)) {
2223 $ratingsmenuused = true;
2228 return $ratingsmenuused;
2231 function forum_print_posts_threaded($parent, $course, $depth, $ratings, $reply) {
2235 $ratingsmenuused = false;
2237 if ($posts = forum_get_child_posts($parent)) {
2238 foreach ($posts as $post) {
2242 $ownpost = ($USER->id
== $post->userid
);
2243 if (forum_print_post($post, $course, $ownpost, $reply, $link, $ratings)) {
2244 $ratingsmenuused = true;
2248 $by->name
= fullname($post, isteacher($course->id
));
2249 $by->date
= userdate($post->modified
);
2250 echo "<li><p><a name=\"$post->id\"></a><font size=-1><b><a href=\"discuss.php?d=$post->discussion&parent=$post->id\">$post->subject</a></b> ";
2251 print_string("bynameondate", "forum", $by);
2252 echo "</font></p></li>";
2255 if (forum_print_posts_threaded($post->id
, $course, $depth-1, $ratings, $reply)) {
2256 $ratingsmenuused = true;
2261 return $ratingsmenuused;
2264 function forum_print_posts_nested($parent, $course, $ratings, $reply) {
2268 $ratingsmenuused = false;
2270 if ($posts = forum_get_child_posts($parent)) {
2271 foreach ($posts as $post) {
2273 if (empty($USER->id
)) {
2276 $ownpost = ($USER->id
== $post->userid
);
2280 if (forum_print_post($post, $course, $ownpost, $reply, $link, $ratings)) {
2281 $ratingsmenuused = true;
2284 if (forum_print_posts_nested($post->id
, $course, $ratings, $reply)) {
2285 $ratingsmenuused = true;
2290 return $ratingsmenuused;
2293 function forum_get_recent_mod_activity(&$activities, &$index, $sincetime, $courseid, $forum="0", $user="", $groupid="") {
2294 // Returns all forum posts since a given time. If forum is specified then
2295 // this restricts the results
2300 $forumselect = " AND cm.id = '$forum'";
2306 $userselect = " AND u.id = '$user'";
2311 $posts = get_records_sql("SELECT p.*, d.name, u.firstname, u.lastname,
2312 u.picture, d.groupid, cm.instance, f.name, cm.section
2313 FROM {$CFG->prefix}forum_posts p,
2314 {$CFG->prefix}forum_discussions d,
2315 {$CFG->prefix}user u,
2316 {$CFG->prefix}course_modules cm,
2317 {$CFG->prefix}forum f
2318 WHERE p.modified > '$sincetime' $forumselect
2319 AND p.userid = u.id $userselect
2320 AND d.course = '$courseid'
2321 AND p.discussion = d.id $groupselect
2322 AND cm.instance = f.id
2323 AND cm.course = d.course
2324 AND cm.course = f.course
2331 foreach ($posts as $post) {
2333 if (empty($groupid) ||
ismember($groupid, $post->userid
)) {
2334 $tmpactivity->type
= "forum";
2335 $tmpactivity->defaultindex
= $index;
2336 $tmpactivity->instance
= $post->instance
;
2337 $tmpactivity->name
= $post->name
;
2338 $tmpactivity->section
= $post->section
;
2340 $tmpactivity->content
->id
= $post->id
;
2341 $tmpactivity->content
->discussion
= $post->discussion
;
2342 $tmpactivity->content
->subject
= $post->subject
;
2343 $tmpactivity->content
->parent
= $post->parent
;
2345 $tmpactivity->user
->userid
= $post->userid
;
2346 $tmpactivity->user
->fullname
= fullname($post);
2347 $tmpactivity->user
->picture
= $post->picture
;
2349 $tmpactivity->timestamp
= $post->modified
;
2350 $activities[] = $tmpactivity;
2359 function forum_print_recent_mod_activity($activity, $course, $detail=false) {
2363 echo '<table border="0" cellpadding="3" cellspacing="0">';
2365 if ($activity->content
->parent
) {
2366 $openformat = "<font size=\"2\"><i>";
2367 $closeformat = "</i></font>";
2369 $openformat = "<b>";
2370 $closeformat = "</b>";
2373 echo "<tr><td bgcolor=\"$THEME->cellcontent2\" class=\"forumpostpicture\" width=\"35\" valign=\"top\">";
2374 print_user_picture($activity->user
->userid
, $course, $activity->user
->picture
);
2375 echo "</td><td>$openformat";
2378 echo "<img src=\"$CFG->modpixpath/$activity->type/icon.gif\" ".
2379 "height=16 width=16 alt=\"$activity->name\"> ";
2381 echo "<a href=\"$CFG->wwwroot/mod/forum/discuss.php?d=" . $activity->content
->discussion
2382 . "#" . $activity->content
->id
. "\">";
2384 echo $activity->content
->subject
;
2385 echo "</a>$closeformat";
2387 echo "<br><font size=\"2\">";
2388 echo "<a href=\"$CFG->wwwroot/user/view.php?id=" . $activity->user
->userid
. "&course=" . "$course\">"
2389 . $activity->user
->fullname
. "</a>";
2390 echo " - " . userdate($activity->timestamp
) . "</font></td></tr>";