diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php
index b65afab450..139ec513c4 100644
--- a/classes/privacy/provider.php
+++ b/classes/privacy/provider.php
@@ -143,9 +143,15 @@ public static function get_contexts_for_userid(int $userid) : contextlist {
INNER JOIN {modules} m ON m.id = cm.module AND m.name = :modname
INNER JOIN {moodleoverflow} mof ON mof.id = cm.instance
WHERE EXISTS (
- SELECT 1 FROM {moodleoverflow_discussions} d WHERE d.moodleoverflow = mof.id AND (d.userid = :duserid OR d.usermodified = :dmuserid)
+ SELECT 1
+ FROM {moodleoverflow_discussions} d
+ WHERE d.moodleoverflow = mof.id AND (d.userid = :duserid OR d.usermodified = :dmuserid)
) OR EXISTS (
- SELECT 1 FROM {moodleoverflow_posts} p WHERE p.discussion IN (SELECT id FROM {moodleoverflow_discussions} WHERE moodleoverflow = mof.id) AND p.userid = :puserid
+ SELECT 1
+ FROM {moodleoverflow_posts} p
+ WHERE p.discussion IN (SELECT id
+ FROM {moodleoverflow_discussions}
+ WHERE moodleoverflow = mof.id) AND p.userid = :puserid
) OR EXISTS (
SELECT 1 FROM {moodleoverflow_read} r WHERE r.moodleoverflowid = mof.id AND r.userid = :ruserid
) OR EXISTS (
diff --git a/classes/ratings.php b/classes/ratings.php
index f6092c2418..6db3641bf7 100644
--- a/classes/ratings.php
+++ b/classes/ratings.php
@@ -477,7 +477,7 @@ public static function moodleoverflow_discussion_is_solved($discussionid, $teach
*
* @return int
*/
- private static function moodleoverflow_get_reputation_instance($moodleoverflowid, $userid = null) {
+ public static function moodleoverflow_get_reputation_instance($moodleoverflowid, $userid = null) {
global $DB, $USER;
// Get the user id.
@@ -574,7 +574,7 @@ private static function moodleoverflow_get_reputation_instance($moodleoverflowid
*
* @return int
*/
- private static function moodleoverflow_get_reputation_course($courseid, $userid = null) {
+ public static function moodleoverflow_get_reputation_course($courseid, $userid = null) {
global $USER, $DB;
// Get the userid.
diff --git a/classes/tables/userstats_table.php b/classes/tables/userstats_table.php
index 5d040b1990..1c1e9a24a4 100644
--- a/classes/tables/userstats_table.php
+++ b/classes/tables/userstats_table.php
@@ -15,10 +15,7 @@
// along with Moodle. If not, see .
/**
- * Prints a particular instance of moodleoverflow
- *
- * You can have a rather longer description of the file as well,
- * if you like, and it can span multiple lines.
+ * Class needed in userstats.php
*
* @package mod_moodleoverflow
* @copyright 2023 Tamaro Walter
@@ -28,6 +25,7 @@
defined('MOODLE_INTERNAL') || die();
+use mod_moodleoverflow\ratings;
require_once($CFG->dirroot . '/mod/moodleoverflow/lib.php');
require_once($CFG->libdir . '/tablelib.php');
@@ -71,15 +69,23 @@ public function __construct($uniqueid, $courseid, $moodleoverflow, $url) {
$this->set_attribute('class', 'moodleoverflow-statistics-table');
$this->set_attribute('id', $uniqueid);
- $this->define_columns(['username', 'receivedupvotes', 'receiveddownvotes', 'activity', 'reputation']);
+ $this->define_columns(['username',
+ 'receivedupvotes',
+ 'receiveddownvotes',
+ 'forumactivity',
+ 'courseactivity',
+ 'forumreputation',
+ 'coursereputation']);
$this->define_baseurl($url);
$this->define_headers([get_string('fullnameuser'),
get_string('userstatsupvotes', 'moodleoverflow'),
get_string('userstatsdownvotes', 'moodleoverflow'),
- (get_string('userstatsactivity', 'moodleoverflow') . $this->helpactivity->object),
- get_string('userstatsreputation', 'moodleoverflow')]);
+ (get_string('userstatsforumactivity', 'moodleoverflow') . $this->helpactivity->object),
+ (get_string('userstatscourseactivity', 'moodleoverflow') . $this->helpactivity->object),
+ get_string('userstatsforumreputation', 'moodleoverflow'),
+ get_string('userstatscoursereputation', 'moodleoverflow')]);
$this->get_table_data();
- $this->sortable(true, 'reputation', SORT_DESC);
+ $this->sortable(true, 'coursereputation', SORT_DESC);
$this->no_sorting('username');
$this->setup();
}
@@ -89,11 +95,10 @@ public function __construct($uniqueid, $courseid, $moodleoverflow, $url) {
* @return void
*/
public function out() {
- global $DB;
$this->start_output();
$this->sort_table_data($this->get_sort_order());
$this->format_and_add_array_of_rows($this->userstatsdata, true);
- $this->text_sorting('reputation');
+ $this->text_sorting('coursereputation');
$this->finish_output();
}
@@ -168,7 +173,7 @@ private function quick_usertable_sort($low, $high, $key, $order) {
}
if ($high > $left) {
if ($order == 'asc') {
- $this->quick_usertable_sort($left, $high, $key, 'desc');
+ $this->quick_usertable_sort($left, $high, $key, 'asc');
} else if ($order == 'desc') {
$this->quick_usertable_sort($left, $high, $key, 'desc');
}
@@ -182,64 +187,65 @@ private function quick_usertable_sort($low, $high, $key, $order) {
* @return 2d-array with user statistic
*/
public function get_table_data() {
- global $DB;
// Get all userdata from a course.
$context = \context_course::instance($this->courseid);
- $users = get_enrolled_users($context , '', 0, $userfields = 'u.id, u.firstname, u.lastname');
+ $users = get_enrolled_users($context , '', 0, 'u.id, u.firstname, u.lastname');
- // Step 1.0: Build the datatable with all relevant Informations.
- $sqlquery = 'SELECT (ROW_NUMBER() OVER (ORDER BY ratings.id)) AS row_num,
- ratings.id AS rateid,
- discuss.userid AS discussuserid,
- posts.id AS postid,
- posts.userid AS postuserid,
- ratings.rating AS rating,
- ratings.userid AS rateuserid,
- ratings.postid AS ratepostid,
- discuss.id AS discussid,
- posts.discussion AS postdiscussid,
- ratings.discussionid AS ratediscussid
- FROM {moodleoverflow_discussions} discuss
- LEFT JOIN {moodleoverflow_posts} posts ON discuss.id = posts.discussion
- LEFT JOIN {moodleoverflow_ratings} ratings ON posts.id = ratings.postid
- WHERE discuss.course = ' . $this->courseid . ';';
- $ratingdata = $DB->get_records_sql($sqlquery);
+ $ratingdata = $this->get_rating_data();
// Step 2.0: Now collect the data for every user in the course.
foreach ($users as $user) {
- $student = new \stdClass();
- $student->id = $user->id;
- $student->name = $user->firstname . ' ' . $user->lastname;
- $linktostudent = new \moodle_url('/user/view.php', array('id' => $student->id, 'course' => $this->courseid));
- $student->link = \html_writer::link($linktostudent->out(), $student->name);
- $student->submittedposts = array(); // Key = postid, Value = postid.
- $student->ratedposts = array(); // Key = rateid, Value = rateid.
- $student->receivedupvotes = 0;
- $student->receiveddownvotes = 0;
- $student->activity = 0;
- $student->reputation = 0;
+ $student = $this->createstudent($user);
+
foreach ($ratingdata as $row) {
+ // Is the rating from or for the current student?
if ($row->postuserid !== $student->id && $row->rateuserid !== $student->id) {
continue;
}
- if ($row->postuserid == $student->id && $row->rating == RATING_UPVOTE) {
- $student->receivedupvotes += 1;
- }
- if ($row->postuserid == $student->id && $row->rating == RATING_DOWNVOTE) {
- $student->receiveddownvotes += 1;
+
+ // Did the student receive an up- or downvote?
+ // Only count if the discussion is not anonymous or if the user is not starter of the discussion.
+ if ($row->postuserid == $student->id &&
+ (($row->anonymoussetting == 0) || ($row->anonymoussetting == 1 && $row->postuserid != $row->discussuserid))) {
+ if ($row->rating == RATING_UPVOTE) {
+ $student->receivedupvotes += 1;
+ } else if ($row->rating == RATING_DOWNVOTE) {
+ $student->receiveddownvotes += 1;
+ }
}
- if ($row->rateuserid == $student->id && !array_key_exists($row->rateid, $student->ratedposts)) {
- $student->activity += 1;
+
+ // Did a student submit a rating?
+ // For solution marks: only count a solution if the discussion is not completely anonymous.
+ // For helpful marks: only count helpful marks if the discussion is not any kind of anonymous.
+ // Up and downvotes are always counted.
+ if ($row->rateuserid == $student->id && !array_key_exists($row->rateid, $student->ratedposts) &&
+ (($row->rating == RATING_SOLVED && $row->anonymoussetting != 2) ||
+ ($row->rating == RATING_HELPFUL && $row->anonymoussetting == 0) ||
+ ($row->rating == RATING_UPVOTE) ||
+ ($row->rating == RATING_DOWNVOTE))) {
+
+ if ($row->moodleoverflowid == $this->moodleoverflowid) {
+ $student->forumactivity += 1;
+ }
+ $student->courseactivity += 1;
$student->ratedposts[$row->rateid] = $row->rateid;
}
- if ($row->postuserid == $student->id && !array_key_exists($row->postid, $student->submittedposts)) {
- $student->activity += 1;
+
+ // Did the student write a post? Only count a written post if: the post is not in an anonymous discussion;
+ // or the post is in a partial anonymous discussion and the user is not the starter of the discussion.
+ if ($row->postuserid == $student->id && !array_key_exists($row->postid, $student->submittedposts) &&
+ ($row->anonymoussetting == 0 || ($row->anonymoussetting == 1 && $row->postuserid != $row->discussuserid))) {
+
+ if ($row->moodleoverflowid == $this->moodleoverflowid) {
+ $student->forumactivity += 1;
+ }
+ $student->courseactivity += 1;
$student->submittedposts[$row->postid] = $row->postid;
}
}
// Get the user reputation from the course.
- $student->reputation = \mod_moodleoverflow\ratings::moodleoverflow_get_reputation($this->moodleoverflowid,
- $student->id);
+ $student->forumreputation = ratings::moodleoverflow_get_reputation_instance($this->moodleoverflowid, $student->id);
+ $student->coursereputation = ratings::moodleoverflow_get_reputation_course($this->courseid, $student->id);
array_push($this->userstatsdata, $student);
}
}
@@ -295,13 +301,7 @@ public function col_username($row) {
* @return string
*/
public function col_receivedupvotes($row) {
- if ($row->receivedupvotes > 0) {
- return \html_writer::tag('h5', \html_writer::start_span('badge badge-success') .
- $row->receivedupvotes . \html_writer::end_span());
- } else {
- return \html_writer::tag('h5', \html_writer::start_span('badge badge-warning') .
- $row->receivedupvotes . \html_writer::end_span());
- }
+ return $this->badge_render($row->receivedupvotes);
}
/**
@@ -310,45 +310,59 @@ public function col_receivedupvotes($row) {
* @return string
*/
public function col_receiveddownvotes($row) {
- if ($row->receiveddownvotes > 0) {
- return \html_writer::tag('h5', \html_writer::start_span('badge badge-success') .
- $row->receiveddownvotes . \html_writer::end_span());
- } else {
- return \html_writer::tag('h5', \html_writer::start_span('badge badge-warning') .
- $row->receiveddownvotes . \html_writer::end_span());
- }
+ return $this->badge_render($row->receiveddownvotes);
}
/**
- * activity column
+ * Forum activity column
* @param object $row
* @return string
*/
- public function col_activity($row) {
- if ($row->activity > 0) {
- return \html_writer::tag('h5', \html_writer::start_span('badge badge-success') .
- $row->activity . \html_writer::end_span());
- } else {
- return \html_writer::tag('h5', \html_writer::start_span('badge badge-warning') .
- $row->activity . \html_writer::end_span());
- }
+ public function col_forumactivity($row) {
+ return $this->badge_render($row->forumactivity);
}
/**
- * reputation column
+ * Forum reputation column
* @param object $row
* @return string
*/
- public function col_reputation($row) {
- if ($row->reputation > 0) {
+ public function col_forumreputation($row) {
+ return $this->badge_render($row->forumreputation);
+ }
+
+ /**
+ * Course activity column
+ * @param object $row
+ * @return string
+ */
+ public function col_courseactivity($row) {
+ return $this->badge_render($row->courseactivity);
+ }
+
+ /**
+ * Course reputation column
+ * @param object $row
+ * @return string
+ */
+ public function col_coursereputation($row) {
+ return $this->badge_render($row->coursereputation);
+ }
+
+ /**
+ * Dependeng on the value display success or warning badge.
+ * @param int $number
+ * @return string
+ */
+ private function badge_render($number) {
+ if ($number > 0) {
return \html_writer::tag('h5', \html_writer::start_span('badge badge-success') .
- $row->reputation . \html_writer::end_span());
+ $number . \html_writer::end_span());
} else {
return \html_writer::tag('h5', \html_writer::start_span('badge badge-warning') .
- $row->reputation . \html_writer::end_span());
+ $number . \html_writer::end_span());
}
}
-
/**
* error handling
* @param object $colname
@@ -358,4 +372,52 @@ public function col_reputation($row) {
public function other_cols($colname, $attempt) {
return null;
}
+ /**
+ * Return a student object.
+ * @param \stdClass $user
+ * @return object
+ */
+ private function createstudent($user) {
+ $student = new \stdClass();
+ $student->id = $user->id;
+ $student->name = $user->firstname . ' ' . $user->lastname;
+ $linktostudent = new \moodle_url('/user/view.php', array('id' => $student->id, 'course' => $this->courseid));
+ $student->link = \html_writer::link($linktostudent->out(), $student->name);
+ $student->submittedposts = array(); // Posts written by the student. Key = postid, Value = postid.
+ $student->ratedposts = array(); // Posts that the student rated. Key = rateid, Value = rateid.
+ $student->receivedupvotes = 0;
+ $student->receiveddownvotes = 0;
+ $student->forumactivity = 0; // Number of written posts and submitted ratings in the current moodleoverflow.
+ $student->courseactivity = 0; // Number of written posts and submitted ratings in the course.
+ $student->forumreputation = 0; // Reputation in the current moodleoverflow.
+ $student->coursereputation = 0; // Reputation in the course.
+ return $student;
+ }
+
+ /**
+ * All ratings upvotes downbotes activity etc. from the current course.
+ * @return array
+ * @throws \dml_exception
+ */
+ private function get_rating_data() {
+ global $DB;
+ // Step 1.0: Build the datatable with all relevant Informations.
+ $sqlquery = 'SELECT (ROW_NUMBER() OVER (ORDER BY ratings.id)) AS row_num,
+ discuss.id AS discussid,
+ discuss.userid AS discussuserid,
+ posts.id AS postid,
+ posts.userid AS postuserid,
+ ratings.id AS rateid,
+ ratings.rating AS rating,
+ ratings.userid AS rateuserid,
+ ratings.postid AS ratepostid,
+ moodleoverflow.anonymous AS anonymoussetting,
+ moodleoverflow.id AS moodleoverflowid
+ FROM {moodleoverflow_discussions} discuss
+ LEFT JOIN {moodleoverflow_posts} posts ON discuss.id = posts.discussion
+ LEFT JOIN {moodleoverflow_ratings} ratings ON posts.id = ratings.postid
+ LEFT JOIN {moodleoverflow} moodleoverflow ON discuss.moodleoverflow = moodleoverflow.id
+ WHERE discuss.course = ' . $this->courseid . ';';
+ return $DB->get_records_sql($sqlquery);
+ }
}
diff --git a/lang/en/moodleoverflow.php b/lang/en/moodleoverflow.php
index 23955a1580..2f50386242 100644
--- a/lang/en/moodleoverflow.php
+++ b/lang/en/moodleoverflow.php
@@ -205,8 +205,10 @@
// Strings for the userstats feature.
$string['userstatsupvotes'] = 'Received upvotes';
$string['userstatsdownvotes'] = 'Received downvotes';
-$string['userstatsactivity'] = 'Amount of activity';
-$string['userstatsreputation'] = 'User reputation';
+$string['userstatsforumactivity'] = 'Activity (this forum)';
+$string['userstatsforumreputation'] = 'Reputation (this forum)';
+$string['userstatscourseactivity'] = 'Activity (coursewide)';
+$string['userstatscoursereputation'] = 'Reputation (coursewide)';
$string['helpamountofactivity'] = 'Each activity like writing a post, starting a discussion or giving a rating gives 1 point';
$string['showuserstats'] = 'Show cumulative user statistics';
$string['configshowuserstats'] = 'Allow teachers in courses to see statistics summarizing the activity of users in Moodleoverflows.';
diff --git a/styles.css b/styles.css
index f0c92ff5bf..d6f90bdb9f 100644
--- a/styles.css
+++ b/styles.css
@@ -529,7 +529,7 @@
}
-.moodleoverflow-statistics-table .header.c3 .helpactivityclass {
+.moodleoverflow-statistics-table .header .helpactivityclass {
padding: 0;
margin-left: 8px;
}
diff --git a/tests/privacy_provider_test.php b/tests/privacy_provider_test.php
index ca7e98f1ca..c4d10fc712 100644
--- a/tests/privacy_provider_test.php
+++ b/tests/privacy_provider_test.php
@@ -39,6 +39,7 @@
* @group mod_moodleoverflow
* @group mod_moodleoverflow_privacy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @covers \provider
*/
class privacy_provider_test extends \core_privacy\tests\provider_testcase {
/**
diff --git a/tests/readtracking_test.php b/tests/readtracking_test.php
index 7f50a39f9e..bb74a59553 100644
--- a/tests/readtracking_test.php
+++ b/tests/readtracking_test.php
@@ -36,6 +36,7 @@
* @package mod_moodleoverflow
* @copyright 2017 Kennet Winter
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @covers \readtracking
*/
class readtracking_test extends advanced_testcase {
diff --git a/tests/subscriptions_test.php b/tests/subscriptions_test.php
index f6693e944b..110a4f5a63 100644
--- a/tests/subscriptions_test.php
+++ b/tests/subscriptions_test.php
@@ -36,6 +36,7 @@
* @package mod_moodleoverflow
* @copyright 2017 Kennet Winter
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @covers \subscriptions
*/
class subscriptions_test extends advanced_testcase {
diff --git a/tests/userstats_test.php b/tests/userstats_test.php
index 9b26db5e56..044dd1f8b7 100644
--- a/tests/userstats_test.php
+++ b/tests/userstats_test.php
@@ -36,6 +36,8 @@
* @package mod_moodleoverflow
* @copyright 2023 Tamaro Walter
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ *
+ * @covers \userstats_table
*/
class userstats_test extends \advanced_testcase {
@@ -107,11 +109,7 @@ public function test_upvote() {
// Create the user statistics table for this course and save it in $data.
$data = $this->create_statstable();
- foreach ($data as $student) {
- if ($student->id == $this->user2->id) {
- $upvotes = $student->receivedupvotes;
- }
- }
+ $upvotes = $this->get_specific_userstats($data, $this->user2, 'receivedupvotes');
$this->assertEquals(1, $upvotes);
}
@@ -125,11 +123,7 @@ public function test_downvote() {
// Create the user statistics table for this course and save it in $data.
$data = $this->create_statstable();
- foreach ($data as $student) {
- if ($student->id == $this->user1->id) {
- $downvotes = $student->receiveddownvotes;
- }
- }
+ $downvotes = $this->get_specific_userstats($data, $this->user1, 'receiveddownvotes');
$this->assertEquals(1, $downvotes);
}
@@ -146,11 +140,7 @@ public function test_activity() {
// Activity = 5.
// Create the user statistics table for this course and save it in $data.
$data = $this->create_statstable();
- foreach ($data as $student) {
- if ($student->id == $this->user1->id) {
- $activity = $student->activity;
- }
- }
+ $activity = $this->get_specific_userstats($data, $this->user1, 'forumactivity');
$this->assertEquals(5, $activity);
}
@@ -165,18 +155,115 @@ public function test_reputation() {
$this->create_downvote($this->user1, $this->discussion2[1], $this->post2);
$this->create_solution($this->teacher, $this->discussion1[1], $this->answer1);
- // Calculate the reputation of user2.
- $reputation = \mod_moodleoverflow\ratings::moodleoverflow_get_reputation($this->moodleoverflow->id, $this->user2->id);
+ // Calculate the forum reputation of user2.
+ $reputation = \mod_moodleoverflow\ratings::moodleoverflow_get_reputation_instance($this->moodleoverflow->id,
+ $this->user2->id);
// Create the user statistics table for this course and save it in $data.
$data = $this->create_statstable();
- foreach ($data as $student) {
- if ($student->id == $this->user2->id) {
- $reputation2 = $student->reputation;
- }
- }
+ $reputation2 = $this->get_specific_userstats($data, $this->user2, 'forumreputation');
$this->assertEquals($reputation, $reputation2);
}
+ /**
+ * Test, if userstats are calculated correctly if the moodleoverflow is partially anonymous.
+ * @covers \userstats_table
+ */
+ public function test_partial_anonymous() {
+ global $DB;
+ // Test case: Only topic startes are anonymous.
+ $this->make_anonymous(1);
+
+ // Get the current userstats to compare later.
+ $olduserstats = $this->create_statstable();
+ $oldupvotesuser1 = $this->get_specific_userstats($olduserstats, $this->user1, 'receivedupvotes');
+ $oldactivityuser1 = $this->get_specific_userstats($olduserstats, $this->user1, 'forumactivity');
+
+ $oldupvotesuser2 = $this->get_specific_userstats($olduserstats, $this->user2, 'receivedupvotes');
+ $oldactivityuser2 = $this->get_specific_userstats($olduserstats, $this->user2, 'forumactivity');
+
+ // User1 starts a new discussion, the forum activity shouldn't change.
+ $discussion = $this->generator->post_to_forum($this->moodleoverflow, $this->user1);
+ $starterpost = $DB->get_record('moodleoverflow_posts', array('id' => $discussion[0]->firstpost), '*');
+ $newuserstats = $this->create_statstable();
+ $newactivityuser1 = $this->get_specific_userstats($newuserstats, $this->user1, 'forumactivity');
+ $this->assertEquals($oldactivityuser1, $newactivityuser1);
+
+ // User2 now gives an answer to user1, his activity should change.
+ $answeruser2 = $this->generator->reply_to_post($discussion[1], $this->user2, true);
+ $newuserstats = $this->create_statstable();
+ $newactivityuser2 = $this->get_specific_userstats($newuserstats, $this->user2, 'forumactivity');
+ $this->assertEquals($oldactivityuser2 + 1, $newactivityuser2);
+ $oldactivityuser2 = $newactivityuser2; // Update it for further comparisons.
+
+ // User1 rates the answer from user2 as helpful an gives it an upvote.
+ // The activity of user1 should only change when he gives an upvote.
+ // The received upvotes from user2 should change.
+ $this->create_helpful($this->user1, $discussion[1], $answeruser2);
+ $newuserstats = $this->create_statstable();
+ $newactivityuser1 = $this->get_specific_userstats($newuserstats, $this->user1, 'forumactivity');
+ $this->assertEquals($oldactivityuser1, $newactivityuser1);
+
+ $this->create_upvote($this->user1, $discussion[1], $answeruser2);
+ $newuserstats = $this->create_statstable();
+ $newactivityuser1 = $this->get_specific_userstats($newuserstats, $this->user1, 'forumactivity');
+ $newupvotesuser2 = $this->get_specific_userstats($newuserstats, $this->user2, 'receivedupvotes');
+ $this->assertEquals($oldactivityuser1 + 1, $newactivityuser1);
+ $this->assertEquals($oldupvotesuser2 + 1, $newupvotesuser2);
+
+ // User2 gives the discussion starter post an upvote.
+ // Activity of User2 should change, the receivedupvotes from user1 shouln't change.
+ $this->create_upvote($this->user2, $discussion[1], $starterpost);
+ $newuserstats = $this->create_statstable();
+ $newactivityuser2 = $this->get_specific_userstats($newuserstats, $this->user2, 'forumactivity');
+ $newupvotesuser1 = $this->get_specific_userstats($newuserstats, $this->user1, 'receivedupvotes');
+ $this->assertEquals($oldactivityuser2 + 1, $newactivityuser2);
+ $this->assertEquals($oldupvotesuser1, $newupvotesuser1);
+ }
+
+ /**
+ * Test, if userstats are calculated correctly if the moodleoverflow is partially anonymous.
+ * @covers \userstats_table
+ */
+ public function test_total_anonymous() {
+ // Test case: Only topic startes are anonymous.
+ $this->make_anonymous(2);
+
+ // Get the current userstats to compare later.
+ $olduserstats = $this->create_statstable();
+ $oldupvotesuser1 = $this->get_specific_userstats($olduserstats, $this->user1, 'receivedupvotes');
+ $oldactivityuser1 = $this->get_specific_userstats($olduserstats, $this->user1, 'forumactivity');
+
+ $oldupvotesuser2 = $this->get_specific_userstats($olduserstats, $this->user2, 'receivedupvotes');
+ $oldactivityuser2 = $this->get_specific_userstats($olduserstats, $this->user2, 'forumactivity');
+
+ // User1 starts a new discussion, the forum activity shouldn't change.
+ $discussion = $this->generator->post_to_forum($this->moodleoverflow, $this->user1);
+ $newuserstats = $this->create_statstable();
+ $newactivityuser1 = $this->get_specific_userstats($newuserstats, $this->user1, 'forumactivity');
+ $this->assertEquals($oldactivityuser1, $newactivityuser1);
+
+ // User2 now gives an answer to user1, his activity shouldn't change.
+ $answeruser2 = $this->generator->reply_to_post($discussion[1], $this->user2, true);
+ $newuserstats = $this->create_statstable();
+ $newactivityuser2 = $this->get_specific_userstats($newuserstats, $this->user2, 'forumactivity');
+ $this->assertEquals($oldactivityuser2, $newactivityuser2);
+
+ // User1 rates the answer from user2 as helpful an gives it an upvote.
+ // The activity of user1 should only change when he gives an upvote.
+ // User2 received upvotes should not change.
+ $this->create_helpful($this->user1, $discussion[1], $answeruser2);
+ $newuserstats = $this->create_statstable();
+ $newactivityuser1 = $this->get_specific_userstats($newuserstats, $this->user1, 'forumactivity');
+ $this->assertEquals($oldactivityuser1, $newactivityuser1);
+
+ $this->create_upvote($this->user1, $discussion[1], $answeruser2);
+ $newuserstats = $this->create_statstable();
+ $newactivityuser1 = $this->get_specific_userstats($newuserstats, $this->user1, 'forumactivity');
+ $newupvotesuser2 = $this->get_specific_userstats($newuserstats, $this->user2, 'receivedupvotes');
+ $this->assertEquals($oldactivityuser1 + 1, $newactivityuser1);
+ $this->assertEquals($oldupvotesuser2, $newupvotesuser2);
+ }
+
// Helper functions.
/**
@@ -212,6 +299,23 @@ private function helper_course_set_up() {
$this->answer2 = $this->generator->reply_to_post($this->discussion2[1], $this->user1, true);
}
+ /**
+ * Makes the existing moodleoverflow anonymous.
+ * There are 2 types of anonymous moodleoverflows:
+ * anonymous = 1, the topic starter is anonymous
+ * anonymous = 2, all users are anonym
+ *
+ * @param int $anonymoussetting
+ */
+ private function make_anonymous($anonymoussetting) {
+ global $DB;
+ if ($anonymoussetting == 1 || $anonymoussetting == 2) {
+ $this->moodleoverflow->anonymous = $anonymoussetting;
+ $DB->update_record('moodleoverflow', $this->moodleoverflow);
+ } else {
+ throw new \Exception('invalid parameter, anonymoussetting should be 1 or 2');
+ }
+ }
/**
* Create a usertable and return it.
@@ -284,7 +388,7 @@ private function create_helpful($author, $discussion, $post) {
'discussionid' => $discussion->id,
'userid' => $author->id,
'postid' => $post->id,
- 'rating' => 3,
+ 'rating' => 4,
'firstrated' => time(),
'lastchanged' => time()
];
@@ -306,10 +410,42 @@ private function create_solution($author, $discussion, $post) {
'discussionid' => $discussion->id,
'userid' => $author->id,
'postid' => $post->id,
- 'rating' => 4,
+ 'rating' => 3,
'firstrated' => time(),
'lastchanged' => time()
];
return $this->generator->create_rating($record);
}
+
+ /**
+ * Return a specific value from the userstatstable.
+ *
+ * @param array $statstable
+ * @param object $user
+ * @param string $stats // A key that specifies which value should be returned.
+ */
+ private function get_specific_userstats($statstable, $user, $stats) {
+ foreach ($statstable as $student) {
+ if ($student->id == $user->id) {
+ switch ($stats) {
+ case 'receivedupvotes':
+ $result = $student->receivedupvotes;
+ break;
+ case 'receiveddownvotes':
+ $result = $student->receiveddownvotes;
+ break;
+ case 'forumactivity':
+ $result = $student->forumactivity;
+ break;
+ case 'forumreputation':
+ $result = $student->forumreputation;
+ break;
+ default:
+ throw new \Exception('parameter unknown');
+ break;
+ }
+ }
+ }
+ return $result;
+ }
}