[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * functions used by SCORM 1.2/2004 packages. 19 * 20 * @package mod_scorm 21 * @copyright 1999 onwards Roberto Pinna 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 function scorm_get_resources($blocks) { 26 $resources = array(); 27 foreach ($blocks as $block) { 28 if ($block['name'] == 'RESOURCES' && isset($block['children'])) { 29 foreach ($block['children'] as $resource) { 30 if ($resource['name'] == 'RESOURCE') { 31 $resources[addslashes_js($resource['attrs']['IDENTIFIER'])] = $resource['attrs']; 32 } 33 } 34 } 35 } 36 return $resources; 37 } 38 39 function scorm_get_manifest($blocks, $scoes) { 40 global $OUTPUT; 41 static $parents = array(); 42 static $resources; 43 44 static $manifest; 45 static $organization; 46 47 $manifestresourcesnotfound = array(); 48 if (count($blocks) > 0) { 49 foreach ($blocks as $block) { 50 switch ($block['name']) { 51 case 'METADATA': 52 if (isset($block['children'])) { 53 foreach ($block['children'] as $metadata) { 54 if ($metadata['name'] == 'SCHEMAVERSION') { 55 if (empty($scoes->version)) { 56 $isversionset = (preg_match("/^(1\.2)$|^(CAM )?(1\.3)$/", $metadata['tagData'], $matches)); 57 if (isset($metadata['tagData']) && $isversionset) { 58 $scoes->version = 'SCORM_'.$matches[count($matches) - 1]; 59 } else { 60 $isversionset = (preg_match("/^2004 (3rd|4th) Edition$/", $metadata['tagData'], $matches)); 61 if (isset($metadata['tagData']) && $isversionset) { 62 $scoes->version = 'SCORM_1.3'; 63 } else { 64 $scoes->version = 'SCORM_1.2'; 65 } 66 } 67 } 68 } 69 } 70 } 71 break; 72 case 'MANIFEST': 73 $manifest = $block['attrs']['IDENTIFIER']; 74 $organization = ''; 75 $resources = array(); 76 $resources = scorm_get_resources($block['children']); 77 $scoes = scorm_get_manifest($block['children'], $scoes); 78 if (empty($scoes->elements) || count($scoes->elements) <= 0) { 79 foreach ($resources as $item => $resource) { 80 if (!empty($resource['HREF'])) { 81 $sco = new stdClass(); 82 $sco->identifier = $item; 83 $sco->title = $item; 84 $sco->parent = '/'; 85 $sco->launch = $resource['HREF']; 86 $sco->scormtype = $resource['ADLCP:SCORMTYPE']; 87 $scoes->elements[$manifest][$organization][$item] = $sco; 88 } 89 } 90 } 91 break; 92 case 'ORGANIZATIONS': 93 if (!isset($scoes->defaultorg) && isset($block['attrs']['DEFAULT'])) { 94 $scoes->defaultorg = $block['attrs']['DEFAULT']; 95 } 96 if (!empty($block['children'])) { 97 $scoes = scorm_get_manifest($block['children'], $scoes); 98 } 99 break; 100 case 'ORGANIZATION': 101 $identifier = $block['attrs']['IDENTIFIER']; 102 $organization = ''; 103 $scoes->elements[$manifest][$organization][$identifier] = new stdClass(); 104 $scoes->elements[$manifest][$organization][$identifier]->identifier = $identifier; 105 $scoes->elements[$manifest][$organization][$identifier]->parent = '/'; 106 $scoes->elements[$manifest][$organization][$identifier]->launch = ''; 107 $scoes->elements[$manifest][$organization][$identifier]->scormtype = ''; 108 109 $parents = array(); 110 $parent = new stdClass(); 111 $parent->identifier = $identifier; 112 $parent->organization = $organization; 113 array_push($parents, $parent); 114 $organization = $identifier; 115 116 if (!empty($block['children'])) { 117 $scoes = scorm_get_manifest($block['children'], $scoes); 118 } 119 120 array_pop($parents); 121 break; 122 case 'ITEM': 123 $parent = array_pop($parents); 124 array_push($parents, $parent); 125 126 $identifier = $block['attrs']['IDENTIFIER']; 127 $scoes->elements[$manifest][$organization][$identifier] = new stdClass(); 128 $scoes->elements[$manifest][$organization][$identifier]->identifier = $identifier; 129 $scoes->elements[$manifest][$organization][$identifier]->parent = $parent->identifier; 130 if (!isset($block['attrs']['ISVISIBLE'])) { 131 $block['attrs']['ISVISIBLE'] = 'true'; 132 } 133 $scoes->elements[$manifest][$organization][$identifier]->isvisible = $block['attrs']['ISVISIBLE']; 134 if (!isset($block['attrs']['PARAMETERS'])) { 135 $block['attrs']['PARAMETERS'] = ''; 136 } 137 $scoes->elements[$manifest][$organization][$identifier]->parameters = $block['attrs']['PARAMETERS']; 138 if (!isset($block['attrs']['IDENTIFIERREF'])) { 139 $scoes->elements[$manifest][$organization][$identifier]->launch = ''; 140 $scoes->elements[$manifest][$organization][$identifier]->scormtype = 'asset'; 141 } else { 142 $idref = $block['attrs']['IDENTIFIERREF']; 143 $base = ''; 144 if (isset($resources[$idref]['XML:BASE'])) { 145 $base = $resources[$idref]['XML:BASE']; 146 } 147 if (!isset($resources[$idref])) { 148 $manifestresourcesnotfound[] = $idref; 149 $scoes->elements[$manifest][$organization][$identifier]->launch = ''; 150 } else { 151 $scoes->elements[$manifest][$organization][$identifier]->launch = $base.$resources[$idref]['HREF']; 152 if (empty($resources[$idref]['ADLCP:SCORMTYPE'])) { 153 $resources[$idref]['ADLCP:SCORMTYPE'] = 'asset'; 154 } 155 $scoes->elements[$manifest][$organization][$identifier]->scormtype = $resources[$idref]['ADLCP:SCORMTYPE']; 156 } 157 } 158 159 $parent = new stdClass(); 160 $parent->identifier = $identifier; 161 $parent->organization = $organization; 162 array_push($parents, $parent); 163 164 if (!empty($block['children'])) { 165 $scoes = scorm_get_manifest($block['children'], $scoes); 166 } 167 168 array_pop($parents); 169 break; 170 case 'TITLE': 171 $parent = array_pop($parents); 172 array_push($parents, $parent); 173 if (!isset($block['tagData'])) { 174 $block['tagData'] = ''; 175 } 176 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->title = $block['tagData']; 177 break; 178 case 'ADLCP:PREREQUISITES': 179 if ($block['attrs']['TYPE'] == 'aicc_script') { 180 $parent = array_pop($parents); 181 array_push($parents, $parent); 182 if (!isset($block['tagData'])) { 183 $block['tagData'] = ''; 184 } 185 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->prerequisites = $block['tagData']; 186 } 187 break; 188 case 'ADLCP:MAXTIMEALLOWED': 189 $parent = array_pop($parents); 190 array_push($parents, $parent); 191 if (!isset($block['tagData'])) { 192 $block['tagData'] = ''; 193 } 194 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->maxtimeallowed = $block['tagData']; 195 break; 196 case 'ADLCP:TIMELIMITACTION': 197 $parent = array_pop($parents); 198 array_push($parents, $parent); 199 if (!isset($block['tagData'])) { 200 $block['tagData'] = ''; 201 } 202 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->timelimitaction = $block['tagData']; 203 break; 204 case 'ADLCP:DATAFROMLMS': 205 $parent = array_pop($parents); 206 array_push($parents, $parent); 207 if (!isset($block['tagData'])) { 208 $block['tagData'] = ''; 209 } 210 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->datafromlms = $block['tagData']; 211 break; 212 case 'ADLCP:MASTERYSCORE': 213 $parent = array_pop($parents); 214 array_push($parents, $parent); 215 if (!isset($block['tagData'])) { 216 $block['tagData'] = ''; 217 } 218 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->masteryscore = $block['tagData']; 219 break; 220 case 'ADLCP:COMPLETIONTHRESHOLD': 221 $parent = array_pop($parents); 222 array_push($parents, $parent); 223 if (!isset($block['attrs']['MINPROGRESSMEASURE'])) { 224 $block['attrs']['MINPROGRESSMEASURE'] = '1.0'; 225 } 226 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->threshold = $block['attrs']['MINPROGRESSMEASURE']; 227 break; 228 case 'ADLNAV:PRESENTATION': 229 $parent = array_pop($parents); 230 array_push($parents, $parent); 231 if (!empty($block['children'])) { 232 foreach ($block['children'] as $adlnav) { 233 if ($adlnav['name'] == 'ADLNAV:NAVIGATIONINTERFACE') { 234 foreach ($adlnav['children'] as $adlnavinterface) { 235 if ($adlnavinterface['name'] == 'ADLNAV:HIDELMSUI') { 236 if ($adlnavinterface['tagData'] == 'continue') { 237 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hidecontinue = 1; 238 } 239 if ($adlnavinterface['tagData'] == 'previous') { 240 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hideprevious = 1; 241 } 242 if ($adlnavinterface['tagData'] == 'exit') { 243 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hideexit = 1; 244 } 245 if ($adlnavinterface['tagData'] == 'exitAll') { 246 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hideexitall = 1; 247 } 248 if ($adlnavinterface['tagData'] == 'abandon') { 249 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hideabandon = 1; 250 } 251 if ($adlnavinterface['tagData'] == 'abandonAll') { 252 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hideabandonall = 1; 253 } 254 if ($adlnavinterface['tagData'] == 'suspendAll') { 255 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->hidesuspendall = 1; 256 } 257 } 258 } 259 } 260 } 261 } 262 break; 263 case 'IMSSS:SEQUENCING': 264 $parent = array_pop($parents); 265 array_push($parents, $parent); 266 if (!empty($block['children'])) { 267 foreach ($block['children'] as $sequencing) { 268 if ($sequencing['name'] == 'IMSSS:CONTROLMODE') { 269 if (isset($sequencing['attrs']['CHOICE'])) { 270 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->choice = 271 $sequencing['attrs']['CHOICE'] == 'true' ? 1 : 0; 272 } 273 if (isset($sequencing['attrs']['CHOICEEXIT'])) { 274 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->choiceexit = 275 $sequencing['attrs']['CHOICEEXIT'] == 'true' ? 1 : 0; 276 } 277 if (isset($sequencing['attrs']['FLOW'])) { 278 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->flow = 279 $sequencing['attrs']['FLOW'] == 'true' ? 1 : 0; 280 } 281 if (isset($sequencing['attrs']['FORWARDONLY'])) { 282 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->forwardonly = 283 $sequencing['attrs']['FORWARDONLY'] == 'true' ? 1 : 0; 284 } 285 if (isset($sequencing['attrs']['USECURRENTATTEMPTOBJECTINFO'])) { 286 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->usecurrentattemptobjectinfo = 287 $sequencing['attrs']['USECURRENTATTEMPTOBJECTINFO'] == 'true' ? 1 : 0; 288 } 289 if (isset($sequencing['attrs']['USECURRENTATTEMPTPROGRESSINFO'])) { 290 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->usecurrentattemptprogressinfo = 291 $sequencing['attrs']['USECURRENTATTEMPTPROGRESSINFO'] == 'true' ? 1 : 0; 292 } 293 } 294 if ($sequencing['name'] == 'IMSSS:DELIVERYCONTROLS') { 295 if (isset($sequencing['attrs']['TRACKED'])) { 296 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->tracked = 297 $sequencing['attrs']['TRACKED'] == 'true' ? 1 : 0; 298 } 299 if (isset($sequencing['attrs']['COMPLETIONSETBYCONTENT'])) { 300 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->completionsetbycontent = 301 $sequencing['attrs']['COMPLETIONSETBYCONTENT'] == 'true' ? 1 : 0; 302 } 303 if (isset($sequencing['attrs']['OBJECTIVESETBYCONTENT'])) { 304 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->objectivesetbycontent = 305 $sequencing['attrs']['OBJECTIVESETBYCONTENT'] == 'true' ? 1 : 0; 306 } 307 } 308 if ($sequencing['name'] == 'ADLSEQ:CONSTRAINEDCHOICECONSIDERATIONS') { 309 if (isset($sequencing['attrs']['CONSTRAINCHOICE'])) { 310 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->constrainChoice = 311 $sequencing['attrs']['CONSTRAINCHOICE'] == 'true' ? 1 : 0; 312 } 313 if (isset($sequencing['attrs']['PREVENTACTIVATION'])) { 314 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->preventactivation = 315 $sequencing['attrs']['PREVENTACTIVATION'] == 'true' ? 1 : 0; 316 } 317 } 318 if ($sequencing['name'] == 'IMSSS:OBJECTIVES') { 319 $objectives = array(); 320 foreach ($sequencing['children'] as $objective) { 321 $objectivedata = new stdClass(); 322 $objectivedata->primaryobj = 0; 323 switch ($objective['name']) { 324 case 'IMSSS:PRIMARYOBJECTIVE': 325 $objectivedata->primaryobj = 1; 326 case 'IMSSS:OBJECTIVE': 327 $objectivedata->satisfiedbymeasure = 0; 328 if (isset($objective['attrs']['SATISFIEDBYMEASURE'])) { 329 $objectivedata->satisfiedbymeasure = 330 $objective['attrs']['SATISFIEDBYMEASURE'] == 'true' ? 1 : 0; 331 } 332 $objectivedata->objectiveid = ''; 333 if (isset($objective['attrs']['OBJECTIVEID'])) { 334 $objectivedata->objectiveid = $objective['attrs']['OBJECTIVEID']; 335 } 336 $objectivedata->minnormalizedmeasure = 1.0; 337 if (!empty($objective['children'])) { 338 $mapinfos = array(); 339 foreach ($objective['children'] as $objectiveparam) { 340 if ($objectiveparam['name'] == 'IMSSS:MINNORMALIZEDMEASURE') { 341 if (isset($objectiveparam['tagData'])) { 342 $objectivedata->minnormalizedmeasure = $objectiveparam['tagData']; 343 } else { 344 $objectivedata->minnormalizedmeasure = 0; 345 } 346 } 347 if ($objectiveparam['name'] == 'IMSSS:MAPINFO') { 348 $mapinfo = new stdClass(); 349 $mapinfo->targetobjectiveid = ''; 350 if (isset($objectiveparam['attrs']['TARGETOBJECTIVEID'])) { 351 $mapinfo->targetobjectiveid = 352 $objectiveparam['attrs']['TARGETOBJECTIVEID']; 353 } 354 $mapinfo->readsatisfiedstatus = 1; 355 if (isset($objectiveparam['attrs']['READSATISFIEDSTATUS'])) { 356 $mapinfo->readsatisfiedstatus = 357 $objectiveparam['attrs']['READSATISFIEDSTATUS'] == 'true' ? 1 : 0; 358 } 359 $mapinfo->writesatisfiedstatus = 0; 360 if (isset($objectiveparam['attrs']['WRITESATISFIEDSTATUS'])) { 361 $mapinfo->writesatisfiedstatus = 362 $objectiveparam['attrs']['WRITESATISFIEDSTATUS'] == 'true' ? 1 : 0; 363 } 364 $mapinfo->readnormalizemeasure = 1; 365 if (isset($objectiveparam['attrs']['READNORMALIZEDMEASURE'])) { 366 $mapinfo->readnormalizemeasure = 367 $objectiveparam['attrs']['READNORMALIZEDMEASURE'] == 'true' ? 1 : 0; 368 } 369 $mapinfo->writenormalizemeasure = 0; 370 if (isset($objectiveparam['attrs']['WRITENORMALIZEDMEASURE'])) { 371 $mapinfo->writenormalizemeasure = 372 $objectiveparam['attrs']['WRITENORMALIZEDMEASURE'] == 'true' ? 1 : 0; 373 } 374 array_push($mapinfos, $mapinfo); 375 } 376 } 377 if (!empty($mapinfos)) { 378 $objectivesdata->mapinfos = $mapinfos; 379 } 380 } 381 break; 382 } 383 array_push($objectives, $objectivedata); 384 } 385 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->objectives = $objectives; 386 } 387 if ($sequencing['name'] == 'IMSSS:LIMITCONDITIONS') { 388 if (isset($sequencing['attrs']['ATTEMPTLIMIT'])) { 389 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->attemptLimit = 390 $sequencing['attrs']['ATTEMPTLIMIT']; 391 } 392 if (isset($sequencing['attrs']['ATTEMPTABSOLUTEDURATIONLIMIT'])) { 393 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->attemptAbsoluteDurationLimit = 394 $sequencing['attrs']['ATTEMPTABSOLUTEDURATIONLIMIT']; 395 } 396 } 397 if ($sequencing['name'] == 'IMSSS:ROLLUPRULES') { 398 if (isset($sequencing['attrs']['ROLLUPOBJECTIVESATISFIED'])) { 399 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->rollupobjectivesatisfied = 400 $sequencing['attrs']['ROLLUPOBJECTIVESATISFIED'] == 'true' ? 1 : 0; 401 } 402 if (isset($sequencing['attrs']['ROLLUPPROGRESSCOMPLETION'])) { 403 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->rollupprogresscompletion = 404 $sequencing['attrs']['ROLLUPPROGRESSCOMPLETION'] == 'true' ? 1 : 0; 405 } 406 if (isset($sequencing['attrs']['OBJECTIVEMEASUREWEIGHT'])) { 407 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->objectivemeasureweight = 408 $sequencing['attrs']['OBJECTIVEMEASUREWEIGHT']; 409 } 410 411 if (!empty($sequencing['children'])) { 412 $rolluprules = array(); 413 foreach ($sequencing['children'] as $sequencingrolluprule) { 414 if ($sequencingrolluprule['name'] == 'IMSSS:ROLLUPRULE' ) { 415 $rolluprule = new stdClass(); 416 $rolluprule->childactivityset = 'all'; 417 if (isset($sequencingrolluprule['attrs']['CHILDACTIVITYSET'])) { 418 $rolluprule->childactivityset = $sequencingrolluprule['attrs']['CHILDACTIVITYSET']; 419 } 420 $rolluprule->minimumcount = 0; 421 if (isset($sequencingrolluprule['attrs']['MINIMUMCOUNT'])) { 422 $rolluprule->minimumcount = $sequencingrolluprule['attrs']['MINIMUMCOUNT']; 423 } 424 $rolluprule->minimumpercent = 0.0000; 425 if (isset($sequencingrolluprule['attrs']['MINIMUMPERCENT'])) { 426 $rolluprule->minimumpercent = $sequencingrolluprule['attrs']['MINIMUMPERCENT']; 427 } 428 if (!empty($sequencingrolluprule['children'])) { 429 foreach ($sequencingrolluprule['children'] as $rolluproleconditions) { 430 if ($rolluproleconditions['name'] == 'IMSSS:ROLLUPCONDITIONS') { 431 $conditions = array(); 432 $rolluprule->conditioncombination = 'all'; 433 if (isset($rolluproleconditions['attrs']['CONDITIONCOMBINATION'])) { 434 $rolluprule->CONDITIONCOMBINATION = $rolluproleconditions['attrs']['CONDITIONCOMBINATION']; 435 } 436 foreach ($rolluproleconditions['children'] as $rolluprulecondition) { 437 if ($rolluprulecondition['name'] == 'IMSSS:ROLLUPCONDITION') { 438 $condition = new stdClass(); 439 if (isset($rolluprulecondition['attrs']['CONDITION'])) { 440 $condition->cond = $rolluprulecondition['attrs']['CONDITION']; 441 } 442 $condition->operator = 'noOp'; 443 if (isset($rolluprulecondition['attrs']['OPERATOR'])) { 444 $condition->operator = $rolluprulecondition['attrs']['OPERATOR']; 445 } 446 array_push($conditions, $condition); 447 } 448 } 449 $rolluprule->conditions = $conditions; 450 } 451 if ($rolluproleconditions['name'] == 'IMSSS:ROLLUPACTION') { 452 $rolluprule->rollupruleaction = $rolluproleconditions['attrs']['ACTION']; 453 } 454 } 455 } 456 array_push($rolluprules, $rolluprule); 457 } 458 } 459 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->rolluprules = $rolluprules; 460 } 461 } 462 463 if ($sequencing['name'] == 'IMSSS:SEQUENCINGRULES') { 464 if (!empty($sequencing['children'])) { 465 $sequencingrules = array(); 466 foreach ($sequencing['children'] as $conditionrules) { 467 $conditiontype = -1; 468 switch($conditionrules['name']) { 469 case 'IMSSS:PRECONDITIONRULE': 470 $conditiontype = 0; 471 break; 472 case 'IMSSS:POSTCONDITIONRULE': 473 $conditiontype = 1; 474 break; 475 case 'IMSSS:EXITCONDITIONRULE': 476 $conditiontype = 2; 477 break; 478 } 479 if (!empty($conditionrules['children'])) { 480 $sequencingrule = new stdClass(); 481 foreach ($conditionrules['children'] as $conditionrule) { 482 if ($conditionrule['name'] == 'IMSSS:RULECONDITIONS') { 483 $ruleconditions = array(); 484 $sequencingrule->conditioncombination = 'all'; 485 if (isset($conditionrule['attrs']['CONDITIONCOMBINATION'])) { 486 $sequencingrule->conditioncombination = $conditionrule['attrs']['CONDITIONCOMBINATION']; 487 } 488 foreach ($conditionrule['children'] as $rulecondition) { 489 if ($rulecondition['name'] == 'IMSSS:RULECONDITION') { 490 $condition = new stdClass(); 491 if (isset($rulecondition['attrs']['CONDITION'])) { 492 $condition->cond = $rulecondition['attrs']['CONDITION']; 493 } 494 $condition->operator = 'noOp'; 495 if (isset($rulecondition['attrs']['OPERATOR'])) { 496 $condition->operator = $rulecondition['attrs']['OPERATOR']; 497 } 498 $condition->measurethreshold = 0.0000; 499 if (isset($rulecondition['attrs']['MEASURETHRESHOLD'])) { 500 $condition->measurethreshold = $rulecondition['attrs']['MEASURETHRESHOLD']; 501 } 502 $condition->referencedobjective = ''; 503 if (isset($rulecondition['attrs']['REFERENCEDOBJECTIVE'])) { 504 $condition->referencedobjective = $rulecondition['attrs']['REFERENCEDOBJECTIVE']; 505 } 506 array_push($ruleconditions, $condition); 507 } 508 } 509 $sequencingrule->ruleconditions = $ruleconditions; 510 } 511 if ($conditionrule['name'] == 'IMSSS:RULEACTION') { 512 $sequencingrule->action = $conditionrule['attrs']['ACTION']; 513 } 514 $sequencingrule->type = $conditiontype; 515 } 516 array_push($sequencingrules, $sequencingrule); 517 } 518 } 519 $scoes->elements[$manifest][$parent->organization][$parent->identifier]->sequencingrules = $sequencingrules; 520 } 521 } 522 } 523 } 524 break; 525 } 526 } 527 } 528 if (!empty($manifestresourcesnotfound)) { 529 // Throw warning to user to let them know manifest contains references to resources that don't appear to exist. 530 if (!defined('DEBUGGING_PRINTED')) { 531 // Prevent redirect and display warning. 532 define('DEBUGGING_PRINTED', 1); 533 } 534 echo $OUTPUT->notification(get_string('invalidmanifestresource', 'scorm').' '. implode(', ', $manifestresourcesnotfound)); 535 } 536 return $scoes; 537 } 538 539 /** 540 * Sets up SCORM 1.2/2004 packages using the manifest file. 541 * Called whenever SCORM changes 542 * @param object $scorm instance - fields are updated and changes saved into database 543 * @param stored_file|string $manifest - path to manifest file or stored_file. 544 * @return bool 545 */ 546 function scorm_parse_scorm(&$scorm, $manifest) { 547 global $CFG, $DB; 548 549 // Load manifest into string. 550 if ($manifest instanceof stored_file) { 551 $xmltext = $manifest->get_content(); 552 } else { 553 require_once("$CFG->libdir/filelib.php"); 554 $xmltext = download_file_content($manifest); 555 } 556 557 $defaultorgid = 0; 558 $firstinorg = 0; 559 560 $pattern = '/&(?!\w{2,6};)/'; 561 $replacement = '&'; 562 $xmltext = preg_replace($pattern, $replacement, $xmltext); 563 564 $objxml = new xml2Array(); 565 $manifests = $objxml->parse($xmltext); 566 $scoes = new stdClass(); 567 $scoes->version = ''; 568 $scoes = scorm_get_manifest($manifests, $scoes); 569 $newscoes = array(); 570 $sortorder = 0; 571 if (count($scoes->elements) > 0) { 572 $olditems = $DB->get_records('scorm_scoes', array('scorm' => $scorm->id)); 573 foreach ($scoes->elements as $manifest => $organizations) { 574 foreach ($organizations as $organization => $items) { 575 foreach ($items as $identifier => $item) { 576 $sortorder++; 577 // This new db mngt will support all SCORM future extensions. 578 $newitem = new stdClass(); 579 $newitem->scorm = $scorm->id; 580 $newitem->manifest = $manifest; 581 $newitem->organization = $organization; 582 $newitem->sortorder = $sortorder; 583 $standarddatas = array('parent', 'identifier', 'launch', 'scormtype', 'title'); 584 foreach ($standarddatas as $standarddata) { 585 if (isset($item->$standarddata)) { 586 $newitem->$standarddata = $item->$standarddata; 587 } else { 588 $newitem->$standarddata = ''; 589 } 590 } 591 592 if (!empty($defaultorgid) && empty($firstinorg) && $newitem->parent == $scoes->defaultorg) { 593 $firstinorg = $sortorder; 594 } 595 596 if (!empty($olditems) && ($olditemid = scorm_array_search('identifier', $newitem->identifier, $olditems))) { 597 $newitem->id = $olditemid; 598 // Update the Sco sortorder but keep id so that user tracks are kept against the same ids. 599 $DB->update_record('scorm_scoes', $newitem); 600 $id = $olditemid; 601 // Remove all old data so we don't duplicate it. 602 $DB->delete_records('scorm_scoes_data', array('scoid' => $olditemid)); 603 $DB->delete_records('scorm_seq_objective', array('scoid' => $olditemid)); 604 $DB->delete_records('scorm_seq_mapinfo', array('scoid' => $olditemid)); 605 $DB->delete_records('scorm_seq_ruleconds', array('scoid' => $olditemid)); 606 $DB->delete_records('scorm_seq_rulecond', array('scoid' => $olditemid)); 607 $DB->delete_records('scorm_seq_rolluprule', array('scoid' => $olditemid)); 608 $DB->delete_records('scorm_seq_rolluprulecond', array('scoid' => $olditemid)); 609 610 // Now remove this SCO from the olditems object as we have dealt with it. 611 unset($olditems[$olditemid]); 612 } else { 613 // Insert the new SCO, and retain the link between the old and new for later adjustment. 614 $id = $DB->insert_record('scorm_scoes', $newitem); 615 } 616 // Save this sco in memory so we can use it later. 617 $newscoes[$id] = $newitem; 618 619 if ($optionaldatas = scorm_optionals_data($item, $standarddatas)) { 620 $data = new stdClass(); 621 $data->scoid = $id; 622 foreach ($optionaldatas as $optionaldata) { 623 if (isset($item->$optionaldata)) { 624 $data->name = $optionaldata; 625 $data->value = $item->$optionaldata; 626 $dataid = $DB->insert_record('scorm_scoes_data', $data); 627 } 628 } 629 } 630 631 if (isset($item->sequencingrules)) { 632 foreach ($item->sequencingrules as $sequencingrule) { 633 $rule = new stdClass(); 634 $rule->scoid = $id; 635 $rule->ruletype = $sequencingrule->type; 636 $rule->conditioncombination = $sequencingrule->conditioncombination; 637 $rule->action = $sequencingrule->action; 638 $ruleid = $DB->insert_record('scorm_seq_ruleconds', $rule); 639 if (isset($sequencingrule->ruleconditions)) { 640 foreach ($sequencingrule->ruleconditions as $rulecondition) { 641 $rulecond = new stdClass(); 642 $rulecond->scoid = $id; 643 $rulecond->ruleconditionsid = $ruleid; 644 $rulecond->referencedobjective = $rulecondition->referencedobjective; 645 $rulecond->measurethreshold = $rulecondition->measurethreshold; 646 $rulecond->operator = $rulecondition->operator; 647 $rulecond->cond = $rulecondition->cond; 648 $rulecondid = $DB->insert_record('scorm_seq_rulecond', $rulecond); 649 } 650 } 651 } 652 } 653 654 if (isset($item->rolluprules)) { 655 foreach ($item->rolluprules as $rolluprule) { 656 $rollup = new stdClass(); 657 $rollup->scoid = $id; 658 $rollup->childactivityset = $rolluprule->childactivityset; 659 $rollup->minimumcount = $rolluprule->minimumcount; 660 $rollup->minimumpercent = $rolluprule->minimumpercent; 661 $rollup->rollupruleaction = $rolluprule->rollupruleaction; 662 $rollup->conditioncombination = $rolluprule->conditioncombination; 663 664 $rollupruleid = $DB->insert_record('scorm_seq_rolluprule', $rollup); 665 if (isset($rollup->conditions)) { 666 foreach ($rollup->conditions as $condition) { 667 $cond = new stdClass(); 668 $cond->scoid = $rollup->scoid; 669 $cond->rollupruleid = $rollupruleid; 670 $cond->operator = $condition->operator; 671 $cond->cond = $condition->cond; 672 $conditionid = $DB->insert_record('scorm_seq_rolluprulecond', $cond); 673 } 674 } 675 } 676 } 677 678 if (isset($item->objectives)) { 679 foreach ($item->objectives as $objective) { 680 $obj = new stdClass(); 681 $obj->scoid = $id; 682 $obj->primaryobj = $objective->primaryobj; 683 $obj->satisfiedbumeasure = $objective->satisfiedbymeasure; 684 $obj->objectiveid = $objective->objectiveid; 685 $obj->minnormalizedmeasure = trim($objective->minnormalizedmeasure); 686 $objectiveid = $DB->insert_record('scorm_seq_objective', $obj); 687 if (isset($objective->mapinfos)) { 688 foreach ($objective->mapinfos as $objmapinfo) { 689 $mapinfo = new stdClass(); 690 $mapinfo->scoid = $id; 691 $mapinfo->objectiveid = $objectiveid; 692 $mapinfo->targetobjectiveid = $objmapinfo->targetobjectiveid; 693 $mapinfo->readsatisfiedstatus = $objmapinfo->readsatisfiedstatus; 694 $mapinfo->writesatisfiedstatus = $objmapinfo->writesatisfiedstatus; 695 $mapinfo->readnormalizedmeasure = $objmapinfo->readnormalizedmeasure; 696 $mapinfo->writenormalizedmeasure = $objmapinfo->writenormalizedmeasure; 697 $mapinfoid = $DB->insert_record('scorm_seq_mapinfo', $mapinfo); 698 } 699 } 700 } 701 } 702 if (empty($defaultorgid) && ((empty($scoes->defaultorg)) || ($scoes->defaultorg == $identifier))) { 703 $defaultorgid = $id; 704 } 705 } 706 } 707 } 708 if (!empty($olditems)) { 709 foreach ($olditems as $olditem) { 710 $DB->delete_records('scorm_scoes', array('id' => $olditem->id)); 711 $DB->delete_records('scorm_scoes_data', array('scoid' => $olditem->id)); 712 $DB->delete_records('scorm_scoes_track', array('scoid' => $olditem->id)); 713 $DB->delete_records('scorm_seq_objective', array('scoid' => $olditem->id)); 714 $DB->delete_records('scorm_seq_mapinfo', array('scoid' => $olditem->id)); 715 $DB->delete_records('scorm_seq_ruleconds', array('scoid' => $olditem->id)); 716 $DB->delete_records('scorm_seq_rulecond', array('scoid' => $olditem->id)); 717 $DB->delete_records('scorm_seq_rolluprule', array('scoid' => $olditem->id)); 718 $DB->delete_records('scorm_seq_rolluprulecond', array('scoid' => $olditem->id)); 719 } 720 } 721 if (empty($scoes->version)) { 722 $scoes->version = 'SCORM_1.2'; 723 } 724 $DB->set_field('scorm', 'version', $scoes->version, array('id' => $scorm->id)); 725 $scorm->version = $scoes->version; 726 } 727 $scorm->launch = 0; 728 // Check launch sco is valid. 729 if (!empty($defaultorgid) && isset($newscoes[$defaultorgid]) && !empty($newscoes[$defaultorgid]->launch)) { 730 // Launch param is valid - do nothing. 731 $scorm->launch = $defaultorgid; 732 } else if (!empty($defaultorgid) && isset($newscoes[$defaultorgid]) && empty($newscoes[$defaultorgid]->launch)) { 733 // The launch is probably the default org so we need to find the first launchable item inside this org. 734 $sqlselect = 'scorm = ? AND sortorder >= ? AND '.$DB->sql_isnotempty('scorm_scoes', 'launch', false, true); 735 // We use get_records here as we need to pass a limit in the query that works cross db. 736 $scoes = $DB->get_records_select('scorm_scoes', $sqlselect, array($scorm->id, $firstinorg), 'sortorder', 'id', 0, 1); 737 if (!empty($scoes)) { 738 $sco = reset($scoes); // We only care about the first record - the above query only returns one. 739 $scorm->launch = $sco->id; 740 } 741 } 742 if (empty($scorm->launch)) { 743 // No valid Launch is specified - find the first launchable sco instead. 744 $sqlselect = 'scorm = ? AND '.$DB->sql_isnotempty('scorm_scoes', 'launch', false, true); 745 // We use get_records here as we need to pass a limit in the query that works cross db. 746 $scoes = $DB->get_records_select('scorm_scoes', $sqlselect, array($scorm->id), 'sortorder', 'id', 0, 1); 747 if (!empty($scoes)) { 748 $sco = reset($scoes); // We only care about the first record - the above query only returns one. 749 $scorm->launch = $sco->id; 750 } 751 } 752 753 return true; 754 } 755 756 function scorm_optionals_data($item, $standarddata) { 757 $result = array(); 758 $sequencingdata = array('sequencingrules', 'rolluprules', 'objectives'); 759 foreach ($item as $element => $value) { 760 if (! in_array($element, $standarddata)) { 761 if (! in_array($element, $sequencingdata)) { 762 $result[] = $element; 763 } 764 } 765 } 766 return $result; 767 } 768 769 function scorm_is_leaf($sco) { 770 global $DB; 771 772 if ($DB->record_exists('scorm_scoes', array('scorm' => $sco->scorm, 'parent' => $sco->identifier))) { 773 return false; 774 } 775 return true; 776 } 777 778 function scorm_get_parent($sco) { 779 global $DB; 780 781 if ($sco->parent != '/') { 782 if ($parent = $DB->get_record('scorm_scoes', array('scorm' => $sco->scorm, 'identifier' => $sco->parent))) { 783 return scorm_get_sco($parent->id); 784 } 785 } 786 return null; 787 } 788 789 function scorm_get_children($sco) { 790 global $DB; 791 792 $children = $DB->get_records('scorm_scoes', array('scorm' => $sco->scorm, 'parent' => $sco->identifier), 'sortorder, id'); 793 if (!empty($children)) { 794 return $children; 795 } 796 return null; 797 } 798 799 function scorm_get_available_children($sco) { 800 global $DB; 801 802 $res = $DB->get_records('scorm_scoes', array('scorm' => $sco->scorm, 'parent' => $sco->identifier), 'sortorder, id'); 803 if (!$res || $res == null) { 804 return false; 805 } else { 806 foreach ($res as $sco) { 807 $result[] = $sco; 808 } 809 return $result; 810 } 811 } 812 813 function scorm_get_available_descendent($descend = array(), $sco) { 814 if ($sco == null) { 815 return $descend; 816 } else { 817 $avchildren = scorm_get_available_children($sco); 818 foreach ($avchildren as $avchild) { 819 array_push($descend, $avchild); 820 } 821 foreach ($avchildren as $avchild) { 822 scorm_get_available_descendent($descend, $avchild); 823 } 824 } 825 } 826 827 function scorm_get_siblings($sco) { 828 global $DB; 829 830 if ($siblings = $DB->get_records('scorm_scoes', array('scorm' => $sco->scorm, 'parent' => $sco->parent), 'sortorder, id')) { 831 unset($siblings[$sco->id]); 832 if (!empty($siblings)) { 833 return $siblings; 834 } 835 } 836 return null; 837 } 838 // Get an array that contains all the parent scos for this sco. 839 function scorm_get_ancestors($sco) { 840 $ancestors = array(); 841 $continue = true; 842 while ($continue) { 843 $ancestor = scorm_get_parent($sco); 844 if (!empty($ancestor) && $ancestor->id !== $sco->id) { 845 $sco = $ancestor; 846 $ancestors[] = $ancestor; 847 if ($sco->parent == '/') { 848 $continue = false; 849 } 850 } else { 851 $continue = false; 852 } 853 } 854 return $ancestors; 855 } 856 857 function scorm_get_preorder(&$preorder = array(), $sco = null) { 858 if ($sco != null) { 859 array_push($preorder, $sco); 860 if ($children = scorm_get_children($sco)) { 861 foreach ($children as $child) { 862 scorm_get_preorder($preorder, $child); 863 } 864 } 865 } 866 return $preorder; 867 } 868 869 function scorm_find_common_ancestor($ancestors, $sco) { 870 $pos = scorm_array_search('identifier', $sco->parent, $ancestors); 871 if ($sco->parent != '/') { 872 if ($pos === false) { 873 return scorm_find_common_ancestor($ancestors, scorm_get_parent($sco)); 874 } 875 } 876 return $pos; 877 } 878 879 /* Usage 880 Grab some XML data, either from a file, URL, etc. however you want. Assume storage in $strYourXML; 881 882 $objXML = new xml2Array(); 883 $arroutput = $objXML->parse($strYourXML); 884 print_r($arroutput); //print it out, or do whatever! 885 886 */ 887 class xml2Array { 888 889 public $arroutput = array(); 890 public $resparser; 891 public $strxmldata; 892 893 /** 894 * Convert a utf-8 string to html entities 895 * 896 * @param string $str The UTF-8 string 897 * @return string 898 */ 899 public function utf8_to_entities($str) { 900 global $CFG; 901 902 $entities = ''; 903 $values = array(); 904 $lookingfor = 1; 905 906 return $str; 907 } 908 909 /** 910 * Parse an XML text string and create an array tree that rapresent the XML structure 911 * 912 * @param string $strinputxml The XML string 913 * @return array 914 */ 915 public function parse($strinputxml) { 916 $this->resparser = xml_parser_create ('UTF-8'); 917 xml_set_object($this->resparser, $this); 918 xml_set_element_handler($this->resparser, "tagopen", "tagclosed"); 919 920 xml_set_character_data_handler($this->resparser, "tagdata"); 921 922 $this->strxmldata = xml_parse($this->resparser, $strinputxml ); 923 if (!$this->strxmldata) { 924 die(sprintf("XML error: %s at line %d", 925 xml_error_string(xml_get_error_code($this->resparser)), 926 xml_get_current_line_number($this->resparser))); 927 } 928 929 xml_parser_free($this->resparser); 930 931 return $this->arroutput; 932 } 933 934 public function tagopen($parser, $name, $attrs) { 935 $tag = array("name" => $name, "attrs" => $attrs); 936 array_push($this->arroutput, $tag); 937 } 938 939 public function tagdata($parser, $tagdata) { 940 if (trim($tagdata)) { 941 if (isset($this->arroutput[count($this->arroutput) - 1]['tagData'])) { 942 $this->arroutput[count($this->arroutput) - 1]['tagData'] .= $this->utf8_to_entities($tagdata); 943 } else { 944 $this->arroutput[count($this->arroutput) - 1]['tagData'] = $this->utf8_to_entities($tagdata); 945 } 946 } 947 } 948 949 public function tagclosed($parser, $name) { 950 $this->arroutput[count($this->arroutput) - 2]['children'][] = $this->arroutput[count($this->arroutput) - 1]; 951 array_pop($this->arroutput); 952 } 953 954 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |