Merge branch 'MDL-75173-400' of https://github.com/ilyatregubov/moodle into MOODLE_400_STABLE

This commit is contained in:
Sara Arjona
2022-10-17 15:18:03 +02:00
7 changed files with 415 additions and 26 deletions
+30 -21
View File
@@ -110,7 +110,36 @@ $params = array(
);
$ccompletion = new completion_completion($params);
if ($coursecomplete) {
// Save row data.
$rows = array();
// Flag to set if current completion data is inconsistent with what is stored in the database.
$pendingupdate = false;
// Load criteria to display.
$completions = $info->get_completions($user->id);
// Loop through course criteria.
foreach ($completions as $completion) {
$criteria = $completion->get_criteria();
if (!$pendingupdate && $criteria->is_pending($completion)) {
$pendingupdate = true;
}
$row = array();
$row['type'] = $criteria->criteriatype;
$row['title'] = $criteria->get_title();
$row['status'] = $completion->get_status();
$row['complete'] = $completion->is_complete();
$row['timecompleted'] = $completion->timecompleted;
$row['details'] = $criteria->get_details($completion);
$rows[] = $row;
}
if ($pendingupdate) {
echo html_writer::tag('i', get_string('pending', 'completion'));
} else if ($coursecomplete) {
echo get_string('complete');
} else if (!$criteriacomplete && !$ccompletion->timestarted) {
echo html_writer::tag('i', get_string('notyetstarted', 'completion'));
@@ -121,9 +150,6 @@ if ($coursecomplete) {
echo html_writer::end_tag('td');
echo html_writer::end_tag('tr');
// Load criteria to display.
$completions = $info->get_completions($user->id);
// Check if this course has any criteria.
if (empty($completions)) {
echo html_writer::start_tag('tr');
@@ -166,23 +192,6 @@ if (empty($completions)) {
echo html_writer::tag('th', get_string('completiondate', 'report_completion'), array('class' => 'c5 header', 'scope' => 'col'));
echo html_writer::end_tag('tr');
// Save row data.
$rows = array();
// Loop through course criteria.
foreach ($completions as $completion) {
$criteria = $completion->get_criteria();
$row = array();
$row['type'] = $criteria->criteriatype;
$row['title'] = $criteria->get_title();
$row['status'] = $completion->get_status();
$row['complete'] = $completion->is_complete();
$row['timecompleted'] = $completion->timecompleted;
$row['details'] = $criteria->get_details($completion);
$rows[] = $row;
}
// Print table.
$last_type = '';
$agg_type = false;
@@ -133,4 +133,4 @@ Feature: Enable Block Completion in a course using activity completion
And I am on "Course 1" course homepage
And I follow "More details"
And I should see "Achieving grade, Achieving passing grade" in the "Activity completion" "table_row"
And I should see "Yes" in the "Activity completion" "table_row"
And I should see "No" in the "Activity completion" "table_row"
+6 -3
View File
@@ -142,6 +142,7 @@ class api {
INNER JOIN {course} c ON cr.course = c.id
INNER JOIN {context} con ON con.instanceid = c.id
INNER JOIN {role_assignments} ra ON ra.contextid = con.id
INNER JOIN {course_modules} cm ON cm.id = cr.moduleinstance
INNER JOIN {course_modules_completion} mc ON mc.coursemoduleid = cr.moduleinstance AND mc.userid = ra.userid
LEFT JOIN {course_completion_crit_compl} cc ON cc.criteriaid = cr.id AND cc.userid = ra.userid
WHERE cr.criteriatype = :criteriatype
@@ -150,15 +151,17 @@ class api {
AND cc.id IS NULL
AND (
mc.completionstate = :completionstate
OR mc.completionstate = :completionstatepass
OR mc.completionstate = :completionstatefail
OR (cm.completionpassgrade = 1 AND mc.completionstate = :completionstatepass1)
OR (cm.completionpassgrade = 0 AND (mc.completionstate = :completionstatepass2
OR mc.completionstate = :completionstatefail))
)";
$params = [
'criteriatype' => COMPLETION_CRITERIA_TYPE_ACTIVITY,
'contextlevel' => CONTEXT_COURSE,
'completionstate' => COMPLETION_COMPLETE,
'completionstatepass' => COMPLETION_COMPLETE_PASS,
'completionstatepass1' => COMPLETION_COMPLETE_PASS,
'completionstatepass2' => COMPLETION_COMPLETE_PASS,
'completionstatefail' => COMPLETION_COMPLETE_FAIL
];
+5 -1
View File
@@ -80,7 +80,11 @@ class progress {
$completed = 0;
foreach ($modules as $module) {
$data = $completion->get_data($module, true, $userid);
$completed += $data->completionstate == COMPLETION_INCOMPLETE ? 0 : 1;
if (($data->completionstate == COMPLETION_INCOMPLETE) || ($data->completionstate == COMPLETION_COMPLETE_FAIL)) {
$completed += 0;
} else {
$completed += 1;
};
}
return ($completed / $count) * 100;
+97
View File
@@ -287,4 +287,101 @@ class api_test extends \advanced_testcase {
$this->assertEquals($student1->id, reset($actual)->userid);
$this->assertEquals($student2->id, end($actual)->userid);
}
/**
* Test for mark_course_completions_activity_criteria() with different completionpassgrade settings.
* @covers ::mark_course_completions_activity_criteria
*/
public function test_mark_course_completions_activity_criteria_completion_states() {
global $DB, $CFG;
require_once($CFG->dirroot . '/completion/criteria/completion_criteria_activity.php');
$this->resetAfterTest(true);
$courses[] = $this->getDataGenerator()->create_course(['shortname' => 'completionpassgradenotset',
'enablecompletion' => 1]);
$courses[] = $this->getDataGenerator()->create_course(['shortname' => 'completionpassgradeset',
'enablecompletion' => 1]);
$student1 = $this->getDataGenerator()->create_user();
$student2 = $this->getDataGenerator()->create_user();
$teacher = $this->getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
foreach ($courses as $course) {
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
$this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id);
$completioncriteria = [
'completionusegrade' => 1,
'gradepass' => 50
];
if ($course->shortname == 'completionpassgradeset') {
$completioncriteria['completionpassgrade'] = 1;
}
/** @var \mod_assign_generator $assigngenerator */
$assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$assign = $assigngenerator->create_instance([
'course' => $course->id,
'completion' => COMPLETION_ENABLED,
] + $completioncriteria);
$cmassing = get_coursemodule_from_id('assign', $assign->cmid);
$cm = get_coursemodule_from_instance('assign', $assign->id);
$c = new \completion_info($course);
// Add activity completion criteria.
$criteriadata = new \stdClass();
$criteriadata->id = $course->id;
$criteriadata->criteria_activity = array();
// Some activities.
$criteriadata->criteria_activity[$cmassing->id] = 1;
$criterion = new \completion_criteria_activity();
$criterion->update_config($criteriadata);
$this->setUser($teacher);
// Mark user completions.
$completion = new \stdClass();
$completion->coursemoduleid = $cm->id;
$completion->timemodified = time();
$completion->viewed = COMPLETION_NOT_VIEWED;
$completion->overrideby = null;
// Student1 achieved passgrade.
$completion->id = 0;
$completion->completionstate = COMPLETION_COMPLETE_PASS;
$completion->userid = $student1->id;
$c->internal_set_data($cm, $completion, true);
// Student2 has not achieved passgrade.
$completion->id = 0;
$completion->completionstate = COMPLETION_COMPLETE_FAIL;
$completion->userid = $student2->id;
$c->internal_set_data($cm, $completion, true);
$actual = $DB->get_records('course_completions', ['course' => $course->id]);
$this->assertEmpty($actual);
// Run course completions cron.
$coursecompletionid = \core_completion\api::mark_course_completions_activity_criteria();
$this->assertEquals(0, $coursecompletionid);
$actual = $DB->get_records('course_completions', ['course' => $course->id]);
if ($course->shortname == 'completionpassgradeset') {
// Only student1 has completed a course.
$this->assertEquals(1, count($actual));
$this->assertEquals($student1->id, reset($actual)->userid);
} else {
// Both students completed a course.
$this->assertEquals(2, count($actual));
$this->assertEquals($student1->id, reset($actual)->userid);
$this->assertEquals($student2->id, end($actual)->userid);
}
}
}
}
@@ -0,0 +1,168 @@
@block @block_completionstatus @javascript
Feature: Course completion state should match completion criteria
In order to understand the configuration or status of an course's completion
As a user
I need to see the appropriate completion information on course and dashboard pages
Background:
Given the following "users" exist:
| username | firstname | lastname | email | idnumber |
| teacher1 | Teacher | 1 | teacher1@example.com | T1 |
| teacher2 | Teacher | 2 | teacher1@example.com | T2 |
| student1 | Student | 1 | student1@example.com | S1 |
And the following "courses" exist:
| fullname | shortname | category | enablecompletion | showcompletionconditions |
| Course 1 | C1 | 0 | 1 | 1 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| teacher2 | C1 | teacher |
| student1 | C1 | student |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| section | 1 |
| name | Test assignment name |
| intro | Submit your online text |
| completion | 1 |
| assignsubmission_onlinetext_enabled | 1 |
| grade[modgrade_type] | Point |
| grade[modgrade_point] | 100 |
And I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
And I navigate to "Course completion" in current page administration
And I click on "Condition: Activity completion" "link"
And I set the field "Assignment - Test assignment name" to "1"
And I press "Save changes"
And I add the "Course completion status" block
And I am on the "Test assignment name" "assign activity" page
And I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Completion tracking | Show activity as complete when conditions are met |
| completionusegrade | 1 |
| completionpassgrade | 1 |
| gradepass | 70 |
And I press "Save and return to course"
And I log out
Scenario: Completion status show match completion criteria when passgrage condition is set.
Given I am on the "Course 1" course page logged in as "student1"
And the "Receive a grade" completion condition of "Test assignment name" is displayed as "todo"
And the "Receive a passing grade" completion condition of "Test assignment name" is displayed as "todo"
And I should see "Status: Not yet started" in the "Course completion status" "block"
And I am on the "Test assignment name" "assign activity" page
And I press "Add submission"
And I set the following fields to these values:
| Online text | I'm the student1 submission |
And I press "Save changes"
And I press "Submit assignment"
And I press "Continue"
And I log out
And I am on the "Test assignment name" "assign activity" page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the following fields to these values:
| Grade out of 100 | 50.0 |
And I press "Save changes"
And I am on the "Course 1" course page
And I navigate to "Reports" in current page administration
And I click on "Activity completion" "link"
And "Student 1, Test assignment name: Completed (did not achieve pass grade)" "icon" should exist in the "Student 1" "table_row"
And I navigate to "Reports" in current page administration
And I click on "Course completion" "link" in the "region-main" "region"
And "Student 1, Test assignment name: Completed (did not achieve pass grade)" "icon" should exist in the "Student 1" "table_row"
And "Student 1, Course complete: Not completed" "icon" should exist in the "Student 1" "table_row"
And I log out
When I am on the "Course 1" course page logged in as "student1"
And I should see "Status: Pending" in the "Course completion status" "block"
And the "Receive a grade" completion condition of "Test assignment name" is displayed as "done"
And the "Receive a passing grade" completion condition of "Test assignment name" is displayed as "failed"
And I am on the "My courses" page
And I should not see "100%" in the "Course overview" "block"
And I log out
And I am on the "Test assignment name" "assign activity" page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the following fields to these values:
| Grade out of 100 | 75.0 |
And I press "Save changes"
And I am on the "Course 1" course page
And I navigate to "Reports" in current page administration
And I click on "Activity completion" "link"
And "Student 1, Test assignment name: Completed (achieved pass grade)" "icon" should exist in the "Student 1" "table_row"
And I navigate to "Reports" in current page administration
And I click on "Course completion" "link" in the "region-main" "region"
And "Student 1, Test assignment name: Completed (achieved pass grade)" "icon" should exist in the "Student 1" "table_row"
And "Student 1, Course complete: Completed" "icon" should exist in the "Student 1" "table_row"
And I log out
And I am on the "Course 1" course page logged in as "student1"
And I should see "Status: Complete" in the "Course completion status" "block"
And the "Receive a grade" completion condition of "Test assignment name" is displayed as "done"
And the "Receive a passing grade" completion condition of "Test assignment name" is displayed as "done"
And I am on the "My courses" page
Then I should see "100%" in the "Course overview" "block"
Scenario: Completion status show match completion criteria when passgrage condition is not set.
Given I am on the "Course 1" course page logged in as "teacher1"
And I am on the "Test assignment name" "assign activity" page
And I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Completion tracking | Show activity as complete when conditions are met |
| completionusegrade | 1 |
| completionpassgrade | 0 |
| gradepass | 70 |
And I press "Save and return to course"
And I log out
And I am on the "Course 1" course page logged in as "student1"
And the "Receive a grade" completion condition of "Test assignment name" is displayed as "todo"
And I should see "Status: Not yet started" in the "Course completion status" "block"
And I am on the "Test assignment name" "assign activity" page
And I press "Add submission"
And I set the following fields to these values:
| Online text | I'm the student1 submission |
And I press "Save changes"
And I press "Submit assignment"
And I press "Continue"
And I log out
And I am on the "Test assignment name" "assign activity" page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the following fields to these values:
| Grade out of 100 | 50.0 |
And I press "Save changes"
And I am on the "Course 1" course page
And I navigate to "Reports" in current page administration
And I click on "Activity completion" "link"
And "Student 1, Test assignment name: Completed (did not achieve pass grade)" "icon" should exist in the "Student 1" "table_row"
And I navigate to "Reports" in current page administration
And I click on "Course completion" "link" in the "region-main" "region"
And "Student 1, Test assignment name: Completed (did not achieve pass grade)" "icon" should exist in the "Student 1" "table_row"
And "Student 1, Course complete: Completed" "icon" should exist in the "Student 1" "table_row"
And I log out
When I am on the "Course 1" course page logged in as "student1"
And I should see "Status: Complete" in the "Course completion status" "block"
# Once MDL-75582 is fixed "failed" should be changed to "done"
And the "Receive a grade" completion condition of "Test assignment name" is displayed as "failed"
And I am on the "My courses" page
And I should see "100%" in the "Course overview" "block"
And I log out
And I am on the "Test assignment name" "assign activity" page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student 1" "table_row"
And I set the following fields to these values:
| Grade out of 100 | 75.0 |
And I press "Save changes"
And I am on the "Course 1" course page
And I navigate to "Reports" in current page administration
And I click on "Activity completion" "link"
And "Student 1, Test assignment name: Completed (achieved pass grade)" "icon" should exist in the "Student 1" "table_row"
And I navigate to "Reports" in current page administration
And I click on "Course completion" "link" in the "region-main" "region"
And "Student 1, Test assignment name: Completed (achieved pass grade)" "icon" should exist in the "Student 1" "table_row"
And "Student 1, Course complete: Completed" "icon" should exist in the "Student 1" "table_row"
And I log out
And I am on the "Course 1" course page logged in as "student1"
And I should see "Status: Complete" in the "Course completion status" "block"
And the "Receive a grade" completion condition of "Test assignment name" is displayed as "done"
And I am on the "My courses" page
Then I should see "100%" in the "Course overview" "block"
+108
View File
@@ -120,6 +120,114 @@ class progress_test extends \advanced_testcase {
$this->assertEquals('100', \core_completion\progress::get_course_progress_percentage($course, $user->id));
}
/**
* Tests that the course progress percentage is returned correctly for various grade to pass settings
*
* @covers \core_completion\progress::get_course_progress_percentage.
*/
public function test_course_progress_percentage_completion_state() {
global $DB;
// Add a course that supports completion.
$course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
// Enrol a user in the course.
$teacher = $this->getDataGenerator()->create_user();
$user = $this->getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', ['shortname' => 'student']);
$teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
$this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
// Add three activities that use completion.
/** @var \mod_assign_generator $assigngenerator */
$assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$assign['passgragepassed'] = $assigngenerator->create_instance([
'course' => $course->id,
'completion' => COMPLETION_ENABLED,
'completionusegrade' => 1,
'gradepass' => 50,
'completionpassgrade' => 1
]);
$assign['passgragefailed'] = $assigngenerator->create_instance([
'course' => $course->id,
'completion' => COMPLETION_ENABLED,
'completionusegrade' => 1,
'gradepass' => 50,
'completionpassgrade' => 1
]);
$assign['passgragenotused'] = $assigngenerator->create_instance([
'course' => $course->id,
'completion' => COMPLETION_ENABLED,
'completionusegrade' => 1,
'gradepass' => 50,
]);
$assign['nograde'] = $assigngenerator->create_instance([
'course' => $course->id,
'completion' => COMPLETION_ENABLED,
]);
$c = new \completion_info($course);
foreach ($assign as $item) {
$cmassing = get_coursemodule_from_id('assign', $item->cmid);
// Add activity completion criteria.
$criteriadata = new \stdClass();
$criteriadata->id = $course->id;
$criteriadata->criteria_activity = [];
// Some activities.
$criteriadata->criteria_activity[$cmassing->id] = 1;
$criterion = new \completion_criteria_activity();
$criterion->update_config($criteriadata);
}
$this->setUser($teacher);
foreach ($assign as $key => $item) {
$cm = get_coursemodule_from_instance('assign', $item->id);
// Mark user completions.
$completion = new \stdClass();
$completion->coursemoduleid = $cm->id;
$completion->timemodified = time();
$completion->viewed = COMPLETION_NOT_VIEWED;
$completion->overrideby = null;
if ($key == 'passgragepassed') {
$completion->id = 0;
$completion->completionstate = COMPLETION_COMPLETE_PASS;
$completion->userid = $user->id;
$c->internal_set_data($cm, $completion, true);
} else if ($key == 'passgragefailed') {
$completion->id = 0;
$completion->completionstate = COMPLETION_COMPLETE_FAIL;
$completion->userid = $user->id;
$c->internal_set_data($cm, $completion, true);
} else if ($key == 'passgragenotused') {
$completion->id = 0;
$completion->completionstate = COMPLETION_COMPLETE;
$completion->userid = $user->id;
$c->internal_set_data($cm, $completion, true);
} else if ($key == 'nograde') {
$completion->id = 0;
$completion->completionstate = COMPLETION_COMPLETE;
$completion->userid = $user->id;
$c->internal_set_data($cm, $completion, true);
}
}
// Run course completions cron.
\core_completion\api::mark_course_completions_activity_criteria();
// Check we have received valid data.
// Only assign2 is not completed.
$this->assertEquals('75', \core_completion\progress::get_course_progress_percentage($course, $user->id));
}
/**
* Tests that the course progress returns null when the course does not support it.
*/