ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilSCORM2004Tracking.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 
13 {
19  {
20  }
21 
22  function _getInProgress($scorm_item_id,$a_obj_id)
23  {
24 
25 die("Not Implemented: ilSCORM2004Tracking_getInProgress");
26 /*
27  global $ilDB;
28 
29  if(is_array($scorm_item_id))
30  {
31  $where = "WHERE sco_id IN(";
32  $where .= implode(",",ilUtil::quoteArray($scorm_item_id));
33  $where .= ") ";
34  $where .= ("AND obj_id = ".$ilDB->quote($a_obj_id)." ");
35 
36  }
37  else
38  {
39  $where = "WHERE sco_id = ".$ilDB->quote($scorm_item_id)." ";
40  $where .= ("AND obj_id = ".$ilDB->quote($a_obj_id)." ");
41  }
42 
43 
44  $query = "SELECT user_id,sco_id FROM scorm_tracking ".
45  $where.
46  "GROUP BY user_id, sco_id";
47 
48 
49  $res = $ilDB->query($query);
50  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
51  {
52  $in_progress[$row->sco_id][] = $row->user_id;
53  }
54  return is_array($in_progress) ? $in_progress : array();
55 */
56  }
57 
58  function _getCompleted($scorm_item_id,$a_obj_id)
59  {
60  global $ilDB;
61 
62 die("Not Implemented: ilSCORM2004Tracking_getCompleted");
63 /*
64  if(is_array($scorm_item_id))
65  {
66  $where = "WHERE sco_id IN(".implode(",",ilUtil::quoteArray($scorm_item_id)).") ";
67  }
68  else
69  {
70  $where = "sco_id = ".$ilDB->quote($scorm_item_id)." ";
71  }
72 
73  $query = "SELECT DISTINCT(user_id) FROM scorm_tracking ".
74  $where.
75  "AND obj_id = ".$ilDB->quote($a_obj_id)." ".
76  "AND lvalue = 'cmi.core.lesson_status' ".
77  "AND ( rvalue = 'completed' ".
78  "OR rvalue = 'passed')";
79  $res = $ilDB->query($query);
80  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
81  {
82  $user_ids[] = $row->user_id;
83  }
84  return $user_ids ? $user_ids : array();
85 */
86  }
87 
88  function _getFailed($scorm_item_id,$a_obj_id)
89  {
90  global $ilDB;
91 
92 die("Not Implemented: ilSCORM2004Tracking_getFailed");
93 /*
94  if(is_array($scorm_item_id))
95  {
96  $where = "WHERE sco_id IN('".implode("','",$scorm_item_id)."') ";
97  }
98  else
99  {
100  $where = "sco_id = '".$scorm_item_id."' ";
101  }
102 
103  $query = "SELECT DISTINCT(user_id) FROM scorm_tracking ".
104  $where.
105  "AND obj_id = '".$a_obj_id."' ".
106  "AND lvalue = 'cmi.core.lesson_status' ".
107  "AND rvalue = 'failed'";
108  $res = $ilDB->query($query);
109  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
110  {
111  $user_ids[] = $row->user_id;
112  }
113  return $user_ids ? $user_ids : array();
114 */
115  }
116 
124  function _getCountCompletedPerUser($a_scorm_item_ids, $a_obj_id, $a_omit_failed = false)
125  {
126  global $ilDB;
127 
128  $in = $ilDB->in('cp_node.cp_node_id', $a_scorm_item_ids, false, 'integer');
129 
130  // #8171: success_status vs. completion status
131  $omit_failed = '';
132  if($a_omit_failed)
133  {
134  $omit_failed = ' AND success_status <> '.$ilDB->quote('failed', 'text');
135  }
136 
137  $res = $ilDB->queryF('
138  SELECT cmi_node.user_id user_id, COUNT(user_id) completed FROM cp_node, cmi_node
139  WHERE '.$in.$omit_failed.'
140  AND cp_node.cp_node_id = cmi_node.cp_node_id
141  AND cp_node.slm_id = %s
142  AND completion_status = %s
143  GROUP BY cmi_node.user_id',
144  array('integer', 'text'),
145  array($a_obj_id, 'completed')
146  );
147  while($row = $ilDB->fetchObject($res))
148  {
149  $users[$row->user_id] = $row->completed;
150  }
151 
152  return $users ? $users : array();
153  }
154 
155 
161  function _getProgressInfo($a_obj_id)
162  {
163  global $ilDB;
164 
165  $res = $ilDB->queryF('
166  SELECT * FROM cmi_gobjective
167  WHERE objective_id = %s
168  AND scope_id = %s',
169  array('text', 'integer'),
170  array('-course_overall_status-', $a_obj_id)
171  );
172 
173  $info['completed'] = array();
174  $info['failed'] = array();
175  $info['in_progress'] = array();
176 
177  while($row = $ilDB->fetchAssoc($res))
178  {
179  if (self::_isCompleted($row["status"], $row["status"]))
180  {
181  $info['completed'][] = $row["user_id"];
182  }
183  if (self::_isInProgress($row["status"], $row["status"]))
184  {
185  $info['in_progress'][] = $row["user_id"];
186  }
187  if (self::_isFailed($row["status"], $row["status"]))
188  {
189  $info['failed'][] = $row["user_id"];
190  }
191  }
192 
193  return $info;
194  }
195 
201  function _getProgressInfoOfUser($a_obj_id, $a_user_id)
202  {
203  global $ilDB, $ilLog;
204 
205  $res = $ilDB->queryF('
206  SELECT * FROM cmi_gobjective
207  WHERE objective_id = %s
208  AND scope_id = %s AND user_id = %s',
209  array('text', 'integer', 'integer'),
210  array('-course_overall_status-', $a_obj_id, $a_user_id)
211  );
212 
213  $status = "not_attempted";
214  if ($row = $ilDB->fetchAssoc($res))
215  {
216  if (self::_isInProgress($row["status"], $row["status"]))
217  {
218  $status = "in_progress";
219  }
220  if (self::_isCompleted($row["status"], $row["status"]))
221  {
222  $status = "completed";
223  }
224  if (self::_isFailed($row["status"], $row["status"]))
225  {
226  $status = "failed";
227  }
228  }
229  return $status;
230  }
231 
237  function _getTrackedUsers($a_obj_id)
238  {
239  global $ilDB, $ilLog;
240 
241  $res = $ilDB->queryF('
242  SELECT DISTINCT user_id FROM cmi_gobjective
243  WHERE objective_id = %s
244  AND scope_id = %s',
245  array('text', 'integer'),
246  array('-course_overall_status-', $a_obj_id)
247  );
248 
249  $users = array();
250  while ($row = $ilDB->fetchAssoc($res))
251  {
252  $users[] = $row["user_id"];
253  }
254  return $users;
255  }
256 
257  function _getItemProgressInfo($a_scorm_item_ids, $a_obj_id, $a_omit_failed = false)
258  {
259  global $ilDB;
260 
261  $in = $ilDB->in('cp_node.cp_node_id', $a_scorm_item_ids, false, 'integer');
262 
263  $res = $ilDB->queryF(
264  'SELECT cp_node.cp_node_id id,
265  cmi_node.user_id user_id,
266  cmi_node.completion_status completion,
267  cmi_node.success_status success
268  FROM cp_node, cmi_node
269  WHERE '.$in.'
270  AND cp_node.cp_node_id = cmi_node.cp_node_id
271  AND cp_node.slm_id = %s',
272  array('integer'),
273  array($a_obj_id)
274  );
275 
276  $info['completed'] = array();
277  $info['failed'] = array();
278  $info['in_progress'] = array();
279 
280  while($row = $ilDB->fetchAssoc($res))
281  {
282  // if any data available, set in progress.
283  $info['in_progress'][$row["id"]][] = $row["user_id"];
284  if ($row["completion"] == "completed" || $row["success"] == "passed")
285  {
286  // #8171: success_status vs. completion status
287  if(!$a_omit_failed || $row["success"] != "failed")
288  {
289  $info['completed'][$row["id"]][] = $row["user_id"];
290  }
291  }
292  if ($row["success"] == "failed")
293  {
294  $info['failed'][$row["id"]][] = $row["user_id"];
295  }
296  }
297  return $info;
298  }
299 
300  public static function _getCollectionStatus($a_scos, $a_obj_id, $a_user_id)
301  {
302  global $ilDB;
303 
304  $status = "not_attempted";
305 
306  if (is_array($a_scos))
307  {
308  $in = $ilDB->in('cp_node.cp_node_id', $a_scos, false, 'integer');
309 
310  $res = $ilDB->queryF(
311  'SELECT cp_node.cp_node_id id,
312  cmi_node.completion_status completion,
313  cmi_node.success_status success
314  FROM cp_node, cmi_node
315  WHERE '.$in.'
316  AND cp_node.cp_node_id = cmi_node.cp_node_id
317  AND cp_node.slm_id = %s
318  AND cmi_node.user_id = %s',
319  array('integer', 'integer'),
320  array($a_obj_id, $a_user_id)
321  );
322 
323  $started = false;
324  $cntcompleted = 0;
325  $failed = false;
326  while ($rec = $ilDB->fetchAssoc($res))
327  {
328  if ($rec["completion"] == "completed" || $rec["success"] == "passed")
329  {
330  $cntcompleted++;
331  }
332  if ($rec["success"] == "failed") $failed = true;
333  $started = true;
334  }
335  if ($started == true) $status = "in_progress";
336  if ($failed == true) $status = "failed";
337  else if ($cntcompleted == count($a_scos)) $status = "completed";
338 
339  // check max attempts
340  if ($status == "in_progress" && self::_hasMaxAttempts($a_obj_id, $a_user_id))
341  {
342  $status = "failed";
343  }
344  }
345  return $status;
346  }
347 
348  public static function _hasMaxAttempts($a_obj_id, $a_user_id)
349  {
350  global $ilDB;
351 
352  // see ilSCORM13Player
353  $res = $ilDB->queryF(
354  'SELECT max_attempt FROM sahs_lm WHERE id = %s',
355  array('integer'),
356  array($a_obj_id)
357  );
358  $row = $ilDB->fetchAssoc($res);
359  $max_attempts = $row['max_attempt'];
360 
361  if ($max_attempts)
362  {
363  $res = $ilDB->queryF('
364  SELECT rvalue FROM cmi_custom
365  WHERE user_id = %s AND sco_id = %s
366  AND lvalue = %s AND obj_id = %s',
367  array('integer', 'integer', 'text', 'integer'),
368  array($a_user_id, 0, 'package_attempts', $a_obj_id)
369  );
370  $row = $ilDB->fetchAssoc($res);
371 
372  $row['rvalue'] = str_replace("\r\n", "\n", $row['rvalue']);
373  if($row['rvalue'] == null)
374  {
375  $row['rvalue'] = 0;
376  }
377  $act_attempts = $row['rvalue'];
378 
379  if ($act_attempts >= $max_attempts)
380  {
381  return true;
382  }
383  }
384 
385  return false;
386  }
387 
388  public static function _countCompleted($a_scos, $a_obj_id, $a_user_id,
389  $a_omit_failed = false)
390  {
391  global $ilDB;
392 
393  if (is_array($a_scos))
394  {
395  $in = $ilDB->in('cp_node.cp_node_id', $a_scos, false, 'integer');
396 
397  $res = $ilDB->queryF(
398  'SELECT cp_node.cp_node_id id,
399  cmi_node.completion_status completion,
400  cmi_node.success_status success
401  FROM cp_node, cmi_node
402  WHERE '.$in.'
403  AND cp_node.cp_node_id = cmi_node.cp_node_id
404  AND cp_node.slm_id = %s
405  AND cmi_node.user_id = %s',
406  array('integer', 'integer'),
407  array($a_obj_id, $a_user_id)
408  );
409 
410 
411  $cnt = 0;
412  while ($rec = $ilDB->fetchAssoc($res))
413  {
414  // #8171: alex, added (!$a_omit_failed || $rec["success"] != "failed")
415  // since completed/failed combination should not be included in
416  // percentage calculation at ilLPStatusSCOM::determinePercentage
417  if (($rec["completion"] == "completed" || $rec["success"] == "passed")
418  && (!$a_omit_failed || $rec["success"] != "failed"))
419  {
420  $cnt++;
421  }
422  }
423 
424  }
425  return $cnt;
426  }
427 
434  function _syncReadEvent($a_obj_id, $a_user_id, $a_type, $a_ref_id)
435  {
436  global $ilDB, $ilLog;
437 
438  // get attempts
439  $val_set = $ilDB->queryF('
440  SELECT rvalue FROM cmi_custom
441  WHERE user_id = %s
442  AND sco_id = %s
443  AND lvalue = %s
444  AND obj_id = %s',
445  array('integer','integer', 'text','integer'),
446  array($a_user_id, 0,'package_attempts',$a_obj_id));
447 
448  $val_rec = $ilDB->fetchAssoc($val_set);
449 
450  $val_rec["rvalue"] = str_replace("\r\n", "\n", $val_rec["rvalue"]);
451  if ($val_rec["rvalue"] == null) {
452  $val_rec["rvalue"]="";
453  }
454 
455  $attempts = $val_rec["rvalue"];
456 
457  // time
458  $scos = array();
459  $val_set = $ilDB->queryF(
460  'SELECT cp_node_id FROM cp_node
461  WHERE nodename = %s
462  AND cp_node.slm_id = %s',
463  array('text', 'integer'),
464  array('item', $a_obj_id)
465  );
466  while($val_rec = $ilDB->fetchAssoc($val_set))
467  {
468  array_push($scos,$val_rec['cp_node_id']);
469  }
470  $time = 0;
471  foreach ($scos as $sco)
472  {
473  include_once("./Modules/Scorm2004/classes/class.ilObjSCORM2004LearningModule.php");
474  $data_set = $ilDB->queryF('
475  SELECT total_time
476  FROM cmi_node
477  WHERE cp_node_id = %s
478  AND user_id = %s',
479  array('integer','integer'),
480  array($sco, $a_user_id)
481  );
482 
483  while($data_rec = $ilDB->fetchAssoc($data_set))
484  {
485  // see bug report 7246
486 // $sec = ilObjSCORM2004LearningModule::_ISODurationToCentisec($data_rec["session_time"]) / 100;
487  $sec = ilObjSCORM2004LearningModule::_ISODurationToCentisec($data_rec["total_time"]) / 100;
488  }
489  $time += (int) $sec;
490  $sec = 0;
491 //$ilLog->write("++".$time);
492  }
493 
494  include_once("./Services/Tracking/classes/class.ilChangeEvent.php");
495  ilChangeEvent::_recordReadEvent($a_type, $a_ref_id,
496  $a_obj_id, $a_user_id, false, $attempts, $time);
497  }
498 
499 
503  static function _isCompleted($a_status, $a_satisfied)
504  {
505  if ($a_status == "completed")
506  {
507  return true;
508  }
509 
510  return false;
511  }
512 
516  static function _isInProgress($a_status, $a_satisfied)
517  {
518  if ($a_status != "completed")
519  {
520  return true;
521  }
522 
523  return false;
524  }
525 
529  static function _isFailed($a_status, $a_satisfied)
530  {
531  if ($a_status == "completed" && $a_satisfied == "notSatisfied")
532  {
533  return true;
534  }
535 
536  return false;
537  }
538 
539 
540 }
541 // END class.ilSCORM2004Tracking
542 ?>