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
$failed
Definition: Utf8Test.php:85
if(php_sapi_name() !='cli') $in
Definition: Utf8Test.php:37
if(! $in) print
$users
Definition: authpage.php:44
$_GET["client_id"]
$_POST["username"]
An exception for terminatinating execution or to throw for unit testing.
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 _updateStatus($a_obj_id, $a_usr_id, $a_obj=null, $a_percentage=false, $a_force_raise=false)
Update status.
static writeStatus($a_obj_id, $a_user_id, $a_status, $a_percentage=false, $a_force_per=false)
Write status for user and object.
static handleOutcomeWithoutLP($a_obj_id, $a_usr_id, $a_percentage)
Class ilObjSCORMTracking.
static _getTrackedUsers($a_obj_id)
Get all tracked users.
static _getProgressInfo($sco_item_ids, $a_obj_id)
Get info about.
static syncGlobalStatus($userId, $packageId, $data, $new_global_status)
static _getCompleted($scorm_item_id, $a_obj_id)
like necessary because of Oracle
static _countCompleted($a_scos, $a_obj_id, $a_user_id)
static _getInProgress($scorm_item_id, $a_obj_id, $a_blocked_user_ids=null)
static _getCollectionStatus($a_scos, $a_obj_id, $a_user_id)
static _syncReadEvent($a_obj_id, $a_user_id, $a_type, $a_ref_id)
Synch read event table.
static _getFailed($scorm_item_id, $a_obj_id)
like necessary because of Oracle
static lookupLastAccessTimes($a_obj_id)
Lookup last acccess time for all users of a scorm module @global ilDB $ilDB.
static storeJsApiCmi($user_id, $obj_id, $data)
static _getCountCompletedPerUser($a_scorm_item_ids, $a_obj_id)
Get users who have status completed or passed.
static _insertTrackData($a_sahs_id, $a_lval, $a_rval, $a_obj_id)
static checkIfAllowed($packageId, $userId, $hash)
store($obj_id=0, $sahs_id=0, $extractData=1)
static _lookupObjId($a_id)
static _lookupPresentableItems($a_slm_id)
Count number of presentable SCOs/Assets of SCORM learning module.
static now()
Return current timestamp in Y-m-d H:i:s format.
$key
Definition: croninfo.php:18
$i
Definition: disco.tpl.php:19
$time
Definition: cron.php:21
$info
Definition: index.php:5
$row
$GLOBALS['JPEG_Segment_Names']
Global Variable: XMP_tag_captions.
update($pash, $contents, Config $config)
$query
global $DIC
Definition: saml.php:7
foreach($_POST as $key=> $value) $res
$packageId
global $ilDB
$ilUser
Definition: imgupload.php:18
$data
Definition: bench.php:6
$a_type
Definition: workflow.php:92