ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
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 {
19  public $validator;
20 
27  public function __construct($a_id = 0, $a_call_by_reference = true)
28  {
29  $this->type = "sahs";
30  parent::__construct($a_id, $a_call_by_reference);
31  }
32 
33 
40  public function validate($directory)
41  {
42  $this->validator = new ilObjSCORMValidator($directory);
43  $returnValue = $this->validator->validate();
44  return $returnValue;
45  }
46 
47  public function getValidationSummary()
48  {
49  if (is_object($this->validator)) {
50  return $this->validator->getSummary();
51  }
52  return "";
53  }
54 
55  public function getTrackingItems()
56  {
58  }
59 
60 
65  public static function _getTrackingItems($a_obj_id)
66  {
67  include_once("./Modules/ScormAicc/classes/SCORM/class.ilSCORMTree.php");
68  $tree = new ilSCORMTree($a_obj_id);
69  $root_id = $tree->readRootId();
70 
71  $items = array();
72  $childs = $tree->getSubTree($tree->getNodeData($root_id));
73 
74  foreach ($childs as $child) {
75  if ($child["c_type"] == "sit") {
76  include_once("./Modules/ScormAicc/classes/SCORM/class.ilSCORMItem.php");
77  $sc_item = new ilSCORMItem($child["obj_id"]);
78  if ($sc_item->getIdentifierRef() != "") {
79  $items[count($items)] = $sc_item;
80  }
81  }
82  }
83 
84  return $items;
85  }
86 
91  public function readObject()
92  {
93  global $DIC;
94  $ilErr = $DIC['ilErr'];
95 
96  $needs_convert = false;
97 
98  // convert imsmanifest.xml file in iso to utf8 if needed
99 
100  $manifest_file = $this->getDataDirectory() . "/imsmanifest.xml";
101 
102  // check if manifestfile exists and space left on device...
103  $check_for_manifest_file = is_file($manifest_file);
104 
105  // if no manifestfile
106  if (!$check_for_manifest_file) {
107  $this->ilias->raiseError($this->lng->txt("Manifestfile $manifest_file not found!"), $this->ilias->error_obj->MESSAGE);
108  return;
109  }
110 
111  if ($check_for_manifest_file) {
112  $manifest_file_array = file($manifest_file);
113  foreach ($manifest_file_array as $mfa) {
114  // if (seems_not_utf8($mfa))
115  if (@iconv('UTF-8', 'UTF-8', $mfa) != $mfa) {
116  $needs_convert = true;
117  break;
118  }
119  }
120 
121  // to copy the file we need some extraspace, counted in bytes *2 ... we need 2 copies....
122  $estimated_manifest_filesize = filesize($manifest_file) * 2;
123 
124  // i deactivated this, because it seems to fail on some windows systems (see bug #1795)
125  //$check_disc_free = disk_free_space($this->getDataDirectory()) - $estimated_manifest_filesize;
126  $check_disc_free = 2;
127  }
128 
129  // if $manifest_file needs to be converted to UTF8
130  if ($needs_convert) {
131  // if file exists and enough space left on device
132  if ($check_for_manifest_file && ($check_disc_free > 1)) {
133 
134  // create backup from original
135  if (!copy($manifest_file, $manifest_file . ".old")) {
136  echo "Failed to copy $manifest_file...<br>\n";
137  }
138 
139  // read backupfile, convert each line to utf8, write line to new file
140  // php < 4.3 style
141  $f_write_handler = fopen($manifest_file . ".new", "w");
142  $f_read_handler = fopen($manifest_file . ".old", "r");
143  while (!feof($f_read_handler)) {
144  $zeile = fgets($f_read_handler);
145  //echo mb_detect_encoding($zeile);
146  fputs($f_write_handler, utf8_encode($zeile));
147  }
148  fclose($f_read_handler);
149  fclose($f_write_handler);
150 
151  // copy new utf8-file to imsmanifest.xml
152  if (!copy($manifest_file . ".new", $manifest_file)) {
153  echo "Failed to copy $manifest_file...<br>\n";
154  }
155 
156  if (!@is_file($manifest_file)) {
157  $this->ilias->raiseError(
158  $this->lng->txt("cont_no_manifest"),
159  $this->ilias->error_obj->WARNING
160  );
161  }
162  } else {
163  // gives out the specific error
164 
165  if (!($check_disc_free > 1)) {
166  $this->ilias->raiseError($this->lng->txt("Not enough space left on device!"), $this->ilias->error_obj->MESSAGE);
167  }
168  return;
169  }
170  } else {
171  // check whether file starts with BOM (that confuses some sax parsers, see bug #1795)
172  $hmani = fopen($manifest_file, "r");
173  $start = fread($hmani, 3);
174  if (strtolower(bin2hex($start)) == "efbbbf") {
175  $f_write_handler = fopen($manifest_file . ".new", "w");
176  while (!feof($hmani)) {
177  $n = fread($hmani, 900);
178  fputs($f_write_handler, $n);
179  }
180  fclose($f_write_handler);
181  fclose($hmani);
182 
183  // copy new utf8-file to imsmanifest.xml
184  if (!copy($manifest_file . ".new", $manifest_file)) {
185  echo "Failed to copy $manifest_file...<br>\n";
186  }
187  } else {
188  fclose($hmani);
189  }
190  }
191 
192  //validate the XML-Files in the SCORM-Package
193  if ($_POST["validate"] == "y") {
194  if (!$this->validate($this->getDataDirectory())) {
195  $ilErr->raiseError("<b>Validation Error(s):</b><br>" . $this->getValidationSummary(), $ilErr->MESSAGE);
196  }
197  }
198 
199  // start SCORM package parser
200  include_once("./Modules/ScormAicc/classes/SCORM/class.ilSCORMPackageParser.php");
201  // todo determine imsmanifest.xml path here...
202  $slmParser = new ilSCORMPackageParser($this, $manifest_file);
203  $slmParser->startParsing();
204  return $slmParser->getPackageTitle();
205  }
206 
211  {
212  global $DIC;
213  $ilSetting = $DIC['ilSetting'];
214  //condition 1
215  $lm_set = new ilSetting("lm");
216  if ($lm_set->get('scorm_lp_auto_activate') != 1) {
217  return;
218  }
219  //condition 2
220  include_once("./Services/Tracking/classes/class.ilObjUserTracking.php");
222  return;
223  }
224 
225  //set Learning Progress to Automatic by Collection of SCORM Items
226  include_once("./Services/Tracking/classes/class.ilLPObjSettings.php");
227  $lm_set = new ilLPObjSettings($this->getId());
229  $lm_set->insert();
230 
231  //select all SCOs as relevant for Learning Progress
232  include_once("Services/Tracking/classes/collection/class.ilLPCollectionOfSCOs.php");
233  $collection = new ilLPCollectionOfSCOs($this->getId(), ilLPObjSettings::LP_MODE_SCORM);
234  $scos = array();
235  foreach ($collection->getPossibleItems() as $sco_id => $item) {
236  $scos[] = $sco_id;
237  }
238  $collection->activateEntries($scos);
239  }
243  public function getTrackedItems()
244  {
245  global $DIC;
246  $ilDB = $DIC['ilDB'];
247  $ilUser = $DIC['ilUser'];
248 
249  $sco_set = $ilDB->queryF(
250  '
251  SELECT DISTINCT sco_id FROM scorm_tracking WHERE obj_id = %s',
252  array('integer'),
253  array($this->getId())
254  );
255 
256  $items = array();
257  while ($sco_rec = $ilDB->fetchAssoc($sco_set)) {
258  include_once("./Modules/ScormAicc/classes/SCORM/class.ilSCORMItem.php");
259  $sc_item = new ilSCORMItem($sco_rec["sco_id"]);
260  if ($sc_item->getIdentifierRef() != "") {
261  $items[count($items)] = $sc_item;
262  }
263  }
264 
265  return $items;
266  }
267 
275  public static function _lookupLastAccess($a_obj_id, $a_usr_id)
276  {
277  global $DIC;
278  $ilDB = $DIC['ilDB'];
279 
280  $result = $ilDB->queryF(
281  '
282  SELECT last_access FROM sahs_user
283  WHERE obj_id = %s
284  AND user_id = %s',
285  array('integer','integer'),
286  array($a_obj_id,$a_usr_id)
287  );
288 
289  if ($ilDB->numRows($result)) {
290  $row = $ilDB->fetchAssoc($result);
291  return $row["last_access"];
292  }
293  return "";
294  }
295 
296  public function getTrackedUsers($a_search)
297  {
298  global $DIC;
299  $ilDB = $DIC['ilDB'];
300  $ilUser = $DIC['ilUser'];
301  //TODO: UK last_access is not correct if no Commit or last_visited_sco
302  // $query = 'SELECT user_id,MAX(c_timestamp) last_access, lastname, firstname FROM scorm_tracking st ' .
303  $query = 'SELECT user_id, last_access, lastname, firstname FROM sahs_user st ' .
304  'JOIN usr_data ud ON st.user_id = ud.usr_id ' .
305  'WHERE obj_id = ' . $ilDB->quote($this->getId(), 'integer');
306  if ($a_search) {
307  // $query .= ' AND (' . $ilDB->like('lastname', 'text', '%' . $a_search . '%') . ' OR ' . $ilDB->like('firstname', 'text', '%' . $a_search . '%') .')';
308  $query .= ' AND ' . $ilDB->like('lastname', 'text', '%' . $a_search . '%');
309  }
310  $query .= ' GROUP BY user_id, lastname, firstname, last_access';
311  $sco_set = $ilDB->query($query);
312 
313  $items = array();
314  while ($sco_rec = $ilDB->fetchAssoc($sco_set)) {
315  $items[] = $sco_rec;
316  }
317  return $items;
318  }
319 
320 
326  public function getAttemptsForUsers()
327  {
328  global $DIC;
329  $ilDB = $DIC['ilDB'];
330  $query = 'SELECT user_id, package_attempts FROM sahs_user WHERE obj_id = ' . $ilDB->quote($this->getId(), 'integer') . ' ';
331  $res = $ilDB->query($query);
332 
333  $attempts = array();
334  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
335  $attempts[$row['user_id']] = (int) $row['package_attempts'];
336  }
337  return $attempts;
338  }
339 
340 
344  public function getAttemptsForUser($a_user_id)
345  {
346  global $DIC;
347  $ilDB = $DIC['ilDB'];
348  $val_set = $ilDB->queryF(
349  'SELECT package_attempts FROM sahs_user WHERE obj_id = %s AND user_id = %s',
350  array('integer','integer'),
351  array($this->getId(),$a_user_id)
352  );
353 
354  $val_rec = $ilDB->fetchAssoc($val_set);
355 
356  if ($val_rec["package_attempts"] == null) {
357  $val_rec["package_attempts"] = "";
358  }
359  return $val_rec["package_attempts"];
360  }
361 
362 
367  public function getModuleVersionForUsers()
368  {
369  global $DIC;
370  $ilDB = $DIC['ilDB'];
371  $query = 'SELECT user_id, module_version FROM sahs_user WHERE obj_id = ' . $ilDB->quote($this->getId(), 'integer') . ' ';
372  $res = $ilDB->query($query);
373 
374  $versions = array();
375  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
376  $versions[$row['user_id']] = (int) $row['module_version'];
377  }
378  return $versions;
379  }
380 
381 
385  public function getModuleVersionForUser($a_user_id)
386  {
387  global $DIC;
388  $ilDB = $DIC['ilDB'];
389  $val_set = $ilDB->queryF(
390  'SELECT module_version FROM sahs_user WHERE obj_id = %s AND user_id = %s',
391  array('integer','integer'),
392  array($this->getId(),$a_user_id,0)
393  );
394 
395  $val_rec = $ilDB->fetchAssoc($val_set);
396 
397  if ($val_rec["module_version"] == null) {
398  $val_rec["module_version"] = "";
399  }
400  return $val_rec["module_version"];
401  }
402 
410  public function getTrackingDataPerUser($a_sco_id, $a_user_id)
411  {
412  global $DIC;
413  $ilDB = $DIC['ilDB'];
414 
415  $data_set = $ilDB->queryF(
416  '
417  SELECT * FROM scorm_tracking
418  WHERE user_id = %s
419  AND sco_id = %s
420  AND obj_id = %s
421  ORDER BY lvalue',
422  array('integer','integer','integer'),
423  array($a_user_id,$a_sco_id,$this->getId())
424  );
425 
426  $data = array();
427  while ($data_rec = $ilDB->fetchAssoc($data_set)) {
428  $data[] = $data_rec;
429  }
430 
431  return $data;
432  }
433 
434  public function getTrackingDataAgg($a_user_id)
435  {
436  global $DIC;
437  $ilDB = $DIC['ilDB'];
438 
439  // get all users with any tracking data
440  $sco_set = $ilDB->queryF(
441  '
442  SELECT DISTINCT sco_id FROM scorm_tracking
443  WHERE obj_id = %s
444  AND user_id = %s
445  AND sco_id <> %s',
446  array('integer','integer','integer'),
447  array($this->getId(),$a_user_id,0)
448  );
449 
450  $data = array();
451  while ($sco_rec = $ilDB->fetchAssoc($sco_set)) {
452  $data_set = $ilDB->queryF(
453  '
454  SELECT * FROM scorm_tracking
455  WHERE obj_id = %s
456  AND sco_id = %s
457  AND user_id = %s
458  AND lvalue <> %s
459  AND (lvalue = %s
460  OR lvalue = %s
461  OR lvalue = %s)',
462  array('integer','integer','integer','text','text','text','text'),
463  array($this->getId(),
464  $sco_rec["sco_id"],
465  $a_user_id,
466  "package_attempts",
467  "cmi.core.lesson_status",
468  "cmi.core.total_time",
469  "cmi.core.score.raw")
470  );
471 
472  $score = $time = $status = "";
473 
474  while ($data_rec = $ilDB->fetchAssoc($data_set)) {
475  switch ($data_rec["lvalue"]) {
476  case "cmi.core.lesson_status":
477  $status = $data_rec["rvalue"];
478  break;
479 
480  case "cmi.core.total_time":
481  $time = $data_rec["rvalue"];
482  break;
483 
484  case "cmi.core.score.raw":
485  $score = $data_rec["rvalue"];
486  break;
487  }
488  }
489  //create sco_object
490  include_once './Modules/ScormAicc/classes/SCORM/class.ilSCORMItem.php';
491  $sc_item = new ilSCORMItem($sco_rec["sco_id"]);
492  $data[] = array("sco_id" => $sco_rec["sco_id"], "title" => $sc_item->getTitle(),
493  "score" => $score, "time" => $time, "status" => $status);
494  }
495  return (array) $data;
496  }
497 
498  public function getTrackingDataAggSco($a_sco_id)
499  {
500  global $DIC;
501  $ilDB = $DIC['ilDB'];
502 
503  // get all users with any tracking data
504  $user_set = $ilDB->queryF(
505  '
506  SELECT DISTINCT user_id FROM scorm_tracking
507  WHERE obj_id = %s
508  AND sco_id = %s',
509  array('integer','integer'),
510  array($this->getId(),$a_sco_id)
511  );
512 
513  $data = array();
514  while ($user_rec = $ilDB->fetchAssoc($user_set)) {
515  $data_set = $ilDB->queryF(
516  '
517  SELECT * FROM scorm_tracking
518  WHERE obj_id = %s
519  AND sco_id = %s
520  AND user_id = %s
521  AND (lvalue = %s
522  OR lvalue = %s
523  OR lvalue = %s)',
524  array('integer','integer','integer','text','text','text'),
525  array($this->getId(),
526  $a_sco_id,
527  $user_rec["user_id"],
528  "cmi.core.lesson_status",
529  "cmi.core.total_time",
530  "cmi.core.score.raw")
531  );
532 
533  $score = $time = $status = "";
534 
535  while ($data_rec = $ilDB->fetchAssoc($data_set)) {
536  switch ($data_rec["lvalue"]) {
537  case "cmi.core.lesson_status":
538  $status = $data_rec["rvalue"];
539  break;
540 
541  case "cmi.core.total_time":
542  $time = $data_rec["rvalue"];
543  break;
544 
545  case "cmi.core.score.raw":
546  $score = $data_rec["rvalue"];
547  break;
548  }
549  }
550 
551  $data[] = array("user_id" => $user_rec["user_id"],
552  "score" => $score, "time" => $time, "status" => $status);
553  }
554 
555  return $data;
556  }
557 
558 
559 
567  public function exportSelected($a_all, $a_users = array())
568  {
569  global $DIC;
570  $ilDB = $DIC['ilDB'];
571  $ilUser = $DIC['ilUser'];
572  include_once('./Modules/ScormAicc/classes/class.ilSCORMTrackingItems.php');
573  include_once("./Services/Tracking/classes/class.ilLearningProgressBaseGUI.php");
574  include_once('./Services/PrivacySecurity/classes/class.ilPrivacySettings.php');
575  $privacy = ilPrivacySettings::_getInstance();
576  $allowExportPrivacy = $privacy->enabledExportSCORM();
577 
578  $csv = "";
579  $query = 'SELECT * FROM sahs_user WHERE obj_id = %s';
580  if (count($a_users) > 0) {
581  $query .= ' AND ' . $ilDB->in('user_id', $a_users, false, 'integer');
582  }
583  $res = $ilDB->queryF(
584  $query,
585  array('integer'),
586  array($this->getId())
587  );
588  while ($data = $ilDB->fetchAssoc($res)) {
589  $csv = $csv . $data["obj_id"]
590  . ";\"" . $this->getTitle() . "\""
591  . ";" . $data["module_version"]
592  . ";\"" . implode("\";\"", ilSCORMTrackingItems::userDataArrayForExport($data["user_id"], $allowExportPrivacy)) . "\""
593  . ";\"" . $data["last_access"] . "\""
594  . ";\"" . ilLearningProgressBaseGUI::__readStatus($data["obj_id"], $data["user_id"]) . "\"" //not $data["status"] because modifications to learning progress could have made before export
595  . ";" . $data["package_attempts"]
596  . ";" . $data["percentage_completed"]
597  . ";" . $data["sco_total_time_sec"]
598 // . ";\"" . $certificateDate ."\""
599  . "\n";
600  }
602  $header = "LearningModuleId;LearningModuleTitle;LearningModuleVersion;" . str_replace(',', ';', $udh["cols"]) . ";"
603  . "LastAccess;Status;Attempts;percentageCompletedSCOs;SumTotal_timeSeconds\n";
604 
605  $this->sendExportFile($header, $csv);
606  }
607 
608 
609  public function importTrackingData($a_file)
610  {
611  global $DIC;
612  $ilDB = $DIC['ilDB'];
613  $ilUser = $DIC['ilUser'];
614 
615  $error = 0;
616  //echo file_get_contents($a_file);
617  $method = null;
618 
619  //lets import
620  $fhandle = fopen($a_file, "r");
621 
622  //the top line is the field names
623  $fields = fgetcsv($fhandle, pow(2, 16), ';');
624  //lets check the import method
625  fclose($fhandle);
626 
627  switch ($fields[0]) {
628  case "Scoid":
629  case "SCO-Identifier":
630  $error = $this->importRaw($a_file);
631  break;
632  case "Department":
633  case "LearningModuleId":
634  $error = $this->importSuccess($a_file);
635  break;
636  default:
637  return -1;
638  break;
639  }
640  return $error;
641  }
642 
643  public function importSuccess($a_file)
644  {
645  global $DIC;
646  $ilDB = $DIC['ilDB'];
647  $ilUser = $DIC['ilUser'];
648  include_once("./Services/Tracking/classes/class.ilLPStatus.php");
649  $scos = array();
650  //get all SCO's of this object ONLY RELEVANT!
651  include_once './Services/Object/classes/class.ilObjectLP.php';
652  $olp = ilObjectLP::getInstance($this->getId());
653  $collection = $olp->getCollectionInstance();
654  if ($collection) {
655  $scos = $collection->getItems();
656  }
657 
658  $fhandle = fopen($a_file, "r");
659 
660  $obj_id = $this->getID();
661  $fields = fgetcsv($fhandle, pow(2, 16), ';');
662  $users = array();
663  $usersToDelete = array();
664  while (($csv_rows = fgetcsv($fhandle, pow(2, 16), ";")) !== false) {
665  $data = array_combine($fields, $csv_rows);
666  //no check the format - sufficient to import users
667  if ($data["Login"]) {
668  $user_id = $this->get_user_id($data["Login"]);
669  }
670  if ($data["login"]) {
671  $user_id = $this->get_user_id($data["login"]);
672  }
673  //add mail in future
674  if ($data["user"] && is_numeric($data["user"])) {
675  $user_id = (int) $data["user"];
676  }
677 
678  if ($user_id > 0) {
679  $last_access = ilUtil::now();
680  if ($data['Date']) {
681  $date_ex = explode('.', $data['Date']);
682  $last_access = implode('-', array($date_ex[2], $date_ex[1], $date_ex[0]));
683  }
684  if ($data['LastAccess']) {
685  $last_access = $data['LastAccess'];
686  }
687 
689 
690  if ($data["Status"]) {
691  if (is_int($data["Status"])) {
692  $status = $data["Status"];
693  } elseif ($data["Status"] == "0" || $data["Status"] == "1" || $data["Status"] == "2" || $data["Status"] == "3") {
694  $status = (int) $data["Status"];
695  } elseif ($data["Status"] == ilLPStatus::LP_STATUS_NOT_ATTEMPTED) {
697  } elseif ($data["Status"] == ilLPStatus::LP_STATUS_IN_PROGRESS) {
699  } elseif ($data["Status"] == ilLPStatus::LP_STATUS_FAILED) {
701  }
702  }
703 
704  $attempts = null;
705  if ($data["Attempts"]) {
706  $attempts = $data["Attempts"];
707  }
708 
709  $percentage_completed = 0;
710  if ($status == ilLPStatus::LP_STATUS_COMPLETED_NUM) {
711  $percentage_completed = 100;
712  }
713  if ($data['percentageCompletedSCOs']) {
714  $percentage_completed = $data['percentageCompletedSCOs'];
715  }
716 
717  $sco_total_time_sec = null;
718  if ($data['SumTotal_timeSeconds']) {
719  $sco_total_time_sec = $data['SumTotal_timeSeconds'];
720  }
721 
722  if ($status == ilLPStatus::LP_STATUS_NOT_ATTEMPTED) {
723  $usersToDelete[] = $user_id;
724  } else {
725  $this->importSuccessForSahsUser($user_id, $last_access, $status, $attempts, $percentage_completed, $sco_total_time_sec);
726  $users[] = $user_id;
727  }
728 
729  if ($status == ilLPStatus::LP_STATUS_COMPLETED_NUM) {
730  foreach ($scos as $sco_id) {
731  $statement = $ilDB->queryF(
732  '
733  SELECT * FROM scorm_tracking
734  WHERE user_id = %s
735  AND sco_id = %s
736  AND lvalue = %s
737  AND obj_id = %s',
738  array('integer','integer','text','integer'),
739  array($user_id, $sco_id, 'cmi.core.lesson_status',$obj_id)
740  );
741  if ($ilDB->numRows($statement) > 0) {
742  $ilDB->update(
743  'scorm_tracking',
744  array(
745  'rvalue' => array('clob', 'completed'),
746  'c_timestamp' => array('timestamp', $last_access)
747  ),
748  array(
749  'user_id' => array('integer', $user_id),
750  'sco_id' => array('integer', $sco_id),
751  'lvalue' => array('text', 'cmi.core.lesson_status'),
752  'obj_id' => array('integer', $obj_id)
753  )
754  );
755  } else {
756  $ilDB->insert('scorm_tracking', array(
757  'obj_id' => array('integer', $obj_id),
758  'user_id' => array('integer', $user_id),
759  'sco_id' => array('integer', $sco_id),
760  'lvalue' => array('text', 'cmi.core.lesson_status'),
761  'rvalue' => array('clob', 'completed'),
762  'c_timestamp' => array('timestamp', $last_access)
763  ));
764  }
765  }
766  }
767  } else {
768  //echo "Warning! User $csv_rows[0] does not exist in ILIAS. Data for this user was skipped.\n";
769  }
770  }
771  if (count($usersToDelete) > 0) {
772  // include_once("./Services/Tracking/classes/class.ilLPMarks.php");
773  // ilLPMarks::_deleteForUsers($this->getId(), $usersToDelete);
774  $this->deleteTrackingDataOfUsers($usersToDelete);
775  }
776  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
778  return 0;
779  }
780 
781  public function importSuccessForSahsUser($user_id, $last_access, $status, $attempts = null, $percentage_completed = null, $sco_total_time_sec = null)
782  {
783  global $DIC;
784  $ilDB = $DIC['ilDB'];
785  $statement = $ilDB->queryF(
786  'SELECT * FROM sahs_user WHERE obj_id = %s AND user_id = %s',
787  array('integer','integer'),
788  array($this->getID(),$user_id)
789  );
790  if ($ilDB->numRows($statement) > 0) {
791  $ilDB->update(
792  'sahs_user',
793  array(
794  'last_access' => array('timestamp', $last_access),
795  'status' => array('integer', $status),
796  'package_attempts' => array('integer', $attempts),
797  'percentage_completed' => array('integer', $percentage_completed),
798  'sco_total_time_sec' => array('integer', $sco_total_time_sec)
799  ),
800  array(
801  'obj_id' => array('integer', $this->getID()),
802  'user_id' => array('integer', $user_id)
803  )
804  );
805  } else {
806  $ilDB->insert('sahs_user', array(
807  'obj_id' => array('integer', $this->getID()),
808  'user_id' => array('integer', $user_id),
809  'last_access' => array('timestamp', $last_access),
810  'status' => array('integer', $status),
811  'package_attempts' => array('integer', $attempts),
812  'percentage_completed' => array('integer', $percentage_completed),
813  'sco_total_time_sec' => array('integer', $sco_total_time_sec)
814  ));
815  }
816 
817  include_once("./Services/Tracking/classes/class.ilChangeEvent.php");
818  ilChangeEvent::_recordReadEvent("sahs", (int) $_GET["ref_id"], $this->getID(), $user_id, false, $attempts, $sco_total_time_sec);
819  }
820 
826  private function parseUserId($il_id)
827  {
828  global $DIC;
829  $ilSetting = $DIC['ilSetting'];
830 
831  $parts = explode('_', $il_id);
832 
833  if (!count((array) $parts)) {
834  return 0;
835  }
836  if (!isset($parts[2]) or !isset($parts[3])) {
837  return 0;
838  }
839  if ($parts[2] != $ilSetting->get('inst_id', $parts[2])) {
840  return 0;
841  }
842  return $parts[3];
843  }
844 
852  private function importRaw($a_file)
853  {
854  global $DIC;
855  $ilDB = $DIC['ilDB'];
856  $ilUser = $DIC['ilUser'];
857  $lng = $DIC['lng'];
858  $lng->loadLanguageModule("scormtrac");
859 
860  $fhandle = fopen($a_file, "r");
861 
862  $fields = fgetcsv($fhandle, pow(2, 16), ';');
863  $users = array();
864  $a_last_access = array();
865  $a_time = array();
866  $a_package_attempts = array();
867  $a_module_version = array();
868  while (($csv_rows = fgetcsv($fhandle, pow(2, 16), ";")) !== false) {
869  $data = array_combine($fields, $csv_rows);
870  if ($data['Userid']) {
871  $user_id = $this->parseUserId($data['Userid']);
872  } elseif ($data[$lng->txt("user")]) {
873  if (is_int($data[$lng->txt("user")])) {
874  $user_id = $data[$lng->txt("user")];
875  }
876  }
877  if ($data[$lng->txt("login")]) {
878  $user_id = $this->get_user_id($data[$lng->txt("login")]);
879  }
880  if (!$user_id) {
881  continue;
882  }
883 
884  if ($data['Scoid']) {
885  $il_sco_id = $this->lookupSCOId($data['Scoid']);
886  }
887  if ($data[$lng->txt("identifierref")]) {
888  $il_sco_id = $this->lookupSCOId($data[$lng->txt("identifierref")]);
889  }
890  if (!$il_sco_id) {
891  continue;
892  }
893 
894  $c_timestamp = "";
895  if ($data['Timestamp']) {
896  $c_timestamp = $data['Timestamp'];
897  }
898  if ($data[$lng->txt("c_timestamp")]) {
899  $c_timestamp = $data[$lng->txt("c_timestamp")];
900  }
901  if ($c_timestamp == "") {
902  $date = new DateTime();
903  $c_timestamp = $date->getTimestamp();
904  } else {
905  if ($a_last_access[$user_id]) {
906  if ($a_last_access[$user_id] < $c_timestamp) {
907  $a_last_access[$user_id] = $c_timestamp;
908  }
909  } else {
910  $a_last_access[$user_id] = $c_timestamp;
911  }
912  }
913 
914  if (!$data['Key']) {
915  continue;
916  }
917  if (!$data['Value']) {
918  $data['Value'] = "";
919  }
920 
921  if ($data['Key'] == "cmi.core.total_time" && $data['Value'] != "") {
922  $tarr = explode(":", $data['Value']);
923  $sec = (int) $tarr[2] + (int) $tarr[1] * 60 +
924  (int) substr($tarr[0], strlen($tarr[0]) - 3) * 60 * 60;
925  if ($a_time[$user_id]) {
926  $a_time[$user_id] += $sec;
927  } else {
928  $a_time[$user_id] = $sec;
929  }
930  }
931  //do the actual import
932  if ($il_sco_id > 0) {
933  $statement = $ilDB->queryF(
934  '
935  SELECT * FROM scorm_tracking
936  WHERE user_id = %s
937  AND sco_id = %s
938  AND lvalue = %s
939  AND obj_id = %s',
940  array('integer', 'integer', 'text', 'integer'),
941  array($user_id, $il_sco_id, $data['Key'], $this->getID())
942  );
943  if ($ilDB->numRows($statement) > 0) {
944  $ilDB->update(
945  'scorm_tracking',
946  array(
947  'rvalue' => array('clob', $data['Value']),
948  'c_timestamp' => array('timestamp', $c_timestamp)
949  ),
950  array(
951  'user_id' => array('integer', $user_id),
952  'sco_id' => array('integer', $il_sco_id),
953  'lvalue' => array('text', $data['Key']),
954  'obj_id' => array('integer', $this->getId())
955  )
956  );
957  } else {
958  $ilDB->insert('scorm_tracking', array(
959  'obj_id' => array('integer', $this->getId()),
960  'user_id' => array('integer', $user_id),
961  'sco_id' => array('integer', $il_sco_id),
962  'lvalue' => array('text', $data['Key']),
963  'rvalue' => array('clob', $data['Value']),
964  'c_timestamp' => array('timestamp', $data['Timestamp'])
965  ));
966  }
967  }
968  // $package_attempts = 1;
969  if ($il_sco_id == 0) {
970  if ($data['Key'] == "package_attempts") {
971  $a_package_attempts[$user_id] = $data['Value'];
972  }
973  // if ($data['Key'] == "module_version") $a_module_version[$user_id] = $data['Value'];
974  }
975  if (!in_array($user_id, $users)) {
976  $users[] = $user_id;
977  }
978  }
979  fclose($fhandle);
980 
981  //UK determineStatus, percentage_completed and syncGlobalStatus
982  include_once './Services/Tracking/classes/class.ilLPStatusWrapper.php';
984 
985  // include_once './Services/Tracking/classes/status/class.ilLPStatusSCORM.php';
986  include_once './Services/Tracking/classes/class.ilLPStatus.php';
987  foreach ($users as $user_id) {
988  $attempts = 1;
989  if ($a_package_attempts[$user_id]) {
990  $attempts = $a_package_attempts[$user_id];
991  }
992  // $module_version = 1;
993  // if ($a_module_version[$user_id]) $module_version = $a_module_version[$user_id];
994  $sco_total_time_sec = null;
995  if ($a_time[$user_id]) {
996  $sco_total_time_sec = $a_time[$user_id];
997  }
998  $last_access = null;
999  if ($a_last_access[$user_id]) {
1000  $last_access = $a_last_access[$user_id];
1001  }
1002  // $status = ilLPStatusWrapper::_determineStatus($this->getId(),$user_id);
1003  $status = ilLPStatus::_lookupStatus($this->getId(), $user_id);
1004  // $percentage_completed = ilLPStatusSCORM::determinePercentage($this->getId(),$user_id);
1005  $percentage_completed = ilLPStatus::_lookupPercentage($this->getId(), $user_id);
1006 
1007  $this->importSuccessForSahsUser($user_id, $last_access, $status, $attempts, $percentage_completed, $sco_total_time_sec);
1008  }
1009 
1010  return 0;
1011  }
1012 
1013 
1019  public function decreaseAttemptsForUser($a_user_id)
1020  {
1021  global $DIC;
1022  $ilDB = $DIC['ilDB'];
1023 
1024  foreach ($a_user_id as $user) {
1025  //first check if there is a package_attempts entry
1026  $val_set = $ilDB->queryF(
1027  'SELECT package_attempts FROM sahs_user WHERE user_id = %s AND obj_id = %s',
1028  array('integer','integer'),
1029  array($user,$this->getID())
1030  );
1031 
1032  $val_rec = $ilDB->fetchAssoc($val_set);
1033 
1034  if ($val_rec["package_attempts"] != null && $val_rec["package_attempts"] != 0) {
1035  $new_rec = 0;
1036  //decrease attempt by 1
1037  if ((int) $val_rec["package_attempts"] > 0) {
1038  $new_rec = (int) $val_rec["package_attempts"] - 1;
1039  }
1040  $ilDB->manipulateF(
1041  'UPDATE sahs_user SET package_attempts = %s WHERE user_id = %s AND obj_id = %s',
1042  array('integer','integer','integer'),
1043  array($new_rec,$user,$this->getID())
1044  );
1045 
1046  //following 2 lines were before 4.4 only for SCORM 1.2
1047  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
1048  ilLPStatusWrapper::_updateStatus($this->getId(), $user);
1049  }
1050  }
1051  }
1052 
1053 
1054  //helper function
1055  public function get_user_id($a_login)
1056  {
1057  global $DIC;
1058  $ilDB = $DIC['ilDB'];
1059  $ilUser = $DIC['ilUser'];
1060 
1061  $val_set = $ilDB->queryF(
1062  'SELECT * FROM usr_data WHERE(login=%s)',
1063  array('text'),
1064  array($a_login)
1065  );
1066  $val_rec = $ilDB->fetchAssoc($val_set);
1067 
1068  if (count($val_rec) > 0) {
1069  return $val_rec['usr_id'];
1070  } else {
1071  return null;
1072  }
1073  }
1074 
1075 
1079  private function lookupSCOId($a_referrer)
1080  {
1081  global $DIC;
1082  $ilDB = $DIC['ilDB'];
1083  $ilUser = $DIC['ilUser'];
1084 
1085  //non specific SCO entries
1086  if ($a_referrer == "0") {
1087  return 0;
1088  }
1089 
1090  $val_set = $ilDB->queryF(
1091  '
1092  SELECT obj_id FROM sc_item,scorm_tree
1093  WHERE (obj_id = child
1094  AND identifierref = %s
1095  AND slm_id = %s)',
1096  array('text','integer'),
1097  array($a_referrer,$this->getID())
1098  );
1099  $val_rec = $ilDB->fetchAssoc($val_set);
1100 
1101  return $val_rec["obj_id"];
1102  }
1103 
1107  public function getUserIdEmail($a_mail)
1108  {
1109  global $DIC;
1110  $ilDB = $DIC['ilDB'];
1111  $ilUser = $DIC['ilUser'];
1112 
1113  $val_set = $ilDB->queryF(
1114  'SELECT usr_id FROM usr_data WHERE(email=%s)',
1115  array('text'),
1116  array($a_mail)
1117  );
1118  $val_rec = $ilDB->fetchAssoc($val_set);
1119 
1120 
1121  return $val_rec["usr_id"];
1122  }
1123 
1124 
1128  public function sendExportFile($a_header, $a_content)
1129  {
1130  $timestamp = time();
1131  $refid = $this->getRefId();
1132  $filename = "scorm_tracking_" . $refid . "_" . $timestamp . ".csv";
1134  exit;
1135  }
1136 
1142  public static function _getAllScoIds($a_id)
1143  {
1144  global $DIC;
1145  $ilDB = $DIC['ilDB'];
1146 
1147  $scos = array();
1148 
1149  $val_set = $ilDB->queryF(
1150  '
1151  SELECT scorm_object.obj_id,
1152  scorm_object.title,
1153  scorm_object.c_type,
1154  scorm_object.slm_id,
1155  scorm_object.obj_id scoid
1156  FROM scorm_object,sc_item,sc_resource
1157  WHERE(scorm_object.slm_id = %s
1158  AND scorm_object.obj_id = sc_item.obj_id
1159  AND sc_item.identifierref = sc_resource.import_id
1160  AND sc_resource.scormtype = %s)
1161  GROUP BY scorm_object.obj_id,
1162  scorm_object.title,
1163  scorm_object.c_type,
1164  scorm_object.slm_id,
1165  scorm_object.obj_id ',
1166  array('integer', 'text'),
1167  array($a_id,'sco')
1168  );
1169 
1170  while ($val_rec = $ilDB->fetchAssoc($val_set)) {
1171  array_push($scos, $val_rec['scoid']);
1172  }
1173  return $scos;
1174  }
1175 
1184  public static function _getStatusForUser($a_id, $a_user, $a_allScoIds, $a_numerical = false)
1185  {
1186  global $DIC;
1187  $ilDB = $DIC['ilDB'];
1188  $lng = $DIC['lng'];
1189 
1190  $scos = $a_allScoIds;
1191  //check if all SCO's are completed
1192  $scos_c = implode(',', $scos);
1193 
1194  $val_set = $ilDB->queryF(
1195  '
1196  SELECT * FROM scorm_tracking
1197  WHERE (user_id = %s
1198  AND obj_id = %s
1199  AND ' . $ilDB->in('sco_id', $scos, false, 'integer') . '
1200  AND ((lvalue = %s AND ' . $ilDB->like('rvalue', 'clob', 'completed') . ')
1201  OR (lvalue = %s AND ' . $ilDB->like('rvalue', 'clob', 'passed') . ')))',
1202  array('integer','integer','text','text'),
1203  array($a_user,$a_id,'cmi.core.lesson_status', 'cmi.core.lesson_status')
1204  );
1205  while ($val_rec = $ilDB->fetchAssoc($val_set)) {
1206  $key = array_search($val_rec['sco_id'], $scos);
1207  unset($scos[$key]);
1208  }
1209  //check for completion
1210  if (count($scos) == 0) {
1211  $completion = ($a_numerical === true) ? true: $lng->txt("cont_complete");
1212  }
1213  if (count($scos) > 0) {
1214  $completion = ($a_numerical === true) ? false: $lng->txt("cont_incomplete");
1215  }
1216  return $completion;
1217  }
1218 
1225  public static function _getCourseCompletionForUser($a_id, $a_user)
1226  {
1228  }
1229 
1230  public function getAllScoIds()
1231  {
1232  global $DIC;
1233  $ilDB = $DIC['ilDB'];
1234 
1235  $scos = array();
1236  //get all SCO's of this object
1237  $val_set = $ilDB->queryF(
1238  '
1239  SELECT scorm_object.obj_id,
1240  scorm_object.title,
1241  scorm_object.c_type,
1242  scorm_object.slm_id,
1243  scorm_object.obj_id scoid
1244  FROM scorm_object, sc_item,sc_resource
1245  WHERE(scorm_object.slm_id = %s
1246  AND scorm_object.obj_id = sc_item.obj_id
1247  AND sc_item.identifierref = sc_resource.import_id
1248  AND sc_resource.scormtype = %s )
1249  GROUP BY scorm_object.obj_id,
1250  scorm_object.title,
1251  scorm_object.c_type,
1252  scorm_object.slm_id,
1253  scorm_object.obj_id',
1254  array('integer','text'),
1255  array($this->getId(),'sco')
1256  );
1257 
1258  while ($val_rec = $ilDB->fetchAssoc($val_set)) {
1259  array_push($scos, $val_rec['scoid']);
1260  }
1261  return $scos;
1262  }
1263 
1264  public function getStatusForUser($a_user, $a_allScoIds, $a_numerical = false)
1265  {
1266  global $DIC;
1267  $ilDB = $DIC['ilDB'];
1268  $scos = $a_allScoIds;
1269  //loook up status
1270  //check if all SCO's are completed
1271  $scos_c = implode(',', $scos);
1272 
1273  $val_set = $ilDB->queryF(
1274  '
1275  SELECT sco_id FROM scorm_tracking
1276  WHERE (user_id = %s
1277  AND obj_id = %s
1278  AND ' . $ilDB->in('sco_id', $scos, false, 'integer') . '
1279  AND ((lvalue = %s AND ' . $ilDB->like('rvalue', 'clob', 'completed') . ') OR (lvalue = %s AND ' . $ilDB->like('rvalue', 'clob', 'passed') . ') ) )',
1280  array('integer','integer','text','text',),
1281  array($a_user,$this->getID(),'cmi.core.lesson_status','cmi.core.lesson_status')
1282  );
1283  while ($val_rec = $ilDB->fetchAssoc($val_set)) {
1284  $key = array_search($val_rec['sco_id'], $scos);
1285  unset($scos[$key]);
1286  }
1287  //check for completion
1288  if (count($scos) == 0) {
1289  $completion = ($a_numerical === true) ? true: $this->lng->txt("cont_complete");
1290  }
1291  if (count($scos) > 0) {
1292  $completion = ($a_numerical === true) ? false: $this->lng->txt("cont_incomplete");
1293  }
1294  return $completion;
1295  }
1296 
1297  public function getCourseCompletionForUser($a_user)
1298  {
1299  return $this->getStatusForUser($a_user, $this->getAllScoIds, true);
1300  }
1301 
1302  //to be called from IlObjUser
1303  public static function _removeTrackingDataForUser($user_id)
1304  {
1305  global $DIC;
1306  $ilDB = $DIC['ilDB'];
1307  //gobjective
1308  $ilDB->manipulateF(
1309  'DELETE FROM scorm_tracking WHERE user_id = %s',
1310  array('integer'),
1311  array($user_id)
1312  );
1313  $ilDB->manipulateF(
1314  'DELETE FROM sahs_user WHERE user_id = %s',
1315  array('integer'),
1316  array($user_id)
1317  );
1318  }
1319 
1320  public static function _getScoresForUser($a_item_id, $a_user_id)
1321  {
1322  global $DIC;
1323  $ilDB = $DIC['ilDB'];
1324 
1325  $retAr = array("raw" => null, "max" => null, "scaled" => null);
1326  $val_set = $ilDB->queryF(
1327  "
1328  SELECT lvalue, rvalue FROM scorm_tracking
1329  WHERE sco_id = %s
1330  AND user_id = %s
1331  AND (lvalue = 'cmi.core.score.raw' OR lvalue = 'cmi.core.score.max')",
1332  array('integer', 'integer'),
1333  array($a_item_id, $a_user_id)
1334  );
1335  while ($val_rec = $ilDB->fetchAssoc($val_set)) {
1336  if ($val_rec['lvalue'] == "cmi.core.score.raw") {
1337  $retAr["raw"] = $val_rec["rvalue"];
1338  }
1339  if ($val_rec['lvalue'] == "cmi.core.score.max") {
1340  $retAr["max"] = $val_rec["rvalue"];
1341  }
1342  }
1343  if ($retAr["raw"] != null && $retAr["max"] != null) {
1344  $retAr["scaled"] = ($retAr["raw"] / $retAr["max"]);
1345  }
1346 
1347  return $retAr;
1348  }
1349 
1350 
1351  public function getLastVisited($user_id)
1352  {
1353  global $DIC;
1354  $ilDB = $DIC['ilDB'];
1355  $val_set = $ilDB->queryF(
1356  'SELECT last_visited FROM sahs_user WHERE obj_id = %s AND user_id = %s',
1357  array('integer','integer'),
1358  array($this->getID(),$user_id)
1359  );
1360  while ($val_rec = $ilDB->fetchAssoc($val_set)) {
1361  if ($val_rec["last_visited"] != null) {
1362  return "" . $val_rec["last_visited"];
1363  }
1364  }
1365  return '0';
1366  }
1367 
1368  public function deleteTrackingDataOfUsers($a_users)
1369  {
1370  global $DIC;
1371  $ilDB = $DIC['ilDB'];
1372  include_once("./Services/Tracking/classes/class.ilChangeEvent.php");
1373  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
1374 
1375  ilChangeEvent::_deleteReadEventsForUsers($this->getId(), $a_users);
1376 
1377  foreach ($a_users as $user) {
1378  $ilDB->manipulateF(
1379  '
1380  DELETE FROM scorm_tracking
1381  WHERE user_id = %s
1382  AND obj_id = %s',
1383  array('integer', 'integer'),
1384  array($user, $this->getID())
1385  );
1386 
1387  $ilDB->manipulateF(
1388  '
1389  DELETE FROM sahs_user
1390  WHERE user_id = %s
1391  AND obj_id = %s',
1392  array('integer', 'integer'),
1393  array($user, $this->getID())
1394  );
1395 
1396  ilLPStatusWrapper::_updateStatus($this->getId(), $user);
1397  }
1398  }
1399 }
const LP_STATUS_COMPLETED_NUM
static _getAllScoIds($a_id)
Get an array of id&#39;s for all Sco&#39;s in the module.
static _recordReadEvent( $a_type, $a_ref_id, $obj_id, $usr_id, $isCatchupWriteEvents=true, $a_ext_rc=false, $a_ext_time=false)
Records a read event and catches up with write events.
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.
parseUserId($il_id)
Parse il_usr_123_6 id.
getAttemptsForUsers()
Get attempts for all users ilDB $ilDB.
$result
global $DIC
Definition: saml.php:7
static _getCourseCompletionForUser($a_id, $a_user)
Get the completion of a SCORM module for a given user.
$_GET["client_id"]
const LP_STATUS_NOT_ATTEMPTED
static _updateStatus($a_obj_id, $a_usr_id, $a_obj=null, $a_percentage=false, $a_force_raise=false)
Update status.
getTrackedItems()
get all tracked items of current user
static _lookupPercentage($a_obj_id, $a_user_id)
Lookup percentage.
sendExportFile($a_header, $a_content)
send export file to browser
const LP_STATUS_IN_PROGRESS_NUM
decreaseAttemptsForUser($a_user_id)
Decrease attempts for user ilDB $ilDB.
getUserIdEmail($a_mail)
assumes that only one account exists for a mailadress
getAttemptsForUser($a_user_id)
get number of attempts for a certain user and package
__construct($a_id=0, $a_call_by_reference=true)
Constructor public.
static _refreshStatus($a_obj_id, $a_users=null)
Set dirty.
static now()
Return current timestamp in Y-m-d H:i:s format.
static _lookupLastAccess($a_obj_id, $a_usr_id)
Return the last access timestamp for a given user.
$ilErr
Definition: raiseError.php:18
const LP_STATUS_IN_PROGRESS
getTrackingDataPerUser($a_sco_id, $a_user_id)
Get tracking data per user ilDB $ilDB.
validate($directory)
Validate all XML-Files in a SCOM-Directory.
$start
Definition: bench.php:8
$time
Definition: cron.php:21
getDataDirectory($mode="filesystem")
get data directory of lm
static _enabledLearningProgress()
check wether learing progress is enabled or not
const LP_STATUS_FAILED
foreach($_POST as $key=> $value) $res
getId()
get object id public
$a_content
Definition: workflow.php:93
getTitle()
get object title public
SCORM Item.
$ilUser
Definition: imgupload.php:18
redirection script todo: (a better solution should control the processing via a xml file) ...
$query
getModuleVersionForUser($a_user_id)
get module version that tracking data for a user was recorded on
$n
Definition: RandomTest.php:85
Validation of SCORM-XML Files.
SCORM Object Tree.
$user
Definition: migrateto20.php:57
importSuccessForSahsUser($user_id, $last_access, $status, $attempts=null, $percentage_completed=null, $sco_total_time_sec=null)
$users
Definition: authpage.php:44
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
static _getTrackingItems($a_obj_id)
get all tracking items of scorm object static
$filename
Definition: buildRTE.php:89
getStatusForUser($a_user, $a_allScoIds, $a_numerical=false)
$row
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
const LP_STATUS_NOT_ATTEMPTED_NUM
static __readStatus($a_obj_id, $user_id)
exit
Definition: backend.php:16
static _getStatusForUser($a_id, $a_user, $a_allScoIds, $a_numerical=false)
Get the status of a SCORM module for a given user.
$lm_set
global $ilSetting
Definition: privfeed.php:17
setLearningProgressSettingsAtUpload()
set settings for learning progress determination per default at upload
static _deleteReadEventsForUsers($a_obj_id, array $a_user_ids)
global $ilDB
readObject()
read manifest file public
getRefId()
get reference id public
static _getInstance()
Get instance of ilPrivacySettings.
static _getScoresForUser($a_item_id, $a_user_id)
static userDataArrayForExport($user, $b_allowExportPrivacy=false)
static getInstance($a_obj_id)
$key
Definition: croninfo.php:18
Class ilObjSCORMLearningModule.
$_POST["username"]
static _lookupStatus($a_obj_id, $a_user_id, $a_create=true)
Lookup status.
Class ilObjSCORMLearningModule.
const LP_STATUS_FAILED_NUM
$data
Definition: bench.php:6