get_string('gradescoes', 'scorm'), VALUEHIGHEST => get_string('gradehighest', 'scorm'), VALUEAVERAGE => get_string('gradeaverage', 'scorm'), VALUESUM => get_string('gradesum', 'scorm')); if (!isset($CFG->scorm_validate)) { $scormvalidate = 'none'; //I've commented this out for Moodle 1.4, as I've seen errors in //SCORM packages even though the actual package worked fine. -- Martin Dougiamas if (extension_loaded('domxml') && version_compare(phpversion(),'5.0.0','<')) { $scormvalidate = 'domxml'; } if (version_compare(phpversion(),'5.0.0','>=')) { $scormvalidate = 'php5'; } set_config('scorm_validate', $scormvalidate); } function scorm_add_instance($scorm) { /// Given an object containing all the necessary data, /// (defined by the form in mod.html) this function /// will create a new instance and return the id number /// of the new instance. $scorm->timemodified = time(); # May have to add extra stuff in here # global $CFG; $id = insert_record('scorm', $scorm); // // Rename temp scorm dir to scorm id // $scormdir = $CFG->dataroot.'/'.$scorm->course.'/moddata/scorm'; rename($scormdir.$scorm->datadir,$scormdir.'/'.$id); // // Parse scorm manifest // if ($scorm->launch == 0) { $scorm->launch = scorm_parse($scormdir.'/'.$id,$scorm->pkgtype,$id); set_field('scorm','launch',$scorm->launch,'id',$id); } return $id; } function scorm_update_instance($scorm) { /// Given an object containing all the necessary data, /// (defined by the form in mod.html) this function /// will update an existing instance with new data. $scorm->timemodified = time(); $scorm->id = $scorm->instance; # May have to add extra stuff in here # global $CFG; // // Check if scorm manifest needs to be reparsed // if ($scorm->launch == 0) { $scormdir = $CFG->dataroot.'/'.$scorm->course.'/moddata/scorm'; if (isset($scorm->datadir) && ($scorm->datadir != $scorm->id)) { scorm_delete_files($scormdir.'/'.$scorm->id); rename($scormdir.$scorm->datadir,$scormdir.'/'.$scorm->id); } $scorm->launch = scorm_parse($scormdir.'/'.$scorm->id,$scorm->pkgtype,$scorm->id); } return update_record('scorm', $scorm); } function scorm_delete_instance($id) { /// Given an ID of an instance of this module, /// this function will permanently delete the instance /// and any data that depends on it. require('../config.php'); if (! $scorm = get_record('scorm', 'id', $id)) { return false; } $result = true; # Delete any dependent files # scorm_delete_files($CFG->dataroot.'/'.$scorm->course.'/moddata/scorm/'.$scorm->id); # Delete any dependent records here # if (! delete_records('scorm_scoes_track', 'scormid', $scorm->id)) { $result = false; } if (! delete_records('scorm_scoes', 'scorm', $scorm->id)) { $result = false; } if (! delete_records('scorm', 'id', $scorm->id)) { $result = false; } return $result; } function scorm_user_outline($course, $user, $mod, $scorm) { /// Return a small object with summary information about what a /// user has done with a given particular instance of this module /// Used for user activity reports. /// $return->time = the time they did it /// $return->info = a short text description return true; // TO FIX } function scorm_user_complete($course, $user, $mod, $scorm) { /// Print a detailed representation of what a user has done with /// a given particular instance of this module, for user activity reports. return true; // TO FIX } function scorm_print_recent_activity(&$logs, $isteacher=false) { /// Given a list of logs, assumed to be those since the last login /// this function prints a short list of changes related to this module /// If isteacher is true then perhaps additional information is printed. /// This function is called from course/lib.php: print_recent_activity() return false; // True if anything was printed, otherwise false } function scorm_cron () { /// Function to be run periodically according to the moodle cron /// This function searches for things that need to be done, such /// as sending out mail, toggling flags etc ... global $CFG; return true; } function scorm_grades($scormid) { /// Must return an array of grades for a given instance of this module, /// indexed by user. It also returns a maximum allowed grade. global $CFG; if (!$scorm = get_record('scorm', 'id', $scormid)) { return NULL; } if ($scorm->grademethod == VALUESCOES) { if (!$return->maxgrade = count_records_select('scorm_scoes',"scorm='$scormid' AND launch<>''")) { return NULL; } $return->grades = NULL; if ($scousers=get_records_select('scorm_scoes_track', "scormid='$scormid' GROUP BY userid")) { foreach ($scousers as $scouser) { $userdata=get_records_select('scorm_scoes_track',"scormid='$scormid' AND userid='$scouser->userid' AND element='cmi_core_lesson_status'"); $scores->completed=0; $scores->browsed=0; $scores->incomplete=0; $scores->failed=0; $scores->notattempted=0; $result=''; $data = current($userdata); foreach ($userdata as $data) { if ($data->value=='passed') $scores->completed++; else $scores->{scorm_remove_spaces($data->value)}++; } if ($scores->completed) $result.=''.get_string('completed','scorm').' '.$scores->completed; if ($scores->incomplete) $result.="wwwroot/mod/scorm/pix/incomplete.gif\" alt=\"".get_string('incomplete','scorm')."\" title=\"".get_string('incomplete','scorm')."\" /> $scores->incomplete "; if ($scores->failed) $result.="wwwroot/mod/scorm/pix/failed.gif\" alt=\"".get_string('failed','scorm')."\" title=\"".get_string('failed','scorm')."\" /> $scores->failed "; if ($scores->browsed) $result.="wwwroot/mod/scorm/pix/browsed.gif\" alt=\"".get_string('browsed','scorm')."\" title=\"".get_string('browsed','scorm')."\" /> $scores->browsed "; if ($scores->notattempted) $result.="wwwroot/mod/scorm/pix/notattempted.gif\" alt=\"".get_string('notattempted','scorm')."\" title=\"".get_string('notattempted','scorm')."\" /> $scores->notattempted "; $return->grades[$scouser->userid]=$result; } } } else { $grades = get_records_select('scorm_scoes_track', "scormid=$scormid AND element='cmi_core_score_raw' AND value<>''",'','id,userid,value'); //$grades = get_records_menu("scorm_scoes_track", "scormid",$scormid,"","userid,cmi_core_score_raw"); $valutations = array(); foreach ($grades as $grade) { if (!isset($valutations[$grade->userid])) { if ($scorm->grademethod == VALUEAVERAGE) { $values = array(); $values[$grade->userid]->grade = 0; $values[$grade->userid]->values = 0; } $valutations[$grade->userid] = 0; } switch ($scorm->grademethod) { case VALUEHIGHEST: if ($grade->value > $valutations[$grade->userid]) { $valutations[$grade->userid] = $grade->value; } break; case VALUEAVERAGE: $values[$grade->userid]->grade += $grade->value; $values[$grade->userid]->values++; break; case VALUESUM: $valutations[$grade->userid] += $grade->value; break; } } if ($scorm->grademethod == VALUEAVERAGE) { foreach($values as $userid => $value) { $valutations[$userid] = $value->grade/$value->values; } } //print_r($grades); $return->grades = $valutations; $return->maxgrade = $scorm->maxgrade; } return $return; } ////////////////////////////////////////////////////////////////////////////////////// /// Any other scorm functions go here. Each of them must have a name that /// starts with scorm_ function scorm_randstring($len = '8') { $rstring = NULL; $lchar = ''; 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)); } $rstring .= $char; $lchar = $char; } return $rstring; } function scorm_datadir($strPath, $existingdir='') { global $CFG; if (($existingdir!='') && (is_dir($strPath.'/'.$existingdir))) return $strPath.'/'.$existingdir; if (is_dir($strPath)) { do { $datadir='/'.scorm_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 { return false; } } function scorm_validate($packagedir) { if (is_file($packagedir.'/imsmanifest.xml')) { $validation->result = 'found'; $validation->pkgtype = 'SCORM'; } else { if ($handle = opendir($packagedir)) { while (($file = readdir($handle)) !== false) { $ext = substr($file,strrpos($file,'.')); if (strtolower($ext) == '.cst') { $validation->result = 'found'; $validation->pkgtype = 'AICC'; break; } } closedir($handle); } if (!isset($validation)) { $validation->result = 'nomanifest'; $validation->pkgtype = 'SCORM'; } } return $validation; } function scorm_delete_files($directory) { if (is_dir($directory)) { $files=scorm_scandir($directory); //print_r($files); foreach($files as $file) { if (($file != '.') && ($file != '..')) { if (!is_dir($directory.'/'.$file)) { //chmod($directory.'/'.$file,0777); unlink($directory.'/'.$file); } else { scorm_delete_files($directory.'/'.$file); } } } rmdir($directory); } } function scorm_scandir($directory) { if (version_compare(phpversion(),'5.0.0','>=')) { return scandir($directory); } else { $files = null; if ($dh = opendir($directory)) { while (($file = readdir($dh)) !== false) { $files[] = $file; } closedir($dh); } return $files; } } function scorm_startElement($parser, $name, $attrs) { global $scoes,$i,$resources,$parent,$level,$organization,$manifest,$defaultorg; switch ($name) { case 'ITEM': $i++; $scoes[$i]['manifest'] = $manifest; $scoes[$i]['organization'] = $organization; $scoes[$i]['identifier'] = $attrs['IDENTIFIER']; if (empty($attrs['IDENTIFIERREF'])) $attrs['IDENTIFIERREF'] = ''; $scoes[$i]['identifierref'] = $attrs['IDENTIFIERREF']; if (empty($attrs['ISVISIBLE'])) $attrs['ISVISIBLE'] = ''; $scoes[$i]['isvisible'] = $attrs['ISVISIBLE']; if (empty($attrs['PARAMETERS'])) $attrs['PARAMETERS'] = ''; $scoes[$i]['parameters'] = $attrs['PARAMETERS']; $scoes[$i]['parent'] = $parent[$level]; $level++; $parent[$level] = $attrs['IDENTIFIER']; break; case 'RESOURCE': if (!isset($attrs['HREF'])) { $attrs['HREF'] = ''; } $resources[$attrs['IDENTIFIER']]['href']=$attrs['HREF']; if (!isset($attrs['ADLCP:SCORMTYPE'])) { $attrs['ADLCP:SCORMTYPE'] = 'sco'; //Default scorm type } $resources[$attrs['IDENTIFIER']]['scormtype']=$attrs['ADLCP:SCORMTYPE']; break; case 'ORGANIZATION': $i++; $scoes[$i]['manifest'] = $manifest; $scoes[$i]['organization'] = ''; $scoes[$i]['identifier'] = $attrs['IDENTIFIER']; $scoes[$i]['identifierref'] = ''; $scoes[$i]['isvisible'] = ''; $scoes[$i]['parent'] = $parent[$level]; $level++; $parent[$level] = $attrs['IDENTIFIER']; $organization = $attrs['IDENTIFIER']; break; case 'MANIFEST': $manifest = $attrs['IDENTIFIER']; break; case 'ORGANIZATIONS': if (!isset($attrs['DEFAULT'])) { $attrs['DEFAULT'] = ''; } $defaultorg = $attrs['DEFAULT']; break; } } function scorm_endElement($parser, $name) { global $scoes,$i,$level,$datacontent,$manifest,$organization,$version; if ($name == 'ITEM') { $level--; } //if ($name == 'TITLE' && $level>0) { if ($name == 'TITLE') { $scoes[$i]['title'] = $datacontent; } if ($name == 'ADLCP:HIDERTSUI') { $scoes[$i][$datacontent] = 1; } if ($name == 'ADLCP:DATAFROMLMS') { $scoes[$i]['datafromlms'] = $datacontent; } if ($name == 'ADLCP:PREREQUISITES') { $scoes[$i]['prerequisites'] = $datacontent; } if ($name == 'ADLCP:MAXTIMEALLOWED') { $scoes[$i]['maxtimeallowed'] = $datacontent; } if ($name == 'ADLCP:TIMELIMITACTION') { $scoes[$i]['timelimitaction'] = $datacontent; } if ($name == 'ADLCP:MASTERYSCORE') { $scoes[$i]['masteryscore'] = $datacontent; } if ($name == 'ORGANIZATION') { $organization = ''; $level--; } if ($name == 'MANIFEST') { $manifest = ''; } if ($name == 'SCHEMAVERSION') { if (preg_match("/(\d+)\.(\d+)$/",$datacontent,$matches)) { $version = 'SCORM_'.$matches[1].'.'.$matches[2]; } //$version = $datacontent; } } function scorm_characterData($parser, $data) { global $datacontent; $datacontent = utf8_decode($data); } function scorm_parse($pkgdir,$pkgtype,$scormid){ if ($pkgtype == 'AICC') { return scorm_parse_aicc($pkgdir,$scormid); } else { return scorm_parse_scorm($pkgdir,'/imsmanifest.xml',$scormid); } } function scorm_get_aicc_columns($row,$mastername='system_id') { $tok = strtok(strtolower($row),"\",\n\r"); $result->columns = array(); $i=0; while ($tok) { if ($tok !='') { $result->columns[] = $tok; if ($tok == $mastername) { $result->mastercol = $i; } $i++; } $tok = strtok("\",\n\r"); } return $result; } function scorm_forge_cols_regexp($columns,$remodule='(".*")?,') { $regexp = '/^'; foreach ($columns as $column) { $regexp .= $remodule; } $regexp = substr($regexp,0,-1) . '/'; return $regexp; } function scorm_parse_aicc($pkgdir,$scormid){ $version = 'AICC'; $ids = array(); $courses = array(); if ($handle = opendir($pkgdir)) { while (($file = readdir($handle)) !== false) { $ext = substr($file,strrpos($file,'.')); $extension = strtolower(substr($ext,1)); $id = strtolower(basename($file,$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; } } } } } if (isset($id->des)) { $rows = file($pkgdir.'/'.$id->des); $columns = scorm_get_aicc_columns($rows[0]); $regexp = scorm_forge_cols_regexp($columns->columns); for ($i=1;$icolumns);$j++) { $column = $columns->columns[$j]; $courses[$courseid]->elements[substr(trim($matches[$columns->mastercol+1]),1,-1)]->$column = substr(trim($matches[$j+1]),1,-1); } } } } if (isset($id->au)) { $rows = file($pkgdir.'/'.$id->au); $columns = scorm_get_aicc_columns($rows[0]); $regexp = scorm_forge_cols_regexp($columns->columns); for ($i=1;$icolumns);$j++) { $column = $columns->columns[$j]; $courses[$courseid]->elements[substr(trim($matches[$columns->mastercol+1]),1,-1)]->$column = substr(trim($matches[$j+1]),1,-1); } } } } if (isset($id->cst)) { $rows = file($pkgdir.'/'.$id->cst); $columns = scorm_get_aicc_columns($rows[0],'block'); $regexp = scorm_forge_cols_regexp($columns->columns,'(.+)?,'); for ($i=1;$icolumns);$j++) { if ($j != $columns->mastercol) { $courses[$courseid]->elements[substr(trim($matches[$j+1]),1,-1)]->parent = substr(trim($matches[$columns->mastercol+1]),1,-1); } } } } } if (isset($id->ort)) { $rows = file($pkgdir.'/'.$id->ort); } if (isset($id->pre)) { $rows = file($pkgdir.'/'.$id->pre); $columns = scorm_get_aicc_columns($rows[0],'structure_element'); $regexp = scorm_forge_cols_regexp($columns->columns,'(.+),'); for ($i=1;$ielements[$columns->mastercol+1]->prerequisites = substr(trim($matches[1-$columns->mastercol+1]),1,-1); } } } if (isset($id->cmp)) { $rows = file($pkgdir.'/'.$id->cmp); } } //print_r($courses); $launch = 0; if (isset($courses)) { foreach ($courses as $course) { unset($sco); $sco->identifier = $course->id; $sco->scorm = $scormid; $sco->organization = ''; $sco->title = $course->title; $sco->parent = '/'; $sco->launch = ''; $sco->scormtype = ''; //print_r($sco); $id = insert_record('scorm_scoes',$sco); if ($launch == 0) { $launch = $id; } if (isset($course->elements)) { foreach($course->elements as $element) { unset($sco); $sco->identifier = $element->system_id; $sco->scorm = $scormid; $sco->organization = $course->id; $sco->title = $element->title; if (strtolower($element->parent) == 'root') { $sco->parent = '/'; } else { $sco->parent = $element->parent; } if (isset($element->file_name)) { $sco->launch = $element->file_name; $sco->scormtype = 'sco'; } else { $element->file_name = ''; $sco->scormtype = ''; } if (!isset($element->prerequisites)) { $element->prerequisites = ''; } $sco->prerequisites = $element->prerequisites; if (!isset($element->max_time_allowed)) { $element->max_time_allowed = ''; } $sco->maxtimeallowed = $element->max_time_allowed; if (!isset($element->time_limit_action)) { $element->time_limit_action = ''; } $sco->timelimitaction = $element->time_limit_action; if (!isset($element->mastery_score)) { $element->mastery_score = ''; } $sco->masteryscore = $element->mastery_score; $sco->previous = 0; $sco->next = 0; //print_r($sco); $id = insert_record('scorm_scoes',$sco); if ($launch==0) { $launch = $id; } } } } } if (isset($courses[0]->version)) { $version = $courses[0]->version; } set_field('scorm','version',$version,'id',$scormid); return $launch; } function scorm_parse_scorm($pkgdir,$file,$scormid) { global $scoes,$i,$resources,$parent,$level,$defaultorg,$version,$organization,$manifest; $datacontent = ''; $scoes[][] = ''; $resources[] = ''; $manifest = ''; $version = 'SCORM'; $organization = ''; $defaultorg = ''; $i = 0; $level = 0; $parent[$level] = '/'; $xmlparser = xml_parser_create('UTF-8'); // use case-folding so we are sure to find the tag in $map_array xml_parser_set_option($xmlparser, XML_OPTION_CASE_FOLDING, true); xml_set_element_handler($xmlparser, 'scorm_startElement', 'scorm_endElement'); xml_set_character_data_handler($xmlparser, 'scorm_characterData'); if (!($fp = fopen($pkgdir.$file, 'r'))) { die('could not open XML input'); } while ($data = fread($fp, 4096)) { if (!xml_parse($xmlparser, $data, feof($fp))) { die(sprintf('XML error: %s at line %d', xml_error_string(xml_get_error_code($xmlparser)), xml_get_current_line_number($xmlparser))); } } xml_parser_free($xmlparser); $launch = 0; $sco->scorm = $scormid; delete_records('scorm_scoes','scorm',$scormid); delete_records('scorm_scoes_track','scormid',$scormid); if (isset($scoes[1])) { for ($j=1; $j<=$i; $j++) { $sco->identifier = $scoes[$j]['identifier']; $sco->parent = $scoes[$j]['parent']; $sco->title = $scoes[$j]['title']; $sco->manifest = $scoes[$j]['manifest']; $sco->organization = $scoes[$j]['organization']; if (!isset($scoes[$j]['datafromlms'])) { $scoes[$j]['datafromlms'] = ''; } $sco->datafromlms = $scoes[$j]['datafromlms']; if (!isset($scoes[$j]['prerequisites'])) { $scoes[$j]['prerequisites'] = ''; } $sco->prerequisites = $scoes[$j]['prerequisites']; if (!isset($scoes[$j]['maxtimeallowed'])) { $scoes[$j]['maxtimeallowed'] = ''; } $sco->maxtimeallowed = $scoes[$j]['maxtimeallowed']; if (!isset($scoes[$j]['timelimitaction'])) { $scoes[$j]['timelimitaction'] = ''; } $sco->timelimitaction = $scoes[$j]['timelimitaction']; if (!isset($scoes[$j]['masteryscore'])) { $scoes[$j]['masteryscore'] = ''; } $sco->masteryscore = $scoes[$j]['masteryscore']; if (!isset($resources[($scoes[$j]['identifierref'])]['href'])) { $resources[($scoes[$j]['identifierref'])]['href'] = ''; } $sco->launch = $resources[($scoes[$j]['identifierref'])]['href']; if (!isset($scoes[$j]['parameters'])) { $scoes[$j]['parameters'] = ''; } $sco->parameters = $scoes[$j]['parameters']; if (!isset($resources[($scoes[$j]['identifierref'])]['scormtype'])) { $resources[($scoes[$j]['identifierref'])]['scormtype'] = ''; } $sco->scormtype = $resources[($scoes[$j]['identifierref'])]['scormtype']; if (!isset($scoes[$j]['previous'])) { $scoes[$j]['previous'] = 0; } $sco->previous = $scoes[$j]['previous']; if (!isset($scoes[$j]['continue'])) { $scoes[$j]['continue'] = 0; } $sco->next = $scoes[$j]['continue']; if (scorm_remove_spaces($scoes[$j]['isvisible']) != 'false') { $id = insert_record('scorm_scoes',$sco); } if (($launch==0) && ($defaultorg==$sco->identifier)) { $launch = $id; } } } else { foreach ($resources as $label => $resource) { if (!empty($resource['href'])) { $sco->identifier = $label; $sco->title = $label; $sco->parent = '/'; $sco->launch = $resource['href']; $sco->scormtype = $resource['type']; $id = insert_record('scorm_scoes',$sco); if ($launch == 0) { $launch = $id; } } } } set_field('scorm','version',$version,'id',$scormid); return $launch; } function scorm_get_tracks($scoid,$userid) { /// Gets all tracks of specified sco and user global $CFG; if ($tracks = get_records_select('scorm_scoes_track',"userid=$userid AND scoid=$scoid")) { $usertrack->userid = $userid; $usertrack->scoid = $scoid; $usertrack->score_raw = ''; $usertrack->status = ''; foreach ($tracks as $track) { $element = str_replace('.','_',$track->element); switch ($element) { case 'cmi_core_lesson_status': case 'cmi_completition_status': if ($track->value == 'not attempted') { $track->value = 'notattempted'; } $usertrack->status = $track->value; break; case 'cmi_core_score_raw': case 'cmi_score_raw': $usertrack->score_raw = $track->value; break; default: $usertrack->{$element} = $track->value; } } //print_r($usertrack); return $usertrack; } else { return false; } } function scorm_get_scoes_records($scouser) { /// Gets all info required to display the table of scorm results /// for report.php global $CFG; return get_records_sql("SELECT su.*, u.firstname, u.lastname, u.picture FROM {$CFG->prefix}scorm_scoes_track su, {$CFG->prefix}user u WHERE su.scormid = '$scouser->scormid' AND su.userid = u.id AND su.userid = '$scouser->userid' ORDER BY scoid"); } function scorm_remove_spaces($sourcestr) { // Remove blank space from a string $newstr=''; for( $i=0; $i$len ) { return ''.substr($stringa,0,$len-4).'...'.substr($stringa,strlen($stringa)-1,1).''; } else return $stringa; } function scorm_external_link($link) { // check if a link is external $result = false; $link = strtolower($link); if (substr($link,0,7) == 'http://') $result = true; else if (substr($link,0,8) == 'https://') $result = true; else if (substr($link,0,4) == 'www.') $result = true; return $result; } function scorm_count_launchable($scormid,$organization) { return count_records_select('scorm_scoes',"scorm=$scormid AND organization='$organization' AND launch<>''"); } function scorm_display_structure($scorm,$liststyle,$currentorg='',$scoid='',$mode='normal',$play=false) { global $USER; $strexpand = get_string('expcoll','scorm'); echo "
    "; $incomplete = false; $organizationsql = ''; if (empty($currentorg)) { // } else { $organizationsql = "AND organization='$currentorg'"; } if ($scoes = get_records_select('scorm_scoes',"scorm='$scorm->id' $organizationsql order by id ASC")){ $level=0; $sublist=1; $previd = 0; $nextid = 0; $parents[$level]='/'; foreach ($scoes as $sco) { if ($parents[$level]!=$sco->parent) { if ($level>0 && $parents[$level-1]==$sco->parent) { echo "\t\t
\n"; $level--; } else { $i = $level; $closelist = ''; while (($i > 0) && ($parents[$level] != $sco->parent)) { $closelist .= "\t\t\n"; $i--; } if (($i == 0) && ($sco->parent != $currentorg)) { echo "\t\t
    • \n"; $level++; } else { echo $closelist; $level = $i; } $parents[$level]=$sco->parent; } } echo "\t\t
    • "; $nextsco = next($scoes); if (($nextsco !== false) && ($sco->parent != $nextsco->parent) && (($level==0) || (($level>0) && ($nextsco->parent == $sco->identifier)))) { $sublist++; echo ''.$strexpand.''; } else { echo ''; } if ($sco->launch) { $startbold = ''; $endbold = ''; $score = ''; if ($usertrack=scorm_get_tracks($sco->id,$USER->id)) { if ( $usertrack->status == '') { $usertrack->status = 'notattempted'; } $strstatus = get_string($usertrack->status,'scorm'); echo "$strstatus"; if (($usertrack->status == 'notattempted') || ($usertrack->status == 'incomplete')) { $incomplete = true; if ($play && empty($scoid)) { $scoid = $sco->id; } } if ($usertrack->score_raw != '') { $score = '('.get_string('score','scorm').': '.$usertrack->score_raw.')'; } } else { if ($play && empty($scoid)) { $scoid = $sco->id; } if ($sco->scormtype == 'sco') { echo ''.get_string('notattempted','scorm').''; $incomplete = true; } else { echo ''.get_string('asset','scorm').''; } } if ($sco->id == $scoid) { $startbold = '> '; $endbold = ' <'; if ($nextsco !== false) { $nextid = $nextsco->id; } else { $nextid = 0; } } if (($nextid == 0) && (scorm_count_launchable($scorm->id,$currentorg) > 1)) { $previd = $sco->id; } echo " $startbold$sco->title $score$endbold
    • \n"; } else { echo " $sco->title\n"; } } for ($i=0;$i<$level;$i++) { echo "\t\t
  • \n"; } } echo "\t\n"; if ($play) { $result->id = $scoid; $result->prev = $previd; $result->next = $nextid; return $result; } else { return $incomplete; } } ?>