MDL-16088 scorm new file api conversion
authorskodak <skodak>
Tue, 9 Sep 2008 08:30:00 +0000 (08:30 +0000)
committerskodak <skodak>
Tue, 9 Sep 2008 08:30:00 +0000 (08:30 +0000)
12 files changed:
lang/en_utf8/scorm.php
mod/scorm/api.php
mod/scorm/datamodels/aicclib.php
mod/scorm/datamodels/scormlib.php
mod/scorm/db/install.xml
mod/scorm/db/upgrade.php
mod/scorm/lib.php
mod/scorm/loadSCO.php
mod/scorm/locallib.php
mod/scorm/mod_form.php
mod/scorm/settings.php
mod/scorm/version.php

index 06c7149..8cf989e 100644 (file)
@@ -4,6 +4,12 @@
 
 $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';
@@ -125,6 +131,7 @@ $string['scorm:skipview'] = 'Skip overview';
 $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';
@@ -145,6 +152,12 @@ $string['toolbar'] = 'Show the toolbar';
 $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.';
index 771cd4b..ca6613a 100644 (file)
@@ -2,7 +2,7 @@
 
     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
@@ -33,7 +33,7 @@
         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")) {
@@ -58,7 +58,7 @@
         $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);
index 908e7e2..7adf7fc 100644 (file)
@@ -90,49 +90,57 @@ function scorm_forge_cols_regexp($columns,$remodule='(".*")?,') {
     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++) {
@@ -145,7 +153,7 @@ function scorm_parse_aicc($pkgdir,$scormid) {
             }
         }
         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++) {
@@ -158,7 +166,7 @@ function scorm_parse_aicc($pkgdir,$scormid) {
             }
         }
         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++) {
@@ -172,7 +180,7 @@ function scorm_parse_aicc($pkgdir,$scormid) {
             }
         }
         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++) {
@@ -186,7 +194,7 @@ function scorm_parse_aicc($pkgdir,$scormid) {
             }
         }
         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++) {
@@ -196,19 +204,19 @@ function scorm_parse_aicc($pkgdir,$scormid) {
             }
         }
         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 = '/';
@@ -216,7 +224,7 @@ function scorm_parse_aicc($pkgdir,$scormid) {
             $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]);
@@ -231,7 +239,7 @@ function scorm_parse_aicc($pkgdir,$scormid) {
                 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;
                  
@@ -302,8 +310,12 @@ function scorm_parse_aicc($pkgdir,$scormid) {
             $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) {
index 68e49d7..aca4b74 100644 (file)
@@ -456,161 +456,165 @@ function scorm_get_manifest($blocks,$scoes) {
     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 = '&amp;';
-        $xmltext = preg_replace($pattern, $replacement, $xmltext);
+    $pattern = '/&(?!\w{2,6};)/';
+    $replacement = '&amp;';
+    $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) {
index 1386d83..12642de 100644 (file)
@@ -1,5 +1,5 @@
 <?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"
 >
@@ -8,17 +8,20 @@
       <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"/>
@@ -31,7 +34,7 @@
         <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
index 1a0c0ab..9061b24 100644 (file)
@@ -1,6 +1,6 @@
 <?php  //$Id$
 
-// This file keeps track of upgrades to 
+// This file keeps track of upgrades to
 // the scorm module
 //
 // Sometimes, changes between versions involve
@@ -33,15 +33,207 @@ function xmldb_scorm_upgrade($oldversion) {
         $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;
 }
 
index 51a5397..5042c38 100755 (executable)
@@ -1,72 +1,93 @@
 <?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;
 }
 
 /**
@@ -74,65 +95,73 @@ function scorm_add_instance($scorm) {
 * (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;
 }
 
 /**
@@ -152,13 +181,6 @@ function scorm_delete_instance($id) {
 
     $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;
@@ -168,7 +190,7 @@ function scorm_delete_instance($id) {
             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;
@@ -197,10 +219,10 @@ function scorm_delete_instance($id) {
     }
     if (! $DB->delete_records('scorm_sequencing_ruleconditions', array('scormid'=>$scorm->id))) {
         $result = false;
-    }*/     
+    }*/
 
     scorm_grade_item_delete($scorm);
-  
+
     return $result;
 }
 
@@ -211,11 +233,11 @@ function scorm_delete_instance($id) {
 *
 * @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');
 
@@ -230,7 +252,7 @@ function scorm_user_outline($course, $user, $mod, $scorm) {
 *
 * @param int $course Course id
 * @param int $user User id
-* @param int $mod  
+* @param int $mod
 * @param int $scorm The scorm id
 * @return boolean
 */
@@ -244,7 +266,7 @@ function scorm_user_complete($course, $user, $mod, $scorm) {
     $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);
@@ -263,7 +285,7 @@ function scorm_user_complete($course, $user, $mod, $scorm) {
                 $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]='/';
@@ -336,7 +358,7 @@ function scorm_user_complete($course, $user, $mod, $scorm) {
                                 }
                             }
                             $report .= "\t\t\t</ul></li>\n";
-                        } 
+                        }
                     } else {
                         $report .= "&nbsp;$sco->title</li>\n";
                     }
