3 declare(strict_types=1);
28 public const DB_ENCODE_XSL =
'./Modules/Scorm2004/templates/xsl/op/op-scorm13.xsl';
29 public const CONVERT_XSL =
'./Modules/Scorm2004/templates/xsl/op/scorm12To2004.xsl';
30 public const DB_DECODE_XSL =
'./Modules/Scorm2004/templates/xsl/op/op-scorm13-revert.xsl';
31 public const VALIDATE_XSD =
'./libs/ilias/Scorm2004/xsd/op/op-scorm13.xsd';
33 public const WRAPPER_HTML =
'./Modules/Scorm2004/scripts/converter/GenericRunTimeWrapper1.0_aadlc/GenericRunTimeWrapper.htm';
34 public const WRAPPER_JS =
'./Modules/Scorm2004/scripts/converter/GenericRunTimeWrapper1.0_aadlc/SCOPlayerWrapper.js';
89 $this->packagesFolder =
'';
90 if ($packageId != null) {
91 $this->
load($packageId);
95 public function load(
int $packageId): void
98 $ilDB = $DIC->database();
100 $lm_set =
$ilDB->queryF(
'SELECT * FROM sahs_lm WHERE id = %s', array(
'integer'), array($packageId));
102 $pg_set =
$ilDB->queryF(
'SELECT * FROM cp_package WHERE obj_id = %s', array(
'integer'), array($packageId));
105 $this->packageData = array_merge($lm_data, $pg_data);
107 $this->packageFolder = $this->packagesFolder .
'/' .
$packageId;
108 $this->packageFile = $this->packageFolder .
'.zip';
109 $this->imsmanifestFile = $this->packageFolder .
'/' .
'imsmanifest.xml';
117 public function il_import(
string $packageFolder,
int $packageId,
bool $reimport =
false)
120 $ilDB = $DIC->database();
126 if ($reimport ===
true) {
131 $this->packageData[
'persistprevattempts'] = 0;
132 $this->packageData[
'default_lesson_mode'] =
'normal';
133 $this->packageData[
'credit'] =
'credit';
134 $this->packageData[
'auto_review'] =
'n';
138 $this->imsmanifestFile = $this->packageFolder .
'/' .
'imsmanifest.xml';
141 $this->imsmanifest->async =
false;
142 if (!@$this->imsmanifest->load($this->imsmanifestFile)) {
143 $this->diagnostic[] =
'XML not wellformed';
148 $this->manifest = $this->
transform($this->imsmanifest, self::DB_ENCODE_XSL);
150 if (!$this->manifest) {
151 $this->diagnostic[] =
'Cannot transform into normalized manifest';
155 $path =
new DOMXpath($this->manifest);
156 $path->registerNamespace(
"scorm",
"http://www.openpalms.net/scorm/scorm13");
157 $items =
$path->query(
"//scorm:item");
158 if ($items->length == 1) {
159 $n = $items->item(0);
160 $resource =
$path->query(
"//scorm:resource");
161 foreach ($resource as
$res) {
162 if ($n !== null && $res->getAttribute(
'id') == $n->getAttribute(
"resourceId")) {
163 $res->setAttribute(
'scormType',
'sco');
169 if (file_exists($this->packageFolder .
'/' .
'index.xml')) {
170 $doc = simplexml_load_file($this->packageFolder .
'/' .
'index.xml');
171 $l = $doc->xpath(
"/ContentObject/MetaData");
174 $mdxml->startParsing();
175 $mdo = $mdxml->getMDObject();
183 $title = $importer->getTitle();
184 $description = $importer->getDescription();
185 if ($description !=
"") {
191 $x = simplexml_load_string($this->manifest->saveXML());
192 $x[
'persistPreviousAttempts'] = $this->packageData[
'persistprevattempts'];
195 $x[
'defaultLessonMode'] = $this->packageData[
'default_lesson_mode'];
196 $x[
'credit'] = $this->packageData[
'credit'];
197 $x[
'autoReview'] = $this->packageData[
'auto_review'];
201 foreach ($x->resource as $xe) {
202 $r[strval($xe[
'id'])] = $xe;
206 foreach ($x->xpath(
'//*[local-name()="item"]') as $xe) {
208 if (
$b = ($r[strval($xe[
'resourceId'])] ??
false)) {
209 $xe[
'href'] = strval(
$b[
'base']) . strval(
$b[
'href']);
210 unset($xe[
'resourceId']);
211 if (strval(
$b[
'scormType']) ===
'sco') {
219 $this->
jsonNode($x->organization, $j[
'item']);
220 foreach ($x->sequencing as $s) {
221 $this->
jsonNode($s, $j[
'sequencing'][]);
224 $j[
'item'][
'base'] = strval($x[
'base']);
226 $j[
'base'] = $packageFolder .
'/';
227 $j[
'foreignId'] = floatval($x[
'foreignId']);
228 $j[
'id'] = strval($x[
'id']);
230 for(
$i = 0;
$i < count($j[
'item'][
'item']);
$i++) {
236 $adl_tree = $act->buildNodeSeqTree($this->imsmanifestFile);
240 'xmldata' => array(
'clob', $x->asXML()),
241 'jsdata' => array(
'clob', json_encode($j)),
242 'activitytree' => array(
'clob', json_encode($adl_tree[
'tree'])),
243 'global_to_system' => array(
'integer', (
int) $adl_tree[
'global']),
244 'shared_data_global_to_system' => array(
'integer', (
int) $adl_tree[
'dataglobal'])
247 'obj_id' => array(
'integer', (
int) $this->packageId)
256 return $j[
'item'][
'title'];
267 public function jsonNode(
object $node, ?array &$sink): void
269 foreach ($node->attributes() as $k => $v) {
274 } elseif ($v ===
"false") {
276 } elseif (is_numeric($v)) {
281 foreach ($node->children() as
$name => $child) {
282 self::jsonNode($child, $sink[$name][]);
286 public function dbImport(
object $node, ?
int &$lft = 1, ?
int $depth = 1, ?
int $parent = 0): void
289 $ilDB = $DIC->database();
291 switch ($node->nodeType) {
292 case XML_DOCUMENT_NODE:
297 'SELECT * FROM cp_package WHERE obj_id = %s AND c_identifier = %s',
298 array(
'integer',
'text'),
299 array($this->packageId, $this->packageName)
302 $query =
'UPDATE cp_package ' 303 .
'SET persistprevattempts = %s, c_settings = %s ' 304 .
'WHERE obj_id = %s AND c_identifier= %s';
307 array(
'integer',
'text',
'integer',
'text'),
308 array(0, null, $this->packageId, $this->packageName)
311 $query =
'INSERT INTO cp_package (obj_id, c_identifier, persistprevattempts, c_settings) ' 312 .
'VALUES (%s, %s, %s, %s)';
315 array(
'integer',
'text',
'integer',
'text'),
316 array($this->packageId, $this->packageName, 0, null)
321 $this->
dbImport($node->documentElement);
324 case XML_ELEMENT_NODE:
325 if ($node->nodeName ===
'manifest') {
326 if ($node->getAttribute(
'uri') ==
"") {
328 $node->setAttribute(
'uri',
'md5:' . $this->packageHash);
332 $cp_node_id =
$ilDB->nextId(
'cp_node');
334 $query =
'INSERT INTO cp_node (cp_node_id, slm_id, nodename) ' 335 .
'VALUES (%s, %s, %s)';
338 array(
'integer',
'integer',
'text'),
339 array($cp_node_id, $this->packageId, $node->nodeName)
342 $query =
'INSERT INTO cp_tree (child, depth, lft, obj_id, parent, rgt) ' 343 .
'VALUES (%s, %s, %s, %s, %s, %s)';
346 array(
'integer',
'integer',
'integer',
'integer',
'integer',
'integer'),
347 array($cp_node_id, $depth, $lft++, $this->packageId, $parent, 0)
352 $names = array(
'cp_node_id');
353 $values = array($cp_node_id);
354 $types = array(
'integer');
356 foreach ($node->attributes as $attr) {
357 switch (strtolower($attr->name)) {
358 case 'completionsetbycontent': $names[] =
'completionbycontent';
360 case 'objectivesetbycontent': $names[] =
'objectivebycontent';
362 case 'type': $names[] =
'c_type';
364 case 'mode': $names[] =
'c_mode';
366 case 'language': $names[] =
'c_language';
368 case 'condition': $names[] =
'c_condition';
370 case 'operator': $names[] =
'c_operator';
373 case 'readnormalizedmeasure': $names[] =
'readnormalmeasure';
375 case 'writenormalizedmeasure': $names[] =
'writenormalmeasure';
377 case 'minnormalizedmeasure': $names[] =
'minnormalmeasure';
379 case 'primary': $names[] =
'c_primary';
382 case 'persistpreviousattempts': $names[] =
'persistprevattempts';
384 case 'identifier': $names[] =
'c_identifier';
386 case 'settings': $names[] =
'c_settings';
388 case 'activityabsolutedurationlimit': $names[] =
'activityabsdurlimit';
390 case 'activityexperienceddurationlimit': $names[] =
'activityexpdurlimit';
392 case 'attemptabsolutedurationlimit': $names[] =
'attemptabsdurlimit';
394 case 'measuresatisfactionifactive': $names[] =
'measuresatisfactive';
396 case 'objectivemeasureweight': $names[] =
'objectivemeasweight';
398 case 'requiredforcompleted': $names[] =
'requiredcompleted';
400 case 'requiredforincomplete': $names[] =
'requiredincomplete';
402 case 'requiredfornotsatisfied': $names[] =
'requirednotsatisfied';
404 case 'rollupobjectivesatisfied': $names[] =
'rollupobjectivesatis';
406 case 'rollupprogresscompletion': $names[] =
'rollupprogcompletion';
408 case 'usecurrentattemptobjectiveinfo': $names[] =
'usecurattemptobjinfo';
410 case 'usecurrentattemptprogressinfo': $names[] =
'usecurattemptproginfo';
412 default: $names[] = strtolower($attr->name);
417 $names[count($names) - 1],
418 array(
'flow',
'completionbycontent',
419 'objectivebycontent',
'rollupobjectivesatis',
421 'choiceexit',
'satisfiedbymeasure',
422 'c_primary',
'constrainchoice',
423 'forwardonly',
'global_to_system',
424 'writenormalmeasure',
'writesatisfiedstatus',
425 'readnormalmeasure',
'readsatisfiedstatus',
426 'preventactivation',
'measuresatisfactive',
427 'reorderchildren',
'usecurattemptproginfo',
428 'usecurattemptobjinfo',
'rollupprogcompletion',
429 'read_shared_data',
'write_shared_data',
430 'shared_data_global_to_system',
'completedbymeasure')
432 if ($attr->value ===
'true') {
434 } elseif ($attr->value ===
'false') {
437 $values[] = (
int) $attr->value;
440 $values[] = $attr->value;
444 $names[count($names) - 1],
445 array(
'objectivesglobtosys',
'attemptlimit',
446 'flow',
'completionbycontent',
447 'objectivebycontent',
'rollupobjectivesatis',
449 'choiceexit',
'satisfiedbymeasure',
450 'c_primary',
'constrainchoice',
451 'forwardonly',
'global_to_system',
452 'writenormalmeasure',
'writesatisfiedstatus',
453 'readnormalmeasure',
'readsatisfiedstatus',
454 'preventactivation',
'measuresatisfactive',
455 'reorderchildren',
'usecurattemptproginfo',
456 'usecurattemptobjinfo',
'rollupprogcompletion',
457 'read_shared_data',
'write_shared_data',
458 'shared_data_global_to_system')
460 $types[] =
'integer';
462 $names[count($names) - 1],
463 array(
'jsdata',
'xmldata',
'activitytree',
'data')
466 } elseif ($names[count($names) - 1] ===
'objectivemeasweight') {
473 if ($node->nodeName ===
'datamap') {
476 $types[] =
'integer';
478 $names[] =
'sco_node_id';
480 $types[] =
'integer';
484 $insert_data = array();
485 foreach ($names as
$key => $db_field) {
486 $insert_data[$db_field] = array($types[
$key], trim((
string) $values[$key]));
488 $ilDB->insert(
'cp_' . strtolower($node->nodeName), $insert_data);
490 $node->setAttribute(
'foreignId', (
string) $cp_node_id);
491 $this->idmap[$node->getAttribute(
'id')] = $cp_node_id;
494 foreach ($node->childNodes as $child) {
495 $this->
dbImport($child, $lft, $depth + 1, $cp_node_id);
499 $query =
'UPDATE cp_tree SET rgt = %s WHERE child = %s';
502 array(
'integer',
'integer'),
503 array($lft++, $cp_node_id)
520 $ilDB = $DIC->database();
527 'SELECT cp_node.cp_node_id FROM cp_node WHERE cp_node.slm_id = %s',
529 array($this->packageId)
532 $cp_nodes[] =
$data[
'cp_node_id'];
536 foreach (self::$elements[
'cp'] as $t) {
539 $in =
$ilDB->in(strtolower($t) .
'.cp_node_id', $cp_nodes,
false,
'integer');
540 $ilDB->manipulate(
'DELETE FROM ' . strtolower($t) .
' WHERE ' . $in);
545 'DELETE FROM cp_tree WHERE cp_tree.obj_id = %s',
547 array($this->packageId)
551 'DELETE FROM cp_node WHERE cp_node.slm_id = %s',
553 array($this->packageId)
558 'DELETE FROM cp_package WHERE cp_package.obj_id = %s',
560 array($this->packageId)
578 if (!@$xsl->load($xslfile)) {
579 die(
'ERROR: load StyleSheet ' . $xslfile);
581 $prc =
new XSLTProcessor();
582 $prc->registerPHPFunctions();
583 $r = @$prc->importStyleSheet($xsl);
584 if (
false === @$prc->importStyleSheet($xsl)) {
585 die(
'ERROR: importStyleSheet ' . $xslfile);
588 file_put_contents($outputpath, $prc->transformToXML($inputdoc));
590 return $prc->transformToDoc($inputdoc);
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getLogger(string $a_component_id)
Get component logger.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
__construct(?int $packageId=null)
dbImport(object $node, ?int &$lft=1, ?int $depth=1, ?int $parent=0)
il_import(string $packageFolder, int $packageId, bool $reimport=false)
Imports an extracted SCORM 2004 module from ilias-data dir into database.
static _refreshStatus(int $a_obj_id, ?array $a_users=null)
jsonNode(object $node, ?array &$sink)
Helper for UploadAndImport Recursively copies values from XML into PHP array for export as json Eleme...
transform(\DOMDocument $inputdoc, string $xslfile, ?string $outputpath=null)
static removeCMIDataForUser(int $user_id)
static removeCMIDataForPackage(int $packageId)
static _lookupType(int $id, bool $reference=false)
static _removeTrackingDataForUser(int $user_id)
static _writeDescription(int $obj_id, string $desc)
write description to db (static)