コード例 #1
0
 /**
  * @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();
 }
コード例 #2
0
ファイル: lib.php プロジェクト: unikent/moodle-mod_forumng
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>');
        }
    }
}
コード例 #3
0
 /**
  * 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;
 }
コード例 #4
0
 /**
  * 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);
 }
コード例 #5
0
 /**
  * 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;
 }