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