From 045c3ec3ee2f18e164b6a4dd8f825e6581b8f6e5 Mon Sep 17 00:00:00 2001 From: Ilya Tregubov Date: Wed, 20 Jan 2021 14:18:09 +0200 Subject: [PATCH] MDL-68394 h5pactivity: Implement methods to display recent activity info. --- mod/h5pactivity/lang/en/h5pactivity.php | 2 + mod/h5pactivity/lib.php | 282 +++++++++++++++++- .../templates/reviewattempts.mustache | 58 ++++ .../tests/behat/recent_activity.feature | 79 +++++ mod/h5pactivity/tests/lib_test.php | 242 +++++++++++++++ 5 files changed, 662 insertions(+), 1 deletion(-) create mode 100644 mod/h5pactivity/templates/reviewattempts.mustache create mode 100644 mod/h5pactivity/tests/behat/recent_activity.feature create mode 100644 mod/h5pactivity/tests/lib_test.php diff --git a/mod/h5pactivity/lang/en/h5pactivity.php b/mod/h5pactivity/lang/en/h5pactivity.php index 822b338ee96..376b59be509 100644 --- a/mod/h5pactivity/lang/en/h5pactivity.php +++ b/mod/h5pactivity/lang/en/h5pactivity.php @@ -77,6 +77,7 @@ $string['grade_highest_attempt'] = 'Highest grade'; $string['grade_average_attempt'] = 'Average grade'; $string['grade_last_attempt'] = 'Last attempt'; $string['grade_first_attempt'] = 'First attempt'; +$string['grade_h5p'] = 'Grade: {$a}'; $string['h5pactivity:addinstance'] = 'Add a new H5P'; $string['h5pactivity:reviewattempts'] = 'Review H5P attempts'; $string['h5pactivity:submit'] = 'Submit H5P attempts'; @@ -94,6 +95,7 @@ Any question attempts are marked automatically, and the grade is recorded in the $string['modulename_link'] = 'mod/h5pactivity/view'; $string['modulenameplural'] = 'H5P'; $string['myattempts'] = 'My attempts'; +$string['newsubmissions'] = 'H5P submitted'; $string['no_compatible_track'] = 'This interaction ({$a}) does not provide tracking information or the tracking provided is not compatible with the current activity version.'; $string['noparticipants'] = 'No participants to display'; diff --git a/mod/h5pactivity/lib.php b/mod/h5pactivity/lib.php index 4d8acbf8206..d1226003dcc 100644 --- a/mod/h5pactivity/lib.php +++ b/mod/h5pactivity/lib.php @@ -261,7 +261,7 @@ function h5pactivity_reset_course_form_defaults(stdClass $course): array { * @return array of reseting status */ function h5pactivity_reset_userdata(stdClass $data): array { - global $CFG, $DB; + global $DB; $componentstr = get_string('modulenameplural', 'mod_h5pactivity'); $status = []; if (!empty($data->reset_h5pactivity)) { @@ -541,3 +541,283 @@ function h5pactivity_dndupload_handle($uploadinfo): int { return h5pactivity_add_instance($h5p, null); } + +/** + * Print recent activity from all h5pactivities in a given course + * + * This is used by the recent activity block + * @param mixed $course the course to print activity for + * @param bool $viewfullnames boolean to determine whether to show full names or not + * @param int $timestart the time the rendering started + * @return bool true if activity was printed, false otherwise. + */ +function h5pactivity_print_recent_activity($course, bool $viewfullnames, int $timestart): bool { + global $CFG, $DB, $OUTPUT, $USER; + + $dbparams = [$timestart, $course->id, 'h5pactivity']; + + $userfieldsapi = \core_user\fields::for_userpic(); + $namefields = $userfieldsapi->get_sql('u', false, '', 'userid', false)->selects;; + + $sql = "SELECT h5pa.id, h5pa.timemodified, cm.id as cmid, $namefields + FROM {h5pactivity_attempts} h5pa + JOIN {h5pactivity} h5p ON h5p.id = h5pa.h5pactivityid + JOIN {course_modules} cm ON cm.instance = h5p.id + JOIN {modules} md ON md.id = cm.module + JOIN {user} u ON u.id = h5pa.userid + WHERE h5pa.timemodified > ? + AND h5p.course = ? + AND md.name = ? + ORDER BY h5pa.timemodified ASC"; + + if (!$submissions = $DB->get_records_sql($sql, $dbparams)) { + return false; + } + + $modinfo = get_fast_modinfo($course); + + $recentactivity = h5pactivity_fetch_recent_activity($submissions, $course->id); + + if (empty($recentactivity)) { + return false; + } + + $cms = $modinfo->get_cms(); + + echo $OUTPUT->heading(get_string('newsubmissions', 'h5pactivity') . ':', 6); + + foreach ($recentactivity as $submission) { + $cm = $cms[$submission->cmid]; + $link = $CFG->wwwroot.'/mod/h5pactivity/view.php?id='.$cm->id; + print_recent_activity_note($submission->timemodified, + $submission, + $cm->name, + $link, + false, + $viewfullnames); + } + + return true; +} + +/** + * Returns all h5pactivities since a given time. + * + * @param array $activities The activity information is returned in this array + * @param int $index The current index in the activities array + * @param int $timestart The earliest activity to show + * @param int $courseid Limit the search to this course + * @param int $cmid The course module id + * @param int $userid Optional user id + * @param int $groupid Optional group id + * @return void + */ +function h5pactivity_get_recent_mod_activity(array &$activities, int &$index, int $timestart, int $courseid, + int $cmid, int $userid=0, int $groupid=0) { + global $CFG, $DB, $USER; + + $course = get_course($courseid); + $modinfo = get_fast_modinfo($course); + + $cm = $modinfo->get_cm($cmid); + $params = []; + if ($userid) { + $userselect = 'AND u.id = :userid'; + $params['userid'] = $userid; + } else { + $userselect = ''; + } + + if ($groupid) { + $groupselect = 'AND gm.groupid = :groupid'; + $groupjoin = 'JOIN {groups_members} gm ON gm.userid=u.id'; + $params['groupid'] = $groupid; + } else { + $groupselect = ''; + $groupjoin = ''; + } + + $params['cminstance'] = $cm->instance; + $params['timestart'] = $timestart; + + $userfieldsapi = \core_user\fields::for_userpic(); + $userfields = $userfieldsapi->get_sql('u', false, '', 'userid', false)->selects; + + $sql = "SELECT h5pa.id, h5pa.timemodified, cm.id as cmid, $userfields + FROM {h5pactivity_attempts} h5pa + JOIN {h5pactivity} h5p ON h5p.id = h5pa.h5pactivityid + JOIN {course_modules} cm ON cm.instance = h5p.id + JOIN {modules} md ON md.id = cm.module + JOIN {user} u ON u.id = h5pa.userid $groupjoin + WHERE h5pa.timemodified > :timestart + AND h5p.id = :cminstance $userselect $groupselect + ORDER BY h5pa.timemodified ASC"; + + if (!$submissions = $DB->get_records_sql($sql, $params)) { + return; + } + + $cmcontext = context_module::instance($cm->id); + $grader = has_capability('mod/h5pactivity:reviewattempts', $cmcontext); + $viewfullnames = has_capability('moodle/site:viewfullnames', $cmcontext); + + $recentactivity = h5pactivity_fetch_recent_activity($submissions, $courseid); + + if (empty($recentactivity)) { + return; + } + + if ($grader) { + require_once($CFG->libdir.'/gradelib.php'); + $userids = []; + foreach ($recentactivity as $id => $submission) { + $userids[] = $submission->userid; + } + $grades = grade_get_grades($courseid, 'mod', 'h5pactivity', $cm->instance, $userids); + } + + $aname = format_string($cm->name, true); + foreach ($recentactivity as $submission) { + $activity = new stdClass(); + + $activity->type = 'h5pactivity'; + $activity->cmid = $cm->id; + $activity->name = $aname; + $activity->sectionnum = $cm->sectionnum; + $activity->timestamp = $submission->timemodified; + $activity->user = new stdClass(); + if ($grader) { + $activity->grade = $grades->items[0]->grades[$submission->userid]->str_long_grade; + } + + $userfields = explode(',', implode(',', \core_user\fields::get_picture_fields())); + foreach ($userfields as $userfield) { + if ($userfield == 'id') { + // Aliased in SQL above. + $activity->user->{$userfield} = $submission->userid; + } else { + $activity->user->{$userfield} = $submission->{$userfield}; + } + } + $activity->user->fullname = fullname($submission, $viewfullnames); + + $activities[$index++] = $activity; + } + + return; +} + +/** + * Print recent activity from all h5pactivities in a given course + * + * This is used by course/recent.php + * @param stdClass $activity + * @param int $courseid + * @param bool $detail + * @param array $modnames + */ +function h5pactivity_print_recent_mod_activity(stdClass $activity, int $courseid, bool $detail, array $modnames) { + global $OUTPUT; + + $modinfo = []; + if ($detail) { + $modinfo['modname'] = $activity->name; + $modinfo['modurl'] = new moodle_url('/mod/h5pactivity/view.php', ['id' => $activity->cmid]); + $modinfo['modicon'] = $OUTPUT->image_icon('icon', $modnames[$activity->type], 'h5pactivity'); + } + + $userpicture = $OUTPUT->user_picture($activity->user); + + $template = ['userpicture' => $userpicture, + 'submissiontimestamp' => $activity->timestamp, + 'modinfo' => $modinfo, + 'userurl' => new moodle_url('/user/view.php', array('id' => $activity->user->id, 'course' => $courseid)), + 'fullname' => $activity->user->fullname]; + if (isset($activity->grade)) { + $template['grade'] = get_string('grade_h5p', 'h5pactivity', $activity->grade); + } + + echo $OUTPUT->render_from_template('mod_h5pactivity/reviewattempts', $template); +} + +/** + * Fetches recent activity for course module. + * + * @param array $submissions The activity submissions + * @param int $courseid Limit the search to this course + * @return array $recentactivity recent activity in a course. + */ +function h5pactivity_fetch_recent_activity(array $submissions, int $courseid) : array { + global $USER; + + $course = get_course($courseid); + $modinfo = get_fast_modinfo($course); + + $recentactivity = []; + $grader = []; + + $cms = $modinfo->get_cms(); + + foreach ($submissions as $submission) { + if (!array_key_exists($submission->cmid, $cms)) { + continue; + } + $cm = $cms[$submission->cmid]; + if (!$cm->uservisible) { + continue; + } + + if ($USER->id == $submission->userid) { + $recentactivity[$submission->userid] = $submission; + continue; + } + + $cmcontext = context_module::instance($cm->id); + // The act of submitting of attempt may be considered private - + // only graders will see it if specified. + if (!array_key_exists($cm->id, $grader)) { + $grader[$cm->id] = has_capability('mod/h5pactivity:reviewattempts', $cmcontext); + } + if (!$grader[$cm->id]) { + continue; + } + + $groups = []; + $usersgroups = []; + + $groupmode = groups_get_activity_groupmode($cm, $course); + $accessallgroups = has_capability('moodle/site:accessallgroups', $cmcontext); + + if ($groupmode == SEPARATEGROUPS && !$accessallgroups) { + + if (isguestuser()) { + // Shortcut - guest user does not belong into any group. + continue; + } + + if (!isset($groups[$cm->groupingid])) { + $groups[$cm->groupingid] = $modinfo->get_groups($cm->groupingid); + if (!$groups[$cm->groupingid]) { + continue; + } + } + + if (!isset($usersgroups[$cm->groupingid][$submission->userid])) { + $usersgroups[$cm->groupingid][$submission->userid] = + groups_get_all_groups($course->id, $submission->userid, $cm->groupingid); + } + + if (is_array($usersgroups[$cm->groupingid][$submission->userid])) { + $usersgroupstmp = array_keys($usersgroups[$cm->groupingid][$submission->userid]); + $intersect = array_intersect($usersgroupstmp, $groups[$cm->groupingid]); + if (empty($intersect)) { + continue; + } + } + } + + $recentactivity[$submission->userid] = $submission; + } + + return $recentactivity; +} diff --git a/mod/h5pactivity/templates/reviewattempts.mustache b/mod/h5pactivity/templates/reviewattempts.mustache new file mode 100644 index 00000000000..c0cfa5c99e5 --- /dev/null +++ b/mod/h5pactivity/templates/reviewattempts.mustache @@ -0,0 +1,58 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template mod_h5pactivity/reviewattempts + + This template will render the H5P activity inside a recent activity report. + + Variables requirer for this template: + * userpicture - User fullname and picture + * grade - User grade + * userdate - Submission date + + Example context (json): + { + "userpicture": " ", + "grade": "30.77 / 100.00", + "userdate": "Wednesday, 27 January 2021, 9:54 AM", + "userurl": "http://localhost/m/stable_master/user/view.php?id=3&course=6", + "fullname": "Lukáš Svoboda" + } + +}} + + + + + + + +
{{{userpicture}}} +
+ {{#modinfo}} + {{modicon}}{{modname}} + {{/modinfo}} +
+ {{#grade}} +
+ {{grade}} +
+ {{/grade}} +
+ {{fullname}} - {{#userdate}} {{submissiontimestamp}}, {{#str}} strftimedatetime {{/str}} {{/userdate}} +
+
diff --git a/mod/h5pactivity/tests/behat/recent_activity.feature b/mod/h5pactivity/tests/behat/recent_activity.feature new file mode 100644 index 00000000000..05b44268375 --- /dev/null +++ b/mod/h5pactivity/tests/behat/recent_activity.feature @@ -0,0 +1,79 @@ +@mod @mod_h5pactivity @core_h5p @_file_upload @_switch_iframe +Feature: Users can see the H5P recent activity from the recent activity block + In order to quickly see the updates from H5P activity in my course + As a user + I need to be able to see the recent activity in the recent activity block + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | + | teacher1 | Teacher | 1 | teacher1@example.com | + | student1 | Student | 1 | student1@example.com | + | student2 | Student | 2 | student2@example.com | + And the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + And the following "course enrolments" exist: + | user | course | role | + | teacher1 | C1 | editingteacher | + | student1 | C1 | student | + | student2 | C1 | student | + And the following "permission overrides" exist: + | capability | permission | role | contextlevel | reference | + | moodle/h5p:updatelibraries | Allow | editingteacher | System | | + And I log in as "teacher1" + And I am on "Course 1" course homepage with editing mode on + And I add a "H5P" to section "1" + And I set the following fields to these values: + | Name | Awesome H5P package | + | Description | Description | + And I upload "h5p/tests/fixtures/multiple-choice-2-6.h5p" file to "Package file" filemanager + And I click on "Save and return to course" "button" + And I add the "Recent activity" block + And I log out + And I log in as "student1" + And I am on "Course 1" course homepage + And I follow "Awesome H5P package" + And I switch to "h5p-player" class iframe + And I switch to "h5p-iframe" class iframe + And I click on "Wrong one" "text" in the ".h5p-question-content" "css_element" + And I click on "Check" "button" in the ".h5p-question-buttons" "css_element" + And I switch to the main frame + And I log out + And I log in as "student2" + And I am on "Course 1" course homepage + And I follow "Awesome H5P package" + And I switch to "h5p-player" class iframe + And I switch to "h5p-iframe" class iframe + And I click on "Correct one" "text" in the ".h5p-question-content" "css_element" + And I click on "Check" "button" in the ".h5p-question-buttons" "css_element" + And I switch to the main frame + And I log out + + @javascript + Scenario: Student see only his own activity + Given I log in as "student1" + And I am on "Course 1" course homepage + And I should see "H5P submitted:" in the "Recent activity" "block" + And I should see "Student 1" in the "Recent activity" "block" + And I should not see "Grade:" in the "Recent activity" "block" + And I should not see "Student 2" in the "Recent activity" "block" + When I click on "Full report of recent activity" "link" + Then I should see "H5P Awesome H5P package" + And I should see "Student 1 - " + And I should not see "Grade:" + And I should not see "Student 2 - " + + @javascript + Scenario: Teacher see each student activity + Given I log in as "teacher1" + And I am on "Course 1" course homepage + And I should see "H5P submitted:" in the "Recent activity" "block" + And I should see "Student 1" in the "Recent activity" "block" + And I should not see "Grade:" in the "Recent activity" "block" + And I should see "Student 2" in the "Recent activity" "block" + When I click on "Full report of recent activity" "link" + Then I should see "H5P Awesome H5P package" + And I should see "Student 1 - " + And I should see "Grade:" + And I should see "Student 2 - " diff --git a/mod/h5pactivity/tests/lib_test.php b/mod/h5pactivity/tests/lib_test.php new file mode 100644 index 00000000000..9bfa5ab774c --- /dev/null +++ b/mod/h5pactivity/tests/lib_test.php @@ -0,0 +1,242 @@ +. + +/** + * Unit tests for (some of) mod/h5pactivity/lib.php. + * + * @package mod_h5pactivity + * @copyright 2021 Ilya Tregubov + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +use mod_h5pactivity\local\manager; + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/mod/h5pactivity/lib.php'); + +/** + * Unit tests for (some of) mod/h5pactivity/lib.php. + * + * @copyright 2021 Ilya Tregubov + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class lib_test extends advanced_testcase { + + /** + * Test that assign_print_recent_activity shows ungraded submitted assignments. + */ + public function test_print_recent_activity() { + $this->resetAfterTest(); + $this->setAdminUser(); + + $course = $this->getDataGenerator()->create_course(); + $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); + $activity = $this->getDataGenerator()->create_module('h5pactivity', + ['course' => $course, 'enabletracking' => 1, 'grademethod' => manager::GRADEHIGHESTATTEMPT]); + + $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity'); + + $manager = manager::create_from_instance($activity); + $cm = $manager->get_coursemodule(); + + $user = $student; + $params = ['cmid' => $cm->id, 'userid' => $user->id]; + $generator->create_content($activity, $params); + $this->setUser($student); + $this->expectOutputRegex('/submitted:/'); + h5pactivity_print_recent_activity($course, true, time() - 3600); + } + + /** + * Test that h5pactivity_print_recent_activity does not display any warnings when a custom fullname has been configured. + */ + public function test_print_recent_activity_fullname() { + $this->resetAfterTest(); + $this->setAdminUser(); + + $course = $this->getDataGenerator()->create_course(); + $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher'); + $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); + $activity = $this->getDataGenerator()->create_module('h5pactivity', + ['course' => $course, 'enabletracking' => 1, 'grademethod' => manager::GRADEHIGHESTATTEMPT]); + + $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity'); + + $manager = manager::create_from_instance($activity); + $cm = $manager->get_coursemodule(); + + $user = $student; + $params = ['cmid' => $cm->id, 'userid' => $user->id]; + $generator->create_content($activity, $params); + + $this->setUser($teacher); + + $this->expectOutputRegex('/submitted:/'); + set_config('fullnamedisplay', 'firstname, lastnamephonetic'); + h5pactivity_print_recent_activity($course, false, time() - 3600); + } + + /** + * Test that h5pactivity_get_recent_mod_activity fetches the h5pactivity correctly. + */ + public function test_h5pactivity_get_recent_mod_activity() { + $this->resetAfterTest(); + $this->setAdminUser(); + + $course = $this->getDataGenerator()->create_course(); + $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher'); + $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); + $activity = $this->getDataGenerator()->create_module('h5pactivity', + ['course' => $course, 'enabletracking' => 1, 'grademethod' => manager::GRADEHIGHESTATTEMPT]); + + $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity'); + + $manager = manager::create_from_instance($activity); + $cm = $manager->get_coursemodule(); + + $user = $student; + $params = ['cmid' => $cm->id, 'userid' => $user->id]; + $generator->create_content($activity, $params); + + $index = 1; + $activities = [ + $index => (object) [ + 'type' => 'h5pactivity', + 'cmid' => $cm->id, + ], + ]; + + $this->setUser($teacher); + h5pactivity_get_recent_mod_activity($activities, $index, time() - HOURSECS, $course->id, $cm->id); + + $activity = $activities[1]; + $this->assertEquals("h5pactivity", $activity->type); + $this->assertEquals($student->id, $activity->user->id); + } + + /** + * Test that h5pactivity_get_recent_mod_activity fetches activity correctly. + */ + public function test_h5pactivity_fetch_recent_activity() { + global $DB; + + $this->resetAfterTest(); + $this->setAdminUser(); + + $course = $this->getDataGenerator()->create_course(); + + // Create users and groups. + $students = array(); + $groups = array(); + $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher'); + + for ($i = 1; $i < 4; $i++) { + $students[$i] = $this->getDataGenerator()->create_and_enrol($course, 'student'); + $groups[$i] = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); + } + + // Update the course set the groupmode SEPARATEGROUPS and forced. + update_course((object)array('id' => $course->id, 'groupmode' => SEPARATEGROUPS, 'groupmodeforce' => true)); + + // Student 1 is in groups 1 and 3. + groups_add_member($groups[1], $students[1]); + groups_add_member($groups[3], $students[1]); + + // Student 2 is in groups 1 and 2. + groups_add_member($groups[1], $students[2]); + groups_add_member($groups[2], $students[2]); + + // Student 3 is only in group 3. + groups_add_member($groups[3], $students[3]); + + // Grader is only in group 3. + groups_add_member($groups[3], $teacher); + + $timestart = time() - 1; + // Create h5pactivity. + $activity = $this->getDataGenerator()->create_module('h5pactivity', + ['course' => $course->id, 'enabletracking' => 1, 'grademethod' => manager::GRADEHIGHESTATTEMPT, + 'groupmode' => SEPARATEGROUPS]); + + $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); + $cmcontext = \context_module::instance($activity->cmid); + assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $teacherrole->id, $cmcontext, true); + + $manager = manager::create_from_instance($activity); + $cm = $manager->get_coursemodule(); + + // Create attempts. + $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity'); + foreach ($students as $student) { + $params = ['cmid' => $cm->id, 'userid' => $student->id]; + $generator->create_content($activity, $params); + } + + // Get all attempts. + $dbparams = [$timestart, $course->id, 'h5pactivity']; + $userfieldsapi = \core_user\fields::for_userpic(); + $namefields = $userfieldsapi->get_sql('u', false, '', 'userid', false)->selects;; + + $sql = "SELECT h5pa.id, h5pa.timemodified, cm.id as cmid, $namefields + FROM {h5pactivity_attempts} h5pa + JOIN {h5pactivity} h5p ON h5p.id = h5pa.h5pactivityid + JOIN {course_modules} cm ON cm.instance = h5p.id + JOIN {modules} md ON md.id = cm.module + JOIN {user} u ON u.id = h5pa.userid + WHERE h5pa.timemodified > ? + AND h5p.course = ? + AND md.name = ? + ORDER BY h5pa.timemodified ASC"; + + $submissions = $DB->get_records_sql($sql, $dbparams); + $this->assertCount(count($students), $submissions); + + // Fetch activity for student (only his own). + $this->setUser($students[1]); + $recentactivity = h5pactivity_fetch_recent_activity($submissions, $course->id); + $this->assertCount(1, $recentactivity); + $this->assertEquals($students[1]->id, $recentactivity[$students[1]->id]->userid); + + // Fetch users group info for grader. + $this->setUser($teacher); + $recentactivity = h5pactivity_fetch_recent_activity($submissions, $course->id); + $this->assertCount(2, $recentactivity); + // Grader, Student 1 and 3 are in Group 3. + $this->assertEquals($students[1]->id, $recentactivity[$students[1]->id]->userid); + $this->assertEquals($students[3]->id, $recentactivity[$students[3]->id]->userid); + + // Grader is in Group 2. + groups_remove_member($groups[3], $teacher); + groups_add_member($groups[2], $teacher); + get_fast_modinfo($course->id, 0, true); + $recentactivity = h5pactivity_fetch_recent_activity($submissions, $course->id); + $this->assertCount(1, $recentactivity); + // Grader, Student 2 are in Group 2. + $this->assertEquals($students[2]->id, $recentactivity[$students[2]->id]->userid); + + // Grader is in Group 1. + groups_remove_member($groups[2], $teacher); + groups_add_member($groups[1], $teacher); + get_fast_modinfo($course->id, 0, true); + $recentactivity = h5pactivity_fetch_recent_activity($submissions, $course->id); + $this->assertCount(2, $recentactivity); + // Grader, Student 1 and 2 are in Group 1. + $this->assertEquals($students[1]->id, $recentactivity[$students[1]->id]->userid); + $this->assertEquals($students[2]->id, $recentactivity[$students[2]->id]->userid); + } +}