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