From 28a774b13efeeb58bf3da87ee42aece44d489d61 Mon Sep 17 00:00:00 2001 From: bobopinna Date: Wed, 13 Jul 2005 20:11:56 +0000 Subject: [PATCH] Fixed some manifest parsing problems and a structure display bug --- mod/scorm/lib.php | 421 +++++++++++++++++++++------------------------- 1 file changed, 195 insertions(+), 226 deletions(-) diff --git a/mod/scorm/lib.php b/mod/scorm/lib.php index 5c424d5fca7..9b5d82bb1ba 100755 --- a/mod/scorm/lib.php +++ b/mod/scorm/lib.php @@ -3,6 +3,8 @@ /// Library of functions and constants for module scorm /// (replace scorm with the name of your module and delete this line) +require_once('xml2array.class.php'); // Used to parse manifest + define('VALUESCOES', '0'); define('VALUEHIGHEST', '1'); define('VALUEAVERAGE', '2'); @@ -517,118 +519,6 @@ function scorm_scandir($directory) { } } -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; - - $datacontent = trim($datacontent); - - if ($name == 'ITEM') { - $level--; - } - //if ($name == 'TITLE' && $level>0) { - if (($name == 'TITLE') && !isset($scoes[$i]['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("/^(1\.2)$|^(CAM )?(1\.3)$/",$datacontent,$matches)) { - $version = 'SCORM_'.$matches[count($matches)-1]; - } else { - $version = 'SCORM_1.2'; - } - } - $datacontent = ''; -} - -function scorm_characterData($parser, $data) { - global $datacontent; - $datacontent .= utf8_decode($data); -} - function scorm_parse($pkgdir,$pkgtype,$scormid){ delete_records('scorm_scoes','scorm',$scormid); delete_records('scorm_scoes_track','scormid',$scormid); @@ -636,7 +526,7 @@ function scorm_parse($pkgdir,$pkgtype,$scormid){ if ($pkgtype == 'AICC') { return scorm_parse_aicc($pkgdir,$scormid); } else { - return scorm_parse_scorm($pkgdir,'/imsmanifest.xml',$scormid); + return scorm_parse_scorm($pkgdir.'/imsmanifest.xml',$scormid); } } @@ -823,120 +713,197 @@ function scorm_parse_aicc($pkgdir,$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; - - if (isset($scoes[1])) { - for ($j=1; $j<=$i; $j++) { - $sco->identifier = $scoes[$j]['identifier']; - $sco->parent = $scoes[$j]['parent']; - if (!isset($scoes[$j]['title'])) { - $scoes[$j]['title'] = ''; - } - $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; +function scorm_get_resources($blocks) { + foreach ($blocks as $block) { + if ($block['name'] == 'RESOURCES') { + foreach ($block['children'] as $resource) { + if ($resource['name'] == 'RESOURCE') { + $resources[addslashes($resource['attrs']['IDENTIFIER'])] = $resource['attrs']; } } } } - set_field('scorm','version',$version,'id',$scormid); + return $resources; +} + +function scorm_get_manifest($blocks,$scoes) { + static $parents = array(); + static $resources; + + static $manifest; + static $organization; + + if (count($blocks) > 0) { + foreach ($blocks as $block) { + switch ($block['name']) { + case 'METADATA': + if (isset($block['children'])) { + foreach ($block['children'] as $metadata) { + if ($metadata['name'] == 'SCHEMAVERSION') { + if (empty($scoes->version)) { + if (preg_match("/^(1\.2)$|^(CAM )?(1\.3)$/",$metadata['tagData'],$matches)) { + $scoes->version = 'SCORM_'.$matches[count($matches)-1]; + } else { + $scoes->version = 'SCORM_1.2'; + } + } + } + } + } + break; + case 'MANIFEST': + $manifest = addslashes($block['attrs']['IDENTIFIER']); + $organization = ''; + $resources = array(); + $resources = scorm_get_resources($block['children']); + $scoes = scorm_get_manifest($block['children'],$scoes); + if (count($scoes->elements) <= 0) { + foreach ($resources as $item => $resource) { + if (!empty($resource['HREF'])) { + $sco = new stdClass(); + $sco->identifier = $item; + $sco->title = $item; + $sco->parent = '/'; + $sco->launch = addslashes($resource['HREF']); + $sco->scormtype = addslashes($resource['ADLCP:SCORMTYPE']); + $scoes->elements[$manifest][$organization][$item] = $sco; + } + } + } + break; + case 'ORGANIZATIONS': + if (!isset($scoes->defaultorg)) { + $scoes->defaultorg = addslashes($block['attrs']['DEFAULT']); + } + $scoes = scorm_get_manifest($block['children'],$scoes); + break; + case 'ORGANIZATION': + $identifier = addslashes($block['attrs']['IDENTIFIER']); + $organization = ''; + $scoes->elements[$manifest][$organization][$identifier]->identifier = $identifier; + $scoes->elements[$manifest][$organization][$identifier]->parent = '/'; + $scoes->elements[$manifest][$organization][$identifier]->launch = ''; + $scoes->elements[$manifest][$organization][$identifier]->scormtype = ''; + + $parents = array(); + $parent = new stdClass(); + $parent->identifier = $identifier; + $parent->organization = $organization; + array_push($parents, $parent); + $organization = $identifier; + + $scoes = scorm_get_manifest($block['children'],$scoes); + + array_pop($parents); + break; + case 'ITEM': + $parent = array_pop($parents); + array_push($parents, $parent); + + $identifier = addslashes($block['attrs']['IDENTIFIER']); + $scoes->elements[$manifest][$organization][$identifier]->identifier = $identifier; + $scoes->elements[$manifest][$organization][$identifier]->parent = $parent->identifier; + if (!isset($block['attrs']['ISVISIBLE'])) { + $block['attrs']['ISVISIBLE'] = 'true'; + } + $scoes->elements[$manifest][$organization][$identifier]->isvisible = addslashes($block['attrs']['ISVISIBLE']); + if (!isset($block['attrs']['PARAMETERS'])) { + $block['attrs']['PARAMETERS'] = ''; + } + $scoes->elements[$manifest][$organization][$identifier]->parameters = addslashes($block['attrs']['PARAMETERS']); + if (!isset($block['attrs']['IDENTIFIERREF'])) { + $scoes->elements[$manifest][$organization][$identifier]->launch = ''; + $scoes->elements[$manifest][$organization][$identifier]->scormtype = 'asset'; + } else { + $idref = addslashes($block['attrs']['IDENTIFIERREF']); + $scoes->elements[$manifest][$organization][$identifier]->launch = addslashes($resources[$idref]['HREF']); + if (empty($resources[$idref]['ADLCP:SCORMTYPE'])) { + $resources[$idref]['ADLCP:SCORMTYPE'] = 'asset'; + } + $scoes->elements[$manifest][$organization][$identifier]->scormtype = addslashes($resources[$idref]['ADLCP:SCORMTYPE']); + } + + $parent = new stdClass(); + $parent->identifier = $identifier; + $parent->organization = $organization; + array_push($parents, $parent); + + $scoes = scorm_get_manifest($block['children'],$scoes); + + array_pop($parents); + break; + case 'TITLE': + $parent = array_pop($parents); + array_push($parents, $parent); + $scoes->elements[$manifest][$parent->organization][$parent->identifier]->title = addslashes($block['tagData']); + break; + case 'ADLCP:PREREQUISITES': + if ($block['attrs']['TYPE'] == 'aicc_script') { + $parent = array_pop($parents); + array_push($parents, $parent); + $scoes->elements[$manifest][$parent->organization][$parent->identifier]->prerequisites = addslashes($block['tagData']); + } + break; + case 'ADLCP:MAXTIMEALLOWED': + $parent = array_pop($parents); + array_push($parents, $parent); + $scoes->elements[$manifest][$parent->organization][$parent->identifier]->maxtimeallowed = addslashes($block['tagData']); + break; + case 'ADLCP:TIMELIMITACTION': + $parent = array_pop($parents); + array_push($parents, $parent); + $scoes->elements[$manifest][$parent->organization][$parent->identifier]->timelimitaction = addslashes($block['tagData']); + break; + case 'ADLCP:DATAFROMLMS': + $parent = array_pop($parents); + array_push($parents, $parent); + $scoes->elements[$manifest][$parent->organization][$parent->identifier]->datafromlms = addslashes($block['tagData']); + break; + case 'ADLCP:MASTERYSCORE': + $parent = array_pop($parents); + array_push($parents, $parent); + $scoes->elements[$manifest][$parent->organization][$parent->identifier]->masteryscore = addslashes($block['tagData']); + break; + } + } + } + + return $scoes; +} + + +function scorm_parse_scorm($manifestfile,$scormid) { + + $launch = 0; + + if (is_file($manifestfile)) { + $xmlstring = file_get_contents($manifestfile); + $objXML = new xml2Array(); + $manifests = $objXML->parse($xmlstring); + + $scoes = new stdClass(); + $scoes->version = 'SCORM'; + $scoes = scorm_get_manifest($manifests,$scoes); + + if (count($scoes->elements) > 0) { + foreach ($scoes->elements as $manifest => $organizations) { + foreach ($organizations as $organization => $items) { + foreach ($items as $identifier => $item) { + $item->scorm = $scormid; + $item->manifest = $manifest; + $item->organization = $organization; + $id = insert_record('scorm_scoes',$item); + + if (($launch == 0) && ((empty($scoes->defaultorg)) || ($scoes->defaultorg == $identifier))) { + $launch = $id; + } + } + } + } + set_field('scorm','version',$scoes->version,'id',$scormid); + } + } + return $launch; } @@ -1050,9 +1017,11 @@ function scorm_display_structure($scorm,$liststyle,$currentorg='',$scoid='',$mod $parents[$level]='/'; foreach ($scoes as $sco) { if ($parents[$level]!=$sco->parent) { - if ($level>0 && $parents[$level-1]==$sco->parent) { - echo "\t\t\n"; - $level--; + if ($newlevel = array_search($sco->parent,$parents)) { + for ($i=0; $i<($level-$newlevel); $i++) { + echo "\t\t\n"; + } + $level = $newlevel; } else { $i = $level; $closelist = '';