ILIAS  eassessment Revision 61809
 All Data Structures Namespaces Files Functions Variables Groups Pages
ilSCORM13Package.php
Go to the documentation of this file.
1 <?php
2 
3 /* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
4 
11 require_once "./Modules/Scorm2004/classes/ilSCORM13Package.php";
12 require_once "./Modules/Scorm2004/classes/class.ilSCORM2004Chapter.php";
13 require_once "./Modules/Scorm2004/classes/class.ilSCORM2004Sco.php";
14 require_once "./Modules/Scorm2004/classes/class.ilSCORM2004PageNode.php";
15 require_once "./Modules/Scorm2004/classes/adlparser/SeqTreeBuilder.php";
16 require_once("./Modules/ScormAicc/classes/SCORM/class.ilSCORMTree.php");
17 
19 {
20 
21  const DB_ENCODE_XSL = './Modules/Scorm2004/templates/xsl/op/op-scorm13.xsl';
22  const CONVERT_XSL = './Modules/Scorm2004/templates/xsl/op/scorm12To2004.xsl';
23  const DB_DECODE_XSL = './Modules/Scorm2004/templates/xsl/op/op-scorm13-revert.xsl';
24  const VALIDATE_XSD = './Modules/Scorm2004/templates/xsd/op/op-scorm13.xsd';
25 
26  const WRAPPER_HTML = './Modules/Scorm2004/scripts/converter/GenericRunTimeWrapper1.0_aadlc/GenericRunTimeWrapper.htm';
27  const WRAPPER_JS = './Modules/Scorm2004/scripts/converter/GenericRunTimeWrapper1.0_aadlc/SCOPlayerWrapper.js';
28 
29 
30  private $packageFile;
31  private $packageFolder;
32  private $packagesFolder;
33  private $packageData;
34  private $slm;
35  private $slm_tree;
36 
37  public $imsmanifest;
38  public $manifest;
39  public $diagnostic;
40  public $status;
41  public $packageId;
42  public $packageName;
43  public $packageHash;
44  public $userId;
45 
46  private $idmap = array();
47  private $progress = 0.0;
48 
49  static private $elements = array(
50  'cp' => array(
51  'manifest',
52  'organization',
53  'item',
54  'hideLMSUI',
55  'resource',
56  'file',
57  'dependency',
58  'sequencing',
59  'rule',
60  'auxilaryResource',
61  'condition',
62  'mapinfo',
63  'objective',
64  ),
65  'cmi' => array(
66  'comment',
67  'correct_response',
68  'interaction',
69  'node',
70  'objective',
71  ),
72  );
73 
74  public function __construct($packageId = null)
75  {
76  $this->packagesFolder = IL_OP_PACKAGES_FOLDER;
77  $this->load($packageId);
78  $this->userId = $GLOBALS['USER']['usr_id'];
79  }
80 
81  public function load($packageId)
82  {
83  global $ilDB;
84 
85  if (!is_numeric($packageId))
86  {
87  return false;
88  }
89 
90  $lm_set = $ilDB->queryF('SELECT * FROM sahs_lm WHERE id = %s', array('integer'), array($packageId));
91  $lm_data = $ilDB->fetchAssoc($lm_set);
92  $pg_set = $ilDB->queryF('SELECT * FROM cp_package WHERE obj_id = %s', array('integer'), array($packageId));
93  $pg_data = $ilDB->fetchAssoc($lm_set);
94 
95  $this->packageData = array_merge($lm_data, $pg_data);
96  $this->packageId = $packageId;
97  $this->packageFolder = $this->packagesFolder . '/' . $packageId;
98  $this->packageFile = $this->packageFolder . '.zip';
99  $this->imsmanifestFile = $this->packageFolder . '/' . 'imsmanifest.xml';
100  return true;
101  }
102 
103  public function rollback()
104  {
105  $this->setProgress(0, 'Rolling back...');
106  $this->dbRemoveAll();
107  if (is_dir($this->packageFolder))
108  dir_delete($this->packageFolder);
109  if (is_file($this->packageFile))
110  @unlink($this->packageFile);
111  $this->setProgress(0, 'Roll back finished: Ok. ');
112  }
113 
114  public function exportZIP()
115  {
116  header('content-type: application/zip');
117  header('content-disposition: attachment; filename="' . basename($this->packageFile) . '"');
118  readfile($this->packageFile);
119  }
120 
124  public function exportXML()
125  {
126  global $ilDB;
127 
128  header('content-type: text/xml');
129  header('content-disposition: attachment; filename="manifest.xml"');
130 
131  //$row = ilSCORM13DB::getRecord("cp_package", "obj_id",$this->packageId);
132  $res = $ilDB->queryF(
133  'SELECT xmldata FROM cp_package WHERE obj_id = %s',
134  array('integer'),
135  array($this->packageId)
136  );
137  $row = $ilDB->fetchAssoc($res);
138 
139  print($row['xmldata']);
140  }
141 
142 
149  public function il_import($packageFolder,$packageId,$ilias,$validate,$reimport=false){
150  global $ilDB, $ilLog, $ilErr;
151 
152 
153  if ($reimport === true) {
154  $this->packageId = $packageId;
155  $this->dbRemoveAll();
156  }
157 
158  $this->packageFolder=$packageFolder;
159  $this->packageId=$packageId;
160  $this->imsmanifestFile = $this->packageFolder . '/' . 'imsmanifest.xml';
161  //step 1 - parse Manifest-File and validate
162  $this->imsmanifest = new DOMDocument;
163  $this->imsmanifest->async = false;
164  if (!@$this->imsmanifest->load($this->imsmanifestFile))
165  {
166  $this->diagnostic[] = 'XML not wellformed';
167  return false;
168  }
169 
170  //step 2 tranform
171  $this->manifest = $this->transform($this->imsmanifest, self::DB_ENCODE_XSL);
172 
173  if (!$this->manifest)
174  {
175  $this->diagnostic[] = 'Cannot transform into normalized manifest';
176  return false;
177  }
178  //step 3 validation -just for normalized XML
179  if ($validate=="y") {
180  if (!$this->validate($this->manifest, self::VALIDATE_XSD))
181  {
182 
183  $ilErr->raiseError("<b>The uploaded SCORM 1.2 / SCORM 2004 is not valid. You can try to import the package without the validation option checked on your own risk. </b><br><br>Validation Error(s):</b><br> Normalized XML is not conform to ". self::VALIDATE_XSD,
184  $ilErr->MESSAGE);
185  }
186  }
187  $this->dbImport($this->manifest);
188 
189  if(file_exists($this->packageFolder . '/' . 'index.xml'))
190  {
191  $doc = simplexml_load_file($this->packageFolder . '/' . 'index.xml');
192  $l = $doc->xpath ("/ContentObject/MetaData" );
193  if($l[0])
194  {
195  include_once 'Services/MetaData/classes/class.ilMDXMLCopier.php';
197  $mdxml->startParsing();
198  $mdxml->getMDObject()->update();
199  }
200  }
201 
202  //step 5
203  $x = simplexml_load_string($this->manifest->saveXML());
204  $x['persistPreviousAttempts'] = $this->packageData['persistprevattempts'];
205  $x['online'] = $this->packageData['c_online'];
206 
207  $x['defaultLessonMode'] = $this->packageData['default_lesson_mode'];
208  $x['credit'] = $this->packageData['credit'];
209  $x['autoReview'] = $this->packageData['auto_review'];
210  $j = array();
211  // first read resources into flat array to resolve item/identifierref later
212  $r = array();
213  foreach ($x->resource as $xe)
214  {
215  $r[strval($xe['id'])] = $xe;
216  unset($xe);
217  }
218  // iterate through items and set href and scoType as activity attributes
219  foreach ($x->xpath('//*[local-name()="item"]') as $xe)
220  {
221  // get reference to resource and set href accordingly
222  if ($b = $r[strval($xe['resourceId'])])
223  {
224  $xe['href'] = strval($b['base']) . strval($b['href']);
225  unset($xe['resourceId']);
226  if (strval($b['scormType'])=='sco') $xe['sco'] = true;
227  }
228  }
229  // iterate recursivly through activities and build up simple php object
230  // with items and associated sequencings
231  // top node is the default organization which is handled as an item
232  self::jsonNode($x->organization, $j['item']);
233  foreach($x->sequencing as $s)
234  {
235  self::jsonNode($s, $j['sequencing'][]);
236  }
237  // combined manifest+resources xml:base is set as organization base
238  $j['item']['base'] = strval($x['base']);
239  // package folder is base to whole playing process
240  $j['base'] = $packageFolder . '/';
241  $j['foreignId'] = floatval($x['foreignId']); // manifest cp_node_id for associating global (package wide) objectives
242  $j['id'] = strval($x['id']); // manifest id for associating global (package wide) objectives
243 
244 
245  //last step - build ADL Activity tree
246  $act = new SeqTreeBuilder();
247  $adl_tree = $act->buildNodeSeqTree($this->imsmanifestFile);
248  $ilDB->update('cp_package',
249  array(
250  'xmldata' => array('clob', $x->asXML()),
251  'jsdata' => array('clob', json_encode($j)),
252  'activitytree' => array('clob', json_encode($adl_tree['tree'])),
253  'global_to_system' => array('integer', (int)$adl_tree['global'])
254  ),
255  array(
256  'obj_id' => array('integer', (int)$this->packageId)
257  )
258  );
259 
260  return $j['item']['title'];
261  }
262 
263 
270  public function il_importSco($packageId, $sco_id, $packageFolder)
271  {
272  global $ilDB, $ilLog;
273 
274 
275  $this->packageFolder=$packageFolder;
276  $this->packageId=$packageId;
277  $this->imsmanifestFile = $this->packageFolder . '/' . 'index.xml';
278  $this->imsmanifest = new DOMDocument;
279  $this->imsmanifest->async = false;
280 
281  if (!@$this->imsmanifest->load($this->imsmanifestFile))
282  {
283  $this->diagnostic[] = 'XML not wellformed';
284  return false;
285  }
286 
288  $sco = new ilSCORM2004Sco($slm,$sco_id);
289  $this->dbImportSco($slm,$sco);
290 
291  // import sco.xml
292  $sco_xml_file = $this->packageFolder . '/sco.xml';
293  if (is_file($sco_xml_file))
294  {
295  $scodoc = new DOMDocument;
296  $scodoc->async = false;
297  if (!@$scodoc->load($sco_xml_file))
298  {
299  $this->diagnostic[] = 'XML of sco.xml not wellformed';
300  return false;
301  }
302  //$doc = new SimpleXMLElement($scodoc->saveXml());
303  //$l = $doc->xpath("/sco/objective");
304  $xpath = new DOMXPath($scodoc);
305  $nodes = $xpath->query("/sco/objective");
306  foreach($nodes as $node)
307  {
308  $t_node = $node->firstChild;
309  if (is_object($t_node))
310  {
311  $objective_text = $t_node->textContent;
312  if (trim($objective_text) != "")
313  {
314  $objs = $sco->getObjectives();
315  foreach ($objs as $o)
316  {
317  $mappings = $o->getMappings();
318  if ($mappings == null)
319  {
320  $ob = new ilScorm2004Objective($sco->getId(), $o->getId());
321  $ob->setObjectiveID($objective_text);
322  $ob->updateObjective();
323  }
324  }
325  }
326  }
327  }
328  }
329  return "";
330  }
331 
332  public function il_importLM($slm, $packageFolder)
333  {
334  global $ilDB, $ilLog;
335 
336  $this->packageFolder=$packageFolder;
337  $this->packageId=$slm->getId();
338  $this->imsmanifestFile = $this->packageFolder . '/' . 'imsmanifest.xml';
339  $this->imsmanifest = new DOMDocument;
340  $this->imsmanifest->async = false;
341  $this->slm = $slm;
342  if (!@$this->imsmanifest->load($this->imsmanifestFile))
343  {
344  $this->diagnostic[] = 'XML not wellformed';
345  return false;
346  }
347  $this->dbImportLM(simplexml_import_dom($this->imsmanifest->documentElement),$this->slm);
348  if(is_dir($packageFolder."/glossary"))
349  {
350  $this->importGlossary($slm,$packageFolder."/glossary");
351  }
352  //die($slm->title);
353  return $slm->title;
354  }
355 
357  {
358  global $ilias;
359  // create and insert object in objecttree
360  include_once("./Modules/Glossary/classes/class.ilObjGlossary.php");
361  $newObj = new ilObjGlossary();
362  $newObj->setType('glo');
363  $newObj->setTitle('');
364  $newObj->create(true);
365  $newObj->createReference();
366  $newObj->putInTree($_GET["ref_id"]);
367  $newObj->setPermissions($_GET["ref_id"]);
368  $newObj->notify("new",$_GET["ref_id"],$_GET["parent_non_rbac_id"],$_GET["ref_id"],$newObj->getRefId());
369 
370  $xml_file = $packageFolder."/glossary.xml";
371 
372  // check whether xml file exists within zip file
373  if (!is_file($xml_file))
374  {
375  return;
376  }
377 
378  include_once ("./Modules/LearningModule/classes/class.ilContObjParser.php");
379  $contParser = new ilContObjParser($newObj, $xml_file, $packageFolder);
380  $contParser->startParsing();
381  $newObj->update();
382  //ilObject::_writeImportId($newObj->getId(), $newObj->getImportId());
383  $slm->setAssignedGlossary($newObj->getId());
384  $slm->update();
385  }
386 
387  function dbImportLM($node, $parent_id)
388  {
389 
390  switch($node->getName())
391  {
392  case "manifest":
393  $this->slm_tree =& new ilTree($this->slm->getId());
394  $this->slm_tree->setTreeTablePK("slm_id");
395  $this->slm_tree->setTableNames('sahs_sc13_tree', 'sahs_sc13_tree_node');
396  $this->slm_tree->addTree($this->slm->getId(), 1);
397  //add seqinfo for rootNode
398  include_once ("./Modules/Scorm2004/classes/seq_editor/class.ilSCORM2004Sequencing.php");
399  $seq_info = new ilSCORM2004Sequencing($this->slm->getId(),true);
400  $seq_info->insert();
401 
402  if(file_exists($this->packageFolder . '/' . 'index.xml'))
403  {
404  $doc = simplexml_load_file($this->packageFolder . '/' . 'index.xml');
405  $l = $doc->xpath ( "/ContentObject/MetaData" );
406  if($l[0])
407  {
408  include_once 'Services/MetaData/classes/class.ilMDXMLCopier.php';
409  $mdxml =& new ilMDXMLCopier($l[0]->asXML(),$this->slm->getId(),$this->slm->getId(),$this->slm->getType());
410  $mdxml->startParsing();
411  $mdxml->getMDObject()->update();
412  }
413  }
414  break;
415  case "organization":
416  $this->slm->title=$node->title;
417  break;
418  case "item":
419  $a = $node->attributes();
420  if(preg_match("/il_\d+_chap_\d+/",$a['identifier']))
421  {
422  $chap=& new ilSCORM2004Chapter($this->slm);
423  $chap->setTitle($node->title);
424  $chap->setSLMId($this->slm->getId());
425  $chap->create(true);
426  ilSCORM2004Node::putInTree($chap, "", "");
427  $parent_id=$chap->getId();
428  $doc = simplexml_load_file($this->packageFolder . '/' . 'index.xml');
429  $l = $doc->xpath ( "/ContentObject/StructureObject/MetaData[General/Identifier/@Entry='".$a['identifier']."']" );
430  if($l[0])
431  {
432  include_once 'Services/MetaData/classes/class.ilMDXMLCopier.php';
433  $mdxml =& new ilMDXMLCopier($l[0]->asXML(),$this->slm->getId(),$chap->getId(),$chap->getType());
434  $mdxml->startParsing();
435  $mdxml->getMDObject()->update();
436  }
437  }
438  if(preg_match("/il_\d+_sco_(\d+)/",$a['identifier'], $match))
439  {
440  $sco = new ilSCORM2004Sco($this->slm);
441  $sco->setTitle($node->title);
442  $sco->setSLMId($this->slm->getId());
443  $sco->create(true);
444  ilSCORM2004Node::putInTree($sco, $parent_id, "");
445  $newPack = new ilSCORM13Package();
446  $newPack->il_importSco($this->slm->getId(),$sco->getId(),$this->packageFolder."/".$match[1]);
447  $parent_id = $sco->getId();
448  }
449 
450  break;
451  }
452  //if($node->nodeType==XML_ELEMENT_NODE)
453  {
454  foreach($node->children() as $child)
455  {
456  $this->dbImportLM($child,$parent_id);
457  }
458  }
459  }
460 
461  private function setProgress($progress, $msg = '')
462  {
463  $this->progress = $progress;
464  $this->diagnostic[] = $msg;
465  }
466 
475  public function jsonNode($node, &$sink)
476  {
477  foreach ($node->attributes() as $k => $v)
478  {
479  // cast to boolean and number if possible
480  $v = strval($v);
481  if ($v==="true") $v = true;
482  else if ($v==="false") $v = false;
483  else if (is_numeric($v)) $v = (float) $v;
484  $sink[$k] = $v;
485  }
486  foreach ($node->children() as $name => $child)
487  {
488  self::jsonNode($child, $sink[$name][]); // RECURSION
489  }
490  }
491 
492  public function dbImportSco($slm,$sco)
493  {
494  $qtis = array();
495  $d = ilUtil::getDir ( $this->packageFolder );
496  foreach ( $d as $f ) {
497  //continue;
498  if ($f [type] == 'file' && substr ( $f [entry], 0, 4 ) == 'qti_') {
499  include_once "./Services/QTI/classes/class.ilQTIParser.php";
500  include_once "./Modules/Test/classes/class.ilObjTest.php";
501 
502 
503  $qtiParser = new ilQTIParser ( $this->packageFolder . "/" . $f [entry], IL_MO_VERIFY_QTI, 0, "" );
504  $result = $qtiParser->startParsing ();
505  $founditems = & $qtiParser->getFoundItems ();
506  // die(print_r($founditems));
507  foreach ( $founditems as $qp ) {
508  $newObj = new ilObjTest ( 0, true );
509 
510  // This creates a lot of invalid repository objects for each question
511  // question are not repository objects (see e.g. table object_data), alex 29 Sep 2009
512 
513 // $newObj->setType ( $qp ['type'] );
514 // $newObj->setTitle ( $qp ['title'] );
515 // $newObj->create ( true );
516 // $newObj->createReference ();
517 // $newObj->putInTree ($_GET ["ref_id"]);
518 // $newObj->setPermissions ( $sco->getId ());
519 // $newObj->notify ("new", $_GET["ref_id"], $sco->getId (), $_GET["ref_id"], $newObj->getRefId () );
520 // $newObj->mark_schema->flush ();
521  $qtiParser = new ilQTIParser ( $this->packageFolder . "/" . $f [entry], IL_MO_PARSE_QTI, 0, "" );
522  $qtiParser->setTestObject ( $newObj );
523  $result = $qtiParser->startParsing ();
524 // $newObj->saveToDb ();
525  $qtis = array_merge($qtis, $qtiParser->getImportMapping());
526 
527  }
528  }
529  }
530 //exit;
531  include_once 'class.ilSCORM2004Page.php';
532  $doc = new SimpleXMLElement($this->imsmanifest->saveXml());
533  $l = $doc->xpath ( "/ContentObject/MetaData" );
534  if($l[0])
535  {
536  include_once 'Services/MetaData/classes/class.ilMDXMLCopier.php';
537  $mdxml =& new ilMDXMLCopier($l[0]->asXML(),$slm->getId(),$sco->getId(),$sco->getType());
538  $mdxml->startParsing();
539  $mdxml->getMDObject()->update();
540  }
541  $l = $doc->xpath("/ContentObject/PageObject");
542  foreach ( $l as $page_xml )
543  {
544  $tnode = $page_xml->xpath ( 'MetaData/General/Title' );
545  $page = new ilSCORM2004PageNode ( $slm );
546  $page->setTitle ( $tnode [0] );
547  $page->setSLMId ( $slm->getId () );
548  $page->create (true);
549  ilSCORM2004Node::putInTree ( $page, $sco->getId (), $target );
550  $pmd = $page_xml->xpath ("MetaData");
551  if($pmd[0])
552  {
553  include_once 'Services/MetaData/classes/class.ilMDXMLCopier.php';
554  $mdxml =& new ilMDXMLCopier($pmd[0]->asXML(),$slm->getId(),$page->getId(),$page->getType());
555  $mdxml->startParsing();
556  $mdxml->getMDObject()->update();
557  }
558  $tnode = $page_xml->xpath("//MediaObject/MediaAlias");
559  foreach($tnode as $ttnode)
560  {
561  include_once './Services/MediaObjects/classes/class.ilObjMediaObject.php';
562  $OriginId = $ttnode[OriginId];
563  $medianodes = $doc->xpath("//MediaObject[MetaData/General/Identifier/@Entry='".$OriginId ."']");
564  $medianode = $medianodes[0];
565  if($medianode)
566  {
567  $media_object = new ilObjMediaObject ( );
568  $media_object->setTitle ($medianode->MetaData->General->Title);
569  $media_object->setDescription ($medianode->MetaData->General->Description);
570  $media_object->create (false);
571  $mmd = $medianode->xpath ("MetaData");
572  if($mmd[0])
573  {
574  include_once 'Services/MetaData/classes/class.ilMDXMLCopier.php';
575  $mdxml =& new ilMDXMLCopier($mmd[0]->asXML(),0,$media_object->getId(),$media_object->getType());
576  $mdxml->startParsing();
577  $mdxml->getMDObject()->update();
578  }
579  // determine and create mob directory, move uploaded file to directory
580  $media_object->createDirectory ();
581  $mob_dir = ilObjMediaObject::_getDirectory ( $media_object->getId () );
582  foreach ( $medianode->MediaItem as $xMediaItem )
583  {
584  $media_item = & new ilMediaItem ( );
585  $media_object->addMediaItem ( $media_item );
586  $media_item->setPurpose($xMediaItem[Purpose]);
587  $media_item->setFormat($xMediaItem->Format );
588  $media_item->setLocation($xMediaItem->Location);
589  $media_item->setLocationType($xMediaItem->Location[Type]);
590  $media_item->setWidth ( $xMediaItem->Layout[Width]);
591  $media_item->setHeight ( $xMediaItem->Layout[Height]);
592  $media_item->setHAlign($xMediaItem->Layout[HorizontalAlign]);
593  if($media_item->getLocationType()=="LocalFile")
594  {
595  $tmp_name = $this->packageFolder."/objects/".$OriginId."/".$xMediaItem->Location;
596  copy($tmp_name, $mob_dir."/".$xMediaItem->Location);
597  }
598  }
599 
600  // alex: fixed media import: these lines have been
601  // behind the next curly bracket which makes it fail
602  // when no medianode is given. (id=0 -> fatal error)
603  ilUtil::renameExecutables ( $mob_dir );
604  $media_object->update(true);
605  $ttnode [OriginId] = "il__mob_" . $media_object->getId ();
606  }
607  }
608  include_once("./Modules/File/classes/class.ilObjFile.php");
609  include_once("./Services/Utilities/classes/class.ilFileUtils.php");
610  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
611 
612  $intlinks = $page_xml->xpath("//IntLink");
613  //die($intlinks);
614  //if($intlinks )
615  {
616  foreach ( $intlinks as $intlink )
617  {
618  if($intlink[Type]!="File") continue;
619  $path = $this->packageFolder."/objects/".str_replace('dfile','file',$intlink[Target]);
620  if(!is_dir($path )) continue;
621  $ffiles = array();
623  $filename = $ffiles[file][0];
624  $fileObj = new ilObjFile();
625  $fileObj->setType("file");
628 
629  // better use this, mime_content_type is deprecated
630  $fileObj->setFileType(ilObjMediaObject::getMimeType($path. "/" . $filename));
631 
632  $fileObj->setFileSize(filesize($path. "/" . $filename));
633  $fileObj->create();
634  $fileObj->createReference();
635  //$fileObj->putInTree($_GET["ref_id"]);
636  //$fileObj->setPermissions($slm->getId ());
637  $fileObj->createDirectory();
638  $fileObj->storeUnzipedFile($path."/" .$filename,ilFileUtils::utf8_encode(ilUtil::stripSlashes($filename)));
639  $intlink[Target]="il__dfile_".$fileObj->getId();
640 
641  }
642  }
643  $fileitems = $page_xml->xpath("//FileItem/Identifier");
644  //if($intlinks )
645  {
646  foreach ( $fileitems as $fileitem )
647  {
648  $path = $this->packageFolder."/objects/".$fileitem[Entry];
649  if(!is_dir($path )) continue;
650  $ffiles = array();
652  $filename = $ffiles[file][0];
653  $fileObj = new ilObjFile();
654  $fileObj->setType("file");
657 
658  // better use this, mime_content_type is deprecated
659  $fileObj->setFileType(ilObjMediaObject::getMimeType($path. "/" . $filename));
660 
661  $fileObj->setFileSize(filesize($path. "/" . $filename));
662  $fileObj->create();
663  $fileObj->createReference();
664  //$fileObj->putInTree($_GET["ref_id"]);
665  //$fileObj->setPermissions($slm->getId ());
666  $fileObj->createDirectory();
667  $fileObj->storeUnzipedFile($path."/" .$filename,ilFileUtils::utf8_encode(ilUtil::stripSlashes($filename)));
668  $fileitem[Entry]="il__file_".$fileObj->getId();
669 
670  }
671  }
672  $pagex = new ilSCORM2004Page($page->getId());
673 
674  $ddoc = new DOMDocument();
675  $ddoc->async = false;
676  $ddoc->preserveWhiteSpace = false;
677  $ddoc->formatOutput = false;
678  $ddoc->loadXML($page_xml->asXML());
679  $xpath = new DOMXPath($ddoc);
680  $tnode = $xpath->query('PageContent');
681  $t = "<PageObject>";
682  foreach($tnode as $ttnode)
683  $t .= $ddoc->saveXML($ttnode);
684  $t .="</PageObject>";
685  foreach ($qtis as $old=>$q)
686  $t = str_replace($old,'il__qst_'.$q['pool'], $t);
687  $pagex->setXMLContent($t);
688  $pagex->updateFromXML();
689  }
690  }
691 
692  public function dbImport($node, &$lft=1, $depth=1, $parent=0)
693  {
694  global $ilDB;
695 
696  switch ($node->nodeType)
697  {
698  case XML_DOCUMENT_NODE:
699 
700  // insert into cp_package
701  /*ilSCORM13DB::setRecord('cp_package', array(
702  'obj_id' => $this->packageId,
703  'identifier' => $this->packageName,
704  'persistPreviousAttempts' => 0,
705  'settings' => '',
706  ));*/
707 
708  $res = $ilDB->queryF(
709  'SELECT * FROM cp_package WHERE obj_id = %s AND c_identifier = %s',
710  array('integer', 'text'),
711  array($this->packageId, $this->packageName)
712  );
713  if($num_rows = $ilDB->numRows($res))
714  {
715  $query = 'UPDATE cp_package '
716  . 'SET persistprevattempts = %s, c_settings = %s '
717  . 'WHERE obj_id = %s AND c_identifier= %s';
718  $ilDB->manipulateF(
719  $query,
720  array('integer', 'text', 'integer', 'text'),
721  array(0, NULL, $this->packageId, $this->packageName)
722  );
723  }
724  else
725  {
726  $query = 'INSERT INTO cp_package (obj_id, c_identifier, persistprevattempts, c_settings) '
727  . 'VALUES (%s, %s, %s, %s)';
728  $ilDB->manipulateF(
729  $query,
730  array('integer','text','integer', 'text'),
731  array($this->packageId, $this->packageName, 0, NULL)
732  );
733  }
734 
735  // run sub nodes
736  $this->dbImport($node->documentElement); // RECURSION
737  break;
738 
739  case XML_ELEMENT_NODE:
740  if ($node->nodeName==='manifest')
741  {
742  if ($node->getAttribute('uri')=="")
743  {
744  // default URI is md5 hash of zip file, i.e. packageHash
745  $node->setAttribute('uri', 'md5:' . $this->packageHash);
746  }
747  }
748 
749  $cp_node_id = $ilDB->nextId('cp_node');
750 
751  $query = 'INSERT INTO cp_node (cp_node_id, slm_id, nodename) '
752  . 'VALUES (%s, %s, %s)';
753  $ilDB->manipulateF(
754  $query,
755  array('integer', 'integer', 'text'),
756  array($cp_node_id, $this->packageId, $node->nodeName)
757  );
758 
759  $query = 'INSERT INTO cp_tree (child, depth, lft, obj_id, parent, rgt) '
760  . 'VALUES (%s, %s, %s, %s, %s, %s)';
761  $ilDB->manipulateF(
762  $query,
763  array('integer', 'integer', 'integer', 'integer', 'integer', 'integer'),
764  array($cp_node_id, $depth, $lft++, $this->packageId, $parent, 0)
765  );
766 
767  // insert into cp_*
768  //$a = array('cp_node_id' => $cp_node_id);
769  $names = array('cp_node_id');
770  $values = array($cp_node_id);
771  $types = array('integer');
772 
773  foreach ($node->attributes as $attr)
774  {
775  switch(strtolower($attr->name))
776  {
777  case 'completionsetbycontent': $names[] = 'completionbycontent';break;
778  case 'objectivesetbycontent': $names[] = 'objectivebycontent';break;
779  case 'type': $names[] = 'c_type';break;
780  case 'mode': $names[] = 'c_mode';break;
781  case 'language': $names[] = 'c_language';break;
782  case 'condition': $names[] = 'c_condition';break;
783  case 'operator': $names[] = 'c_operator';break;
784  case 'condition': $names[] = 'c_condition';break;
785  case 'readnormalizedmeasure': $names[] = 'readnormalmeasure';break;
786  case 'writenormalizedmeasure': $names[] = 'writenormalmeasure';break;
787  case 'minnormalizedmeasure': $names[] = 'minnormalmeasure';break;
788  case 'primary': $names[] = 'c_primary';break;
789  case 'minnormalizedmeasure': $names[] = 'minnormalmeasure';break;
790  case 'persistpreviousattempts': $names[] = 'persistprevattempts';break;
791  case 'identifier': $names[] = 'c_identifier';break;
792  case 'settings': $names[] = 'c_settings';break;
793  case 'activityabsolutedurationlimit': $names[] = 'activityabsdurlimit';break;
794  case 'activityexperienceddurationlimit': $names[] = 'activityexpdurlimit';break;
795  case 'attemptabsolutedurationlimit': $names[] = 'attemptabsdurlimit';break;
796  case 'measuresatisfactionifactive': $names[] = 'measuresatisfactive';break;
797  case 'objectivemeasureweight': $names[] = 'objectivemeasweight';break;
798  case 'requiredforcompleted': $names[] = 'requiredcompleted';break;
799  case 'requiredforincomplete': $names[] = 'requiredincomplete';break;
800  case 'requiredfornotsatisfied': $names[] = 'requirednotsatisfied';break;
801  case 'rollupobjectivesatisfied': $names[] = 'rollupobjectivesatis';break;
802  case 'rollupprogresscompletion': $names[] = 'rollupprogcompletion';break;
803  case 'usecurrentattemptobjectiveinfo': $names[] = 'usecurattemptobjinfo';break;
804  case 'usecurrentattemptprogressinfo': $names[] = 'usecurattemptproginfo';break;
805  default: $names[] = strtolower($attr->name);break;
806  }
807 
808  if(in_array($names[count($names) - 1],
809  array('flow', 'completionbycontent',
810  'objectivebycontent', 'rollupobjectivesatis',
811  'tracked', 'choice',
812  'choiceexit', 'satisfiedbymeasure',
813  'c_primary', 'constrainchoice',
814  'forwardonly', 'global_to_system',
815  'writenormalmeasure', 'writesatisfiedstatus',
816  'readnormalmeasure', 'readsatisfiedstatus',
817  'preventactivation', 'measuresatisfactive',
818  'reorderchildren', 'usecurattemptproginfo',
819  'usecurattemptobjinfo', 'rollupprogcompletion')))
820  {
821  if($attr->value == 'true')
822  $values[] = 1;
823  else if ($attr->value == 'false')
824  $values[] = 0;
825  else
826  $values[] = (int)$attr->value;
827  }
828  else
829  {
830  $values[] = $attr->value;
831  }
832 
833  if( in_array($names[count($names) - 1],
834  array('objectivesglobtosys', 'attemptlimit',
835  'flow', 'completionbycontent',
836  'objectivebycontent', 'rollupobjectivesatis',
837  'tracked', 'choice',
838  'choiceexit', 'satisfiedbymeasure',
839  'c_primary', 'constrainchoice',
840  'forwardonly', 'global_to_system',
841  'writenormalmeasure', 'writesatisfiedstatus',
842  'readnormalmeasure', 'readsatisfiedstatus',
843  'preventactivation', 'measuresatisfactive',
844  'reorderchildren', 'usecurattemptproginfo',
845  'usecurattemptobjinfo', 'rollupprogcompletion')))
846  $types[] = 'integer';
847  else if ( in_array($names[count($names) - 1],
848  array('jsdata', 'xmldata', 'activitytree', 'data')))
849  $types[] = 'clob';
850  else if ( in_array($names[count($names) - 1],
851  array('objectivemeasweight')))
852  $types[] = 'float';
853  else
854  $types[] = 'text';
855  }
856 
857  // we have to change the insert method because of clob fields ($ilDB->manipulate does not work here)
858  $insert_data = array();
859  foreach($names as $key => $db_field)
860  {
861  $insert_data[$db_field] = array($types[$key], trim($values[$key]));
862  }
863  $ilDB->insert('cp_'.strtolower($node->nodeName), $insert_data);
864 
865  $node->setAttribute('foreignId', $cp_node_id);
866  $this->idmap[$node->getAttribute('id')] = $cp_node_id;
867 
868  // run sub nodes
869  foreach($node->childNodes as $child)
870  {
871  $this->dbImport($child, $lft, $depth + 1, $cp_node_id); // RECURSION
872  }
873 
874  // update cp_tree (rgt value for pre order walk in sql tree)
875  $query = 'UPDATE cp_tree SET rgt = %s WHERE child = %s';
876  $ilDB->manipulateF(
877  $query,
878  array('integer', 'integer'),
879  array($lft++, $cp_node_id)
880  );
881 
882  break;
883  }
884  }
885 
889  public function dbAddNew()
890  {
891  global $ilDB;
892 
893  //$this->packageId = 100;
894  //return true;
895  //ilSCORM13DB::getRecord('sahs_lm', array());
896  // $this->packageId = ilSCORM13DB::getRecord('sahs_lm', array());
897 /* ilSCORM13DB::setRecord('cp_package', array(
898  'obj_id' => $this->packageId,
899  'xmldata' => $x->asXML(),
900  'jsdata' => json_encode($j),
901  ), 'obj_id');
902 */
903 
904  $ilDB->insert('cp_package', array(
905  'obj_id' => array('integer', $this->packageId),
906  'xmldata' => array('clob', $x->asXML()),
907  'jsdata' => array('clob', json_encode($j))
908  ));
909 
910  return true;
911  }
912 
913 
914  public function removeCMIData()
915  {
916  global $ilDB;
917 
918  //cmi nodes
919  $cmi_nodes = array();
920 
921  $res = $ilDB->queryF('
922  SELECT cmi_node.cmi_node_id
923  FROM cmi_node, cp_node
924  WHERE cp_node.slm_id = %s AND cmi_node.cp_node_id = cp_node.cp_node_id',
925  array('integer'),
926  array($this->packageId)
927  );
928  while($data = $ilDB->fetchAssoc($res))
929  {
930  $cmi_node_values[] = $data['cmi_node_id'];
931  }
932 
933  //cmi interaction nodes
934  $cmi_inodes = array();
935 
936  $res = $ilDB->queryF('
937  SELECT cmi_interaction.cmi_interaction_id
938  FROM cmi_interaction, cmi_node, cp_node
939  WHERE (cp_node.slm_id = %s
940  AND cmi_node.cp_node_id = cp_node.cp_node_id
941  AND cmi_node.cmi_node_id = cmi_interaction.cmi_node_id)',
942  array('integer'),
943  array($this->packageId)
944  );
945  while($data = $ilDB->fetchAssoc($res))
946  {
947  $cmi_inode_values[] = $data['cmi_interaction_id'];
948  }
949 
950  //response
951  $query = 'DELETE FROM cmi_correct_response WHERE '
952  . $ilDB->in('cmi_correct_response.cmi_interaction_id', $cmi_inode_values, false, 'integer');
953  $ilDB->manipulate($query);
954 
955  //objective interaction
956  $query = 'DELETE FROM cmi_objective WHERE '
957  . $ilDB->in('cmi_objective.cmi_interaction_id', $cmi_inode_values, false, 'integer');
958  $ilDB->manipulate($query);
959 
960  //objective
961  $query = 'DELETE FROM cmi_objective WHERE '
962  . $ilDB->in('cmi_objective.cmi_node_id', $cmi_node_values, false, 'integer');
963  $ilDB->manipulate($query);
964 
965  //interaction
966  $query = 'DELETE FROM cmi_interaction WHERE '
967  . $ilDB->in('cmi_interaction.cmi_node_id', $cmi_node_values, false, 'integer');
968  $ilDB->manipulate($query);
969 
970  //comment
971  $query = 'DELETE FROM cmi_comment WHERE '
972  . $ilDB->in('cmi_comment.cmi_node_id', $cmi_node_values, false, 'integer');
973  $ilDB->manipulate($query);
974 
975  //node
976  $query = 'DELETE FROM cmi_node WHERE '
977  . $ilDB->in('cmi_node.cmi_node_id', $cmi_node_values, false, 'integer');
978  $ilDB->manipulate($query);
979 
980  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
981  ilLPStatusWrapper::_refreshStatus($this->packageId);
982 
983  }
984 
985  public function removeCPData()
986  {
987  global $ilDB, $ilLog;
988 
989  //get relevant nodes
990  $cp_nodes = array();
991 
992  $res = $ilDB->queryF(
993  'SELECT cp_node.cp_node_id FROM cp_node WHERE cp_node.slm_id = %s',
994  array('integer'),
995  array($this->packageId)
996  );
997  while($data = $ilDB->fetchAssoc($res))
998  {
999  $cp_nodes[] = $data['cp_node_id'];
1000  }
1001 
1002  //remove package data
1003  foreach(self::$elements['cp'] as $t)
1004  {
1005  $t = 'cp_' . $t;
1006 
1007  $in = $ilDB->in(strtolower($t).'.cp_node_id', $cp_nodes, false, 'integer');
1008  $ilDB->manipulate('DELETE FROM '.strtolower($t).' WHERE '.$in);
1009  }
1010 
1011  // remove CP structure entries in tree and node
1012  $ilDB->manipulateF(
1013  'DELETE FROM cp_tree WHERE cp_tree.obj_id = %s',
1014  array('integer'),
1015  array($this->packageId)
1016  );
1017 
1018  $ilDB->manipulateF(
1019  'DELETE FROM cp_node WHERE cp_node.slm_id = %s',
1020  array('integer'),
1021  array($this->packageId)
1022  );
1023 
1024  // remove general package entry
1025  $ilDB->manipulateF(
1026  'DELETE FROM cp_package WHERE cp_package.obj_id = %s',
1027  array('integer'),
1028  array($this->packageId)
1029  );
1030  }
1031 
1032  public function dbRemoveAll()
1033  {
1034  //dont change order of calls
1035  $this->removeCMIData();
1036  $this->removeCPData();
1037  }
1038 
1039  public function transform($inputdoc, $xslfile, $outputpath = null)
1040  {
1041  $xsl = new DOMDocument;
1042  $xsl->async = false;
1043  if (!@$xsl->load($xslfile))
1044  {
1045  die('ERROR: load StyleSheet ' . $xslfile);
1046  }
1047  $prc = new XSLTProcessor;
1048  $r = @$prc->importStyleSheet($xsl);
1049  if (false===@$prc->importStyleSheet($xsl))
1050  {
1051  die('ERROR: importStyleSheet ' . $xslfile);
1052  }
1053  if ($outputpath)
1054  {
1055  file_put_contents($outputpath, $prc->transformToXML($inputdoc));
1056  }
1057  else
1058  {
1059  return $prc->transformToDoc($inputdoc);
1060  }
1061  }
1062 
1063  public function validate($doc, $schema)
1064  {
1065  libxml_use_internal_errors(true);
1066  $return = @$doc->schemaValidate($schema);
1067  if (!$return)
1068  {
1069  $levels = array(
1070  LIBXML_ERR_ERROR => 'Error',
1071  LIBXML_ERR_FATAL => 'Fatal Error'
1072  );
1073  foreach (libxml_get_errors() as $error)
1074  {
1075  $level = $levels[$error->level];
1076  if (isset($level))
1077  {
1078  $message = trim($error->message);
1079  $this->diagnostic[] = "XSLT $level (Line $error->line) $message";
1080  }
1081  }
1082  libxml_clear_errors();
1083  }
1084  libxml_use_internal_errors(false);
1085  return $return;
1086  }
1087 
1088  //to be called from IlObjUser
1089  public static function _removeTrackingDataForUser($user_id) {
1090  global $ilDB;
1091 
1092  //get all cmi_nodes to delete
1093  $res = $ilDB->queryF('
1094  SELECT cmi_node.cmi_node_id
1095  FROM cmi_node, cp_node
1096  WHERE cmi_node.cp_node_id = cp_node.cp_node_id AND cmi_node.user_id = %s',
1097  array('integer'),
1098  array($user_id)
1099  );
1100 
1101  $cmi_nodes = array();
1102  while($data = $ilDB->fetchAssoc($res))
1103  {
1104  $cmi_node_values[] = $data['cmi_node_id'];
1105  }
1106 
1107  //get all cmi_interaction_nodes to delete
1108  $res = $ilDB->queryF('
1109  SELECT cmi_interaction.cmi_interaction_id
1110  FROM cmi_interaction, cmi_node, cp_node
1111  WHERE (cmi_node.user_id = %s
1112  AND cmi_node.cp_node_id = cp_node.cp_node_id
1113  AND cmi_node.cmi_node_id = cmi_interaction.cmi_node_id)',
1114  array('integer'),
1115  array($user_id)
1116  );
1117 
1118  $cmi_inodes = array();
1119 
1120  while($data = $ilDB->fetchAssoc($res))
1121  {
1122  $cmi_inode_values[] = $data['cmi_interaction_id'];
1123  }
1124 
1125  //delete data in dependent tables
1126 
1127  //response
1128  $query = 'DELETE FROM cmi_correct_response WHERE '
1129  . $ilDB->in('cmi_correct_response.cmi_interaction_id', $cmi_inode_values, false, 'integer');
1130  $ilDB->manipulate($query);
1131 
1132  //objective interaction
1133  $query = 'DELETE FROM cmi_objective WHERE '
1134  . $ilDB->in('cmi_objective.cmi_interaction_id', $cmi_inode_values, false, 'integer');
1135  $ilDB->manipulate($query);
1136 
1137  //objective
1138  $query = 'DELETE FROM cmi_objective WHERE '
1139  . $ilDB->in('cmi_objective.cmi_node_id', $cmi_node_values, false, 'integer');
1140  $ilDB->manipulate($query);
1141 
1142  //interaction
1143  $query = 'DELETE FROM cmi_interaction WHERE '
1144  . $ilDB->in('cmi_interaction.cmi_node_id', $cmi_node_values, false, 'integer');
1145  $ilDB->manipulate($query);
1146 
1147  //comment
1148  $query = 'DELETE FROM cmi_comment WHERE '
1149  . $ilDB->in('cmi_comment.cmi_node_id', $cmi_node_values, false, 'integer');
1150  $ilDB->manipulate($query);
1151 
1152  //node
1153  $query = 'DELETE FROM cmi_node WHERE '
1154  . $ilDB->in('cmi_node.cmi_node_id', $cmi_node_values, false, 'integer');
1155  $ilDB->manipulate($query);
1156 
1157  //gobjective
1158  $ilDB->manipulateF(
1159  'DELETE FROM cmi_gobjective WHERE user_id = %s',
1160  array('integer'),
1161  array($user_id)
1162  );
1163  }
1164 }
1165 ?>