$string['activation'] = 'Activation';
$string['advanced'] = 'Parameters';
+$string['allowtypeexternal'] = 'Enable external package type';
+$string['allowtypeimsrepository'] = 'Enable IMS package type';
+$string['allowtypelocalsync'] = 'Enable downloaded package type';
+$string['areaintro'] = 'Introduction files';
+$string['areacontent'] = 'Content files';
+$string['areapackage'] = 'Package file';
$string['asset'] = 'Asset';
$string['assetlaunched'] = 'Asset - Viewed';
$string['attempt'] = 'attempt';
$string['scorm:viewreport'] = 'View reports';
$string['scorm:viewscores'] = 'View scores';
$string['scormcourse'] = 'Learning Course';
+$string['scormtype'] = 'Type';
$string['scrollbars'] = 'Allow the window to be scrolled';
$string['sided'] = 'On the left side';
$string['skipview'] = 'Student skip content structure page';
$string['totaltime'] = 'Time';
$string['trackingloose'] = 'WARNING: The tracking data of this package will be lost!';
$string['type'] = 'Type';
+$string['typeexternal'] = 'External SCORM manifest';
+$string['typeimsrepository'] = 'Local IMS content repository';
+$string['typelocal'] = 'Uploaded package';
+$string['typelocalsync'] = 'Downloaded package';
+$string['updatetime'] = 'Synchronisation time';
+$string['url'] = 'URL';
$string['validateascorm'] = 'Validate a package';
$string['validation'] = 'Validation result';
$string['validationtype'] = 'This preference set the DOMXML library used for validating SCORM Manifest. If you don\'t know leave the selected choice.';
require_once("../../config.php");
require_once('locallib.php');
-
+
$id = optional_param('id', '', PARAM_INT); // Course Module ID, or
$a = optional_param('a', '', PARAM_INT); // scorm ID
$scoid = required_param('scoid', PARAM_INT); // sco ID
print_error('missingparameter');
}
- require_login($course->id, false, $cm);
+ require_login($course, false, $cm);
if ($usertrack = scorm_get_tracks($scoid,$USER->id,$attempt)) {
if ((isset($usertrack->{'cmi.exit'}) && ($usertrack->{'cmi.exit'} != 'time-out')) || ($scorm->version != "SCORM_1.3")) {
$userdata->credit = 'credit';
} else {
$userdata->credit = 'no-credit';
- }
+ }
if ($scodatas = scorm_get_sco($scoid, SCO_DATA)) {
foreach ($scodatas as $key => $value) {
$userdata->$key = addslashes_js($value);
return $regexp;
}
-function scorm_parse_aicc($pkgdir,$scormid) {
+
+function scorm_parse_aicc($scorm) {
global $DB;
+ if (!isset($scorm->cmid)) {
+ $cm = get_coursemodule_from_instance('scorm', $scorm->id);
+ $scorm->cmid = $cm->id;
+ }
+ $context = get_context_instance(COURSE_MODULE, $scorm->cmid);
+
+ $fs = get_file_storage();
+
+ $files = $fs->get_area_files($context->id, 'scorm_content', 0, '', false);
+
+
$version = 'AICC';
$ids = array();
$courses = array();
$extaiccfiles = array('crs','des','au','cst','ort','pre','cmp');
- if ($handle = opendir($pkgdir)) {
- while (($file = readdir($handle)) !== false) {
- if ($file[0] != '.') {
- $ext = substr($file,strrpos($file,'.'));
- $extension = strtolower(substr($ext,1));
- if (in_array($extension,$extaiccfiles)) {
- $id = strtolower(basename($file,$ext));
- $ids[$id]->$extension = $file;
- }
- }
+
+ foreach ($files as $file) {
+ $filename = $file->get_filename();
+ $ext = substr($filename,strrpos($filename,'.'));
+ $extension = strtolower(substr($ext,1));
+ if (in_array($extension,$extaiccfiles)) {
+ $id = strtolower(basename($filename,$ext));
+ $ids[$id]->$extension = $file;
}
- closedir($handle);
}
+
foreach ($ids as $courseid => $id) {
if (isset($id->crs)) {
- if (is_file($pkgdir.'/'.$id->crs)) {
- $rows = file($pkgdir.'/'.$id->crs);
- foreach ($rows as $row) {
- if (preg_match("/^(.+)=(.+)$/",$row,$matches)) {
- switch (strtolower(trim($matches[1]))) {
- case 'course_id':
- $courses[$courseid]->id = trim($matches[2]);
- break;
- case 'course_title':
- $courses[$courseid]->title = trim($matches[2]);
- break;
- case 'version':
- $courses[$courseid]->version = 'AICC_'.trim($matches[2]);
- break;
- }
+ $rows = $id->crs->get_content();
+ foreach ($rows as $row) {
+ if (preg_match("/^(.+)=(.+)$/",$row,$matches)) {
+ switch (strtolower(trim($matches[1]))) {
+ case 'course_id':
+ $courses[$courseid]->id = trim($matches[2]);
+ break;
+ case 'course_title':
+ $courses[$courseid]->title = trim($matches[2]);
+ break;
+ case 'version':
+ $courses[$courseid]->version = 'AICC_'.trim($matches[2]);
+ break;
}
}
}
}
if (isset($id->des)) {
- $rows = file($pkgdir.'/'.$id->des);
+ $rows = $id->des->get_content();
$columns = scorm_get_aicc_columns($rows[0]);
$regexp = scorm_forge_cols_regexp($columns->columns);
for ($i=1;$i<count($rows);$i++) {
}
}
if (isset($id->au)) {
- $rows = file($pkgdir.'/'.$id->au);
+ $rows = $id->au->get_content();
$columns = scorm_get_aicc_columns($rows[0]);
$regexp = scorm_forge_cols_regexp($columns->columns);
for ($i=1;$i<count($rows);$i++) {
}
}
if (isset($id->cst)) {
- $rows = file($pkgdir.'/'.$id->cst);
+ $rows = $id->cst->get_content();
$columns = scorm_get_aicc_columns($rows[0],'block');
$regexp = scorm_forge_cols_regexp($columns->columns,'(.+)?,');
for ($i=1;$i<count($rows);$i++) {
}
}
if (isset($id->ort)) {
- $rows = file($pkgdir.'/'.$id->ort);
+ $rows = $id->ort->get_content();
$columns = scorm_get_aicc_columns($rows[0],'course_element');
$regexp = scorm_forge_cols_regexp($columns->columns,'(.+)?,');
for ($i=1;$i<count($rows);$i++) {
}
}
if (isset($id->pre)) {
- $rows = file($pkgdir.'/'.$id->pre);
+ $rows = $id->pre->get_content();
$columns = scorm_get_aicc_columns($rows[0],'structure_element');
$regexp = scorm_forge_cols_regexp($columns->columns,'(.+),');
for ($i=1;$i<count($rows);$i++) {
}
}
if (isset($id->cmp)) {
- $rows = file($pkgdir.'/'.$id->cmp);
+ $rows = $id->cmp->get_content();
}
}
//print_r($courses);
- $oldscoes = $DB->get_records('scorm_scoes', array('scorm'=>$scormid));
+ $oldscoes = $DB->get_records('scorm_scoes', array('scorm'=>$scorm->id));
$launch = 0;
if (isset($courses)) {
foreach ($courses as $course) {
$sco = new object();
$sco->identifier = $course->id;
- $sco->scorm = $scormid;
+ $sco->scorm = $scorm->id;
$sco->organization = '';
$sco->title = $course->title;
$sco->parent = '/';
$sco->scormtype = '';
//print_r($sco);
- if ($ss = $DB->get_record('scorm_scoes', array('scorm'=>$scormid,'identifier'=>$sco->identifier))) {
+ if ($ss = $DB->get_record('scorm_scoes', array('scorm'=>$scorm->id,'identifier'=>$sco->identifier))) {
$id = $ss->id;
$DB->update_record('scorm_scoes',$sco);
unset($oldscoes[$id]);
foreach($course->elements as $element) {
unset($sco);
$sco->identifier = $element->system_id;
- $sco->scorm = $scormid;
+ $sco->scorm = $scorm->id;
$sco->organization = $course->id;
$sco->title = $element->title;
$DB->delete_records('scorm_scoes_track', array('scoid'=>$oldsco->id));
}
}
- $DB->set_field('scorm','version','AICC', array('id'=>$scormid));
- return $launch;
+
+ $scorm->version = 'AICC';
+
+ $scorm->launch = $launch;
+
+ return true;
}
function scorm_get_toc($user,$scorm,$liststyle,$currentorg='',$scoid='',$mode='normal',$attempt='',$play=false) {
return $scoes;
}
-function scorm_parse_scorm($pkgdir,$scormid) {
+function scorm_parse_scorm($scorm, $manifest) {
global $CFG, $DB;
-
- $launch = 0;
- $manifestfile = $pkgdir.'/imsmanifest.xml';
- if (is_file($manifestfile)) {
+ // load manifest into string
+ if ($manifest instanceof stored_file) {
+ $xmltext = $manifest->get_content();
+ } else {
+ require_once "$CFG->libdir/filelib.php";
+ $xmltext = download_file_content($manifest);
+ }
- $xmltext = file_get_contents($manifestfile);
+ $launch = 0;
- $pattern = '/&(?!\w{2,6};)/';
- $replacement = '&';
- $xmltext = preg_replace($pattern, $replacement, $xmltext);
+ $pattern = '/&(?!\w{2,6};)/';
+ $replacement = '&';
+ $xmltext = preg_replace($pattern, $replacement, $xmltext);
- $objXML = new xml2Array();
- $manifests = $objXML->parse($xmltext);
+ $objXML = new xml2Array();
+ $manifests = $objXML->parse($xmltext);
//print_object($manifests);
- $scoes = new stdClass();
- $scoes->version = '';
- $scoes = scorm_get_manifest($manifests,$scoes);
+ $scoes = new stdClass();
+ $scoes->version = '';
+ $scoes = scorm_get_manifest($manifests,$scoes);
//print_object($scoes);
- if (count($scoes->elements) > 0) {
- $olditems = $DB->get_records('scorm_scoes', array('scorm'=>$scormid));
- foreach ($scoes->elements as $manifest => $organizations) {
- foreach ($organizations as $organization => $items) {
- foreach ($items as $identifier => $item) {
- // This new db mngt will support all SCORM future extensions
- $newitem = new stdClass();
- $newitem->scorm = $scormid;
- $newitem->manifest = $manifest;
- $newitem->organization = $organization;
- $standarddatas = array('parent', 'identifier', 'launch', 'scormtype', 'title');
- foreach ($standarddatas as $standarddata) {
- if (isset($item->$standarddata)) {
- $newitem->$standarddata = $item->$standarddata;
- }
+ if (count($scoes->elements) > 0) {
+ $olditems = $DB->get_records('scorm_scoes', array('scorm'=>$scorm->id));
+ foreach ($scoes->elements as $manifest => $organizations) {
+ foreach ($organizations as $organization => $items) {
+ foreach ($items as $identifier => $item) {
+ // This new db mngt will support all SCORM future extensions
+ $newitem = new stdClass();
+ $newitem->scorm = $scorm->id;
+ $newitem->manifest = $manifest;
+ $newitem->organization = $organization;
+ $standarddatas = array('parent', 'identifier', 'launch', 'scormtype', 'title');
+ foreach ($standarddatas as $standarddata) {
+ if (isset($item->$standarddata)) {
+ $newitem->$standarddata = $item->$standarddata;
}
-
- // Insert the new SCO, and retain the link between the old and new for later adjustment
- $id = $DB->insert_record('scorm_scoes',$newitem);
- if (!empty($olditems) && ($olditemid = scorm_array_search('identifier',$newitem->identifier,$olditems))) {
- $olditems[$olditemid]->newid = $id;
- }
-
- if ($optionaldatas = scorm_optionals_data($item,$standarddatas)) {
- $data = new stdClass();
- $data->scoid = $id;
- foreach ($optionaldatas as $optionaldata) {
- if (isset($item->$optionaldata)) {
- $data->name = $optionaldata;
- $data->value = $item->$optionaldata;
- $dataid = $DB->insert_record('scorm_scoes_data',$data);
- }
+ }
+
+ // Insert the new SCO, and retain the link between the old and new for later adjustment
+ $id = $DB->insert_record('scorm_scoes',$newitem);
+ if (!empty($olditems) && ($olditemid = scorm_array_search('identifier',$newitem->identifier,$olditems))) {
+ $olditems[$olditemid]->newid = $id;
+ }
+
+ if ($optionaldatas = scorm_optionals_data($item,$standarddatas)) {
+ $data = new stdClass();
+ $data->scoid = $id;
+ foreach ($optionaldatas as $optionaldata) {
+ if (isset($item->$optionaldata)) {
+ $data->name = $optionaldata;
+ $data->value = $item->$optionaldata;
+ $dataid = $DB->insert_record('scorm_scoes_data',$data);
}
}
+ }
- if (isset($item->sequencingrules)) {
- foreach($item->sequencingrules as $sequencingrule) {
- $rule = new stdClass();
- $rule->scoid = $id;
- $rule->ruletype = $sequencingrule->type;
- $rule->conditioncombination = $sequencingrule->conditioncombination;
- $rule->action = $sequencingrule->action;
- $ruleid = $DB->insert_record('scorm_seq_ruleconds',$rule);
- if (isset($sequencingrule->ruleconditions)) {
- foreach($sequencingrule->ruleconditions as $rulecondition) {
- $rulecond = new stdClass();
- $rulecond->scoid = $id;
- $rulecond->ruleconditionsid = $ruleid;
- $rulecond->referencedobjective = $rulecondition->referencedobjective;
- $rulecond->measurethreshold = $rulecondition->measurethreshold;
- $rulecond->cond = $rulecondition->cond;
- $rulecondid = $DB->insert_record('scorm_seq_rulecond',$rulecond);
- }
+ if (isset($item->sequencingrules)) {
+ foreach($item->sequencingrules as $sequencingrule) {
+ $rule = new stdClass();
+ $rule->scoid = $id;
+ $rule->ruletype = $sequencingrule->type;
+ $rule->conditioncombination = $sequencingrule->conditioncombination;
+ $rule->action = $sequencingrule->action;
+ $ruleid = $DB->insert_record('scorm_seq_ruleconds',$rule);
+ if (isset($sequencingrule->ruleconditions)) {
+ foreach($sequencingrule->ruleconditions as $rulecondition) {
+ $rulecond = new stdClass();
+ $rulecond->scoid = $id;
+ $rulecond->ruleconditionsid = $ruleid;
+ $rulecond->referencedobjective = $rulecondition->referencedobjective;
+ $rulecond->measurethreshold = $rulecondition->measurethreshold;
+ $rulecond->cond = $rulecondition->cond;
+ $rulecondid = $DB->insert_record('scorm_seq_rulecond',$rulecond);
}
- }
- }
-
- if (isset($item->rolluprules)) {
- foreach($item->rolluprules as $rolluprule) {
- $rollup = new stdClass();
- $rollup->scoid = $id;
- $rollup->childactivityset = $rolluprule->childactivityset;
- $rollup->minimumcount = $rolluprule->minimumcount;
- $rollup->minimumpercent = $rolluprule->minimumpercent;
- $rollup->rollupruleaction = $rolluprule->rollupruleaction;
- $rollup->conditioncombination = $rolluprule->conditioncombination;
-
- $rollupruleid = $DB->insert_record('scorm_seq_rolluprule',$rollup);
- if (isset($rollup->conditions)) {
- foreach($rollup->conditions as $condition){
- $cond = new stdClass();
- $cond->scoid = $rollup->scoid;
- $cond->rollupruleid = $rollupruleid;
- $cond->operator = $condition->operator;
- $cond->cond = $condition->cond;
- $conditionid = $DB->insert_record('scorm_seq_rolluprulecond',$cond);
- }
+ }
+ }
+ }
+
+ if (isset($item->rolluprules)) {
+ foreach($item->rolluprules as $rolluprule) {
+ $rollup = new stdClass();
+ $rollup->scoid = $id;
+ $rollup->childactivityset = $rolluprule->childactivityset;
+ $rollup->minimumcount = $rolluprule->minimumcount;
+ $rollup->minimumpercent = $rolluprule->minimumpercent;
+ $rollup->rollupruleaction = $rolluprule->rollupruleaction;
+ $rollup->conditioncombination = $rolluprule->conditioncombination;
+
+ $rollupruleid = $DB->insert_record('scorm_seq_rolluprule',$rollup);
+ if (isset($rollup->conditions)) {
+ foreach($rollup->conditions as $condition){
+ $cond = new stdClass();
+ $cond->scoid = $rollup->scoid;
+ $cond->rollupruleid = $rollupruleid;
+ $cond->operator = $condition->operator;
+ $cond->cond = $condition->cond;
+ $conditionid = $DB->insert_record('scorm_seq_rolluprulecond',$cond);
}
- }
- }
+ }
+ }
+ }
- if (isset($item->objectives)) {
- foreach($item->objectives as $objective) {
- $obj = new stdClass();
- $obj->scoid = $id;
- $obj->primaryobj = $objective->primaryobj;
- $obj->satisfiedbumeasure = $objective->satisfiedbymeasure;
- $obj->objectiveid = $objective->objectiveid;
- $obj->minnormalizedmeasure = $objective->minnormalizedmeasure;
- $objectiveid = $DB->insert_record('scorm_seq_objective',$obj);
- if (isset($objective->mapinfos)) {
+ if (isset($item->objectives)) {
+ foreach($item->objectives as $objective) {
+ $obj = new stdClass();
+ $obj->scoid = $id;
+ $obj->primaryobj = $objective->primaryobj;
+ $obj->satisfiedbumeasure = $objective->satisfiedbymeasure;
+ $obj->objectiveid = $objective->objectiveid;
+ $obj->minnormalizedmeasure = $objective->minnormalizedmeasure;
+ $objectiveid = $DB->insert_record('scorm_seq_objective',$obj);
+ if (isset($objective->mapinfos)) {
//print_object($objective->mapinfos);
- foreach($objective->mapinfos as $objmapinfo) {
- $mapinfo = new stdClass();
- $mapinfo->scoid = $id;
- $mapinfo->objectiveid = $objectiveid;
- $mapinfo->targetobjectiveid = $objmapinfo->targetobjectiveid;
- $mapinfo->readsatisfiedstatus = $objmapinfo->readsatisfiedstatus;
- $mapinfo->writesatisfiedstatus = $objmapinfo->writesatisfiedstatus;
- $mapinfo->readnormalizedmeasure = $objmapinfo->readnormalizedmeasure;
- $mapinfo->writenormalizedmeasure = $objmapinfo->writenormalizedmeasure;
- $mapinfoid = $DB->insert_record('scorm_seq_mapinfo',$mapinfo);
- }
+ foreach($objective->mapinfos as $objmapinfo) {
+ $mapinfo = new stdClass();
+ $mapinfo->scoid = $id;
+ $mapinfo->objectiveid = $objectiveid;
+ $mapinfo->targetobjectiveid = $objmapinfo->targetobjectiveid;
+ $mapinfo->readsatisfiedstatus = $objmapinfo->readsatisfiedstatus;
+ $mapinfo->writesatisfiedstatus = $objmapinfo->writesatisfiedstatus;
+ $mapinfo->readnormalizedmeasure = $objmapinfo->readnormalizedmeasure;
+ $mapinfo->writenormalizedmeasure = $objmapinfo->writenormalizedmeasure;
+ $mapinfoid = $DB->insert_record('scorm_seq_mapinfo',$mapinfo);
}
}
}
+ }
//print_object($item);
- if (($launch == 0) && ((empty($scoes->defaultorg)) || ($scoes->defaultorg == $identifier))) {
- $launch = $id;
- }
+ if (($launch == 0) && ((empty($scoes->defaultorg)) || ($scoes->defaultorg == $identifier))) {
+ $launch = $id;
}
}
}
- if (!empty($olditems)) {
- foreach($olditems as $olditem) {
- $DB->delete_records('scorm_scoes', array('id'=>$olditem->id));
- $DB->delete_records('scorm_scoes_data',array('scoid'=>$olditem->id));
- if (isset($olditem->newid)) {
- $DB->set_field('scorm_scoes_track', 'scoid', $olditem->newid, array('scoid' => $olditem->id));
- }
- $DB->delete_records('scorm_scoes_track',array('scoid'=>$olditem->id));
- $DB->delete_records('scorm_seq_objective', array('scoid'=>$olditem->id));
- $DB->delete_records('scorm_seq_mapinfo', array('scoid'=>$olditem->id));
- $DB->delete_records('scorm_seq_ruleconds', array('scoid'=>$olditem->id));
- $DB->delete_records('scorm_seq_rulecond', array('scoid'=>$olditem->id));
- $DB->delete_records('scorm_seq_rolluprule', array('scoid'=>$olditem->id));
- $DB->delete_records('scorm_seq_rolluprulecond', array('scoid'=>$olditem->id));
+ }
+ if (!empty($olditems)) {
+ foreach($olditems as $olditem) {
+ $DB->delete_records('scorm_scoes', array('id'=>$olditem->id));
+ $DB->delete_records('scorm_scoes_data',array('scoid'=>$olditem->id));
+ if (isset($olditem->newid)) {
+ $DB->set_field('scorm_scoes_track', 'scoid', $olditem->newid, array('scoid' => $olditem->id));
}
+ $DB->delete_records('scorm_scoes_track',array('scoid'=>$olditem->id));
+ $DB->delete_records('scorm_seq_objective', array('scoid'=>$olditem->id));
+ $DB->delete_records('scorm_seq_mapinfo', array('scoid'=>$olditem->id));
+ $DB->delete_records('scorm_seq_ruleconds', array('scoid'=>$olditem->id));
+ $DB->delete_records('scorm_seq_rulecond', array('scoid'=>$olditem->id));
+ $DB->delete_records('scorm_seq_rolluprule', array('scoid'=>$olditem->id));
+ $DB->delete_records('scorm_seq_rolluprulecond', array('scoid'=>$olditem->id));
}
- $DB->set_field('scorm','version',$scoes->version, array('id'=>$scormid));
}
- }
+ $scorm->version = $scoes->version;
+ }
- return $launch;
+ $scorm->launch = $launch;
+
+ return true;
}
function scorm_optionals_data($item, $standarddata) {
<?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="mod/scorm/db" VERSION="20070124" COMMENT="XMLDB file for Moodle mod/scorm"
+<XMLDB PATH="mod/scorm/db" VERSION="20080903" COMMENT="XMLDB file for Moodle mod/scorm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" ENUM="false" NEXT="course"/>
<FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="id" NEXT="name"/>
- <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="course" NEXT="reference"/>
- <FIELD NAME="reference" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="name" NEXT="summary"/>
+ <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="course" NEXT="scormtype"/>
+ <FIELD NAME="scormtype" TYPE="char" LENGTH="50" NOTNULL="true" DEFAULT="local" SEQUENCE="false" ENUM="false" COMMENT="local, external or repository" PREVIOUS="name" NEXT="reference"/>
+ <FIELD NAME="reference" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="scormtype" NEXT="summary"/>
<FIELD NAME="summary" TYPE="text" LENGTH="small" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="reference" NEXT="version"/>
<FIELD NAME="version" TYPE="char" LENGTH="9" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="summary" NEXT="maxgrade"/>
<FIELD NAME="maxgrade" TYPE="float" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="version" NEXT="grademethod"/>
<FIELD NAME="grademethod" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="maxgrade" NEXT="whatgrade"/>
<FIELD NAME="whatgrade" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="grademethod" NEXT="maxattempt"/>
<FIELD NAME="maxattempt" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="1" SEQUENCE="false" ENUM="false" PREVIOUS="whatgrade" NEXT="updatefreq"/>
- <FIELD NAME="updatefreq" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="Define when the package must be automatically update" PREVIOUS="maxattempt" NEXT="md5hash"/>
- <FIELD NAME="md5hash" TYPE="char" LENGTH="32" NOTNULL="true" SEQUENCE="false" ENUM="false" COMMENT="MD5 Hash of package file" PREVIOUS="updatefreq" NEXT="launch"/>
- <FIELD NAME="launch" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="md5hash" NEXT="skipview"/>
+ <FIELD NAME="updatefreq" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="Define when the package must be automatically update" PREVIOUS="maxattempt" NEXT="sha1hash"/>
+ <FIELD NAME="sha1hash" TYPE="char" LENGTH="40" NOTNULL="false" SEQUENCE="false" ENUM="false" COMMENT="pacakge content or ext path hash" PREVIOUS="updatefreq" NEXT="md5hash"/>
+ <FIELD NAME="md5hash" TYPE="char" LENGTH="32" NOTNULL="true" SEQUENCE="false" ENUM="false" COMMENT="MD5 Hash of package file" PREVIOUS="sha1hash" NEXT="revision"/>
+ <FIELD NAME="revision" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="revison number" PREVIOUS="md5hash" NEXT="launch"/>
+ <FIELD NAME="launch" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="revision" NEXT="skipview"/>
<FIELD NAME="skipview" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="true" DEFAULT="1" SEQUENCE="false" ENUM="false" PREVIOUS="launch" NEXT="hidebrowse"/>
<FIELD NAME="hidebrowse" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="skipview" NEXT="hidetoc"/>
<FIELD NAME="hidetoc" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="hidebrowse" NEXT="hidenav"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="height"/>
</FIELDS>
<KEYS>
- <KEY NAME="primary" TYPE="primary" FIELDS="id" />
+ <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
</KEYS>
<INDEXES>
<INDEX NAME="course" UNIQUE="false" FIELDS="course"/>
</SENTENCES>
</STATEMENT>
</STATEMENTS>
-</XMLDB>
+</XMLDB>
\ No newline at end of file
<?php //$Id$
-// This file keeps track of upgrades to
+// This file keeps track of upgrades to
// the scorm module
//
// Sometimes, changes between versions involve
$table = new xmldb_table('scorm');
$field = new xmldb_field('whatgrade');
$field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'grademethod');
-
+
/// Launch add field whatgrade
if (!$dbman->field_exists($table,$field)) {
$dbman->add_field($table, $field);
}
-
+
upgrade_mod_savepoint($result, 2008073000, 'scorm');
}
-
+
+ if ($result && $oldversion < 2008082500) {
+
+ /// Define field scormtype to be added to scorm
+ $table = new xmldb_table('scorm');
+ $field = new xmldb_field('scormtype', XMLDB_TYPE_CHAR, '50', null, XMLDB_NOTNULL, null, null, null, 'local', 'name');
+
+ /// Launch add field scormtype
+ $dbman->add_field($table, $field);
+
+ /// scorm savepoint reached
+ upgrade_mod_savepoint($result, 2008082500, 'scorm');
+ }
+
+ if ($result && $oldversion < 2008090300) {
+
+ /// Define field sha1hash to be added to scorm
+ $table = new xmldb_table('scorm');
+ $field = new xmldb_field('sha1hash', XMLDB_TYPE_CHAR, '40', null, null, null, null, null, null, 'updatefreq');
+
+ /// Launch add field sha1hash
+ $dbman->add_field($table, $field);
+
+ /// scorm savepoint reached
+ upgrade_mod_savepoint($result, 2008090300, 'scorm');
+ }
+
+ if ($result && $oldversion < 2008090301) {
+
+ /// Define field revision to be added to scorm
+ $table = new xmldb_table('scorm');
+ $field = new xmldb_field('revision', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'md5hash');
+
+ /// Launch add field revision
+ $dbman->add_field($table, $field);
+
+ /// scorm savepoint reached
+ upgrade_mod_savepoint($result, 2008090301, 'scorm');
+ }
+
+ if ($result && $oldversion < 2008090302) {
+ $sql = "UPDATE {scorm}
+ SET scormtype = 'external'
+ WHERE reference LIKE ? OR reference LIKE ? OR reference LIKE ?";
+ $DB->execute($sql, array('http://%imsmanifest.xml', 'https://%imsmanifest.xml', 'www.%imsmanifest.xml'));
+
+ $sql = "UPDATE {scorm}
+ SET scormtype = 'localsync'
+ WHERE reference LIKE ? OR reference LIKE ? OR reference LIKE ?
+ OR reference LIKE ? OR reference LIKE ? OR reference LIKE ?";
+ $DB->execute($sql, array('http://%.zip', 'https://%.zip', 'www.%.zip', 'http://%.pif', 'https://%.pif', 'www.%.pif'));
+
+ $sql = "UPDATE {scorm} SET scormtype = 'imsrepository' WHERE reference LIKE ?";
+ $DB->execute($sql, array('#%'));
+
+ /// scorm savepoint reached
+ upgrade_mod_savepoint($result, 2008090302, 'scorm');
+ }
+
+ if ($result && $oldversion < 2008090303) {
+ //remove obsoleted config settings
+ unset_config('scorm_advancedsettings');
+ unset_config('scorm_windowsettings');
+
+ /// scorm savepoint reached
+ upgrade_mod_savepoint($result, 2008090303, 'scorm');
+ }
+
+ if ($result && $oldversion < 2008090304) {
+
+ /////////////////////////////////////
+ /// new file storage upgrade code ///
+ /////////////////////////////////////
+
+ function scorm_migrate_content_files($context, $base, $path) {
+ global $CFG;
+
+ $fullpathname = $base.$path;
+ $fs = get_file_storage();
+ $filearea = 'scorm_content';
+ $items = new DirectoryIterator($fullpathname);
+
+ foreach ($items as $item) {
+ if ($item->isDot()) {
+ unset($item); // release file handle
+ continue;
+ }
+
+ if ($item->isLink()) {
+ // do not follow symlinks - they were never supported in moddata, sorry
+ unset($item); // release file handle
+ continue;
+ }
+
+ if ($item->isFile()) {
+ if (!$item->isReadable()) {
+ notify(" File not readable, skipping: ".$fullpathname.$item->getFilename());
+ unset($item); // release file handle
+ continue;
+ }
+
+ $filepath = clean_param($path, PARAM_PATH);
+ $filename = clean_param($item->getFilename(), PARAM_FILE);
+ $oldpathname = $fullpathname.$item->getFilename();
+
+ if ($filename === '') {
+ continue;
+ unset($item); // release file handle
+ }
+
+ if (!$fs->file_exists($context->id, $filearea, '0', $filepath, $filename)) {
+ $file_record = array('contextid'=>$context->id, 'filearea'=>$filearea, 'itemid'=>0, 'filepath'=>$filepath, 'filename'=>$filename,
+ 'timecreated'=>$item->getCTime(), 'timemodified'=>$item->getMTime());
+ unset($item); // release file handle
+ if ($fs->create_file_from_pathname($file_record, $oldpathname)) {
+ @unlink($oldpathname);
+ }
+ } else {
+ unset($item); // release file handle
+ }
+
+ } else {
+ //migrate recursively all subdirectories
+ $oldpathname = $fullpathname.$item->getFilename().'/';
+ $subpath = $path.$item->getFilename().'/';
+ unset($item); // release file handle
+ scorm_migrate_content_files($context, $base, $subpath);
+ @rmdir($oldpathname); // deletes dir if empty
+ }
+ }
+ unset($items); //release file handles
+ }
+
+ $fs = get_file_storage();
+
+ $sqlfrom = "FROM {scorm} s
+ JOIN {modules} m ON m.name = 'scorm'
+ JOIN {course_modules} cm ON (cm.module = m.id AND cm.instance = s.id)";
+
+ $count = $DB->count_records_sql("SELECT COUNT('x') $sqlfrom");
+
+ if ($rs = $DB->get_recordset_sql("SELECT s.id, s.scormtype, s.reference, s.course, cm.id AS cmid $sqlfrom ORDER BY s.course, s.id")) {
+
+ $pbar = new progress_bar('migratescormfiles', 500, true);
+
+ $olddebug = $DB->get_debug();
+ $DB->set_debug(false); // lower debug level, there might be many files
+ $i = 0;
+ foreach ($rs as $scorm) {
+ $i++;
+ upgrade_set_timeout(180); // set up timeout, may also abort execution
+ $pbar->update($i, $count, "Migrating scorm files - $i/$count.");
+
+ $context = get_context_instance(CONTEXT_MODULE, $scorm->cmid);
+ $coursecontext = get_context_instance(CONTEXT_COURSE, $scorm->course);
+
+ // first copy local packages if found - do not delete in case they are shared ;-)
+ if ($scorm->scormtype === 'local' and preg_match('/.*(\.zip|\.pif)$/i', $scorm->reference)) {
+ $packagefile = '/'.clean_param($scorm->reference, PARAM_PATH);
+ $pathnamehash = sha1($coursecontext->id.'course_content0'.$packagefile);
+ if ($file = $fs->get_file_by_hash($pathnamehash)) {
+ $file_record = array('scontextid'=>$context->id, 'filearea'=>'scorm_pacakge',
+ 'itemid'=>0, 'filepath'=>'/');
+ $packagefile = $fs->create_file_from_storedfile($file_record, $file);
+ $scorm->reference = $packagefile->get_filename();
+ } else {
+ $scorm->reference = '';
+ }
+ $DB->update_record('scorm', $scorm);
+ }
+
+ // now migrate the extracted package
+ $basepath = "$CFG->dataroot/$scorm->course/$CFG->moddata/scorm/$scorm->id";
+ if (!is_dir($basepath)) {
+ //no files?
+ continue;
+ }
+
+ scorm_migrate_content_files($context, $basepath, '/');
+
+ // remove dirs if empty
+ @rmdir("$CFG->dataroot/$scorm->course/$CFG->moddata/scorm/$scorm->id/");
+ @rmdir("$CFG->dataroot/$scorm->course/$CFG->moddata/scorm/");
+ @rmdir("$CFG->dataroot/$scorm->course/$CFG->moddata/");
+ }
+ $DB->set_debug($olddebug); // reset debug level
+ $rs->close();
+ }
+
+ /// scorm savepoint reached
+ upgrade_mod_savepoint($result, 2008090304, 'scorm');
+ }
+
return $result;
}
<?php // $Id$
+define('SCORM_TYPE_LOCAL', 'local');
+define('SCORM_TYPE_LOCALSYNC', 'localsync');
+define('SCORM_TYPE_EXTERNAL', 'external');
+define('SCORM_TYPE_IMSREPOSITORY', 'imsrepository');
+
+
/**
* Given an object containing all the necessary data,
* (defined by the form in mod_form.php) this function
* will create a new instance and return the id number
* of the new instance.
*
-* @param mixed $scorm Form data
-* @return int
+* @param object $scorm Form data
+* @param object $mform
+* @return int new instance id
*/
-//require_once('locallib.php');
-function scorm_add_instance($scorm) {
+
+function scorm_add_instance($scorm, $mform=null) {
global $CFG, $DB;
require_once('locallib.php');
- if (($packagedata = scorm_check_package($scorm)) != null) {
- $scorm->pkgtype = $packagedata->pkgtype;
- $scorm->datadir = $packagedata->datadir;
- $scorm->launch = $packagedata->launch;
- $scorm->parse = 1;
+ $cmid = $scorm->coursemodule;
+ $cmidnumber = $scorm->cmidnumber;
+ $courseid = $scorm->course;
- $scorm->timemodified = time();
- if (!scorm_external_link($scorm->reference)) {
- $scorm->md5hash = md5_file($CFG->dataroot.'/'.$scorm->course.'/'.$scorm->reference);
- } else {
- $scorm->dir = $CFG->dataroot.'/'.$scorm->course.'/moddata/scorm';
- $scorm->md5hash = md5_file($scorm->dir.$scorm->datadir.'/'.basename($scorm->reference));
- }
+ $context = get_context_instance(CONTEXT_MODULE, $cmid);
- $scorm = scorm_option2text($scorm);
- $scorm->width = str_replace('%','',$scorm->width);
- $scorm->height = str_replace('%','',$scorm->height);
+ $scorm = scorm_option2text($scorm);
+ $scorm->width = (int)str_replace('%', '', $scorm->width);
+ $scorm->height = (int)str_replace('%', '', $scorm->height);
- //sanitize submitted values a bit
- $scorm->width = clean_param($scorm->width, PARAM_INT);
- $scorm->height = clean_param($scorm->height, PARAM_INT);
+ if (!isset($scorm->whatgrade)) {
+ $scorm->whatgrade = 0;
+ }
+ $scorm->grademethod = ($scorm->whatgrade * 10) + $scorm->grademethod;
- if (!isset($scorm->whatgrade)) {
- $scorm->whatgrade = 0;
- }
- $scorm->grademethod = ($scorm->whatgrade * 10) + $scorm->grademethod;
+ if (!$id = $DB->insert_record('scorm', $scorm)) {
+ return false;
+ }
- $id = $DB->insert_record('scorm', $scorm);
+/// update course module record - from now on this instance properly exists and all function may be used
+ if (!$DB->set_field('course_modules', 'instance', $id, array('id'=>$cmid))) {
+ print_error('cannotaddcoursemodule');
+ }
- if (scorm_external_link($scorm->reference) || ((basename($scorm->reference) != 'imsmanifest.xml') && ($scorm->reference[0] != '#'))) {
- // Rename temp scorm dir to scorm id
- $scorm->dir = $CFG->dataroot.'/'.$scorm->course.'/moddata/scorm';
- if (file_exists($scorm->dir.'/'.$id)) {
- //delete directory as it shouldn't exist! - most likely there from an old moodle install with old files in dataroot
- scorm_delete_files($scorm->dir.'/'.$id);
+/// reload scorm instance
+ $scorm = $DB->get_record('scorm', array('id'=>$id));
+
+/// store the package and verify
+ if ($scorm->scormtype === SCORM_TYPE_LOCAL) {
+ if ($mform) {
+ $filename = $mform->get_new_filename('packagefile');
+ if ($filename !== false) {
+ $fs = get_file_storage();
+ $fs->delete_area_files($context->id, 'scorm_package');
+ $mform->save_stored_file('packagefile', $context->id, 'scorm_package', 0, '/', $filename);
+ $scorm->reference = $filename;
}
- rename($scorm->dir.$scorm->datadir,$scorm->dir.'/'.$id);
}
- // Parse scorm manifest
- if ($scorm->parse == 1) {
- $scorm->id = $id;
- $scorm->launch = scorm_parse($scorm);
- $DB->set_field('scorm', 'launch', $scorm->launch, array('id'=>$scorm->id));
- }
+ } else if ($scorm->scormtype === SCORM_TYPE_LOCALSYNC) {
+ $scorm->reference = $scorm->packageurl;
- scorm_grade_item_update($scorm);
+ } else if ($scorm->scormtype === SCORM_TYPE_EXTERNAL) {
+ $scorm->reference = $scorm->packageurl;
+
+ } else if ($scorm->scormtype === SCORM_TYPE_IMSREPOSITORY) {
+ $scorm->reference = $scorm->packageurl;
- return $id;
} else {
- print_error('badpackage','scorm');
+ return false;
}
+
+ // save reference
+ $DB->update_record('scorm', $scorm);
+
+
+/// extra fields required in grade related functions
+ $scorm->course = $courseid;
+ $scorm->cmidnumber = $cmidnumber;
+ $scorm->cmid = $cmid;
+
+ scorm_parse($scorm, true);
+
+ scorm_grade_item_update($scorm);
+
+ return $scorm->id;
}
/**
* (defined by the form in mod_form.php) this function
* will update an existing instance with new data.
*
-* @param mixed $scorm Form data
-* @return int
+* @param object $scorm Form data
+* @param object $mform
+* @return bool success
*/
-function scorm_update_instance($scorm) {
+function scorm_update_instance($scorm, $mform=null) {
global $CFG, $DB;
require_once('locallib.php');
- $scorm->parse = 0;
- if (($packagedata = scorm_check_package($scorm)) != null) {
- $scorm->pkgtype = $packagedata->pkgtype;
- if ($packagedata->launch == 0) {
- $scorm->launch = $packagedata->launch;
- $scorm->datadir = $packagedata->datadir;
- $scorm->parse = 1;
- if (!scorm_external_link($scorm->reference) && $scorm->reference[0] != '#') { //dont set md5hash if this is from a repo.
- $scorm->md5hash = md5_file($CFG->dataroot.'/'.$scorm->course.'/'.$scorm->reference);
- } elseif($scorm->reference[0] != '#') { //dont set md5hash if this is from a repo.
- $scorm->dir = $CFG->dataroot.'/'.$scorm->course.'/moddata/scorm';
- $scorm->md5hash = md5_file($scorm->dir.$scorm->datadir.'/'.basename($scorm->reference));
+ $cmid = $scorm->coursemodule;
+ $cmidnumber = $scorm->cmidnumber;
+ $courseid = $scorm->course;
+
+ $scorm->id = $scorm->instance;
+
+ $context = get_context_instance(CONTEXT_MODULE, $cmid);
+
+ if ($scorm->scormtype === SCORM_TYPE_LOCAL) {
+ if ($mform) {
+ $filename = $mform->get_new_filename('packagefile');
+ if ($filename !== false) {
+ $scorm->reference = $filename;
+ $fs = get_file_storage();
+ $fs->delete_area_files($context->id, 'scorm_package');
+ $mform->save_stored_file('packagefile', $context->id, 'scorm_package', 0, '/', $filename);
}
}
- }
- $scorm->timemodified = time();
- $scorm->id = $scorm->instance;
+ } else if ($scorm->scormtype === SCORM_TYPE_LOCALSYNC) {
+ $scorm->reference = $scorm->packageurl;
+
+ } else if ($scorm->scormtype === SCORM_TYPE_EXTERNAL) {
+ $scorm->reference = $scorm->packageurl;
+
+ } else if ($scorm->scormtype === SCORM_TYPE_IMSREPOSITORY) {
+ $scorm->reference = $scorm->packageurl;
+
+ } else {
+ return false;
+ }
$scorm = scorm_option2text($scorm);
- $scorm->width = str_replace('%','',$scorm->width);
- $scorm->height = str_replace('%','',$scorm->height);
+ $scorm->width = (int)str_replace('%','',$scorm->width);
+ $scorm->height = (int)str_replace('%','',$scorm->height);
+ $scorm->timemodified = time();
if (!isset($scorm->whatgrade)) {
$scorm->whatgrade = 0;
}
- $scorm->grademethod = ($scorm->whatgrade * 10) + $scorm->grademethod;
+ $scorm->grademethod = ($scorm->whatgrade * 10) + $scorm->grademethod;
- // Check if scorm manifest needs to be reparsed
- if ($scorm->parse == 1) {
- $scorm->dir = $CFG->dataroot.'/'.$scorm->course.'/moddata/scorm';
- if (is_dir($scorm->dir.'/'.$scorm->id)) {
- scorm_delete_files($scorm->dir.'/'.$scorm->id);
- }
- if (isset($scorm->datadir) && ($scorm->datadir != $scorm->id) &&
- (scorm_external_link($scorm->reference) || ((basename($scorm->reference) != 'imsmanifest.xml') && ($scorm->reference[0] != '#')))) {
- rename($scorm->dir.$scorm->datadir,$scorm->dir.'/'.$scorm->id);
- }
-
- $scorm->launch = scorm_parse($scorm);
- } else {
- $oldscorm = $DB->get_record('scorm', array('id'=>$scorm->id));
- $scorm->reference = $oldscorm->reference; // This fix a problem with Firefox when the teacher choose Cancel on overwrite question
- }
-
- if ($result = $DB->update_record('scorm', $scorm)) {
- scorm_grade_item_update(stripslashes_recursive($scorm));
- //scorm_grade_item_update($scorm); // John Macklins fix - dont think this is needed
+ if (!$DB->update_record('scorm', $scorm)) {
+ return false;
}
- return $result;
+ $scorm = $DB->get_record('scorm', array('id'=>$scorm->id));
+
+/// extra fields required in grade related functions
+ $scorm->course = $courseid;
+ $scorm->idnumber = $cmidnumber;
+ $scorm->cmid = $cmid;
+
+ scorm_parse($scorm, (bool)$scorm->updatefreq);
+
+ scorm_grade_item_update($scorm);
+
+ return true;
}
/**
$result = true;
- $scorm->dir = $CFG->dataroot.'/'.$scorm->course.'/moddata/scorm';
- if (is_dir($scorm->dir.'/'.$scorm->id)) {
- // Delete any dependent files
- require_once('locallib.php');
- scorm_delete_files($scorm->dir.'/'.$scorm->id);
- }
-
// Delete any dependent records
if (! $DB->delete_records('scorm_scoes_track', array('scormid'=>$scorm->id))) {
$result = false;
if (! $DB->delete_records('scorm_scoes_data', array('scoid'=>$sco->id))) {
$result = false;
}
- }
+ }
$DB->delete_records('scorm_scoes', array('scorm'=>$scorm->id));
} else {
$result = false;
}
if (! $DB->delete_records('scorm_sequencing_ruleconditions', array('scormid'=>$scorm->id))) {
$result = false;
- }*/
+ }*/
scorm_grade_item_delete($scorm);
-
+
return $result;
}
*
* @param int $course Course id
* @param int $user User id
-* @param int $mod
+* @param int $mod
* @param int $scorm The scorm id
* @return mixed
*/
-function scorm_user_outline($course, $user, $mod, $scorm) {
+function scorm_user_outline($course, $user, $mod, $scorm) {
global $CFG;
require_once('locallib.php');
*
* @param int $course Course id
* @param int $user User id
-* @param int $mod
+* @param int $mod
* @param int $scorm The scorm id
* @return boolean
*/
$lastmodify = 0;
$sometoreport = false;
$report = '';
-
+
if ($orgs = $DB->get_records('scorm_scoes', array('scorm'=>$scorm->id, 'organization'=>'', 'launch'=>''),'id','id,identifier,title')) {
if (count($orgs) <= 1) {
unset($orgs);
$conditions['scorm'] = $scorm->id;
if ($scoes = $DB->get_records('scorm_scoes', $conditions, "id ASC")){
// drop keys so that we can access array sequentially
- $scoes = array_values($scoes);
+ $scoes = array_values($scoes);
$level=0;
$sublist=1;
$parents[$level]='/';
}
}
$report .= "\t\t\t</ul></li>\n";
- }
+ }
} else {
$report .= " $sco->title</li>\n";
}
require_once('locallib.php');
$sitetimezone = $CFG->timezone;
- /// Now see if there are any digest mails waiting to be sent, and if we should send them
+ /// Now see if there are any scorm updates to be done
+
if (!isset($CFG->scorm_updatetimelast)) { // To catch the first time
set_config('scorm_updatetimelast', 0);
}
mtrace('Updating scorm packages which require daily update');//We are updating
$scormsupdate = $DB->get_records('scorm', array('updatefreq'=>UPDATE_EVERYDAY));
- if (!empty($scormsupdate)) {
- foreach($scormsupdate as $scormupdate) {
- $scormupdate->instance = $scormupdate->id;
- $id = scorm_update_instance($scormupdate);
- }
+ foreach($scormsupdate as $scormupdate) {
+ scorm_parse($scormupdate, true);
}
}
if (isset($scorm->cmidnumber)) {
$params['idnumber'] = $scorm->cmidnumber;
}
-
+
if (($scorm->grademethod % 10) == 0) { // GRADESCOES
if ($maxgrade = $DB->count_records_select('scorm_scoes', 'scorm = ? AND launch <> ?', array($scorm->id, $DB->sql_empty()))) {
$params['gradetype'] = GRADE_TYPE_VALUE;
}
function scorm_option2text($scorm) {
- global $SCORM_POPUP_OPTIONS;
+ $SCORM_POPUP_OPTIONS = array('resizable'=>1,
+ 'scrollbars'=>1,
+ 'directories'=>0,
+ 'location'=>0,
+ 'menubar'=>0,
+ 'toolbar'=>0,
+ 'status'=>0);
+
if (isset($scorm->popup)) {
if ($scorm->popup == 1) {
$optionlist = array();
} else {
$optionlist[] = $name.'=0';
}
- }
+ }
$scorm->options = implode(',', $optionlist);
} else {
$scorm->options = '';
- }
+ }
} else {
$scorm->popup = 0;
$scorm->options = '';
return array('moodle/site:accessallgroups');
}
+/**
+ * Lists all file areas current user may browse
+ */
+function scorm_get_file_areas($course, $cm, $context) {
+ $areas = array();
+ if (has_capability('moodle/course:managefiles', $context)) {
+ $areas['scorm_intro'] = get_string('areaintro', 'scorm');
+ $areas['scorm_content'] = get_string('areacontent', 'scorm');
+ $areas['scorm_package'] = get_string('areapackage', 'scorm');
+ }
+ return $areas;
+}
+
+/**
+ * File browsing support
+ */
+function scorm_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) {
+ global $CFG;
+
+ if (!has_capability('moodle/course:managefiles', $context)) {
+ return null;
+ }
+
+ // no writing for now!
+
+ $fs = get_file_storage();
+
+ if ($filearea === 'scorm_content') {
+
+ $filepath = is_null($filepath) ? '/' : $filepath;
+ $filename = is_null($filename) ? '.' : $filename;
+
+ $urlbase = $CFG->wwwroot.'/pluginfile.php';
+ if (!$storedfile = $fs->get_file($context->id, $filearea, 0, $filepath, $filename)) {
+ if ($filepath === '/' and $filename === '.') {
+ $storedfile = new virtual_root_file($context->id, $filearea, 0);
+ } else {
+ // not found
+ return null;
+ }
+ }
+ class scorm_package_file_info extends file_info_stored {
+ public function get_parent() {
+ if ($this->lf->get_filepath() === '/' and $this->lf->get_filename() === '.') {
+ return $this->browser->get_file_info($this->context);
+ }
+ return parent::get_parent();
+ }
+ public function get_visible_name() {
+ if ($this->lf->get_filepath() === '/' and $this->lf->get_filename() === '.') {
+ return $this->areavisiblename;
+ }
+ return parent::get_visible_name();
+ }
+ }
+ return new scorm_package_file_info($browser, $context, $storedfile, $urlbase, $areas[$filearea], true, true, false);
+
+ } else if ($filearea === 'scorm_package') {
+ $filepath = is_null($filepath) ? '/' : $filepath;
+ $filename = is_null($filename) ? '.' : $filename;
+
+ $urlbase = $CFG->wwwroot.'/pluginfile.php';
+ if (!$storedfile = $fs->get_file($context->id, $filearea, 0, $filepath, $filename)) {
+ if ($filepath === '/' and $filename === '.') {
+ $storedfile = new virtual_root_file($context->id, $filearea, 0);
+ } else {
+ // not found
+ return null;
+ }
+ }
+ return new file_info_stored($browser, $context, $storedfile, $urlbase, $areas[$filearea], false, true, false);
+ }
+
+ // scorm_intro handled in file_browser
+
+ return false;
+}
+
+/**
+ * Serves scorm content, introduction images and packages. Implements needed access control ;-)
+ */
+function scorm_pluginfile($course, $cminfo, $context, $filearea, $args) {
+ global $CFG;
+
+ if (!$cminfo->uservisible) {
+ return false; // probably hidden
+ }
+
+ $lifetime = isset($CFG->filelifetime) ? $CFG->filelifetime : 86400;
+
+ if ($filearea === 'scorm_intro') {
+ // all users may access it
+ $relativepath = '/'.implode('/', $args);
+ $fullpath = $context->id.'scorm_intro0'.$relativepath;
+
+ $fs = get_file_storage();
+ if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
+ return false;
+ }
+
+ } else if ($filearea === 'scorm_content') {
+ $revision = (int)array_shift($args); // prevents caching problems - ignored here
+ $relativepath = '/'.implode('/', $args);
+ $fullpath = $context->id.'scorm_content0'.$relativepath;
+ // TODO: add any other access restrictions here if needed!
+
+ } else if ($filearea === 'scorm_package') {
+ if (!has_capability('moodle/course:manageactivities', $context)) {
+ return false;
+ }
+ $relativepath = '/'.implode('/', $args);
+ $fullpath = $context->id.'scorm_package0'.$relativepath;
+ $lifetime = 0; // no caching here
+
+ } else {
+ return false;
+ }
+
+ $fs = get_file_storage();
+ if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
+ return false;
+ }
+
+ // finally send the file
+ send_stored_file($file, $lifetime, 0, false);
+}
+
?>
require_once('../../config.php');
require_once('locallib.php');
- $id = optional_param('id', '', PARAM_INT); // Course Module ID, or
- $a = optional_param('a', '', PARAM_INT); // scorm ID
+ $id = optional_param('id', '', PARAM_INT); // Course Module ID, or
+ $a = optional_param('a', '', PARAM_INT); // scorm ID
$scoid = required_param('scoid', PARAM_INT); // sco ID
$delayseconds = 2; // Delay time before sco launch, used to give time to browser to define API
}
require_login($course->id, false, $cm);
+
+ $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+
if (!empty($scoid)) {
//
// Direct SCO request
$value = 'completed';
$result = scorm_insert_track($USER->id, $scorm->id, $sco->id, $attempt, $element, $value);
}
-
+
//
// Forge SCO URL
//
$sco->parameters = substr($sco->parameters,1);
}
}
-
+
if ($version == 'AICC') {
if (isset($sco->parameters) && (!empty($sco->parameters))) {
$sco->parameters = '&'. $sco->parameters;
$launcher = $sco->launch;
}
}
-
+
if (scorm_external_link($sco->launch)) {
- // Remote learning activity
+ //TODO: does this happen?
$result = $launcher;
- } else if ($scorm->reference[0] == '#') {
+
+ } else if ($scorm->scormtype === SCORM_TYPE_EXTERNAL) {
+ // Remote learning activity
+ $result = dirname($scorm->reference).'/'.$launcher;
+
+ } else if ($scorm->scormtype === SCORM_TYPE_IMSREPOSITORY) {
// Repository
- $result = $CFG->repositorywebroot.substr($scorm->reference,1).'/'.$sco->launch;
- } else {
- if ((basename($scorm->reference) == 'imsmanifest.xml') && scorm_external_link($scorm->reference)) {
- // Remote manifest
- $result = dirname($scorm->reference).'/'.$launcher;
- } else {
- // Moodle internal package/manifest or remote (auto-imported) package
- if (basename($scorm->reference) == 'imsmanifest.xml') {
- $basedir = dirname($scorm->reference);
- } else {
- $basedir = $CFG->moddata.'/scorm/'.$scorm->id;
- }
- //note: do not convert this to use get_file_url()!
- // SCORM does not work without slasharguments anyway and there might be some extra ?xx=yy params
- // see MDL-16060
- $result = $CFG->wwwroot.'/file.php/'.$scorm->course.'/'.$basedir.'/'.$launcher;
- }
+ $result = $CFG->repositorywebroot.substr($scorm->reference, 1).'/'.$sco->launch;
+
+ } else if ($scorm->scormtype === SCORM_TYPE_LOCAL or $scorm->scormtype === SCORM_TYPE_LOCALSYNC) {
+ //note: do not convert this to use get_file_url()!
+ // SCORM does not work without slasharguments anyway and there might be some extra ?xx=yy params
+ // see MDL-16060
+ $result = "$CFG->wwwroot/pluginfile.php/$context->id/scorm_content/$scorm->revision/$launcher";
}
-
+
$scormpixdir = $CFG->modpixpath.'/scorm/pix';
?>
<html>
}
}, 1000);
}
- //]]>
+ //]]>
</script>
<noscript>
<meta http-equiv="refresh" content="<?php echo $delayseconds ?>;url=<?php echo $result ?>" />
- </noscript>
+ </noscript>
</head>
<body onload="doredirect();">
<p><?php echo get_string('activityloading', 'scorm');?> <span id="countdown"><?php echo $delayseconds ?></span> <?php echo get_string('numseconds');?>. <img src='<?php echo $scormpixdir;?>/wait.gif'><p>
add_to_log($course->id, 'scorm', 'launch', 'view.php?id='.$cm->id, $result, $cm->id);
}
?>
- </body>
+ </body>
</html>
<?php // $Id$
+require_once("$CFG->dirroot/mod/scorm/lib.php");
+
/// Constants and settings for module scorm
define('UPDATE_NEVER', '0');
define('UPDATE_ONCHANGE', '1');
define('GRADEHIGHEST', '1');
define('GRADEAVERAGE', '2');
define('GRADESUM', '3');
-$SCORM_GRADE_METHOD = array (GRADESCOES => get_string('gradescoes', 'scorm'),
- GRADEHIGHEST => get_string('gradehighest', 'scorm'),
- GRADEAVERAGE => get_string('gradeaverage', 'scorm'),
- GRADESUM => get_string('gradesum', 'scorm'));
define('HIGHESTATTEMPT', '0');
define('AVERAGEATTEMPT', '1');
define('FIRSTATTEMPT', '2');
define('LASTATTEMPT', '3');
-$SCORM_WHAT_GRADE = array (HIGHESTATTEMPT => get_string('highestattempt', 'scorm'),
- AVERAGEATTEMPT => get_string('averageattempt', 'scorm'),
- FIRSTATTEMPT => get_string('firstattempt', 'scorm'),
- LASTATTEMPT => get_string('lastattempt', 'scorm'));
-
-$SCORM_POPUP_OPTIONS = array('resizable'=>1,
- 'scrollbars'=>1,
- 'directories'=>0,
- 'location'=>0,
- 'menubar'=>0,
- 'toolbar'=>0,
- 'status'=>0);
-$stdoptions = '';
-foreach ($SCORM_POPUP_OPTIONS as $popupopt => $value) {
- $stdoptions .= $popupopt.'='.$value;
- if ($popupopt != 'status') {
- $stdoptions .= ',';
- }
-}
-if (!isset($CFG->scorm_maxattempts)) {
- set_config('scorm_maxattempts','6');
-}
-
-if (!isset($CFG->scorm_frameheight)) {
- set_config('scorm_frameheight','500');
-}
-if (!isset($CFG->scorm_framewidth)) {
- set_config('scorm_framewidth','100%');
-}
+/// Local Library of functions for module scorm
-if (!isset($CFG->scorm_updatetime)) {
- set_config('scorm_updatetime','2');
-}
+/**
+ * Extracts scrom package, sets up all variables.
+ * Called whenever scorm changes
+ * @param object $scorm instance - fields are updated and changes saved into database
+ * @param bool $full force full update if true
+ * @return void
+ */
+function scorm_parse($scorm, $full) {
+ global $CFG, $DB;
-if (!isset($CFG->scorm_advancedsettings)) {
- set_config('scorm_advancedsettings','0');
-}
+ if (!isset($scorm->cmid)) {
+ $cm = get_coursemodule_from_instance('scorm', $scorm->id);
+ $scorm->cmid = $cm->id;
+ }
+ $context = get_context_instance(CONTEXT_MODULE, $scorm->cmid);
+ $newhash = $scorm->sha1hash;
-if (!isset($CFG->scorm_windowsettings)) {
- set_config('scorm_windowsettings','0');
-}
+ if ($scorm->scormtype === SCORM_TYPE_LOCAL or $scorm->scormtype === SCORM_TYPE_LOCALSYNC) {
-/// Local Library of functions for module scorm
+ $fs = get_file_storage();
+ $packagefile = false;
-/**
-* This function will permanently delete the given
-* directory and all files and subdirectories.
-*
-* @param string $directory The directory to remove
-* @return boolean
-*/
-function scorm_delete_files($directory) {
- if (is_dir($directory)) {
- $files=scandir($directory);
- set_time_limit(0);
- foreach($files as $file) {
- if (($file != '.') && ($file != '..')) {
- if (!is_dir($directory.'/'.$file)) {
- unlink($directory.'/'.$file);
+ if ($scorm->scormtype === SCORM_TYPE_LOCAL) {
+ if ($packagefile = $fs->get_file($context->id, 'scorm_package', 0, '/', $scorm->reference)) {
+ $newhash = $packagefile->get_contenthash();
+ } else {
+ $newhash = null;
+ }
+ } else {
+ if (!$CFG->scorm_allowtypelocalsync) {
+ // sorry - localsync disabled
+ return;
+ }
+ if ($scorm->reference !== '' and (!$full or $scorm->sha1hash !== sha1($scorm->reference))) {
+ $fs->delete_area_files($context->id, 'scorm_package');
+ $file_record = array('contextid'=>$context->id, 'filearea'=>'scorm_package', 'itemid'=>0, 'filepath'=>'/');
+ if ($packagefile = $fs->create_file_from_url($file_record, $scorm->reference)) {
+ $newhash = sha1($scorm->reference);
} else {
- scorm_delete_files($directory.'/'.$file);
+ $newhash = null;
}
}
}
- rmdir($directory);
- return true;
- }
- return false;
-}
-/**
-* Create a new temporary subdirectory with a random name in the given path
-*
-* @param string $strpath The scorm data directory
-* @return string/boolean
-*/
-function scorm_tempdir($strPath)
-{
- global $CFG;
-
- if (is_dir($strPath)) {
- do {
- // Create a random string of 8 chars
- $randstring = NULL;
- $lchar = '';
- $len = 8;
- for ($i=0; $i<$len; $i++) {
- $char = chr(rand(48,122));
- while (!ereg('[a-zA-Z0-9]', $char)){
- if ($char == $lchar) continue;
- $char = chr(rand(48,90));
+ if ($packagefile) {
+ if (!$full and $packagefile and $scorm->sha1hash === $newhash) {
+ if (strpos($scorm->version, 'SCORM') !== false) {
+ if ($fs->get_file($context->id, 'scorm_content', 0, '/', 'imsmanifest.xml')) {
+ // no need to update
+ return;
}
- $randstring .= $char;
- $lchar = $char;
- }
- $datadir='/'.$randstring;
- } while (file_exists($strPath.$datadir));
- mkdir($strPath.$datadir, $CFG->directorypermissions);
- @chmod($strPath.$datadir, $CFG->directorypermissions); // Just in case mkdir didn't do it
- return $strPath.$datadir;
+ } else if (strpos($scorm->version, 'AICC') !== false) {
+ // TODO: add more sanity checks - something really exists in scorm_content area
+ return;
+ }
+ }
+
+ // now extract files
+ $fs->delete_area_files($context->id, 'scorm_content');
+
+ $packer = get_file_packer('application/zip');
+ $packagefile->extract_to_storage($packer, $context->id, 'scorm_content', 0, '/');
+
+ } else if (!$full) {
+ return;
+ }
+
+
+ if ($manifest = $fs->get_file($context->id, 'scorm_content', 0, '/', 'imsmanifest.xml')) {
+ require_once("$CFG->dirroot/mod/scorm/datamodels/scormlib.php");
+ // SCORM
+ if (!scorm_parse_scorm($scorm, $manifest)) {
+ $scorm->version = 'ERROR';
+ }
+ } else {
+ require_once("$CFG->dirroot/mod/scorm/datamodels/aicclib.php");
+ // AICC
+ if (!scorm_parse_aicc($scorm)) {
+ $scorm->version = 'ERROR';
+ }
+ }
+
+ } else if ($scorm->scormtype === SCORM_TYPE_EXTERNAL and $CFG->scorm_allowtypeexternal) {
+ if (!$full and $scorm->sha1hash === sha1($scorm->reference)) {
+ return;
+ }
+ require_once("$CFG->dirroot/mod/scorm/datamodels/scormlib.php");
+ // SCORM only, AICC can not be external
+ if (!scorm_parse_scorm($scorm, $scorm->reference)) {
+ $scorm->version = 'ERROR';
+ }
+ $newhash = sha1($scorm->reference);
+
+ } else if ($scorm->scormtype === SCORM_TYPE_IMSREPOSITORY and !empty($CFG->repositoryactivate) and $CFG->scorm_allowtypeimsrepository) {
+ if (!$full and $scorm->sha1hash === sha1($scorm->reference)) {
+ return;
+ }
+ require_once("$CFG->dirroot/mod/scorm/datamodels/scormlib.php");
+ if (!scorm_parse_scorm($scorm, $CFG->repository.substr($scorm->reference,1).'/imsmanifest.xml')) {
+ $scorm->version = 'ERROR';
+ }
+ $newhash = sha1($scorm->reference);
+
} else {
- return false;
+ // sorry, disabled type
+ return;
}
+
+ $scorm->revision++;
+ $scorm->sha1hash = $newhash;
+ $DB->update_record('scorm', $scorm);
}
+
function scorm_array_search($item, $needle, $haystacks, $strict=false) {
if (!empty($haystacks)) {
foreach ($haystacks as $key => $element) {
$sco->{$scodata->name} = $scodata->value;
}
} else if (($what != SCO_ONLY) && (!($scodatas = $DB->get_records('scorm_scoes_data', array('scoid'=>$id))))) {
- $sco->parameters = '';
+ $sco->parameters = '';
}
return $sco;
} else {
$track->timemodified = time();
$id = $DB->insert_record('scorm_scoes_track',$track);
}
-
+
// MDL-9552, update the gradebook everything raw score is sent
// Scoring by learning objects also needs to be included in the gradebook update
- if (strstr($element, '.score.raw') ||
+ if (strstr($element, '.score.raw') ||
(($element == 'cmi.core.lesson_status' || $element == 'cmi.completion_status') && ($track->value == 'completed' || $track->value == 'passed'))) {
$scorm = $DB->get_record('scorm', array('id' => $scormid));
$grademethod = $scorm->grademethod % 10;
scorm_update_grades($scorm, $userid);
}
}
-
+
return $id;
}
}
if ($tracks = $DB->get_records('scorm_scoes_track', array('userid'=>$userid, 'scoid'=>$scoid, 'attempt'=>$attempt),'element ASC')) {
$usertrack->userid = $userid;
- $usertrack->scoid = $scoid;
+ $usertrack->scoid = $scoid;
// Defined in order to unify scorm1.2 and scorm2004
$usertrack->score_raw = '';
$usertrack->status = '';
case 'cmi.completion_status':
if ($track->value == 'not attempted') {
$track->value = 'notattempted';
- }
+ }
$usertrack->status = $track->value;
- break;
+ break;
case 'cmi.core.score.raw':
case 'cmi.score.raw':
$usertrack->score_raw = $track->value;
- break;
+ break;
case 'cmi.core.session_time':
case 'cmi.session_time':
$usertrack->session_time = $track->value;
- break;
+ break;
case 'cmi.core.total_time':
case 'cmi.total_time':
$usertrack->total_time = $track->value;
- break;
- }
+ break;
+ }
if (isset($track->timemodified) && ($track->timemodified > $usertrack->timemodified)) {
$usertrack->timemodified = $track->timemodified;
- }
+ }
}
- if (is_array($usertrack)) {
+ if (is_array($usertrack)) {
ksort($usertrack);
}
return $usertrack;
function scorm_grade_user_attempt($scorm, $userid, $attempt=1, $time=false) {
global $DB;
- $attemptscore = NULL;
+ $attemptscore = NULL;
$attemptscore->scoes = 0;
$attemptscore->values = 0;
$attemptscore->max = 0;
$attemptscore->sum = 0;
$attemptscore->lastmodify = 0;
-
+
if (!$scoes = $DB->get_records('scorm_scoes', array('scorm'=>$scorm->id))) {
return NULL;
}
// and 1s are grademethod
$grademethod = $scorm->grademethod % 10;
- foreach ($scoes as $sco) {
+ foreach ($scoes as $sco) {
if ($userdata=scorm_get_tracks($sco->id, $userid,$attempt)) {
if (($userdata->status == 'completed') || ($userdata->status == 'passed')) {
$attemptscore->scoes++;
- }
+ }
if (!empty($userdata->score_raw)) {
$attemptscore->values++;
$attemptscore->sum += $userdata->score_raw;
} else {
$attemptscore->lastmodify = 0;
}
- }
- }
+ }
+ }
}
switch ($grademethod) {
case GRADEHIGHEST:
$score = $attemptscore->max;
- break;
+ break;
case GRADEAVERAGE:
if ($attemptscore->values > 0) {
$score = $attemptscore->sum/$attemptscore->values;
} else {
$score = 0;
- }
- break;
+ }
+ break;
case GRADESUM:
$score = $attemptscore->sum;
- break;
+ break;
case GRADESCOES:
$score = $attemptscore->scoes;
break;
switch ($whatgrade) {
case FIRSTATTEMPT:
return scorm_grade_user_attempt($scorm, $userid, 1, $time);
- break;
+ break;
case LASTATTEMPT:
return scorm_grade_user_attempt($scorm, $userid, scorm_get_last_attempt($scorm->id, $userid), $time);
break;
echo '<div class="mod-scorm">';
if ($scorms = get_all_instances_in_course('scorm', $course)) {
- // The module SCORM activity with the least id is the course
+ // The module SCORM activity with the least id is the course
$scorm = current($scorms);
if (! $cm = get_coursemodule_from_instance('scorm', $scorm->id, $course->id)) {
print_error('invalidcoursemodule');
$headertext .= '<td class="reportlink">'.get_string('noreports','scorm');
}
$colspan = ' colspan="2"';
- }
+ }
$headertext .= '</td></tr><tr><td'.$colspan.'>'.format_text(get_string('summary').':<br />'.$scorm->summary).'</td></tr></table>';
print_simple_box($headertext,'','100%');
scorm_view_display($user, $scorm, 'view.php?id='.$course->id, $cm, '100%');
function scorm_view_display ($user, $scorm, $action, $cm, $boxwidth='') {
global $CFG, $DB;
- if ($scorm->updatefreq == UPDATE_EVERYTIME){
- require_once($CFG->dirroot.'/mod/scorm/lib.php');
-
- $scorm->instance = $scorm->id;
- scorm_update_instance($scorm);
+ if ($scorm->updatefreq == UPDATE_EVERYTIME) {
+ scorm_parse($scorm, false);
}
$organization = optional_param('organization', '', PARAM_INT);
global $DB;
$result = false;
-
+
$scoes = $DB->get_records_select('scorm_scoes', 'scorm = ? AND launch <> ?', array($scorm->id, $DB->sql_empty()));
-
+
if ($scoes && (count($scoes) == 1)) {
if ($scorm->skipview >= 1) {
$sco = current($scoes);
return $result;
}
*/
-function scorm_parse($scorm) {
- global $CFG;
-
- if ($scorm->reference[0] == '#') {
- if (isset($CFG->repositoryactivate) && $CFG->repositoryactivate) {
- $referencedir = $CFG->repository.substr($scorm->reference,1);
- }
- } else {
- if ((!scorm_external_link($scorm->reference)) && (basename($scorm->reference) == 'imsmanifest.xml')) {
- $referencedir = $CFG->dataroot.'/'.$scorm->course.'/'.$scorm->datadir;
- } else {
- $referencedir = $CFG->dataroot.'/'.$scorm->course.'/moddata/scorm/'.$scorm->id;
- }
- }
-
- // Parse scorm manifest
- if ($scorm->pkgtype == 'AICC') {
- require_once('datamodels/aicclib.php');
- $scorm->launch = scorm_parse_aicc($referencedir, $scorm->id);
- } else {
- require_once('datamodels/scormlib.php');
- $scorm->launch = scorm_parse_scorm($referencedir,$scorm->id);
- }
- return $scorm->launch;
-}
-
-/**
-* Given a manifest path, this function will check if the manifest is valid
-*
-* @param string $manifest The manifest file
-* @return object
-*/
-function scorm_validate_manifest($manifest) {
- $validation = new stdClass();
- if (is_file($manifest)) {
- $validation->result = true;
- } else {
- $validation->result = false;
- $validation->errors['reference'] = get_string('nomanifest','scorm');
- }
- return $validation;
-}
-
-/**
-* Given a aicc package directory, this function will check if the course structure is valid
-*
-* @param string $packagedir The aicc package directory path
-* @return object
-*/
-function scorm_validate_aicc($packagedir) {
- $validation = new stdClass();
- $validation->result = false;
- if (is_dir($packagedir)) {
- if ($handle = opendir($packagedir)) {
- while (($file = readdir($handle)) !== false) {
- $ext = substr($file,strrpos($file,'.'));
- if (strtolower($ext) == '.cst') {
- $validation->result = true;
- break;
- }
- }
- closedir($handle);
- }
- }
- if ($validation->result == false) {
- $validation->errors['reference'] = get_string('nomanifest','scorm');
- }
- return $validation;
-}
-
-
-function scorm_validate($data) {
- global $CFG, $DB;
-
- $validation = new stdClass();
- $validation->errors = array();
-
- if (!isset($data['course']) || empty($data['course'])) {
- $validation->errors['reference'] = get_string('missingparam','scorm');
- $validation->result = false;
- return $validation;
- }
- $courseid = $data['course']; // Course Module ID
-
- if (!isset($data['reference']) || empty($data['reference'])) {
- $validation->errors['reference'] = get_string('packagefile','scorm');
- $validation->result = false;
- return $validation;
- }
- $reference = $data['reference']; // Package/manifest path/location
-
- $scormid = $data['instance']; // scorm ID
- $scorm = new stdClass();
- if (!empty($scormid)) {
- if (!$scorm = $DB->get_record('scorm', array('id'=>$scormid))) {
- $validation->errors['reference'] = get_string('missingparam','scorm');
- $validation->result = false;
- return $validation;
- }
- }
-
- if ($reference[0] == '#') {
- if (isset($CFG->repositoryactivate) && $CFG->repositoryactivate) {
- $reference = $CFG->repository.substr($reference,1).'/imsmanifest.xml';
- } else {
- $validation->errors['reference'] = get_string('badpackage','scorm');
- $validation->result = false;
- return $validation;
- }
- } else if (!scorm_external_link($reference)) {
- $reference = $CFG->dataroot.'/'.$courseid.'/'.$reference;
- }
-
- // Create a temporary directory to unzip package or copy manifest and validate package
- $tempdir = '';
- $scormdir = '';
- if ($scormdir = make_upload_directory("$courseid/$CFG->moddata/scorm")) {
- if ($tempdir = scorm_tempdir($scormdir)) {
- $localreference = $tempdir.'/'.basename($reference);
- copy ("$reference", $localreference);
- if (!is_file($localreference)) {
- $validation->errors['reference'] = get_string('badpackage','scorm');
- $validation->result = false;
- } else {
- $ext = strtolower(substr(basename($localreference),strrpos(basename($localreference),'.')));
- switch ($ext) {
- case '.pif':
- case '.zip':
- if (!unzip_file($localreference, $tempdir, false)) {
- $validation->errors['reference'] = get_string('unziperror','scorm');
- $validation->result = false;
- } else {
- unlink ($localreference);
- if (is_file($tempdir.'/imsmanifest.xml')) {
- $validation = scorm_validate_manifest($tempdir.'/imsmanifest.xml');
- $validation->pkgtype = 'SCORM';
- } else {
- $validation = scorm_validate_aicc($tempdir);
- if (($validation->result == 'regular') || ($validation->result == 'found')) {
- $validation->pkgtype = 'AICC';
- } else {
- $validation->errors['reference'] = get_string('nomanifest','scorm');
- $validation->result = false;
- }
- }
- }
- break;
- case '.xml':
- if (basename($localreference) == 'imsmanifest.xml') {
- $validation = scorm_validate_manifest($localreference);
- } else {
- $validation->errors['reference'] = get_string('nomanifest','scorm');
- $validation->result = false;
- }
- break;
- default:
- $validation->errors['reference'] = get_string('badpackage','scorm');
- $validation->result = false;
- break;
- }
- }
- if (is_dir($tempdir)) {
- // Delete files and temporary directory
- scorm_delete_files($tempdir);
- }
- } else {
- $validation->errors['reference'] = get_string('packagedir','scorm');
- $validation->result = false;
- }
- } else {
- $validation->errors['reference'] = get_string('datadir','scorm');
- $validation->result = false;
- }
- return $validation;
-}
-
-function scorm_check_package($data) {
- global $CFG, $COURSE, $DB;
-
- $courseid = $data->course; // Course Module ID
- $reference = $data->reference; // Package path
- $scormid = $data->instance; // scorm ID
-
- $validation = new stdClass();
-
- if (!empty($courseid) && !empty($reference)) {
- $externalpackage = scorm_external_link($reference);
-
- $validation->launch = 0;
- $referencefield = $reference;
- if (empty($reference)) {
- $validation = null;
- } else if ($reference[0] == '#') {
- if (isset($CFG->repositoryactivate) && $CFG->repositoryactivate) {
- $referencefield = $reference.'/imsmanifest.xml';
- $reference = $CFG->repository.substr($reference,1).'/imsmanifest.xml';
- } else {
- $validation = null;
- }
- } else if (!$externalpackage) {
- $reference = $CFG->dataroot.'/'.$courseid.'/'.$reference;
- }
-
- if (!empty($scormid)) {
- //
- // SCORM Update
- //
- if ((!empty($validation)) && (is_file($reference) || $externalpackage)){
-
- if (!$externalpackage) {
- $mdcheck = md5_file($reference);
- } else if ($externalpackage){
- if ($scormdir = make_upload_directory("$courseid/$CFG->moddata/scorm")) {
- if ($tempdir = scorm_tempdir($scormdir)) {
- copy ("$reference", $tempdir.'/'.basename($reference));
- $mdcheck = md5_file($tempdir.'/'.basename($reference));
- scorm_delete_files($tempdir);
- }
- }
- }
-
- if ($scorm = $DB->get_record('scorm', array('id'=>$scormid))) {
- if ($scorm->reference[0] == '#') {
- if (isset($CFG->repositoryactivate) && $CFG->repositoryactivate) {
- $oldreference = $CFG->repository.substr($scorm->reference,1).'/imsmanifest.xml';
- } else {
- $oldreference = $scorm->reference;
- }
- } else if (!scorm_external_link($scorm->reference)) {
- $oldreference = $CFG->dataroot.'/'.$courseid.'/'.$scorm->reference;
- } else {
- $oldreference = $scorm->reference;
- }
- $validation->launch = $scorm->launch;
- if ((($oldreference == $reference) && ($mdcheck != $scorm->md5hash)) || ($oldreference != $reference)) {
- // This is a new or a modified package
- $validation->launch = 0;
- } else {
- // Old package already validated
- if (strpos($scorm->version,'AICC') !== false) {
- $validation->pkgtype = 'AICC';
- } else {
- $validation->pkgtype = 'SCORM';
- }
- }
- } else {
- $validation = null;
- }
- } else {
- $validation = null;
- }
- }
- //$validation->launch = 0;
- if (($validation != null) && ($validation->launch == 0)) {
- //
- // Package must be validated
- //
- $ext = strtolower(substr(basename($reference),strrpos(basename($reference),'.')));
- $tempdir = '';
- switch ($ext) {
- case '.pif':
- case '.zip':
- // Create a temporary directory to unzip package and validate package
- $scormdir = '';
- if ($scormdir = make_upload_directory("$courseid/$CFG->moddata/scorm")) {
- if ($tempdir = scorm_tempdir($scormdir)) {
- copy ("$reference", $tempdir.'/'.basename($reference));
- unzip_file($tempdir.'/'.basename($reference), $tempdir, false);
- if (!$externalpackage) {
- unlink ($tempdir.'/'.basename($reference));
- }
- if (is_file($tempdir.'/imsmanifest.xml')) {
- $validation = scorm_validate_manifest($tempdir.'/imsmanifest.xml');
- $validation->pkgtype = 'SCORM';
- } else {
- $validation = scorm_validate_aicc($tempdir);
- $validation->pkgtype = 'AICC';
- }
- } else {
- $validation = null;
- }
- } else {
- $validation = null;
- }
- break;
- case '.xml':
- if (basename($reference) == 'imsmanifest.xml') {
- if ($externalpackage) {
- if ($scormdir = make_upload_directory("$courseid/$CFG->moddata/scorm")) {
- if ($tempdir = scorm_tempdir($scormdir)) {
- copy ("$reference", $tempdir.'/'.basename($reference));
- if (is_file($tempdir.'/'.basename($reference))) {
- $validation = scorm_validate_manifest($tempdir.'/'.basename($reference));
- } else {
- $validation = null;
- }
- }
- }
- } else {
- $validation = scorm_validate_manifest($reference);
- }
- $validation->pkgtype = 'SCORM';
- } else {
- $validation = null;
- }
- break;
- default:
- $validation = null;
- break;
- }
- if ($validation == null) {
- if (is_dir($tempdir)) {
- // Delete files and temporary directory
- scorm_delete_files($tempdir);
- }
- } else {
- if (($ext == '.xml') && (!$externalpackage)) {
- $validation->datadir = dirname($referencefield);
- } else {
- $validation->datadir = substr($tempdir,strlen($scormdir));
- }
- $validation->launch = 0;
- }
- }
- } else {
- $validation = null;
- }
- return $validation;
-}
-
function scorm_get_count_users($scormid, $groupingid=null) {
global $CFG, $DB;
-
+
if (!empty($CFG->enablegroupings) && !empty($groupingid)) {
$sql = "SELECT COUNT(DISTINCT st.userid)
FROM {scorm_scoes_track} st
INNER JOIN {groups_members} gm ON st.userid = gm.userid
- INNER JOIN {groupings_groups} gg ON gm.groupid = gg.groupid
+ INNER JOIN {groupings_groups} gg ON gm.groupid = gg.groupid
WHERE st.scormid = ? AND gg.groupingid = ?
";
$params = array($scormid, $groupingid);
} else {
$sql = "SELECT COUNT(DISTINCT st.userid)
- FROM {scorm_scoes_track} st
+ FROM {scorm_scoes_track} st
WHERE st.scormid = ?
";
$params = array($scormid);
}
-
+
return ($DB->count_records_sql($sql, $params));
}
class mod_scorm_mod_form extends moodleform_mod {
function definition() {
+ global $CFG;
- global $CFG, $COURSE, $SCORM_GRADE_METHOD, $SCORM_WHAT_GRADE;
- $mform =& $this->_form;
- if (isset($CFG->slasharguments) && !$CFG->slasharguments) {
+ $mform = $this->_form;
+
+ $SCORM_GRADE_METHOD = array (GRADESCOES => get_string('gradescoes', 'scorm'),
+ GRADEHIGHEST => get_string('gradehighest', 'scorm'),
+ GRADEAVERAGE => get_string('gradeaverage', 'scorm'),
+ GRADESUM => get_string('gradesum', 'scorm'));
+
+ $SCORM_WHAT_GRADE = array (HIGHESTATTEMPT => get_string('highestattempt', 'scorm'),
+ AVERAGEATTEMPT => get_string('averageattempt', 'scorm'),
+ FIRSTATTEMPT => get_string('firstattempt', 'scorm'),
+ LASTATTEMPT => get_string('lastattempt', 'scorm'));
+
+
+ if (!$CFG->slasharguments) {
$mform->addElement('static', '', '',notify(get_string('slashargs', 'scorm'), 'notifyproblem', 'center', true));
}
//-------------------------------------------------------------------------------
$mform->addRule('summary', get_string('required'), 'required', null, 'client');
$mform->setHelpButton('summary', array('writing', 'questions', 'richtext'), false, 'editorhelpbutton');
+// Scorm types
+ $options = array(SCORM_TYPE_LOCAL => get_string('typelocal', 'scorm'));
+
+ if ($CFG->scorm_allowtypeexternal) {
+ $options[SCORM_TYPE_EXTERNAL] = get_string('typeexternal', 'scorm');
+ }
+
+ if ($CFG->scorm_allowtypelocalsync) {
+ $options[SCORM_TYPE_LOCALSYNC] = get_string('typelocalsync', 'scorm');
+ }
+
+ if (!empty($CFG->repositoryactivate) and $CFG->scorm_allowtypeimsrepository) {
+ $options[SCORM_TYPE_IMSREPOSITORY] = get_string('typeimsrepository', 'scorm');
+ }
+
+ $mform->addElement('select', 'scormtype', get_string('scormtype', 'scorm'), $options);
+
// Reference
- $mform->addElement('choosecoursefileorimsrepo', 'reference', get_string('package','scorm'));
- $mform->setType('reference', PARAM_RAW); // We need to find a better PARAM
- $mform->addRule('reference', get_string('required'), 'required');
- $mform->setHelpButton('reference',array('package', get_string('package', 'scorm'), 'scorm'));
+ if (count($options) > 1) {
+ $mform->addElement('text', 'packageurl', get_string('url', 'scorm'), array('size'=>60));
+ $mform->setType('packageurl', PARAM_RAW);
+ $mform->setHelpButton('packageurl', array('packagefile', get_string('package', 'scorm'), 'scorm'));
+ $mform->disabledIf('packageurl', 'scormtype', 'eq', SCORM_TYPE_LOCAL);
+ }
+
+// New local package upload
+ $mform->addElement('file', 'packagefile', get_string('package','scorm'));
+ $mform->disabledIf('packagefile', 'scormtype', 'noteq', SCORM_TYPE_LOCAL);
//-------------------------------------------------------------------------------
// Other Settings
// Grade Method
$mform->addElement('select', 'grademethod', get_string('grademethod', 'scorm'), $SCORM_GRADE_METHOD);
- $mform->setHelpButton('grademethod', array('grademethod',get_string('grademethod', 'scorm'),'scorm'));
+ $mform->setHelpButton('grademethod', array('grademethod', get_string('grademethod', 'scorm'),'scorm'));
$mform->setDefault('grademethod', 0);
// Maximum Grade
}
$mform->addElement('select', 'maxgrade', get_string('maximumgrade'), $grades);
$mform->setDefault('maxgrade', 0);
- $mform->disabledIf('maxgrade', 'grademethod','eq',GRADESCOES);
+ $mform->disabledIf('maxgrade', 'grademethod','eq', GRADESCOES);
// Attempts
$mform->addElement('static', '', '' ,'<hr />');
$mform->addElement('static', 'stagesize', get_string('stagesize','scorm'));
$mform->setHelpButton('stagesize', array('stagesize',get_string('stagesize', 'scorm'), 'scorm'));
// Width
- $mform->addElement('text', 'width', get_string('width','scorm'),'maxlength="5" size="5"');
+ $mform->addElement('text', 'width', get_string('width','scorm'), 'maxlength="5" size="5"');
$mform->setDefault('width', $CFG->scorm_framewidth);
$mform->setType('width', PARAM_INT);
-
+
// Height
- $mform->addElement('text', 'height', get_string('height','scorm'),'maxlength="5" size="5"');
+ $mform->addElement('text', 'height', get_string('height','scorm'), 'maxlength="5" size="5"');
$mform->setDefault('height', $CFG->scorm_frameheight);
$mform->setType('height', PARAM_INT);
$options = array();
$options[0] = get_string('iframe', 'scorm');
$options[1] = get_string('popup', 'scorm');
- $mform->addElement('select', 'popup', get_string('display','scorm'), $options);
+ $mform->addElement('select', 'popup', get_string('display', 'scorm'), $options);
$mform->setDefault('popup', 0);
$mform->setAdvanced('popup');
foreach ($options as $option) {
list($element,$value) = explode('=',$option);
$element = trim($element);
- $default_values[$element] = trim($value);
+ $default_values[$element] = trim($value);
}
}
if (isset($default_values['grademethod'])) {
$coursescorm = current($scorms);
if (($COURSE->format == 'scorm') && ((count($scorms) == 0) || ($default_values['instance'] == $coursescorm->id))) {
$default_values['redirect'] = 'yes';
- $default_values['redirecturl'] = '../course/view.php?id='.$default_values['course'];
+ $default_values['redirecturl'] = '../course/view.php?id='.$default_values['course'];
} else {
$default_values['redirect'] = 'no';
$default_values['redirecturl'] = '../mod/scorm/view.php?id='.$default_values['coursemodule'];
function validation($data, $files) {
$errors = parent::validation($data, $files);
- $validate = scorm_validate($data);
+ $type = $data['scormtype'];
+
+ if ($type === SCORM_TYPE_LOCAL) {
+ if (!empty($data['update'])) {
+ //ok, not required
- if (!$validate->result) {
- $errors = $errors + $validate->errors;
+ } else if (empty($files['packagefile'])) {
+ $errors['packagefile'] = get_string('required');
+
+ } else {
+ $packer = get_file_packer('application/zip');
+
+ $filelist = $packer->list_files($files['packagefile']);
+ if (!is_array($filelist)) {
+ $errors['packagefile'] = 'Incorrect file package - not an archive'; //TODO: localise
+ } else {
+ $manifestpresent = false;
+ $aiccfound = false;
+ foreach ($filelist as $info) {
+ if ($info->pathname == 'imsmanifest.xml') {
+ $manifestpresent = true;
+ break;
+ }
+ if (preg_match('/\.cst$/', $info->pathname)) {
+ $aiccfound = true;
+ break;
+ }
+ }
+ if (!$manifestpresent and !$aiccfound) {
+ $errors['packagefile'] = 'Incorrect file package - missing imsmanifest.xml or AICC structure'; //TODO: localise
+ }
+ }
+ }
+
+ } else if ($type === SCORM_TYPE_EXTERNAL) {
+ $reference = $data['packageurl'];
+ if (!preg_match('/(http:\/\/|https:\/\/|www).*\/imsmanifest.xml$/i', $reference)) {
+ $errors['packageurl'] = get_string('required'); // TODO: improve help
+ }
+
+ } else if ($type === 'packageurl') {
+ $reference = $data['reference'];
+ if (!preg_match('/(http:\/\/|https:\/\/|www).*(\.zip|\.pif)$/i', $reference)) {
+ $errors['packageurl'] = get_string('required'); // TODO: improve help
+ }
+
+ } else if ($type === SCORM_TYPE_IMSREPOSITORY) {
+ $reference = $data['packageurl'];
+ if (stripos($reference, '#') !== 0) {
+ $errors['packageurl'] = get_string('required');
+ }
}
return $errors;
}
- //need to translate the "options" field.
+
+ //need to translate the "options" and "reference" field.
function set_data($default_values) {
- if (is_object($default_values)) {
- if (!empty($default_values->options)) {
- $options = explode(',', $default_values->options);
- foreach ($options as $option) {
- $opt = explode('=', $option);
- if (isset($opt[1])) {
- $default_values->$opt[0] = $opt[1];
- }
+ $default_values = (array)$default_values;
+
+ if (isset($default_values['scormtype']) and isset($default_values['reference'])) {
+ switch ($default_values['scormtype']) {
+ case SCORM_TYPE_LOCALSYNC :
+ case SCORM_TYPE_EXTERNAL:
+ case SCORM_TYPE_IMSREPOSITORY:
+ $default_values['packageurl'] = $default_values['reference'];
+ }
+ }
+ unset($default_values['reference']);
+
+ if (!empty($default_values['options'])) {
+ $options = explode(',', $default_values['options']);
+ foreach ($options as $option) {
+ $opt = explode('=', $option);
+ if (isset($opt[1])) {
+ $default_values[$opt][0] = $opt[1];
}
}
- $default_values = (array)$default_values;
}
+
$this->data_preprocessing($default_values);
- parent::set_data($default_values); //never slashed for moodleform_mod
+ parent::set_data($default_values);
}
}
?>
\ No newline at end of file
<?php //$Id$
$settings->add(new admin_setting_configtext('scorm_framewidth', get_string('width', 'scorm'),
- get_string('framewidth', 'scorm'), '100%'));
+ get_string('framewidth', 'scorm'), 100));
$settings->add(new admin_setting_configtext('scorm_frameheight', get_string('height', 'scorm'),
get_string('frameheight', 'scorm'), 500));
-?>
+$settings->add(new admin_setting_configtext('scorm_maxattempts', get_string('maximumattempts', 'scorm'),
+ '', 6));
+
+$settings->add(new admin_setting_configtext('scorm_updatetime', get_string('updatetime', 'scorm'),
+ '', 2));
+
+$settings->add(new admin_setting_configcheckbox('scorm_allowtypeexternal', get_string('allowtypeexternal', 'scorm'),
+ '', 0));
+
+$settings->add(new admin_setting_configcheckbox('scorm_allowtypelocalsync', get_string('allowtypelocalsync', 'scorm'),
+ '', 0));
+
+$settings->add(new admin_setting_configcheckbox('scorm_allowtypeimsrepository', get_string('allowtypeimsrepository', 'scorm'),
+ '', 0));
+
+
+
/////////////////////////////////////////////////////////////////////////////////
-// NOTE The version below was accidentally set a month into the future! We need to
-// catch up now, so until 27th October please only increment in very tiny steps
+// NOTE The version below was accidentally set a month into the future! We need to
+// catch up now, so until 27th October please only increment in very tiny steps
// in HEAD, until we get past that date..
-$module->version = 2008073100; // The (date) version of this module
-$module->requires = 2007101509; // The version of Moodle that is required
+$module->version = 2008090304; // The (date) version of this module
+$module->requires = 2008090108; // The version of Moodle that is required
$module->cron = 300; // How often should cron check this module (seconds)?
?>
\ No newline at end of file