diff --git a/mod/scorm/lib.php b/mod/scorm/lib.php index 620d71e35f0..2416be80fdf 100644 --- a/mod/scorm/lib.php +++ b/mod/scorm/lib.php @@ -1449,12 +1449,30 @@ function scorm_check_mode($scorm, &$newattempt, &$attempt, $userid, &$mode) { } // Check if the scorm module is incomplete (used to validate user request to start a new attempt). $incomplete = true; + + // Note - in SCORM_13 the cmi-core.lesson_status field was split into + // 'cmi.completion_status' and 'cmi.success_status'. + // 'cmi.completion_status' can only contain values 'completed', 'incomplete', 'not attempted' or 'unknown'. + // This means the values 'passed' or 'failed' will never be reported for a track in SCORM_13 and + // the only status that will be treated as complete is 'completed'. + + $completionelements = array( + SCORM_12 => 'cmi.core.lesson_status', + SCORM_13 => 'cmi.completion_status', + SCORM_AICC => 'cmi.core.lesson_status' + ); + $scormversion = scorm_version_check($scorm->version); + if($scormversion===false) { + $scormversion = SCORM_12; + } + $completionelement = $completionelements[$scormversion]; + $sql = "SELECT sc.id, t.value FROM {scorm_scoes} sc LEFT JOIN {scorm_scoes_track} t ON sc.scorm = t.scormid AND sc.id = t.scoid - AND t.element = 'cmi.core.lesson_status' AND t.userid = ? AND t.attempt = ? + AND t.element = ? AND t.userid = ? AND t.attempt = ? WHERE sc.scormtype = 'sco' AND sc.scorm = ?"; - $tracks = $DB->get_recordset_sql($sql, array($userid, $attempt, $scorm->id)); + $tracks = $DB->get_recordset_sql($sql, array($completionelement, $userid, $attempt, $scorm->id)); foreach ($tracks as $track) { if (($track->value == 'completed') || ($track->value == 'passed') || ($track->value == 'failed')) { diff --git a/mod/scorm/tests/generator/lib.php b/mod/scorm/tests/generator/lib.php index 97435974a2e..2828a02fefa 100644 --- a/mod/scorm/tests/generator/lib.php +++ b/mod/scorm/tests/generator/lib.php @@ -45,7 +45,6 @@ class mod_scorm_generator extends testing_module_generator { $record = (array)$record + array( 'scormtype' => SCORM_TYPE_LOCAL, 'packagefile' => '', - 'packagefilepath' => $CFG->dirroot.'/mod/scorm/tests/packages/singlescobasic.zip', 'packageurl' => '', 'updatefreq' => SCORM_UPDATE_NEVER, 'popup' => 0, @@ -72,6 +71,9 @@ class mod_scorm_generator extends testing_module_generator { 'auto' => $cfgscorm->auto, 'displayactivityname' => $cfgscorm->displayactivityname ); + if (empty($record['packagefilepath'])) { + $record['packagefilepath'] = $CFG->dirroot.'/mod/scorm/tests/packages/singlescobasic.zip'; + } // The 'packagefile' value corresponds to the draft file area ID. If not specified, create from packagefilepath. if (empty($record['packagefile']) && $record['scormtype'] === SCORM_TYPE_LOCAL) { diff --git a/mod/scorm/tests/lib_test.php b/mod/scorm/tests/lib_test.php index 0fcc38ec408..9440e24d63d 100644 --- a/mod/scorm/tests/lib_test.php +++ b/mod/scorm/tests/lib_test.php @@ -67,6 +67,48 @@ class mod_scorm_lib_testcase extends externallib_advanced_testcase { $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, $this->teacherrole->id, 'manual'); } + /** Test scorm_check_mode + * + * @return void + */ + public function test_scorm_check_mode() { + global $CFG; + + $newattempt = 'on'; + $attempt = 1; + $mode = 'normal'; + scorm_check_mode($this->scorm, $newattempt, $attempt, $this->student->id, $mode); + $this->assertEquals('off', $newattempt); + + $scoes = scorm_get_scoes($this->scorm->id); + $sco = array_pop($scoes); + scorm_insert_track($this->student->id, $this->scorm->id, $sco->id, 1, 'cmi.core.lesson_status', 'completed'); + $newattempt = 'on'; + scorm_check_mode($this->scorm, $newattempt, $attempt, $this->student->id, $mode); + $this->assertEquals('on', $newattempt); + + // Now do the same with a SCORM 2004 package. + $record = new stdClass(); + $record->course = $this->course->id; + $record->packagefilepath = $CFG->dirroot.'/mod/scorm/tests/packages/RuntimeBasicCalls_SCORM20043rdEdition.zip'; + $scorm13 = $this->getDataGenerator()->create_module('scorm', $record); + $newattempt = 'on'; + $attempt = 1; + $mode = 'normal'; + scorm_check_mode($scorm13, $newattempt, $attempt, $this->student->id, $mode); + $this->assertEquals('off', $newattempt); + + $scoes = scorm_get_scoes($scorm13->id); + $sco = array_pop($scoes); + scorm_insert_track($this->student->id, $scorm13->id, $sco->id, 1, 'cmi.completion_status', 'completed'); + + $newattempt = 'on'; + $attempt = 1; + $mode = 'normal'; + scorm_check_mode($scorm13, $newattempt, $attempt, $this->student->id, $mode); + $this->assertEquals('on', $newattempt); + } + /** * Test scorm_view * @return void diff --git a/mod/scorm/tests/packages/RuntimeBasicCalls_SCORM20043rdEdition.zip b/mod/scorm/tests/packages/RuntimeBasicCalls_SCORM20043rdEdition.zip new file mode 100644 index 00000000000..417c50b42d9 Binary files /dev/null and b/mod/scorm/tests/packages/RuntimeBasicCalls_SCORM20043rdEdition.zip differ diff --git a/mod/scorm/tests/packages/readme_moodle.txt b/mod/scorm/tests/packages/readme_moodle.txt index 6c691314bc8..49898592c06 100644 --- a/mod/scorm/tests/packages/readme_moodle.txt +++ b/mod/scorm/tests/packages/readme_moodle.txt @@ -6,6 +6,7 @@ Sample Packages downloaded from http://scorm.com/scorm-explained/technical-scorm * singlescobasic.zip - Single SCO with basic runtime calls. SCORM 1.2. * singlesco_scorm12.zip - Single SCO content packaging example. SCORM 1.2. * RuntimeMinimumCalls_SCORM12.zip - Multi-SCO packaging example. SCORM 1.2. +* RuntimeBasicCalls_SCORM20043rdEdition.zip - Multi-SCO packaging example. SCORM 2004 3rd edition. These packages were downloaded from http://scorm.com/ website, the website disclaimer states that *Content on this site is licensed under a Creative