ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilObjSCORMTracking.php
Go to the documentation of this file.
1 <?php
2 
3 /* Copyright (c) 1998-2011 ILIAS open source, Extended GPL, see docs/LICENSE */
4 
13 {
14  public function extractData()
15  {
16  $this->insert = array();
17  if (is_array($_GET["iL"])) {
18  foreach ($_GET["iL"] as $key => $value) {
19  $this->insert[] = array("left" => $value, "right" => $_GET["iR"][$key]);
20  }
21  }
22  if (is_array($_POST["iL"])) {
23  foreach ($_POST["iL"] as $key => $value) {
24  $this->insert[] = array("left" => $value, "right" => $_POST["iR"][$key]);
25  }
26  }
27 
28  $this->update = array();
29  if (is_array($_GET["uL"])) {
30  foreach ($_GET["uL"] as $key => $value) {
31  $this->update[] = array("left" => $value, "right" => $_GET["uR"][$key]);
32  }
33  }
34  if (is_array($_POST["uL"])) {
35  foreach ($_POST["uL"] as $key => $value) {
36  $this->update[] = array("left" => $value, "right" => $_POST["uR"][$key]);
37  }
38  }
39  }
40 
41  public function store($obj_id = 0, $sahs_id = 0, $extractData = 1)
42  {
43  global $DIC;
44  $ilDB = $DIC['ilDB'];
45  $ilUser = $DIC['ilUser'];
46 
47  $ref_id = $_GET["ref_id"];
48  if (empty($obj_id)) {
49  $obj_id = ilObject::_lookupObjId($_GET["ref_id"]);
50  }
51 
52  // writing to scorm test log
53  $f = fopen("./Modules/ScormAicc/log/scorm.log", "a");
54  fwrite($f, "\nCALLING SCORM store()\n");
55  fwrite($f, 'POST: ' . print_r($_POST, true));
56 
57 
58  if (empty($sahs_id)) {
59  $sahs_id = ($_GET["sahs_id"] != "") ? $_GET["sahs_id"] : $_POST["sahs_id"];
60  }
61 
62  if ($extractData == 1) {
63  $this->extractData();
64  }
65 
66  if (is_object($ilUser)) {
67  $user_id = $ilUser->getId();
68  }
69 
70 
71 
72  if ($obj_id <= 1) {
73  fwrite($f, "Error: No obj_id given.\n");
74  } else {
75  foreach ($this->insert as $insert) {
76  $set = $ilDB->queryF(
77  '
78  SELECT * FROM scorm_tracking
79  WHERE user_id = %s
80  AND sco_id = %s
81  AND lvalue = %s
82  AND obj_id = %s',
83  array('integer','integer','text','integer'),
84  array($user_id,$sahs_id,$insert["left"],$obj_id)
85  );
86  if ($rec = $ilDB->fetchAssoc($set)) {
87  fwrite($f, "Error Insert, left value already exists. L:" . $insert["left"] . ",R:" .
88  $insert["right"] . ",sahs_id:" . $sahs_id . ",user_id:" . $user_id . "\n");
89  } else {
90  $ilDB->insert('scorm_tracking', array(
91  'obj_id' => array('integer', $obj_id),
92  'user_id' => array('integer', $user_id),
93  'sco_id' => array('integer', $sahs_id),
94  'lvalue' => array('text', $insert["left"]),
95  'rvalue' => array('clob', $insert["right"]),
96  'c_timestamp' => array('timestamp', ilUtil::now())
97  ));
98 
99  fwrite($f, "Insert - L:" . $insert["left"] . ",R:" .
100  $insert["right"] . ",sahs_id:" . $sahs_id . ",user_id:" . $user_id . "\n");
101  }
102  }
103  foreach ($this->update as $update) {
104  $set = $ilDB->queryF(
105  '
106  SELECT * FROM scorm_tracking
107  WHERE user_id = %s
108  AND sco_id = %s
109  AND lvalue = %s
110  AND obj_id = %s',
111  array('integer','integer','text','integer'),
112  array($user_id,$sahs_id,$update["left"],$obj_id)
113  );
114 
115  if ($rec = $ilDB->fetchAssoc($set)) {
116  $ilDB->update(
117  'scorm_tracking',
118  array(
119  'rvalue' => array('clob', $update["right"]),
120  'c_timestamp' => array('timestamp', ilUtil::now())
121  ),
122  array(
123  'user_id' => array('integer', $user_id),
124  'sco_id' => array('integer', $sahs_id),
125  'lvalue' => array('text', $update["left"]),
126  'obj_id' => array('integer', $obj_id)
127  )
128  );
129  } else {
130  fwrite($f, "ERROR Update, left value does not exist. L:" . $update["left"] . ",R:" .
131  $update["right"] . ",sahs_id:" . $sahs_id . ",user_id:" . $user_id . "\n");
132  }
133  }
134  }
135  fclose($f);
136 
137  // update status
138  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
139  ilLPStatusWrapper::_updateStatus($obj_id, $user_id);
140 
141  // update time and numbers of attempts in change event
142  //NOTE: is possibly not correct (it is count of commit with changed values); be careful to performance issues
143  ilObjSCORMTracking::_syncReadEvent($obj_id, $user_id, "sahs", $ref_id);
144  }
145 
146  public static function storeJsApi($obj_id = 0)
147  {
148  // global $DIC;
149  // $ilLog = $DIC['ilLog'];
150  // $ilUser = $DIC['ilUser'];
151 
152  // if (is_object($ilUser)) {
153  // $user_id = $ilUser->getId();
154  // }
155  // if (empty($obj_id)) $obj_id = ilObject::_lookupObjId($_GET["ref_id"]);
156  $obj_id = (int) $_GET["package_id"];
157  $in = file_get_contents("php://input");
158  // $ilLog->write($in);
159  $data = json_decode($in);
160  $user_id = (int) $data->p;
161 
162  header('Content-Type: text/plain; charset=UTF-8');
163 
164  $rval = self::storeJsApiCmi($user_id, $obj_id, $data);
165  if ($rval != true) {
166  print("storeJsApiCmi failed");
167  } else {
168  $rval = self::syncGlobalStatus($user_id, $obj_id, $data, $data->now_global_status);
169  if ($rval != true) {
170  print("syncGlobalStatus failed");
171  }
172  }
173  if ($rval == true) {
174  print("ok");
175  }
176  }
177 
178  public static function storeJsApiCmi($user_id, $obj_id, $data)
179  {
180  global $DIC;
181  $ilLog = $DIC['ilLog'];
182  $ilDB = $DIC['ilDB'];
183 
184  $b_updateStatus = false;
185  $i_score_max = 0;
186  $i_score_raw = 0;
187 
188  $b_messageLog = false;
189  if ($ilLog->current_log_level == 30) {
190  $b_messageLog = true;
191  }
192 
193  if ($b_messageLog) {
194  $ilLog->write("ScormAicc: CALLING SCORM storeJsApi() " . $_POST);
195  }
196 
197 
198  $aa_data = array();
199  // if (is_array($_POST["S"])) {
200  // foreach($_POST["S"] as $key => $value) {
201  // $aa_data[] = array("sco_id" => $value, "left" => $_POST["L"][$key], "right" => $_POST["R"][$key]);
202  // }
203  // }
204  for ($i = 0;$i < count($data->cmi);$i++) {
205  $aa_data[] = array("sco_id" => (int) $data->cmi[$i][0], "left" => $data->cmi[$i][1], "right" => $data->cmi[$i][2]);
206  // $aa_data[] = array("sco_id" => (int) $data->cmi[$i][0], "left" => $data->cmi[$i][1], "right" => rawurldecode($data->cmi[$i][2]));
207  }
208 
209  if ($obj_id <= 1) {
210  $ilLog->write("ScormAicc: storeJsApi: Error: No valid obj_id given.");
211  } else {
212  foreach ($aa_data as $a_data) {
213  $set = $ilDB->queryF(
214  '
215  SELECT rvalue FROM scorm_tracking
216  WHERE user_id = %s
217  AND sco_id = %s
218  AND lvalue = %s
219  AND obj_id = %s',
220  array('integer','integer','text','integer'),
221  array($user_id,$a_data["sco_id"],$a_data["left"],$obj_id)
222  );
223  if ($rec = $ilDB->fetchAssoc($set)) {
224  if ($a_data["left"] == 'cmi.core.lesson_status' && $a_data["right"] != $rec["rvalue"]) {
225  $b_updateStatus = true;
226  }
227  $ilDB->update(
228  'scorm_tracking',
229  array(
230  'rvalue' => array('clob', $a_data["right"]),
231  'c_timestamp' => array('timestamp', ilUtil::now())
232  ),
233  array(
234  'user_id' => array('integer', $user_id),
235  'sco_id' => array('integer', $a_data["sco_id"]),
236  'lvalue' => array('text', $a_data["left"]),
237  'obj_id' => array('integer', $obj_id)
238  )
239  );
240  if ($b_messageLog) {
241  $ilLog->write("ScormAicc: storeJsApi Updated - L:" . $a_data["left"] . ",R:" .
242  $a_data["right"] . " for obj_id:" . $obj_id . ",sco_id:" . $a_data["sco_id"] . ",user_id:" . $user_id);
243  }
244  } else {
245  if ($a_data["left"] == 'cmi.core.lesson_status') {
246  $b_updateStatus = true;
247  }
248  $ilDB->insert('scorm_tracking', array(
249  'obj_id' => array('integer', $obj_id),
250  'user_id' => array('integer', $user_id),
251  'sco_id' => array('integer', $a_data["sco_id"]),
252  'lvalue' => array('text', $a_data["left"]),
253  'rvalue' => array('clob', $a_data["right"]),
254  'c_timestamp' => array('timestamp', ilUtil::now())
255  ));
256  if ($b_messageLog) {
257  $ilLog->write("ScormAicc: storeJsApi Inserted - L:" . $a_data["left"] . ",R:" .
258  $a_data["right"] . " for obj_id:" . $obj_id . ",sco_id:" . $a_data["sco_id"] . ",user_id:" . $user_id);
259  }
260  }
261  if ($a_data["left"] == 'cmi.core.score.max') {
262  $i_score_max = $a_data["right"];
263  }
264  if ($a_data["left"] == 'cmi.core.score.raw') {
265  $i_score_raw = $a_data["right"];
266  }
267  }
268  // mantis #30293
269  if ($i_score_max > 0 && $i_score_raw > 0) {
270  if (count(ilSCORMObject::_lookupPresentableItems($obj_id)) == 1) {
272  ($i_score_raw / $i_score_max) * 100);
273  }
274  }
275  }
276 
277  // update status
278  // if ($b_updateStatus == true) {
279  // include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
280  // ilLPStatusWrapper::_updateStatus($obj_id, $user_id);
281  // }
282 
283  return true;
284  }
285 
286  //erase later see ilSCORM2004StoreData
287  public static function syncGlobalStatus($userId, $packageId, $data, $new_global_status)
288  {
289  global $DIC;
290  $ilDB = $DIC['ilDB'];
291  $ilLog = $DIC['ilLog'];
292  $saved_global_status = $data->saved_global_status;
293  $ilLog->write("saved_global_status=" . $saved_global_status);
294 
295  // get attempts
296  if (!$data->packageAttempts) {
297  $val_set = $ilDB->queryF(
298  'SELECT package_attempts FROM sahs_user WHERE obj_id = %s AND user_id = %s',
299  array('integer','integer'),
300  array($packageId,$userId)
301  );
302  $val_rec = $ilDB->fetchAssoc($val_set);
303  $attempts = $val_rec["package_attempts"];
304  } else {
305  $attempts = $data->packageAttempts;
306  }
307  if ($attempts == null) {
308  $attempts = 1;
309  }
310 
311  //update percentage_completed, sco_total_time_sec,status in sahs_user
312  $totalTime = (int) $data->totalTimeCentisec;
313  $totalTime = round($totalTime / 100);
314  $ilDB->queryF(
315  'UPDATE sahs_user SET last_visited=%s, last_access = %s, sco_total_time_sec=%s, status=%s, percentage_completed=%s, package_attempts=%s WHERE obj_id = %s AND user_id = %s',
316  array('text', 'timestamp', 'integer', 'integer', 'integer', 'integer', 'integer', 'integer'),
317  array($data->last_visited, date('Y-m-d H:i:s'), $totalTime, $new_global_status, $data->percentageCompleted, $attempts, $packageId, $userId)
318  );
319 
320  // self::ensureObjectDataCacheExistence();
321  global $DIC;
322  $ilObjDataCache = $DIC['ilObjDataCache'];
323  include_once("./Services/Tracking/classes/class.ilChangeEvent.php");
324  ilChangeEvent::_recordReadEvent("sahs", (int) $_GET['ref_id'], $packageId, $userId, false, $attempts, $totalTime);
325 
326  //end sync access number and time in read event table
327 
328  // update learning progress
329  if ($new_global_status != null) {//could only happen when synchronising from SCORM Offline Player
330  include_once("./Services/Tracking/classes/class.ilObjUserTracking.php");
331  include_once("./Services/Tracking/classes/class.ilLPStatus.php");
332  ilLPStatus::writeStatus($packageId, $userId, $new_global_status, $data->percentageCompleted);
333 
334  // here put code for soap to MaxCMS e.g. when if($saved_global_status != $new_global_status)
335  }
336  return true;
337  }
338 
339 
346  public static function _syncReadEvent($a_obj_id, $a_user_id, $a_type, $a_ref_id)
347  {
348  global $DIC;
349  $ilDB = $DIC['ilDB'];
350  $ilLog = $DIC['ilLog'];
351  $val_set = $ilDB->queryF(
352  'SELECT package_attempts, total_time_sec, sco_total_time_sec, time_from_lms FROM sahs_user, sahs_lm '
353  . 'WHERE sahs_user.obj_id = %s AND sahs_user.user_id = %s AND sahs_user.obj_id = sahs_lm.id',
354  array('integer','integer'),
355  array($a_obj_id,$a_user_id)
356  );
357 
358  $val_rec = $ilDB->fetchAssoc($val_set);
359 
360  if ($val_rec["package_attempts"] == null) {
361  $val_rec["package_attempts"] = "";
362  }
363  $attempts = $val_rec["package_attempts"];
364 
365  $time = 0;
366  // if ($val_rec["time_from_lms"] == "y") {
367  // $time = (int)$val_rec["total_time_sec"];
368  // } else {
369  $time = (int) $val_rec["sco_total_time_sec"];
370  // }
371 
372  // get learning time for old ILIAS-Versions
373  if ($time == 0) {
374  $sco_set = $ilDB->queryF(
375  '
376  SELECT sco_id, rvalue FROM scorm_tracking
377  WHERE obj_id = %s
378  AND user_id = %s
379  AND lvalue = %s
380  AND sco_id <> %s',
381  array('integer','integer','text','integer'),
382  array($a_obj_id,$a_user_id, 'cmi.core.total_time',0)
383  );
384 
385  while ($sco_rec = $ilDB->fetchAssoc($sco_set)) {
386  $tarr = explode(":", $sco_rec["rvalue"]);
387  $sec = (int) $tarr[2] + (int) $tarr[1] * 60 +
388  (int) substr($tarr[0], strlen($tarr[0]) - 3) * 60 * 60;
389  $time += $sec;
390  }
391  }
392 
393  include_once("./Services/Tracking/classes/class.ilChangeEvent.php");
394  ilChangeEvent::_recordReadEvent($a_type, $a_ref_id, $a_obj_id, $a_user_id, false, $attempts, $time);
395  }
396 
397  public static function _insertTrackData($a_sahs_id, $a_lval, $a_rval, $a_obj_id)
398  {
399  global $DIC;
400  $ilDB = $DIC['ilDB'];
401  $ilUser = $DIC['ilUser'];
402 
403  $ilDB->insert('scorm_tracking', array(
404  'obj_id' => array('integer', $a_obj_id),
405  'user_id' => array('integer', $ilUser->getId()),
406  'sco_id' => array('integer', $a_sahs_id),
407  'lvalue' => array('text', $a_lval),
408  'rvalue' => array('clob', $a_rval),
409  'c_timestamp' => array('timestamp', ilUtil::now())
410  ));
411 
412  if ($a_lval == "cmi.core.lesson_status") {
413  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
414  ilLPStatusWrapper::_updateStatus($a_obj_id, $ilUser->getId());
415  }
416  }
417 
418 
425  public static function _getInProgress($scorm_item_id, $a_obj_id, $a_blocked_user_ids = null)
426  {
427  global $DIC;
428  $ilDB = $DIC['ilDB'];
429 
430  if (is_array($scorm_item_id)) {
431  $in = $ilDB->in('sco_id', $scorm_item_id, false, 'integer');
432 
433  $res = $ilDB->queryF(
434  'SELECT user_id,sco_id FROM scorm_tracking
435  WHERE ' . $in . '
436  AND obj_id = %s
437  GROUP BY user_id, sco_id',
438  array('integer'),
439  array($a_obj_id)
440  );
441  } else {
442  $res = $ilDB->queryF(
443  'SELECT user_id,sco_id FROM scorm_tracking
444  WHERE sco_id = %s
445  AND obj_id = %s',
446  array('integer','integer'),
447  array($scorm_item_id,$a_obj_id)
448  );
449  }
450 
451  $in_progress = array();
452 
453  while ($row = $ilDB->fetchObject($res)) {
454  // #15061 - see _getProgressInfo()
455  if (!($a_blocked_user_ids &&
456  is_array($a_blocked_user_ids[$row->sco_id]) &&
457  in_array($row->user_id, $a_blocked_user_ids[$row->sco_id]))) {
458  $in_progress[$row->sco_id][] = $row->user_id;
459  }
460  }
461  return $in_progress;
462  }
463 
470  public static function _getCompleted($scorm_item_id, $a_obj_id)
471  {
472  global $DIC;
473  $ilDB = $DIC['ilDB'];
474 
475  if (is_array($scorm_item_id)) {
476  $in = $ilDB->in('sco_id', $scorm_item_id, false, 'integer');
477 
478  $res = $ilDB->queryF(
479  'SELECT DISTINCT(user_id) FROM scorm_tracking
480  WHERE ' . $in . '
481  AND obj_id = %s
482  AND lvalue = %s
483  AND (' . $ilDB->like('rvalue', 'clob', 'completed') . ' OR ' . $ilDB->like('rvalue', 'clob', 'passed') . ')',
484  array('integer','text'),
485  array($a_obj_id,'cmi.core.lesson_status')
486  );
487  } else {
488  $res = $ilDB->queryF(
489  'SELECT DISTINCT(user_id) FROM scorm_tracking
490  WHERE sco_id = %s
491  AND obj_id = %s
492  AND lvalue = %s
493  AND (' . $ilDB->like('rvalue', 'clob', 'completed') . ' OR ' . $ilDB->like('rvalue', 'clob', 'passed') . ')',
494  array('integer','integer','text'),
495  array($scorm_item_id,$a_obj_id,'cmi.core.lesson_status')
496  );
497  }
498 
499  while ($row = $ilDB->fetchObject($res)) {
500  $user_ids[] = $row->user_id;
501  }
502  return $user_ids ? $user_ids : array();
503  }
504 
505  public static function _getCollectionStatus($a_scos, $a_obj_id, $a_user_id)
506  {
507  global $DIC;
508  $ilDB = $DIC['ilDB'];
509 
510 
511  $status = "not_attempted";
512 
513  if (is_array($a_scos)) {
514  $in = $ilDB->in('sco_id', $a_scos, false, 'integer');
515 
516  $res = $ilDB->queryF(
517  'SELECT sco_id, rvalue FROM scorm_tracking
518  WHERE ' . $in . '
519  AND obj_id = %s
520  AND lvalue = %s
521  AND user_id = %s',
522  array('integer','text', 'integer'),
523  array($a_obj_id,'cmi.core.lesson_status', $a_user_id)
524  );
525 
526  $cnt = 0;
527  $completed = true;
528  $failed = false;
529  while ($rec = $ilDB->fetchAssoc($res)) {
530  if ($rec["rvalue"] == "failed") {
531  $failed = true;
532  }
533  if ($rec["rvalue"] != "completed" && $rec["rvalue"] != "passed") {
534  $completed = false;
535  }
536  $cnt++;
537  }
538  if ($cnt > 0) {
539  $status = "in_progress";
540  }
541  if ($completed && $cnt == count($a_scos)) {
542  $status = "completed";
543  }
544  if ($failed) {
545  $status = "failed";
546  }
547  }
548  return $status;
549  }
550 
551 
552  public static function _countCompleted($a_scos, $a_obj_id, $a_user_id)
553  {
554  global $DIC;
555  $ilDB = $DIC['ilDB'];
556 
557  if (is_array($a_scos)) {
558  $in = $ilDB->in('sco_id', $a_scos, false, 'integer');
559 
560  $res = $ilDB->queryF(
561  'SELECT sco_id, rvalue FROM scorm_tracking
562  WHERE ' . $in . '
563  AND obj_id = %s
564  AND lvalue = %s
565  AND user_id = %s',
566  array('integer','text', 'integer'),
567  array($a_obj_id,'cmi.core.lesson_status', $a_user_id)
568  );
569 
570  $cnt = 0;
571  while ($rec = $ilDB->fetchAssoc($res)) {
572  if ($rec["rvalue"] == "completed" || $rec["rvalue"] == "passed") {
573  $cnt++;
574  }
575  }
576  }
577  return $cnt;
578  }
579  //not correct because of assets!
586  public static function lookupLastAccessTimes($a_obj_id)
587  {
588  global $DIC;
589  $ilDB = $DIC['ilDB'];
590 
591  $query = 'SELECT user_id, MAX(c_timestamp) tst ' .
592  'FROM scorm_tracking ' .
593  'WHERE obj_id = ' . $ilDB->quote($a_obj_id, 'integer') . ' ' .
594  'GROUP BY user_id';
595  $res = $ilDB->query($query);
596 
597  $users = array();
598  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
599  $users[$row->user_id] = $row->tst;
600  }
601  return $users;
602  }
603 
604 
610  public static function _getTrackedUsers($a_obj_id)
611  {
612  global $DIC;
613  $ilDB = $DIC['ilDB'];
614  $ilLog = $DIC['ilLog'];
615 
616  $res = $ilDB->queryF(
617  'SELECT DISTINCT user_id FROM scorm_tracking
618  WHERE obj_id = %s
619  AND lvalue = %s',
620  array('integer','text'),
621  array($a_obj_id,'cmi.core.lesson_status')
622  );
623 
624  $users = array();
625  while ($row = $ilDB->fetchAssoc($res)) {
626  $users[] = $row["user_id"];
627  }
628  return $users;
629  }
630 
637  public static function _getFailed($scorm_item_id, $a_obj_id)
638  {
639  global $DIC;
640  $ilDB = $DIC['ilDB'];
641 
642  if (is_array($scorm_item_id)) {
643  $in = $ilDB->in('sco_id', $scorm_item_id, false, 'integer');
644 
645  $res = $ilDB->queryF(
646  '
647  SELECT DISTINCT(user_id) FROM scorm_tracking
648  WHERE ' . $in . '
649  AND obj_id = %s
650  AND lvalue = %s
651  AND ' . $ilDB->like('rvalue', 'clob', 'failed') . ' ',
652  array('integer','text'),
653  array($a_obj_id,'cmi.core.lesson_status')
654  );
655  } else {
656  $res = $ilDB->queryF(
657  '
658  SELECT DISTINCT(user_id) FROM scorm_tracking
659  WHERE sco_id = %s
660  AND obj_id = %s
661  AND lvalue = %s
662  AND ' . $ilDB->like('rvalue', 'clob', 'failed') . ' ',
663  array('integer','integer','text'),
664  array($scorm_item_id,$a_obj_id,'cmi.core.lesson_status')
665  );
666  }
667 
668  while ($row = $ilDB->fetchObject($res)) {
669  $user_ids[] = $row->user_id;
670  }
671  return $user_ids ? $user_ids : array();
672  }
673 
680  public static function _getCountCompletedPerUser($a_scorm_item_ids, $a_obj_id)
681  {
682  global $DIC;
683  $ilDB = $DIC['ilDB'];
684 
685  $in = $ilDB->in('sco_id', $a_scorm_item_ids, false, 'integer');
686 
687  // Why does this query use a like search against "passed" and "failed"
688  //because it's clob and we support Oracle
689  $res = $ilDB->queryF(
690  '
691  SELECT user_id, COUNT(user_id) completed FROM scorm_tracking
692  WHERE ' . $in . '
693  AND obj_id = %s
694  AND lvalue = %s
695  AND (' . $ilDB->like('rvalue', 'clob', 'completed') . ' OR ' . $ilDB->like('rvalue', 'clob', 'passed') . ')
696  GROUP BY user_id',
697  array('integer', 'text'),
698  array($a_obj_id, 'cmi.core.lesson_status')
699  );
700  while ($row = $ilDB->fetchObject($res)) {
701  $users[$row->user_id] = $row->completed;
702  }
703  return $users ? $users : array();
704  }
705 
712  public static function _getProgressInfo($sco_item_ids, $a_obj_id)
713  {
714  global $DIC;
715  $ilDB = $DIC['ilDB'];
716 
717  $in = $ilDB->in('sco_id', $sco_item_ids, false, 'integer');
718 
719  $res = $ilDB->queryF(
720  '
721  SELECT * FROM scorm_tracking
722  WHERE ' . $in . '
723  AND obj_id = %s
724  AND lvalue = %s ',
725  array('integer','text'),
726  array($a_obj_id,'cmi.core.lesson_status')
727  );
728 
729  $info['completed'] = array();
730  $info['failed'] = array();
731 
732  $user_ids = array();
733  while ($row = $ilDB->fetchObject($res)) {
734  switch ($row->rvalue) {
735  case 'completed':
736  case 'passed':
737  $info['completed'][$row->sco_id][] = $row->user_id;
738  $user_ids[$row->sco_id][] = $row->user_id;
739  break;
740 
741  case 'failed':
742  $info['failed'][$row->sco_id][] = $row->user_id;
743  $user_ids[$row->sco_id][] = $row->user_id;
744  break;
745  }
746  }
747  $info['in_progress'] = ilObjSCORMTracking::_getInProgress($sco_item_ids, $a_obj_id, $user_ids);
748 
749  return $info;
750  }
751 
752  public static function scorm12PlayerUnload()
753  {
754  global $DIC;
755  $ilUser = $DIC['ilUser'];
756  $ilDB = $DIC['ilDB'];
757  $user_id = (int) $_GET["p"];
758  $ref_id = (int) $_GET["ref_id"];
759  $obj_id = (int) $_GET["package_id"];
760  if ($obj_id <= 1) {
761  $GLOBALS['DIC']['ilLog']->write(__METHOD__ . ' no valid obj_id');
762  } else {
763  $last_visited = (string) $_GET['last_visited'];
764  $endDate = date('Y-m-d H:i:s', mktime(date('H'), date('i') + 5, date('s'), date('m'), date('d'), date('Y')));
765  $ilDB->manipulateF(
766  'UPDATE sahs_user
767  SET last_visited = %s, hash_end =%s, last_access = %s
768  WHERE obj_id = %s AND user_id = %s',
769  array('text', 'timestamp', 'timestamp', 'integer', 'integer'),
770  array($last_visited, $endDate, date('Y-m-d H:i:s'), $obj_id, $user_id)
771  );
772  // update time and numbers of attempts in change event
773  //NOTE: here it is correct (not count of commit with changed values); be careful to performance issues
774  ilObjSCORMTracking::_syncReadEvent($obj_id, $user_id, "sahs", $ref_id);
775  }
776  header('Content-Type: text/plain; charset=UTF-8');
777  print("");
778  }
779 
780  public static function checkIfAllowed($packageId, $userId, $hash)
781  {
782  global $DIC;
783  $ilDB = $DIC['ilDB'];
784  $res = $ilDB->queryF(
785  'select hash from sahs_user where obj_id=%s AND user_id=%s AND hash_end>%s',
786  array('integer','integer','timestamp'),
787  array($packageId,$userId,date('Y-m-d H:i:s'))
788  );
789  $rowtmp = $ilDB->fetchAssoc($res);
790  if ($rowtmp['hash'] == $hash) {
791  return;
792  } else {
793  die("not allowed");
794  }
795  }
796 } // END class.ilObjSCORMTracking
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 storeJsApiCmi($user_id, $obj_id, $data)
global $DIC
Definition: saml.php:7
static _getCompleted($scorm_item_id, $a_obj_id)
like necessary because of Oracle
$_GET["client_id"]
static _updateStatus($a_obj_id, $a_usr_id, $a_obj=null, $a_percentage=false, $a_force_raise=false)
Update status.
Class ilObjSCORMTracking.
static _getTrackedUsers($a_obj_id)
Get all tracked users.
static now()
Return current timestamp in Y-m-d H:i:s format.
static _countCompleted($a_scos, $a_obj_id, $a_user_id)
$time
Definition: cron.php:21
$a_type
Definition: workflow.php:92
static _getCountCompletedPerUser($a_scorm_item_ids, $a_obj_id)
Get users who have status completed or passed.
static _lookupPresentableItems($a_slm_id)
Count number of presentable SCOs/Assets of SCORM learning module.
foreach($_POST as $key=> $value) $res
static _lookupObjId($a_id)
static _getFailed($scorm_item_id, $a_obj_id)
like necessary because of Oracle
$ilUser
Definition: imgupload.php:18
$query
static _syncReadEvent($a_obj_id, $a_user_id, $a_type, $a_ref_id)
Synch read event table.
$failed
Definition: Utf8Test.php:85
$users
Definition: authpage.php:44
$row
static _insertTrackData($a_sahs_id, $a_lval, $a_rval, $a_obj_id)
if(php_sapi_name() !='cli') $in
Definition: Utf8Test.php:37
update($pash, $contents, Config $config)
static handleOutcomeWithoutLP($a_obj_id, $a_usr_id, $a_percentage)
static lookupLastAccessTimes($a_obj_id)
Lookup last acccess time for all users of a scorm module ilDB $ilDB.
static writeStatus($a_obj_id, $a_user_id, $a_status, $a_percentage=false, $a_force_per=false)
Write status for user and object.
static _getInProgress($scorm_item_id, $a_obj_id, $a_blocked_user_ids=null)
static _getCollectionStatus($a_scos, $a_obj_id, $a_user_id)
static _getProgressInfo($sco_item_ids, $a_obj_id)
Get info about.
global $ilDB
$i
Definition: disco.tpl.php:19
$packageId
static syncGlobalStatus($userId, $packageId, $data, $new_global_status)
static checkIfAllowed($packageId, $userId, $hash)
$info
Definition: index.php:5
store($obj_id=0, $sahs_id=0, $extractData=1)
$key
Definition: croninfo.php:18
$_POST["username"]
$GLOBALS['JPEG_Segment_Names']
Global Variable: XMP_tag_captions.
$data
Definition: bench.php:6