Merge branch 'MDL-50993-master' of git://github.com/ryanwyllie/moodle
authorAndrew Nicols <andrew@nicols.co.uk>
Mon, 19 Oct 2015 04:43:40 +0000 (12:43 +0800)
committerAndrew Nicols <andrew@nicols.co.uk>
Mon, 19 Oct 2015 04:43:40 +0000 (12:43 +0800)
blocks/news_items/block_news_items.php
mod/forum/lib.php
mod/forum/tests/lib_test.php

index 092ae4b..de57a2d 100644 (file)
@@ -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;
index 1d032e1..3eab24b 100644 (file)
@@ -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;
index 6ccdbc2..b57c320 100644 (file)
@@ -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);
+        $this->assertEquals($disc10->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);
+        $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);
+        $this->assertEquals($disc10->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);
+        $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']);
     }