|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 // This file is part of Moodle - http://moodle.org/ 00003 // 00004 // Moodle is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // Moodle is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00016 00017 function scorm_get_resources($blocks) { 00018 $resources = array(); 00019 foreach ($blocks as $block) { 00020 if ($block['name'] == 'RESOURCES' && isset($block['children'])) { 00021 foreach ($block['children'] as $resource) { 00022 if ($resource['name'] == 'RESOURCE') { 00023 $resources[addslashes_js($resource['attrs']['IDENTIFIER'])] = $resource['attrs']; 00024 } 00025 } 00026 } 00027 } 00028 return $resources; 00029 } 00030 00031 function scorm_get_manifest($blocks, $scoes) { 00032 global $OUTPUT; 00033 static $parents = array(); 00034 static $resources; 00035 00036 static $manifest; 00037 static $organization; 00038 00039 $manifestresourcesnotfound = array(); 00040 if (count($blocks) > 0) { 00041 foreach ($blocks as $block) { 00042 switch ($block['name']) { 00043 case 'METADATA': 00044 if (isset($block['children'])) { 00045 foreach ($block['children'] as $metadata) { 00046 if ($metadata['name'] == 'SCHEMAVERSION') { 00047 if (empty($scoes->version)) { 00048 if (isset($metadata['tagData']) && (preg_match("/^(1\.2)$|^(CAM )?(1\.3)$/", $metadata['tagData'], $matches))) { 00049 $scoes->version = 'SCORM_'.$matches[count($matches)-1]; 00050 } else { 00051 if (isset($metadata['tagData']) && (preg_match("/^2004 (3rd|4th) Edition$/", $metadata['tagData'], $matches))) { 00052 $scoes->version = 'SCORM_1.3'; 00053 } else { 00054 $scoes->version = 'SCORM_1.2'; 00055 } 00056 } 00057 } 00058 } 00059 } 00060 } 00061 break; 00062 case 'MANIFEST': 00063 $manifest = $block['attrs']['IDENTIFIER']; 00064 $organization = ''; 00065 $resources = array(); 00066 $resources = scorm_get_resources($block['children']); 00067 $scoes = scorm_get_manifest($block['children'], $scoes); 00068 if (empty($scoes->elements) || count($scoes->elements) <= 0) { 00069 foreach ($resources as $item => $resource) { 00070 if (!empty($resource['HREF'])) { 00071 $sco = new stdClass(); 00072 $sco->identifier = $item; 00073 $sco->title = $item; 00074 $sco->parent = '/'; 00075 $sco->launch = $resource['HREF']; 00076 $sco->scormtype = $resource['ADLCP:SCORMTYPE']; 00077 $scoes->elements[$manifest][$organization][$item] = $sco; 00078 } 00079 } 00080 } 00081 break; 00082 case 'ORGANIZATIONS': 00083 if (!isset($scoes->defaultorg) && isset($block['attrs']['DEFAULT'])) { 00084 $scoes->defaultorg = $block['attrs']['DEFAULT']; 00085 } 00086 if (!empty($block['children'])) { 00087 $scoes = scorm_get_manifest($block['children'], $scoes); 00088 } 00089 break; 00090 case 'ORGANIZATION': 00091 $identifier = $block['attrs']['IDENTIFIER']; 00092 $organization = ''; 00093 $scoes->elements[$manifest][$organization][$identifier]->identifier = $identifier; 00094 $scoes->elements[$manifest][$organization][$identifier]->parent = '/'; 00095 $scoes->elements[$manifest][$organization][$identifier]->launch = ''; 00096 $scoes->elements[$manifest][$organization][$identifier]->scormtype = ''; 00097 00098 $parents = array(); 00099 $parent = new stdClass(); 00100 $parent->identifier = $identifier; 00101 $parent->organization = $organization; 00102 array_push($parents, $parent); 00103 $organization = $identifier; 00104 00105 if (!empty($block['children'])) { 00106 $scoes = scorm_get_manifest($block['children'], $scoes); 00107 } 00108 00109 array_pop($parents); 00110 break; 00111 case 'ITEM': 00112 $parent = array_pop($parents); 00113 array_push($parents, $parent); 00114 00115 $identifier = $block['attrs']['IDENTIFIER']; 00116 $scoes->elements[$manifest][$organization][$identifier]->identifier = $identifier; 00117 $scoes->elements[$manifest][$organization][$identifier]->parent = $parent->identifier; 00118 if (!isset($block['attrs']['ISVISIBLE'])) { 00119 $block['attrs']['ISVISIBLE'] = 'true'; 00120 } 00121 $scoes->elements[$manifest][$organization][$identifier]->isvisible = $block['attrs']['ISVISIBLE']; 00122 if (!isset($block['attrs']['PARAMETERS'])) { 00123 $block['attrs']['PARAMETERS'] = ''; 00124 } 00125 $scoes->elements[$manifest][$organization][$identifier]->parameters = $block['attrs']['PARAMETERS']; 00126 if (!isset($block['attrs']['IDENTIFIERREF'])) { 00127 $scoes->elements[$manifest][$organization][$identifier]->launch = ''; 00128 $scoes->elements[$manifest][$organization][$identifier]->scormtype = 'asset'; 00129 } else { 00130 $idref = $block['attrs']['IDENTIFIERREF']; 00131 $base = ''; 00132 if (isset($resources[$idref]['XML:BASE'])) { 00133 $base = $resources[$idref]['XML:BASE']; 00134 } 00135 if (!isset($resources[$idref])) { 00136 $manifestresourcesnotfound[] = $idref; 00137 $scoes->elements[$manifest][$organization][$identifier]->launch = ''; 00138 } else { 00139 $scoes->elements[$manifest][$organization][$identifier]->launch = $base.$resources[$idref]['HREF']; 00140 if (empty($resources[$idref]['ADLCP:SCORMTYPE'])) { 00141 $resources[$idref]['ADLCP:SCORMTYPE'] = 'asset'; 00142 } 00143 $scoes->elements[$manifest][$organization][$identifier]->scormtype = $resources[$idref]['ADLCP:SCORMTYPE']; 00144 } 00145 } 00146 00147 $parent = new stdClass(); 00148 $parent->identifier = $identifier; 00149 $parent->organization = $organization; 00150 array_push($parents, $parent); 00151 00152 if (!empty($block['children'])) { 00153 $scoes = scorm_get_manifest($block['children'], $scoes); 00154 } 00155 00156 array_pop($parents); 00157 break; 00158 case 'TITLE': 00159 $parent = array_pop($parents); 00160 array_push($parents, $parent); 00161 if (!isset($block['tagData'])) { 00162 $block['tagData'] = ''; 00163 } 00164 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->title = $block['tagData']; 00165 break; 00166 case 'ADLCP:PREREQUISITES': 00167 if ($block['attrs']['TYPE'] == 'aicc_script') { 00168 $parent = array_pop($parents); 00169 array_push($parents, $parent); 00170 if (!isset($block['tagData'])) { 00171 $block['tagData'] = ''; 00172 } 00173 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->prerequisites = $block['tagData']; 00174 } 00175 break; 00176 case 'ADLCP:MAXTIMEALLOWED': 00177 $parent = array_pop($parents); 00178 array_push($parents, $parent); 00179 if (!isset($block['tagData'])) { 00180 $block['tagData'] = ''; 00181 } 00182 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->maxtimeallowed = $block['tagData']; 00183 break; 00184 case 'ADLCP:TIMELIMITACTION': 00185 $parent = array_pop($parents); 00186 array_push($parents, $parent); 00187 if (!isset($block['tagData'])) { 00188 $block['tagData'] = ''; 00189 } 00190 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->timelimitaction = $block['tagData']; 00191 break; 00192 case 'ADLCP:DATAFROMLMS': 00193 $parent = array_pop($parents); 00194 array_push($parents, $parent); 00195 if (!isset($block['tagData'])) { 00196 $block['tagData'] = ''; 00197 } 00198 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->datafromlms = $block['tagData']; 00199 break; 00200 case 'ADLCP:MASTERYSCORE': 00201 $parent = array_pop($parents); 00202 array_push($parents, $parent); 00203 if (!isset($block['tagData'])) { 00204 $block['tagData'] = ''; 00205 } 00206 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->masteryscore = $block['tagData']; 00207 break; 00208 case 'ADLCP:COMPLETIONTHRESHOLD': 00209 $parent = array_pop($parents); 00210 array_push($parents, $parent); 00211 if (!isset($block['attrs']['MINPROGRESSMEASURE'])) { 00212 $block['attrs']['MINPROGRESSMEASURE'] = '1.0'; 00213 } 00214 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->threshold = $block['attrs']['MINPROGRESSMEASURE']; 00215 break; 00216 case 'ADLNAV:PRESENTATION': 00217 $parent = array_pop($parents); 00218 array_push($parents, $parent); 00219 if (!empty($block['children'])) { 00220 foreach ($block['children'] as $adlnav) { 00221 if ($adlnav['name'] == 'ADLNAV:NAVIGATIONINTERFACE') { 00222 foreach ($adlnav['children'] as $adlnavInterface) { 00223 if ($adlnavInterface['name'] == 'ADLNAV:HIDELMSUI') { 00224 if ($adlnavInterface['tagData'] == 'continue') { 00225 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hidecontinue = 1; 00226 } 00227 if ($adlnavInterface['tagData'] == 'previous') { 00228 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hideprevious = 1; 00229 } 00230 if ($adlnavInterface['tagData'] == 'exit') { 00231 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hideexit = 1; 00232 } 00233 if ($adlnavInterface['tagData'] == 'exitAll') { 00234 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hideexitall = 1; 00235 } 00236 if ($adlnavInterface['tagData'] == 'abandon') { 00237 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hideabandon = 1; 00238 } 00239 if ($adlnavInterface['tagData'] == 'abandonAll') { 00240 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hideabandonall = 1; 00241 } 00242 if ($adlnavInterface['tagData'] == 'suspendAll') { 00243 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hidesuspendall = 1; 00244 } 00245 } 00246 } 00247 } 00248 } 00249 } 00250 break; 00251 case 'IMSSS:SEQUENCING': 00252 $parent = array_pop($parents); 00253 array_push($parents, $parent); 00254 if (!empty($block['children'])) { 00255 foreach ($block['children'] as $sequencing) { 00256 if ($sequencing['name']=='IMSSS:CONTROLMODE') { 00257 if (isset($sequencing['attrs']['CHOICE'])) { 00258 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->choice = $sequencing['attrs']['CHOICE'] == 'true'?1:0; 00259 } 00260 if (isset($sequencing['attrs']['CHOICEEXIT'])) { 00261 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->choiceexit = $sequencing['attrs']['CHOICEEXIT'] == 'true'?1:0; 00262 } 00263 if (isset($sequencing['attrs']['FLOW'])) { 00264 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->flow = $sequencing['attrs']['FLOW'] == 'true'?1:0; 00265 } 00266 if (isset($sequencing['attrs']['FORWARDONLY'])) { 00267 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->forwardonly = $sequencing['attrs']['FORWARDONLY'] == 'true'?1:0; 00268 } 00269 if (isset($sequencing['attrs']['USECURRENTATTEMPTOBJECTINFO'])) { 00270 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->usecurrentattemptobjectinfo = $sequencing['attrs']['USECURRENTATTEMPTOBJECTINFO'] == 'true'?1:0; 00271 } 00272 if (isset($sequencing['attrs']['USECURRENTATTEMPTPROGRESSINFO'])) { 00273 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->usecurrentattemptprogressinfo = $sequencing['attrs']['USECURRENTATTEMPTPROGRESSINFO'] == 'true'?1:0; 00274 } 00275 } 00276 if ($sequencing['name']=='ADLSEQ:CONSTRAINEDCHOICECONSIDERATIONS') { 00277 if (isset($sequencing['attrs']['CONSTRAINCHOICE'])) { 00278 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->constrainChoice = $sequencing['attrs']['CONSTRAINCHOICE'] == 'true'?1:0; 00279 } 00280 if (isset($sequencing['attrs']['PREVENTACTIVATION'])) { 00281 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->preventactivation = $sequencing['attrs']['PREVENTACTIVATION'] == 'true'?1:0; 00282 } 00283 } 00284 if ($sequencing['name']=='IMSSS:OBJECTIVES') { 00285 $objectives = array(); 00286 foreach ($sequencing['children'] as $objective) { 00287 $objectivedata = new stdClass(); 00288 $objectivedata->primaryobj = 0; 00289 switch ($objective['name']) { 00290 case 'IMSSS:PRIMARYOBJECTIVE': 00291 $objectivedata->primaryobj = 1; 00292 case 'IMSSS:OBJECTIVE': 00293 $objectivedata->satisfiedbymeasure = 0; 00294 if (isset($objective['attrs']['SATISFIEDBYMEASURE'])) { 00295 $objectivedata->satisfiedbymeasure = $objective['attrs']['SATISFIEDBYMEASURE']== 'true'?1:0; 00296 } 00297 $objectivedata->objectiveid = ''; 00298 if (isset($objective['attrs']['OBJECTIVEID'])) { 00299 $objectivedata->objectiveid = $objective['attrs']['OBJECTIVEID']; 00300 } 00301 $objectivedata->minnormalizedmeasure = 1.0; 00302 if (!empty($objective['children'])) { 00303 $mapinfos = array(); 00304 foreach ($objective['children'] as $objectiveparam) { 00305 if ($objectiveparam['name']=='IMSSS:MINNORMALIZEDMEASURE') { 00306 if (isset($objectiveparam['tagData'])) { 00307 $objectivedata->minnormalizedmeasure = $objectiveparam['tagData']; 00308 } else { 00309 $objectivedata->minnormalizedmeasure = 0; 00310 } 00311 } 00312 if ($objectiveparam['name']=='IMSSS:MAPINFO') { 00313 $mapinfo = new stdClass(); 00314 $mapinfo->targetobjectiveid = ''; 00315 if (isset($objectiveparam['attrs']['TARGETOBJECTIVEID'])) { 00316 $mapinfo->targetobjectiveid = $objectiveparam['attrs']['TARGETOBJECTIVEID']; 00317 } 00318 $mapinfo->readsatisfiedstatus = 1; 00319 if (isset($objectiveparam['attrs']['READSATISFIEDSTATUS'])) { 00320 $mapinfo->readsatisfiedstatus = $objectiveparam['attrs']['READSATISFIEDSTATUS'] == 'true'?1:0; 00321 } 00322 $mapinfo->writesatisfiedstatus = 0; 00323 if (isset($objectiveparam['attrs']['WRITESATISFIEDSTATUS'])) { 00324 $mapinfo->writesatisfiedstatus = $objectiveparam['attrs']['WRITESATISFIEDSTATUS'] == 'true'?1:0; 00325 } 00326 $mapinfo->readnormalizemeasure = 1; 00327 if (isset($objectiveparam['attrs']['READNORMALIZEDMEASURE'])) { 00328 $mapinfo->readnormalizemeasure = $objectiveparam['attrs']['READNORMALIZEDMEASURE'] == 'true'?1:0; 00329 } 00330 $mapinfo->writenormalizemeasure = 0; 00331 if (isset($objectiveparam['attrs']['WRITENORMALIZEDMEASURE'])) { 00332 $mapinfo->writenormalizemeasure = $objectiveparam['attrs']['WRITENORMALIZEDMEASURE'] == 'true'?1:0; 00333 } 00334 array_push($mapinfos, $mapinfo); 00335 } 00336 } 00337 if (!empty($mapinfos)) { 00338 $objectivesdata->mapinfos = $mapinfos; 00339 } 00340 } 00341 break; 00342 } 00343 array_push($objectives, $objectivedata); 00344 } 00345 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->objectives = $objectives; 00346 } 00347 if ($sequencing['name']=='IMSSS:LIMITCONDITIONS') { 00348 if (isset($sequencing['attrs']['ATTEMPTLIMIT'])) { 00349 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->attemptLimit = $sequencing['attrs']['ATTEMPTLIMIT']; 00350 } 00351 if (isset($sequencing['attrs']['ATTEMPTABSOLUTEDURATIONLIMIT'])) { 00352 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->attemptAbsoluteDurationLimit = $sequencing['attrs']['ATTEMPTABSOLUTEDURATIONLIMIT']; 00353 } 00354 } 00355 if ($sequencing['name']=='IMSSS:ROLLUPRULES') { 00356 if (isset($sequencing['attrs']['ROLLUPOBJECTIVESATISFIED'])) { 00357 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->rollupobjectivesatisfied = $sequencing['attrs']['ROLLUPOBJECTIVESATISFIED'] == 'true'?1:0;; 00358 } 00359 if (isset($sequencing['attrs']['ROLLUPPROGRESSCOMPLETION'])) { 00360 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->rollupprogresscompletion = $sequencing['attrs']['ROLLUPPROGRESSCOMPLETION'] == 'true'?1:0; 00361 } 00362 if (isset($sequencing['attrs']['OBJECTIVEMEASUREWEIGHT'])) { 00363 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->objectivemeasureweight = $sequencing['attrs']['OBJECTIVEMEASUREWEIGHT']; 00364 } 00365 00366 if (!empty($sequencing['children'])) { 00367 $rolluprules = array(); 00368 foreach ($sequencing['children'] as $sequencingrolluprule) { 00369 if ($sequencingrolluprule['name']=='IMSSS:ROLLUPRULE' ) { 00370 $rolluprule = new stdClass(); 00371 $rolluprule->childactivityset = 'all'; 00372 if (isset($sequencingrolluprule['attrs']['CHILDACTIVITYSET'])) { 00373 $rolluprule->childactivityset = $sequencingrolluprule['attrs']['CHILDACTIVITYSET']; 00374 } 00375 $rolluprule->minimumcount = 0; 00376 if (isset($sequencingrolluprule['attrs']['MINIMUMCOUNT'])) { 00377 $rolluprule->minimumcount = $sequencingrolluprule['attrs']['MINIMUMCOUNT']; 00378 } 00379 $rolluprule->minimumpercent = 0.0000; 00380 if (isset($sequencingrolluprule['attrs']['MINIMUMPERCENT'])) { 00381 $rolluprule->minimumpercent = $sequencingrolluprule['attrs']['MINIMUMPERCENT']; 00382 } 00383 if (!empty($sequencingrolluprule['children'])) { 00384 foreach ($sequencingrolluprule['children'] as $rolluproleconditions) { 00385 if ($rolluproleconditions['name']=='IMSSS:ROLLUPCONDITIONS') { 00386 $conditions = array(); 00387 $rolluprule->conditioncombination = 'all'; 00388 if (isset($rolluproleconditions['attrs']['CONDITIONCOMBINATION'])) { 00389 $rolluprule->conditioncombination = $rolluproleconditions['attrs']['CONDITIONCOMBINATION']; 00390 } 00391 foreach ($rolluproleconditions['children'] as $rolluprulecondition) { 00392 if ($rolluprulecondition['name']=='IMSSS:ROLLUPCONDITION') { 00393 $condition = new stdClass(); 00394 if (isset($rolluprulecondition['attrs']['CONDITION'])) { 00395 $condition->cond = $rolluprulecondition['attrs']['CONDITION']; 00396 } 00397 $condition->operator = 'noOp'; 00398 if (isset($rolluprulecondition['attrs']['OPERATOR'])) { 00399 $condition->operator = $rolluprulecondition['attrs']['OPERATOR']; 00400 } 00401 array_push($conditions, $condition); 00402 } 00403 } 00404 $rolluprule->conditions = $conditions; 00405 } 00406 if ($rolluproleconditions['name']=='IMSSS:ROLLUPACTION') { 00407 $rolluprule->rollupruleaction = $rolluproleconditions['attrs']['ACTION']; 00408 } 00409 } 00410 } 00411 array_push($rolluprules, $rolluprule); 00412 } 00413 } 00414 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->rolluprules = $rolluprules; 00415 } 00416 } 00417 00418 if ($sequencing['name']=='IMSSS:SEQUENCINGRULES') { 00419 if (!empty($sequencing['children'])) { 00420 $sequencingrules = array(); 00421 foreach ($sequencing['children'] as $conditionrules) { 00422 $conditiontype = -1; 00423 switch($conditionrules['name']) { 00424 case 'IMSSS:PRECONDITIONRULE': 00425 $conditiontype = 0; 00426 break; 00427 case 'IMSSS:POSTCONDITIONRULE': 00428 $conditiontype = 1; 00429 break; 00430 case 'IMSSS:EXITCONDITIONRULE': 00431 $conditiontype = 2; 00432 break; 00433 } 00434 if (!empty($conditionrules['children'])) { 00435 $sequencingrule = new stdClass(); 00436 foreach ($conditionrules['children'] as $conditionrule) { 00437 if ($conditionrule['name']=='IMSSS:RULECONDITIONS') { 00438 $ruleconditions = array(); 00439 $sequencingrule->conditioncombination = 'all'; 00440 if (isset($conditionrule['attrs']['CONDITIONCOMBINATION'])) { 00441 $sequencingrule->conditioncombination = $conditionrule['attrs']['CONDITIONCOMBINATION']; 00442 } 00443 foreach ($conditionrule['children'] as $rulecondition) { 00444 if ($rulecondition['name']=='IMSSS:RULECONDITION') { 00445 $condition = new stdClass(); 00446 if (isset($rulecondition['attrs']['CONDITION'])) { 00447 $condition->cond = $rulecondition['attrs']['CONDITION']; 00448 } 00449 $condition->operator = 'noOp'; 00450 if (isset($rulecondition['attrs']['OPERATOR'])) { 00451 $condition->operator = $rulecondition['attrs']['OPERATOR']; 00452 } 00453 $condition->measurethreshold = 0.0000; 00454 if (isset($rulecondition['attrs']['MEASURETHRESHOLD'])) { 00455 $condition->measurethreshold = $rulecondition['attrs']['MEASURETHRESHOLD']; 00456 } 00457 $condition->referencedobjective = ''; 00458 if (isset($rulecondition['attrs']['REFERENCEDOBJECTIVE'])) { 00459 $condition->referencedobjective = $rulecondition['attrs']['REFERENCEDOBJECTIVE']; 00460 } 00461 array_push($ruleconditions, $condition); 00462 } 00463 } 00464 $sequencingrule->ruleconditions = $ruleconditions; 00465 } 00466 if ($conditionrule['name']=='IMSSS:RULEACTION') { 00467 $sequencingrule->action = $conditionrule['attrs']['ACTION']; 00468 } 00469 $sequencingrule->type = $conditiontype; 00470 } 00471 array_push($sequencingrules, $sequencingrule); 00472 } 00473 } 00474 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->sequencingrules = $sequencingrules; 00475 } 00476 } 00477 } 00478 } 00479 break; 00480 } 00481 } 00482 } 00483 if (!empty($manifestresourcesnotfound)) { 00484 //throw warning to user to let them know manifest contains references to resources that don't appear to exist. 00485 if (!defined('DEBUGGING_PRINTED')) { //prevent redirect and display warning 00486 define('DEBUGGING_PRINTED', 1); 00487 } 00488 echo $OUTPUT->notification(get_string('invalidmanifestresource', 'scorm').' '. implode(', ',$manifestresourcesnotfound)); 00489 } 00490 return $scoes; 00491 } 00492 00493 function scorm_parse_scorm($scorm, $manifest) { 00494 global $CFG, $DB; 00495 00496 // load manifest into string 00497 if ($manifest instanceof stored_file) { 00498 $xmltext = $manifest->get_content(); 00499 } else { 00500 require_once("$CFG->libdir/filelib.php"); 00501 $xmltext = download_file_content($manifest); 00502 } 00503 00504 $launch = 0; 00505 00506 $pattern = '/&(?!\w{2,6};)/'; 00507 $replacement = '&'; 00508 $xmltext = preg_replace($pattern, $replacement, $xmltext); 00509 00510 $objXML = new xml2Array(); 00511 $manifests = $objXML->parse($xmltext); 00512 $scoes = new stdClass(); 00513 $scoes->version = ''; 00514 $scoes = scorm_get_manifest($manifests, $scoes); 00515 if (count($scoes->elements) > 0) { 00516 $olditems = $DB->get_records('scorm_scoes', array('scorm'=>$scorm->id)); 00517 foreach ($scoes->elements as $manifest => $organizations) { 00518 foreach ($organizations as $organization => $items) { 00519 foreach ($items as $identifier => $item) { 00520 // This new db mngt will support all SCORM future extensions 00521 $newitem = new stdClass(); 00522 $newitem->scorm = $scorm->id; 00523 $newitem->manifest = $manifest; 00524 $newitem->organization = $organization; 00525 $standarddatas = array('parent', 'identifier', 'launch', 'scormtype', 'title'); 00526 foreach ($standarddatas as $standarddata) { 00527 if (isset($item->$standarddata)) { 00528 $newitem->$standarddata = $item->$standarddata; 00529 } 00530 } 00531 00532 // Insert the new SCO, and retain the link between the old and new for later adjustment 00533 $id = $DB->insert_record('scorm_scoes', $newitem); 00534 if (!empty($olditems) && ($olditemid = scorm_array_search('identifier', $newitem->identifier, $olditems))) { 00535 $olditems[$olditemid]->newid = $id; 00536 } 00537 00538 if ($optionaldatas = scorm_optionals_data($item, $standarddatas)) { 00539 $data = new stdClass(); 00540 $data->scoid = $id; 00541 foreach ($optionaldatas as $optionaldata) { 00542 if (isset($item->$optionaldata)) { 00543 $data->name = $optionaldata; 00544 $data->value = $item->$optionaldata; 00545 $dataid = $DB->insert_record('scorm_scoes_data', $data); 00546 } 00547 } 00548 } 00549 00550 if (isset($item->sequencingrules)) { 00551 foreach ($item->sequencingrules as $sequencingrule) { 00552 $rule = new stdClass(); 00553 $rule->scoid = $id; 00554 $rule->ruletype = $sequencingrule->type; 00555 $rule->conditioncombination = $sequencingrule->conditioncombination; 00556 $rule->action = $sequencingrule->action; 00557 $ruleid = $DB->insert_record('scorm_seq_ruleconds', $rule); 00558 if (isset($sequencingrule->ruleconditions)) { 00559 foreach ($sequencingrule->ruleconditions as $rulecondition) { 00560 $rulecond = new stdClass(); 00561 $rulecond->scoid = $id; 00562 $rulecond->ruleconditionsid = $ruleid; 00563 $rulecond->referencedobjective = $rulecondition->referencedobjective; 00564 $rulecond->measurethreshold = $rulecondition->measurethreshold; 00565 $rulecond->cond = $rulecondition->cond; 00566 $rulecondid = $DB->insert_record('scorm_seq_rulecond', $rulecond); 00567 } 00568 } 00569 } 00570 } 00571 00572 if (isset($item->rolluprules)) { 00573 foreach ($item->rolluprules as $rolluprule) { 00574 $rollup = new stdClass(); 00575 $rollup->scoid = $id; 00576 $rollup->childactivityset = $rolluprule->childactivityset; 00577 $rollup->minimumcount = $rolluprule->minimumcount; 00578 $rollup->minimumpercent = $rolluprule->minimumpercent; 00579 $rollup->rollupruleaction = $rolluprule->rollupruleaction; 00580 $rollup->conditioncombination = $rolluprule->conditioncombination; 00581 00582 $rollupruleid = $DB->insert_record('scorm_seq_rolluprule', $rollup); 00583 if (isset($rollup->conditions)) { 00584 foreach ($rollup->conditions as $condition) { 00585 $cond = new stdClass(); 00586 $cond->scoid = $rollup->scoid; 00587 $cond->rollupruleid = $rollupruleid; 00588 $cond->operator = $condition->operator; 00589 $cond->cond = $condition->cond; 00590 $conditionid = $DB->insert_record('scorm_seq_rolluprulecond', $cond); 00591 } 00592 } 00593 } 00594 } 00595 00596 if (isset($item->objectives)) { 00597 foreach ($item->objectives as $objective) { 00598 $obj = new stdClass(); 00599 $obj->scoid = $id; 00600 $obj->primaryobj = $objective->primaryobj; 00601 $obj->satisfiedbumeasure = $objective->satisfiedbymeasure; 00602 $obj->objectiveid = $objective->objectiveid; 00603 $obj->minnormalizedmeasure = trim($objective->minnormalizedmeasure); 00604 $objectiveid = $DB->insert_record('scorm_seq_objective', $obj); 00605 if (isset($objective->mapinfos)) { 00606 foreach ($objective->mapinfos as $objmapinfo) { 00607 $mapinfo = new stdClass(); 00608 $mapinfo->scoid = $id; 00609 $mapinfo->objectiveid = $objectiveid; 00610 $mapinfo->targetobjectiveid = $objmapinfo->targetobjectiveid; 00611 $mapinfo->readsatisfiedstatus = $objmapinfo->readsatisfiedstatus; 00612 $mapinfo->writesatisfiedstatus = $objmapinfo->writesatisfiedstatus; 00613 $mapinfo->readnormalizedmeasure = $objmapinfo->readnormalizedmeasure; 00614 $mapinfo->writenormalizedmeasure = $objmapinfo->writenormalizedmeasure; 00615 $mapinfoid = $DB->insert_record('scorm_seq_mapinfo', $mapinfo); 00616 } 00617 } 00618 } 00619 } 00620 if (($launch == 0) && ((empty($scoes->defaultorg)) || ($scoes->defaultorg == $identifier))) { 00621 $launch = $id; 00622 } 00623 } 00624 } 00625 } 00626 if (!empty($olditems)) { 00627 foreach ($olditems as $olditem) { 00628 $DB->delete_records('scorm_scoes', array('id'=>$olditem->id)); 00629 $DB->delete_records('scorm_scoes_data', array('scoid'=>$olditem->id)); 00630 if (isset($olditem->newid)) { 00631 $DB->set_field('scorm_scoes_track', 'scoid', $olditem->newid, array('scoid' => $olditem->id)); 00632 } 00633 $DB->delete_records('scorm_scoes_track', array('scoid'=>$olditem->id)); 00634 $DB->delete_records('scorm_seq_objective', array('scoid'=>$olditem->id)); 00635 $DB->delete_records('scorm_seq_mapinfo', array('scoid'=>$olditem->id)); 00636 $DB->delete_records('scorm_seq_ruleconds', array('scoid'=>$olditem->id)); 00637 $DB->delete_records('scorm_seq_rulecond', array('scoid'=>$olditem->id)); 00638 $DB->delete_records('scorm_seq_rolluprule', array('scoid'=>$olditem->id)); 00639 $DB->delete_records('scorm_seq_rolluprulecond', array('scoid'=>$olditem->id)); 00640 } 00641 } 00642 if (empty($scoes->version)) { 00643 $scoes->version = 'SCORM_1.2'; 00644 } 00645 $DB->set_field('scorm', 'version', $scoes->version, array('id'=>$scorm->id)); 00646 $scorm->version = $scoes->version; 00647 } 00648 00649 $scorm->launch = $launch; 00650 00651 return true; 00652 } 00653 00654 function scorm_optionals_data($item, $standarddata) { 00655 $result = array(); 00656 $sequencingdata = array('sequencingrules', 'rolluprules', 'objectives'); 00657 foreach ($item as $element => $value) { 00658 if (! in_array($element, $standarddata)) { 00659 if (! in_array($element, $sequencingdata)) { 00660 $result[] = $element; 00661 } 00662 } 00663 } 00664 return $result; 00665 } 00666 00667 function scorm_is_leaf($sco) { 00668 global $DB; 00669 00670 if ($DB->get_record('scorm_scoes', array('scorm'=>$sco->scorm, 'parent'=>$sco->identifier))) { 00671 return false; 00672 } 00673 return true; 00674 } 00675 00676 function scorm_get_parent($sco) { 00677 global $DB; 00678 00679 if ($sco->parent != '/') { 00680 if ($parent = $DB->get_record('scorm_scoes', array('scorm'=>$sco->scorm, 'identifier'=>$sco->parent))) { 00681 return scorm_get_sco($parent->id); 00682 } 00683 } 00684 return null; 00685 } 00686 00687 function scorm_get_children($sco) { 00688 global $DB; 00689 00690 if ($children = $DB->get_records('scorm_scoes', array('scorm'=>$sco->scorm, 'parent'=>$sco->identifier))) {//originally this said parent instead of childrean 00691 return $children; 00692 } 00693 return null; 00694 } 00695 00696 function scorm_get_available_children($sco) { // TODO: undefined vars!!! 00697 global $DB; 00698 00699 $res = $DB->get_record('scorm_scoes_track', array('scoid'=>$scoid, 00700 'userid'=>$userid, 00701 'element'=>'availablechildren')); 00702 if (!$res || $res == null) { 00703 return false; 00704 } else { 00705 return unserialize($res->value); 00706 } 00707 } 00708 00709 function scorm_get_available_descendent($descend = array(), $sco) { 00710 if ($sco == null) { 00711 return $descend; 00712 } else { 00713 $avchildren = scorm_get_available_children($sco); 00714 foreach ($avchildren as $avchild) { 00715 array_push($descend, $avchild); 00716 } 00717 foreach ($avchildren as $avchild) { 00718 scorm_get_available_descendent($descend, $avchild); 00719 } 00720 } 00721 } 00722 00723 function scorm_get_siblings($sco) { 00724 global $DB; 00725 00726 if ($siblings = $DB->get_records('scorm_scoes', array('scorm'=>$sco->scorm, 'parent'=>$sco->parent))) { 00727 unset($siblings[$sco->id]); 00728 if (!empty($siblings)) { 00729 return $siblings; 00730 } 00731 } 00732 return null; 00733 } 00734 //get an array that contains all the parent scos for this sco. 00735 function scorm_get_ancestors($sco) { 00736 $ancestors = array(); 00737 $continue = true; 00738 while ($continue) { 00739 $ancestor = scorm_get_parent($sco); 00740 if (!empty($ancestor) && $ancestor->id !== $sco->id) { 00741 $sco = $ancestor; 00742 $ancestors[] = $ancestor; 00743 if ($sco->parent == '/') { 00744 $continue = false; 00745 } 00746 } else { 00747 $continue = false; 00748 } 00749 } 00750 return $ancestors; 00751 } 00752 00753 function scorm_get_preorder($preorder=array(), $sco) { 00754 if ($sco != null) { 00755 array_push($preorder, $sco); 00756 $children = scorm_get_children($sco); 00757 foreach ($children as $child) { 00758 scorm_get_preorder($sco); 00759 } 00760 } else { 00761 return $preorder; 00762 } 00763 } 00764 00765 function scorm_find_common_ancestor($ancestors, $sco) { 00766 $pos = scorm_array_search('identifier', $sco->parent, $ancestors); 00767 if ($sco->parent != '/') { 00768 if ($pos === false) { 00769 return scorm_find_common_ancestor($ancestors, scorm_get_parent($sco)); 00770 } 00771 } 00772 return $pos; 00773 } 00774 00775 /* Usage 00776 Grab some XML data, either from a file, URL, etc. however you want. Assume storage in $strYourXML; 00777 00778 $objXML = new xml2Array(); 00779 $arrOutput = $objXML->parse($strYourXML); 00780 print_r($arrOutput); //print it out, or do whatever! 00781 00782 */ 00783 class xml2Array { 00784 00785 var $arrOutput = array(); 00786 var $resParser; 00787 var $strXmlData; 00788 00795 function utf8_to_entities($str) { 00796 global $CFG; 00797 00798 $entities = ''; 00799 $values = array(); 00800 $lookingfor = 1; 00801 00802 return $str; 00803 } 00804 00811 function parse($strInputXML) { 00812 $this->resParser = xml_parser_create ('UTF-8'); 00813 xml_set_object($this->resParser, $this); 00814 xml_set_element_handler($this->resParser, "tagOpen", "tagClosed"); 00815 00816 xml_set_character_data_handler($this->resParser, "tagData"); 00817 00818 $this->strXmlData = xml_parse($this->resParser, $strInputXML ); 00819 if (!$this->strXmlData) { 00820 die(sprintf("XML error: %s at line %d", 00821 xml_error_string(xml_get_error_code($this->resParser)), 00822 xml_get_current_line_number($this->resParser))); 00823 } 00824 00825 xml_parser_free($this->resParser); 00826 00827 return $this->arrOutput; 00828 } 00829 00830 function tagOpen($parser, $name, $attrs) { 00831 $tag=array("name"=>$name, "attrs"=>$attrs); 00832 array_push($this->arrOutput, $tag); 00833 } 00834 00835 function tagData($parser, $tagData) { 00836 if (trim($tagData)) { 00837 if (isset($this->arrOutput[count($this->arrOutput)-1]['tagData'])) { 00838 $this->arrOutput[count($this->arrOutput)-1]['tagData'] .= $this->utf8_to_entities($tagData); 00839 } else { 00840 $this->arrOutput[count($this->arrOutput)-1]['tagData'] = $this->utf8_to_entities($tagData); 00841 } 00842 } 00843 } 00844 00845 function tagClosed($parser, $name) { 00846 $this->arrOutput[count($this->arrOutput)-2]['children'][] = $this->arrOutput[count($this->arrOutput)-1]; 00847 array_pop($this->arrOutput); 00848 } 00849 00850 }