From c4f303b42accc88f835bdd606962b4806eb8e090 Mon Sep 17 00:00:00 2001 From: Anupama Sarjoshi Date: Mon, 19 Jan 2026 14:44:33 +0530 Subject: [PATCH 1/2] MDL-51447 core_completion: Get visible activities with completion on --- lib/completionlib.php | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/lib/completionlib.php b/lib/completionlib.php index 19df8dbccf4..51d973dd618 100644 --- a/lib/completionlib.php +++ b/lib/completionlib.php @@ -1345,6 +1345,44 @@ class completion_info { return $result; } + /** + * Return a list of activities that are visible on the course page and have completion enabled. + * + * This includes activities that the user can see on the course page (visible or restricted), + * but only those with completion tracking enabled. Activities hidden from + * the user, located in hidden sections or restricted by group/grouping are excluded. + * + * @param int $userid User id + * @return array Array of user visible activities with completion enabled. + */ + public function get_user_activities_with_completion($userid): array { + $visible = []; + $activities = $this->get_activities(); + + foreach ($activities as $cm) { + // Step 1: Exclude activities hidden from the user on the course page. + if (!$cm->is_visible_on_course_page()) { + continue; + } + + // Step 2: Check if the user is excluded by group or grouping style restrictions. + $info = new \core_availability\info_module($cm); + + $users = [$userid => (object)['id' => $userid]]; + $users = $info->filter_user_list($users); + + if (empty($users)) { + // The user was removed from the list, meaning user list restrictions apply. + // This is where group and grouping restrictions exclude the user. + continue; + } + + // If we reach here, count this activity for completion details and percentage. + $visible[$cm->id] = 1; + } + return $visible; + } + /** * Checks to see if the userid supplied has a tracked role in * this course From 1944075f31d697371675d970dc5e519eb835c12d Mon Sep 17 00:00:00 2001 From: Anupama Sarjoshi Date: Mon, 19 Jan 2026 14:50:19 +0530 Subject: [PATCH 2/2] MDL-51447 block_completionstatus: Show only user-visible activities This change ensures that the completion details page displays only the activities that are visible to the user on the course home page. Activities that are hidden, unavailable or located in hidden sections are no longer shown in the completion details view. Co-authored by: ewallah --- .../block_completionstatus.php | 8 + blocks/completionstatus/details.php | 11 + ...mpletionstatus_activity_completion.feature | 285 +++++++++++++++++- 3 files changed, 293 insertions(+), 11 deletions(-) diff --git a/blocks/completionstatus/block_completionstatus.php b/blocks/completionstatus/block_completionstatus.php index 4735e760062..9bd4c6fadb4 100644 --- a/blocks/completionstatus/block_completionstatus.php +++ b/blocks/completionstatus/block_completionstatus.php @@ -104,6 +104,9 @@ class block_completionstatus extends block_base { // Flag to set if current completion data is inconsistent with what is stored in the database. $pending_update = false; + // Get activities visible to the user that have completion enabled. + $visibleactivities = $info->get_user_activities_with_completion($USER->id); + // Loop through course criteria. foreach ($completions as $completion) { $criteria = $completion->get_criteria(); @@ -115,6 +118,11 @@ class block_completionstatus extends block_base { // Activities are a special case, so cache them and leave them till last. if ($criteria->criteriatype == COMPLETION_CRITERIA_TYPE_ACTIVITY) { + // Only include activities that are visible to the user. + if (!isset($visibleactivities[$criteria->moduleinstance])) { + continue; + } + $activities[$criteria->moduleinstance] = $complete; if ($complete) { diff --git a/blocks/completionstatus/details.php b/blocks/completionstatus/details.php index e00892babe2..eada453ce2c 100644 --- a/blocks/completionstatus/details.php +++ b/blocks/completionstatus/details.php @@ -119,10 +119,21 @@ $pendingupdate = false; // Load criteria to display. $completions = $info->get_completions($user->id); +// Get activities visible to the user that have completion enabled. +$visibleactivities = $info->get_user_activities_with_completion($user->id); + // Loop through course criteria. foreach ($completions as $completion) { $criteria = $completion->get_criteria(); + // Skip display of activity completion criteria for activities the user cannot see. + if ( + $criteria->criteriatype == COMPLETION_CRITERIA_TYPE_ACTIVITY && + !isset($visibleactivities[$criteria->moduleinstance]) + ) { + continue; + } + if (!$pendingupdate && $criteria->is_pending($completion)) { $pendingupdate = true; } diff --git a/blocks/completionstatus/tests/behat/block_completionstatus_activity_completion.feature b/blocks/completionstatus/tests/behat/block_completionstatus_activity_completion.feature index 941a4683529..806388566c1 100644 --- a/blocks/completionstatus/tests/behat/block_completionstatus_activity_completion.feature +++ b/blocks/completionstatus/tests/behat/block_completionstatus_activity_completion.feature @@ -6,9 +6,10 @@ Feature: Enable Block Completion in a course using activity completion Background: Given the following "users" exist: - | username | firstname | lastname | email | idnumber | - | teacher1 | Teacher | 1 | teacher1@example.com | T1 | - | student1 | Student | 1 | student1@example.com | S1 | + | username | firstname | lastname | email | idnumber | + | teacher1 | Teacher | 1 | teacher1@example.com | T1 | + | student1 | Student | 1 | student1@example.com | S1 | + | student2 | Student | 2 | student2@example.com | S2 | And the following "courses" exist: | fullname | shortname | category | enablecompletion | | Course 1 | C1 | 0 | 1 | @@ -16,6 +17,7 @@ Feature: Enable Block Completion in a course using activity completion | user | course | role | | teacher1 | C1 | editingteacher | | student1 | C1 | student | + | student2 | C1 | student | And the following "activities" exist: | activity | course | idnumber | name | gradepass | completion | completionview | completionusegrade | completionpassgrade | | page | C1 | page1 | Test page name | | 2 | 1 | 0 | 0 | @@ -23,10 +25,12 @@ Feature: Enable Block Completion in a course using activity completion And the following "blocks" exist: | blockname | contextlevel | reference | pagetypepattern | defaultregion | | completionstatus | Course | C1 | course-view-* | side-pre | + And I am on the "Course 1" course page logged in as teacher1 + And I change window size to "large" + And I turn editing mode on Scenario: Completion status block when student has not started any activities - Given I am on the "Course 1" course page logged in as teacher1 - And I navigate to "Course completion" in current page administration + Given I navigate to "Course completion" in current page administration And I expand all fieldsets And I set the following fields to these values: | Test page name | 1 | @@ -36,8 +40,7 @@ Feature: Enable Block Completion in a course using activity completion And I should see "0 of 1" in the "Activity completion" "table_row" Scenario: Completion status block when student has completed a page - Given I am on the "Course 1" course page logged in as teacher1 - And I navigate to "Course completion" in current page administration + Given I navigate to "Course completion" in current page administration And I expand all fieldsets And I set the following fields to these values: | Test page name | 1 | @@ -50,8 +53,7 @@ Feature: Enable Block Completion in a course using activity completion And I should see "Yes" in the "Activity completion" "table_row" Scenario: Completion status block with items with passing grade - Given I am on the "Course 1" course page logged in as teacher1 - And I navigate to "Course completion" in current page administration + Given I navigate to "Course completion" in current page administration And I expand all fieldsets And I set the following fields to these values: | Test assign name | 1 | @@ -69,8 +71,7 @@ Feature: Enable Block Completion in a course using activity completion And I should see "Yes" in the "Activity completion" "table_row" Scenario: Completion status block with items with failing grade - Given I am on the "Course 1" course page logged in as teacher1 - And the following "grade grades" exist: + Given the following "grade grades" exist: | gradeitem | user | grade | | Test assign name | student1 | 49 | And I navigate to "Course completion" in current page administration @@ -86,3 +87,265 @@ Feature: Enable Block Completion in a course using activity completion And I follow "More details" And I should see "Achieving grade, Achieving passing grade" in the "Activity completion" "table_row" And I should see "No" in the "Activity completion" "table_row" + + @javascript + Scenario: Student visibility respects combined activity and section restrictions with progressive completion + Given the following "activities" exist: + | activity | name | intro | course | idnumber | section | visible | completion | completionview | + | page | task A | page description | C1 | page1 | 0 | 1 | 2 | 1 | + | page | task B | page description | C1 | page2 | 1 | 1 | 2 | 1 | + | assign | task C | assignment description | C1 | assign1 | 1 | 1 | 2 | 1 | + And I navigate to "Course completion" in current page administration + And I expand all fieldsets + And I set the following fields to these values: + | Page - task A | 1 | + | Page - task B | 1 | + | Assignment - task C | 1 | + And I press "Save changes" + # Add conditionally visible restriction (open eye) to section 1 requiring task A completion. + And I turn editing mode on + And I edit the section "1" + And I expand all fieldsets + And I click on "Add restriction..." "button" + And I click on "Activity completion" "button" in the "Add restriction..." "dialogue" + And I set the field "Activity or resource" to "task A" + And I press "Save changes" + # Add conditionally hidden restriction (closed eye) to task C requiring task A completion. + And I am on the "task C" "assign activity editing" page + And I expand all fieldsets + And I click on "Add restriction..." "button" + And I click on "Activity completion" "button" in the "Add restriction..." "dialogue" + And I click on "Displayed if student doesn't meet this condition • Click to hide" "link" + And I set the field "Activity or resource" to "task A" + And I press "Save and return to course" + And I log out + # Initial state: Only unrestricted visible activities appear. + When I am on the "Course 1" course page logged in as student1 + Then I should see "Status: Not yet started" + And I should see "0 of 1" in the "Activity completion" "table_row" + And I follow "More details" + And I should see "task A" in the "criteriastatus" "table" + And I should not see "task B" in the "criteriastatus" "table" + And I should not see "task C" in the "criteriastatus" "table" + # After completing task A: Section 2 activities become visible. + And I click on "task A" "link" + And I am on the "Course 1" course page logged in as student1 + And I should see "Status: In progress" + And I should see "1 of 3" in the "Activity completion" "table_row" + And I follow "More details" + And I should see "task A" in the "criteriastatus" "table" + And I should see "task B" in the "criteriastatus" "table" + And I should see "task C" in the "criteriastatus" "table" + + @javascript + Scenario: Student completion view shows only accessible activities considering all activity restrictions + Given the following "activities" exist: + | activity | name | intro | course | idnumber | section | visible | completion | completionview | + | page | task A | page description | C1 | page1 | 0 | 1 | 2 | 1 | + | page | task B | page description | C1 | assign1 | 1 | 1 | 2 | 1 | + | assign | task C | assignment description | C1 | assign2 | 1 | 1 | 2 | 1 | + And I navigate to "Course completion" in current page administration + And I expand all fieldsets + # Set completion of the activities. + And I set the following fields to these values: + | Page - task A | 1 | + | Page - task B | 1 | + | Assignment - task C | 1 | + And I press "Save changes" + # Add conditionally visible restriction (open eye) to "task B". + And I am on the "task B" "page activity editing" page + And I expand all fieldsets + And I click on "Add restriction..." "button" + And I click on "Activity completion" "button" in the "Add restriction..." "dialogue" + And I set the field "Activity or resource" to "task A" + And I press "Save and return to course" + # Add conditionally hidden restriction (closed eye) to "task C". + And I am on the "task C" "assign activity editing" page + And I expand all fieldsets + And I click on "Add restriction..." "button" + And I click on "Activity completion" "button" in the "Add restriction..." "dialogue" + And I click on "Displayed if student doesn't meet this condition • Click to hide" "link" + And I set the field "Activity or resource" to "task A" + And I press "Save and return to course" + When I am on the "Course 1" course page logged in as student1 + And I should see "Status: Not yet started" + And I should see "0 of 2" in the "Activity completion" "table_row" + And I follow "More details" + Then I should see "task A" in the "criteriastatus" "table" + And I should see "task B" in the "criteriastatus" "table" + And I should not see "task C" in the "criteriastatus" "table" + And I click on "task A" "link" + # Complete task A to make task C visible. + And I am on the "Course 1" course page logged in as student1 + And I should see "Status: In progress" + And I should see "1 of 3" in the "Activity completion" "table_row" + And I follow "More details" + And I should see "task A" in the "criteriastatus" "table" + And I should see "task B" in the "criteriastatus" "table" + And I should see "task C" in the "criteriastatus" "table" + + @javascript + Scenario: Hidden activities do not appear in the completion status block + Given the following "activities" exist: + | activity | name | intro | course | idnumber | section | visible | completion | completionview | + | page | task A | page description | C1 | page1 | 0 | 1 | 2 | 1 | + | page | task B | page description | C1 | page2 | 0 | 0 | 2 | 1 | + And I navigate to "Course completion" in current page administration + And I expand all fieldsets + # Set completion of the activities. + And I set the following fields to these values: + | Page - task A | 1 | + | Page - task B | 1 | + And I press "Save changes" + When I am on the "Course 1" course page logged in as student1 + And I should see "Status: Not yet started" + And I should see "0 of 1" in the "Activity completion" "table_row" + And I follow "More details" + And I should see "task A" in the "criteriastatus" "table" + Then I should not see "task B" in the "criteriastatus" "table" + + @javascript + Scenario: Activities in the hidden section do not appear in the completion status block + Given the following "activities" exist: + | activity | name | intro | course | idnumber | section | visible | completion | completionview | + | page | task A | page description | C1 | page1 | 0 | 1 | 2 | 1 | + | page | task B | page description | C1 | page2 | 1 | 1 | 2 | 1 | + | assign | task C | page description | C1 | page3 | 2 | 1 | 2 | 1 | + | assign | task D | page description | C1 | page4 | 3 | 1 | 2 | 1 | + And I navigate to "Course completion" in current page administration + And I expand all fieldsets + # Set completion of the activities. + And I set the following fields to these values: + | Page - task A | 1 | + | Page - task B | 1 | + | Assignment - task C | 1 | + | Assignment - task D | 1 | + And I press "Save changes" + # Hide section 1 to make sure book activities are not visible to the student. + And I hide section "1" + # Add conditionally visible restriction to section 2. + And I edit the section "2" + And I expand all fieldsets + And I click on "Add restriction..." "button" + And I click on "Activity completion" "button" in the "Add restriction..." "dialogue" + And I set the field "Activity or resource" to "task A" + And I press "Save changes" + # Add conditionally hidden restriction to section 3. + And I am on the "Course 1" course page + And I edit the section "3" + And I expand all fieldsets + And I click on "Add restriction..." "button" + And I click on "Activity completion" "button" in the "Add restriction..." "dialogue" + And I set the field "Activity or resource" to "task A" + And I click on "Displayed if student doesn't meet this condition • Click to hide" "link" + And I press "Save changes" + And I log out + When I am on the "Course 1" course page logged in as student1 + And I should see "Status: Not yet started" + And I should see "0 of 1" in the "Activity completion" "table_row" + And I follow "More details" + Then I should see "task A" in the "criteriastatus" "table" + And I should not see "task B" in the "criteriastatus" "table" + And I should not see "task C" in the "criteriastatus" "table" + And I should not see "task D" in the "criteriastatus" "table" + # Complete task A to make other activities visible. + And I click on "task A" "link" + And I am on the "Course 1" course page logged in as student1 + And I should see "Status: In progress" + And I should see "1 of 3" in the "Activity completion" "table_row" + And I follow "More details" + And I should see "task A" in the "criteriastatus" "table" + And I should not see "task B" in the "criteriastatus" "table" + And I should see "task C" in the "criteriastatus" "table" + And I should see "task D" in the "criteriastatus" "table" + + @javascript + Scenario: Activities with disabled completion tracking are omitted from the completion view + Given the following "activities" exist: + | activity | name | intro | course | idnumber | section | visible | completion | completionview | + | page | task A | page description | C1 | page1 | 0 | 1 | 2 | 1 | + | page | task B | page description | C1 | page2 | 1 | 1 | 2 | 1 | + And I navigate to "Course completion" in current page administration + And I expand all fieldsets + # Set completion of the activities. + And I set the following fields to these values: + | Page - task A | 1 | + | Page - task B | 1 | + And I press "Save changes" + # Disable completion tracking for "task A". + And I am on the "task A" "page activity editing" page + And I expand all fieldsets + And I set the following fields to these values: + | completion | 0 | + And I press "Save and return to course" + When I am on the "Course 1" course page logged in as student1 + And I should see "Status: Not yet started" + And I should see "0 of 1" in the "Activity completion" "table_row" + And I follow "More details" + Then I should not see "task A" in the "criteriastatus" "table" + And I should see "task B" in the "criteriastatus" "table" + + @javascript + Scenario: Activities with group or grouping restrictions are omitted from the completion view + Given the following "activities" exist: + | activity | name | intro | course | idnumber | section | visible | completion | completionview | + | page | task A | page description | C1 | page1 | 0 | 1 | 2 | 1 | + | page | task B | page description | C1 | page2 | 1 | 1 | 2 | 1 | + | page | task C | page description | C1 | page3 | 2 | 1 | 2 | 1 | + And I navigate to "Course completion" in current page administration + And I expand all fieldsets + # Set completion of the activities. + And I set the following fields to these values: + | Page - task A | 1 | + | Page - task B | 1 | + | Page - task C | 1 | + And I press "Save changes" + # Add groups and groupings. + And the following "groups" exist: + | name | course | idnumber | + | G1 | C1 | GI1 | + | G2 | C1 | GI2 | + And the following "groupings" exist: + | name | course | idnumber | + | Grouping 1 | C1 | GG1 | + | Grouping 2 | C1 | GG2 | + And the following "grouping groups" exist: + | grouping | group | + | GG1 | GI1 | + | GG2 | GI2 | + # Add students to groups. + And the following "group members" exist: + | user | group | + | student1 | GI1 | + | student2 | GI2 | + # Add group restriction to "task B". + And I am on the "task B" "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 "G1" + And I click on "Save and return to course" "button" + # Add Grouping and 'Activity or resource' restriction to "task C". + And I am on the "task C" "page activity editing" page + And I expand all fieldsets + And I click on "Add restriction..." "button" + And I click on "Grouping" "button" in the "Add restriction..." "dialogue" + And I set the field "Grouping" to "Grouping 2" + And I click on "Add restriction..." "button" + And I click on "Activity completion" "button" in the "Add restriction..." "dialogue" + And I set the field "Activity or resource" to "task A" + And I click on "Save and return to course" "button" + When I am on the "Course 1" course page logged in as student1 + And I should see "Status: Not yet started" + And I should see "0 of 2" in the "Activity completion" "table_row" + And I follow "More details" + Then I should see "task A" in the "criteriastatus" "table" + And I should see "task B" in the "criteriastatus" "table" + And I should not see "task C" in the "criteriastatus" "table" + And I am on the "Course 1" course page logged in as student2 + And I should see "Status: Not yet started" + And I should see "0 of 2" in the "Activity completion" "table_row" + And I follow "More details" + And I should see "task A" in the "criteriastatus" "table" + And I should not see "task B" in the "criteriastatus" "table" + And I should see "task C" in the "criteriastatus" "table"