mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 05:58:34 +01:00
MDL-50993 forum: Display timed posts/discussions in a logical order
Users that don't have permission to view timed posts outside of the release time frame will have discussions that have entered the visible frame appear in an odd order from their point of view on the discussion list. Example: Discussion 1, modified 2015-01-01, hidden till 2015-01-03 Discussion 2, modified 2015-01-02, not hidden The standard 'modified descending' order means that D2 is listed at the top even after D1 becomes visible. When scanning the list of discussions for new posts, the user could be tricked into thinking they'd already read it. This fix instead takes into account the release time of the discussion when timed forum posts are enabled. I opted to use CASE statements to handle this instead of GREATEST as the latter is not supported by MSSQL.
This commit is contained in:
parent
1b7bf43562
commit
1e36665719
@ -89,7 +89,12 @@ class block_news_items extends block_base {
|
||||
|
||||
/// Get all the recent discussions we're allowed to see
|
||||
|
||||
if (! $discussions = forum_get_discussions($cm, 'p.modified DESC', false,
|
||||
// This block displays the most recent posts in a forum in
|
||||
// descending order. The call to default sort order here will use
|
||||
// that unless the discussion that post is in has a timestart set
|
||||
// in the future.
|
||||
$sort = forum_get_default_sort_order(true, 'p.modified');
|
||||
if (! $discussions = forum_get_discussions($cm, $sort, false,
|
||||
$currentgroup, $this->page->course->newsitems) ) {
|
||||
$text .= '('.get_string('nonews', 'forum').')';
|
||||
$this->content->text = $text;
|
||||
|
@ -2473,7 +2473,7 @@ function forum_count_discussions($forum, $cm, $course) {
|
||||
* Use FORUM_POSTS_ALL_USER_GROUPS for all the user groups
|
||||
* @return array
|
||||
*/
|
||||
function forum_get_discussions($cm, $forumsort="d.timemodified DESC", $fullpost=true, $unused=-1, $limit=-1,
|
||||
function forum_get_discussions($cm, $forumsort="", $fullpost=true, $unused=-1, $limit=-1,
|
||||
$userlastmodified=false, $page=-1, $perpage=0, $groupid = -1) {
|
||||
global $CFG, $DB, $USER;
|
||||
|
||||
@ -2568,7 +2568,7 @@ function forum_get_discussions($cm, $forumsort="d.timemodified DESC", $fullpost=
|
||||
$groupselect = "";
|
||||
}
|
||||
if (empty($forumsort)) {
|
||||
$forumsort = "d.timemodified DESC";
|
||||
$forumsort = forum_get_default_sort_order();
|
||||
}
|
||||
if (empty($fullpost)) {
|
||||
$postdata = "p.id,p.subject,p.modified,p.discussion,p.userid";
|
||||
@ -2707,11 +2707,37 @@ function forum_get_discussion_neighbours($cm, $discussion, $forum) {
|
||||
$timelimit
|
||||
$groupselect";
|
||||
|
||||
$prevsql = $sql . " AND d.timemodified < :disctimemodified
|
||||
ORDER BY d.timemodified DESC";
|
||||
if (empty($CFG->forum_enabletimedposts)) {
|
||||
$prevsql = $sql . " AND d.timemodified < :disctimemodified";
|
||||
$nextsql = $sql . " AND d.timemodified > :disctimemodified";
|
||||
|
||||
$nextsql = $sql . " AND d.timemodified > :disctimemodified
|
||||
ORDER BY d.timemodified ASC";
|
||||
} else {
|
||||
// Normally we would just use the timemodified for sorting
|
||||
// discussion posts. However, when timed discussions are enabled,
|
||||
// then posts need to be sorted base on the later of timemodified
|
||||
// or the release date of the post (timestart).
|
||||
$params['disctimecompare'] = $discussion->timemodified;
|
||||
if ($discussion->timemodified < $discussion->timestart) {
|
||||
$params['disctimecompare'] = $discussion->timestart;
|
||||
}
|
||||
$params['disctimecompare2'] = $params['disctimecompare'];
|
||||
|
||||
// Here we need to take into account the release time (timestart)
|
||||
// if one is set, of the neighbouring posts and compare it to the
|
||||
// timestart or timemodified of *this* post depending on if the
|
||||
// release date of this post is in the future or not.
|
||||
// This stops discussions that appear later because of the
|
||||
// timestart value from being buried under discussions that were
|
||||
// made afterwards.
|
||||
$prevsql = $sql . " AND CASE WHEN d.timemodified < d.timestart
|
||||
THEN d.timestart < :disctimecompare
|
||||
ELSE d.timemodified < :disctimecompare2 END";
|
||||
$nextsql = $sql . " AND CASE WHEN d.timemodified < d.timestart
|
||||
THEN d.timestart > :disctimecompare
|
||||
ELSE d.timemodified > :disctimecompare2 END";
|
||||
}
|
||||
$prevsql .= ' ORDER BY '.forum_get_default_sort_order();
|
||||
$nextsql .= ' ORDER BY '.forum_get_default_sort_order(false);
|
||||
|
||||
$neighbours['prev'] = $DB->get_record_sql($prevsql, $params, IGNORE_MULTIPLE);
|
||||
$neighbours['next'] = $DB->get_record_sql($nextsql, $params, IGNORE_MULTIPLE);
|
||||
@ -2720,6 +2746,35 @@ function forum_get_discussion_neighbours($cm, $discussion, $forum) {
|
||||
return $neighbours;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sql to use in the ORDER BY clause for forum discussions.
|
||||
*
|
||||
* This has the ordering take timed discussion windows into account.
|
||||
*
|
||||
* @param bool $desc True for DESC, False for ASC.
|
||||
* @param string $compare The field in the SQL to compare to normally sort by.
|
||||
* @param string $prefix The prefix being used for the discussion table.
|
||||
* @return string
|
||||
*/
|
||||
function forum_get_default_sort_order($desc = true, $compare = 'd.timemodified', $prefix = 'd') {
|
||||
global $CFG;
|
||||
|
||||
if (!empty($prefix)) {
|
||||
$prefix .= '.';
|
||||
}
|
||||
|
||||
$dir = $desc ? 'DESC' : 'ASC';
|
||||
|
||||
$sort = "{$prefix}timemodified";
|
||||
if (!empty($CFG->forum_enabletimedposts)) {
|
||||
$sort = "CASE WHEN {$compare} < {$prefix}timestart
|
||||
THEN {$prefix}timestart
|
||||
ELSE {$compare}
|
||||
END";
|
||||
}
|
||||
return "$sort $dir";
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @global object
|
||||
@ -5133,7 +5188,7 @@ function forum_print_latest_discussions($course, $forum, $maxdiscussions = -1, $
|
||||
$context = context_module::instance($cm->id);
|
||||
|
||||
if (empty($sort)) {
|
||||
$sort = "d.timemodified DESC";
|
||||
$sort = forum_get_default_sort_order();
|
||||
}
|
||||
|
||||
$olddiscussionlink = false;
|
||||
|
@ -903,19 +903,30 @@ class mod_forum_lib_testcase extends advanced_testcase {
|
||||
$record->timestart = $past;
|
||||
$record->timeend = $future;
|
||||
$disc12 = $forumgen->create_discussion($record);
|
||||
sleep(1);
|
||||
$record->timestart = $future + 1; // Should be last post for those that can see it.
|
||||
$record->timeend = 0;
|
||||
$disc13 = $forumgen->create_discussion($record);
|
||||
|
||||
// Admin user ignores the timed settings of discussions.
|
||||
// Post ordering taking into account timestart:
|
||||
// 8 = t
|
||||
// 10 = t+3
|
||||
// 11 = t+4
|
||||
// 12 = t+5
|
||||
// 9 = t+60
|
||||
// 13 = t+61.
|
||||
$this->setAdminUser();
|
||||
$neighbours = forum_get_discussion_neighbours($cm, $disc8, $forum);
|
||||
$this->assertEquals($disc7->id, $neighbours['prev']->id);
|
||||
$this->assertEquals($disc9->id, $neighbours['next']->id);
|
||||
|
||||
$neighbours = forum_get_discussion_neighbours($cm, $disc9, $forum);
|
||||
$this->assertEquals($disc8->id, $neighbours['prev']->id);
|
||||
$this->assertEquals($disc10->id, $neighbours['next']->id);
|
||||
|
||||
$neighbours = forum_get_discussion_neighbours($cm, $disc9, $forum);
|
||||
$this->assertEquals($disc12->id, $neighbours['prev']->id);
|
||||
$this->assertEquals($disc13->id, $neighbours['next']->id);
|
||||
|
||||
$neighbours = forum_get_discussion_neighbours($cm, $disc10, $forum);
|
||||
$this->assertEquals($disc9->id, $neighbours['prev']->id);
|
||||
$this->assertEquals($disc8->id, $neighbours['prev']->id);
|
||||
$this->assertEquals($disc11->id, $neighbours['next']->id);
|
||||
|
||||
$neighbours = forum_get_discussion_neighbours($cm, $disc11, $forum);
|
||||
@ -924,20 +935,24 @@ class mod_forum_lib_testcase extends advanced_testcase {
|
||||
|
||||
$neighbours = forum_get_discussion_neighbours($cm, $disc12, $forum);
|
||||
$this->assertEquals($disc11->id, $neighbours['prev']->id);
|
||||
$this->assertEquals($disc9->id, $neighbours['next']->id);
|
||||
|
||||
$neighbours = forum_get_discussion_neighbours($cm, $disc13, $forum);
|
||||
$this->assertEquals($disc9->id, $neighbours['prev']->id);
|
||||
$this->assertEmpty($neighbours['next']);
|
||||
|
||||
// Normal user can see their own timed discussions.
|
||||
$this->setUser($user);
|
||||
$neighbours = forum_get_discussion_neighbours($cm, $disc8, $forum);
|
||||
$this->assertEquals($disc7->id, $neighbours['prev']->id);
|
||||
$this->assertEquals($disc9->id, $neighbours['next']->id);
|
||||
|
||||
$neighbours = forum_get_discussion_neighbours($cm, $disc9, $forum);
|
||||
$this->assertEquals($disc8->id, $neighbours['prev']->id);
|
||||
$this->assertEquals($disc10->id, $neighbours['next']->id);
|
||||
|
||||
$neighbours = forum_get_discussion_neighbours($cm, $disc9, $forum);
|
||||
$this->assertEquals($disc12->id, $neighbours['prev']->id);
|
||||
$this->assertEquals($disc13->id, $neighbours['next']->id);
|
||||
|
||||
$neighbours = forum_get_discussion_neighbours($cm, $disc10, $forum);
|
||||
$this->assertEquals($disc9->id, $neighbours['prev']->id);
|
||||
$this->assertEquals($disc8->id, $neighbours['prev']->id);
|
||||
$this->assertEquals($disc11->id, $neighbours['next']->id);
|
||||
|
||||
$neighbours = forum_get_discussion_neighbours($cm, $disc11, $forum);
|
||||
@ -946,6 +961,10 @@ class mod_forum_lib_testcase extends advanced_testcase {
|
||||
|
||||
$neighbours = forum_get_discussion_neighbours($cm, $disc12, $forum);
|
||||
$this->assertEquals($disc11->id, $neighbours['prev']->id);
|
||||
$this->assertEquals($disc9->id, $neighbours['next']->id);
|
||||
|
||||
$neighbours = forum_get_discussion_neighbours($cm, $disc13, $forum);
|
||||
$this->assertEquals($disc9->id, $neighbours['prev']->id);
|
||||
$this->assertEmpty($neighbours['next']);
|
||||
|
||||
// Normal user does not ignore timed settings.
|
||||
@ -975,11 +994,11 @@ class mod_forum_lib_testcase extends advanced_testcase {
|
||||
$disc3 = $DB->get_record('forum_discussions', array('id' => $disc3->id));
|
||||
|
||||
$neighbours = forum_get_discussion_neighbours($cm, $disc2, $forum);
|
||||
$this->assertEquals($disc12->id, $neighbours['prev']->id);
|
||||
$this->assertEquals($disc13->id, $neighbours['prev']->id);
|
||||
$this->assertEmpty($neighbours['next']);
|
||||
|
||||
$neighbours = forum_get_discussion_neighbours($cm, $disc3, $forum);
|
||||
$this->assertEquals($disc12->id, $neighbours['prev']->id);
|
||||
$this->assertEquals($disc13->id, $neighbours['prev']->id);
|
||||
$this->assertEmpty($neighbours['next']);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user