/** * @return bool True if read tracking is enabled for this discussion * (it is not too old, and read tracking is turned on globally) */ public function is_read_tracked() { $this->check_full(); return mod_forumng::enabled_read_tracking() && $this->discussionfields->timemodified >= mod_forumng::get_read_tracking_deadline(); }
function mod_forumng_cm_info_view(cm_info $cm) { global $CFG; require_once $CFG->dirroot . '/mod/forumng/mod_forumng.php'; static $forums = null; if ($forums === null) { // Read tracking is for real users only if (mod_forumng::enabled_read_tracking() && !isguestuser() && isloggedin()) { $forums = mod_forumng::get_course_forums($cm->get_course(), 0, mod_forumng::UNREAD_BINARY); } else { $forums = array(); } } // If current forum is listed, check whether it's unread or not if (array_key_exists($cm->instance, $forums)) { if ($forums[$cm->instance]->has_unread_discussions()) { $cm->set_after_link('<span class="unread">' . get_string('hasunreadposts', 'forumng') . '</span>'); } } }
/** * Splits this post to become a new discussion * @param $newsubject * @param bool $log True to log action * @return int ID of new discussion */ public function split($newsubject, $log = true) { global $DB; $this->require_children(); // Begin a transaction $transaction = $DB->start_delegated_transaction(); $olddiscussion = $this->get_discussion(); // Create new discussion $newest = null; $this->find_newest_child($newest); $newdiscussionid = $olddiscussion->clone_for_split($this->get_id(), $newest->get_id()); // Update all child posts $list = array(); $this->list_child_ids($list); unset($list[0]); // Don't include this post itself if (count($list) > 0) { list($listsql, $listparams) = mod_forumng_utils::get_in_array_sql('id', $list); $DB->execute("\nUPDATE\n {forumng_posts}\nSET\n discussionid = ?\nWHERE\n {$listsql}", array_merge(array($newdiscussionid), $listparams)); } // Update any edited posts in this discussion. Edited posts are // not included in the child id list above because they are not // loaded as children, but they are conceptually stored as children // of one of the posts being moved. $parentlist = $list; $parentlist[] = $this->get_id(); list($parentlistsql, $parentlistparams) = mod_forumng_utils::get_in_array_sql('parentpostid', $parentlist); $DB->execute("\nUPDATE\n {forumng_posts}\nSET\n discussionid = ?\nWHERE\n oldversion = 1 AND {$parentlistsql}", array_merge(array($newdiscussionid), $parentlistparams)); // Update this post $changes = new stdClass(); $changes->id = $this->get_id(); $changes->subject = $newsubject; $changes->parentpostid = null; // When split the post, reset the important to 0 so that it is not highlighted. $changes->important = 0; // Note don't update modified time, or it makes this post unread, // which isn't very helpful $changes->discussionid = $newdiscussionid; $DB->update_record('forumng_posts', $changes); // Update read data if relevant if (mod_forumng::enabled_read_tracking() && $newest->get_modified() >= mod_forumng::get_read_tracking_deadline()) { $rs = $DB->get_recordset_sql("\nSELECT\n userid, time\nFROM\n {forumng_read}\nWHERE\n discussionid = ? AND time >= ?", array($olddiscussion->get_id(), $this->get_created())); foreach ($rs as $rec) { $rec->discussionid = $newdiscussionid; $DB->insert_record('forumng_read', $rec); } $rs->close(); } $olddiscussion->possible_lastpost_change(); if ($log) { $this->log('split post'); } $transaction->allow_commit(); $this->get_discussion()->uncache(); // If discussion-based completion is turned on, this may enable someone // to complete if ($this->get_forum()->get_completion_discussions()) { $this->update_completion(true); } return $newdiscussionid; }
/** * Tests that discussions can be marked as read. * (unread count etc tested in test_get_course_forums()) */ public function test_individual_posts_marked_read() { global $USER, $DB, $CFG; $this->resetAfterTest(true); $this->setAdminUser(); $adminid = $USER->id; $CFG->forumng_trackreadposts = true; $generator = $this->getDataGenerator()->get_plugin_generator('mod_forumng'); $course = $this->get_new_course(); $etuser = $this->get_new_user('editingteacher', $course->id); $suser1 = $this->get_new_user('student', $course->id); $suser2 = $this->get_new_user('student', $course->id); // Set mark as read to 'manually' for discussions and posts. set_user_preference('forumng_manualmark', 1, $adminid); set_user_preference('forumng_manualmark', 1, $etuser); set_user_preference('forumng_manualmark', 1, $suser1); set_user_preference('forumng_manualmark', 1, $suser2); $forum1 = $this->get_new_forumng($course->id, array('groupmode' => VISIBLEGROUPS, 'shared' => false, 'cmidnumber' => 'IPMR')); $did1 = $generator->create_discussion(array('course' => $course, 'forum' => $forum1->get_id(), 'userid' => $etuser->id)); $forumetposts = mod_forumng::get_course_forums($course, $etuser->id, mod_forumng::UNREAD_DISCUSSIONS); // Check new discussion test state for 1st etuser. $this->assertFalse($forumetposts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(0, $forumetposts[$forum1->get_id()]->get_num_unread_discussions()); $post1 = $generator->create_post(array('discussionid' => $did1[0], 'parentpostid' => $did1[1], 'userid' => $suser1->id)); $post2 = $generator->create_post(array('discussionid' => $did1[0], 'parentpostid' => $did1[1], 'userid' => $suser2->id)); $post3 = $generator->create_post(array('discussionid' => $did1[0], 'parentpostid' => $did1[1], 'userid' => $suser1->id)); $post4 = $generator->create_post(array('discussionid' => $did1[0], 'parentpostid' => $did1[1], 'userid' => $suser2->id)); $post5 = $generator->create_post(array('discussionid' => $did1[0], 'parentpostid' => $did1[1], 'userid' => $etuser->id)); $post6 = $generator->create_post(array('discussionid' => $did1[0], 'parentpostid' => $did1[1], 'userid' => $suser1->id)); $post7 = $generator->create_post(array('discussionid' => $did1[0], 'parentpostid' => $did1[1], 'userid' => $suser2->id)); $post8 = $generator->create_post(array('discussionid' => $did1[0], 'parentpostid' => $did1[1], 'userid' => $suser1->id)); $post9 = $generator->create_post(array('discussionid' => $did1[0], 'parentpostid' => $did1[1], 'userid' => $suser2->id)); $post10 = $generator->create_post(array('discussionid' => $did1[0], 'parentpostid' => $did1[1], 'userid' => $etuser->id)); $forumadminposts = mod_forumng::get_course_forums($course, $adminid, mod_forumng::UNREAD_DISCUSSIONS); $this->assertTrue($forumadminposts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(1, $forumadminposts[$forum1->get_id()]->get_num_unread_discussions()); // Note etuser is classed as read at forum level as they made last post in discussion. $forumetposts = mod_forumng::get_course_forums($course, $etuser->id, mod_forumng::UNREAD_DISCUSSIONS); $this->assertFalse($forumetposts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(0, $forumetposts[$forum1->get_id()]->get_num_unread_discussions()); // Check etuser should be classed as unread at discussion level. $discussionetuser = mod_forumng_discussion::get_from_id($did1[0], 0, $etuser->id); $this->assertEquals(8, $discussionetuser->get_num_unread_posts()); $forumsuser1posts = mod_forumng::get_course_forums($course, $suser1->id, mod_forumng::UNREAD_DISCUSSIONS); $this->assertTrue($forumsuser1posts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(1, $forumsuser1posts[$forum1->get_id()]->get_num_unread_discussions()); $forumsuser2posts = mod_forumng::get_course_forums($course, $suser2->id, mod_forumng::UNREAD_DISCUSSIONS); $this->assertTrue($forumsuser2posts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(1, $forumsuser2posts[$forum1->get_id()]->get_num_unread_discussions()); // Create post objects. $post = mod_forumng_post::get_from_id($did1[1], 0); // Etuser. $posta = mod_forumng_post::get_from_id($post1->id, 0); // Suser1. $postb = mod_forumng_post::get_from_id($post2->id, 0); // Suser2. $postc = mod_forumng_post::get_from_id($post3->id, 0); // Suser1. $postd = mod_forumng_post::get_from_id($post4->id, 0); // Suser2. $poste = mod_forumng_post::get_from_id($post5->id, 0); // Etuser. $postf = mod_forumng_post::get_from_id($post6->id, 0); // Suser1. $postg = mod_forumng_post::get_from_id($post7->id, 0); // Suser2. $posth = mod_forumng_post::get_from_id($post8->id, 0); // Suser1. $posti = mod_forumng_post::get_from_id($post9->id, 0); // Suser2. $postj = mod_forumng_post::get_from_id($post10->id, 0); // Etuser. // Individuals mark some posts as read. $post->mark_read(0, $suser1->id); // Poster Etuser, reader Student 1. $post->mark_read(0, $suser2->id); // Poster Etuser, reader Student 2. $posta->mark_read(0, $etuser->id); // Poster Suser1, reader Teacher. $posta->mark_read(0, $suser2->id); // Poster Suser1, reader Student 1. $postb->mark_read(0, $suser1->id); // Poster Suser2, reader Student 2. $postb->mark_read(0, $etuser->id); // Poster Suser2, reader Teacher. $postc->mark_read(0, $suser2->id); // Poster Suser1, reader Student 2. $postc->mark_read(0, $etuser->id); // Poster Suser1, reader Teacher. $postd->mark_read(0, $suser1->id); // Poster Suser2, reader Student 1. $postd->mark_read(0, $etuser->id); // Poster Suser2, reader Teacher. $poste->mark_read(0, $suser1->id); // Poster Etuser, reader Student 1. $poste->mark_read(0, $suser2->id); // Poster Etuser, reader Student 2. // Test forum read aggregate functions. $this->assertTrue(mod_forumng::enabled_read_tracking()); $forumadminposts = mod_forumng::get_course_forums($course, $adminid, mod_forumng::UNREAD_DISCUSSIONS); $this->assertTrue($forumadminposts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(1, $forumadminposts[$forum1->get_id()]->get_num_unread_discussions()); // Note etuser is classed as read at forum level as they made last post in discussion. $forumetposts = mod_forumng::get_course_forums($course, $etuser->id, mod_forumng::UNREAD_DISCUSSIONS); $this->assertFalse($forumetposts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(0, $forumetposts[$forum1->get_id()]->get_num_unread_discussions()); $forumsuser1posts = mod_forumng::get_course_forums($course, $suser1->id, mod_forumng::UNREAD_DISCUSSIONS); $this->assertTrue($forumsuser1posts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(1, $forumsuser1posts[$forum1->get_id()]->get_num_unread_discussions()); $forumsuser2posts = mod_forumng::get_course_forums($course, $suser2->id, mod_forumng::UNREAD_DISCUSSIONS); $this->assertTrue($forumsuser2posts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(1, $forumsuser2posts[$forum1->get_id()]->get_num_unread_discussions()); // Get read counts for editingteacher, include count of their own posts. $discussionetuser = mod_forumng_discussion::get_from_id($did1[0], 0, $etuser->id); $etuserposts = $discussionetuser->get_num_posts(); $this->assertEquals(1, count($etuserposts)); $unreadpostsetuser = $discussionetuser->get_num_unread_posts(); $this->assertEquals(4, $unreadpostsetuser); $readpostsetuser = $DB->get_records('forumng_read_posts', array('userid' => $etuser->id)); $this->assertCount(4, $readpostsetuser); // Get the first count for the student user 1, includes count of their own posts. $discussionsuser1 = mod_forumng_discussion::get_from_id($did1[0], 0, $suser1->id); $suser1posts = $discussionsuser1->get_num_posts(); $this->assertEquals(1, count($suser1posts)); $unreadpostsuser1 = $discussionsuser1->get_num_unread_posts(); $this->assertEquals(3, $unreadpostsuser1); $readpostsuser1 = $DB->get_records('forumng_read_posts', array('userid' => $suser1->id)); $this->assertCount(4, $readpostsuser1); // Get the first count for the student user 2, includes count of their own posts. $discussionsuser2 = mod_forumng_discussion::get_from_id($did1[0], 0, $suser2->id); $suser2posts = $discussionsuser2->get_num_posts(); $this->assertEquals(1, count($suser2posts)); $unreadpostsuser2 = $discussionsuser2->get_num_unread_posts(); $this->assertEquals(3, $unreadpostsuser2); $readpostsuser2 = $DB->get_records('forumng_read_posts', array('userid' => $suser2->id)); $this->assertCount(4, $readpostsuser2); // Individuals mark some more posts as read. $postf->mark_read(0, $etuser->id); // Poster Suser1, reader Teacher. $postf->mark_read(0, $suser2->id); // Poster Suser1, reader Student 2. $postg->mark_read(0, $suser2->id); // Poster Suser2, reader Teacher. $postg->mark_read(0, $suser1->id); // Poster Suser2, reader Student 1. $posth->mark_read(0, $etuser->id); // Poster Suser1, reader Teacher. $posth->mark_read(0, $suser2->id); // Poster Suser1, reader Student 2. $posti->mark_read(0, $suser1->id); // Poster Suser2, reader Student 1. $posti->mark_read(0, $etuser->id); // Poster Suser2, reader Teacher. $postj->mark_read(0, $suser1->id); // Poster Etuser, reader Student 1. $postj->mark_read(0, $suser2->id); // Poster Etuser, reader Student 2. $forumadminposts = mod_forumng::get_course_forums($course, $adminid, mod_forumng::UNREAD_DISCUSSIONS); $this->assertTrue($forumadminposts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(1, $forumadminposts[$forum1->get_id()]->get_num_unread_discussions()); // Note etuser is classed as read at forum level as they made last post in discussion. $forumetposts = mod_forumng::get_course_forums($course, $etuser->id, mod_forumng::UNREAD_DISCUSSIONS); $this->assertFalse($forumetposts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(0, $forumetposts[$forum1->get_id()]->get_num_unread_discussions()); $forumsuser1posts = mod_forumng::get_course_forums($course, $suser1->id, mod_forumng::UNREAD_DISCUSSIONS); $this->assertFalse($forumsuser1posts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(0, $forumsuser1posts[$forum1->get_id()]->get_num_unread_discussions()); $forumsuser2posts = mod_forumng::get_course_forums($course, $suser2->id, mod_forumng::UNREAD_DISCUSSIONS); $this->assertFalse($forumsuser2posts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(0, $forumsuser2posts[$forum1->get_id()]->get_num_unread_discussions()); // Get second read count for editingteacher, includes count of their own posts. $discussionetuser = mod_forumng_discussion::get_from_id($did1[0], 0, $etuser->id); $etuserposts = $discussionetuser->get_num_posts(); $this->assertEquals(11, $etuserposts); $unreadpostsetuser = $discussionetuser->get_num_unread_posts(); $this->assertEquals(1, $unreadpostsetuser); $readpostsetuser = $DB->get_records('forumng_read_posts', array('userid' => $etuser->id)); $this->assertCount(7, $readpostsetuser); // Get the second count for the student user 1, includes count of their own posts. $discussionsuser1 = mod_forumng_discussion::get_from_id($did1[0], 0, $suser1->id); $suser1posts = $discussionsuser1->get_num_posts(); $this->assertEquals(1, count($suser1posts)); $unreadpostsuser1 = $discussionsuser1->get_num_unread_posts(); $this->assertEquals(0, $unreadpostsuser1); $readpostsuser1 = $DB->get_records('forumng_read_posts', array('userid' => $suser1->id)); $this->assertCount(7, $readpostsuser1); // Get more counts for the student user 2, includes count of their own posts. $discussionsuser2 = mod_forumng_discussion::get_from_id($did1[0], 0, $suser2->id); $suser2posts = $discussionsuser2->get_num_posts(); $this->assertEquals(1, count($suser2posts)); $unreadpostsuser2 = $discussionsuser2->get_num_unread_posts(); $this->assertEquals(0, $unreadpostsuser2); $readpostsuser2 = $DB->get_records('forumng_read_posts', array('userid' => $suser2->id)); $this->assertCount(8, $readpostsuser2); // Mark ALL individual posts as unread. $discussionetuser->mark_unread($etuser->id); $discussionsuser1->mark_unread($suser1->id); $discussionsuser2->mark_unread($suser2->id); $forumadminposts = mod_forumng::get_course_forums($course, $adminid, mod_forumng::UNREAD_DISCUSSIONS); $this->assertTrue($forumadminposts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(1, $forumadminposts[$forum1->get_id()]->get_num_unread_discussions()); // Note etuser is classed as read at forum level as they made last post in discussion. $forumetposts = mod_forumng::get_course_forums($course, $etuser->id, mod_forumng::UNREAD_DISCUSSIONS); $this->assertFalse($forumetposts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(0, $forumetposts[$forum1->get_id()]->get_num_unread_discussions()); $forumsuser1posts = mod_forumng::get_course_forums($course, $suser1->id, mod_forumng::UNREAD_DISCUSSIONS); $this->assertTrue($forumsuser1posts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(1, $forumsuser1posts[$forum1->get_id()]->get_num_unread_discussions()); $forumsuser2posts = mod_forumng::get_course_forums($course, $suser2->id, mod_forumng::UNREAD_DISCUSSIONS); $this->assertTrue($forumsuser2posts[$forum1->get_id()]->has_unread_discussions()); $this->assertEquals(1, $forumsuser2posts[$forum1->get_id()]->get_num_unread_discussions()); $discussionetuser = mod_forumng_discussion::get_from_id($did1[0], 0, $etuser->id); $etuserposts = $discussionetuser->get_num_posts(); $this->assertEquals(11, $etuserposts); $unreadpostsetuser = $discussionetuser->get_num_unread_posts(); $this->assertEquals(8, $unreadpostsetuser); $readpostsetuser = $DB->get_records('forumng_read_posts', array('userid' => $etuser->id)); $this->assertCount(0, $readpostsetuser); $unreadpostset = $discussionetuser->get_num_unread_posts(); $unreadpostsuser1 = $discussionsuser1->get_num_unread_posts(); $unreadpostsuser2 = $discussionsuser2->get_num_unread_posts(); $this->assertEquals(8, $unreadpostset); $this->assertEquals(0, $unreadpostsuser1); $this->assertEquals(0, $unreadpostsuser2); }
/** * Internal method. Queries for a number of forums, including additional * data about unread posts etc. Returns the database result. * @param array $cmids If specified, array of course-module IDs of desired * forums * @param object $course If specified, course object * @param int $userid User ID, 0 = current user * @param int $unread Type of unread data to obtain (UNREAD_xx constant). * @param array $groups Array of group IDs to which the given user belongs * (may be null if unread data not required) * @param array $aagforums Array of forums in which the user has * 'access all groups' (may be null if unread data not required) * @param array $viewhiddenforums Array of forums in which the user has * 'view hidden discussions' (may be null if unread data not required) * @return array Array of row objects */ private static function query_forums($cmids = array(), $course = null, $userid, $unread, $groups, $aagforums, $viewhiddenforums) { global $DB, $CFG, $USER; if (!count($cmids) && !$course) { throw new coding_exception("mod_forumng::query_forums requires course id or cmids"); } if (count($cmids)) { list($in, $conditionsparams) = mod_forumng_utils::get_in_array_sql('cm.id', $cmids); $conditions = $in; } else { $conditions = "f.course = ?"; $conditionsparams = array($course->id); } $singleforum = count($cmids) == 1 ? reset($cmids) : false; list($inviewhiddenforums, $inviewhiddenforumsparams) = mod_forumng_utils::get_in_array_sql('fd.forumngid', $viewhiddenforums); list($cfdinviewhiddenforums, $inviewhiddenforumsparams) = mod_forumng_utils::get_in_array_sql('cfd.forumngid', $viewhiddenforums); // This array of additional results is used later if combining // standard results with single-forum calls. $plusresult = array(); // For read tracking, we get a count of total number of posts in // forum, and total number of read posts in the forum (this // is so we can display the number of UNread posts, but the query // works that way around because it will return 0 if no read // information is stored). if ($unread != self::UNREAD_NONE && mod_forumng::enabled_read_tracking()) { // Work out when unread status ends $endtime = time() - $CFG->forumng_readafterdays * 24 * 3600; if (!$userid) { $userid = $USER->id; } list($ingroups, $ingroupsparams) = mod_forumng_utils::get_in_array_sql('fd.groupid', $groups); list($inaagforums, $inaagforumsparams) = mod_forumng_utils::get_in_array_sql('fd.forumngid', $aagforums); $restrictionsql = ''; $restrictionparams = array(); if ($singleforum) { // If it is for a single forum, get the restriction from the // forum type $forum = mod_forumng::get_from_cmid($singleforum, mod_forumng::CLONE_DIRECT); $type = $forum->get_type(); if ($type->has_unread_restriction()) { list($value, $restrictionparams) = $type->get_unread_restriction_sql($forum); if ($value) { $restrictionsql = 'AND ' . $value; } } } else { // When it is not for a single forum, we can only group together // results for types that do not place restrictions on the // unread count. $modinfo = get_fast_modinfo($course); $okayids = array(); if (array_key_exists('forumng', $modinfo->instances)) { foreach ($modinfo->instances['forumng'] as $info) { if (count($cmids) && !in_array($info->id, $cmids)) { continue; } $type = self::get_type_from_modinfo_info($info); if (forumngtype::get_new($type)->has_unread_restriction()) { // This one's a problem! Do it individually $problemresults = self::query_forums(array($info->id), null, $userid, $unread, $groups, $aagforums, $viewhiddenforums); foreach ($problemresults as $problemresult) { $plusresult[$problemresult->f_id] = $problemresult; } } else { $okayids[] = $info->id; } } } if (count($okayids) == 0) { // There are no 'normal' forums, so return result so far // after sorting it uasort($plusresult, 'mod_forumng::sort_mod_forumng_result'); return $plusresult; } else { // Fall through to normal calculation, but change conditions // to include only the 'normal' forums list($in, $inparams) = mod_forumng_utils::get_in_array_sql('cm.id', $okayids); $conditions .= " AND " . $in; $conditionsparams = array_merge($conditionsparams, $inparams); } } // NOTE fpfirst is used only by forum types, not here $now = time(); $sharedquerypart = "\nFROM\n {forumng_discussions} fd\n INNER JOIN {forumng_posts} fplast ON fd.lastpostid = fplast.id\n INNER JOIN {forumng_posts} fpfirst ON fd.postid = fpfirst.id\n LEFT JOIN {forumng_read} fr ON fd.id = fr.discussionid AND fr.userid = ?\nWHERE\n fd.forumngid = f.id AND fplast.modified>?\n AND (\n (fd.groupid IS NULL)\n OR ({$ingroups})\n OR cm.groupmode = " . VISIBLEGROUPS . "\n OR ({$inaagforums})\n )\n AND fd.deleted = 0\n AND (\n ((fd.timestart = 0 OR fd.timestart <= ?)\n AND (fd.timeend = 0 OR fd.timeend > ?))\n OR ({$inviewhiddenforums})\n )\n AND ((fplast.edituserid IS NOT NULL AND fplast.edituserid<>?)\n OR fplast.userid<>?)\n AND (fr.time IS NULL OR fplast.modified>fr.time)\n {$restrictionsql}"; $sharedqueryparams = array_merge(array($userid, $endtime), $ingroupsparams, $inaagforumsparams, array($now, $now), $inviewhiddenforumsparams, array($userid, $userid), $restrictionparams); // Note: There is an unusual case in which this number can // be inaccurate. It is to do with ignoring messages the user // posted. We consider a discussion as 'not unread' if the last // message is by current user. In actual fact, a discussion could // contain unread messages if messages were posted by other users // after this user viewed the forum last, but before they posted // their reply. Since this should be an infrequent occurrence I // believe this behaviour is acceptable. if ($unread == self::UNREAD_BINARY) { // Query to get 0/1 unread discussions count $readtracking = self::select_exists("SELECT 1 {$sharedquerypart}") . "AS f_hasunreaddiscussions"; $readtrackingparams = $sharedqueryparams; } else { // Query to get full unread discussions count $readtracking = "\n(SELECT\n COUNT(1)\n{$sharedquerypart}\n) AS f_numunreaddiscussions"; $readtrackingparams = $sharedqueryparams; } } else { $readtracking = "NULL AS numreadposts, NULL AS timeread"; $readtrackingparams = array(); } $now = time(); $orderby = "LOWER(f.name)"; // Main query. This retrieves: // - Full forum fields // - Basic course-module and course data (not whole tables) // - Discussion count // - Unread data, if enabled // - User subscription data $result = $DB->get_records_sql($sql = "\nSELECT\n " . mod_forumng_utils::select_mod_forumng_fields('f') . ",\n " . mod_forumng_utils::select_course_module_fields('cm') . ",\n " . mod_forumng_utils::select_course_fields('c') . ",\n (SELECT COUNT(1)\n FROM {forumng_discussions} cfd\n WHERE cfd.forumngid = f.id AND cfd.deleted = 0\n AND (\n ((cfd.timestart = 0 OR cfd.timestart <= ?)\n AND (cfd.timeend = 0 OR cfd.timeend > ?))\n OR ({$cfdinviewhiddenforums})\n )\n ) AS f_numdiscussions,\n {$readtracking}\nFROM\n {forumng} f\n INNER JOIN {course_modules} cm ON cm.instance = f.id\n AND cm.module = (SELECT id from {modules} WHERE name = 'forumng')\n INNER JOIN {course} c ON c.id = f.course\nWHERE\n {$conditions}\nORDER BY\n {$orderby}", array_merge(array($now, $now), $inviewhiddenforumsparams, $readtrackingparams, $conditionsparams)); if (count($plusresult) > 0) { foreach ($plusresult as $key => $value) { $result[$key] = $value; } uasort($result, 'mod_forumng::sort_mod_forumng_result'); } return $result; }