ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
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  $obj_id = (int)$_GET["package_id"];
177  $in = file_get_contents("php://input");
178  // $ilLog->write($in);
179  $data = json_decode($in);
180  $user_id = (int)$data->p;
181 
182  header('Content-Type: text/plain; charset=UTF-8');
183 
184  $rval=self::storeJsApiCmi($user_id,$obj_id,$data);
185  if($rval!=true) {
186  print("storeJsApiCmi failed");
187  } else {
188  $rval=self::syncGlobalStatus($user_id, $obj_id, $data, $data->now_global_status);
189  if($rval!=true) print("syncGlobalStatus failed");
190  }
191  if($rval==true) print("ok");
192  }
193 
194  function storeJsApiCmi($user_id, $obj_id, $data) {
195  global $ilLog, $ilDB;
196 
197  $b_updateStatus=false;
198 
199  $b_messageLog=false;
200  if ($ilLog->current_log_level == 30)
201  $b_messageLog=true;
202 
203  if ($b_messageLog)
204  $ilLog->write("ScormAicc: CALLING SCORM storeJsApi() ".$_POST);
205 
206 
207  $aa_data = array();
208  // if (is_array($_POST["S"])) {
209  // foreach($_POST["S"] as $key => $value) {
210  // $aa_data[] = array("sco_id" => $value, "left" => $_POST["L"][$key], "right" => $_POST["R"][$key]);
211  // }
212  // }
213  for ($i=0;$i<count($data->cmi);$i++) {
214  $aa_data[] = array("sco_id" => (int) $data->cmi[$i][0], "left" => $data->cmi[$i][1], "right" => $data->cmi[$i][2]);
215 // $aa_data[] = array("sco_id" => (int) $data->cmi[$i][0], "left" => $data->cmi[$i][1], "right" => rawurldecode($data->cmi[$i][2]));
216  }
217 
218  if ($obj_id <= 1) {
219  $ilLog->write("ScormAicc: storeJsApi: Error: No valid obj_id given.");
220  }
221  else {
222  foreach($aa_data as $a_data) {
223  $set = $ilDB->queryF('
224  SELECT rvalue FROM scorm_tracking
225  WHERE user_id = %s
226  AND sco_id = %s
227  AND lvalue = %s
228  AND obj_id = %s',
229  array('integer','integer','text','integer'),
230  array($user_id,$a_data["sco_id"],$a_data["left"],$obj_id));
231  if ($rec = $ilDB->fetchAssoc($set)) {
232  if ($a_data["left"] == 'cmi.core.lesson_status' && $a_data["right"] != $rec["rvalue"]) {
233  $b_updateStatus = true;
234  }
235  $ilDB->update('scorm_tracking',
236  array(
237  'rvalue' => array('clob', $a_data["right"]),
238  'c_timestamp' => array('timestamp', ilUtil::now())
239  ),
240  array(
241  'user_id' => array('integer', $user_id),
242  'sco_id' => array('integer', $a_data["sco_id"]),
243  'lvalue' => array('text', $a_data["left"]),
244  'obj_id' => array('integer', $obj_id)
245  )
246  );
247  if ($b_messageLog) {
248  $ilLog->write("ScormAicc: storeJsApi Updated - L:".$a_data["left"].",R:".
249  $a_data["right"]." for obj_id:".$obj_id.",sco_id:".$a_data["sco_id"].",user_id:".$user_id);
250  }
251  }
252  else {
253  if ($a_data["left"] == 'cmi.core.lesson_status') {
254  $b_updateStatus = true;
255  }
256  $ilDB->insert('scorm_tracking', array(
257  'obj_id' => array('integer', $obj_id),
258  'user_id' => array('integer', $user_id),
259  'sco_id' => array('integer', $a_data["sco_id"]),
260  'lvalue' => array('text', $a_data["left"]),
261  'rvalue' => array('clob', $a_data["right"]),
262  'c_timestamp' => array('timestamp', ilUtil::now())
263  ));
264  if ($b_messageLog) {
265  $ilLog->write("ScormAicc: storeJsApi Inserted - L:".$a_data["left"].",R:".
266  $a_data["right"]." for obj_id:".$obj_id.",sco_id:".$$a_data["sco_id"].",user_id:".$user_id);
267  }
268  }
269  }
270  }
271 
272  // update status
273  // if ($b_updateStatus == true) {
274  // include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
275  // ilLPStatusWrapper::_updateStatus($obj_id, $user_id);
276  // }
277 
278  return true;
279  }
280 
281 //erase later see ilSCORM2004StoreData
282  public function syncGlobalStatus($userId, $packageId, $data, $new_global_status) {
283 
284  global $ilDB, $ilLog;
285  $saved_global_status=$data->saved_global_status;
286  $ilLog->write("saved_global_status=".$saved_global_status);
287 
288  //last_visited!
289 
290  // get attempts
291  if (!$data->packageAttempts) {
292  $val_set = $ilDB->queryF('SELECT package_attempts FROM sahs_user WHERE obj_id = %s AND user_id = %s',
293  array('integer','integer'), array($packageId,$userId));
294  $val_rec = $ilDB->fetchAssoc($val_set);
295  $attempts = $val_rec["package_attempts"];
296  } else {
297  $attempts=$data->packageAttempts;
298  }
299  if ($attempts == null) $attempts = 1;
300 
301  //update percentage_completed, sco_total_time_sec,status in sahs_user
302  $totalTime=(int)$data->totalTimeCentisec;
303  $totalTime=round($totalTime/100);
304  $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',
305  array('integer', 'integer', 'integer', 'integer', 'integer', 'integer'),
306  array($totalTime, $new_global_status, $data->percentageCompleted, $attempts, $packageId, $userId));
307 
308 // self::ensureObjectDataCacheExistence();
309  global $ilObjDataCache;
310  include_once("./Services/Tracking/classes/class.ilChangeEvent.php");
311  ilChangeEvent::_recordReadEvent("sahs", (int)$_GET['ref_id'],$packageId, $userId, false, $attempts, $totalTime);
312 
313  //end sync access number and time in read event table
314 
315  // update learning progress
316  if ($new_global_status != null) {//could only happen when synchronising from SCORM Offline Player
317  include_once("./Services/Tracking/classes/class.ilObjUserTracking.php");
318  include_once("./Services/Tracking/classes/class.ilLPStatus.php");
319  ilLPStatus::writeStatus($packageId, $userId,$new_global_status,$data->percentageCompleted);
320 
321 // here put code for soap to MaxCMS e.g. when if($saved_global_status != $new_global_status)
322  }
323  return true;
324  }
325 
326 
333  function _syncReadEvent($a_obj_id, $a_user_id, $a_type, $a_ref_id)
334  {
335  global $ilDB, $ilLog;
336  //TODO: use sahs_user in future!! Especially for learningTime!
337  // get attempts
338  $val_set = $ilDB->queryF('SELECT package_attempts FROM sahs_user WHERE obj_id = %s AND user_id = %s',
339  array('integer','integer'),
340  array($a_obj_id,$a_user_id));
341 
342  $val_rec = $ilDB->fetchAssoc($val_set);
343 
344  if ($val_rec["package_attempts"] == null) {
345  $val_rec["package_attempts"]="";
346  }
347  $attempts = $val_rec["package_attempts"];
348 
349  // get learning time
350  $sco_set = $ilDB->queryF('
351  SELECT sco_id, rvalue FROM scorm_tracking
352  WHERE obj_id = %s
353  AND user_id = %s
354  AND lvalue = %s
355  AND sco_id <> %s',
356  array('integer','integer','text','integer'),
357  array($a_obj_id,$a_user_id, 'cmi.core.total_time',0));
358 
359  $time = 0;
360  while($sco_rec = $ilDB->fetchAssoc($sco_set))
361  {
362  $tarr = explode(":", $sco_rec["rvalue"]);
363  $sec = (int) $tarr[2] + (int) $tarr[1] * 60 +
364  (int) substr($tarr[0], strlen($tarr[0]) - 3) * 60 * 60;
365  $time += $sec;
366  }
367 
368  include_once("./Services/Tracking/classes/class.ilChangeEvent.php");
369  ilChangeEvent::_recordReadEvent($a_type, $a_ref_id, $a_obj_id, $a_user_id, false, $attempts, $time);
370  }
371 
372  function _insertTrackData($a_sahs_id, $a_lval, $a_rval, $a_obj_id)
373  {
374  global $ilDB, $ilUser;
375 
376  $ilDB->insert('scorm_tracking', array(
377  'obj_id' => array('integer', $a_obj_id),
378  'user_id' => array('integer', $ilUser->getId()),
379  'sco_id' => array('integer', $a_sahs_id),
380  'lvalue' => array('text', $a_lval),
381  'rvalue' => array('clob', $a_rval),
382  'c_timestamp' => array('timestamp', ilUtil::now())
383  ));
384 
385  if ($a_lval == "cmi.core.lesson_status")
386  {
387  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
388  ilLPStatusWrapper::_updateStatus($a_obj_id, $ilUser->getId());
389  }
390  }
391 
392 
399  public static function _getInProgress($scorm_item_id,$a_obj_id,$a_blocked_user_ids = null)
400  {
401  global $ilDB;
402 
403  if(is_array($scorm_item_id))
404  {
405  $in = $ilDB->in('sco_id', $scorm_item_id, false, 'integer');
406 
407  $res = $ilDB->queryF('SELECT user_id,sco_id FROM scorm_tracking
408  WHERE '.$in.'
409  AND obj_id = %s
410  GROUP BY user_id, sco_id',
411  array('integer'),array($a_obj_id));
412 
413  }
414  else
415  {
416  $res = $ilDB->queryF('SELECT user_id,sco_id FROM scorm_tracking
417  WHERE sco_id = %s
418  AND obj_id = %s',
419  array('integer','integer'),array($scorm_item_id,$a_obj_id)
420  );
421  }
422 
423  $in_progress = array();
424 
425  while($row = $ilDB->fetchObject($res))
426  {
427  // #15061 - see _getProgressInfo()
428  if(!($a_blocked_user_ids &&
429  is_array($a_blocked_user_ids[$row->sco_id]) &&
430  in_array($row->user_id, $a_blocked_user_ids[$row->sco_id])))
431  {
432  $in_progress[$row->sco_id][] = $row->user_id;
433  }
434  }
435  return $in_progress;
436  }
437 
444  public static function _getCompleted($scorm_item_id,$a_obj_id)
445  {
446  global $ilDB;
447 
448  if(is_array($scorm_item_id))
449  {
450  $in = $ilDB->in('sco_id', $scorm_item_id, false, 'integer');
451 
452  $res = $ilDB->queryF('SELECT DISTINCT(user_id) FROM scorm_tracking
453  WHERE '.$in.'
454  AND obj_id = %s
455  AND lvalue = %s
456  AND ('.$ilDB->like('rvalue', 'clob', 'completed').' OR '.$ilDB->like('rvalue', 'clob', 'passed').')',
457  array('integer','text'),
458  array($a_obj_id,'cmi.core.lesson_status'));
459  }
460  else
461  {
462  $res = $ilDB->queryF('SELECT DISTINCT(user_id) FROM scorm_tracking
463  WHERE sco_id = %s
464  AND obj_id = %s
465  AND lvalue = %s
466  AND ('.$ilDB->like('rvalue', 'clob', 'completed').' OR '.$ilDB->like('rvalue', 'clob', 'passed').')',
467  array('integer','integer','text'),
468  array($scorm_item_id,$a_obj_id,'cmi.core.lesson_status'));
469  }
470 
471  while($row = $ilDB->fetchObject($res))
472  {
473  $user_ids[] = $row->user_id;
474  }
475  return $user_ids ? $user_ids : array();
476  }
477 
478  public static function _getCollectionStatus($a_scos, $a_obj_id, $a_user_id)
479  {
480  global $ilDB;
481 
482 
483  $status = "not_attempted";
484 
485  if (is_array($a_scos))
486  {
487  $in = $ilDB->in('sco_id', $a_scos, false, 'integer');
488 
489  $res = $ilDB->queryF('SELECT sco_id, rvalue FROM scorm_tracking
490  WHERE '.$in.'
491  AND obj_id = %s
492  AND lvalue = %s
493  AND user_id = %s',
494  array('integer','text', 'integer'),
495  array($a_obj_id,'cmi.core.lesson_status', $a_user_id));
496 
497  $cnt = 0;
498  $completed = true;
499  $failed = false;
500  while ($rec = $ilDB->fetchAssoc($res))
501  {
502  if ($rec["rvalue"] == "failed")
503  {
504  $failed = true;
505  }
506  if ($rec["rvalue"] != "completed" && $rec["rvalue"] != "passed")
507  {
508  $completed = false;
509  }
510  $cnt++;
511  }
512  if ($cnt > 0)
513  {
514  $status = "in_progress";
515  }
516  if ($completed && $cnt == count($a_scos))
517  {
518  $status = "completed";
519  }
520  if ($failed)
521  {
522  $status = "failed";
523  }
524 
525  }
526  return $status;
527  }
528 
529 
530  public static function _countCompleted($a_scos, $a_obj_id, $a_user_id)
531  {
532  global $ilDB;
533 
534  if (is_array($a_scos))
535  {
536  $in = $ilDB->in('sco_id', $a_scos, false, 'integer');
537 
538  $res = $ilDB->queryF('SELECT sco_id, rvalue FROM scorm_tracking
539  WHERE '.$in.'
540  AND obj_id = %s
541  AND lvalue = %s
542  AND user_id = %s',
543  array('integer','text', 'integer'),
544  array($a_obj_id,'cmi.core.lesson_status', $a_user_id));
545 
546  $cnt = 0;
547  while ($rec = $ilDB->fetchAssoc($res))
548  {
549  if ($rec["rvalue"] == "completed" || $rec["rvalue"] == "passed")
550  {
551  $cnt++;
552  }
553  }
554  }
555  return $cnt;
556  }
557 //not correct because of assets!
564  public static function lookupLastAccessTimes($a_obj_id)
565  {
566  global $ilDB;
567 
568  $query = 'SELECT user_id, MAX(c_timestamp) tst '.
569  'FROM scorm_tracking '.
570  'WHERE obj_id = '.$ilDB->quote($a_obj_id,'integer').' '.
571  'GROUP BY user_id';
572  $res = $ilDB->query($query);
573 
574  $users = array();
575  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
576  {
577  $users[$row->user_id] = $row->tst;
578  }
579  return $users;
580  }
581 
582 
588  function _getTrackedUsers($a_obj_id)
589  {
590  global $ilDB, $ilLog;
591 
592  $res = $ilDB->queryF('SELECT DISTINCT user_id FROM scorm_tracking
593  WHERE obj_id = %s
594  AND lvalue = %s',
595  array('integer','text'),
596  array($a_obj_id,'cmi.core.lesson_status'));
597 
598  $users = array();
599  while ($row = $ilDB->fetchAssoc($res))
600  {
601  $users[] = $row["user_id"];
602  }
603  return $users;
604  }
605 
612  function _getFailed($scorm_item_id,$a_obj_id)
613  {
614  global $ilDB;
615 
616  if(is_array($scorm_item_id))
617  {
618  $in = $ilDB->in('sco_id', $scorm_item_id, false, 'integer');
619 
620  $res = $ilDB->queryF('
621  SELECT DISTINCT(user_id) FROM scorm_tracking
622  WHERE '.$in.'
623  AND obj_id = %s
624  AND lvalue = %s
625  AND '.$ilDB->like('rvalue', 'clob', 'failed').' ',
626  array('integer','text'),
627  array($a_obj_id,'cmi.core.lesson_status'));
628  }
629  else
630  {
631 
632  $res = $ilDB->queryF('
633  SELECT DISTINCT(user_id) FROM scorm_tracking
634  WHERE sco_id = %s
635  AND obj_id = %s
636  AND lvalue = %s
637  AND '.$ilDB->like('rvalue', 'clob', 'failed').' ',
638  array('integer','integer','text'),
639  array($scorm_item_id,$a_obj_id,'cmi.core.lesson_status'));
640  }
641 
642  while($row = $ilDB->fetchObject($res))
643  {
644  $user_ids[] = $row->user_id;
645  }
646  return $user_ids ? $user_ids : array();
647  }
648 
655  public static function _getCountCompletedPerUser($a_scorm_item_ids,$a_obj_id)
656  {
657  global $ilDB;
658 
659  $in = $ilDB->in('sco_id', $a_scorm_item_ids, false, 'integer');
660 
661  // Why does this query use a like search against "passed" and "failed"
662  //because it's clob and we support Oracle
663  $res = $ilDB->queryF('
664  SELECT user_id, COUNT(user_id) completed FROM scorm_tracking
665  WHERE '.$in.'
666  AND obj_id = %s
667  AND lvalue = %s
668  AND ('.$ilDB->like('rvalue', 'clob', 'completed').' OR '.$ilDB->like('rvalue', 'clob', 'passed').')
669  GROUP BY user_id',
670  array('integer', 'text'),
671  array($a_obj_id, 'cmi.core.lesson_status')
672  );
673  while($row = $ilDB->fetchObject($res))
674  {
675  $users[$row->user_id] = $row->completed;
676  }
677  return $users ? $users : array();
678  }
679 
686  public static function _getProgressInfo($sco_item_ids,$a_obj_id)
687  {
688  global $ilDB;
689 
690  $in = $ilDB->in('sco_id', $sco_item_ids, false, 'integer');
691 
692  $res = $ilDB->queryF('
693  SELECT * FROM scorm_tracking
694  WHERE '.$in.'
695  AND obj_id = %s
696  AND lvalue = %s ',
697  array('integer','text'),
698  array($a_obj_id,'cmi.core.lesson_status'));
699 
700  $info['completed'] = array();
701  $info['failed'] = array();
702 
703  $user_ids = array();
704  while($row = $ilDB->fetchObject($res))
705  {
706  switch($row->rvalue)
707  {
708  case 'completed':
709  case 'passed':
710  $info['completed'][$row->sco_id][] = $row->user_id;
711  $user_ids[$row->sco_id][] = $row->user_id;
712  break;
713 
714  case 'failed':
715  $info['failed'][$row->sco_id][] = $row->user_id;
716  $user_ids[$row->sco_id][] = $row->user_id;
717  break;
718  }
719  }
720  $info['in_progress'] = ilObjSCORMTracking::_getInProgress($sco_item_ids,$a_obj_id,$user_ids);
721 
722  return $info;
723  }
724 
726  {
727  global $ilUser, $ilDB;
728 
729  //$user_id = $ilUser->getID();
730  $user_id = (int)$_GET["p"];
731  $ref_id = (int)$_GET["ref_id"];
732  // $obj_id = ilObject::_lookupObjId($ref_id);
733  $obj_id = (int)$_GET["package_id"];
734  if ($obj_id <= 1){
735  $GLOBALS['ilLog']->write(__METHOD__.' no valid obj_id');
736  } else {
737  $last_visited=$_POST['last_visited'];
738  $endDate = date('Y-m-d H:i:s', mktime(date('H'), date('i')+5, date('s'), date('m'), date('d'), date('Y')));
739  $ilDB->manipulateF('UPDATE sahs_user
740  SET last_visited = %s, hash_end =%s, last_access = %s
741  WHERE obj_id = %s AND user_id = %s',
742  array('text', 'timestamp', 'timestamp', 'integer', 'integer'),
743  array($last_visited, $endDate, date('Y-m-d H:i:s'), $obj_id, $user_id)
744  );
745  // update time and numbers of attempts in change event
746  //NOTE: here it is correct (not count of commit with changed values); be careful to performance issues
747  ilObjSCORMTracking::_syncReadEvent($obj_id, $user_id, "sahs", $ref_id);
748  }
749  header('Content-Type: text/plain; charset=UTF-8');
750  print("");
751  }
752 
753  function checkIfAllowed($packageId,$userId,$hash){
754  global $ilDB;
755  $res = $ilDB->queryF('select hash from sahs_user where obj_id=%s AND user_id=%s AND hash_end>%s',
756  array('integer','integer','timestamp'),
757  array($packageId,$userId,date('Y-m-d H:i:s'))
758  );
759  $rowtmp=$ilDB->fetchAssoc($res);
760  if ($rowtmp['hash']==$hash) return;
761  else die("not allowed");
762  }
763 
764 } // END class.ilObjSCORMTracking
765 ?>
syncGlobalStatus($userId, $packageId, $data, $new_global_status)
$_POST['username']
Definition: cron.php:12
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 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 _getCountCompletedPerUser($a_scorm_item_ids, $a_obj_id)
Get users who have status completed or passed.
$info
Definition: example_052.php:80
$data
static _lookupObjId($a_id)
checkIfAllowed($packageId, $userId, $hash)
$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.
$GLOBALS['PHPCAS_CLIENT']
This global variable is used by the interface class phpCAS.
Definition: CAS.php:276
store($obj_id=0, $sahs_id=0, $extractData=1)