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