diff --git a/lib/grouplib.php b/lib/grouplib.php index 1c251f3f5df..d4c4ade52a6 100644 --- a/lib/grouplib.php +++ b/lib/grouplib.php @@ -447,9 +447,12 @@ function groups_get_my_groups() { * @category group * @param int $courseid * @param int $userid $USER if not specified + * @param bool $includehidden Include groups with GROUP_VISIBILITY_NONE that the user is a member of, but is not allowed to see + * themselves. Use this parameter with care - it is the responsibility of the calling code to ensure these groups are not exposed + * to the user, as this could have privacy implications. * @return array Array[groupingid][groupid] including grouping id 0 which means all groups */ -function groups_get_user_groups($courseid, $userid=0) { +function groups_get_user_groups(int $courseid, int $userid = 0, bool $includehidden = false): array { global $USER, $DB; if (empty($courseid)) { @@ -461,7 +464,7 @@ function groups_get_user_groups($courseid, $userid=0) { } $usergroups = false; - $viewhidden = has_capability('moodle/course:viewhiddengroups', context_course::instance($courseid)); + $viewhidden = $includehidden || has_capability('moodle/course:viewhiddengroups', context_course::instance($courseid)); $viewall = \core_group\visibility::can_view_all_groups($courseid); $cache = cache::make('core', 'user_group_groupings'); @@ -473,7 +476,7 @@ function groups_get_user_groups($courseid, $userid=0) { if ($usergroups === false) { - $sql = "SELECT g.id, g.courseid, gg.groupingid + $sql = "SELECT g.id, g.courseid, gg.groupingid, g.visibility FROM {groups} g JOIN {groups_members} gm ON gm.groupid = g.id LEFT JOIN {groupings_groups} gg ON gg.groupid = g.id diff --git a/lib/tests/grouplib_test.php b/lib/tests/grouplib_test.php index ea02fe88a85..7045b2fb4ec 100644 --- a/lib/tests/grouplib_test.php +++ b/lib/tests/grouplib_test.php @@ -2109,6 +2109,12 @@ class grouplib_test extends \advanced_testcase { // Own groups - should see all groups except group with visibility::NONE. $usergroups1 = groups_get_user_groups($course->id, $users[1]->id); $this->assertEquals([$groups['all']->id, $groups['members']->id, $groups['own']->id], $usergroups1[0]); + // Own groups including hidden - should see all groups. + $usergroups1hidden = groups_get_user_groups($course->id, $users[1]->id, true); + $this->assertEquals( + [$groups['all']->id, $groups['members']->id, $groups['own']->id, $groups['none']->id], + $usergroups1hidden[0] + ); // Fellow member of a group with visiblity::MEMBERS. Should see that group. $usergroups2 = groups_get_user_groups($course->id, $users[2]->id); $this->assertEquals([$groups['members']->id], $usergroups2[0]); @@ -2118,6 +2124,9 @@ class grouplib_test extends \advanced_testcase { // Fellow member of a group with visiblity::NONE. Should not see that group. $usergroups4 = groups_get_user_groups($course->id, $users[4]->id); $this->assertEmpty($usergroups4[0]); + // Fellow member of a group with visiblity::NONE including hidden. Should see that group. + $usergroups4hidden = groups_get_user_groups($course->id, $users[4]->id, true); + $this->assertEquals([$groups['none']->id], $usergroups4hidden[0]); // Run as a user with viewhiddengroups. Should see all group memberships for each member. $this->setUser($users[5]); diff --git a/lib/upgrade.txt b/lib/upgrade.txt index 5080744ea45..fbda37d6886 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -1,6 +1,11 @@ This files describes API changes in core libraries and APIs, information provided here is intended especially for developers. +=== 4.2.7 === +* groups_get_user_groups() in grouplib has a new $includehidden paramater, which will return groups for user even if they have + GROUP_VISIBILITY_NONE. This is false by default, and should be used with care. The calling code must ensure that these groups + are not exposed to the user as this may be a privacy issue. + === 4.2.6 === * The `html_writer::select_time` method has a `$timezone` parameter to use when formatting the time parameter