/** * Internal method. Queries for a number of discussions, including additional * data about unread posts etc. Returns the database result. * @param string $conditions WHERE clause (may refer to aliases 'd' for discussion) * @param array $conditionparams Parameters for conditions * @param int $userid User ID, 0 = current user, -1 = no unread data is needed * @param string $orderby ORDER BY clause * @param int $limitfrom Limit on results * @param int $limitnum Limit on results * @param mod_forumng $typeforum If set, this forum is used to potentially restrict * the results based on forum type limits * @return adodb_recordset Database query results */ static function query_discussions($conditions, $conditionparams, $userid, $orderby, $limitfrom = '', $limitnum = '', $typeforum = null) { global $USER, $DB; // For read tracking, we get a count of total number of posts in // discussion, and total number of read posts in the discussion (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 (mod_forumng::enabled_read_tracking() && $userid != -1) { if (!$userid) { $userid = $USER->id; } $deadline = mod_forumng::get_read_tracking_deadline(); $readtracking = "\n , (CASE WHEN fplast.modified<? THEN " . self::PAST_SELL_BY . " ELSE (SELECT COUNT(1)\n FROM {forumng_posts} fp3\n WHERE fp3.discussionid = fd.id AND fp3.oldversion = 0\n AND fp3.deleted = 0\n AND (fp3.modified<fr.time OR fp3.edituserid = ?\n OR (fp3.edituserid IS NULL AND fp3.userid = ?)\n OR fp3.modified < ?)) END) AS numreadposts,\n fr.time AS timeread"; $readtrackingjoin = "LEFT JOIN {forumng_read} fr\n ON fd.id = fr.discussionid AND fr.userid = ?"; $readtrackingparams = array($deadline, $userid, $userid, $deadline); $readtrackingjoinparams = array($userid); } else { $readtracking = ""; $readtrackingjoin = ""; $readtrackingparams = array(); $readtrackingjoinparams = array(); } $order = $orderby ? 'ORDER BY ' . $orderby : ''; // Handle forum type restriction $typejoin = ''; $typeparams = array(); if ($typeforum && $userid != -1) { $type = $typeforum->get_type(); if ($type->has_unread_restriction()) { list($restrictionsql, $restrictionparams) = $type->get_unread_restriction_sql($typeforum, $userid); } else { $restrictionsql = false; } if ($restrictionsql) { $typejoin = "\n INNER JOIN {forumng} f ON f.id = fd.forumngid\n INNER JOIN {course} c ON c.id = f.course\n INNER JOIN {course_modules} cm ON cm.instance = f.id AND cm.course = f.course\n INNER JOIN {modules} m ON m.id = cm.module"; $conditions .= " AND m.name = 'forumng' AND {$restrictionsql}"; $conditionparams = array_merge($conditionparams, $restrictionparams); } } // Main query. This retrieves: // * Basic discussion information. // * Information about the discussion that is obtained from the first and // last post. // * Information about the users responsible for first and last post. $rs = $DB->get_recordset_sql("\nSELECT * FROM (SELECT\n fd.*,\n fpfirst.created AS timecreated,\n fplast.modified AS timemodified,\n fpfirst.subject AS subject,\n fplast.subject AS lastsubject,\n fplast.message AS lastmessage,\n " . mod_forumng_utils::select_username_fields('fu') . ",\n " . mod_forumng_utils::select_username_fields('lu') . ",\n (SELECT COUNT(1)\n FROM {forumng_posts} fp2\n WHERE fp2.discussionid = fd.id AND fp2.deleted = 0 AND fp2.oldversion = 0)\n AS numposts,\n g.name AS groupname\n {$readtracking}\nFROM\n {forumng_discussions} fd\n INNER JOIN {forumng_posts} fpfirst ON fd.postid = fpfirst.id\n INNER JOIN {user} fu ON fpfirst.userid = fu.id\n INNER JOIN {forumng_posts} fplast ON fd.lastpostid = fplast.id\n INNER JOIN {user} lu ON fplast.userid = lu.id\n LEFT JOIN {groups} g ON g.id = fd.groupid\n {$readtrackingjoin}\n {$typejoin}\nWHERE\n {$conditions}) x {$order}\n", array_merge($readtrackingparams, $readtrackingjoinparams, $conditionparams), $limitfrom, $limitnum); return $rs; }
/** * Shared logic that works out whether a particular subscriber receives a * discussion or not. * @param mod_forumng $forum Forum * @param mod_forumng_discussion $discussion Discussion * @param object $subscriber Subscriber */ private static function subscriber_receives_discussion($forum, $discussion, $subscriber) { // Did they subscribe specifically to this discussion? $explicitsubscribed = array_key_exists($discussion->get_id(), $subscriber->discussionids); // Did they subscribe to the group this discussion belongs to $explicitsubscribedtogroup = in_array($discussion->get_group_id(), $subscriber->groupids); $groupid = $discussion->get_group_id(); $visiblegroups = $forum->get_group_mode() == VISIBLEGROUPS; // Conditions for each subscriber to get this discussion $result = ($subscriber->wholeforum || $explicitsubscribed || $explicitsubscribedtogroup) && (!$groupid || $subscriber->accessallgroups || $visiblegroups || array_key_exists($groupid, $subscriber->groups)) && $forum->get_type()->can_view_discussion($discussion, $subscriber->id); return $result; }
/** * Internal method. Queries for a number of discussions, including additional * data about unread posts etc. Returns the database result. * @param string $conditions WHERE clause (may refer to aliases 'd' for discussion) * @param array $conditionparams Parameters for conditions * @param int $userid User ID, 0 = current user, -1 = no unread data is needed * @param string $orderby ORDER BY clause * @param int $limitfrom Limit on results * @param int $limitnum Limit on results * @param mod_forumng $typeforum If set, this forum is used to potentially restrict * the results based on forum type limits * @param boolean $flags set to indicate that flagged discussions are to be returned * @param boolean hastag set to indicate that tagged discussions are to be returned * @return adodb_recordset Database query results */ public static function query_discussions($conditions, $conditionparams, $userid, $orderby, $limitfrom = '', $limitnum = '', $typeforum = null, $flags = false, $hastag = false) { global $USER, $DB; // For read tracking, we get a count of total number of posts in // discussion, and total number of read posts in the discussion (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 (mod_forumng::enabled_read_tracking() && $userid != -1) { if (!$userid) { $userid = $USER->id; } $deadline = mod_forumng::get_read_tracking_deadline(); $readjoin1 = ""; $readwhere1 = ""; $readtrackingparams = array($deadline, $userid, $userid, $deadline); $readtrackingjoinparams = array($userid); if (!mod_forumng::mark_read_automatically($userid)) { // Ind Mark read - check individual read_posts state. $readjoin1 = "LEFT JOIN {forumng_read_posts} frp2 on frp2.postid = fp3.id AND frp2.userid = ?"; $readwhere1 = "OR frp2.id IS NOT NULL"; $readtrackingparams = array($deadline, $userid, $userid, $userid, $deadline); } // Get unread count only when last added post is newer than deadline. // When PAST_SELL_BY, posts modified later than last will be unread but not picked up. $readtracking = "\n , (CASE WHEN fplast.modified IS NOT NULL AND fplast.modified < ? THEN " . self::PAST_SELL_BY . " ELSE (SELECT COUNT(1)\n FROM {forumng_posts} fp3\n {$readjoin1}\n WHERE fp3.discussionid = fd.id AND fp3.oldversion = 0\n AND fp3.deleted = 0\n AND (fp3.modified < fr.time OR fp3.edituserid = ?\n {$readwhere1}\n OR (fp3.edituserid IS NULL AND fp3.userid = ?)\n OR fp3.modified < ?)) END) AS numreadposts,\n fr.time AS timeread"; // Join read info, get posts not authored by user: get latest modified post time. $readtrackingjoin = "LEFT JOIN {forumng_read} fr ON fd.id = fr.discussionid AND fr.userid = ?"; } else { $readtracking = ", 0 AS numreadposts, NULL AS timeread"; $readtrackingjoin = ""; $readtrackingparams = array(); $readtrackingjoinparams = array(); } $order = $orderby ? 'ORDER BY ' . $orderby : ''; // Handle forum type restriction $typejoin = ''; $typeparams = array(); $flagsjoin = ''; $flagsquery = ''; $flagparams = array(); if ($typeforum && $userid != -1) { $type = $typeforum->get_type(); if ($type->has_unread_restriction()) { list($restrictionsql, $restrictionparams) = $type->get_unread_restriction_sql($typeforum, $userid); } else { $restrictionsql = false; } if ($restrictionsql) { $typejoin = "\n INNER JOIN {forumng} f ON f.id = fd.forumngid\n INNER JOIN {course} c ON c.id = f.course\n INNER JOIN {course_modules} cm ON cm.instance = f.id AND cm.course = f.course\n INNER JOIN {modules} m ON m.id = cm.module"; $conditions .= " AND m.name = 'forumng' AND {$restrictionsql}"; $conditionparams = array_merge($conditionparams, $restrictionparams); } } if ($flags && $userid != -1) { $flagsjoin = "LEFT JOIN {forumng_flags} ff ON ff.discussionid = fd.id AND ff.userid = ?"; $flagsquery = ', ff.flagged'; $flagparams = array($userid); } // Tag join sql if needed. $tagjoin = ''; if ($hastag) { $tagjoin = "LEFT JOIN {tag_instance} ti on ti.itemid = fd.id\n AND ti.itemtype = 'forumng_discussions'\n AND ti.component = 'mod_forumng'"; } // Main query. This retrieves: // * Basic discussion information. // * Information about the discussion that is obtained from the first and // last post. // * Information about the users responsible for first and last post. $rs = $DB->get_recordset_sql("\nSELECT * FROM (SELECT\n fd.*,\n fpfirst.created AS timecreated,\n fplast.modified AS timemodified,\n fpfirst.subject AS subject,\n fplast.subject AS lastsubject,\n fplast.message AS lastmessage,\n fpfirst.asmoderator AS firstasmoderator,\n fplast.asmoderator AS lastasmoderator,\n " . mod_forumng_utils::select_username_fields('fu') . ",\n " . mod_forumng_utils::select_username_fields('lu') . ",\n (SELECT COUNT(1)\n FROM {forumng_posts} fp2\n WHERE fp2.discussionid = fd.id AND fp2.deleted = 0 AND fp2.oldversion = 0)\n AS numposts,\n g.name AS groupname\n {$readtracking}\n {$flagsquery}\nFROM\n {forumng_discussions} fd\n INNER JOIN {forumng_posts} fpfirst ON fd.postid = fpfirst.id\n INNER JOIN {user} fu ON fpfirst.userid = fu.id\n INNER JOIN {forumng_posts} fplast ON fd.lastpostid = fplast.id\n INNER JOIN {user} lu ON fplast.userid = lu.id\n LEFT JOIN {groups} g ON g.id = fd.groupid\n {$readtrackingjoin}\n {$typejoin}\n {$flagsjoin}\n {$tagjoin}\nWHERE\n {$conditions}) x {$order}\n", array_merge($readtrackingparams, $readtrackingjoinparams, $flagparams, $conditionparams), $limitfrom, $limitnum); return $rs; }
/** * Checks forum object created in test_get_forum() * In function so same tests can be carried out on multiple forum setups * @param object $forum * @param object $course * @param object $cm */ private function check_forum_settings(mod_forumng $forum, $course, $cm) { $this->assertEquals('TEST', $forum->get_name()); $this->assertEquals('abc123', $forum->get_intro()); $this->assertEquals('abc123', $forum->get_intro(true)); // Pick up errors in abbreviation. $this->assertEquals(FORMAT_MOODLE, $forum->get_intro_format()); $this->assertEquals($cm->instance, $forum->get_id()); $this->assertEquals($course->id, $forum->get_course_id()); $this->assertEquals($course->id, $forum->get_course()->id); $this->assertEquals($cm->id, $forum->get_course_module_id()); $this->assertEquals(mod_forumng::NO_GROUPS, $forum->get_activity_group($cm)); $context = context_module::instance($cm->id); $this->assertEquals($context->id, $forum->get_context()->id); $this->assertInstanceOf('forumngtype', $forum->get_type()); }