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