diff --git a/availability/classes/info.php b/availability/classes/info.php index b54d919a615..ffab7b25c4f 100644 --- a/availability/classes/info.php +++ b/availability/classes/info.php @@ -49,6 +49,9 @@ abstract class info { /** @var tree Availability configuration, decoded from JSON; null if unset */ protected $availabilitytree; + /** @var array The groups the current user belongs to. */ + protected $groups; + /** @var array|null Array of information about current restore if any */ protected static $restoreinfo = null; @@ -65,6 +68,7 @@ abstract class info { $this->course = $course; $this->visible = (bool)$visible; $this->availability = $availability; + $this->groups = null; } /** @@ -800,4 +804,28 @@ abstract class info { } return false; } + + /** + * Returns groups that the current user belongs to on the course. Note: If not already + * available, this may make a database query. + * + * This will include groups the user is not allowed to see themselves, so check visibility + * before displaying groups to the user. + * + * @param int $groupingid Grouping ID or 0 (default) for all groups + * @return int[] Array of int (group id) => int (same group id again); empty array if none + */ + public function get_groups(int $groupingid = 0): array { + global $USER; + if (is_null($this->groups)) { + $allgroups = groups_get_user_groups($this->course->id, $USER->id, true); + $this->groups = $allgroups; + } else { + $allgroups = $this->groups; + } + if (!isset($allgroups[$groupingid])) { + return []; + } + return $allgroups[$groupingid]; + } } diff --git a/availability/condition/group/classes/condition.php b/availability/condition/group/classes/condition.php index fd247e26053..feeae1c6ce3 100644 --- a/availability/condition/group/classes/condition.php +++ b/availability/condition/group/classes/condition.php @@ -71,7 +71,7 @@ class condition extends \core_availability\condition { $allow = true; if (!has_capability('moodle/site:accessallgroups', $context, $userid)) { // Get all groups the user belongs to. - $groups = $info->get_modinfo()->get_groups(); + $groups = $info->get_groups(); if ($this->groupid) { $allow = in_array($this->groupid, $groups); } else { diff --git a/availability/condition/group/tests/behat/availability_group.feature b/availability/condition/group/tests/behat/availability_group.feature index 57e4d4cc1a6..4d9e1a97c31 100644 --- a/availability/condition/group/tests/behat/availability_group.feature +++ b/availability/condition/group/tests/behat/availability_group.feature @@ -108,3 +108,49 @@ Feature: availability_group When I am on the "C1" "Course" page logged in as "student1" Then I should see "Not available unless: You belong to G-One" And I should not see "G-Un" + + @javascript + Scenario: Condition using a hidden group + And the following "groups" exist: + | name | course | idnumber | visibility | + | Hidden Group | C1 | GA | 3 | + And I log in as "teacher1" + And I add a page activity to course "Course 1" section "1" + And I expand all fieldsets + + # Page P1 any group. + And I am on the "P1" "page activity editing" page + And I expand all fieldsets + And I click on "Add restriction..." "button" + Then "Group" "button" should exist in the "Add restriction..." "dialogue" + Given I click on "Group" "button" in the "Add restriction..." "dialogue" + And I set the field "Group" to "(Any group)" + And I click on ".availability-item .availability-eye img" "css_element" + And I click on "Save and return to course" "button" + + # Page P2 with hidden group. + And I am on the "P2" "page activity editing" page + And I expand all fieldsets + And I click on "Add restriction..." "button" + And I click on "Group" "button" in the "Add restriction..." "dialogue" + And I set the field "Group" to "Hidden Group" + And I click on "Save and return to course" "button" + + # Log back in as student. + When I am on the "Course 1" "course" page logged in as "student1" + + # No pages should appear yet. + Then I should not see "P1" in the "region-main" "region" + And I should not see "P2" in the "region-main" "region" + And I should not see "Hidden Group" + + # Add to groups and log out/in again. + Given the following "group members" exist: + | user | group | + | student1 | GA | + And I am on "Course 1" course homepage + + # P1 (any groups) and P2 should show. The user should not see the hidden group mentioned anywhere. + Then I should see "P1" in the "region-main" "region" + And I should see "P2" in the "region-main" "region" + And I should not see "Hidden Group" diff --git a/availability/condition/group/tests/condition_test.php b/availability/condition/group/tests/condition_test.php index eb221ea9234..f20a3d9a554 100644 --- a/availability/condition/group/tests/condition_test.php +++ b/availability/condition/group/tests/condition_test.php @@ -49,6 +49,7 @@ class condition_test extends \advanced_testcase { $course = $generator->create_course(); $user = $generator->create_user(); $generator->enrol_user($user->id, $course->id); + $this->setUser($user); $info = new \core_availability\mock_info($course, $user->id); // Make 2 test groups, one in a grouping and one not. @@ -70,7 +71,7 @@ class condition_test extends \advanced_testcase { // Add user to groups and refresh cache. groups_add_member($group1, $user); groups_add_member($group2, $user); - get_fast_modinfo($course->id, 0, true); + $info = new \core_availability\mock_info($course, $user->id); // Recheck. $this->assertTrue($cond->is_available(false, $info, true, $user->id));