ILIAS  release_4-4 Revision
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilObjSCORMLearningModule.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 
5 require_once "./Services/Object/classes/class.ilObject.php";
6 require_once "./Modules/ScormAicc/classes/class.ilObjSCORMValidator.php";
7 require_once "./Modules/ScormAicc/classes/class.ilObjSAHSLearningModule.php";
8 
18 {
20 
27  function ilObjSCORMLearningModule($a_id = 0, $a_call_by_reference = true)
28  {
29  $this->type = "sahs";
30  parent::ilObject($a_id,$a_call_by_reference);
31  }
32 
33 
40  function validate($directory)
41  {
42  $this->validator = new ilObjSCORMValidator($directory);
43  $returnValue = $this->validator->validate();
44  return $returnValue;
45  }
46 
48  {
49  if(is_object($this->validator))
50  {
51  return $this->validator->getSummary();
52  }
53  return "";
54  }
55 
56  function getTrackingItems()
57  {
59  }
60 
61 
66  function _getTrackingItems($a_obj_id)
67  {
68  include_once("./Modules/ScormAicc/classes/SCORM/class.ilSCORMTree.php");
69  $tree = new ilSCORMTree($a_obj_id);
70  $root_id = $tree->readRootId();
71 
72  $items = array();
73  $childs = $tree->getSubTree($tree->getNodeData($root_id));
74 
75  foreach($childs as $child)
76  {
77  if($child["c_type"] == "sit")
78  {
79  include_once("./Modules/ScormAicc/classes/SCORM/class.ilSCORMItem.php");
80  $sc_item =& new ilSCORMItem($child["obj_id"]);
81  if ($sc_item->getIdentifierRef() != "")
82  {
83  $items[count($items)] =& $sc_item;
84  }
85  }
86  }
87 
88  return $items;
89  }
90 
95  function readObject()
96  {
97  global $ilErr;
98 
99  $needs_convert = false;
100 
101  // convert imsmanifest.xml file in iso to utf8 if needed
102 
103  $manifest_file = $this->getDataDirectory()."/imsmanifest.xml";
104 
105  // check if manifestfile exists and space left on device...
106  $check_for_manifest_file = is_file($manifest_file);
107 
108  // if no manifestfile
109  if (!$check_for_manifest_file)
110  {
111  $this->ilias->raiseError($this->lng->txt("Manifestfile $manifest_file not found!"), $this->ilias->error_obj->MESSAGE);
112  return;
113  }
114 
115  if ($check_for_manifest_file)
116  {
117  $manifest_file_array = file($manifest_file);
118  foreach($manifest_file_array as $mfa)
119  {
120  // if (seems_not_utf8($mfa))
121  if (@iconv('UTF-8', 'UTF-8', $mfa) != $mfa)
122  {
123  $needs_convert = true;
124  break;
125  }
126  }
127 
128  // to copy the file we need some extraspace, counted in bytes *2 ... we need 2 copies....
129  $estimated_manifest_filesize = filesize($manifest_file) * 2;
130 
131  // i deactivated this, because it seems to fail on some windows systems (see bug #1795)
132  //$check_disc_free = disk_free_space($this->getDataDirectory()) - $estimated_manifest_filesize;
133  $check_disc_free = 2;
134  }
135 
136  // if $manifest_file needs to be converted to UTF8
137  if ($needs_convert)
138  {
139  // if file exists and enough space left on device
140  if ($check_for_manifest_file && ($check_disc_free > 1))
141  {
142 
143  // create backup from original
144  if (!copy($manifest_file, $manifest_file.".old"))
145  {
146  echo "Failed to copy $manifest_file...<br>\n";
147  }
148 
149  // read backupfile, convert each line to utf8, write line to new file
150  // php < 4.3 style
151  $f_write_handler = fopen($manifest_file.".new", "w");
152  $f_read_handler = fopen($manifest_file.".old", "r");
153  while (!feof($f_read_handler))
154  {
155  $zeile = fgets($f_read_handler);
156  //echo mb_detect_encoding($zeile);
157  fputs($f_write_handler, utf8_encode($zeile));
158  }
159  fclose($f_read_handler);
160  fclose($f_write_handler);
161 
162  // copy new utf8-file to imsmanifest.xml
163  if (!copy($manifest_file.".new", $manifest_file))
164  {
165  echo "Failed to copy $manifest_file...<br>\n";
166  }
167 
168  if (!@is_file($manifest_file))
169  {
170  $this->ilias->raiseError($this->lng->txt("cont_no_manifest"),
171  $this->ilias->error_obj->WARNING);
172  }
173  }
174  else
175  {
176  // gives out the specific error
177 
178  if (!($check_disc_free > 1))
179  $this->ilias->raiseError($this->lng->txt("Not enough space left on device!"),$this->ilias->error_obj->MESSAGE);
180  return;
181  }
182 
183  }
184  else
185  {
186  // check whether file starts with BOM (that confuses some sax parsers, see bug #1795)
187  $hmani = fopen($manifest_file, "r");
188  $start = fread($hmani, 3);
189  if (strtolower(bin2hex($start)) == "efbbbf")
190  {
191  $f_write_handler = fopen($manifest_file.".new", "w");
192  while (!feof($hmani))
193  {
194  $n = fread($hmani, 900);
195  fputs($f_write_handler, $n);
196  }
197  fclose($f_write_handler);
198  fclose($hmani);
199 
200  // copy new utf8-file to imsmanifest.xml
201  if (!copy($manifest_file.".new", $manifest_file))
202  {
203  echo "Failed to copy $manifest_file...<br>\n";
204  }
205  }
206  else
207  {
208  fclose($hmani);
209  }
210  }
211 
212  //validate the XML-Files in the SCORM-Package
213  if ($_POST["validate"] == "y")
214  {
215  if (!$this->validate($this->getDataDirectory()))
216  {
217  $ilErr->raiseError("<b>Validation Error(s):</b><br>".$this->getValidationSummary(),$ilErr->MESSAGE);
218  }
219  }
220 
221  // start SCORM package parser
222  include_once ("./Modules/ScormAicc/classes/SCORM/class.ilSCORMPackageParser.php");
223  // todo determine imsmanifest.xml path here...
224  $slmParser = new ilSCORMPackageParser($this, $manifest_file);
225  $slmParser->startParsing();
226  return $slmParser->getPackageTitle();
227  }
228 
229 
233  function getTrackedItems()
234  {
235  global $ilDB, $ilUser;
236 
237  $sco_set = $ilDB->queryF('
238  SELECT DISTINCT sco_id FROM scorm_tracking WHERE obj_id = %s',
239  array('integer'),array($this->getId()));
240 
241  $items = array();
242  while($sco_rec = $ilDB->fetchAssoc($sco_set))
243  {
244  include_once("./Modules/ScormAicc/classes/SCORM/class.ilSCORMItem.php");
245  $sc_item =& new ilSCORMItem($sco_rec["sco_id"]);
246  if ($sc_item->getIdentifierRef() != "")
247  {
248  $items[count($items)] =& $sc_item;
249  }
250  }
251 
252  return $items;
253  }
254 
262  public static function _lookupLastAccess($a_obj_id, $a_usr_id)
263  {
264  global $ilDB;
265 
266  $result = $ilDB->queryF('
267  SELECT last_access FROM sahs_user
268  WHERE obj_id = %s
269  AND user_id = %s',
270  array('integer','integer'), array($a_obj_id,$a_usr_id));
271 
272  if ($ilDB->numRows($result))
273  {
274  $row = $ilDB->fetchAssoc($result);
275  return $row["last_access"];
276  }
277  return "";
278  }
279 
280  function getTrackedUsers($a_search)
281  {
282  global $ilDB, $ilUser;
283 //TODO: UK last_access is not correct if no Commit or last_visited_sco
284 // $query = 'SELECT user_id,MAX(c_timestamp) last_access, lastname, firstname FROM scorm_tracking st ' .
285  $query = 'SELECT user_id, last_access, lastname, firstname FROM sahs_user st ' .
286  'JOIN usr_data ud ON st.user_id = ud.usr_id ' .
287  'WHERE obj_id = ' . $ilDB->quote($this->getId(), 'integer');
288  if($a_search) {
289 // $query .= ' AND (' . $ilDB->like('lastname', 'text', '%' . $a_search . '%') . ' OR ' . $ilDB->like('firstname', 'text', '%' . $a_search . '%') .')';
290  $query .= ' AND ' . $ilDB->like('lastname', 'text', '%' . $a_search . '%');
291  }
292  $query .= ' GROUP BY user_id, lastname, firstname';
293  $sco_set = $ilDB->query($query);
294 
295  $items = array();
296  while($sco_rec = $ilDB->fetchAssoc($sco_set))
297  {
298  $items[] = $sco_rec;
299  }
300  return $items;
301  }
302 
303 
309  public function getAttemptsForUsers()
310  {
311  global $ilDB;
312  $query = 'SELECT user_id, package_attempts FROM sahs_user WHERE obj_id = ' . $ilDB->quote($this->getId(), 'integer') . ' ';
313  $res = $ilDB->query($query);
314 
315  $attempts = array();
316  while($row = $res->fetchRow(DB_FETCHMODE_ASSOC))
317  {
318  $attempts[$row['user_id']] = (int) $row['package_attempts'];
319  }
320  return $attempts;
321  }
322 
323 
327  function getAttemptsForUser($a_user_id){
328  global $ilDB;
329  $val_set = $ilDB->queryF('SELECT package_attempts FROM sahs_user WHERE obj_id = %s AND user_id = %s',
330  array('integer','integer'),
331  array($this->getId(),$a_user_id,0));
332 
333  $val_rec = $ilDB->fetchAssoc($val_set);
334 
335  if ($val_rec["package_attempts"] == null) {
336  $val_rec["package_attempts"]="";
337  }
338  return $val_rec["package_attempts"];
339  }
340 
341 
346  public function getModuleVersionForUsers()
347  {
348  global $ilDB;
349  $query = 'SELECT user_id, module_version FROM sahs_user WHERE obj_id = ' . $ilDB->quote($this->getId(), 'integer') . ' ';
350  $res = $ilDB->query($query);
351 
352  $versions = array();
353  while($row = $res->fetchRow(DB_FETCHMODE_ASSOC))
354  {
355  $versions[$row['user_id']] = (int) $row['module_version'];
356  }
357  return $versions;
358  }
359 
360 
364  function getModuleVersionForUser($a_user_id){
365  global $ilDB;
366  $val_set = $ilDB->queryF('SELECT module_version FROM sahs_user WHERE obj_id = %s AND user_id = %s',
367  array('integer','integer'),
368  array($this->getId(),$a_user_id,0));
369 
370  $val_rec = $ilDB->fetchAssoc($val_set);
371 
372  if ($val_rec["module_version"] == null) {
373  $val_rec["module_version"]="";
374  }
375  return $val_rec["module_version"];
376  }
377 
385  function getTrackingDataPerUser($a_sco_id, $a_user_id)
386  {
387  global $ilDB;
388 
389  $data_set = $ilDB->queryF('
390  SELECT * FROM scorm_tracking
391  WHERE user_id = %s
392  AND sco_id = %s
393  AND obj_id = %s
394  ORDER BY lvalue',
395  array('integer','integer','integer'),
396  array($a_user_id,$a_sco_id,$this->getId()));
397 
398  $data = array();
399  while($data_rec = $ilDB->fetchAssoc($data_set)) {
400  $data[] = $data_rec;
401  }
402 
403  return $data;
404  }
405 
406  function getTrackingDataAgg($a_user_id)
407  {
408  global $ilDB;
409 
410  // get all users with any tracking data
411  $sco_set = $ilDB->queryF('
412  SELECT DISTINCT sco_id FROM scorm_tracking
413  WHERE obj_id = %s
414  AND user_id = %s
415  AND sco_id <> %s',
416  array('integer','integer','integer'),
417  array($this->getId(),$a_user_id,0));
418 
419  $data = array();
420  while($sco_rec = $ilDB->fetchAssoc($sco_set))
421  {
422  $data_set = $ilDB->queryF('
423  SELECT * FROM scorm_tracking
424  WHERE obj_id = %s
425  AND sco_id = %s
426  AND user_id = %s
427  AND lvalue <> %s
428  AND (lvalue = %s
429  OR lvalue = %s
430  OR lvalue = %s)',
431  array('integer','integer','integer','text','text','text','text'),
432  array($this->getId(),
433  $sco_rec["sco_id"],
434  $a_user_id,
435  "package_attempts",
436  "cmi.core.lesson_status",
437  "cmi.core.total_time",
438  "cmi.core.score.raw")
439  );
440 
441  $score = $time = $status = "";
442 
443  while($data_rec = $ilDB->fetchAssoc($data_set))
444  {
445  switch($data_rec["lvalue"])
446  {
447  case "cmi.core.lesson_status":
448  $status = $data_rec["rvalue"];
449  break;
450 
451  case "cmi.core.total_time":
452  $time = $data_rec["rvalue"];
453  break;
454 
455  case "cmi.core.score.raw":
456  $score = $data_rec["rvalue"];
457  break;
458  }
459  }
460  //create sco_object
461  include_once './Modules/ScormAicc/classes/SCORM/class.ilSCORMItem.php';
462  $sc_item =& new ilSCORMItem($sco_rec["sco_id"]);
463  $data[] = array("sco_id"=>$sco_rec["sco_id"], "title" => $sc_item->getTitle(),
464  "score" => $score, "time" => $time, "status" => $status);
465 
466  }
467  return (array) $data;
468  }
469 
470  function getTrackingDataAggSco($a_sco_id)
471  {
472  global $ilDB;
473 
474  // get all users with any tracking data
475  $user_set = $ilDB->queryF('
476  SELECT DISTINCT user_id FROM scorm_tracking
477  WHERE obj_id = %s
478  AND sco_id = %s',
479  array('integer','integer'),
480  array($this->getId(),$a_sco_id));
481 
482  $data = array();
483  while($user_rec = $ilDB->fetchAssoc($user_set))
484  {
485 
486  $data_set = $ilDB->queryF('
487  SELECT * FROM scorm_tracking
488  WHERE obj_id = %s
489  AND sco_id = %s
490  AND user_id = %s
491  AND (lvalue = %s
492  OR lvalue = %s
493  OR lvalue = %s)',
494  array('integer','integer','integer','text','text','text'),
495  array($this->getId(),
496  $a_sco_id,
497  $user_rec["user_id"],
498  "cmi.core.lesson_status",
499  "cmi.core.total_time",
500  "cmi.core.score.raw")
501  );
502 
503  $score = $time = $status = "";
504 
505  while($data_rec = $ilDB->fetchAssoc($data_set))
506  {
507  switch($data_rec["lvalue"])
508  {
509  case "cmi.core.lesson_status":
510  $status = $data_rec["rvalue"];
511  break;
512 
513  case "cmi.core.total_time":
514  $time = $data_rec["rvalue"];
515  break;
516 
517  case "cmi.core.score.raw":
518  $score = $data_rec["rvalue"];
519  break;
520  }
521  }
522 
523  $data[] = array("user_id" => $user_rec["user_id"],
524  "score" => $score, "time" => $time, "status" => $status);
525  }
526 
527  return $data;
528  }
529 
530 
538  public function exportSelectedRaw($a_exportall, $a_user = array())
539  {
540  global $ilDB, $ilUser, $ilSetting;
541 
542  $inst_id = $ilSetting->get('inst_id',0);
543 
544  include_once './Services/Utilities/classes/class.ilCSVWriter.php';
545  $csv = new ilCSVWriter();
546  $csv->setSeparator(';');
547  $csv->addColumn('Scoid');
548  $csv->addColumn('Key');
549  $csv->addColumn('Value');
550  $csv->addColumn('Email');
551  $csv->addColumn('Timestamp');
552  $csv->addColumn('Userid');
553 
554  // Collect users
555  $user_array = array();
556  if($a_exportall)
557  {
558  $res = $ilDB->queryF(
559  'SELECT user_id FROM scorm_tracking WHERE obj_id = %s GROUP BY user_id',
560  array('integer'),
561  array($this->getId())
562  );
563  while($row = $ilDB->fetchAssoc($res))
564  {
565  $user_array[] = $row['user_id'];
566  }
567  }
568  else
569  {
570  $user_array = $a_user;
571  }
572 
573  // Read user data
574  $query = "SELECT usr_id,email FROM usr_data ".
575  "WHERE ".$ilDB->in('usr_id', $user_array, FALSE, 'integer');
576  $res = $ilDB->query($query);
577  $emails = array();
578  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
579  {
580  $emails[$row->usr_id] = $row->email;
581  }
582 
583  foreach($user_array as $user_id)
584  {
585  // Sco related information
586  $query = 'SELECT rvalue, lvalue, identifierref, c_timestamp FROM scorm_tracking st '.
587  'JOIN sc_item si ON st.sco_id = si.obj_id '.
588  'WHERE user_id = '.$ilDB->quote($user_id,'integer'). ' '.
589  'AND st.obj_id = '.$ilDB->quote($this->getId(),'integer');
590  $res = $ilDB->query($query);
591  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
592  {
593  $csv->addRow();
594  $csv->addColumn($row->identifierref);
595  $csv->addColumn($row->lvalue);
596  $csv->addColumn($row->rvalue);
597  $csv->addColumn(isset($emails[$user_id]) ? (string) $emails[$user_id] : '');
598  $csv->addColumn($row->c_timestamp);
599  $csv->addColumn('il_usr_'.$inst_id.'_'.$user_id);
600  }
601  // Sco unrelated information
602  $query = 'SELECT package_attempts,module_version,last_visited,last_access FROM sahs_user '.
603  'WHERE user_id = '.$ilDB->quote($user_id,'integer').' '.
604  'AND obj_id = '.$ilDB->quote($this->getId(),'integer');
605  $res = $ilDB->query($query);
606  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
607  {
608  if ($row->package_attempts != null) {
609  $csv->addRow();
610  $csv->addColumn(0);
611  $csv->addColumn("package_attempts");
612  $csv->addColumn($row->package_attempts);
613  $csv->addColumn(isset($emails[$user_id]) ? (string) $emails[$user_id] : '');
614  $csv->addColumn($row->last_access);
615  $csv->addColumn('il_usr_'.$inst_id.'_'.$user_id);
616  }
617  if ($row->last_visited != null) {
618  $csv->addRow();
619  $csv->addColumn(0);
620  $csv->addColumn("last_visited");
621  $csv->addColumn($row->last_visited);
622  $csv->addColumn(isset($emails[$user_id]) ? (string) $emails[$user_id] : '');
623  $csv->addColumn($row->last_access);
624  $csv->addColumn('il_usr_'.$inst_id.'_'.$user_id);
625  }
626  if ($row->module_version != null) {
627  $csv->addRow();
628  $csv->addColumn(0);
629  $csv->addColumn("module_version");
630  $csv->addColumn($row->module_version);
631  $csv->addColumn(isset($emails[$user_id]) ? (string) $emails[$user_id] : '');
632  $csv->addColumn($row->last_access);
633  $csv->addColumn('il_usr_'.$inst_id.'_'.$user_id);
634  }
635  }
636  //before 4.4
637  // $query = 'SELECT rvalue, lvalue, c_timestamp FROM scorm_tracking '.
638  // 'WHERE sco_id = 0 AND user_id = '.$ilDB->quote($user_id,'integer').' '.
639  // 'AND obj_id = '.$ilDB->quote($this->getId(),'integer');
640  // $res = $ilDB->query($query);
641  // while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
642  // {
643  // $csv->addRow();
644  // $csv->addColumn(0);
645  // $csv->addColumn($row->lvalue);
646  // $csv->addColumn($row->rvalue);
647  // $csv->addColumn(isset($emails[$user_id]) ? (string) $emails[$user_id] : '');
648  // $csv->addColumn($row->c_timestamp);
649  // $csv->addColumn('il_usr_'.$inst_id.'_'.$user_id);
650  // }
651  }
652 
654  $csv->getCSVString(),
655  'scorm_tracking_raw_' . $this->getRefId() . '_' . time() . '.csv'
656  );
657  return;
658  }
659 
660 
661 
669  public function exportSelected($a_all, $a_users = array())
670  {
671  global $ilDB, $ilUser, $ilSetting;
672 
673  $inst_id = $ilSetting->get('inst_id',0);
674 
675  // Get all scos
676  $scos = array();
677 
678  //get all SCO's of this object
679  $query = 'SELECT scorm_object.obj_id, scorm_object.title, '
680  . 'scorm_object.c_type, scorm_object.slm_id, scorm_object.obj_id scoid '
681  . 'FROM scorm_object, sc_item, sc_resource '
682  . 'WHERE (scorm_object.slm_id = %s '
683  . 'AND scorm_object.obj_id = sc_item.obj_id '
684  . 'AND sc_item.identifierref = sc_resource.import_id '
685  . 'AND sc_resource.scormtype = %s) '
686  . 'GROUP BY scorm_object.obj_id, scorm_object.title, scorm_object.c_type, '
687  . 'scorm_object.slm_id, scorm_object.obj_id ';
688  $res = $ilDB->queryF(
689  $query,
690  array('integer', 'text'),
691  array($this->getId(), 'sco')
692  );
693  while($row = $ilDB->fetchAssoc($res))
694  {
695  $scos[] = $row['scoid'];
696  }
697 
698 
699  $users = array();
700  if($a_all)
701  {
702  $query = 'SELECT user_id FROM scorm_tracking ' .
703  'WHERE obj_id = ' . $ilDB->quote($this->getId(), 'integer') . ' ' .
704  'GROUP BY user_id';
705  $res = $ilDB->query($query);
706  while($row = $ilDB->fetchAssoc($res))
707  {
708  $users[] = $row['user_id'];
709  }
710  }
711  else
712  {
713  $users = $a_users;
714  }
715 
716  // get all completed
717  include_once './Modules/ScormAicc/classes/SCORM/class.ilObjSCORMTracking.php';
718  $completed = ilObjSCORMTracking::_getCompleted($scos, $this->getId());
720 
721  include_once './Services/Utilities/classes/class.ilCSVWriter.php';
722  $csv = new ilCSVWriter();
723  $csv->setSeparator(';');
724  foreach(array('Department', 'Login', 'Lastname', 'Firstname', 'Email', 'Date', 'Status') as $col)
725  {
726  $csv->addColumn($col);
727  }
728 
729  // Read user data
730  $query = 'SELECT usr_id,login,firstname,lastname,department,email ' .
731  'FROM usr_data ' .
732  'WHERE ' . $ilDB->in('usr_id', $users, false, 'integer');
733  $res = $ilDB->query($query);
734 
735  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
736  {
737  $csv->addRow();
738  $csv->addColumn((string) $row->department);
739  $csv->addColumn((string) $row->login);
740  $csv->addColumn((string) $row->lastname);
741  $csv->addColumn((string) $row->firstname);
742  $csv->addColumn((string) $row->email);
743  if(isset($last[$row->usr_id]))
744  {
745  $dt = new ilDateTime($last[$row->usr_id], IL_CAL_DATETIME);
746  $csv->addColumn((string) $dt->get(IL_CAL_FKT_DATE, 'd.m.Y'));
747  }
748  else
749  {
750  $csv->addColumn('');
751  }
752  $csv->addColumn(in_array($row->usr_id, $completed) ? 1 : 0);
753  }
754 
755 
757  $csv->getCSVString(),
758  'scorm_tracking_' . $this->getRefId() . '_' . time() . '.csv'
759  );
760  }
761 
762 
763  function importTrackingData($a_file)
764  {
765  global $ilDB, $ilUser;
766 
767  $error = 0;
768  //echo file_get_contents($a_file);
769  $method = null;
770 
771  //lets import
772  $fhandle = fopen($a_file, "r");
773 
774  //the top line is the field names
775  $fields = fgetcsv($fhandle, pow(2, 16), ';');
776  //lets check the import method
777  fclose($fhandle);
778 
779  switch($fields[0])
780  {
781  case "Scoid":
782  $error = $this->importRaw($a_file);
783  break;
784  case "Department":
785  $error = $this->importSuccess($a_file);
786  break;
787  default:
788  return -1;
789  break;
790  }
791  return $error;
792  }
793 
794  function importSuccess($a_file) {
795 
796  global $ilDB, $ilUser;
797 
798  $scos = array();
799  //get all SCO's of this object
800 
801  $val_set = $ilDB->queryF('
802  SELECT scorm_object.obj_id,
803  scorm_object.title,
804  scorm_object.c_type,
805  scorm_object.slm_id,
806  scorm_object.obj_id scoid
807  FROM scorm_object,sc_item,sc_resource
808  WHERE(scorm_object.slm_id = %s
809  AND scorm_object.obj_id=sc_item.obj_id
810  AND sc_item.identifierref = sc_resource.import_id
811  AND sc_resource.scormtype = %s)
812  GROUP BY scorm_object.obj_id,
813  scorm_object.title,
814  scorm_object.c_type,
815  scorm_object.slm_id,
816  scorm_object.obj_id ',
817  array('integer','text'),
818  array($this->getId(),'sco')
819  );
820 
821  if (count($val_set)<1)
822  {
823  return -1;
824  }
825  while($rows_sco = $ilDB->fetchAssoc($val_set))
826  {
827  array_push($scos,$rows_sco['scoid']);
828  }
829 
830  $fhandle = fopen($a_file, "r");
831 
832  $obj_id = $this->getID();
833 
834  $fields = fgetcsv($fhandle, pow(2, 16), ';');
835  $users = array();
836  while(($csv_rows = fgetcsv($fhandle, pow(2, 16), ";")) !== FALSE)
837  {
838  $data = array_combine($fields, $csv_rows);
839  //check the format
840  $statuscheck = 0;
841  if (count($csv_rows) == 6) {$statuscheck = 1;}
842 
843  if ($this->get_user_id($data["Login"])>0) {
844 
845  $user_id = $this->get_user_id($data["Login"]);
846  $users[] = $user_id;
847  $import = $data["Status"];
848  if ($import == "") {$import = 1;}
849  //iterate over all SCO's
850  if ($import == 1) {
851  foreach ($scos as $sco)
852  {
853  $sco_id = $sco;
854 
855  $date_ex = explode('.', $data['Date']);
856  $date = implode('-', array($date_ex[2], $date_ex[1], $date_ex[0]));
857 
858  $statement = $ilDB->queryF('
859  SELECT * FROM scorm_tracking
860  WHERE user_id = %s
861  AND sco_id = %s
862  AND lvalue = %s
863  AND obj_id = %s',
864  array('integer','integer','text','integer'),
865  array($user_id, $sco_id, 'cmi.core.lesson_status',$obj_id)
866  );
867  if($ilDB->numRows($statement) > 0)
868  {
869  $ilDB->update('scorm_tracking',
870  array(
871  'rvalue' => array('clob', 'completed'),
872  'c_timestamp' => array('timestamp', $date)
873  ),
874  array(
875  'user_id' => array('integer', $user_id),
876  'sco_id' => array('integer', $sco_id),
877  'lvalue' => array('text', 'cmi.core.lesson_status'),
878  'obj_id' => array('integer', $obj_id)
879  )
880  );
881  }
882  else
883  {
884  $ilDB->insert('scorm_tracking', array(
885  'obj_id' => array('integer', $obj_id),
886  'user_id' => array('integer', $user_id),
887  'sco_id' => array('integer', $sco_id),
888  'lvalue' => array('text', 'cmi.core.lesson_status'),
889  'rvalue' => array('clob', 'completed'),
890  'c_timestamp' => array('timestamp', $date)
891  ));
892  }
893 
894  $statement = $ilDB->queryF('
895  SELECT * FROM scorm_tracking
896  WHERE user_id = %s
897  AND sco_id = %s
898  AND lvalue = %s
899  AND obj_id = %s',
900  array('integer','integer','text','integer'),
901  array($user_id, $sco_id, 'cmi.core.entry',$obj_id)
902  );
903  if($ilDB->numRows($statement) > 0)
904  {
905  $ilDB->update('scorm_tracking',
906  array(
907  'rvalue' => array('clob', 'completed'),
908  'c_timestamp' => array('timestamp', $date)
909  ),
910  array(
911  'user_id' => array('integer', $user_id),
912  'sco_id' => array('integer', $sco_id),
913  'lvalue' => array('text', 'cmi.core.entry'),
914  'obj_id' => array('integer', $obj_id)
915  )
916  );
917  }
918  else
919  {
920  $ilDB->insert('scorm_tracking', array(
921  'obj_id' => array('integer', $obj_id),
922  'user_id' => array('integer', $user_id),
923  'sco_id' => array('integer', $sco_id),
924  'lvalue' => array('text', 'cmi.core.entry'),
925  'rvalue' => array('clob', 'completed'),
926  'c_timestamp' => array('timestamp', $date)
927  ));
928  }
929  }
930  }
931  } else {
932  //echo "Warning! User $csv_rows[0] does not exist in ILIAS. Data for this user was skipped.\n";
933  }
934  }
935 
936  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
938 // <4.2.6: foreach ($users as $user_id) {ilLPStatusWrapper::_updateStatus($obj_id, $user_id);}
939  return 0;
940  }
941 
947  private function parseUserId($il_id)
948  {
949  global $ilSetting;
950 
951  $parts = explode('_', $il_id);
952 
953  if(!count((array) $parts))
954  {
955  return 0;
956  }
957  if(!isset($parts[2]) or !isset($parts[3]))
958  {
959  return 0;
960  }
961  if($parts[2] != $ilSetting->get('inst_id',$parts[2]))
962  {
963  return 0;
964  }
965  return $parts[3];
966  }
967 
975  private function importRaw($a_file)
976  {
977  global $ilDB, $ilUser;
978  //no need to use sahs_user because never data was imported
979 
980  $fhandle = fopen($a_file, "r");
981 
982  $fields = fgetcsv($fhandle, pow(2, 16), ';');
983  $users = array();
984  while(($csv_rows = fgetcsv($fhandle, pow(2, 16), ";")) !== FALSE)
985  {
986  $data = array_combine($fields, $csv_rows);
987  $user_id = $this->parseUserId($data['Userid']);
988 
989  if(!$user_id)
990  {
991  continue;
992  }
993 
994  $il_sco_id = $this->lookupSCOId($data['Scoid']);
995 
996  //do the actual import
997  if($il_sco_id >= 0)
998  {
999  $statement = $ilDB->queryF('
1000  SELECT * FROM scorm_tracking
1001  WHERE user_id = %s
1002  AND sco_id = %s
1003  AND lvalue = %s
1004  AND obj_id = %s',
1005  array('integer', 'integer', 'text', 'integer'),
1006  array($user_id, $il_sco_id, $data['Key'], $this->getID())
1007  );
1008  if($ilDB->numRows($statement) > 0)
1009  {
1010  $ilDB->update('scorm_tracking',
1011  array(
1012  'rvalue' => array('clob', $data['Value']),
1013  'c_timestamp' => array('timestamp', $data['Timestamp'])
1014  ),
1015  array(
1016  'user_id' => array('integer', $user_id),
1017  'sco_id' => array('integer', $il_sco_id),
1018  'lvalue' => array('text', $data['Key']),
1019  'obj_id' => array('integer', $this->getId())
1020  )
1021  );
1022  }
1023  else
1024  {
1025  $ilDB->insert('scorm_tracking', array(
1026  'obj_id' => array('integer', $this->getId()),
1027  'user_id' => array('integer', $user_id),
1028  'sco_id' => array('integer', $il_sco_id),
1029  'lvalue' => array('text', $data['Key']),
1030  'rvalue' => array('clob', $data['Value']),
1031  'c_timestamp' => array('timestamp', $data['Timestamp'])
1032  ));
1033  }
1034  }
1035  }
1036  fclose($fhandle);
1037 
1038  include_once './Services/Tracking/classes/class.ilLPStatusWrapper.php';
1040 
1041  return 0;
1042  }
1043 
1044  //helper function
1045  function get_user_id($a_login) {
1046  global $ilDB, $ilUser;
1047 
1048  $val_set = $ilDB->queryF('SELECT * FROM usr_data WHERE(login=%s)',
1049  array('text'),array($a_login));
1050  $val_rec = $ilDB->fetchAssoc($val_set);
1051 
1052  if (count($val_rec)>0) {
1053  return $val_rec['usr_id'];
1054  } else {
1055  return null;
1056  }
1057  }
1058 
1059 
1063  private function lookupSCOId($a_referrer){
1064  global $ilDB, $ilUser;
1065 
1066  //non specific SCO entries
1067  if ($a_referrer=="0") {
1068  return 0;
1069  }
1070 
1071  $val_set = $ilDB->queryF('
1072  SELECT obj_id FROM sc_item,scorm_tree
1073  WHERE (obj_id = child
1074  AND identifierref = %s
1075  AND slm_id = %s)',
1076  array('text','integer'), array($a_referrer,$this->getID()));
1077  $val_rec = $ilDB->fetchAssoc($val_set);
1078 
1079  return $val_rec["obj_id"];
1080  }
1081 
1085  function getUserIdEmail($a_mail)
1086  {
1087  global $ilDB, $ilUser;
1088 
1089  $val_set = $ilDB->queryF('SELECT usr_id FROM usr_data WHERE(email=%s)',
1090  array('text'),array($a_mail));
1091  $val_rec = $ilDB->fetchAssoc($val_set);
1092 
1093 
1094  return $val_rec["usr_id"];
1095  }
1096 
1097 
1101  function sendExportFile($a_header,$a_content)
1102  {
1103  $timestamp = time();
1104  $refid = $this->getRefId();
1105  $filename = "scorm_tracking_".$refid."_".$timestamp.".csv";
1106  //Header
1107  header("Expires: 0");
1108  header("Cache-control: private");
1109  header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
1110  header("Content-Description: File Transfer");
1111  header("Content-Type: application/octet-stream");
1112  header("Content-disposition: attachment; filename=$filename");
1113  echo $a_header.$a_content;
1114  exit;
1115  }
1116 
1122  public static function _getAllScoIds($a_id)
1123  {
1124  global $ilDB;
1125 
1126  $scos = array();
1127 
1128  $val_set = $ilDB->queryF('
1129  SELECT scorm_object.obj_id,
1130  scorm_object.title,
1131  scorm_object.c_type,
1132  scorm_object.slm_id,
1133  scorm_object.obj_id scoid
1134  FROM scorm_object,sc_item,sc_resource
1135  WHERE(scorm_object.slm_id = %s
1136  AND scorm_object.obj_id = sc_item.obj_id
1137  AND sc_item.identifierref = sc_resource.import_id
1138  AND sc_resource.scormtype = %s)
1139  GROUP BY scorm_object.obj_id,
1140  scorm_object.title,
1141  scorm_object.c_type,
1142  scorm_object.slm_id,
1143  scorm_object.obj_id ',
1144  array('integer', 'text'),
1145  array($a_id,'sco'));
1146 
1147  while ($val_rec = $ilDB->fetchAssoc($val_set))
1148  {
1149  array_push($scos,$val_rec['scoid']);
1150  }
1151  return $scos;
1152  }
1153 
1162  public static function _getStatusForUser($a_id, $a_user,$a_allScoIds,$a_numerical=false)
1163  {
1164  global $ilDB, $lng;
1165 
1166  $scos = $a_allScoIds;
1167  //check if all SCO's are completed
1168  $scos_c = implode(',',$scos);
1169 
1170  $val_set = $ilDB->queryF('
1171  SELECT * FROM scorm_tracking
1172  WHERE (user_id = %s
1173  AND obj_id = %s
1174  AND '.$ilDB->in('sco_id', $scos, false, 'integer').'
1175  AND ((lvalue = %s AND '.$ilDB->like('rvalue', 'clob', 'completed').')
1176  OR (lvalue = %s AND '.$ilDB->like('rvalue', 'clob', 'passed').')))',
1177  array('integer','integer','text','text'),
1178  array($a_user,$a_id,'cmi.core.lesson_status', 'cmi.core.lesson_status'));
1179  while ($val_rec = $ilDB->fetchAssoc($val_set))
1180  {
1181  $key = array_search($val_rec['sco_id'], $scos);
1182  unset ($scos[$key]);
1183  }
1184  //check for completion
1185  if (count($scos) == 0) {
1186  $completion = ($a_numerical===true) ? true: $lng->txt("cont_complete");
1187  }
1188  if (count($scos) > 0) {
1189  $completion = ($a_numerical===true) ? false: $lng->txt("cont_incomplete");
1190  }
1191  return $completion;
1192  }
1193 
1200  public static function _getCourseCompletionForUser($a_id, $a_user)
1201  {
1203  }
1204 
1205  function getAllScoIds(){
1206  global $ilDB;
1207 
1208  $scos = array();
1209  //get all SCO's of this object
1210  $val_set = $ilDB->queryF('
1211  SELECT scorm_object.obj_id,
1212  scorm_object.title,
1213  scorm_object.c_type,
1214  scorm_object.slm_id,
1215  scorm_object.obj_id scoid
1216  FROM scorm_object, sc_item,sc_resource
1217  WHERE(scorm_object.slm_id = %s
1218  AND scorm_object.obj_id = sc_item.obj_id
1219  AND sc_item.identifierref = sc_resource.import_id
1220  AND sc_resource.scormtype = %s )
1221  GROUP BY scorm_object.obj_id,
1222  scorm_object.title,
1223  scorm_object.c_type,
1224  scorm_object.slm_id,
1225  scorm_object.obj_id',
1226  array('integer','text'),
1227  array($this->getId(),'sco'));
1228 
1229  while ($val_rec = $ilDB->fetchAssoc($val_set))
1230  {
1231  array_push($scos,$val_rec['scoid']);
1232  }
1233  return $scos;
1234  }
1235 
1236  function getStatusForUser($a_user,$a_allScoIds,$a_numerical=false){
1237  global $ilDB;
1238  $scos = $a_allScoIds;
1239  //loook up status
1240  //check if all SCO's are completed
1241  $scos_c = implode(',',$scos);
1242 
1243  $val_set = $ilDB->queryF('
1244  SELECT sco_id FROM scorm_tracking
1245  WHERE (user_id = %s
1246  AND obj_id = %s
1247  AND '.$ilDB->in('sco_id', $scos, false, 'integer').'
1248  AND ((lvalue = %s AND '.$ilDB->like('rvalue', 'clob', 'completed').') OR (lvalue = %s AND '.$ilDB->like('rvalue', 'clob', 'passed').') ) )',
1249  array('integer','integer','text','text',),
1250  array($a_user,$this->getID(),'cmi.core.lesson_status','cmi.core.lesson_status'));
1251  while ($val_rec = $ilDB->fetchAssoc($val_set))
1252  {
1253  $key = array_search($val_rec['sco_id'], $scos);
1254  unset ($scos[$key]);
1255  }
1256  //check for completion
1257  if (count($scos) == 0) {
1258  $completion = ($a_numerical===true) ? true: $this->lng->txt("cont_complete");
1259  }
1260  if (count($scos) > 0) {
1261  $completion = ($a_numerical===true) ? false: $this->lng->txt("cont_incomplete");
1262  }
1263  return $completion;
1264  }
1265 
1266  function getCourseCompletionForUser($a_user) {
1267  return $this->getStatusForUser($a_user,$this->getAllScoIds,true);
1268  }
1269 
1270  //to be called from IlObjUser
1271  public static function _removeTrackingDataForUser($user_id) {
1272  global $ilDB;
1273  //gobjective
1274  $ilDB->manipulateF(
1275  'DELETE FROM scorm_tracking WHERE user_id = %s',
1276  array('integer'),
1277  array($user_id)
1278  );
1279  $ilDB->manipulateF(
1280  'DELETE FROM sahs_user WHERE user_id = %s',
1281  array('integer'),
1282  array($user_id)
1283  );
1284  }
1285 
1286  function _getScoresForUser($a_item_id, $a_user_id)
1287  {
1288  global $ilDB;
1289 
1290  $retAr = array("raw" => null, "max" => null, "scaled" => null);
1291  $val_set = $ilDB->queryF("
1292  SELECT lvalue, rvalue FROM scorm_tracking
1293  WHERE sco_id = %s
1294  AND user_id = %s
1295  AND (lvalue = 'cmi.core.score.raw' OR lvalue = 'cmi.core.score.max')",
1296  array('integer', 'integer'),
1297  array($a_item_id, $a_user_id)
1298  );
1299  while ($val_rec = $ilDB->fetchAssoc($val_set))
1300  {
1301  if ($val_rec['lvalue'] == "cmi.core.score.raw") $retAr["raw"] = $val_rec["rvalue"];
1302  if ($val_rec['lvalue'] == "cmi.core.score.max") $retAr["max"] = $val_rec["rvalue"];
1303  }
1304  if ($retAr["raw"] != null && $retAr["max"] != null) $retAr["scaled"] = ($retAr["raw"] / $retAr["max"]);
1305 
1306  return $retAr;
1307  }
1308 
1309 
1310  public function getLastVisited($user_id)
1311  {
1312  global $ilDB;
1313  $val_set = $ilDB->queryF('SELECT last_visited FROM sahs_user WHERE obj_id = %s AND user_id = %s',
1314  array('integer','integer'),
1315  array($this->getID(),$user_id)
1316  );
1317  while ($val_rec = $ilDB->fetchAssoc($val_set))
1318  {
1319  if ($val_rec["last_visited"] != null) return "".$val_rec["last_visited"];
1320  }
1321  return '0';
1322  }
1323 
1324 }
1325 ?>
static _getAllScoIds($a_id)
Get an array of id&#39;s for all Sco&#39;s in the module.
static deliverData($a_data, $a_filename, $mime="application/octet-stream", $charset="")
deliver data for download via browser.
importRaw($a_file)
Import raw data ilDB $ilDB ilObjUser $ilUser.
_getTrackingItems($a_obj_id)
get all tracking items of scorm object static
exit
Definition: login.php:54
$_POST['username']
Definition: cron.php:12
parseUserId($il_id)
Parse il_usr_123_6 id.
const IL_CAL_DATETIME
getAttemptsForUsers()
Get attempts for all users ilDB $ilDB.
Helper class to generate CSV files.
$result
static _getCourseCompletionForUser($a_id, $a_user)
Get the completion of a SCORM module for a given user.
static _getCompleted($scorm_item_id, $a_obj_id)
like necessary because of Oracle
getTrackedItems()
get all tracked items of current user
exportSelectedRaw($a_exportall, $a_user=array())
Export ilDB $ilDB ilObjUser $ilUser.
sendExportFile($a_header, $a_content)
send export file to browser
ilObjSCORMLearningModule($a_id=0, $a_call_by_reference=true)
Constructor public.
getUserIdEmail($a_mail)
assumes that only one account exists for a mailadress
getAttemptsForUser($a_user_id)
get number of atttempts for a certain user and package
static _lookupLastAccess($a_obj_id, $a_usr_id)
Return the last access timestamp for a given user.
const DB_FETCHMODE_OBJECT
Definition: class.ilDB.php:11
getTrackingDataPerUser($a_sco_id, $a_user_id)
Get tracking data per user ilDB $ilDB.
validate($directory)
Validate all XML-Files in a SCOM-Directory.
getDataDirectory($mode="filesystem")
get data directory of lm
getId()
get object id public
const IL_CAL_FKT_DATE
Date and time handling
SCORM Item.
redirection script todo: (a better solution should control the processing via a xml file) ...
const DB_FETCHMODE_ASSOC
Definition: class.ilDB.php:10
getModuleVersionForUser($a_user_id)
get module version that tracking data for a user was recorded on
$n
Definition: RandomTest.php:80
Validation of SCORM-XML Files.
SCORM Object Tree.
exportSelected($a_all, $a_users=array())
Export selected user tracking data ilDB $ilDB ilObjUser $ilUser.
getModuleVersionForUsers()
Get module version for users.
lookupSCOId($a_referrer)
resolves manifest SCOID to internal ILIAS SCO ID
$filename
Definition: buildRTE.php:89
getStatusForUser($a_user, $a_allScoIds, $a_numerical=false)
static lookupLastAccessTimes($a_obj_id)
Lookup last acccess time for all users of a scorm module ilDB $ilDB.
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
static _getStatusForUser($a_id, $a_user, $a_allScoIds, $a_numerical=false)
Get the status of a SCORM module for a given user.
while($lm_rec=$ilDB->fetchAssoc($lm_set)) $data
_refreshStatus($a_obj_id, $a_users=null)
Set dirty.
global $ilUser
Definition: imgupload.php:15
global $ilSetting
Definition: privfeed.php:40
readObject()
read manifest file public
getRefId()
get reference id public
Class ilObjSCORMLearningModule.
Class ilObjSCORMLearningModule.