fixed loglive paging related bug #4116, patch submitted by samulik; merged from MOODL...
[moodle.git] / mod / forum / lib.php
CommitLineData
41905731 1<?php // $Id$
f93f848a 2
f1e0649c 3require_once($CFG->libdir.'/filelib.php');
7f6689e4 4
501cdbd8 5/// CONSTANTS ///////////////////////////////////////////////////////////
f93f848a 6
d3583b41 7define('FORUM_MODE_FLATOLDEST', 1);
8define('FORUM_MODE_FLATNEWEST', -1);
9define('FORUM_MODE_THREADED', 2);
10define('FORUM_MODE_NESTED', 3);
2e2e71a8 11
d3583b41 12define('FORUM_FORCESUBSCRIBE', 1);
13define('FORUM_INITIALSUBSCRIBE', 2);
709f0ec8 14
eaf50aef 15define('FORUM_TRACKING_OFF', 0);
16define('FORUM_TRACKING_OPTIONAL', 1);
17define('FORUM_TRACKING_ON', 2);
18
d3583b41 19$FORUM_LAYOUT_MODES = array ( FORUM_MODE_FLATOLDEST => get_string('modeflatoldestfirst', 'forum'),
20 FORUM_MODE_FLATNEWEST => get_string('modeflatnewestfirst', 'forum'),
21 FORUM_MODE_THREADED => get_string('modethreaded', 'forum'),
22 FORUM_MODE_NESTED => get_string('modenested', 'forum') );
f93f848a 23
11b0c469 24// These are course content forums that can be added to the course manually
d3583b41 25$FORUM_TYPES = array ('general' => get_string('generalforum', 'forum'),
26 'eachuser' => get_string('eachuserforum', 'forum'),
27 'single' => get_string('singleforum', 'forum') );
f93f848a 28
d3583b41 29$FORUM_OPEN_MODES = array ('2' => get_string('openmode2', 'forum'),
30 '1' => get_string('openmode1', 'forum'),
31 '0' => get_string('openmode0', 'forum') );
70c476a7 32
5be7800c 33if (!isset($CFG->forum_displaymode)) {
d3583b41 34 set_config('forum_displaymode', FORUM_MODE_NESTED);
65b0e537 35}
73bb0835 36
5be7800c 37if (!isset($CFG->forum_shortpost)) {
d3583b41 38 set_config('forum_shortpost', 300); // Less non-HTML characters than this is short
65b0e537 39}
4d871a72 40
5be7800c 41if (!isset($CFG->forum_longpost)) {
d3583b41 42 set_config('forum_longpost', 600); // More non-HTML characters than this is long
65b0e537 43}
4d871a72 44
5be7800c 45if (!isset($CFG->forum_manydiscussions)) {
d3583b41 46 set_config('forum_manydiscussions', 100); // Number of discussions on a page
65b0e537 47}
e07635f4 48
4909e176 49if (!isset($CFG->forum_maxbytes)) {
d3583b41 50 set_config('forum_maxbytes', 512000); // Default maximum size for all forums
65b0e537 51}
4909e176 52
f37da850 53if (!isset($CFG->forum_trackreadposts)) {
d3583b41 54 set_config('forum_trackreadposts', true); // Default whether user needs to mark a post as read
f37da850 55}
56
57if (!isset($CFG->forum_oldpostdays)) {
81c679ce 58 set_config('forum_oldpostdays', 14); // Default number of days that a post is considered old
f37da850 59}
60
61if (!isset($CFG->forum_usermarksread)) {
d3583b41 62 set_config('forum_usermarksread', false); // Default whether user needs to mark a post as read
f37da850 63}
64
65if (!isset($CFG->forum_cleanreadtime)) {
d3583b41 66 set_config('forum_cleanreadtime', 2); // Default time (hour) to execute 'clean_read_records' cron
f37da850 67}
68
1246ea56 69if (!isset($CFG->forum_replytouser)) {
d3583b41 70 set_config('forum_replytouser', true); // Default maximum size for all forums
1246ea56 71}
72
27888a20 73if (empty($USER->id) or isguest()) {
74 $CFG->forum_trackreadposts = false; // This feature never works when a user isn't logged in
75}
4909e176 76
e07635f4 77
caadf009 78/// STANDARD FUNCTIONS ///////////////////////////////////////////////////////////
79
80function forum_add_instance($forum) {
65b0e537 81// Given an object containing all the necessary data,
82// (defined by the form in mod.html) this function
83// will create a new instance and return the id number
caadf009 84// of the new instance.
85
86 global $CFG;
87
88 $forum->timemodified = time();
89
f2f56406 90 if (!$forum->userating) {
91 $forum->assessed = 0;
92 }
93
98914efd 94 if (!empty($forum->ratingtime)) {
65b0e537 95 $forum->assesstimestart = make_timestamp($forum->startyear, $forum->startmonth, $forum->startday,
98914efd 96 $forum->starthour, $forum->startminute, 0);
65b0e537 97 $forum->assesstimefinish = make_timestamp($forum->finishyear, $forum->finishmonth, $forum->finishday,
98914efd 98 $forum->finishhour, $forum->finishminute, 0);
99 } else {
100 $forum->assesstimestart = 0;
101 $forum->assesstimefinish = 0;
102 }
caadf009 103
d3583b41 104 if (! $forum->id = insert_record('forum', $forum)) {
cb9a975f 105 return false;
106 }
107
d3583b41 108 if ($forum->type == 'single') { // Create related discussion.
caadf009 109 $discussion->course = $forum->course;
110 $discussion->forum = $forum->id;
111 $discussion->name = $forum->name;
112 $discussion->intro = $forum->intro;
113 $discussion->assessed = $forum->assessed;
93c86520 114 $discussion->format = $forum->format;
caadf009 115
93c86520 116 if (! forum_add_discussion($discussion, $discussion->intro)) {
d3583b41 117 error('Could not add the discussion for this forum');
caadf009 118 }
119 }
8f0cd6ef 120
709f0ec8 121 if ($forum->forcesubscribe == FORUM_INITIALSUBSCRIBE) { // all users should be subscribed initially
122 $users = get_course_users($forum->course);
123 foreach ($users as $user) {
124 forum_subscribe($user->id, $forum->id);
125 }
126 }
caadf009 127
128 return $forum->id;
129}
130
131
132function forum_update_instance($forum) {
65b0e537 133// Given an object containing all the necessary data,
134// (defined by the form in mod.html) this function
caadf009 135// will update an existing instance with new data.
136
137 $forum->timemodified = time();
138 $forum->id = $forum->instance;
139
3ad7a8c7 140 if (empty($forum->userating)) {
f2f56406 141 $forum->assessed = 0;
142 }
143
98914efd 144 if (!empty($forum->ratingtime)) {
65b0e537 145 $forum->assesstimestart = make_timestamp($forum->startyear, $forum->startmonth, $forum->startday,
98914efd 146 $forum->starthour, $forum->startminute, 0);
65b0e537 147 $forum->assesstimefinish = make_timestamp($forum->finishyear, $forum->finishmonth, $forum->finishday,
98914efd 148 $forum->finishhour, $forum->finishminute, 0);
149 } else {
150 $forum->assesstimestart = 0;
151 $forum->assesstimefinish = 0;
152 }
153
d3583b41 154 if ($forum->type == 'single') { // Update related discussion and post.
155 if (! $discussion = get_record('forum_discussions', 'forum', $forum->id)) {
156 if ($discussions = get_records('forum_discussions', 'forum', $forum->id, 'timemodified ASC')) {
157 notify('Warning! There is more than one discussion in this forum - using the most recent');
caadf009 158 $discussion = array_pop($discussions);
159 } else {
d3583b41 160 error('Could not find the discussion in this forum');
caadf009 161 }
162 }
d3583b41 163 if (! $post = get_record('forum_posts', 'id', $discussion->firstpost)) {
164 error('Could not find the first post in this forum discussion');
caadf009 165 }
166
167 $post->subject = $forum->name;
168 $post->message = $forum->intro;
169 $post->modified = $forum->timemodified;
170
d3583b41 171 if (! update_record('forum_posts', $post)) {
172 error('Could not update the first post');
caadf009 173 }
174
175 $discussion->name = $forum->name;
176
d3583b41 177 if (! update_record('forum_discussions', $discussion)) {
178 error('Could not update the discussion');
caadf009 179 }
180 }
181
d3583b41 182 return update_record('forum', $forum);
caadf009 183}
184
185
186function forum_delete_instance($id) {
65b0e537 187// Given an ID of an instance of this module,
188// this function will permanently delete the instance
189// and any data that depends on it.
caadf009 190
d3583b41 191 if (! $forum = get_record('forum', 'id', $id)) {
caadf009 192 return false;
193 }
194
195 $result = true;
196
d3583b41 197 if ($discussions = get_records('forum_discussions', 'forum', $forum->id)) {
caadf009 198 foreach ($discussions as $discussion) {
e2c1dbe9 199 if (! forum_delete_discussion($discussion, true)) {
caadf009 200 $result = false;
201 }
202 }
203 }
204
d3583b41 205 if (! delete_records('forum_subscriptions', 'forum', $forum->id)) {
caadf009 206 $result = false;
207 }
208
f37da850 209 forum_tp_delete_read_records(-1, -1, -1, $forum->id);
210
d3583b41 211 if (! delete_records('forum', 'id', $forum->id)) {
caadf009 212 $result = false;
213 }
214
215 return $result;
216}
217
218
219function forum_cron () {
edffca15 220/// Function to be run periodically according to the moodle cron
221/// Finds all posts that have yet to be mailed out, and mails them
222/// out to all subscribers
caadf009 223
d30867b0 224 global $CFG, $USER;
aaf7a9dc 225 static $strforums = NULL;
857b798b 226
227 if ($strforums === NULL) {
aaf7a9dc 228 $strforums = get_string('forums', 'forum');
229 }
230
1066e0dc 231 if (!empty($USER->id)) { // Remember real USER account if necessary
ec2137ba 232 $realuser = $USER;
233 }
234
3ecca1ee 235 /// Posts older than 2 days will not be mailed. This is to avoid the problem where
236 /// cron has not been running for a long time, and then suddenly people are flooded
237 /// with mail from the past few weeks or months
caadf009 238
3ecca1ee 239 $timenow = time();
240 $endtime = $timenow - $CFG->maxeditingtime;
38ad519c 241 $starttime = $endtime - 48 * 3600; /// Two days earlier
3ecca1ee 242
243 if ($posts = forum_get_unmailed_posts($starttime, $endtime)) {
caadf009 244
65b0e537 245 /// Mark them all now as being mailed. It's unlikely but possible there
246 /// might be an error later so that a post is NOT actually mailed out,
edffca15 247 /// but since mail isn't crucial, we can accept this risk. Doing it now
248 /// prevents the risk of duplicated mails, which is a worse problem.
249
3ecca1ee 250 if (!forum_mark_old_posts_as_mailed($endtime)) {
d3583b41 251 mtrace('Errors occurred while trying to mark some posts as being mailed.');
3ecca1ee 252 return false; // Don't continue trying to mail them, in case we are in a cron loop
edffca15 253 }
254
ca8e8a10 255 @set_time_limit(0); /// so that script does not get timed out when posting to many users
aaf7a9dc 256
857b798b 257 $urlinfo = parse_url($CFG->wwwroot);
258 $hostname = $urlinfo['host'];
259
caadf009 260 foreach ($posts as $post) {
261
d3583b41 262 mtrace(get_string('processingpost', 'forum', $post->id), '');
caadf009 263
d3583b41 264 if (! $userfrom = get_record('user', 'id', $post->userid)) {
265 mtrace('Could not find user '.$post->userid);
caadf009 266 continue;
267 }
268
857b798b 269
49d9b738 270
caadf009 271 if (! $discussion = get_record("forum_discussions", "id", "$post->discussion")) {
b140ae85 272 mtrace("Could not find discussion $post->discussion");
caadf009 273 continue;
274 }
275
276 if (! $forum = get_record("forum", "id", "$discussion->forum")) {
b140ae85 277 mtrace("Could not find forum $discussion->forum");
caadf009 278 continue;
279 }
280
281 if (! $course = get_record("course", "id", "$forum->course")) {
b140ae85 282 mtrace("Could not find course $forum->course");
caadf009 283 continue;
284 }
285
fd8585a0 286 $cleanforumname = str_replace('"', "'", strip_tags($forum->name));
287 $userfrom->customheaders = array ( // Headers to make emails easier to track
288 'Precedence: Bulk',
289 'List-Id: "'.$cleanforumname.'" <moodleforum'.$forum->id.'@'.$hostname.'>',
290 'List-Help: '.$CFG->wwwroot.'/mod/forum/view.php?f='.$forum->id,
291 'Message-Id: <moodlepost'.$post->id.'@'.$hostname.'>',
292 'In-Reply-To: <moodlepost'.$post->parent.'@'.$hostname.'>',
293 'References: <moodlepost'.$post->parent.'@'.$hostname.'>',
294 'X-Course-Id: '.$course->id,
ddff0984 295 'X-Course-Name: '.strip_tags($course->fullname)
fd8585a0 296 );
297
298
e1fb2e6e 299 if (!empty($course->lang)) {
300 $CFG->courselang = $course->lang;
301 } else {
302 unset($CFG->courselang);
303 }
9c84314e 304
9197e147 305 $groupmode = false;
306 if ($cm = get_coursemodule_from_instance("forum", $forum->id, $course->id)) {
2862b309 307 if ($groupmode = groupmode($course, $cm) and $discussion->groupid > 0) { // Groups are being used
2f9c977e 308 if (!$group = get_record("groups", "id", $discussion->groupid)) { // Can't find group
9197e147 309 continue; // Be safe and don't send it to anyone
310 }
311 }
69d79bc3 312 } else {
313 $cm->id = 0;
314 }
9197e147 315
caadf009 316 if ($users = forum_subscribed_users($course, $forum)) {
caadf009 317
318 $mailcount=0;
3d94772d 319 $errorcount=0;
caadf009 320 foreach ($users as $userto) {
9197e147 321 if ($groupmode) { // Look for a reason not to send this email
322 if (!isteacheredit($course->id, $userto->id)) {
2862b309 323 if (!empty($group->id)) {
324 if (!ismember($group->id, $userto->id)) {
325 continue;
326 }
9197e147 327 }
328 }
329 }
65b0e537 330
aaf7a9dc 331 if ($userto->maildigest > 0) {
332 // This user wants the mails to be in digest form
333 $queue = New stdClass;
334 $queue->userid = $userto->id;
335 $queue->discussionid = $discussion->id;
336 $queue->postid = $post->id;
337 if(!insert_record('forum_queue', $queue)) {
b140ae85 338 mtrace("Error: mod/forum/cron.php: Could not queue for digest mail for id $post->id to user $userto->id ($userto->email) .. not trying again.");
aaf7a9dc 339 }
340 continue;
341 }
65b0e537 342
343 /// Override the language and timezone of the "current" user, so that
ec2137ba 344 /// mail is customised for the receiver.
345 $USER->lang = $userto->lang;
346 $USER->timezone = $userto->timezone;
347
17dc3f3c 348 $postsubject = "$course->shortname: ".format_string($post->subject,true);
aaf7a9dc 349 $posttext = forum_make_mail_text($course, $forum, $discussion, $post, $userfrom, $userto);
350 $posthtml = forum_make_mail_html($course, $forum, $discussion, $post, $userfrom, $userto);
caadf009 351
8f0cd6ef 352 if (!$mailresult = email_to_user($userto, $userfrom, $postsubject, $posttext,
50a26903 353 $posthtml, '', '', $CFG->forum_replytouser)) {
b140ae85 354 mtrace("Error: mod/forum/cron.php: Could not send out mail for id $post->id to user $userto->id".
355 " ($userto->email) .. not trying again.");
8f0cd6ef 356 add_to_log($course->id, 'forum', 'mail error', "discuss.php?d=$discussion->id#$post->id",
17dc3f3c 357 substr(format_string($post->subject,true),0,30), $cm->id, $userto->id);
aaf7a9dc 358 $errorcount++;
b6268a0e 359 } else if ($mailresult === 'emailstop') {
8f0cd6ef 360 add_to_log($course->id, 'forum', 'mail blocked', "discuss.php?d=$discussion->id#$post->id",
17dc3f3c 361 substr(format_string($post->subject,true),0,30), $cm->id, $userto->id);
caadf009 362 } else {
aaf7a9dc 363 $mailcount++;
f37da850 364
365 /// Mark post as read if forum_usermarksread is set off
eaf50aef 366 if (!$CFG->forum_usermarksread && forum_tp_can_track_forums($forum, $userto) &&
367 forum_tp_is_tracked($forum, $userto->id)) {
f37da850 368 if (!forum_tp_mark_post_read($userto->id, $post, $forum->id)) {
369 mtrace("Error: mod/forum/cron.php: Could not mark post $post->id read for user $userto->id".
370 " while sending email.");
371 }
372 }
caadf009 373 }
aaf7a9dc 374 }
375
b140ae85 376 mtrace(".... mailed to $mailcount users.");
aaf7a9dc 377 if ($errorcount) {
378 set_field("forum_posts", "mailed", "2", "id", "$post->id");
379 }
380 }
381 }
382 }
383
6e6a64b3 384 unset($CFG->courselang);
385
944a2b28 386 if (!empty($realuser)) { // Restore real USER timezone if necessary
387 $sitetimezone = $realuser->timezone;
b140ae85 388 $USER->lang = $realuser->lang;
944a2b28 389 } else {
390 $sitetimezone = $CFG->timezone;
b140ae85 391 $USER->lang = $CFG->lang;
944a2b28 392 }
393
aaf7a9dc 394 /// Now see if there are any digest mails waiting to be sent, and if we should send them
aaf7a9dc 395
8f0cd6ef 396 if (!isset($CFG->digestmailtimelast)) { // To catch the first time
ca8e8a10 397 set_config('digestmailtimelast', 0);
398 }
399
400 $timenow = time();
944a2b28 401 $digesttime = usergetmidnight($timenow, $sitetimezone) + ($CFG->digestmailtime * 3600);
ca8e8a10 402
403 if ($CFG->digestmailtimelast < $digesttime and $timenow > $digesttime) {
b140ae85 404
ca8e8a10 405 set_config('digestmailtimelast', $timenow);
aaf7a9dc 406
b140ae85 407 mtrace('Sending forum digests: '.userdate($timenow, '', $sitetimezone));
408
aaf7a9dc 409 $digestposts = get_records('forum_queue');
410 if(!empty($digestposts)) {
411
412 // We have work to do
413 $usermailcount = 0;
414 $site = get_site();
415
416 $users = array();
417 $posts = array();
418 $discussions = array();
419 $discussionposts = array();
420 $userdiscussions = array();
421 foreach($digestposts as $digestpost) {
422 if(!isset($users[$digestpost->userid])) {
423 $users[$digestpost->userid] = get_record('user', 'id', $digestpost->userid);
424 }
425 if(!isset($discussions[$digestpost->discussionid])) {
426 $discussions[$digestpost->discussionid] = get_record('forum_discussions', 'id', $digestpost->discussionid);
427 }
428 if(!isset($posts[$digestpost->postid])) {
429 $posts[$digestpost->postid] = get_record('forum_posts', 'id', $digestpost->postid);
430 }
431 $userdiscussions[$digestpost->userid][$digestpost->discussionid] = $digestpost->discussionid;
432 $discussionposts[$digestpost->discussionid][$digestpost->postid] = $digestpost->postid;
433 }
434
435 // Data collected, start sending out emails to each user
436
437 foreach($userdiscussions as $userid => $thesediscussions) {
438
b140ae85 439 mtrace(get_string('processingdigest', 'forum', $userid),'... ');
aaf7a9dc 440
441 // First of all delete all the queue entries for this user
442 delete_records('forum_queue', 'userid', $userid);
443 $userto = $users[$userid];
444
445 /// Override the language and timezone of the "current" user, so that
446 /// mail is customised for the receiver.
a0330747 447 $USER->lang = $userto->lang;
448 $USER->timezone = $userto->timezone;
aaf7a9dc 449
450
451 $postsubject = get_string('digestmailsubject', 'forum', $site->shortname);
452 $headerdata = New stdClass;
453 $headerdata->sitename = $site->fullname;
839f2456 454 $headerdata->userprefs = $CFG->wwwroot.'/user/edit.php?id='.$userid.'&amp;course='.$site->id;
aaf7a9dc 455
456 $posttext = get_string('digestmailheader', 'forum', $headerdata)."\n\n";
457 $headerdata->userprefs = '<a target="_blank" href="'.$headerdata->userprefs.'">'.get_string('digestmailprefs', 'forum').'</a>';
9c674431 458
78c0d909 459 $posthtml = "<head>";
460 foreach ($CFG->stylesheets as $stylesheet) {
461 $posthtml .= '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'" />'."\n";
462 }
463 $posthtml .= "</head>\n<body>\n";
a0330747 464 $posthtml .= '<p>'.get_string('digestmailheader', 'forum', $headerdata).'</p><br /><hr size="1" noshade="noshade" />';
aaf7a9dc 465
466 foreach($thesediscussions as $discussionid) {
467 $discussion = $discussions[$discussionid];
468 if(empty($discussion)) {
b140ae85 469 mtrace("Error: Could not find discussion $discussionid");
aaf7a9dc 470 continue;
caadf009 471 }
aaf7a9dc 472
473 if (! $forum = get_record("forum", "id", "$discussion->forum")) {
b140ae85 474 mtrace("Could not find forum $discussion->forum");
aaf7a9dc 475 continue;
f690562f 476 }
aaf7a9dc 477 if (! $course = get_record("course", "id", "$forum->course")) {
b140ae85 478 mtrace("Could not find course $forum->course");
aaf7a9dc 479 continue;
caadf009 480 }
65b0e537 481
aaf7a9dc 482 $canunsubscribe = ! forum_is_forcesubscribed($forum->id);
483 $canreply = forum_user_can_post($forum, $userto);
caadf009 484
caadf009 485
aaf7a9dc 486 $posttext .= "\n \n";
487 $posttext .= '=====================================================================';
488 $posttext .= "\n \n";
3849dae8 489 $posttext .= "$course->shortname -> $strforums -> ".format_string($forum->name,true);
aaf7a9dc 490 if ($discussion->name != $forum->name) {
c78ac798 491 $posttext .= " -> ".format_string($discussion->name,true);
caadf009 492 }
aaf7a9dc 493 $posttext .= "\n";
65b0e537 494
aaf7a9dc 495 $posthtml .= "<p><font face=\"sans-serif\">".
496 "<a target=\"_blank\" href=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</a> -> ".
497 "<a target=\"_blank\" href=\"$CFG->wwwroot/mod/forum/index.php?id=$course->id\">$strforums</a> -> ".
3849dae8 498 "<a target=\"_blank\" href=\"$CFG->wwwroot/mod/forum/view.php?f=$forum->id\">".format_string($forum->name,true)."</a>";
aaf7a9dc 499 if ($discussion->name == $forum->name) {
500 $posthtml .= "</font></p>";
caadf009 501 } else {
c78ac798 502 $posthtml .= " -> <a target=\"_blank\" href=\"$CFG->wwwroot/mod/forum/discuss.php?d=$discussion->id\">".format_string($discussion->name,true)."</a></font></p>";
caadf009 503 }
aaf7a9dc 504 $posthtml .= '<p>';
505
e1c6dde1 506 $postsarray = $discussionposts[$discussionid];
507 sort($postsarray);
508
f37da850 509 /// Create an empty array to use for marking read posts.
510 /// (I'm sure there's already a structure I can use here, but I can't be sure.)
511 $markread = array();
512
857b798b 513 foreach ($postsarray as $postid) {
aaf7a9dc 514 if (! $post = get_record("forum_posts", "id", "$postid")) {
b140ae85 515 mtrace("Error: Could not find post $postid");
aaf7a9dc 516 continue;
517 }
518 if (! $userfrom = get_record("user", "id", "$post->userid")) {
b140ae85 519 mtrace("Error: Could not find user $post->userid");
aaf7a9dc 520 continue;
521 }
522
857b798b 523 $userfrom->customheaders = array ("Precedence: Bulk");
524
525 if ($userto->maildigest == 2) {
aaf7a9dc 526 // Subjects only
527 $by = New stdClass;
528 $by->name = fullname($userfrom);
529 $by->date = userdate($post->modified);
17dc3f3c 530 $posttext .= "\n".format_string($post->subject,true).' '.get_string("bynameondate", "forum", $by);
aaf7a9dc 531 $posttext .= "\n---------------------------------------------------------------------";
532
839f2456 533 $by->name = "<a target=\"_blank\" href=\"$CFG->wwwroot/user/view.php?id=$userfrom->id&amp;course=$course->id\">$by->name</a>";
17dc3f3c 534 $posthtml .= '<div><a target="_blank" href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.$discussion->id.'#'.$post->id.'">'.format_string($post->subject,true).'</a> '.get_string("bynameondate", "forum", $by).'</div>';
857b798b 535
536 } else {
aaf7a9dc 537 // The full treatment
538 $posttext .= forum_make_mail_text($course, $forum, $discussion, $post, $userfrom, $userto, true);
add3201e 539 $posthtml .= forum_make_mail_post($post, $userfrom, $userto, $course, false, $canreply, true, false);
f37da850 540
541 /// Create an array of postid's for this user to mark as read.
eaf50aef 542 if (!$CFG->forum_usermarksread &&
543 forum_tp_can_track_forums($forum, $userto) &&
544 forum_tp_is_tracked($forum, $userto->id)) {
f37da850 545 $markread[$post->id]->post = $post;
546 $markread[$post->id]->forumid = $forum->id;
547 }
aaf7a9dc 548 }
549 }
550 if ($canunsubscribe) {
551 $posthtml .= "\n<div align=\"right\"><font size=\"1\"><a href=\"$CFG->wwwroot/mod/forum/subscribe.php?id=$forum->id\">".get_string("unsubscribe", "forum")."</a></font></div>";
857b798b 552 } else {
aaf7a9dc 553 $posthtml .= "\n<div align=\"right\"><font size=\"1\">".get_string("everyoneissubscribed", "forum")."</font></div>";
554 }
555 $posthtml .= '<hr size="1" noshade="noshade" /></p>';
caadf009 556 }
a0330747 557 $posthtml .= '</body>';
caadf009 558
379a42cb 559 if($userto->mailformat != 1) {
560 // This user DOESN'T want to receive HTML
561 $posthtml = '';
562 }
563
8f0cd6ef 564 if (!$mailresult = email_to_user($userto, $site->shortname, $postsubject, $posttext, $posthtml,
50a26903 565 '', '', $CFG->forum_replytouser)) {
b140ae85 566 mtrace("ERROR!");
aaf7a9dc 567 echo "Error: mod/forum/cron.php: Could not send out digest mail to user $userto->id ($userto->email)... not trying again.\n";
568 add_to_log($course->id, 'forum', 'mail digest error', '', '', $cm->id, $userto->id);
b6268a0e 569 } else if ($mailresult === 'emailstop') {
50a26903 570 add_to_log($course->id, 'forum', 'mail digest blocked', '', '', $cm->id, $userto->id);
aaf7a9dc 571 } else {
b140ae85 572 mtrace("success.");
aaf7a9dc 573 $usermailcount++;
e3ff14ca 574
6ea5ebd4 575 /// Mark post as read if forum_usermarksread is set off
576 if (!$CFG->forum_usermarksread &&
577 forum_tp_can_track_forums($forum->id, $userto) &&
578 forum_tp_is_tracked($forum->id, $userto->id)) {
579 foreach ($markread as $postinfo) {
580 if (!forum_tp_mark_post_read($userto->id, $postinfo->post, $postinfo->forumid)) {
581 mtrace("Error: mod/forum/cron.php: Could not mark post $postid read for user $userto->id".
582 " while sending digest email.");
f37da850 583 }
584 }
6ea5ebd4 585 }
3d94772d 586 }
caadf009 587 }
caadf009 588 }
589 }
590
d658167f 591 if(!empty($usermailcount)) {
b140ae85 592 mtrace(get_string('digestsentusers', 'forum', $usermailcount));
aaf7a9dc 593 }
594
ec2137ba 595 if (!empty($realuser)) { // Restore real USER if necessary
596 $USER = $realuser;
597 }
598
f37da850 599 if (($lastreadclean = get_record("config", "name", "forum_lastreadclean"))) {
600 $cleantime = mktime($CFG->forum_cleanreadtime, 0);
601 $timenow = time();
602 if (($timenow > $cleantime) && ($lastreadclean->value+(24*3600) < $timenow)) {
603 $lastreadclean->value = $timenow;
604 update_record("config", $lastreadclean);
605 forum_tp_clean_read_records();
606 }
607 } else {
608 $lastreadclean->name = 'forum_lastreadclean';
609 $lastreadclean->value = time();
610 insert_record("config", $lastreadclean);
611 }
612
613
caadf009 614 return true;
615}
616
aaf7a9dc 617function forum_make_mail_text($course, $forum, $discussion, $post, $userfrom, $userto, $bare = false) {
618 global $CFG;
619
aaf7a9dc 620 $by = New stdClass;
621 $by->name = fullname($userfrom, isteacher($course->id, $userto->id));
622 $by->date = userdate($post->modified, "", $userto->timezone);
623
624 $strbynameondate = get_string('bynameondate', 'forum', $by);
625
64762ddc 626 $strforums = get_string('forums', 'forum');
627
aaf7a9dc 628 $canunsubscribe = ! forum_is_forcesubscribed($forum->id);
629 $canreply = forum_user_can_post($forum, $userto);
630
631 $posttext = '';
632
633 if(!$bare) {
3849dae8 634 $posttext = "$course->shortname -> $strforums -> ".format_string($forum->name,true);
aaf7a9dc 635
636 if ($discussion->name != $forum->name) {
c78ac798 637 $posttext .= " -> ".format_string($discussion->name,true);
aaf7a9dc 638 }
639 }
640
641 $posttext .= "\n---------------------------------------------------------------------\n";
17dc3f3c 642 $posttext .= format_string($post->subject,true);
aaf7a9dc 643 if($bare) {
644 $posttext .= " ($CFG->wwwroot/mod/forum/discuss.php?d=$discussion->id#$post->id)";
645 }
646 $posttext .= "\n".$strbynameondate."\n";
647 $posttext .= "---------------------------------------------------------------------\n";
648 $posttext .= format_text_email($post->message, $post->format);
649 $posttext .= "\n\n";
650 if ($post->attachment) {
651 $post->course = $course->id;
652 $post->forum = $forum->id;
653 $posttext .= forum_print_attachments($post, "text");
654 }
655 if (!$bare && $canreply) {
656 $posttext .= "---------------------------------------------------------------------\n";
657 $posttext .= get_string("postmailinfo", "forum", $course->shortname)."\n";
658 $posttext .= "$CFG->wwwroot/mod/forum/post.php?reply=$post->id\n";
659 }
660 if (!$bare && $canunsubscribe) {
661 $posttext .= "\n---------------------------------------------------------------------\n";
662 $posttext .= get_string("unsubscribe", "forum");
663 $posttext .= ": $CFG->wwwroot/mod/forum/subscribe.php?id=$forum->id\n";
664 }
665
666 return $posttext;
667}
668
669function forum_make_mail_html($course, $forum, $discussion, $post, $userfrom, $userto) {
670 global $CFG;
671
a0288610 672 if ($userto->mailformat != 1) { // Needs to be HTML
673 return '';
674 }
aaf7a9dc 675
a0288610 676 $strforums = get_string('forums', 'forum');
677 $canreply = forum_user_can_post($forum, $userto);
678 $canunsubscribe = ! forum_is_forcesubscribed($forum->id);
aaf7a9dc 679
a0288610 680 $posthtml = '<head>';
681 foreach ($CFG->stylesheets as $stylesheet) {
682 $posthtml .= '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'" />'."\n";
683 }
684 $posthtml .= '</head>';
f2379d2d 685 $posthtml .= "\n<body id=\"email\">\n\n";
aaf7a9dc 686
f2379d2d 687 $posthtml .= '<div class="navbar">'.
a0288610 688 '<a target="_blank" href="'.$CFG->wwwroot.'/course/view.php?id='.$course->id.'">'.$course->shortname.'</a> &raquo; '.
689 '<a target="_blank" href="'.$CFG->wwwroot.'/mod/forum/index.php?id='.$course->id.'">'.$strforums.'</a> &raquo; '.
690 '<a target="_blank" href="'.$CFG->wwwroot.'/mod/forum/view.php?f='.$forum->id.'">'.format_string($forum->name,true).'</a>';
691 if ($discussion->name == $forum->name) {
692 $posthtml .= '</div>';
aaf7a9dc 693 } else {
a0288610 694 $posthtml .= ' &raquo; <a target="_blank" href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.$discussion->id.'">'.
695 format_string($discussion->name,true).'</a></div>';
aaf7a9dc 696 }
a0288610 697 $posthtml .= forum_make_mail_post($post, $userfrom, $userto, $course, false, $canreply, true, false);
698
699 if ($canunsubscribe) {
700 $posthtml .= '<br /><div class="unsubscribelink"><a href="'.$CFG->wwwroot.'/mod/forum/subscribe.php?id='.$forum->id.'">'.
701 get_string('unsubscribe', 'forum').'</a></div>';
702 }
703
f2379d2d 704 $posthtml .= '</body>';
705
a0288610 706 return $posthtml;
aaf7a9dc 707}
708
caadf009 709function forum_user_outline($course, $user, $mod, $forum) {
710
1f48942e 711 if ($posts = forum_get_user_posts($forum->id, $user->id)) {
caadf009 712 $result->info = get_string("numposts", "forum", count($posts));
713
714 $lastpost = array_pop($posts);
715 $result->time = $lastpost->modified;
716 return $result;
717 }
718 return NULL;
719}
720
721
722function forum_user_complete($course, $user, $mod, $forum) {
723 global $CFG;
724
1f48942e 725 if ($posts = forum_get_user_posts($forum->id, $user->id)) {
caadf009 726 foreach ($posts as $post) {
e3ff14ca 727
f37da850 728 $post->forum = $forum->id;
497588fe 729 forum_print_post($post, $course->id, $ownpost=false, $reply=false, $link=false, $rate=false);
caadf009 730 }
731
732 } else {
41905731 733 echo "<p>".get_string("noposts", "forum")."</p>";
caadf009 734 }
caadf009 735}
736
f8716988 737function forum_print_overview($course,$lastaccess) {
0d6b9d4f 738 global $USER, $CFG;
f8716988 739
29dc9751 740 print_heading(get_string("modulenameplural", "forum"));
f8716988 741 if (!$forums = get_all_instances_in_course("forum", $course)) {
29dc9751 742 echo get_string('nothingnew','forum',$course->fullname);
f8716988 743 return;
744 }
745 // get all forum logs in ONE query (much better!)
95d71ad3 746 if (!$new = get_records_sql("SELECT instance,cmid,COUNT(l.id) as count FROM {$CFG->prefix}log l "
747 ." JOIN {$CFG->prefix}course_modules cm ON cm.id = cmid "
748 ." WHERE time > $lastaccess AND l.course = ".$course->id
749 ." AND l.module = 'forum' AND action LIKE 'add%' "
750 ." AND userid != ".$USER->id." GROUP BY cmid,instance")) {
751 $new = array(); // avoid warnings;
752 }
f8716988 753 foreach ($forums as $forum) {
754 $count = 0;
755 $unread = 0;
756 $showunread = false;
757 // either we have something from logs, or trackposts, or nothing.
758 if (array_key_exists($forum->id, $new) && !empty($new[$forum->id])) {
759 $count = $new[$forum->id]->count;
90558ec4 760 }
f8716988 761 if (forum_tp_can_track_forums($forum)) {
762 $showunread = true;
763 if (isset($forum->groupmode)) {
764 $groupmode = groupmode($course, $forum); /// Can do this because forum->groupmode is defined
765 } else {
766 $groupmode = NOGROUPS;
767 }
768 $groupid = ($groupmode==SEPARATEGROUPS && !isteacheredit($course->id)) ? $currentgroup : false;
769 $unread = forum_tp_count_forum_posts($forum->id, $groupid) -
770 forum_tp_count_forum_read_records($USER->id, $forum->id, $groupid);
0d6b9d4f 771 }
f8716988 772 if ($count > 0 || $unread > 0) {
773 $str .= '<a title="'.get_string('forums').'" href="'.$CFG->wwwroot.'/mod/forum/view.php?f='.$forum->id.'">'
774 .get_string('forum','forum').': '.$forum->name.'</a><br />';
775 $str .= get_string('overviewnumpostssince','forum',$count)."<br />";
776 if (!empty($showunread)) {
777 $str .= get_string('overviewnumunread','forum',$unread).'<br />';
778 }
779 }
780 }
f8716988 781 if (!empty($str)) {
0d6b9d4f 782 echo $str;
f8716988 783 } else {
29dc9751 784 echo get_string('nothingnew','forum',$course->fullname);
0d6b9d4f 785 }
786}
787
1b5910c4 788function forum_print_recent_activity($course, $isteacher, $timestart) {
65b0e537 789/// Given a course and a date, prints a summary of all the new
cc3655a2 790/// messages posted in the course since that date
791
3d891989 792 global $CFG;
caadf009 793
794 $heading = false;
795 $content = false;
796
8f7dc7f1 797 if (!$logs = get_records_select('log', 'time > \''.$timestart.'\' AND '.
798 'course = \''.$course->id.'\' AND '.
799 'module = \'forum\' AND '.
800 'action LIKE \'add %\' ', 'time ASC')){
1b5910c4 801 return false;
802 }
803
8f7dc7f1 804 $strftimerecent = get_string('strftimerecent');
dcde9f02 805
d05956ac 806 $isteacheredit = isteacheredit($course->id);
807 $mygroupid = mygroupid($course->id);
808
809 $groupmode = array(); /// To cache group modes
810
1b5910c4 811 foreach ($logs as $log) {
812 //Get post info, I'll need it later
ac1d9a22 813 if ($post = forum_get_post_from_log($log)) {
814 //Create a temp valid module structure (course,id)
815 $tempmod->course = $log->course;
816 $tempmod->id = $post->forum;
817 //Obtain the visible property from the instance
8f7dc7f1 818 $modvisible = instance_is_visible('forum', $tempmod);
ac1d9a22 819 }
d05956ac 820
ac1d9a22 821 //Only if the post exists and mod is visible
822 if ($post && $modvisible) {
823 /// Check whether this is for teachers only
8f7dc7f1 824 $teacheronly = '';
825 if ($post->forumtype == 'teacher') {
826 if ($isteacher) {
827 $teacheronly = 'class=\'teacheronly\'';
828 } else {
829 continue;
b91d6dcd 830 }
ac1d9a22 831 }
832 /// Check whether this is belongs to a discussion in a group that
833 /// should NOT be accessible to the current user
b91d6dcd 834
ac1d9a22 835 if (!$isteacheredit and $post->groupid != -1) { /// Editing teachers or open discussions
836 if (!isset($cm[$post->forum])) {
8f7dc7f1 837 $cm[$post->forum] = get_coursemodule_from_instance('forum', $post->forum, $course->id);
838 $groupmode[$post->forum] = groupmode($course, $cm[$post->forum]);
436a7cae 839 }
8f7dc7f1 840 if ($groupmode[$post->forum]) {
fa22fd5f 841 //hope i didn't break anything
842 if (!@in_array($mygroupid, $post->groupid))/*$mygroupid != $post->groupid*/{
ac1d9a22 843 continue;
844 }
1b5910c4 845 }
caadf009 846 }
ac1d9a22 847
848 if (! $heading) {
8f7dc7f1 849 print_headline(get_string('newforumposts', 'forum').':');
ac1d9a22 850 $heading = true;
851 $content = true;
852 }
853 $date = userdate($post->modified, $strftimerecent);
8f7dc7f1 854
855 $subjectclass = ($log->action == 'add discussion') ? ' bold' : '';
856
a4f7aac1 857 echo '<div class="head'.$teacheronly.'">'.
858 '<div class="date">'.$date.'</div>'.
859 '<div class="name">'.fullname($post, $isteacher).'</div>'.
860 '</div>';
861 echo '<div class="info'.$subjectclass.'">';
8f7dc7f1 862 echo '"<a href="'.$CFG->wwwroot.'/mod/forum/'.str_replace('&', '&amp;', $log->url).'">';
17dc3f3c 863 $post->subject = break_up_long_words(format_string($post->subject,true));
8f7dc7f1 864 echo $post->subject;
865 echo '</a>"</div>';
caadf009 866 }
867 }
1b5910c4 868
caadf009 869 return $content;
870}
871
872
873function forum_grades($forumid) {
874/// Must return an array of grades, indexed by user, and a max grade.
caadf009 875
4db9d14d 876 if (!$forum = get_record("forum", "id", $forumid)) {
877 return false;
878 }
879 if (!$forum->assessed) {
880 return false;
881 }
d6bdd9d5 882 $scalemenu = make_grades_menu($forum->scale);
02ebf404 883
884 $currentuser = 0;
885 $ratingsuser = array();
886
1f48942e 887 if ($ratings = forum_get_user_grades($forumid)) {
02ebf404 888 foreach ($ratings as $rating) { // Ordered by user
889 if ($currentuser and $rating->userid != $currentuser) {
890 if (!empty($ratingsuser)) {
d6bdd9d5 891 if ($forum->scale < 0) {
892 $return->grades[$currentuser] = forum_get_ratings_mean(0, $scalemenu, $ratingsuser);
893 $return->grades[$currentuser] .= "<br />".forum_get_ratings_summary(0, $scalemenu, $ratingsuser);
894 } else {
895 $total = 0;
896 $count = 0;
897 foreach ($ratingsuser as $ra) {
898 $total += $ra;
899 $count ++;
900 }
901 $return->grades[$currentuser] = format_float($total/$count, 2);
902 }
02ebf404 903 } else {
904 $return->grades[$currentuser] = "";
905 }
906 $ratingsuser = array();
caadf009 907 }
02ebf404 908 $ratingsuser[] = $rating->rating;
909 $currentuser = $rating->userid;
caadf009 910 }
02ebf404 911 if (!empty($ratingsuser)) {
d6bdd9d5 912 if ($forum->scale < 0) {
913 $return->grades[$currentuser] = forum_get_ratings_mean(0, $scalemenu, $ratingsuser);
914 $return->grades[$currentuser] .= "<br />".forum_get_ratings_summary(0, $scalemenu, $ratingsuser);
915 } else {
916 $total = 0;
917 $count = 0;
918 foreach ($ratingsuser as $ra) {
919 $total += $ra;
920 $count ++;
921 }
922 $return->grades[$currentuser] = format_float((float)$total/(float)$count, 2);
923 }
02ebf404 924 } else {
925 $return->grades[$currentuser] = "";
caadf009 926 }
927 } else {
928 $return->grades = array();
929 }
930
d6bdd9d5 931 if ($forum->scale < 0) {
932 $return->maxgrade = "";
933 } else {
934 $return->maxgrade = $forum->scale;
935 }
caadf009 936 return $return;
937}
938
05855091 939function forum_get_participants($forumid) {
940//Returns the users with data in one forum
65b0e537 941//(users with records in forum_subscriptions, forum_posts and forum_ratings, students)
05855091 942
943 global $CFG;
944
945 //Get students from forum_subscriptions
95e72c12 946 $st_subscriptions = get_records_sql("SELECT DISTINCT u.id, u.id
05855091 947 FROM {$CFG->prefix}user u,
948 {$CFG->prefix}forum_subscriptions s
949 WHERE s.forum = '$forumid' and
65b0e537 950 u.id = s.userid");
05855091 951 //Get students from forum_posts
95e72c12 952 $st_posts = get_records_sql("SELECT DISTINCT u.id, u.id
05855091 953 FROM {$CFG->prefix}user u,
954 {$CFG->prefix}forum_discussions d,
955 {$CFG->prefix}forum_posts p
956 WHERE d.forum = '$forumid' and
957 p.discussion = d.id and
958 u.id = p.userid");
959
960 //Get students from forum_ratings
95e72c12 961 $st_ratings = get_records_sql("SELECT DISTINCT u.id, u.id
05855091 962 FROM {$CFG->prefix}user u,
963 {$CFG->prefix}forum_discussions d,
964 {$CFG->prefix}forum_posts p,
965 {$CFG->prefix}forum_ratings r
966 WHERE d.forum = '$forumid' and
967 p.discussion = d.id and
968 r.post = p.id and
969 u.id = r.userid");
970
971 //Add st_posts to st_subscriptions
972 if ($st_posts) {
973 foreach ($st_posts as $st_post) {
974 $st_subscriptions[$st_post->id] = $st_post;
975 }
976 }
977 //Add st_ratings to st_subscriptions
978 if ($st_ratings) {
979 foreach ($st_ratings as $st_rating) {
980 $st_subscriptions[$st_rating->id] = $st_rating;
981 }
982 }
983 //Return st_subscriptions array (it contains an array of unique users)
984 return ($st_subscriptions);
985}
caadf009 986
0f1a97c2 987function forum_scale_used ($forumid,$scaleid) {
988//This function returns if a scale is being used by one forum
65b0e537 989
0f1a97c2 990 $return = false;
65b0e537 991
0f1a97c2 992 $rec = get_record("forum","id","$forumid","scale","-$scaleid");
65b0e537 993
fa22fd5f 994 if (!empty($rec) && !empty($scaleid)) {
0f1a97c2 995 $return = true;
996 }
65b0e537 997
0f1a97c2 998 return $return;
999}
1000
9fa49e22 1001/// SQL FUNCTIONS ///////////////////////////////////////////////////////////
1002
1f48942e 1003function forum_get_post_full($postid) {
1004/// Gets a post with all info ready for forum_print_post
77efef3e 1005/// Most of these joins are just to get the forum id
1f48942e 1006 global $CFG;
1007
8fbdc992 1008 return get_record_sql("SELECT p.*, d.forum, u.firstname, u.lastname, u.email, u.picture
6572ab71 1009 FROM {$CFG->prefix}forum_posts p
1010 LEFT JOIN {$CFG->prefix}forum_discussions d ON p.discussion = d.id
6572ab71 1011 LEFT JOIN {$CFG->prefix}user u ON p.userid = u.id
1012 WHERE p.id = '$postid'");
1f48942e 1013}
1014
77efef3e 1015function forum_get_discussion_posts($discussion, $sort, $forumid) {
1f48942e 1016/// Gets posts with all info ready for forum_print_post
77efef3e 1017/// We pass forumid in because we always know it so no need to make a
1018/// complicated join to find it out.
1f48942e 1019 global $CFG;
1020
77efef3e 1021 return get_records_sql("SELECT p.*, $forumid AS forum, u.firstname, u.lastname, u.email, u.picture
10426cef 1022 FROM {$CFG->prefix}forum_posts p
10426cef 1023 LEFT JOIN {$CFG->prefix}user u ON p.userid = u.id
65b0e537 1024 WHERE p.discussion = $discussion
10426cef 1025 AND p.parent > 0 $sort");
1f48942e 1026}
1027
77efef3e 1028function forum_get_child_posts($parent, $forumid) {
1f48942e 1029/// Gets posts with all info ready for forum_print_post
77efef3e 1030/// We pass forumid in because we always know it so no need to make a
1031/// complicated join to find it out.
1f48942e 1032 global $CFG;
1033
77efef3e 1034 return get_records_sql("SELECT p.*, $forumid AS forum, u.firstname, u.lastname, u.email, u.picture
10426cef 1035 FROM {$CFG->prefix}forum_posts p
10426cef 1036 LEFT JOIN {$CFG->prefix}user u ON p.userid = u.id
65b0e537 1037 WHERE p.parent = '$parent'
1f48942e 1038 ORDER BY p.created ASC");
1039}
1040
1041
4f321bdb 1042function forum_search_posts($searchterms, $courseid, $page=0, $recordsperpage=50, &$totalcount, $groupid=0, $extrasql='') {
8b9c7aa0 1043/// Returns a list of posts found using an array of search terms
1044/// eg word +word -word
1045///
9fa49e22 1046 global $CFG;
855c0839 1047 require_once($CFG->libdir.'/searchlib.php');
e3ff14ca 1048
9fa49e22 1049 if (!isteacher($courseid)) {
1050 $notteacherforum = "AND f.type <> 'teacher'";
4cabd355 1051 $forummodule = get_record("modules", "name", "forum");
453b5314 1052 $onlyvisible = "AND d.forum = f.id AND f.id = cm.instance AND cm.visible = 1 AND cm.module = $forummodule->id";
1053 $onlyvisibletable = ", {$CFG->prefix}course_modules cm, {$CFG->prefix}forum f";
c7a5b3b1 1054 if ($groupid) {
1055 $separategroups = SEPARATEGROUPS;
4dca83a7 1056 $selectgroup = " AND ( NOT (cm.groupmode='$separategroups'".
fa22fd5f 1057 " OR (c.groupmode='$separategroups' AND c.groupmodeforce='1') )";//.
1058 foreach ($groupid as $index => $value){
1059 $selectgroup .= " OR d.groupid = '$value'";
1060 }
1061 $selectgroup .= ")";
1062
1063 // " OR d.groupid = '$groupid')";
453b5314 1064 $selectcourse = " AND d.course = '$courseid' AND c.id='$courseid'";
1065 $coursetable = ", {$CFG->prefix}course c";
c7a5b3b1 1066 } else {
1067 $selectgroup = '';
453b5314 1068 $selectcourse = " AND d.course = '$courseid'";
1069 $coursetable = '';
c7a5b3b1 1070 }
9fa49e22 1071 } else {
1072 $notteacherforum = "";
c7a5b3b1 1073 $selectgroup = '';
4cabd355 1074 $onlyvisible = "";
1075 $onlyvisibletable = "";
453b5314 1076 $coursetable = '';
a702e657 1077 if ($courseid == SITEID && isadmin()) {
1078 $selectcourse = '';
1079 } else {
1080 $selectcourse = " AND d.course = '$courseid'";
1081 }
9fa49e22 1082 }
1083
e6ae4dc8 1084 $limit = sql_paging_limit($page, $recordsperpage);
97485d07 1085
63d99fcb 1086 /// Some differences in syntax for PostgreSQL
1087 if ($CFG->dbtype == "postgres7") {
a74f950c 1088 $LIKE = "ILIKE"; // case-insensitive
2b4c64e9 1089 $NOTLIKE = "NOT ILIKE"; // case-insensitive
1090 $REGEXP = "~*";
1091 $NOTREGEXP = "!~*";
b800ac5a 1092 } else {
a74f950c 1093 $LIKE = "LIKE";
2b4c64e9 1094 $NOTLIKE = "NOT LIKE";
a74f950c 1095 $REGEXP = "REGEXP";
2b4c64e9 1096 $NOTREGEXP = "NOT REGEXP";
c4c57597 1097 }
1098
b800ac5a 1099 $messagesearch = "";
855c0839 1100 $searchstring = "";
1101 // Need to concat these back together for parser to work.
1102 foreach($searchterms as $searchterm){
1103 if ($searchstring != "") {
1104 $searchstring .= " ";
63d99fcb 1105 }
855c0839 1106 $searchstring .= $searchterm;
b800ac5a 1107 }
1108
855c0839 1109 // We need to allow quoted strings for the search. The quotes *should* be stripped
1110 // by the parser, but this should be examined carefully for security implications.
1111 $searchstring = str_replace("\\\"","\"",$searchstring);
1112 $parser = new search_parser();
f99fcffe 1113 $lexer = new search_lexer($parser);
e6ae4dc8 1114
855c0839 1115 if ($lexer->parse($searchstring)) {
1116 $parsearray = $parser->get_parsed_array();
77ffdf4b 1117 $messagesearch = search_generate_SQL($parsearray,'p.message','p.subject','p.userid','u.id','u.firstname','u.lastname','p.modified', 'd.forum');
855c0839 1118 }
e3ff14ca 1119
65b0e537 1120 $selectsql = "{$CFG->prefix}forum_posts p,
1121 {$CFG->prefix}forum_discussions d,
453b5314 1122 {$CFG->prefix}user u $onlyvisibletable $coursetable
855c0839 1123 WHERE ($messagesearch)
65b0e537 1124 AND p.userid = u.id
453b5314 1125 AND p.discussion = d.id $selectcourse $notteacherforum $onlyvisible $selectgroup $extrasql";
65b0e537 1126
8b9c7aa0 1127 $totalcount = count_records_sql("SELECT COUNT(*) FROM $selectsql");
b800ac5a 1128
77efef3e 1129 return get_records_sql("SELECT p.*,d.forum, u.firstname,u.lastname,u.email,u.picture FROM
8b9c7aa0 1130 $selectsql ORDER BY p.modified DESC $limit");
9fa49e22 1131}
1132
63d99fcb 1133
9fa49e22 1134function forum_get_ratings($postid, $sort="u.firstname ASC") {
1135/// Returns a list of ratings for a particular post - sorted.
1136 global $CFG;
65b0e537 1137 return get_records_sql("SELECT u.*, r.rating, r.time
1138 FROM {$CFG->prefix}forum_ratings r,
9fa49e22 1139 {$CFG->prefix}user u
65b0e537 1140 WHERE r.post = '$postid'
1141 AND r.userid = u.id
9fa49e22 1142 ORDER BY $sort");
1143}
1144
3ecca1ee 1145function forum_get_unmailed_posts($starttime, $endtime) {
1f48942e 1146/// Returns a list of all new posts that have not been mailed yet
1147 global $CFG;
65b0e537 1148 return get_records_sql("SELECT p.*, d.course
1149 FROM {$CFG->prefix}forum_posts p,
1f48942e 1150 {$CFG->prefix}forum_discussions d
65b0e537 1151 WHERE p.mailed = 0
3ecca1ee 1152 AND p.created >= '$starttime'
1153 AND p.created < '$endtime'
c274b0e0 1154 AND p.discussion = d.id
1155 ORDER BY p.modified ASC");
1f48942e 1156}
1157
3ecca1ee 1158function forum_mark_old_posts_as_mailed($endtime) {
1159/// Marks posts before a certain time as being mailed already
1160 global $CFG;
c274b0e0 1161 return execute_sql("UPDATE {$CFG->prefix}forum_posts
1162 SET mailed = '1'
0362d553 1163 WHERE created < '$endtime' AND mailed ='0'");
3ecca1ee 1164}
1165
1f48942e 1166function forum_get_user_posts($forumid, $userid) {
1167/// Get all the posts for a user in a forum suitable for forum_print_post
1168 global $CFG;
1169
77efef3e 1170 return get_records_sql("SELECT p.*, d.forum, u.firstname, u.lastname, u.email, u.picture
65b0e537 1171 FROM {$CFG->prefix}forum f,
1172 {$CFG->prefix}forum_discussions d,
1173 {$CFG->prefix}forum_posts p,
1174 {$CFG->prefix}user u
1175 WHERE f.id = '$forumid'
1176 AND d.forum = f.id
1f48942e 1177 AND p.discussion = d.id
65b0e537 1178 AND p.userid = '$userid'
ebc3bd2b 1179 AND p.userid = u.id
1f48942e 1180 ORDER BY p.modified ASC");
1181}
1182
1183function forum_get_post_from_log($log) {
1184/// Given a log entry, return the forum post details for it.
1185 global $CFG;
1186
1187 if ($log->action == "add post") {
1188
8f7dc7f1 1189 return get_record_sql("SELECT p.*, f.type AS forumtype, d.forum, d.groupid,
1190 u.firstname, u.lastname, u.email, u.picture
65b0e537 1191 FROM {$CFG->prefix}forum_discussions d,
1192 {$CFG->prefix}forum_posts p,
8f7dc7f1 1193 {$CFG->prefix}forum f,
65b0e537 1194 {$CFG->prefix}user u
1195 WHERE p.id = '$log->info'
1196 AND d.id = p.discussion
1197 AND p.userid = u.id
8f7dc7f1 1198 AND u.deleted <> '1'
1199 AND f.id = d.forum");
1f48942e 1200
1201
1202 } else if ($log->action == "add discussion") {
1203
8f7dc7f1 1204 return get_record_sql("SELECT p.*, f.type AS forumtype, d.forum, d.groupid,
1205 u.firstname, u.lastname, u.email, u.picture
65b0e537 1206 FROM {$CFG->prefix}forum_discussions d,
1207 {$CFG->prefix}forum_posts p,
8f7dc7f1 1208 {$CFG->prefix}forum f,
65b0e537 1209 {$CFG->prefix}user u
1210 WHERE d.id = '$log->info'
1211 AND d.firstpost = p.id
1212 AND p.userid = u.id
8f7dc7f1 1213 AND u.deleted <> '1'
1214 AND f.id = d.forum");
1f48942e 1215 }
1216 return NULL;
1217}
1218
d05956ac 1219function forum_get_firstpost_from_discussion($discussionid) {
1220/// Given a discussion id, return the first post from the discussion
1221 global $CFG;
1222
1223 return get_record_sql("SELECT p.*
65b0e537 1224 FROM {$CFG->prefix}forum_discussions d,
d05956ac 1225 {$CFG->prefix}forum_posts p
65b0e537 1226 WHERE d.id = '$discussionid'
d05956ac 1227 AND d.firstpost = p.id ");
1228}
1229
1f48942e 1230
1231function forum_get_user_grades($forumid) {
1232/// Get all user grades for a forum
1233 global $CFG;
1234
ebc3bd2b 1235 return get_records_sql("SELECT r.id, p.userid, r.rating
65b0e537 1236 FROM {$CFG->prefix}forum_discussions d,
1237 {$CFG->prefix}forum_posts p,
1f48942e 1238 {$CFG->prefix}forum_ratings r
65b0e537 1239 WHERE d.forum = '$forumid'
1f48942e 1240 AND p.discussion = d.id
02ebf404 1241 AND r.post = p.id
1242 ORDER by p.userid ");
1f48942e 1243}
1244
1245
a48e8c4b 1246function forum_count_discussion_replies($forum='0', $course='0', $user='0') {
1247// Returns an array of counts of replies to each discussion (optionally in one forum or course and/or user)
1f48942e 1248 global $CFG;
1249
a48e8c4b 1250 $forumselect = $courseselect = $userselect = '';
1251
1f48942e 1252 if ($forum) {
1253 $forumselect = " AND d.forum = '$forum'";
a48e8c4b 1254 }
1255 if ($course) {
1256 $courseselect = " AND d.course = '$course'";
1257 }
1258 if ($user) {
1259 $userselect = " AND d.userid = '$user'";
1f48942e 1260 }
3599e487 1261 return get_records_sql("SELECT p.discussion, (count(*)) as replies, max(p.id) as lastpostid
65b0e537 1262 FROM {$CFG->prefix}forum_posts p,
1f48942e 1263 {$CFG->prefix}forum_discussions d
a48e8c4b 1264 WHERE p.parent > 0 $forumselect $courseselect $userselect
1c887009 1265 AND p.discussion = d.id
1f48942e 1266 GROUP BY p.discussion");
1267}
1268
1269function forum_count_unrated_posts($discussionid, $userid) {
1270// How many unrated posts are in the given discussion for a given user?
1271 global $CFG;
1272 if ($posts = get_record_sql("SELECT count(*) as num
1273 FROM {$CFG->prefix}forum_posts
65b0e537 1274 WHERE parent > 0
1275 AND discussion = '$discussionid'
ebc3bd2b 1276 AND userid <> '$userid' ")) {
1f48942e 1277
65b0e537 1278 if ($rated = get_record_sql("SELECT count(*) as num
1279 FROM {$CFG->prefix}forum_posts p,
1f48942e 1280 {$CFG->prefix}forum_ratings r
1281 WHERE p.discussion = '$discussionid'
65b0e537 1282 AND p.id = r.post
ebc3bd2b 1283 AND r.userid = '$userid'")) {
1f48942e 1284 $difference = $posts->num - $rated->num;
1285 if ($difference > 0) {
1286 return $difference;
1287 } else {
1288 return 0; // Just in case there was a counting error
1289 }
1290 } else {
1291 return $posts->num;
1292 }
1293 } else {
1294 return 0;
1295 }
1296}
1297
65b0e537 1298function forum_get_discussions($forum="0", $forumsort="d.timemodified DESC",
13597d01 1299 $user=0, $fullpost=true, $visiblegroups=-1, $limit=0, $userlastmodified=false) {
1f48942e 1300/// Get all discussions in a forum
1301 global $CFG;
1302
1303 if ($user) {
1304 $userselect = " AND u.id = '$user' ";
1305 } else {
1306 $userselect = "";
1307 }
2862b309 1308
90ec387a 1309 if ($limit) {
1310 $limit = " LIMIT $limit ";
1311 } else {
1312 $limit = "";
1313 }
8f0cd6ef 1314
2862b309 1315 if ($visiblegroups == -1) {
02509fe6 1316 $groupselect = "";
2862b309 1317 } else {
1318 $groupselect = " AND (d.groupid = '$visiblegroups' OR d.groupid = '-1') ";
02509fe6 1319 }
2862b309 1320
29507631 1321 if (empty($forumsort)) {
1322 $forumsort = "d.timemodified DESC";
1323 }
2ab968e9 1324 if (empty($fullpost)) {
b879effb 1325 $postdata = "p.id,p.subject,p.modified,p.discussion,p.userid";
2ab968e9 1326 } else {
1327 $postdata = "p.*";
1328 }
9197e147 1329
13597d01 1330 if (empty($userlastmodified)) { // We don't need to know this
1331 $umfields = '';
1332 $umtable = '';
13597d01 1333 } else {
096de9ad 1334 $umfields = ', um.firstname AS umfirstname, um.lastname AS umlastname';
cfdc10e6 1335 $umtable = ' LEFT JOIN '.$CFG->prefix.'user um on (d.usermodified = um.id)';
13597d01 1336 }
1337
80d3523e 1338 //TODO: there must be a nice way to do this that keeps both postgres and mysql 3.2x happy but I can't find it right now.
1339 if ($CFG->dbtype == 'postgres7') {
1340 return get_records_sql("SELECT $postdata, d.name, d.timemodified, d.usermodified, d.groupid,
13597d01 1341 u.firstname, u.lastname, u.email, u.picture $umfields
93d58b30 1342 FROM {$CFG->prefix}forum_discussions d
1343 JOIN {$CFG->prefix}forum_posts p ON p.discussion = d.id
1344 JOIN {$CFG->prefix}user u ON p.userid = u.id
13597d01 1345 $umtable
65b0e537 1346 WHERE d.forum = '$forum'
65b0e537 1347 AND p.parent = 0
93d58b30 1348 $groupselect $userselect
90ec387a 1349 ORDER BY $forumsort $limit");
80d3523e 1350 } else {
1351 return get_records_sql("SELECT $postdata, d.name, d.timemodified, d.usermodified, d.groupid,
1352 u.firstname, u.lastname, u.email, u.picture $umfields
1353 FROM {$CFG->prefix}forum_discussions d,
1354 {$CFG->prefix}forum_posts p,
1355 {$CFG->prefix}user u
1356 $umtable
1357 WHERE d.forum = '$forum'
1358 AND p.discussion = d.id
1359 AND p.parent = 0
1360 AND p.userid = u.id $groupselect $userselect
1361 ORDER BY $forumsort $limit");
1362 }
1f48942e 1363}
1364
1365
1366
b656e2a9 1367function forum_get_user_discussions($courseid, $userid, $groupid=0) {
1368/// Get all discussions started by a particular user in a course (or group)
4f321bdb 1369/// This function no longer used ...
1f48942e 1370 global $CFG;
1371
b656e2a9 1372 if ($groupid) {
1373 $groupselect = " AND d.groupid = '$groupid' ";
1374 } else {
1375 $groupselect = "";
1376 }
1377
2862b309 1378 return get_records_sql("SELECT p.*, d.groupid, u.firstname, u.lastname, u.email, u.picture,
ebc3bd2b 1379 f.type as forumtype, f.name as forumname, f.id as forumid
65b0e537 1380 FROM {$CFG->prefix}forum_discussions d,
1381 {$CFG->prefix}forum_posts p,
1382 {$CFG->prefix}user u,
1f48942e 1383 {$CFG->prefix}forum f
65b0e537 1384 WHERE d.course = '$courseid'
1385 AND p.discussion = d.id
1386 AND p.parent = 0
1387 AND p.userid = u.id
1388 AND u.id = '$userid'
b656e2a9 1389 AND d.forum = f.id $groupselect
b8bf90c5 1390 ORDER BY p.created DESC");
1f48942e 1391}
1392
6673d7bd 1393function forum_subscribed_users($course, $forum, $groupid=0) {
1f48942e 1394/// Returns list of user objects that are subscribed to this forum
1395 global $CFG;
1396
6673d7bd 1397 if ($groupid) {
1398 $grouptables = ", {$CFG->prefix}groups_members g";
1399 $groupselect = " AND g.groupid = '$groupid' AND u.id = g.userid";
1400 } else {
1401 $grouptables = "";
1402 $groupselect = "";
1403 }
1404
709f0ec8 1405 if (forum_is_forcesubscribed($forum->id)) {
7b5944cd 1406 if ($forum->type == "teacher") {
1407 return get_course_teachers($course->id); // Only teachers can be subscribed to teacher forums
adaf3928 1408 } else {
7b5944cd 1409 return get_course_users($course->id); // Otherwise get everyone in the course
1f48942e 1410 }
1411 }
aaf7a9dc 1412 return get_records_sql("SELECT u.id, u.username, u.firstname, u.lastname, u.maildisplay, u.mailformat, u.maildigest, u.emailstop,
4822e9d2 1413 u.email, u.city, u.country, u.lastaccess, u.lastlogin, u.picture, u.timezone, u.lang, u.trackforums
65b0e537 1414 FROM {$CFG->prefix}user u,
6673d7bd 1415 {$CFG->prefix}forum_subscriptions s $grouptables
1f48942e 1416 WHERE s.forum = '$forum->id'
65b0e537 1417 AND s.userid = u.id
6673d7bd 1418 AND u.deleted <> 1 $groupselect
7c81b6e2 1419 ORDER BY u.email ASC");
1f48942e 1420}
9fa49e22 1421
067675c0 1422
1423
caadf009 1424/// OTHER FUNCTIONS ///////////////////////////////////////////////////////////
f93f848a 1425
1426
11b0c469 1427function forum_get_course_forum($courseid, $type) {
1428// How to set up special 1-per-course forums
a6fcdf98 1429 global $CFG;
1430
29cbd93a 1431 if ($forums = get_records_select("forum", "course = '$courseid' AND type = '$type'", "id ASC")) {
65b0e537 1432 // There should always only be ONE, but with the right combination of
29cbd93a 1433 // errors there might be more. In this case, just return the oldest one (lowest ID).
1434 foreach ($forums as $forum) {
1435 return $forum; // ie the first one
11b0c469 1436 }
8daaf761 1437 }
e6874d9f 1438
8daaf761 1439 // Doesn't exist, so create one now.
1440 $forum->course = $courseid;
1441 $forum->type = "$type";
1442 switch ($forum->type) {
1443 case "news":
65a3ef30 1444 $forum->name = addslashes(get_string("namenews", "forum"));
1445 $forum->intro = addslashes(get_string("intronews", "forum"));
906fef94 1446 $forum->forcesubscribe = FORUM_FORCESUBSCRIBE;
8daaf761 1447 $forum->open = 1; // 0 - no, 1 - posts only, 2 - discuss and post
1448 $forum->assessed = 0;
709f0ec8 1449 if ($courseid == SITEID) {
1450 $forum->name = get_string("sitenews");
1451 $forum->forcesubscribe = 0;
8f0cd6ef 1452 }
8daaf761 1453 break;
1454 case "social":
65a3ef30 1455 $forum->name = addslashes(get_string("namesocial", "forum"));
1456 $forum->intro = addslashes(get_string("introsocial", "forum"));
8daaf761 1457 $forum->open = 2; // 0 - no, 1 - posts only, 2 - discuss and post
1458 $forum->assessed = 0;
1459 $forum->forcesubscribe = 0;
1460 break;
1461 case "teacher":
65a3ef30 1462 $forum->name = addslashes(get_string("nameteacher", "forum"));
1463 $forum->intro = addslashes(get_string("introteacher", "forum"));
a796d0b8 1464 $forum->open = 2; // 0 - no, 1 - posts only, 2 - discuss and post
8daaf761 1465 $forum->assessed = 0;
1466 $forum->forcesubscribe = 0;
1467 break;
1468 default:
1469 notify("That forum type doesn't exist!");
1470 return false;
1471 break;
1472 }
1473
1474 $forum->timemodified = time();
1475 $forum->id = insert_record("forum", $forum);
1476
1477 if ($forum->type != "teacher") {
1478 if (! $module = get_record("modules", "name", "forum")) {
1479 notify("Could not find forum module!!");
1480 return false;
1481 }
1482 $mod->course = $courseid;
1483 $mod->module = $module->id;
1484 $mod->instance = $forum->id;
1485 $mod->section = 0;
1486 if (! $mod->coursemodule = add_course_module($mod) ) { // assumes course/lib.php is loaded
1487 notify("Could not add a new course module to the course '$course->fullname'");
1488 return false;
1489 }
1490 if (! $sectionid = add_mod_to_section($mod) ) { // assumes course/lib.php is loaded
1491 notify("Could not add the new course module to that section");
1492 return false;
1493 }
1494 if (! set_field("course_modules", "section", $sectionid, "id", $mod->coursemodule)) {
1495 notify("Could not update the course module with the correct section");
1496 return false;
1497 }
1498 include_once("$CFG->dirroot/course/lib.php");
d769d2ee 1499 rebuild_course_cache($courseid);
82aa0e8d 1500 }
65b0e537 1501
8daaf761 1502 return get_record("forum", "id", "$forum->id");
82aa0e8d 1503}
1504
f93f848a 1505
65b0e537 1506function forum_make_mail_post(&$post, $user, $touser, $course,
11b0c469 1507 $ownpost=false, $reply=false, $link=false, $rate=false, $footer="") {
65b0e537 1508// Given the data about a posting, builds up the HTML to display it and
501cdbd8 1509// returns the HTML in a string. This is designed for sending via HTML email.
1510
d30867b0 1511 global $CFG;
501cdbd8 1512
0d851f90 1513 static $formattedtext; // Cached version of formatted text for a post
1514 static $formattedtextid; // The ID number of the post
1515
1516 if (empty($formattedtextid) or $formattedtextid != $post->id) { // Recalculate the formatting
326ce3c4 1517 $options = new Object;
1518 $options->para = true;
1519 $formattedtext = format_text($post->message, $post->format, $options, $course->id);
0d851f90 1520 $formattedtextid = $post->id;
1521 }
1522
add3201e 1523 $output = '<table border="0" cellpadding="3" cellspacing="0" class="forumpost">';
501cdbd8 1524
add3201e 1525 $output .= '<tr class="header"><td width="35" valign="top" class="picture left">';
501cdbd8 1526 $output .= print_user_picture($user->id, $course->id, $user->picture, false, true);
add3201e 1527 $output .= '</td>';
501cdbd8 1528
1529 if ($post->parent) {
add3201e 1530 $output .= '<td class="topic">';
501cdbd8 1531 } else {
add3201e 1532 $output .= '<td class="topic starter">';
501cdbd8 1533 }
add3201e 1534 $output .= '<div class="subject">'.format_string($post->subject).'</div>';
1b26d5e7 1535
1536 $fullname = fullname($user, isteacher($course->id));
add3201e 1537 $by->name = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$user->id.'&amp;course='.$course->id.'">'.$fullname.'</a>';
1538 $by->date = userdate($post->modified, '', $touser->timezone);
1539 $output .= '<div class="author">'.get_string('bynameondate', 'forum', $by).'</div>';
1540
1541 $output .= '</td></tr>';
1542
1543 $output .= '<tr><td class="left side">';
1544 if ($group = user_group($course->id, $user->id)) {
1545 $output .= print_group_picture($group, $courseid, false, true, true);
1546 } else {
1547 $output .= '&nbsp;';
1548 }
1b26d5e7 1549
add3201e 1550 $output .= '</td><td class="content">';
501cdbd8 1551
7f6689e4 1552 if ($post->attachment) {
1553 $post->course = $course->id;
add3201e 1554 $post->forum = get_field('forum_discussions', 'forum', 'id', $post->discussion);
1555 $output .= '<div class="attachments">';
1556 $output .= forum_print_attachments($post, 'html');
72d497d4 1557 $output .= "</div>";
7f6689e4 1558 }
1559
0d851f90 1560 $output .= $formattedtext;
501cdbd8 1561
add3201e 1562
1563/// Commands
1564
1565 $commands = array();
501cdbd8 1566
2e2e71a8 1567 if ($post->parent) {
add3201e 1568 $commands[] = '<a target="_blank" href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.
1569 $post->discussion.'&amp;parent='.$post->parent.'">'.get_string('parent', 'forum').'</a>';
2e2e71a8 1570 }
ce45515e 1571
501cdbd8 1572 if ($ownpost) {
add3201e 1573 $commands[] = '<a target="_blank" href="'.$CFG->wwwroot.'/mod/forum/post.php?delete='.$post->id.'">'.
1574 get_string('delete', 'forum').'</a>';
1575 }
1576
1577 if ($reply) {
1578 $commands[] = '<a target="_blank" href="'.$CFG->wwwroot.'/mod/forum/post.php?reply='.$post->id.'">'.
1579 get_string('reply', 'forum').'</a>';
501cdbd8 1580 }
1581
add3201e 1582 $output .= '<div class="commands">';
1583 $output .= implode(' | ', $commands);
1584 $output .= '</div>';
1585
1586
1587/// Context link to post if required
65b0e537 1588
501cdbd8 1589 if ($link) {
add3201e 1590 $output .= '<div class="link">';
77e75a76 1591 $output .= '<a target="_blank" href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.$post->discussion.'#'.$post->id.'">'.
add3201e 1592 get_string('postincontext', 'forum').'</a>';
1593 $output .= '</div>';
501cdbd8 1594 }
add3201e 1595
501cdbd8 1596 if ($footer) {
add3201e 1597 $output .= '<div class="footer">'.$footer.'</div>';
501cdbd8 1598 }
add3201e 1599 $output .= '</td></tr></table>'."\n\n";
1600
501cdbd8 1601
1602 return $output;
1603}
1604
1605
65b0e537 1606function forum_print_post(&$post, $courseid, $ownpost=false, $reply=false, $link=false,
f37da850 1607 $ratings=NULL, $footer="", $highlight="", $post_read=-99) {
74f5d1e3 1608
d30867b0 1609 global $USER, $CFG;
501cdbd8 1610
359f2758 1611 static $stredit, $strdelete, $strreply, $strparent, $strprune, $strpruneheading, $threadedmode, $isteacher, $adminedit;
2e2e71a8 1612
77efef3e 1613 static $strmarkread, $strmarkunread, $istracked;
f37da850 1614
2e2e71a8 1615 if (empty($stredit)) {
359f2758 1616 $stredit = get_string('edit', 'forum');
1617 $strdelete = get_string('delete', 'forum');
1618 $strreply = get_string('reply', 'forum');
1619 $strparent = get_string('parent', 'forum');
1620 $strpruneheading = get_string('pruneheading', 'forum');
d494dd83 1621 $strprune = get_string('prune', 'forum');
2e2e71a8 1622 $threadedmode = (!empty($USER->mode) and ($USER->mode == FORUM_MODE_THREADED));
3bd98ad4 1623 $isteacher = isteacher($courseid);
b8be40ce 1624 $adminedit = (isadmin() and !empty($CFG->admineditalways));
f37da850 1625 $strmarkread = get_string('markread', 'forum');
1626 $strmarkunread = get_string('markunread', 'forum');
77efef3e 1627
1628 if (!empty($post->forum)) {
1629 $istracked = (forum_tp_can_track_forums($post->forum) &&
1630 forum_tp_is_tracked($post->forum));
1631 } else {
1632 $istracked = false;
1633 }
f37da850 1634 }
1635
eaf50aef 1636 if ($istracked) {
f37da850 1637 if ($post_read == -99) { // If we don't know yet...
489de4ae 1638 /// The front page can display a news item post to non-logged in users. This should
1639 /// always appear as 'read'.
1640 $post_read = empty($USER) || forum_tp_is_post_read($USER->id, $post);
f37da850 1641 }
1642 if ($post_read) {
1643 $read_style = ' read';
1644 } else {
1645 $read_style = ' unread';
1646 echo '<a name="unread"></a>';
1647 }
1648 } else {
1649 $read_style = '';
2e2e71a8 1650 }
1651
f37da850 1652 echo '<a name="'.$post->id.'"></a>';
33200577 1653 echo '<table cellspacing="0" class="forumpost'.$read_style.'">';
501cdbd8 1654
d3583b41 1655 echo '<tr class="header"><td class="picture left">';
501cdbd8 1656 print_user_picture($post->userid, $courseid, $post->picture);
d3583b41 1657 echo '</td>';
501cdbd8 1658
1659 if ($post->parent) {
d3583b41 1660 echo '<td class="topic">';
501cdbd8 1661 } else {
d3583b41 1662 echo '<td class="topic starter">';
501cdbd8 1663 }
83ec9098 1664
d3583b41 1665 echo '<div class="subject">'.$post->subject.'</div>';
e3ff14ca 1666
d3583b41 1667 echo '<div class="author">';
3bd98ad4 1668 $fullname = fullname($post, $isteacher);
d3583b41 1669 $by->name = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.
1670 $post->userid.'&amp;course='.$courseid.'">'.$fullname.'</a>';
d62413e8 1671 $by->date = userdate($post->modified);
d3583b41 1672 print_string('bynameondate', 'forum', $by);
1673 echo '</div></td></tr>';
1b26d5e7 1674
d3583b41 1675 echo '<tr><td class="left side">';
507407a7 1676 if ($group = user_group($courseid, $post->userid)) {
a4fbb0b2 1677 print_group_picture($group, $courseid, false, false, true);
507407a7 1678 } else {
d3583b41 1679 echo '&nbsp;';
507407a7 1680 }
d3583b41 1681
1682/// Actual content
1683
1684 echo '</td><td class="content">'."\n";
501cdbd8 1685
7f6689e4 1686 if ($post->attachment) {
1687 $post->course = $courseid;
d3583b41 1688 $post->forum = get_field('forum_discussions', 'forum', 'id', $post->discussion);
1689 echo '<div class="attachments">';
72d497d4 1690 $attachedimages = forum_print_attachments($post);
d3583b41 1691 echo '</div>';
e9c2dc1f 1692 } else {
d3583b41 1693 $attachedimages = '';
7f6689e4 1694 }
1695
d3583b41 1696
326ce3c4 1697 $options = new Object;
1698 $options->para = false;
5be7800c 1699 if ($link and (strlen(strip_tags($post->message)) > $CFG->forum_longpost)) {
aa153f29 1700 // Print shortened version
326ce3c4 1701 echo format_text(forum_shorten_post($post->message), $post->format, $options, $courseid);
c585fa17 1702 $numwords = count_words(strip_tags($post->message));
d3583b41 1703 echo '<p><a href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.$post->discussion.'">';
1704 echo get_string('readtherest', 'forum');
1705 echo '</a> ('.get_string('numwords', '', $numwords).')...</p>';
501cdbd8 1706 } else {
aa153f29 1707 // Print whole message
88438a58 1708 if ($highlight) {
326ce3c4 1709 echo highlight($highlight, format_text($post->message, $post->format, $options, $courseid));
88438a58 1710 } else {
326ce3c4 1711 echo format_text($post->message, $post->format, $options, $courseid);
88438a58 1712 }
65b0e537 1713 echo $attachedimages;
501cdbd8 1714 }
1715
d3583b41 1716
1717/// Commands
1718
359f2758 1719 $commands = array();
501cdbd8 1720
eaf50aef 1721 if ($istracked) {
489de4ae 1722 /// SPECIAL CASE: The front page can display a news item post to non-logged in users.
1723 /// Don't display the mark read / unread controls in this case.
1724 if ($CFG->forum_usermarksread && !empty($USER)) {
f37da850 1725 if ($post_read) {
1726 $mcmd = '&amp;mark=unread&amp;postid='.$post->id;
1727 $mtxt = $strmarkunread;
1728 } else {
1729 $mcmd = '&amp;mark=read&amp;postid='.$post->id;
1730 $mtxt = $strmarkread;
1731 }
1732 if ($threadedmode) {
d3583b41 1733 $commands[] = '<a href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.
1734 $post->discussion.'&amp;parent='.$post->id.$mcmd.'">'.$mtxt.'</a>';
f37da850 1735 } else {
d3583b41 1736 $commands[] = '<a href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.
1737 $post->discussion.$mcmd.'#'.$post->id.'">'.$mtxt.'</a>';
f37da850 1738 }
1739 }
1740 }
1741
2e2e71a8 1742 if ($post->parent) {
1743 if ($threadedmode) {
d3583b41 1744 $commands[] = '<a href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.
1745 $post->discussion.'&amp;parent='.$post->parent.'">'.$strparent.'</a>';
2e2e71a8 1746 } else {
d3583b41 1747 $commands[] = '<a href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.
1748 $post->discussion.'#'.$post->parent.'">'.$strparent.'</a>';
2e2e71a8 1749 }
1750 }
1751
501cdbd8 1752 $age = time() - $post->created;
b8be40ce 1753 if ($ownpost or $adminedit) {
1754 if (($age < $CFG->maxeditingtime) or $adminedit) {
d3583b41 1755 $commands[] = '<a href="'.$CFG->wwwroot.'/mod/forum/post.php?edit='.$post->id.'">'.$stredit.'</a>';
501cdbd8 1756 }
64eacd6f 1757 }
aaf7a9dc 1758
cf84431b 1759 if (isteacheredit($courseid) and $post->parent) {
d3583b41 1760 $commands[] = '<a href="'.$CFG->wwwroot.'/mod/forum/post.php?prune='.$post->id.
1761 '" title="'.$strpruneheading.'">'.$strprune.'</a>';
cf84431b 1762 }
aaf7a9dc 1763
ac00b904 1764 if (($ownpost and $age < $CFG->maxeditingtime) or $isteacher) {
d3583b41 1765 $commands[] = '<a href="'.$CFG->wwwroot.'/mod/forum/post.php?delete='.$post->id.'">'.$strdelete.'</a>';
64eacd6f 1766 }
359f2758 1767
64eacd6f 1768 if ($reply) {
d3583b41 1769 $commands[] = '<a href="'.$CFG->wwwroot.'/mod/forum/post.php?reply='.$post->id.'">'.$strreply.'</a>';
501cdbd8 1770 }
501cdbd8 1771
d3583b41 1772 echo '<div class="commands">';
1773 echo implode(' | ', $commands);
1774 echo '</div>';
1775
1776
1777/// Ratings
74f5d1e3 1778
1779 $ratingsmenuused = false;
02ebf404 1780 if (!empty($ratings) and !empty($USER->id)) {
d3583b41 1781 echo '<div class="ratings">';
98914efd 1782 $useratings = true;
1783 if ($ratings->assesstimestart and $ratings->assesstimefinish) {
1784 if ($post->created < $ratings->assesstimestart or $post->created > $ratings->assesstimefinish) {
1785 $useratings = false;
1786 }
1787 }
1788 if ($useratings) {
3bd98ad4 1789 $mypost = ($USER->id == $post->userid);
1790
1791 if (($isteacher or $ratings->assesspublic) and !$mypost) {
1792 forum_print_ratings_mean($post->id, $ratings->scale, $isteacher);
d395046a 1793 if (!empty($ratings->allow)) {
d3583b41 1794 echo '&nbsp;';
d395046a 1795 forum_print_rating_menu($post->id, $USER->id, $ratings->scale);
1796 $ratingsmenuused = true;
1797 }
3bd98ad4 1798
1799 } else if ($mypost) {
1800 forum_print_ratings_mean($post->id, $ratings->scale, true);
1801
98914efd 1802 } else if (!empty($ratings->allow) ) {
1803 forum_print_rating_menu($post->id, $USER->id, $ratings->scale);
74f5d1e3 1804 $ratingsmenuused = true;
2a3cda19 1805 }
501cdbd8 1806 }
d3583b41 1807 echo '</div>';
501cdbd8 1808 }
65b0e537 1809
d3583b41 1810/// Link to post if required
1811
501cdbd8 1812 if ($link) {
d3583b41 1813 echo '<div class="link">';
501cdbd8 1814 if ($post->replies == 1) {
d3583b41 1815 $replystring = get_string('repliesone', 'forum', $post->replies);
501cdbd8 1816 } else {
d3583b41 1817 $replystring = get_string('repliesmany', 'forum', $post->replies);
501cdbd8 1818 }
d3583b41 1819 echo '<a href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.$post->discussion.'">'.
1820 get_string('discussthistopic', 'forum').'</a>&nbsp;('.$replystring.')';
1821 echo '</div>';
501cdbd8 1822 }
d3583b41 1823
501cdbd8 1824 if ($footer) {
d3583b41 1825 echo '<div class="footer">'.$footer.'</div>';
501cdbd8 1826 }
d3583b41 1827 echo '</td></tr></table>'."\n\n";
74f5d1e3 1828
eaf50aef 1829 if ($istracked && !$CFG->forum_usermarksread && !empty($post->forum)) {
f37da850 1830 forum_tp_mark_post_read($USER->id, $post, $post->forum);
1831 }
1832
74f5d1e3 1833 return $ratingsmenuused;
501cdbd8 1834}
eaf50aef 1835/**
1836* This function prints the overview of a discussion in the forum listing.
1837* It needs some discussion information and some post information, these
1838* happen to be combined for efficiency in the $post parameter by the function
1839* that calls this one: forum_print_latest_discussions()
1840*
1841* @param object $post The post object (passed by reference for speed).
1842* @param object $forum The forum object.
1843* @param int $group Current group.
1844* @param string $datestring Format to use for the dates.
1845* @param boolean $cantrack Is tracking enabled for this forum.
1846* @param boolean $forumtracked Is the user tracking this forum.
1847*/
1848function forum_print_discussion_header(&$post, $forum, $group=-1, $datestring="", $cantrack=true, $forumtracked=true) {
43921b8a 1849
d30867b0 1850 global $USER, $CFG;
3335f6fb 1851
f51e8d7e 1852 static $rowcount;
5733262d 1853 static $strmarkalldread;
f51e8d7e 1854
1855 if (!isset($rowcount)) {
1856 $rowcount = 0;
5733262d 1857 $strmarkalldread = get_string('markalldread', 'forum');
f51e8d7e 1858 } else {
1859 $rowcount = ($rowcount + 1) % 2;
1860 }
1861
17dc3f3c 1862 $post->subject = format_string($post->subject,true);
436a7cae 1863
f51e8d7e 1864 echo "\n\n";
1865 echo '<tr class="discussion r'.$rowcount.'">';
3335f6fb 1866
29507631 1867 // Topic
f51e8d7e 1868 echo '<td class="topic starter">';
1869 echo '<a href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.$post->discussion.'">'.$post->subject.'</a>';
29507631 1870 echo "</td>\n";
1871
1872 // Picture
f51e8d7e 1873 echo '<td class="picture">';
a796d0b8 1874 print_user_picture($post->userid, $forum->course, $post->picture);
29507631 1875 echo "</td>\n";
3335f6fb 1876
29507631 1877 // User name
a796d0b8 1878 $fullname = fullname($post, isteacher($forum->course));
f51e8d7e 1879 echo '<td class="author">';
1880 echo '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$post->userid.'&amp;course='.$forum->course.'">'.$fullname.'</a>';
29507631 1881 echo "</td>\n";
1882
3a68fbbb 1883 // Group picture
425b4f1a 1884 if ($group !== -1) { // Groups are active - group is a group data object or NULL
f51e8d7e 1885 echo '<td class="picture group">';
c2b552fe 1886 if (!empty($group->picture) and empty($group->hidepicture)) {
3a68fbbb 1887 print_group_picture($group, $forum->course, false, false, true);
1888 } else if (isset($group->id)) {
fa22fd5f 1889 echo '<a href="'.$CFG->wwwroot.'/user/index.php?id='.$forum->course.'&amp;group='.$group->id.'">'.$group->name.'</a>';
3a68fbbb 1890 }
1891 echo "</td>\n";
1892 }
1893
f51e8d7e 1894 if ($forum->open or $forum->type == 'teacher') { // Show the column with replies
1895 echo '<td class="replies">';
1896 echo '<a href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.$post->discussion.'">';
1897 echo $post->replies.'</a>';
a796d0b8 1898 echo "</td>\n";
e3ff14ca 1899
eaf50aef 1900 if ($cantrack) {
f51e8d7e 1901 echo '<td class="replies">';
eaf50aef 1902 if ($forumtracked) {
1903 if ($post->unread > 0) {
1904 echo '<span class="unread">';
1905 echo '<a href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.$post->discussion.'#unread">';
1906 echo $post->unread;
1907 echo '</a>';
c39748f4 1908 echo '<a title="'.$strmarkalldread.'" href="'.$CFG->wwwroot.'/mod/forum/markposts.php?f='.
eaf50aef 1909 $forum->id.'&amp;d='.$post->discussion.'&amp;mark=read&amp;returnpage=view.php">' .
fee287f3 1910 '<img src="'.$CFG->pixpath.'/t/clear.gif" height="11" width="11" /></a>';
eaf50aef 1911 echo '</span>';
1912 } else {
1913 echo '<span class="read">';
1914 echo '<a href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.$post->discussion.'#unread">';
1915 echo $post->unread;
1916 echo '</a>';
1917 echo '</span>';
1918 }
f51e8d7e 1919 } else {
343af274 1920 echo '<span class="read">';
eaf50aef 1921 echo '-';
343af274 1922 echo '</span>';
3a68fbbb 1923 }
f37da850 1924 echo "</td>\n";
1925 }
a796d0b8 1926 }
3335f6fb 1927
f51e8d7e 1928 echo '<td class="lastpost">';
43921b8a 1929 $usedate = (empty($post->timemodified)) ? $post->modified : $post->timemodified; // Just in case
839f2456 1930 $parenturl = (empty($post->lastpostid)) ? '' : '&amp;parent='.$post->lastpostid;
268c6485 1931 $usermodified->firstname = $post->umfirstname;
1932 $usermodified->lastname = $post->umlastname;
f51e8d7e 1933 echo '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$post->usermodified.'&amp;course='.$forum->course.'">'.
1934 fullname($usermodified).'</a><br />';
ac00b904 1935 echo '<a href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.$post->discussion.$parenturl.'">'.
43921b8a 1936 userdate($usedate, $datestring).'</a>';
29507631 1937 echo "</td>\n";
1938
f51e8d7e 1939 echo "</tr>\n\n";
3335f6fb 1940
3335f6fb 1941}
1942
1943
aa153f29 1944function forum_shorten_post($message) {
c585fa17 1945// Given a post object that we already know has a long message
65b0e537 1946// this function truncates the message nicely to the first
5be7800c 1947// sane place between $CFG->forum_longpost and $CFG->forum_shortpost
1948
1949 global $CFG;
c585fa17 1950
1951 $i = 0;
1952 $tag = false;
1953 $length = strlen($message);
1954 $count = 0;
1955 $stopzone = false;
1956 $truncate = 0;
1957
1958 for ($i=0; $i<$length; $i++) {
a8afb411 1959 $char = $message[$i];
c585fa17 1960
1961 switch ($char) {
65b0e537 1962 case "<":
c585fa17 1963 $tag = true;
1964 break;
65b0e537 1965 case ">":
c585fa17 1966 $tag = false;
1967 break;
1968 default:
1969 if (!$tag) {
1970 if ($stopzone) {
67f0b4cc 1971 if ($char == ".") {
a8afb411 1972 $truncate = $i+1;
c585fa17 1973 break 2;
1974 }
1975 }
1976 $count++;
1977 }
a8afb411 1978 break;
c585fa17 1979 }
1980 if (!$stopzone) {
5be7800c 1981 if ($count > $CFG->forum_shortpost) {
c585fa17 1982 $stopzone = true;
1983 }
1984 }
1985 }
aa153f29 1986
c585fa17 1987 if (!$truncate) {
a8afb411 1988 $truncate = $i;
c585fa17 1989 }
1990
67f0b4cc 1991 return substr($message, 0, $truncate);
aa153f29 1992}
1993
501cdbd8 1994
3bd98ad4 1995function forum_print_ratings_mean($postid, $scale, $link=true) {
02ebf404 1996/// Print the multiple ratings on a post given to the current user by others.
1997/// Scale is an array of ratings
1998
1999 static $strrate;
05c47ef7 2000
2001 $mean = forum_get_ratings_mean($postid, $scale);
65b0e537 2002
05c47ef7 2003 if ($mean !== "") {
02ebf404 2004
2005 if (empty($strratings)) {
2006 $strratings = get_string("ratings", "forum");
501cdbd8 2007 }
501cdbd8 2008
02ebf404 2009 echo "$strratings: ";
3bd98ad4 2010 if ($link) {
2011 link_to_popup_window ("/mod/forum/report.php?id=$postid", "ratings", $mean, 400, 600);
2012 } else {
2013 echo "$mean ";
2014 }
501cdbd8 2015 }
2016}
2017
501cdbd8 2018
0761d83f 2019function forum_get_ratings_mean($postid, $scale, $ratings=NULL) {
2020/// Return the mean rating of a post given to the current user by others.
02ebf404 2021/// Scale is an array of possible ratings in the scale
2022/// Ratings is an optional simple array of actual ratings (just integers)
2023
2024 if (!$ratings) {
2025 $ratings = array();
2026 if ($rates = get_records("forum_ratings", "post", $postid)) {
2027 foreach ($rates as $rate) {
2028 $ratings[] = $rate->rating;
2029 }
501cdbd8 2030 }
501cdbd8 2031 }
02ebf404 2032
0761d83f 2033 $count = count($ratings);
2034
2035 if ($count == 0) {
02ebf404 2036 return "";
02ebf404 2037
0761d83f 2038 } else if ($count == 1) {
2039 return $scale[$ratings[0]];
2040
02ebf404 2041 } else {
0761d83f 2042 $total = 0;
2043 foreach ($ratings as $rating) {
2044 $total += $rating;
2045 }
2046 $mean = round( ((float)$total/(float)$count) + 0.001); // Little fudge factor so that 0.5 goes UP
65b0e537 2047
0761d83f 2048 if (isset($scale[$mean])) {
2049 return $scale[$mean]." ($count)";
2050 } else {
2051 return "$mean ($count)"; // Should never happen, hopefully
2052 }
02ebf404 2053 }
2054}
2055
2056function forum_get_ratings_summary($postid, $scale, $ratings=NULL) {
2057/// Return a summary of post ratings given to the current user by others.
2058/// Scale is an array of possible ratings in the scale
2059/// Ratings is an optional simple array of actual ratings (just integers)
2060
2061 if (!$ratings) {
2062 $ratings = array();
2063 if ($rates = get_records("forum_ratings", "post", $postid)) {
2064 foreach ($rates as $rate) {
2065 $rating[] = $rate->rating;
2066 }
2067 }
2068 }
2069
2070
2071 if (!$count = count($ratings)) {
2072 return "";
2073 }
2074
2075
2076 foreach ($scale as $key => $scaleitem) {
2077 $sumrating[$key] = 0;
2078 }
2079
2080 foreach ($ratings as $rating) {
2081 $sumrating[$rating]++;
2082 }
2083
2084 $summary = "";
2085 foreach ($scale as $key => $scaleitem) {
2086 $summary = $sumrating[$key].$summary;
2087 if ($key > 1) {
2088 $summary = "/$summary";
2089 }
2090 }
2091 return $summary;
2092}
2093
2094function forum_print_rating_menu($postid, $userid, $scale) {
65b0e537 2095/// Print the menu of ratings as part of a larger form.
02ebf404 2096/// If the post has already been - set that value.
2097/// Scale is an array of ratings
2098
2099 static $strrate;
2100
2101 if (!$rating = get_record("forum_ratings", "userid", $userid, "post", $postid)) {
2102 $rating->rating = 0;
2103 }
2104
2105 if (empty($strrate)) {
2106 $strrate = get_string("rate", "forum");
2107 }
2108
2109 choose_from_menu($scale, $postid, $rating->rating, "$strrate...");
501cdbd8 2110}
2111
7a12aab4 2112function forum_print_mode_form($discussion, $mode) {
2113 GLOBAL $FORUM_LAYOUT_MODES;
501cdbd8 2114
839f2456 2115 echo "<div align=\"center\">";
2116 popup_form("discuss.php?d=$discussion&amp;mode=", $FORUM_LAYOUT_MODES, "mode", $mode, "");
2117 echo "</div>\n";
501cdbd8 2118}
2119
6f1cc8d6 2120function forum_search_form($course, $search='') {
501cdbd8 2121 global $CFG;
2122
6f1cc8d6 2123 $output = '<table border="0" cellpadding="0" cellspacing="0"><tr><td nowrap="nowrap">';
2124 $output .= helpbutton('search', get_string('search'), 'moodle', true, false, '', true);
2125 $output .= '&nbsp;<form name="search" action="'.$CFG->wwwroot.'/mod/forum/search.php" style="display:inline">';
2126 $output .= '<input name="search" type="text" size="18" value="'.$search.'" alt="search" />';
2127 $output .= '<input value="'.get_string('searchforums', 'forum').'" type="submit" />';
2128 $output .= '<input name="id" type="hidden" value="'.$course->id.'" />';
2129 $output .= '</form>';
2130 $output .= '</td></tr></table>';
5e367a2d 2131
6f1cc8d6 2132 return $output;
501cdbd8 2133}
2134
2135
11b0c469 2136function forum_set_return() {
607809b3 2137 global $CFG, $SESSION;
501cdbd8 2138
28e1e8b9 2139 if (! isset($SESSION->fromdiscussion)) {
48d38fad 2140 if (!empty($_SERVER['HTTP_REFERER'])) {
2141 $referer = $_SERVER['HTTP_REFERER'];
2142 } else {
2143 $referer = "";
2144 }
28e1e8b9 2145 // If the referer is NOT a login screen then save it.
48d38fad 2146 if (! strncasecmp("$CFG->wwwroot/login", $referer, 300)) {
607809b3 2147 $SESSION->fromdiscussion = $_SERVER["HTTP_REFERER"];
28e1e8b9 2148 }
501cdbd8 2149 }
2150}
2151
2152
11b0c469 2153function forum_go_back_to($default) {
501cdbd8 2154 global $SESSION;
2155
9c9f7d77 2156 if (!empty($SESSION->fromdiscussion)) {
501cdbd8 2157 $returnto = $SESSION->fromdiscussion;
2158 unset($SESSION->fromdiscussion);
2159 return $returnto;
2160 } else {
2161 return $default;
2162 }
2163}
2164
7f6689e4 2165function forum_file_area_name($post) {
2166// Creates a directory file name, suitable for make_upload_directory()
2167 global $CFG;
2168
2169 return "$post->course/$CFG->moddata/forum/$post->forum/$post->id";
2170}
2171
2172function forum_file_area($post) {
2173 return make_upload_directory( forum_file_area_name($post) );
2174}
2175
2176function forum_delete_old_attachments($post, $exception="") {
2177// Deletes all the user files in the attachments area for a post
2178// EXCEPT for any file named $exception
2179
2180 if ($basedir = forum_file_area($post)) {
2181 if ($files = get_directory_list($basedir)) {
2182 foreach ($files as $file) {
2183 if ($file != $exception) {
2184 unlink("$basedir/$file");
2185 notify("Existing file '$file' has been deleted!");
2186 }
2187 }
2188 }
2189 if (!$exception) { // Delete directory as well, if empty
2190 rmdir("$basedir");
2191 }
2192 }
2193}
2194
cc2b7ea5 2195function forum_move_attachments($discussion, $forumid) {
65b0e537 2196/// Given a discussion object that is being moved to forumid,
2197/// this function checks all posts in that discussion
2198/// for attachments, and if any are found, these are
cc2b7ea5 2199/// moved to the new forum directory.
2200
2201 global $CFG;
2202
18b8fbfa 2203 require_once($CFG->dirroot.'/lib/uploadlib.php');
2204
cc2b7ea5 2205 $return = true;
2206
2207 if ($posts = get_records_select("forum_posts", "discussion = '$discussion->id' AND attachment <> ''")) {
2208 foreach ($posts as $oldpost) {
2209 $oldpost->course = $discussion->course;
2210 $oldpost->forum = $discussion->forum;
2211 $oldpostdir = "$CFG->dataroot/".forum_file_area_name($oldpost);
2212 if (is_dir($oldpostdir)) {
2213 $newpost = $oldpost;
2214 $newpost->forum = $forumid;
7f0c3a44 2215 $newpostdir = forum_file_area($newpost);
18b8fbfa 2216 $files = get_directory_list($oldpostdir); // get it before we rename it.
cc2b7ea5 2217 if (! @rename($oldpostdir, $newpostdir)) {
2218 $return = false;
2219 }
18b8fbfa 2220 foreach ($files as $file) {
2221 clam_change_log($oldpostdir.'/'.$file,$newpostdir.'/'.$file);
2222 }
cc2b7ea5 2223 }
2224 }
2225 }
2226 return $return;
2227}
2228
7f6689e4 2229function forum_print_attachments($post, $return=NULL) {
2230// if return=html, then return a html string.
2231// if return=text, then return a text-only string.
72d497d4 2232// otherwise, print HTML for non-images, and return image HTML
7f6689e4 2233
2234 global $CFG;
2235
2236 $filearea = forum_file_area_name($post);
2237
72d497d4 2238 $imagereturn = "";
2239 $output = "";
2240
7f6689e4 2241 if ($basedir = forum_file_area($post)) {
2242 if ($files = get_directory_list($basedir)) {
2243 $strattachment = get_string("attachment", "forum");
2244 foreach ($files as $file) {
2245 $icon = mimeinfo("icon", $file);
2246 if ($CFG->slasharguments) {
2a1975cb 2247 $ffurl = "$CFG->wwwroot/file.php/$filearea/$file";
7f6689e4 2248 } else {
2a1975cb 2249 $ffurl = "$CFG->wwwroot/file.php?file=/$filearea/$file";
7f6689e4 2250 }
2a1975cb 2251 $image = "<img border=\"0\" src=\"$CFG->pixpath/f/$icon\" height=\"16\" width=\"16\" alt=\"\" />";
7f6689e4 2252
2253 if ($return == "html") {
2a1975cb 2254 $output .= "<a href=\"$ffurl\">$image</a> ";
2255 $output .= "<a href=\"$ffurl\">$file</a><br />";
7f6689e4 2256
2257 } else if ($return == "text") {
2a1975cb 2258 $output .= "$strattachment $file:\n$ffurl\n";
7f6689e4 2259
2260 } else {
72d497d4 2261 if ($icon == "image.gif") { // Image attachments don't get printed as links
2a1975cb 2262 $imagereturn .= "<br /><img src=\"$ffurl\" alt=\"\" />";
72d497d4 2263 } else {
2a1975cb 2264 echo "<a href=\"$ffurl\">$image</a> ";
2265 echo "<a href=\"$ffurl\">$file</a><br />";
72d497d4 2266 }
7f6689e4 2267 }
2268 }
2269 }
2270 }
72d497d4 2271
7f6689e4 2272 if ($return) {
2273 return $output;
2274 }
72d497d4 2275
2276 return $imagereturn;
7f6689e4 2277}
db290a6e 2278/**
e3ff14ca 2279 * If successful, this function returns the name of the file
db290a6e 2280 * @param $post is a full post record, including course and forum
2281 * @param $newfile is a full upload array from $_FILES
2282 * @param $message is a string to hold the messages.
e3ff14ca 2283 */
7f6689e4 2284
db290a6e 2285function forum_add_attachment($post, $inputname,&$message) {
7f6689e4 2286
9dd0b378 2287 global $CFG;
2288
4909e176 2289 if (!$forum = get_record("forum", "id", $post->forum)) {
2290 return "";
2291 }
2292
2293 if (!$course = get_record("course", "id", $forum->course)) {
2294 return "";
2295 }
2296
5ddaa2e2 2297 require_once($CFG->dirroot.'/lib/uploadlib.php');
db290a6e 2298 $um = new upload_manager($inputname,true,false,$course,false,$forum->maxbytes,true,true);
5ddaa2e2 2299 $dir = forum_file_area_name($post);
2300 if ($um->process_file_uploads($dir)) {
db290a6e 2301 $message .= $um->get_errors();
5ddaa2e2 2302 return $um->get_new_filename();
7f6689e4 2303 }
db290a6e 2304 $message .= $um->get_errors();
7f6689e4 2305}
501cdbd8 2306
db290a6e 2307function forum_add_new_post($post,&$message) {
501cdbd8 2308
f37da850 2309 global $USER, $CFG;
e3ff14ca 2310
ffe11640 2311 $post->created = $post->modified = time();
501cdbd8 2312 $post->mailed = "0";
a56f0d60 2313 $post->userid = $USER->id;
7f6689e4 2314 $post->attachment = "";
2315
65b0e537 2316 if (! $post->id = insert_record("forum_posts", $post)) {
7f6689e4 2317 return false;
2318 }
2319
db290a6e 2320 if ($post->attachment = forum_add_attachment($post, 'attachment',$message)) {
7f6689e4 2321 set_field("forum_posts", "attachment", $post->attachment, "id", $post->id);
2322 }
29507631 2323
2324 // Update discussion modified date
2325 set_field("forum_discussions", "timemodified", $post->modified, "id", $post->discussion);
016cd6af 2326 set_field("forum_discussions", "usermodified", $post->userid, "id", $post->discussion);
65b0e537 2327
eaf50aef 2328 if (forum_tp_can_track_forums($post->forum) && forum_tp_is_tracked($post->forum)) {
f37da850 2329 forum_tp_mark_post_read($post->userid, $post, $post->forum);
2330 }
2331
7f6689e4 2332 return $post->id;
501cdbd8 2333}
2334
db290a6e 2335function forum_update_post($post,&$message) {
501cdbd8 2336
f37da850 2337 global $USER, $CFG;
a56f0d60 2338
ffe11640 2339 $post->modified = time();
0936de64 2340
2341 if ($USER->id != $post->userid) { // Not the original author
2342 $data->name = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$USER->id.'&course='.$post->course.'">'.
2343 fullname($USER).'</a>';
2344 $data->date = userdate($post->modified);
2345 $editedby = get_string('editedby', 'forum', $data);
2346 if ($post->format == FORMAT_HTML) {
7f65461c 2347 $post->message .= '<p>(<span class="edited">'.$editedby.'</span>)</p>';
0936de64 2348 } else {
2349 $post->message .= "\n\n(".$editedby.')';
2350 }
2351 }
501cdbd8 2352
0ab85112 2353 if (!$post->parent) { // Post is a discussion starter - update discussion title too
2354 set_field("forum_discussions", "name", $post->subject, "id", $post->discussion);
2355 }
29507631 2356
db290a6e 2357 if ($newfilename = forum_add_attachment($post, 'attachment',$message)) {
7f6689e4 2358 $post->attachment = $newfilename;
2359 } else {
2360 unset($post->attachment);
2361 }
29507631 2362
2363 // Update discussion modified date
2364 set_field("forum_discussions", "timemodified", $post->modified, "id", $post->discussion);
016cd6af 2365 set_field("forum_discussions", "usermodified", $post->userid, "id", $post->discussion);
29507631 2366
eaf50aef 2367 if (forum_tp_can_track_forums($post->forum) && forum_tp_is_tracked($post->forum)) {
f37da850 2368 forum_tp_mark_post_read($post->userid, $post, $post->forum);
2369 }
2370
ffe11640 2371 return update_record("forum_posts", $post);
501cdbd8 2372}
2373
db290a6e 2374function forum_add_discussion($discussion,&$message) {
65b0e537 2375// Given an object containing all the necessary data,
501cdbd8 2376// create a new discussion and return the id
2377
f37da850 2378 GLOBAL $USER, $CFG;
501cdbd8 2379
2380 $timenow = time();
2381
65b0e537 2382 // The first post is stored as a real post, and linked
501cdbd8 2383 // to from the discuss entry.
2384
2385 $post->discussion = 0;
2386 $post->parent = 0;
ebc3bd2b 2387 $post->userid = $USER->id;
501cdbd8 2388 $post->created = $timenow;
2389 $post->modified = $timenow;
2390 $post->mailed = 0;
2391 $post->subject = $discussion->name;
2392 $post->message = $discussion->intro;
7f6689e4 2393 $post->attachment = "";
2394 $post->forum = $discussion->forum;
2395 $post->course = $discussion->course;
9f0b8269 2396 $post->format = $discussion->format;
501cdbd8 2397
2398 if (! $post->id = insert_record("forum_posts", $post) ) {
2399 return 0;
2400 }
2401
db290a6e 2402 if ($post->attachment = forum_add_attachment($post, 'attachment',$message)) {
7f6689e4 2403 set_field("forum_posts", "attachment", $post->attachment, "id", $post->id); //ignore errors
2404 }
2405
65b0e537 2406 // Now do the main entry for the discussion,
02509fe6 2407 // linking to this first post
04eba58f 2408
caadf009 2409 $discussion->firstpost = $post->id;
2410 $discussion->timemodified = $timenow;
016cd6af 2411 $discussion->usermodified = $post->userid;
a56f0d60 2412 $discussion->userid = $USER->id;
04eba58f 2413
4e00a4d9 2414 if (! $post->discussion = insert_record("forum_discussions", $discussion) ) {
caadf009 2415 delete_records("forum_posts", "id", $post->id);
2416 return 0;
04eba58f 2417 }
2418
caadf009 2419 // Finally, set the pointer on the post.
4e00a4d9 2420 if (! set_field("forum_posts", "discussion", $post->discussion, "id", $post->id)) {
caadf009 2421 delete_records("forum_posts", "id", $post->id);
4e00a4d9 2422 delete_records("forum_discussions", "id", $post->discussion);
caadf009 2423 return 0;
04eba58f 2424 }
04eba58f 2425
eaf50aef 2426 if (forum_tp_can_track_forums($post->forum) && forum_tp_is_tracked($post->forum)) {
f37da850 2427 forum_tp_mark_post_read($post->userid, $post, $post->forum);
2428 }
2429
4e00a4d9 2430 return $post->discussion;
caadf009 2431}
04eba58f 2432
04eba58f 2433
e2c1dbe9 2434function forum_delete_discussion($discussion, $fulldelete=false) {
caadf009 2435// $discussion is a discussion record object
04eba58f 2436
2437 $result = true;
2438
caadf009 2439 if ($posts = get_records("forum_posts", "discussion", $discussion->id)) {
2440 foreach ($posts as $post) {
2441 $post->course = $discussion->course;
2442 $post->forum = $discussion->forum;
2443 if (! delete_records("forum_ratings", "post", "$post->id")) {
2444 $result = false;
2445 }
e2c1dbe9 2446 if (! forum_delete_post($post, $fulldelete)) {
04eba58f 2447 $result = false;
2448 }
2449 }
2450 }
2451
f37da850 2452 forum_tp_delete_read_records(-1, -1, $discussion->id);
2453
caadf009 2454 if (! delete_records("forum_discussions", "id", "$discussion->id")) {
04eba58f 2455 $result = false;
2456 }
2457
2458 return $result;
2459}
2460
2461
b82faacd 2462function forum_delete_post($post, $children=false) {
1da8c568 2463 if ($childposts = get_records('forum_posts', 'parent', $post->id)) {
2464 if ($children) {
b82faacd 2465 foreach ($childposts as $childpost) {
2466 forum_delete_post($childpost, true);
2467 }
1da8c568 2468 } else {
2469 return false;
b82faacd 2470 }
2471 }
caadf009 2472 if (delete_records("forum_posts", "id", $post->id)) {
2473 delete_records("forum_ratings", "post", $post->id); // Just in case
f37da850 2474
b82faacd 2475 forum_tp_delete_read_records(-1, $post->id);
f37da850 2476
caadf009 2477 if ($post->attachment) {
2478 $discussion = get_record("forum_discussions", "id", $post->discussion);
2479 $post->course = $discussion->course;
2480 $post->forum = $discussion->forum;
2481 forum_delete_old_attachments($post);
2482 }
1da8c568 2483
2484 /// Just in case we are deleting the last post
2485 forum_discussion_update_last_post($post->discussion);
2486
caadf009 2487 return true;
2488 }
2489 return false;
2490}
501cdbd8 2491
b82faacd 2492function forum_count_replies($post, $children=true) {
2493 $count = 0;
2494
2495 if ($children) {
2496 if ($childposts = get_records('forum_posts', 'parent', $post->id)) {
2497 foreach ($childposts as $childpost) {
2498 $count ++; // For this child
2499 $count += forum_count_replies($childpost, true);
2500 }
2501 }
2502 } else {
2503 $count += count_records('forum_posts', 'parent', $post->id);
2504 }
2505
2506 return $count;
2507}
2508
2509
501cdbd8 2510function forum_forcesubscribe($forumid, $value=1) {
2511 return set_field("forum", "forcesubscribe", $value, "id", $forumid);
2512}
2513
2514function forum_is_forcesubscribed($forumid) {
709f0ec8 2515 return (get_field("forum", "forcesubscribe", "id", $forumid) == 1);
501cdbd8 2516}
2517
2518function forum_is_subscribed($userid, $forumid) {
2519 if (forum_is_forcesubscribed($forumid)) {
2520 return true;
2521 }
ebc3bd2b 2522 return record_exists("forum_subscriptions", "userid", $userid, "forum", $forumid);
86970225 2523}
2524
501cdbd8 2525function forum_subscribe($userid, $forumid) {
9fa49e22 2526/// Adds user to the subscriber list
2527
6673d7bd 2528 if (record_exists("forum_subscriptions", "userid", $userid, "forum", $forumid)) {
2529 return true;
2530 }
2531
ebc3bd2b 2532 $sub->userid = $userid;
9fa49e22 2533 $sub->forum = $forumid;
501cdbd8 2534
9fa49e22 2535 return insert_record("forum_subscriptions", $sub);
501cdbd8 2536}
2537
2538function forum_unsubscribe($userid, $forumid) {
9fa49e22 2539/// Removes user from the subscriber list
ebc3bd2b 2540 return delete_records("forum_subscriptions", "userid", $userid, "forum", $forumid);
501cdbd8 2541}
2542
0a9f61b5 2543function forum_post_subscription($post) {
2544/// Given a new post, subscribes or unsubscribes as appropriate.
2545/// Returns some text which describes what happened.
2546
2547 global $USER;
2548
2549 if (empty($post->subscribe) and empty($post->unsubscribe)) {
2550 return "";
2551 }
2552
2553 if (!$forum = get_record("forum", "id", $post->forum)) {
2554 return "";
2555 }
2556
067675c0 2557 $info->name = fullname($USER);
0a9f61b5 2558 $info->forum = $forum->name;
2559
2560 if (!empty($post->subscribe)) {
2561 forum_subscribe($USER->id, $post->forum);
2562 return "<p>".get_string("nowsubscribed", "forum", $info)."</p>";
2563 }
2564
2565 forum_unsubscribe($USER->id, $post->forum);
2566 return "<p>".get_string("nownotsubscribed", "forum", $info)."</p>";
2567}
2568
501cdbd8 2569
11b0c469 2570function forum_user_has_posted_discussion($forumid, $userid) {
29507631 2571 if ($discussions = forum_get_discussions($forumid, "", $userid)) {
501cdbd8 2572 return true;
2573 } else {
2574 return false;
2575 }
2576}
2577
fa22fd5f 2578function forum_user_can_post_discussion($forum, $currentgroup=false, $groupmode='') {
501cdbd8 2579// $forum is an object
fa22fd5f 2580 global $USER, $SESSION;
501cdbd8 2581
2582 if ($forum->type == "eachuser") {
11b0c469 2583 return (! forum_user_has_posted_discussion($forum->id, $USER->id));
501cdbd8 2584 } else if ($forum->type == "teacher") {
2585 return isteacher($forum->course);
9197e147 2586 } else if ($currentgroup) {
d591b40f 2587 return (isteacheredit($forum->course) or (ismember($currentgroup) and $forum->open == 2));
501cdbd8 2588 } else if (isteacher($forum->course)) {
2589 return true;
2590 } else {
fa22fd5f 2591 //else it might be group 0 in visible mode
2592 if ($groupmode == VISIBLEGROUPS){
2593 return ($forum->open == 2 AND ismember($currentgroup));
2594 }
2595 else {
2596 return ($forum->open == 2);
2597 }
501cdbd8 2598 }
2599}
2600
f690562f 2601function forum_user_can_post($forum, $user=NULL) {
2602// $forum, $user are objects
2603
2604 if ($user) {
2605 $isteacher = isteacher($forum->course, $user->id);
2606 } else {
2607 $isteacher = isteacher($forum->course);
2608 }
70c476a7 2609
2610 if ($forum->type == "teacher") {
f690562f 2611 return $isteacher;
2612 } else if ($isteacher) {
70c476a7 2613 return true;
2614 } else {
2615 return $forum->open;
2616 }
2617}
501cdbd8 2618
501cdbd8 2619
eaf50aef 2620/**
2621* Prints the discussion view screen for a forum.
2622*
2623* @param object $course The current course object.
2624* @param object $forum Forum to be printed.
2625* @param int $maxdiscussions The maximum number of discussions per page(optional).
2626* @param string $displayformat The display format to use (optional).
2627* @param string $sort Sort arguments for database query (optional).
2628* @param int $currentgroup Group to display discussions for (optional).
2629* @param int $groupmode Group mode of the forum (optional).
2630* @param int $page Page mode, page to display (optional).
2631*
2632*/
af328e4b 2633function forum_print_latest_discussions($course, $forum, $maxdiscussions=5, $displayformat='plain', $sort='',
2634 $currentgroup=-1, $groupmode=-1, $page=-1) {
c585fa17 2635 global $CFG, $USER;
65b0e537 2636
af328e4b 2637/// Sort out some defaults
2638
2639 if ((!$maxdiscussions) && ($displayformat == 'plain')) {
2640 $displayformat = 'header'; // Abbreviate display by default
2641 }
2642
2643 $fullpost = false;
2644 if ($displayformat == 'plain') {
2645 $fullpost = true;
f93f848a 2646 }
2647
af328e4b 2648
2649/// Decide if current user is allowed to see ALL the current discussions or not
2650
2651/// First check the group stuff
2652
2862b309 2653 if ($groupmode == -1) { /// We need to reconstruct groupmode because none was given
d5bbc556 2654 if ($cm = get_coursemodule_from_instance('forum', $forum->id, $course->id)) {
2862b309 2655 $groupmode = groupmode($course, $cm);
2656 } else {
2657 $groupmode = SEPARATEGROUPS;
2658 }
2659 }
8f0cd6ef 2660
af328e4b 2661 if ($currentgroup == -1) { /// We need to reconstruct currentgroup because none was given
2662 $currentgroup = get_current_group($course->id);
2663 }
2664
2665 if (!$currentgroup and ($groupmode != SEPARATEGROUPS or isteacheredit($course->id)) ) {
2666 $visiblegroups = -1;
2667 } else {
2668 $visiblegroups = $currentgroup;
2669 }
2670
2671/// If the user can post discussions, then this is a good place to put the button for it
fa22fd5f 2672 //add group mode in there, to test for visible group
2673 if (forum_user_can_post_discussion($forum, $currentgroup, $groupmode)) {
af328e4b 2674 echo '<div class="singlebutton forumaddnew">';
49aa3742 2675 echo "<form name=\"newdiscussionform\" method=\"get\" action=\"$CFG->wwwroot/mod/forum/post.php\">";
2676 echo "<input type=\"hidden\" name=\"forum\" value=\"$forum->id\" />";
2677 echo '<input type="submit" value="';
d5bbc556 2678 echo ($forum->type == 'news') ? get_string('addanewtopic', 'forum') : get_string('addanewdiscussion', 'forum');
49aa3742 2679 echo '" />';
2680 echo '</form>';
3479c82f 2681 echo "</div>\n";
77305fe6 2682 }
2683
2862b309 2684
2685/// Get all the recent discussions we're allowed to see
2686
096de9ad 2687 $getuserlastmodified = ($displayformat == 'header');
2688
2689 if (! $discussions = forum_get_discussions($forum->id, $sort, 0, $fullpost, $visiblegroups,0,$getuserlastmodified) ) {
af328e4b 2690 echo '<div class="forumnodiscuss">';
d5bbc556 2691 if ($forum->type == 'news') {
2692 echo '('.get_string('nonews', 'forum').')';
0351b1f9 2693 } else {
d5bbc556 2694 echo '('.get_string('nodiscussions', 'forum').')';
0351b1f9 2695 }
f13075f1 2696 echo "</div>\n";
2ab968e9 2697 return;
2698 }
65b0e537 2699
af328e4b 2700/// If no discussions then don't use paging (to avoid some divide by 0 errors)
2701
2702 if ($maxdiscussions <= 0) {
f6bb7eaa 2703 $page = -1;
af328e4b 2704 $maxdiscussions = 0;
f6bb7eaa 2705 }
2706
af328e4b 2707/// If we want paging
2708
f6bb7eaa 2709 if ($page != -1) {
2710 ///Get the number of discussions found
2711 $numdiscussions = count($discussions);
2712
2713 ///Show the paging bar
af328e4b 2714 print_paging_bar($numdiscussions, $page, $maxdiscussions, "view.php?f=$forum->id&");
f6bb7eaa 2715
2716 //Calculate the page "window"
af328e4b 2717 $pagestart = ($page * $maxdiscussions) + 1;
2718 $pageend = $pagestart + $maxdiscussions - 1;
f6bb7eaa 2719 }
2720
af328e4b 2721
3335f6fb 2722 $replies = forum_count_discussion_replies($forum->id);
f93f848a 2723
3260de67 2724 $canreply = forum_user_can_post($forum);
2725
af328e4b 2726
3335f6fb 2727 $discussioncount = 0;
c20b762a 2728 $olddiscussionlink = false;
f51e8d7e 2729 $strdatestring = get_string('strftimerecentfull');
f93f848a 2730
1d2256d0 2731 /// Check if the forum is tracked.
eaf50aef 2732 if ($cantrack = forum_tp_can_track_forums($forum)) {
77efef3e 2733 $forumtracked = forum_tp_is_tracked($forum);
1d2256d0 2734 } else {
2735 $forumtracked = false;
2736 }
2737
af328e4b 2738 if ($displayformat == 'header') {
5c8d1866 2739 echo '<table cellspacing="0" class="forumheaderlist">';
f51e8d7e 2740 echo '<thead>';
2741 echo '<tr>';
7ff9860d 2742 echo '<th class="header topic">'.get_string('discussion', 'forum').'</th>';
2743 echo '<th class="header author" colspan="2">'.get_string('startedby', 'forum').'</th>';
3a68fbbb 2744 if ($groupmode > 0) {
7ff9860d 2745 echo '<th class="header group">'.get_string('group').'</th>';
3a68fbbb 2746 }
f51e8d7e 2747 if ($forum->open or $forum->type == 'teacher') {
7ff9860d 2748 echo '<th class="header replies">'.get_string('replies', 'forum').'</th>';
eaf50aef 2749 /// If the forum can be tracked, display the unread column.
2750 if ($cantrack) {
524f9dbe 2751 echo '<th class="header replies">'.get_string('unread', 'forum');
2752 if ($forumtracked) {
2753 echo '&nbsp;<a title="'.get_string('markallread', 'forum').
2754 '" href="'.$CFG->wwwroot.'/mod/forum/markposts.php?f='.
2755 $forum->id.'&amp;mark=read&amp;returnpage=view.php">'.
2756 '<img src="'.$CFG->pixpath.'/t/clear.gif" height="11" width="11" border="0" /></a>';
2757 }
2758 echo '</th>';
47d06301 2759 }
f37da850 2760 }
7ff9860d 2761 echo '<th class="header lastpost">'.get_string('lastpost', 'forum').'</th>';
f51e8d7e 2762 echo '</tr>';
2763 echo '</thead>';
2764 echo '<tbody>';
29507631 2765 }
2766
3335f6fb 2767 foreach ($discussions as $discussion) {
2768 $discussioncount++;
f93f848a 2769
af328e4b 2770 if ($page != -1) { // We are using paging
2771 if ($discussioncount < $pagestart) { // Not there yet
f6bb7eaa 2772 continue;
2773 }
af328e4b 2774 if ($discussioncount > $pageend) { // All done, finish the loop
2775 break;
2776 }
f6bb7eaa 2777 //Without paging, old approach
af328e4b 2778 } else if ($maxdiscussions && ($discussioncount > $maxdiscussions)) {
c20b762a 2779 $olddiscussionlink = true;
3335f6fb 2780 break;
2781 }
e3ff14ca 2782
9c9f7d77 2783 if (!empty($replies[$discussion->discussion])) {
3335f6fb 2784 $discussion->replies = $replies[$discussion->discussion]->replies;
3599e487 2785 $discussion->lastpostid = $replies[$discussion->discussion]->lastpostid;
3335f6fb 2786 } else {
2787 $discussion->replies = 0;
2788 }
af328e4b 2789
489de4ae 2790 /// SPECIAL CASE: The front page can display a news item post to non-logged in users.
2791 /// All posts are read in this case.
eaf50aef 2792 if (!$forumtracked) {
2793 $discussion->unread = '-';
2794 } else if (empty($USER)) {
2795 $discussion->unread = 0;
2796 } else {
2797 $discussion->unread = forum_tp_count_discussion_unread_posts($USER->id, $discussion->discussion);
f37da850 2798 }
2799
f7477444 2800 if (!empty($USER->id)) {
2801 $ownpost = ($discussion->userid == $USER->id);
2802 } else {
2803 $ownpost=false;
2804 }
cf84431b 2805 // Use discussion name instead of subject of first post
2806 $discussion->subject = $discussion->name;
2807
af328e4b 2808 switch ($displayformat) {
2809 case 'header':
3a68fbbb 2810 if ($groupmode > 0) {
2811 if (isset($groups[$discussion->groupid])) {
2812 $group = $groups[$discussion->groupid];
2813 } else {
2814 $group = $groups[$discussion->groupid] = get_record('groups', 'id', $discussion->groupid);
2815 }
2816 } else {
2817 $group = -1;
2818 }
eaf50aef 2819 forum_print_discussion_header($discussion, $forum, $group, $strdatestring, $cantrack, $forumtracked);
3335f6fb 2820 break;
2821 default:
3260de67 2822 if ($canreply or $discussion->replies) {
2823 $link = true;
2824 } else {
2825 $link = false;
2826 }
f37da850 2827
af328e4b 2828 $discussion->forum = $forum->id;
f37da850 2829
af328e4b 2830 forum_print_post($discussion, $course->id, $ownpost, $reply=0, $link, $assessed=false);
3335f6fb 2831 break;
f93f848a 2832 }
2833 }
29507631 2834
af328e4b 2835 if ($displayformat == "header") {
f51e8d7e 2836 echo '</tbody>';
2837 echo '</table>';
29507631 2838 }
c20b762a 2839
2840 if ($olddiscussionlink) {
af328e4b 2841 echo '<div class="forumolddiscuss">';
2842 echo '<a href="'.$CFG->wwwroot.'/mod/forum/view.php?f='.$forum->id.'&amp;showall=1">';
2843 echo get_string('olderdiscussions', 'forum').'</a> ...</div>';
c20b762a 2844 }
f6bb7eaa 2845
c8680d86 2846 if ($page != -1) { ///Show the paging bar
af328e4b 2847 print_paging_bar($numdiscussions, $page, $maxdiscussions, "view.php?f=$forum->id&");
f6bb7eaa 2848 }
f93f848a 2849}
2850
af328e4b 2851
c6d691dc 2852function forum_print_discussion($course, $forum, $discussion, $post, $mode, $canreply=NULL) {
501cdbd8 2853
f37da850 2854 global $USER, $CFG;
501cdbd8 2855
61e96406 2856 if (!empty($USER->id)) {
2857 $ownpost = ($USER->id == $post->userid);
2858 } else {
2859 $ownpost = false;
2860 }
c6d691dc 2861 if ($canreply === NULL) {
2862 $reply = forum_user_can_post($forum);
2863 } else {
2864 $reply = $canreply;
2865 }
501cdbd8 2866
02ebf404 2867 $ratings = NULL;
74f5d1e3 2868 $ratingsmenuused = false;
61e96406 2869 if ($forum->assessed and !empty($USER->id)) {
d6bdd9d5 2870 if ($ratings->scale = make_grades_menu($forum->scale)) {
3bd98ad4 2871 $ratings->assesspublic = $forum->assesspublic;
98914efd 2872 $ratings->assesstimestart = $forum->assesstimestart;
2873 $ratings->assesstimefinish = $forum->assesstimefinish;
0efb3c3d 2874 $ratings->allow = (($forum->assessed != 2 or isteacher($course->id)) && !isguest());
3bd98ad4 2875
0efb3c3d 2876 if ($ratings->allow) {
2877 echo '<form name="form" method="post" action="rate.php">';
2878 echo '<input type="hidden" name="id" value="'.$course->id.'" />';
2879 }
9d1b97c5 2880 }
2881 }
2882
77efef3e 2883 $post->forum = $forum->id; // Add the forum id to the post object, later used by forum_print_post
f37da850 2884
c78ac798 2885 $post->subject = format_string($post->subject);
2886
eaf50aef 2887 if (forum_tp_can_track_forums($forum)) {
77efef3e 2888 if ($forumtracked = forum_tp_is_tracked($forum)) {
eaf50aef 2889 $user_read_array = forum_tp_get_discussion_read_records($USER->id, $post->discussion);
2890 } else {
2891 $user_read_array = array();
2892 }
f37da850 2893 } else {
eaf50aef 2894 $forumtracked = false;
f37da850 2895 $user_read_array = array();
2896 }
2897
2898 if (forum_print_post($post, $course->id, $ownpost, $reply, $link=false, $ratings,
143b43cb 2899 '', '', (!$forumtracked || isset($user_read_array[$post->id]) || forum_tp_is_post_old($post)))) {
74f5d1e3 2900 $ratingsmenuused = true;
2901 }
501cdbd8 2902
2903 switch ($mode) {
2e2e71a8 2904 case FORUM_MODE_FLATOLDEST :
2905 case FORUM_MODE_FLATNEWEST :
65b0e537 2906 default:
f37da850 2907 if (forum_print_posts_flat($post->discussion, $course->id, $mode, $ratings, $reply,
2908 $user_read_array, $post->forum)) {
74f5d1e3 2909 $ratingsmenuused = true;
2910 }
501cdbd8 2911 break;
2912
2e2e71a8 2913 case FORUM_MODE_THREADED :
f37da850 2914 if (forum_print_posts_threaded($post->id, $course->id, 0, $ratings, $reply,
2915 $user_read_array, $post->forum)) {
74f5d1e3 2916 $ratingsmenuused = true;
2917 }
501cdbd8 2918 break;
2919
2e2e71a8 2920 case FORUM_MODE_NESTED :
f37da850 2921 if (forum_print_posts_nested($post->id, $course->id, $ratings, $reply,
2922 $user_read_array, $post->forum)) {
74f5d1e3 2923 $ratingsmenuused = true;
2924 }
501cdbd8 2925 break;
2926 }
2927
74f5d1e3 2928 if ($ratingsmenuused) {
b4510d53 2929 echo "<center><input type=\"submit\" value=\"".get_string("sendinratings", "forum")."\" />";
fa01ae8b 2930 if ($forum->scale < 0) {
2931 if ($scale = get_record("scale", "id", abs($forum->scale))) {
2932 print_scale_menu_helpbutton($course->id, $scale );
2933 }
2934 }
02ebf404 2935 echo "</center>";
2936 echo "</form>";
501cdbd8 2937 }
2938}
2939
77efef3e 2940
83a305a7 2941function forum_print_posts_flat($discussion, $courseid, $direction, $ratings, $reply, &$user_read_array, $forumid=0) {
f37da850 2942 global $USER, $CFG;
501cdbd8 2943
501cdbd8 2944 $link = false;
74f5d1e3 2945 $ratingsmenuused = false;
501cdbd8 2946
2947 if ($direction < 0) {
2948 $sort = "ORDER BY created DESC";
2949 } else {
2950 $sort = "ORDER BY created ASC";
2951 }
2952
77efef3e 2953 if ($posts = forum_get_discussion_posts($discussion, $sort, $forumid)) {
501cdbd8 2954 foreach ($posts as $post) {
f37da850 2955
c78ac798 2956 $post->subject = format_string($post->subject);
2957
ebc3bd2b 2958 $ownpost = ($USER->id == $post->userid);
83a305a7 2959 if (forum_print_post($post, $courseid, $ownpost, $reply, $link, $ratings,
f37da850 2960 '', '', (isset($user_read_array[$post->id]) || forum_tp_is_post_old($post)))) {
74f5d1e3 2961 $ratingsmenuused = true;
2962 }
501cdbd8 2963 }
501cdbd8 2964 }
74f5d1e3 2965
2966 return $ratingsmenuused;
501cdbd8 2967}
2968
77efef3e 2969
83a305a7 2970function forum_print_posts_threaded($parent, $courseid, $depth, $ratings, $reply, &$user_read_array, $forumid=0) {
f37da850 2971 global $USER, $CFG;
501cdbd8 2972
501cdbd8 2973 $link = false;
74f5d1e3 2974 $ratingsmenuused = false;
501cdbd8 2975
eaf50aef 2976 $istracking = forum_tp_can_track_forums($forumid) && forum_tp_is_tracked($forumid);
77efef3e 2977
2978 if ($posts = forum_get_child_posts($parent, $forumid)) {
501cdbd8 2979 foreach ($posts as $post) {
2980
7105cf8d 2981 echo '<div class="indent">';
501cdbd8 2982 if ($depth > 0) {
ebc3bd2b 2983 $ownpost = ($USER->id == $post->userid);
f37da850 2984
c78ac798 2985 $post->subject = format_string($post->subject);
2986
83a305a7 2987 if (forum_print_post($post, $courseid, $ownpost, $reply, $link, $ratings,
f37da850 2988 '', '', (isset($user_read_array[$post->id]) || forum_tp_is_post_old($post)))) {
74f5d1e3 2989 $ratingsmenuused = true;
2990 }
501cdbd8 2991 } else {
83a305a7 2992 $by->name = fullname($post, isteacher($courseid));
d62413e8 2993 $by->date = userdate($post->modified);
f37da850 2994
eaf50aef 2995 if ($istracking) {
f37da850 2996 if (isset($user_read_array[$post->id]) || forum_tp_is_post_old($post)) {
2997 $style = '<span class="forumthread read">';
2998 } else {
2999 $style = '<span class="forumthread unread">';
3000 }
3001 } else {
3002 $style = '<span class="forumthread">';
3003 }
3004 echo $style."<a name=\"$post->id\"></a>".
17dc3f3c 3005 "<a href=\"discuss.php?d=$post->discussion&amp;parent=$post->id\">".format_string($post->subject,true)."</a> ";
8c3c8481 3006 print_string("bynameondate", "forum", $by);
f37da850 3007 echo "</span>";
501cdbd8 3008 }
3009
83a305a7 3010 if (forum_print_posts_threaded($post->id, $courseid, $depth-1, $ratings, $reply,
f37da850 3011 $user_read_array, $forumid)) {
74f5d1e3 3012 $ratingsmenuused = true;
3013 }
bb3b56c6 3014 echo "</div>\n";
501cdbd8 3015 }
501cdbd8 3016 }
74f5d1e3 3017 return $ratingsmenuused;
501cdbd8 3018}
3019
83a305a7 3020function forum_print_posts_nested($parent, $courseid, $ratings, $reply, &$user_read_array, $forumid=0) {
f37da850 3021 global $USER, $CFG;
501cdbd8 3022
501cdbd8 3023 $link = false;
74f5d1e3 3024 $ratingsmenuused = false;
501cdbd8 3025
77efef3e 3026 if ($posts = forum_get_child_posts($parent, $forumid)) {
501cdbd8 3027 foreach ($posts as $post) {
3028
7105cf8d 3029 echo '<div class="indent">';
61e96406 3030 if (empty($USER->id)) {
3031 $ownpost = false;
3032 } else {
3033 $ownpost = ($USER->id == $post->userid);
3034 }
c78ac798 3035
3036 $post->subject = format_string($post->subject);
f37da850 3037
83a305a7 3038 if (forum_print_post($post, $courseid, $ownpost, $reply, $link, $ratings,
f37da850 3039 '', '', (isset($user_read_array[$post->id]) || forum_tp_is_post_old($post)))) {
74f5d1e3 3040 $ratingsmenuused = true;
3041 }
83a305a7 3042 if (forum_print_posts_nested($post->id, $courseid, $ratings, $reply, $user_read_array, $forumid)) {
74f5d1e3 3043 $ratingsmenuused = true;
3044 }
bb3b56c6 3045 echo "</div>\n";
501cdbd8 3046 }
501cdbd8 3047 }
74f5d1e3 3048 return $ratingsmenuused;
501cdbd8 3049}
3050
2862b309 3051function forum_get_recent_mod_activity(&$activities, &$index, $sincetime, $courseid, $cmid="0", $user="", $groupid="") {
a57a7794 3052// Returns all forum posts since a given time. If forum is specified then
3053// this restricts the results
3054
3055 global $CFG;
3056
2862b309 3057 if ($cmid) {
3058 $forumselect = " AND cm.id = '$cmid'";
a57a7794 3059 } else {
3060 $forumselect = "";
3061 }
3062
3063 if ($user) {
3064 $userselect = " AND u.id = '$user'";
3065 } else {
3066 $userselect = "";
3067 }
3068
a57a7794 3069 $posts = get_records_sql("SELECT p.*, d.name, u.firstname, u.lastname,
3070 u.picture, d.groupid, cm.instance, f.name, cm.section
3071 FROM {$CFG->prefix}forum_posts p,
3072 {$CFG->prefix}forum_discussions d,
3073 {$CFG->prefix}user u,
3074 {$CFG->prefix}course_modules cm,
3075 {$CFG->prefix}forum f
3076 WHERE p.modified > '$sincetime' $forumselect
3077 AND p.userid = u.id $userselect
3078 AND d.course = '$courseid'
8f0cd6ef 3079 AND p.discussion = d.id
a57a7794 3080 AND cm.instance = f.id
3081 AND cm.course = d.course
3082 AND cm.course = f.course
3083 AND f.id = d.forum
5b257acd 3084 ORDER BY p.discussion ASC,p.created ASC");
a57a7794 3085
2862b309 3086 if (empty($posts)) {
3087 return;
3088 }
3089
3090 $isteacheredit = isteacheredit($courseid);
a57a7794 3091
90708fc1 3092 foreach ($posts as $post) {
a57a7794 3093
2862b309 3094 if ($groupid and ($post->groupid != -1 and $groupid != $post->groupid and !$isteacheredit)) {
3095 continue;
3096 }
a57a7794 3097
ac21ad39 3098 $tmpactivity = new Object;
3099
2862b309 3100 $tmpactivity->type = "forum";
3101 $tmpactivity->defaultindex = $index;
3102 $tmpactivity->instance = $post->instance;
3103 $tmpactivity->name = $post->name;
3104 $tmpactivity->section = $post->section;