@@ -380,7 +402,8 @@ function scorm_cron () {
     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);
     }
@@ -395,11 +418,8 @@ function scorm_cron () {
         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);
         }
     }
 
@@ -514,7 +534,7 @@ function scorm_grade_item_update($scorm, $grades=NULL) {
     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;
@@ -559,7 +579,14 @@ function scorm_get_post_actions() {
 }
 
 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();
@@ -569,11 +596,11 @@ function scorm_option2text($scorm) {
                 } else {
                     $optionlist[] = $name.'=0';
                 }
-            }       
+            }
             $scorm->options = implode(',', $optionlist);
         } else {
             $scorm->options = '';
-        } 
+        }
     } else {
         $scorm->popup = 0;
         $scorm->options = '';
@@ -656,4 +683,131 @@ function scorm_get_extra_capabilities() {
     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);
+}
+
 ?>
index 8de4742..b60e955 100755 (executable)
@@ -2,8 +2,8 @@
     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
@@ -33,6 +33,9 @@
     }
 
     require_login($course->id, false, $cm);
+
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+
     if (!empty($scoid)) {
     //
     // Direct SCO request
@@ -60,7 +63,7 @@
        $value = 'completed';
        $result = scorm_insert_track($USER->id, $scorm->id, $sco->id, $attempt, $element, $value);
     }
-    
+
     //
     // Forge SCO URL
     //
@@ -76,7 +79,7 @@
             $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');?>. &nbsp; <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>
index 727c846..7fecd22 100755 (executable)
@@ -1,5 +1,7 @@
 <?php  // $Id$
 
+require_once("$CFG->dirroot/mod/scorm/lib.php");
+
 /// Constants and settings for module scorm
 define('UPDATE_NEVER', '0');
 define('UPDATE_ONCHANGE', '1');
@@ -14,122 +16,129 @@ define('GRADESCOES', '0');
 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) {
@@ -189,7 +198,7 @@ function scorm_get_sco($id,$what=SCO_ALL) {
                 $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 {
@@ -247,10 +256,10 @@ function scorm_insert_track($userid,$scormid,$scoid,$attempt,$element,$value) {
         $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;
@@ -259,7 +268,7 @@ function scorm_insert_track($userid,$scormid,$scoid,$attempt,$element,$value) {
             scorm_update_grades($scorm, $userid);
         }
     }
-    
+
     return $id;
 }
 
@@ -276,7 +285,7 @@ function scorm_get_tracks($scoid,$userid,$attempt='') {
     }
     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 = '';
@@ -291,27 +300,27 @@ function scorm_get_tracks($scoid,$userid,$attempt='') {
                 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;
@@ -330,13 +339,13 @@ function scorm_get_user_data($userid) {
 
 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;
     }
@@ -346,11 +355,11 @@ function scorm_grade_user_attempt($scorm, $userid, $attempt=1, $time=false) {
     // 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;
@@ -360,23 +369,23 @@ function scorm_grade_user_attempt($scorm, $userid, $attempt=1, $time=false) {
                 } 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;
@@ -410,7 +419,7 @@ function scorm_grade_user($scorm, $userid, $time=false) {
     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;
@@ -502,7 +511,7 @@ function scorm_course_format_display($user,$course) {
 
     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');
@@ -528,7 +537,7 @@ function scorm_course_format_display($user,$course) {
                 $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%');
@@ -546,11 +555,8 @@ function scorm_course_format_display($user,$course) {
 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);
@@ -637,9 +643,9 @@ function scorm_simple_play($scorm,$user) {
     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);
@@ -675,356 +681,26 @@ function scorm_simple_play($scorm,$user) {
     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));
 }
 
index 669cb1b..399edc3 100644 (file)
@@ -5,10 +5,22 @@ require_once($CFG->dirroot.'/mod/scorm/locallib.php');
 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));
         }
 //-------------------------------------------------------------------------------
@@ -29,11 +41,34 @@ class mod_scorm_mod_form extends moodleform_mod {
         $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
@@ -41,7 +76,7 @@ class mod_scorm_mod_form extends moodleform_mod {
 
 // 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
@@ -50,7 +85,7 @@ class mod_scorm_mod_form extends moodleform_mod {
         }
         $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 />');
@@ -99,12 +134,12 @@ class mod_scorm_mod_form extends moodleform_mod {
         $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);
 
@@ -112,7 +147,7 @@ class mod_scorm_mod_form extends moodleform_mod {
         $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');
 
@@ -211,7 +246,7 @@ class mod_scorm_mod_form extends moodleform_mod {
             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'])) {
@@ -228,7 +263,7 @@ class mod_scorm_mod_form extends moodleform_mod {
         $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'];
@@ -244,30 +279,88 @@ class mod_scorm_mod_form extends moodleform_mod {
     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
index 4d99e25..5c75fcf 100644 (file)
@@ -1,9 +1,25 @@
 <?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));
+
+
+
index 98ca6a3..3abb85d 100755 (executable)
@@ -6,12 +6,12 @@
 /////////////////////////////////////////////////////////////////////////////////
 
 
-// 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