/** * Retrieves a list of discussions. * @param int $groupid Group ID or ALL_GROUPS * @param bool $viewhidden True if user can view hidden discussions * @param int $page Page to retrieve (1 = first page) * @param int $sort Sort order (SORT_xx constant) * @param bool $sortreverse Reverses the chosen sort * @param int $userid User ID, 0 = default, -1 if unread count not required * @param bool $ignoreinvalidpage true = default * @param int $tagid tag id of tag to get discussions that contain that tag. * @return mod_forumng_discussion_list */ public function get_discussion_list($groupid = self::ALL_GROUPS, $viewhidden = false, $page = 1, $sort = self::SORT_DATE, $sortreverse = false, $userid = 0, $ignoreinvalidpage = true, $tagid = null) { global $CFG, $DB, $USER; $userid = mod_forumng_utils::get_real_userid($userid); // Build list of SQL conditions /*/////////////////////////////*/ // Correct forum. $conditionparams = array(); $conditions = "fd.forumngid = ?"; $conditionparams[] = $this->forumfields->id; // Group restriction if ($groupid) { $conditions .= " AND (fd.groupid = ? OR fd.groupid IS NULL)"; $conditionparams[] = $groupid; } // View hidden posts if (!$viewhidden) { $now = time(); $conditions .= " AND fd.deleted = 0"; $conditions .= " AND (fd.timestart = 0 OR fd.timestart <= ?)" . " AND (fd.timeend = 0 OR fd.timeend > ?)"; $conditionparams[] = $now; $conditionparams[] = $now; } // Tag join sql if needed. $tagjoin = ''; $hastag = false; if (!empty($tagid)) { $hastag = true; $tagjoin = "LEFT JOIN {tag_instance} ti ON ti.itemid = fd.id AND ti.itemtype = 'forumng_discussions'\n AND ti.component = 'mod_forumng'"; $conditions .= "AND ti.tagid = ?"; $conditionparams[] = $tagid; } // Count all discussions /*//////////////////////*/ if ($this->get_type()->has_unread_restriction()) { list($restrictionsql, $restrictionparams) = $this->get_type()->get_unread_restriction_sql($this, $USER->id); } else { $restrictionsql = false; } if ($restrictionsql) { $querypart = $count = $DB->count_records_sql($sql = "\nSELECT\n COUNT(1)\nFROM\n {forumng_discussions} fd\n INNER JOIN {forumng_posts} fpfirst ON fpfirst.id = fd.postid\n INNER JOIN {forumng_posts} fplast ON fplast.id = fd.lastpostid\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\n {$tagjoin}\nWHERE {$conditions} AND m.name = 'forumng' AND {$restrictionsql}", array_merge($conditionparams, $restrictionparams)); } else { $count = $DB->count_records_sql("SELECT COUNT(1) FROM {forumng_discussions} fd {$tagjoin} WHERE " . $conditions, $conditionparams); } // Check page index makes sense $pagecount = ceil($count / $CFG->forumng_discussionsperpage); if ($pagecount < 1) { $pagecount = 1; } if ($page > $pagecount || $page < 1) { if ($ignoreinvalidpage) { $page = 1; } else { throw new coding_exception("Invalid page {$page}, expecting 1..{$pagecount}"); } } // Special case for no results if ($count == 0) { return new mod_forumng_discussion_list($page, $pagecount, $count); } // Retrieve selected discussions /*//////////////////////////////*/ // Ordering $orderby = 'sticky DESC'; switch ($sort) { case self::SORT_DATE: $orderby .= ', timemodified DESC'; break; case self::SORT_SUBJECT: $orderby .= ', subject ASC'; break; case self::SORT_AUTHOR: // This logic is based on code in fullname(). $override = has_capability('moodle/site:viewfullnames', $this->get_context(), $userid); $fullnamedisplay = $CFG->fullnamedisplay; if ($CFG->fullnamedisplay == 'language') { // Controlled by lang pack - try and work out what it is doing. $fakeuser = new stdClass(); $fakeuser->firstname = 'firstname'; $fakeuser->lastname = 'lastname'; $fullnamedisplay = get_string('fullnamedisplay', '', $fakeuser); } if ($fullnamedisplay == 'firstname lastname' || $override && $fullnamedisplay == 'firstname') { $orderby .= ', fu_firstname ASC, fu_lastname ASC'; } else { if ($fullnamedisplay == 'lastname firstname') { $orderby .= ', fu_lastname ASC, fu_firstname ASC'; } else { if ($fullnamedisplay == 'firstname') { $orderby .= ', fu_firstname ASC'; } } } if (!$override) { if (!empty($CFG->forcefirstname)) { $orderby = preg_replace('~, fu_firstname(ASC)?~', '', $orderby); } if (!empty($CFG->forcelastname)) { $orderby = preg_replace('~, fu_lastname(ASC)?~', '', $orderby); } } break; case self::SORT_POSTS: $orderby .= ', numposts DESC'; break; case self::SORT_UNREAD: $orderby .= ', numposts-numreadposts DESC'; break; case self::SORT_GROUP: $orderby .= ', groupname ASC'; break; default: throw new coding_exception("Unknown SORT_xx constant {$sort}"); } // swap ASC/DESC according to $sortreverse if ($sortreverse) { $orderby = str_replace('DESC', 'ASX', $orderby); $orderby = str_replace('ASC', 'DESC', $orderby); $orderby = str_replace('ASX', 'ASC', $orderby); $orderby = str_replace('sticky ASC', 'sticky DESC', $orderby); } // Ensure consistency by adding id ordering $orderby .= ', id DESC'; // Limits $limitfrom = ($page - 1) * $CFG->forumng_discussionsperpage; $limitnum = $CFG->forumng_discussionsperpage; // Do query $rs = mod_forumng_discussion::query_discussions($conditions, $conditionparams, $userid, $orderby, $limitfrom, $limitnum, $this, false, $hastag); $result = new mod_forumng_discussion_list($page, $pagecount, $count); foreach ($rs as $rec) { // Create a new discussion from the database details $discussion = new mod_forumng_discussion($this, $rec, true, mod_forumng_utils::get_real_userid($userid)); // Give the discussion a chance to invalidate discussion // cache. This is so that if the user looks at a discussion // list, and it shows a newer post, then they click into the // discussion, they don't end up not seeing it! $discussion->maybe_invalidate_cache(); // Add to results $result->add_discussion($discussion); } $rs->close(); return $result; }