ILIAS  release_8 Revision v8.24
class.ilObjSCORMTracking.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
27{
28 public static function storeJsApi(): void
29 {
30 global $DIC;
31 $obj_id = $DIC->http()->wrapper()->query()->retrieve('package_id', $DIC->refinery()->kindlyTo()->int());
32 $refId = $DIC->http()->wrapper()->query()->retrieve('ref_id', $DIC->refinery()->kindlyTo()->int());
33 $in = file_get_contents("php://input");
34 $data = json_decode($in);
35 $user_id = (int) $data->p;
36
37 header('Content-Type: text/plain; charset=UTF-8');
38
39 $rval = self::storeJsApiCmi($user_id, $obj_id, $data);
40 if ($rval != true) {
41 print("storeJsApiCmi failed");
42 } else {
43 $rval = self::syncGlobalStatus($user_id, $obj_id, $refId, $data, $data->now_global_status);
44 if ($rval != true) {
45 print("syncGlobalStatus failed");
46 }
47 }
48 if ($rval == true) {
49 print("ok");
50 }
51 }
52
53 public static function storeJsApiCmi(int $user_id, int $obj_id, object $data): bool
54 {
55 global $DIC;
56 $ilLog = ilLoggerFactory::getLogger('sahs');
57 $ilDB = $DIC->database();
58
59 $b_updateStatus = false;
60 $i_score_max = 0;
61 $i_score_raw = 0;
62
63 $aa_data = array();
64 // if (is_array($_POST["S"])) {
65 // foreach($_POST["S"] as $key => $value) {
66 // $aa_data[] = array("sco_id" => $value, "left" => $_POST["L"][$key], "right" => $_POST["R"][$key]);
67 // }
68 // }
69 foreach ($data->cmi as $value) {
70 $aa_data[] = array("sco_id" => (int) $value[0],
71 "left" => $value[1],
72 "right" => $value[2]
73 );
74 // $aa_data[] = array("sco_id" => (int) $data->cmi[$i][0], "left" => $data->cmi[$i][1], "right" => rawurldecode($data->cmi[$i][2]));
75 }
76
77 if ($obj_id <= 1) {
78 $ilLog->write("ScormAicc: storeJsApi: Error: No valid obj_id given.");
79 } else {
80 foreach ($aa_data as $a_data) {
81 $set = $ilDB->queryF(
82 '
83 SELECT rvalue FROM scorm_tracking
84 WHERE user_id = %s
85 AND sco_id = %s
86 AND lvalue = %s
87 AND obj_id = %s',
88 array('integer', 'integer', 'text', 'integer'),
89 array($user_id, $a_data["sco_id"], $a_data["left"], $obj_id)
90 );
91 if ($rec = $ilDB->fetchAssoc($set)) {
92 if ($a_data["left"] === 'cmi.core.lesson_status' && $a_data["right"] != $rec["rvalue"]) {
93 $b_updateStatus = true;
94 }
95 $ilDB->update(
96 'scorm_tracking',
97 array(
98 'rvalue' => array('clob', $a_data["right"]),
99 'c_timestamp' => array('timestamp', ilUtil::now())
100 ),
101 array(
102 'user_id' => array('integer', $user_id),
103 'sco_id' => array('integer', $a_data["sco_id"]),
104 'lvalue' => array('text', $a_data["left"]),
105 'obj_id' => array('integer', $obj_id)
106 )
107 );
108 $ilLog->debug("ScormAicc: storeJsApi Updated - L:" . $a_data["left"] . ",R:" .
109 $a_data["right"] . " for obj_id:" . $obj_id . ",sco_id:" . $a_data["sco_id"] . ",user_id:" . $user_id);
110 } else {
111 if ($a_data["left"] === 'cmi.core.lesson_status') {
112 $b_updateStatus = true;
113 }
114 $ilDB->insert('scorm_tracking', array(
115 'obj_id' => array('integer', $obj_id),
116 'user_id' => array('integer', $user_id),
117 'sco_id' => array('integer', $a_data["sco_id"]),
118 'lvalue' => array('text', $a_data["left"]),
119 'rvalue' => array('clob', $a_data["right"]),
120 'c_timestamp' => array('timestamp', ilUtil::now())
121 ));
122 $ilLog->debug("ScormAicc: storeJsApi Inserted - L:" . $a_data["left"] . ",R:" .
123 $a_data["right"] . " for obj_id:" . $obj_id . ",sco_id:" . $a_data["sco_id"] . ",user_id:" . $user_id);
124 }
125 if ($a_data["left"] === 'cmi.core.score.max') {
126 $i_score_max = $a_data["right"];
127 }
128 if ($a_data["left"] === 'cmi.core.score.raw') {
129 $i_score_raw = $a_data["right"];
130 }
131 }
132 // mantis #30293
133 if ($i_score_max > 0 && $i_score_raw > 0) {
134 if (count(ilSCORMObject::_lookupPresentableItems($obj_id)) == 1) {
136 $obj_id,
137 $user_id,
138 ($i_score_raw / $i_score_max) * 100
139 );
140 }
141 }
142 }
143
144 // update status
145 // if ($b_updateStatus == true) {
146 // include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
147 // ilLPStatusWrapper::_updateStatus($obj_id, $user_id);
148 // }
149
150 return true;
151 }
152
153 public static function syncGlobalStatus(int $userId, int $packageId, int $refId, object $data, ?int $new_global_status): bool
154 {
155 global $DIC;
156 $ilDB = $DIC->database();
157 $ilLog = ilLoggerFactory::getLogger('sahs');
158 $saved_global_status = $data->saved_global_status;
159 $ilLog->write("saved_global_status=" . $saved_global_status);
160
161 // get attempts
162 if (!isset($data->packageAttempts)) {
163 $val_set = $ilDB->queryF(
164 'SELECT package_attempts FROM sahs_user WHERE obj_id = %s AND user_id = %s',
165 array('integer', 'integer'),
166 array($packageId, $userId)
167 );
168 $val_rec = $ilDB->fetchAssoc($val_set);
169 $attempts = $val_rec["package_attempts"];
170 } else {
171 $attempts = $data->packageAttempts;
172 }
173 if ($attempts == null) {
174 $attempts = 1;
175 }
176
177 //update percentage_completed, sco_total_time_sec,status in sahs_user
178 $totalTime = (int) $data->totalTimeCentisec;
179 $totalTime = round($totalTime / 100);
180 $ilDB->queryF(
181 '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',
182 array('text', 'timestamp', 'integer', 'integer', 'integer', 'integer', 'integer', 'integer'),
183 array($data->last_visited,
184 date('Y-m-d H:i:s'),
185 $totalTime,
186 $new_global_status,
187 $data->percentageCompleted,
188 $attempts,
190 $userId
191 )
192 );
193
194 // self::ensureObjectDataCacheExistence();
195 global $DIC;
196 $ilObjDataCache = $DIC['ilObjDataCache'];
197 //workaround if $row->read_count == null TODO ERASE
198 try {
200 "sahs",
201 $refId,
203 $userId,
204 false,
205 $attempts,
206 $totalTime
207 );
208 } catch (\Exception $exception) {
210 "sahs",
211 $refId,
213 $userId,
214 false,
215 null,
216 $totalTime
217 );
218 }
219
220 //end sync access number and time in read event table
221
222 // update learning progress
223 if ($new_global_status != null) {
224 ilLPStatus::writeStatus($packageId, $userId, $new_global_status, $data->percentageCompleted);
225
226 // here put code for soap to MaxCMS e.g. when if($saved_global_status != $new_global_status)
227 }
228 return true;
229 }
230
231 public static function _insertTrackData(int $a_sahs_id, string $a_lval, string $a_rval, int $a_obj_id): void
232 {
233 global $DIC;
234 $ilDB = $DIC->database();
235 $ilUser = $DIC->user();
236
237 $ilDB->insert('scorm_tracking', array(
238 'obj_id' => array('integer', $a_obj_id),
239 'user_id' => array('integer', $ilUser->getId()),
240 'sco_id' => array('integer', $a_sahs_id),
241 'lvalue' => array('text', $a_lval),
242 'rvalue' => array('clob', $a_rval),
243 'c_timestamp' => array('timestamp', ilUtil::now())
244 ));
245
246 if ($a_lval === "cmi.core.lesson_status") {
247 ilLPStatusWrapper::_updateStatus($a_obj_id, $ilUser->getId());
248 }
249 }
250
251 //erase later see ilSCORM2004StoreData
256 public static function _getCompleted(object $scorm_item_id, int $a_obj_id): array
257 {
258 global $DIC;
259 $ilDB = $DIC->database();
260
261 $user_ids = [];
262
263 if (is_array($scorm_item_id)) {
264 $in = $ilDB->in('sco_id', $scorm_item_id, false, 'integer');
265
266 $res = $ilDB->queryF(
267 'SELECT DISTINCT(user_id) FROM scorm_tracking
268 WHERE ' . $in . '
269 AND obj_id = %s
270 AND lvalue = %s
271 AND (' . $ilDB->like('rvalue', 'clob', 'completed') . ' OR ' . $ilDB->like(
272 'rvalue',
273 'clob',
274 'passed'
275 ) . ')',
276 array('integer', 'text'),
277 array($a_obj_id, 'cmi.core.lesson_status')
278 );
279 } else {
280 $res = $ilDB->queryF(
281 'SELECT DISTINCT(user_id) FROM scorm_tracking
282 WHERE sco_id = %s
283 AND obj_id = %s
284 AND lvalue = %s
285 AND (' . $ilDB->like('rvalue', 'clob', 'completed') . ' OR ' . $ilDB->like(
286 'rvalue',
287 'clob',
288 'passed'
289 ) . ')',
290 array('integer', 'integer', 'text'),
291 array($scorm_item_id, $a_obj_id, 'cmi.core.lesson_status')
292 );
293 }
294
295 while ($row = $ilDB->fetchObject($res)) {
296 $user_ids[] = $row->user_id;
297 }
298 return $user_ids;
299 }
300
301 public static function _getCollectionStatus(?array $a_scos, int $a_obj_id, int $a_user_id): string
302 {
303 global $DIC;
304 $ilDB = $DIC->database();
305
306 $status = "not_attempted";
307
308 if (is_array($a_scos)) {
309 $in = $ilDB->in('sco_id', $a_scos, false, 'integer');
310
311 $res = $ilDB->queryF(
312 'SELECT sco_id, rvalue FROM scorm_tracking
313 WHERE ' . $in . '
314 AND obj_id = %s
315 AND lvalue = %s
316 AND user_id = %s',
317 array('integer', 'text', 'integer'),
318 array($a_obj_id, 'cmi.core.lesson_status', $a_user_id)
319 );
320
321 $cnt = 0;
322 $completed = true;
323 $failed = false;
324 while ($rec = $ilDB->fetchAssoc($res)) {
325 if ($rec["rvalue"] === "failed") {
326 $failed = true;
327 }
328 if ($rec["rvalue"] !== "completed" && $rec["rvalue"] !== "passed") {
329 $completed = false;
330 }
331 $cnt++;
332 }
333 if ($cnt > 0) {
334 $status = "in_progress";
335 }
336 if ($completed && $cnt == count($a_scos)) {
337 $status = "completed";
338 }
339 if ($failed) {
340 $status = "failed";
341 }
342 }
343 return $status;
344 }
345
346 public static function _countCompleted(?array $a_scos, int $a_obj_id, int $a_user_id): int
347 {
348 global $DIC;
349 $ilDB = $DIC->database();
350 $cnt = 0;
351
352 if (is_array($a_scos)) {
353 $in = $ilDB->in('sco_id', $a_scos, false, 'integer');
354
355 $res = $ilDB->queryF(
356 'SELECT sco_id, rvalue FROM scorm_tracking
357 WHERE ' . $in . '
358 AND obj_id = %s
359 AND lvalue = %s
360 AND user_id = %s',
361 array('integer', 'text', 'integer'),
362 array($a_obj_id, 'cmi.core.lesson_status', $a_user_id)
363 );
364
365 while ($rec = $ilDB->fetchAssoc($res)) {
366 if ($rec["rvalue"] === "completed" || $rec["rvalue"] === "passed") {
367 $cnt++;
368 }
369 }
370 }
371 return $cnt;
372 }
373
378 public static function lookupLastAccessTimes(int $a_obj_id): array
379 {
380 global $DIC;
381 $ilDB = $DIC->database();
382 $users = array();
383
384 $query = 'SELECT user_id, MAX(c_timestamp) tst ' .
385 'FROM scorm_tracking ' .
386 'WHERE obj_id = ' . $ilDB->quote($a_obj_id, 'integer') . ' ' .
387 'GROUP BY user_id';
388 $res = $ilDB->query($query);
389
390 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
391 $users[$row->user_id] = $row->tst;
392 }
393 return $users;
394 }
395
400 public static function _getTrackedUsers(int $a_obj_id): array
401 {
402 global $DIC;
403 $ilDB = $DIC->database();
404 // $ilLog = ilLoggerFactory::getLogger('sahs');
405
406 $res = $ilDB->queryF(
407 'SELECT DISTINCT user_id FROM scorm_tracking
408 WHERE obj_id = %s
409 AND lvalue = %s',
410 array('integer', 'text'),
411 array($a_obj_id, 'cmi.core.lesson_status')
412 );
413
414 $users = array();
415 while ($row = $ilDB->fetchAssoc($res)) {
416 $users[] = $row["user_id"];
417 }
418 return $users;
419 }
420
425 public static function _getFailed(object $scorm_item_id, int $a_obj_id): array
426 {
427 global $DIC;
428 $ilDB = $DIC->database();
429 $user_ids = [];
430
431 if (is_array($scorm_item_id)) {
432 $in = $ilDB->in('sco_id', $scorm_item_id, false, 'integer');
433
434 $res = $ilDB->queryF(
435 '
436 SELECT DISTINCT(user_id) FROM scorm_tracking
437 WHERE ' . $in . '
438 AND obj_id = %s
439 AND lvalue = %s
440 AND ' . $ilDB->like('rvalue', 'clob', 'failed') . ' ',
441 array('integer', 'text'),
442 array($a_obj_id, 'cmi.core.lesson_status')
443 );
444 } else {
445 $res = $ilDB->queryF(
446 '
447 SELECT DISTINCT(user_id) FROM scorm_tracking
448 WHERE sco_id = %s
449 AND obj_id = %s
450 AND lvalue = %s
451 AND ' . $ilDB->like('rvalue', 'clob', 'failed') . ' ',
452 array('integer', 'integer', 'text'),
453 array($scorm_item_id, $a_obj_id, 'cmi.core.lesson_status')
454 );
455 }
456
457 while ($row = $ilDB->fetchObject($res)) {
458 $user_ids[] = $row->user_id;
459 }
460 return $user_ids;
461 }
462
467 public static function _getCountCompletedPerUser(array $a_scorm_item_ids, int $a_obj_id): array
468 {
469 global $DIC;
470 $ilDB = $DIC->database();
471 $users = [];
472
473 $in = $ilDB->in('sco_id', $a_scorm_item_ids, false, 'integer');
474
475 // Why does this query use a like search against "passed" and "failed"
476 //because it's clob and we support Oracle
477 $res = $ilDB->queryF(
478 '
479 SELECT user_id, COUNT(user_id) completed 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 GROUP BY user_id',
485 array('integer', 'text'),
486 array($a_obj_id, 'cmi.core.lesson_status')
487 );
488 while ($row = $ilDB->fetchObject($res)) {
489 $users[$row->user_id] = $row->completed;
490 }
491 return $users;
492 }
493 //not correct because of assets!
498 public static function _getProgressInfo(array $sco_item_ids, int $a_obj_id): array
499 {
500 global $DIC;
501 $ilDB = $DIC->database();
502
503 $in = $ilDB->in('sco_id', $sco_item_ids, false, 'integer');
504
505 $res = $ilDB->queryF(
506 '
507 SELECT * FROM scorm_tracking
508 WHERE ' . $in . '
509 AND obj_id = %s
510 AND lvalue = %s ',
511 array('integer', 'text'),
512 array($a_obj_id, 'cmi.core.lesson_status')
513 );
514
515 $info['completed'] = array();
516 $info['failed'] = array();
517
518 $user_ids = array();
519 while ($row = $ilDB->fetchObject($res)) {
520 switch ($row->rvalue) {
521 case 'completed':
522 case 'passed':
523 $info['completed'][$row->sco_id][] = $row->user_id;
524 $user_ids[$row->sco_id][] = $row->user_id;
525 break;
526
527 case 'failed':
528 $info['failed'][$row->sco_id][] = $row->user_id;
529 $user_ids[$row->sco_id][] = $row->user_id;
530 break;
531 }
532 }
533 $info['in_progress'] = ilObjSCORMTracking::_getInProgress($sco_item_ids, $a_obj_id, $user_ids);
534
535 return $info;
536 }
537
542 public static function _getInProgress($scorm_item_id, int $a_obj_id, ?array $a_blocked_user_ids = null): array
543 {
544 global $DIC;
545 $ilDB = $DIC->database();
546
547 if (is_array($scorm_item_id)) {
548 $in = $ilDB->in('sco_id', $scorm_item_id, false, 'integer');
549
550 $res = $ilDB->queryF(
551 'SELECT user_id,sco_id FROM scorm_tracking
552 WHERE ' . $in . '
553 AND obj_id = %s
554 GROUP BY user_id, sco_id',
555 array('integer'),
556 array($a_obj_id)
557 );
558 } else {
559 $res = $ilDB->queryF(
560 'SELECT user_id,sco_id FROM scorm_tracking
561 WHERE sco_id = %s
562 AND obj_id = %s',
563 array('integer', 'integer'),
564 array($scorm_item_id, $a_obj_id)
565 );
566 }
567
568 $in_progress = array();
569
570 while ($row = $ilDB->fetchObject($res)) {
571 // #15061 - see _getProgressInfo()
572 if (!($a_blocked_user_ids &&
573 isset($a_blocked_user_ids[$row->sco_id]) &&
574 is_array($a_blocked_user_ids[$row->sco_id]) &&
575 in_array($row->user_id, $a_blocked_user_ids[$row->sco_id]))) {
576 $in_progress[$row->sco_id][] = $row->user_id;
577 }
578 }
579 return $in_progress;
580 }
581
582 public static function scorm12PlayerUnload(): void
583 {
584 global $DIC;
585 $ilDB = $DIC->database();
586 $user_id = $DIC->http()->wrapper()->query()->retrieve('p', $DIC->refinery()->kindlyTo()->int());
587 $ref_id = $DIC->http()->wrapper()->query()->retrieve('ref_id', $DIC->refinery()->kindlyTo()->int());
588 $obj_id = $DIC->http()->wrapper()->query()->retrieve('package_id', $DIC->refinery()->kindlyTo()->int());
589 if ($obj_id <= 1) {
590 $GLOBALS['DIC']['ilLog']->write(__METHOD__ . ' no valid obj_id');
591 } else {
592 $last_visited = "";
593 if ($DIC->http()->wrapper()->query()->has('last_visited')) {
594 $last_visited = $DIC->http()->wrapper()->query()->retrieve('last_visited', $DIC->refinery()->kindlyTo()->string());
595 }
596
597 $endDate = date(
598 'Y-m-d H:i:s',
599 mktime((int) date('H'), (int) date('i') + 5, (int) date('s'), (int) date('m'), (int) date('d'), (int) date('Y'))
600 );
601 $ilDB->manipulateF(
602 'UPDATE sahs_user
603 SET last_visited = %s, hash_end =%s, last_access = %s
604 WHERE obj_id = %s AND user_id = %s',
605 array('text', 'timestamp', 'timestamp', 'integer', 'integer'),
606 array($last_visited, $endDate, date('Y-m-d H:i:s'), $obj_id, $user_id)
607 );
608 // update time and numbers of attempts in change event
609 //NOTE: here it is correct (not count of commit with changed values); be careful to performance issues
610 ilObjSCORMTracking::_syncReadEvent($obj_id, $user_id, "sahs", $ref_id);
611 }
612 header('Content-Type: text/plain; charset=UTF-8');
613 print("");
614 }
615
616 public static function checkIfAllowed(int $packageId, int $userId, int $hash): void
617 {
618 global $DIC;
619 $ilDB = $DIC->database();
620 $res = $ilDB->queryF(
621 'select hash from sahs_user where obj_id=%s AND user_id=%s AND hash_end>%s',
622 array('integer', 'integer', 'timestamp'),
623 array($packageId, $userId, date('Y-m-d H:i:s'))
624 );
625 $rowtmp = $ilDB->fetchAssoc($res);
626 if (! ($rowtmp && $rowtmp['hash'] == $hash)) {
627 //output used by api
628 die("not allowed");
629 }
630 }
631
632 public static function _syncReadEvent(int $a_obj_id, int $a_user_id, string $a_type, int $a_ref_id): void
633 {
634 global $DIC;
635 $ilDB = $DIC->database();
636 $ilLog = ilLoggerFactory::getLogger('sahs');
637 $val_set = $ilDB->queryF(
638 'SELECT package_attempts, total_time_sec, sco_total_time_sec, time_from_lms FROM sahs_user, sahs_lm '
639 . 'WHERE sahs_user.obj_id = %s AND sahs_user.user_id = %s AND sahs_user.obj_id = sahs_lm.id',
640 array('integer', 'integer'),
641 array($a_obj_id, $a_user_id)
642 );
643
644 $val_rec = $ilDB->fetchAssoc($val_set);
645
646 if ($val_rec["package_attempts"] == null) {
647 $val_rec["package_attempts"] = "";
648 }
649 $attempts = $val_rec["package_attempts"];
650
651 $time = (int) $val_rec["sco_total_time_sec"];
652
653 // get learning time for old ILIAS-Versions
654 if ($time == 0) {
655 $sco_set = $ilDB->queryF(
656 '
657 SELECT sco_id, rvalue FROM scorm_tracking
658 WHERE obj_id = %s
659 AND user_id = %s
660 AND lvalue = %s
661 AND sco_id <> %s',
662 array('integer', 'integer', 'text', 'integer'),
663 array($a_obj_id, $a_user_id, 'cmi.core.total_time', 0)
664 );
665
666 while ($sco_rec = $ilDB->fetchAssoc($sco_set)) {
667 $tarr = explode(":", $sco_rec["rvalue"]);
668 $sec = (int) $tarr[2] + (int) $tarr[1] * 60 +
669 (int) substr($tarr[0], strlen($tarr[0]) - 3) * 60 * 60;
670 $time += $sec;
671 }
672 }
673 ilChangeEvent::_recordReadEvent($a_type, $a_ref_id, $a_obj_id, $a_user_id, false, $attempts, $time);
674 }
675} // END class.ilObjSCORMTracking
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
Definition: PEAR.php:64
static _recordReadEvent(string $a_type, int $a_ref_id, int $obj_id, int $usr_id, bool $isCatchupWriteEvents=true, $a_ext_rc=null, $a_ext_time=null)
static _updateStatus(int $a_obj_id, int $a_usr_id, ?object $a_obj=null, bool $a_percentage=false, bool $a_force_raise=false)
static writeStatus(int $a_obj_id, int $a_user_id, int $a_status, int $a_percentage=0, bool $a_force_per=false, ?int &$a_old_status=self::LP_STATUS_NOT_ATTEMPTED_NUM)
Write status for user and object.
static handleOutcomeWithoutLP(int $a_obj_id, int $a_usr_id, ?float $a_percentage)
static getLogger(string $a_component_id)
Get component logger.
Class ilObjSCORMTracking.
static syncGlobalStatus(int $userId, int $packageId, int $refId, object $data, ?int $new_global_status)
static _getProgressInfo(array $sco_item_ids, int $a_obj_id)
Get info about.
static _syncReadEvent(int $a_obj_id, int $a_user_id, string $a_type, int $a_ref_id)
static _getCountCompletedPerUser(array $a_scorm_item_ids, int $a_obj_id)
Get users who have status completed or passed.
static _insertTrackData(int $a_sahs_id, string $a_lval, string $a_rval, int $a_obj_id)
static _getTrackedUsers(int $a_obj_id)
Get all tracked users.
static _getInProgress($scorm_item_id, int $a_obj_id, ?array $a_blocked_user_ids=null)
static _getCollectionStatus(?array $a_scos, int $a_obj_id, int $a_user_id)
static checkIfAllowed(int $packageId, int $userId, int $hash)
static _getFailed(object $scorm_item_id, int $a_obj_id)
like necessary because of Oracle
static _getCompleted(object $scorm_item_id, int $a_obj_id)
like necessary because of Oracle
static lookupLastAccessTimes(int $a_obj_id)
Lookup last acccess time for all users of a scorm module.
static storeJsApiCmi(int $user_id, int $obj_id, object $data)
static _countCompleted(?array $a_scos, int $a_obj_id, int $a_user_id)
static _lookupPresentableItems(int $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.
global $DIC
Definition: feed.php:28
$ilUser
Definition: imgupload.php:34
$ref_id
Definition: ltiauth.php:67
$res
Definition: ltiservices.php:69
$query
$packageId
Definition: storeScorm.php:25
$refId
Definition: xapitoken.php:58