Skip to content

Commit

Permalink
MDL-79174 availability: Allow group condition to use hidden groups
Browse files Browse the repository at this point in the history
Previously, groups with GROUP_VISIBILITY_NONE could be selected for an
availability condition, but as the group API did not return a user's own
groups with this visibility, the condition's is_available check always
failed.

This change uses the new $includehidden parameter to get all of a user's
groups from groups_get_user_groups when evaluating the condition, so
these groups work as expected. Due to the enforced hiding of conditions
containing these groups, they will never be seen by the user.
  • Loading branch information
marxjohnson committed Feb 21, 2024
1 parent ce70629 commit 238ea3d
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 2 deletions.
28 changes: 28 additions & 0 deletions availability/classes/info.php
Expand Up @@ -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;

Expand All @@ -65,6 +68,7 @@ public function __construct($course, $visible, $availability) {
$this->course = $course;
$this->visible = (bool)$visible;
$this->availability = $availability;
$this->groups = null;
}

/**
Expand Down Expand Up @@ -800,4 +804,28 @@ public static function completion_value_used($course, $cmid) {
}
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];
}
}
2 changes: 1 addition & 1 deletion availability/condition/group/classes/condition.php
Expand Up @@ -71,7 +71,7 @@ public function is_available($not, \core_availability\info $info, $grabthelot, $
$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 {
Expand Down
Expand Up @@ -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"
3 changes: 2 additions & 1 deletion availability/condition/group/tests/condition_test.php
Expand Up @@ -49,6 +49,7 @@ public function test_usage() {
$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.
Expand All @@ -70,7 +71,7 @@ public function test_usage() {
// 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));
Expand Down

0 comments on commit 238ea3d

Please sign in to comment.