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