From 2c7893cf9fdb39fc2e4d80b160774cc366c56e2f Mon Sep 17 00:00:00 2001 From: Peter Dias Date: Thu, 24 Jun 2021 14:02:56 +0800 Subject: [PATCH] MDL-52206 core: Update new activity_custom_completion Update the custom_completion classes to accept the new completion criteria --- .../classes/activity_custom_completion.php | 7 +- completion/classes/cm_completion_details.php | 13 ++- .../tests/cm_completion_details_test.php | 83 +++++++++++++++--- lib/completionlib.php | 87 +++++++++++-------- .../classes/completion/custom_completion.php | 1 + .../classes/completion/custom_completion.php | 1 + .../classes/completion/custom_completion.php | 1 + .../classes/completion/custom_completion.php | 1 + .../classes/completion/custom_completion.php | 1 + .../classes/completion/custom_completion.php | 31 +++---- mod/quiz/tests/custom_completion_test.php | 41 +++++---- .../classes/completion/custom_completion.php | 1 + 12 files changed, 178 insertions(+), 90 deletions(-) diff --git a/completion/classes/activity_custom_completion.php b/completion/classes/activity_custom_completion.php index 4f06cc205ee..b7f95a42136 100644 --- a/completion/classes/activity_custom_completion.php +++ b/completion/classes/activity_custom_completion.php @@ -40,15 +40,20 @@ abstract class activity_custom_completion { /** @var int The user's ID. */ protected $userid; + /** @var array The current state of core completion */ + protected $completionstate; + /** * activity_custom_completion constructor. * * @param cm_info $cm * @param int $userid + * @param array|null $completionstate The current state of the core completion criteria */ - public function __construct(cm_info $cm, int $userid) { + public function __construct(cm_info $cm, int $userid, ?array $completionstate = null) { $this->cm = $cm; $this->userid = $userid; + $this->completionstate = $completionstate; } /** diff --git a/completion/classes/cm_completion_details.php b/completion/classes/cm_completion_details.php index d08196189a4..79004fb7da9 100644 --- a/completion/classes/cm_completion_details.php +++ b/completion/classes/cm_completion_details.php @@ -73,7 +73,11 @@ class cm_completion_details { $this->returndetails = $returndetails; $cmcompletionclass = activity_custom_completion::get_cm_completion_class($this->cminfo->modname); if ($cmcompletionclass) { - $this->cmcompletion = new $cmcompletionclass($this->cminfo, $this->userid); + $this->cmcompletion = new $cmcompletionclass( + $this->cminfo, + $this->userid, + $completioninfo->get_core_completion_state($cminfo, $userid) + ); } } @@ -128,6 +132,13 @@ class cm_completion_details { 'status' => $status, 'description' => get_string('detail_desc:receivegrade', 'completion'), ]; + + if (!is_null($this->cminfo->completionpassgrade) && $this->cminfo->completionpassgrade) { + $details['completionpassgrade'] = (object)[ + 'status' => $completiondata->passgrade ?? COMPLETION_INCOMPLETE, + 'description' => get_string('detail_desc:receivepassgrade', 'completion'), + ]; + } } if ($this->cmcompletion) { diff --git a/completion/tests/cm_completion_details_test.php b/completion/tests/cm_completion_details_test.php index bdbfcf683f9..00d660a110d 100644 --- a/completion/tests/cm_completion_details_test.php +++ b/completion/tests/cm_completion_details_test.php @@ -93,6 +93,7 @@ class cm_completion_details_test extends advanced_testcase { ['modname', $modname], ['completionview', $completionoptions['completionview'] ?? COMPLETION_VIEW_NOT_REQUIRED], ['completiongradeitemnumber', $completionoptions['completionusegrade'] ?? null], + ['completionpassgrade', $completionoptions['completionpassgrade'] ?? null], ])); return new cm_completion_details($this->completioninfo, $mockcminfo, 2); @@ -192,13 +193,13 @@ class cm_completion_details_test extends advanced_testcase { public function get_details_provider() { return [ 'No completion tracking' => [ - COMPLETION_TRACKING_NONE, null, null, [] + COMPLETION_TRACKING_NONE, null, null, null, [] ], 'Manual completion tracking' => [ - COMPLETION_TRACKING_MANUAL, null, null, [] + COMPLETION_TRACKING_MANUAL, null, null, null, [] ], 'Automatic, require view, not viewed' => [ - COMPLETION_TRACKING_AUTOMATIC, COMPLETION_INCOMPLETE, null, [ + COMPLETION_TRACKING_AUTOMATIC, COMPLETION_INCOMPLETE, null, null, [ 'completionview' => (object)[ 'status' => COMPLETION_INCOMPLETE, 'description' => get_string('detail_desc:view', 'completion'), @@ -206,7 +207,7 @@ class cm_completion_details_test extends advanced_testcase { ] ], 'Automatic, require view, viewed' => [ - COMPLETION_TRACKING_AUTOMATIC, COMPLETION_COMPLETE, null, [ + COMPLETION_TRACKING_AUTOMATIC, COMPLETION_COMPLETE, null, null, [ 'completionview' => (object)[ 'status' => COMPLETION_COMPLETE, 'description' => get_string('detail_desc:view', 'completion'), @@ -214,7 +215,7 @@ class cm_completion_details_test extends advanced_testcase { ] ], 'Automatic, require grade, incomplete' => [ - COMPLETION_TRACKING_AUTOMATIC, null, COMPLETION_INCOMPLETE, [ + COMPLETION_TRACKING_AUTOMATIC, null, COMPLETION_INCOMPLETE, null, [ 'completionusegrade' => (object)[ 'status' => COMPLETION_INCOMPLETE, 'description' => get_string('detail_desc:receivegrade', 'completion'), @@ -222,7 +223,7 @@ class cm_completion_details_test extends advanced_testcase { ] ], 'Automatic, require grade, complete' => [ - COMPLETION_TRACKING_AUTOMATIC, null, COMPLETION_COMPLETE, [ + COMPLETION_TRACKING_AUTOMATIC, null, COMPLETION_COMPLETE, null, [ 'completionusegrade' => (object)[ 'status' => COMPLETION_COMPLETE, 'description' => get_string('detail_desc:receivegrade', 'completion'), @@ -230,7 +231,7 @@ class cm_completion_details_test extends advanced_testcase { ] ], 'Automatic, require view (complete) and grade (incomplete)' => [ - COMPLETION_TRACKING_AUTOMATIC, COMPLETION_COMPLETE, COMPLETION_INCOMPLETE, [ + COMPLETION_TRACKING_AUTOMATIC, COMPLETION_COMPLETE, COMPLETION_INCOMPLETE, null, [ 'completionview' => (object)[ 'status' => COMPLETION_COMPLETE, 'description' => get_string('detail_desc:view', 'completion'), @@ -242,7 +243,7 @@ class cm_completion_details_test extends advanced_testcase { ] ], 'Automatic, require view (incomplete) and grade (complete)' => [ - COMPLETION_TRACKING_AUTOMATIC, COMPLETION_INCOMPLETE, COMPLETION_COMPLETE, [ + COMPLETION_TRACKING_AUTOMATIC, COMPLETION_INCOMPLETE, COMPLETION_COMPLETE, null, [ 'completionview' => (object)[ 'status' => COMPLETION_INCOMPLETE, 'description' => get_string('detail_desc:view', 'completion'), @@ -253,6 +254,62 @@ class cm_completion_details_test extends advanced_testcase { ] ] ], + 'Automatic, require grade, require pass grade, complete' => [ + COMPLETION_TRACKING_AUTOMATIC, null, COMPLETION_COMPLETE, COMPLETION_COMPLETE, [ + 'completionusegrade' => (object)[ + 'status' => COMPLETION_COMPLETE, + 'description' => get_string('detail_desc:receivegrade', 'completion'), + ], + 'completionpassgrade' => (object)[ + 'status' => COMPLETION_COMPLETE, + 'description' => get_string('detail_desc:receivepassgrade', 'completion'), + ], + ] + ], + 'Automatic, require grade, require pass grade, incomplete' => [ + COMPLETION_TRACKING_AUTOMATIC, null, COMPLETION_COMPLETE, COMPLETION_INCOMPLETE, [ + 'completionusegrade' => (object)[ + 'status' => COMPLETION_COMPLETE, + 'description' => get_string('detail_desc:receivegrade', 'completion'), + ], + 'completionpassgrade' => (object)[ + 'status' => COMPLETION_INCOMPLETE, + 'description' => get_string('detail_desc:receivepassgrade', 'completion'), + ], + ] + ], + 'Automatic, require view (complete), require grade(complete), require pass grade(complete)' => [ + COMPLETION_TRACKING_AUTOMATIC, COMPLETION_COMPLETE, COMPLETION_COMPLETE, COMPLETION_COMPLETE, [ + 'completionview' => (object)[ + 'status' => COMPLETION_COMPLETE, + 'description' => get_string('detail_desc:view', 'completion'), + ], + 'completionusegrade' => (object)[ + 'status' => COMPLETION_COMPLETE, + 'description' => get_string('detail_desc:receivegrade', 'completion'), + ], + 'completionpassgrade' => (object)[ + 'status' => COMPLETION_COMPLETE, + 'description' => get_string('detail_desc:receivepassgrade', 'completion'), + ], + ] + ], + 'Automatic, require view (incomplete), require grade(complete), require pass grade(complete)' => [ + COMPLETION_TRACKING_AUTOMATIC, COMPLETION_INCOMPLETE, COMPLETION_COMPLETE, COMPLETION_COMPLETE, [ + 'completionview' => (object)[ + 'status' => COMPLETION_INCOMPLETE, + 'description' => get_string('detail_desc:view', 'completion'), + ], + 'completionusegrade' => (object)[ + 'status' => COMPLETION_COMPLETE, + 'description' => get_string('detail_desc:receivegrade', 'completion'), + ], + 'completionpassgrade' => (object)[ + 'status' => COMPLETION_COMPLETE, + 'description' => get_string('detail_desc:receivepassgrade', 'completion'), + ], + ] + ], ]; } @@ -263,13 +320,16 @@ class cm_completion_details_test extends advanced_testcase { * @param int $completion The completion tracking mode. * @param int|null $completionview Completion status of the "view" completion condition. * @param int|null $completiongrade Completion status of the "must receive grade" completion condition. + * @param int|null $completionpassgrade Completion status of the "must receive passing grade" completion condition. * @param array $expecteddetails Expected completion details returned by get_details(). */ - public function test_get_details(int $completion, ?int $completionview, ?int $completiongrade, array $expecteddetails) { + public function test_get_details(int $completion, ?int $completionview, + ?int $completiongrade, ?int $completionpassgrade, array $expecteddetails) { $options = []; $getdatareturn = (object)[ 'viewed' => $completionview, 'completiongrade' => $completiongrade, + 'passgrade' => $completionpassgrade, ]; if (!is_null($completionview)) { @@ -278,13 +338,16 @@ class cm_completion_details_test extends advanced_testcase { if (!is_null($completiongrade)) { $options['completionusegrade'] = true; } + if (!is_null($completionpassgrade)) { + $options['completionpassgrade'] = true; + } $cmcompletion = $this->setup_data($completion, $options, $getdatareturn); $this->assertEquals($expecteddetails, $cmcompletion->get_details()); } /** - * Data provider for test_get_details(). + * Data provider for test_get_details_custom_order(). * @return array[] */ public function get_details_custom_order_provider() { diff --git a/lib/completionlib.php b/lib/completionlib.php index 57f1bfc15c1..e9b5007f40b 100644 --- a/lib/completionlib.php +++ b/lib/completionlib.php @@ -697,14 +697,6 @@ class completion_info { } $newstate = COMPLETION_COMPLETE; - $completionstate = []; - if ($cm->completionview == COMPLETION_VIEW_REQUIRED) { - $newstate = ($current->viewed == COMPLETION_VIEWED ? COMPLETION_COMPLETE : COMPLETION_INCOMPLETE); - $completionstate = [ - 'viewed' => $newstate - ]; - } - if ($cm instanceof stdClass) { // Modname hopefully is provided in $cm but just in case it isn't, let's grab it. if (!isset($cm->modname)) { @@ -717,35 +709,14 @@ class completion_info { } // Make sure we're using a cm_info object. $cminfo = cm_info::create($cm, $userid); - - // Check grade - if (!is_null($cminfo->completiongradeitemnumber)) { - $newstate = $this->get_grade_completion($cminfo, $userid); - $completionstate['usegrade'] = $newstate; - if ($cm->completionpassgrade) { - // If we are asking to use pass grade completion but haven't set it properly, - // then default to COMPLETION_COMPLETE_PASS. - if ($newstate == COMPLETION_COMPLETE) { - $newstate = COMPLETION_COMPLETE_PASS; - } - - // The criteria is to mark an activity as complete if a passing grade has been achieved. - // COMPLETION_COMPLETE_FAIL still marks the activity as completed which is incorrect. - // Rectify this. - if ($newstate == COMPLETION_COMPLETE_FAIL) { - $newstate = COMPLETION_INCOMPLETE; - } - - $completionstate['passgrade'] = $newstate; - } - } + $completionstate = $this->get_core_completion_state($cminfo, $userid); if (plugin_supports('mod', $cminfo->modname, FEATURE_COMPLETION_HAS_RULES)) { $response = true; $cmcompletionclass = activity_custom_completion::get_cm_completion_class($cminfo->modname); if ($cmcompletionclass) { /** @var activity_custom_completion $cmcompletion */ - $cmcompletion = new $cmcompletionclass($cminfo, $userid); + $cmcompletion = new $cmcompletionclass($cminfo, $userid, $completionstate); $response = $cmcompletion->get_overall_completion_state() != COMPLETION_INCOMPLETE; } else { // Fallback to the get_completion_state callback. @@ -1167,6 +1138,51 @@ class completion_info { return (object)$cacheddata[$cminfo->id]; } + /** + * Get the latest completion state for each criteria used in the module + * + * @param cm_info $cm The corresponding module's information + * @param int $userid The id for the user we are calculating core completion state + * @return array $data The individualised core completion state used in the module. + * Consists of the following keys completiongrade, passgrade, viewed + */ + public function get_core_completion_state(cm_info $cm, int $userid): array { + global $DB; + $data = []; + // Include in the completion info the grade completion, if necessary. + if (!is_null($cm->completiongradeitemnumber)) { + $newstate = $this->get_grade_completion($cm, $userid); + $data['completiongrade'] = $newstate; + + if ($cm->completionpassgrade) { + // If we are asking to use pass grade completion but haven't set it properly, + // then default to COMPLETION_COMPLETE_PASS. + if ($newstate == COMPLETION_COMPLETE) { + $newstate = COMPLETION_COMPLETE_PASS; + } + + // The activity is using 'passing grade' criteria therefore fail indication should be on this criteria. + // The user has received a (failing) grade so 'completiongrade' should properly indicate this. + if ($newstate == COMPLETION_COMPLETE_FAIL) { + $data['completiongrade'] = COMPLETION_COMPLETE; + } + + $data['passgrade'] = $newstate; + } + } + + // If view is required, try and fetch from the db. In some cases, cache can be invalid. + if ($cm->completionview == COMPLETION_VIEW_REQUIRED) { + $data['viewed'] = COMPLETION_INCOMPLETE; + $record = $DB->get_record('course_modules_completion', array('coursemoduleid' => $cm->id, 'userid' => $userid)); + if ($record) { + $data['viewed'] = ($record->viewed == COMPLETION_VIEWED ? COMPLETION_COMPLETE : COMPLETION_INCOMPLETE); + } + } + + return $data; + } + /** * Adds the user's custom completion data on the given course module. * @@ -1175,12 +1191,7 @@ class completion_info { * @return array The additional completion data. */ protected function get_other_cm_completion_data(cm_info $cm, int $userid): array { - $data = []; - - // Include in the completion info the grade completion, if necessary. - if (!is_null($cm->completiongradeitemnumber)) { - $data['completiongrade'] = $this->get_grade_completion($cm, $userid); - } + $data = $this->get_core_completion_state($cm, $userid); // Custom activity module completion data. @@ -1200,7 +1211,7 @@ class completion_info { } /** @var activity_custom_completion $customcmcompletion */ - $customcmcompletion = new $cmcompletionclass($cm, $userid); + $customcmcompletion = new $cmcompletionclass($cm, $userid, $data); foreach ($customdata['customcompletionrules'] as $rule => $enabled) { if (!$enabled) { // Skip inactive completion rules. diff --git a/mod/assign/classes/completion/custom_completion.php b/mod/assign/classes/completion/custom_completion.php index 79d2d0b2433..ab14b3eab80 100644 --- a/mod/assign/classes/completion/custom_completion.php +++ b/mod/assign/classes/completion/custom_completion.php @@ -89,6 +89,7 @@ class custom_completion extends activity_custom_completion { 'completionview', 'completionsubmit', 'completionusegrade', + 'completionpassgrade', ]; } } diff --git a/mod/data/classes/completion/custom_completion.php b/mod/data/classes/completion/custom_completion.php index 0f00b797762..3e1b29de066 100644 --- a/mod/data/classes/completion/custom_completion.php +++ b/mod/data/classes/completion/custom_completion.php @@ -80,6 +80,7 @@ class custom_completion extends activity_custom_completion { 'completionview', 'completionentries', 'completionusegrade', + 'completionpassgrade', ]; } } diff --git a/mod/forum/classes/completion/custom_completion.php b/mod/forum/classes/completion/custom_completion.php index ffe5b98b904..e6d90367166 100644 --- a/mod/forum/classes/completion/custom_completion.php +++ b/mod/forum/classes/completion/custom_completion.php @@ -112,6 +112,7 @@ class custom_completion extends activity_custom_completion { 'completionreplies', 'completionposts', 'completionusegrade', + 'completionpassgrade', ]; } } diff --git a/mod/glossary/classes/completion/custom_completion.php b/mod/glossary/classes/completion/custom_completion.php index 41456447213..dcdaa71616c 100644 --- a/mod/glossary/classes/completion/custom_completion.php +++ b/mod/glossary/classes/completion/custom_completion.php @@ -84,6 +84,7 @@ class custom_completion extends activity_custom_completion { 'completionview', 'completionentries', 'completionusegrade', + 'completionpassgrade', ]; } } diff --git a/mod/lesson/classes/completion/custom_completion.php b/mod/lesson/classes/completion/custom_completion.php index c3ce80d264d..ab02a71c96c 100644 --- a/mod/lesson/classes/completion/custom_completion.php +++ b/mod/lesson/classes/completion/custom_completion.php @@ -103,6 +103,7 @@ class custom_completion extends activity_custom_completion { 'completiontimespent', 'completionendreached', 'completionusegrade', + 'completionpassgrade', ]; } } diff --git a/mod/quiz/classes/completion/custom_completion.php b/mod/quiz/classes/completion/custom_completion.php index f8716043fc7..3502a92b378 100644 --- a/mod/quiz/classes/completion/custom_completion.php +++ b/mod/quiz/classes/completion/custom_completion.php @@ -48,23 +48,14 @@ class custom_completion extends activity_custom_completion { $completionpassorattempts = $this->cm->customdata['customcompletionrules']['completionpassorattemptsexhausted']; - if (empty($completionpassorattempts['completionpass'])) { + if (empty($completionpassorattempts['completionpassgrade'])) { return true; } - // Check for passing grade. - $item = grade_item::fetch([ - 'courseid' => $this->cm->get_course()->id, - 'itemtype' => 'mod', - 'itemmodule' => 'quiz', - 'iteminstance' => $this->cm->instance, - 'outcomeid' => null - ]); - if ($item) { - $grades = grade_grade::fetch_users_grades($item, [$this->userid], false); - if (!empty($grades[$this->userid]) && $grades[$this->userid]->is_passed($item)) { - return true; - } + if ($this->completionstate && + isset($this->completionstate['passgrade']) && + $this->completionstate['passgrade'] == COMPLETION_COMPLETE_PASS) { + return true; } // If a passing grade is required and exhausting all available attempts is not accepted for completion, @@ -146,18 +137,15 @@ class custom_completion extends activity_custom_completion { */ public function get_custom_rule_descriptions(): array { $minattempts = $this->cm->customdata['customcompletionrules']['completionminattempts'] ?? 0; + $description['completionminattempts'] = get_string('completiondetail:minattempts', 'mod_quiz', $minattempts); + // Completion pass grade is now part of core. Only show the following if it's combined with min attempts. $completionpassorattempts = $this->cm->customdata['customcompletionrules']['completionpassorattemptsexhausted'] ?? []; if (!empty($completionpassorattempts['completionattemptsexhausted'])) { - $passorallattemptslabel = get_string('completiondetail:passorexhaust', 'mod_quiz'); - } else { - $passorallattemptslabel = get_string('completiondetail:passgrade', 'mod_quiz'); + $description['completionpassorattemptsexhausted'] = get_string('completiondetail:passorexhaust', 'mod_quiz'); } - return [ - 'completionpassorattemptsexhausted' => $passorallattemptslabel, - 'completionminattempts' => get_string('completiondetail:minattempts', 'mod_quiz', $minattempts), - ]; + return $description; } /** @@ -170,6 +158,7 @@ class custom_completion extends activity_custom_completion { 'completionview', 'completionminattempts', 'completionusegrade', + 'completionpassgrade', 'completionpassorattemptsexhausted', ]; } diff --git a/mod/quiz/tests/custom_completion_test.php b/mod/quiz/tests/custom_completion_test.php index d47ebc332b2..7407e492677 100644 --- a/mod/quiz/tests/custom_completion_test.php +++ b/mod/quiz/tests/custom_completion_test.php @@ -20,6 +20,7 @@ namespace mod_quiz; use advanced_testcase; use cm_info; +use core_completion\cm_completion_details; use grade_item; use mod_quiz\completion\custom_completion; use question_engine; @@ -127,11 +128,8 @@ class custom_completion_test extends advanced_testcase { } /** - * Test checking the completion state of a quiz. + * Test checking the completion state of a quiz base on core's completionpassgrade criteria. * The quiz requires a passing grade to be completed. - * - * @covers ::get_state - * @covers ::get_custom_rule_descriptions */ public function test_completionpass() { list($students, $quiz, $cm) = $this->setup_quiz_for_testing_completion([ @@ -139,7 +137,7 @@ class custom_completion_test extends advanced_testcase { 'qtype' => 'numerical', 'quizoptions' => [ 'completionusegrade' => 1, - 'completionpass' => 1 + 'completionpassgrade' => 1 ] ]); @@ -153,13 +151,14 @@ class custom_completion_test extends advanced_testcase { 'tosubmit' => [1 => ['answer' => '3.14']] ]); + $completioninfo = new \completion_info($cm->get_course()); + $completiondetails = new cm_completion_details($completioninfo, $cm, (int) $passstudent->id); + // Check the results. - $customcompletion = new custom_completion($cm, (int) $passstudent->id); - $this->assertArrayHasKey('completionpassorattemptsexhausted', $cm->customdata['customcompletionrules']); - $this->assertEquals(COMPLETION_COMPLETE, $customcompletion->get_state('completionpassorattemptsexhausted')); + $this->assertEquals(COMPLETION_COMPLETE_PASS, $completiondetails->get_details()['completionpassgrade']->status); $this->assertEquals( - 'Receive a pass grade', - $customcompletion->get_custom_rule_descriptions()['completionpassorattemptsexhausted'] + 'Receive a passing grade', + $completiondetails->get_details()['completionpassgrade']->description ); // Do a failing attempt. @@ -170,13 +169,13 @@ class custom_completion_test extends advanced_testcase { 'tosubmit' => [1 => ['answer' => '0']] ]); + $completiondetails = new cm_completion_details($completioninfo, $cm, (int) $failstudent->id); + // Check the results. - $customcompletion = new custom_completion($cm, (int) $failstudent->id); - $this->assertArrayHasKey('completionpassorattemptsexhausted', $cm->customdata['customcompletionrules']); - $this->assertEquals(COMPLETION_INCOMPLETE, $customcompletion->get_state('completionpassorattemptsexhausted')); + $this->assertEquals(COMPLETION_COMPLETE_FAIL, $completiondetails->get_details()['completionpassgrade']->status); $this->assertEquals( - 'Receive a pass grade', - $customcompletion->get_custom_rule_descriptions()['completionpassorattemptsexhausted'] + 'Receive a passing grade', + $completiondetails->get_details()['completionpassgrade']->description ); } @@ -194,7 +193,7 @@ class custom_completion_test extends advanced_testcase { 'quizoptions' => [ 'attempts' => 2, 'completionusegrade' => 1, - 'completionpass' => 1, + 'completionpassgrade' => 1, 'completionattemptsexhausted' => 1 ] ]); @@ -209,8 +208,11 @@ class custom_completion_test extends advanced_testcase { 'tosubmit' => [1 => ['answer' => '3.14']] ]); + $completioninfo = new \completion_info($cm->get_course()); + // Check the results. Quiz is completed by $passstudent because of passing grade. - $customcompletion = new custom_completion($cm, (int) $passstudent->id); + $studentid = (int) $passstudent->id; + $customcompletion = new custom_completion($cm, $studentid, $completioninfo->get_core_completion_state($cm, $studentid)); $this->assertArrayHasKey('completionpassorattemptsexhausted', $cm->customdata['customcompletionrules']); $this->assertEquals(COMPLETION_COMPLETE, $customcompletion->get_state('completionpassorattemptsexhausted')); $this->assertEquals( @@ -227,7 +229,8 @@ class custom_completion_test extends advanced_testcase { ]); // Check the results. Quiz is not completed by $exhauststudent yet because of failing grade and of remaining attempts. - $customcompletion = new custom_completion($cm, (int) $exhauststudent->id); + $studentid = (int) $exhauststudent->id; + $customcompletion = new custom_completion($cm, $studentid, $completioninfo->get_core_completion_state($cm, $studentid)); $this->assertArrayHasKey('completionpassorattemptsexhausted', $cm->customdata['customcompletionrules']); $this->assertEquals(COMPLETION_INCOMPLETE, $customcompletion->get_state('completionpassorattemptsexhausted')); $this->assertEquals( @@ -244,7 +247,7 @@ class custom_completion_test extends advanced_testcase { ]); // Check the results. Quiz is completed by $exhauststudent because there are no remaining attempts. - $customcompletion = new custom_completion($cm, (int) $exhauststudent->id); + $customcompletion = new custom_completion($cm, $studentid, $completioninfo->get_core_completion_state($cm, $studentid)); $this->assertArrayHasKey('completionpassorattemptsexhausted', $cm->customdata['customcompletionrules']); $this->assertEquals(COMPLETION_COMPLETE, $customcompletion->get_state('completionpassorattemptsexhausted')); $this->assertEquals( diff --git a/mod/scorm/classes/completion/custom_completion.php b/mod/scorm/classes/completion/custom_completion.php index 9a551915a1a..c5b11058531 100644 --- a/mod/scorm/classes/completion/custom_completion.php +++ b/mod/scorm/classes/completion/custom_completion.php @@ -210,6 +210,7 @@ class custom_completion extends activity_custom_completion { 'completionstatusallscos', 'completionstatusrequired', 'completionusegrade', + 'completionpassgrade', 'completionscorerequired', ]; }