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; + } }