ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilObjSCORMInitData.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
32 {
33  public static function encodeURIComponent(string $str): string
34  {
35  $revert = array('%21' => '!', '%2A' => '*', '%27' => "'", '%28' => '(', '%29' => ')', '%7E' => '~');
36  return strtr(rawurlencode($str), $revert);
37  }
38 
39  public static function getIliasScormVars(ilObjSCORMLearningModule $slm_obj): string
40  {
41  global $DIC;
42  $ilLog = ilLoggerFactory::getLogger('sahs');
43  $ilUser = $DIC->user();
44  $lng = $DIC->language();
45  $ilDB = $DIC->database();
46  $ilSetting = $DIC->settings();
47  // $slm_obj = new ilObjSCORMLearningModule($_GET["ref_id"]);
48 
49  //variables to set in administration interface
50  $b_storeObjectives = 'false';
51  if ($slm_obj->getObjectives()) {
52  $b_storeObjectives = 'true';
53  }
54  $b_storeInteractions = 'false';
55  if ($slm_obj->getInteractions()) {
56  $b_storeInteractions = 'true';
57  }
58  $b_readInteractions = 'false';
59  $c_storeSessionTime = 's';//n=no, s=sco, i=ilias
60  if ($slm_obj->getTime_from_lms()) {
61  $c_storeSessionTime = 'i';
62  }
63  $i_lessonScoreMax = '-1';
64  $i_lessonMasteryScore = $slm_obj->getMasteryScore();
65 
66  //other variables
67  $b_messageLog = 'false';
68  // if ($ilLog->current_log_level == 30) {
69  // $b_messageLog = 'true';
70  // }
71  $launchId = '0';
72  if ($DIC->http()->wrapper()->query()->has('autolaunch')) {
73  $autoLaunch = $DIC->http()->wrapper()->query()->retrieve('autolaunch', $DIC->refinery()->kindlyTo()->string());
74  if ($autoLaunch != "") {
75  $launchId = $autoLaunch;
76  }
77  }
78  $session_timeout = 0; //unlimited sessions
79  if ($slm_obj->getSession()) {
81  $max_idle = (int) ilSession::getIdleValue();
82  if ($session_timeout > $max_idle) {
83  $session_timeout = $max_idle;
84  }
85  $min_idle = (int) $ilSetting->get('session_min_idle', (string) ilSessionControl::DEFAULT_MIN_IDLE) * 60;
86  if ($session_timeout > $min_idle) {
87  $session_timeout = $min_idle;
88  }
89  if ($session_timeout > 10) { //buffer
90  $session_timeout -= 10;
91  }
92  }
93  $b_autoReview = 'false';
94  if ($slm_obj->getAutoReview()) {
95  $b_autoReview = 'true';
96  }
97  $b_autoSuspend = 'false';
98  if ($slm_obj->getAutoSuspend()) {
99  $b_autoSuspend = 'true';
100  }
101  $b_debug = 'false';
102  if ($slm_obj->getDebug()) {
103  $b_debug = 'true';
104  }
105  $b_autoContinue = 'false';
106  if ($slm_obj->getAutoContinue()) {
107  $b_autoContinue = 'true';
108  }
109  $b_checkSetValues = 'false';
110  if ($slm_obj->getCheck_values()) {
111  $b_checkSetValues = 'true';
112  }
113  $b_autoLastVisited = 'false';
114  if ($slm_obj->getAuto_last_visited()) {
115  $b_autoLastVisited = 'true';
116  if ($launchId == '0') {
117  $launchId = $slm_obj->getLastVisited($ilUser->getID());
118  }
119  }
120 
121  $b_sessionDeactivated = 'false';
122  if ($slm_obj->getSessionDeactivated()) {
123  $b_sessionDeactivated = 'true';
124  }
125 
126  //manifestData //extra to IliasScormManifestData
127  // $s_man = "";
128  $a_man = array();
129  $val_set = $ilDB->queryF(
130  '
131  SELECT sc_item.obj_id,prereq_type,prerequisites,maxtimeallowed,timelimitaction,datafromlms,masteryscore
132  FROM sc_item, scorm_object
133  WHERE scorm_object.obj_id=sc_item.obj_id
134  AND scorm_object.c_type = %s
135  AND scorm_object.slm_id = %s',
136  array('text','integer'),
137  array('sit',$slm_obj->getId())
138  );
139  while ($val_rec = $ilDB->fetchAssoc($val_set)) {
140  if ($val_rec["prereq_type"] != null || $val_rec["prerequisites"] != null || $val_rec["maxtimeallowed"] != null || $val_rec["timelimitaction"] != null || $val_rec["datafromlms"] != null || $val_rec["masteryscore"] != null) {
141  $tmp_man = array((int) $val_rec["obj_id"],null,null,null,null,null,null);
142  if ($val_rec["prereq_type"] != null) {
143  $tmp_man[1] = self::encodeURIComponent($val_rec["prereq_type"]);
144  }
145  if ($val_rec["prerequisites"] != null) {
146  $tmp_man[2] = self::encodeURIComponent($val_rec["prerequisites"]);
147  }
148  if ($val_rec["maxtimeallowed"] != null) {
149  $tmp_man[3] = self::encodeURIComponent($val_rec["maxtimeallowed"]);
150  }
151  if ($val_rec["timelimitaction"] != null) {
152  $tmp_man[4] = self::encodeURIComponent($val_rec["timelimitaction"]);
153  }
154  if ($val_rec["datafromlms"] != null) {
155  $tmp_man[5] = self::encodeURIComponent($val_rec["datafromlms"]);
156  }
157  if ($val_rec["masteryscore"] != null) {
158  $tmp_man[6] = self::encodeURIComponent($val_rec["masteryscore"]);
159  }
160  $a_man[] = $tmp_man;
161  }
162  }
163 
164  $s_out = '{'
165  . '"refId":' . $DIC->http()->wrapper()->query()->retrieve('ref_id', $DIC->refinery()->kindlyTo()->string()) . ','
166  . '"objId":' . $slm_obj->getId() . ','
167  . '"clientId":"' . CLIENT_ID . '",'
168  . '"launchId":' . $launchId . ','
169  . '"launchNr":0,'
170  . '"pingSession":' . $session_timeout . ','
171  . '"studentId":"' . $slm_obj->getApiStudentId() . '",'
172  . '"studentName":"' . self::encodeURIComponent($slm_obj->getApiStudentName()) . '",'
173  . '"studentLogin":"' . self::encodeURIComponent($ilUser->getLogin()) . '",'
174  . '"studentOu":"' . self::encodeURIComponent($ilUser->getDepartment()) . '",'
175  . '"credit":"' . str_replace("_", "-", $slm_obj->getCreditMode()) . '",'
176  . '"lesson_mode":"' . $slm_obj->getDefaultLessonMode() . '",'
177  . '"b_autoReview":' . $b_autoReview . ','
178  . '"b_autoSuspend":' . $b_autoSuspend . ','
179  . '"b_messageLog":' . $b_messageLog . ','
180  . '"b_checkSetValues":' . $b_checkSetValues . ','
181  . '"b_storeObjectives":' . $b_storeObjectives . ','
182  . '"b_storeInteractions":' . $b_storeInteractions . ','
183  . '"b_readInteractions":' . $b_readInteractions . ','
184  . '"c_storeSessionTime":"' . $c_storeSessionTime . '",'
185  . '"b_autoContinue":' . $b_autoContinue . ','
186  . '"b_autoLastVisited":' . $b_autoLastVisited . ','
187  . '"b_sessionDeactivated":' . $b_sessionDeactivated . ','
188  . '"i_lessonScoreMax":' . $i_lessonScoreMax . ','
189  . '"i_lessonMasteryScore":"' . $i_lessonMasteryScore . '",'
190  . '"b_debug":' . $b_debug . ','
191  . '"a_itemParameter":' . json_encode($a_man) . ','
192  . '"status":' . json_encode(self::getStatus($slm_obj->getId(), $ilUser->getID(), $slm_obj->getAuto_last_visited())) . ','
193  . '"dataDirectory":"' . self::encodeURIComponent($slm_obj->getDataDirectory("output") . '/') . '",'
194  . '"img":{'
195  . '"asset":"' . self::encodeURIComponent(ilUtil::getImagePath('scorm/asset.svg')) . '",'
196  . '"browsed":"' . self::encodeURIComponent(ilUtil::getImagePath('scorm/browsed.svg')) . '",'
197  . '"completed":"' . self::encodeURIComponent(ilUtil::getImagePath('scorm/completed.svg')) . '",'
198  . '"failed":"' . self::encodeURIComponent(ilUtil::getImagePath('scorm/failed.svg')) . '",'
199  . '"incomplete":"' . self::encodeURIComponent(ilUtil::getImagePath('scorm/incomplete.svg')) . '",'
200  . '"not_attempted":"' . self::encodeURIComponent(ilUtil::getImagePath('scorm/not_attempted.svg')) . '",'
201  . '"passed":"' . self::encodeURIComponent(ilUtil::getImagePath('scorm/passed.svg')) . '",'
202  . '"running":"' . self::encodeURIComponent(ilUtil::getImagePath('scorm/running.svg')) . '"'
203  . '},'
204  . '"statusTxt":{'
205  . '"wait":"' . self::encodeURIComponent($lng->txt("please_wait")) . '",'
206  . '"status":"' . self::encodeURIComponent($lng->txt("cont_status")) . '",'
207  . '"browsed":"' . self::encodeURIComponent($lng->txt("cont_sc_stat_browsed")) . '",'
208  . '"completed":"' . self::encodeURIComponent($lng->txt("cont_sc_stat_completed")) . '",'
209  . '"failed":"' . self::encodeURIComponent($lng->txt("cont_sc_stat_failed")) . '",'
210  . '"incomplete":"' . self::encodeURIComponent($lng->txt("cont_sc_stat_incomplete")) . '",'
211  . '"not_attempted":"' . self::encodeURIComponent($lng->txt("cont_sc_stat_not_attempted")) . '",'
212  . '"passed":"' . self::encodeURIComponent($lng->txt("cont_sc_stat_passed")) . '",'
213  . '"running":"' . self::encodeURIComponent($lng->txt("cont_sc_stat_running")) . '"'
214  . '}'
215  . '}';
216  return $s_out;
217  }
218 
219  public static function getIliasScormData(int $a_packageId): string
220  {
221  global $DIC;
222  $ilUser = $DIC->user();
223  $ilDB = $DIC->database();
224  $b_readInteractions = 'false';
225  $a_out = array();
226  $tquery = 'SELECT sco_id,lvalue,rvalue FROM scorm_tracking '
227  . 'WHERE user_id = %s AND obj_id = %s '
228  . "AND sco_id > 0 AND lvalue != 'cmi.core.entry' AND lvalue != 'cmi.core.session_time'";
229  if ($b_readInteractions === 'false') {
230  $tquery .= " AND SUBSTR(lvalue, 1, 16) != 'cmi.interactions'";
231  }
232  $val_set = $ilDB->queryF(
233  $tquery,
234  array('integer','integer'),
235  array($ilUser->getId(),$a_packageId)
236  );
237  while ($val_rec = $ilDB->fetchAssoc($val_set)) {
238  if (!strpos($val_rec["lvalue"], "._count")) {
239  $a_out[] = array( (int) $val_rec["sco_id"], $val_rec["lvalue"], self::encodeURIComponent($val_rec["rvalue"]) );
240  }
241  }
242  return json_encode($a_out);
243  }
244 
245  public static function getIliasScormResources(int $a_packageId): string
246  {
247  global $DIC;
248  $ilDB = $DIC->database();
249  // $s_out="";
250  $a_out = array();
251  $s_resourceIds = "";//necessary if resources exist having different href with same identifier
252  $val_set = $ilDB->queryF(
253  "
254  SELECT sc_resource.obj_id
255  FROM scorm_tree, sc_resource
256  WHERE scorm_tree.slm_id=%s
257  AND sc_resource.obj_id=scorm_tree.child",
258  array('integer'),
259  array($a_packageId)
260  );
261  while ($val_rec = $ilDB->fetchAssoc($val_set)) {
262  $s_resourceIds .= "," . $val_rec["obj_id"];
263  }
264  $s_resourceIds = substr($s_resourceIds, 1);
265 
266  $tquery = "SELECT scorm_tree.lft, scorm_tree.child,
267  CASE WHEN sc_resource.scormtype = 'asset' THEN 1 ELSE 0 END AS asset,
268  sc_resource.href
269  FROM scorm_tree, sc_resource, sc_item
270  WHERE scorm_tree.slm_id=%s
271  AND sc_item.obj_id=scorm_tree.child
272  AND sc_resource.import_id=sc_item.identifierref
273  AND sc_resource.obj_id in (" . $s_resourceIds . ")
274  ORDER BY scorm_tree.lft";
275  $val_set = $ilDB->queryF(
276  $tquery,
277  array('integer'),
278  array($a_packageId)
279  );
280  while ($val_rec = $ilDB->fetchAssoc($val_set)) {
281  // $s_out.='['.$val_rec["lft"].','.$val_rec["child"].','.$val_rec["asset"].',"'.self::encodeURIComponent($val_rec["href"]).'"],';
282  $a_out[] = array( (int) $val_rec["lft"], (int) $val_rec["child"], (int) $val_rec["asset"], self::encodeURIComponent($val_rec["href"]) );
283  }
284  // if(substr($s_out,(strlen($s_out)-1))==",") $s_out=substr($s_out,0,(strlen($s_out)-1));
285  // return "[".$s_out."]";
286  return json_encode($a_out);
287  }
288 
289  public static function getIliasScormTree(int $a_packageId): string
290  {
291  global $DIC;
292  $ilDB = $DIC->database();
293  $a_out = array();
294  $tquery = "SELECT scorm_tree.child, scorm_tree.depth-3 depth, scorm_object.title, scorm_object.c_type
295  FROM scorm_tree, scorm_object
296  WHERE scorm_object.obj_id=scorm_tree.child
297  AND scorm_tree.slm_id=%s
298  AND (scorm_object.c_type='sor' OR scorm_object.c_type='sit')
299  ORDER BY scorm_tree.lft";
300  $val_set = $ilDB->queryF(
301  $tquery,
302  array('integer'),
303  array($a_packageId)
304  );
305  while ($val_rec = $ilDB->fetchAssoc($val_set)) {
306  $a_out[] = array((int) $val_rec["child"],(int) $val_rec["depth"],self::encodeURIComponent($val_rec["title"]),$val_rec["c_type"]);
307  }
308  return json_encode($a_out);
309  }
310 
314  public static function getStatus(int $a_packageId, int $a_user_id, bool $auto_last_visited, string $scormType = "1.2"): array
315  {
316  global $DIC;
317  $ilDB = $DIC->database();
318  $oldStatus = ilLPStatus::_lookupStatus($a_packageId, $a_user_id);
319  $status['saved_global_status'] = (int) $oldStatus;
320  $olp = ilObjectLP::getInstance($a_packageId);
321  $status['lp_mode'] = $olp->getCurrentMode();
322  $collection = $olp->getCollectionInstance();
323  if ($collection) {
324  $status['scos'] = $collection->getItems();
325  } else {
326  $status['scos'] = array();
327  }
328  $status['hash'] = ilObjSCORMInitData::setHash($a_packageId, $a_user_id);
329  $status['p'] = $a_user_id;
330 
331  $status['last_visited'] = null;
332  $status['total_time_sec'] = 0;
333  $val_set = $ilDB->queryF(
334  'SELECT last_visited, sco_total_time_sec, total_time_sec FROM sahs_user WHERE obj_id = %s AND user_id = %s',
335  array('integer','integer'),
336  array($a_packageId,$a_user_id)
337  );
338  $val_rec = $ilDB->fetchAssoc($val_set);
339  if ($auto_last_visited) {
340  $status['last_visited'] = $val_rec["last_visited"];
341  }
342  if ($val_rec["total_time_sec"] == null) {
343  if ($val_rec["sco_total_time_sec"] == null) {
344  //fall back for old ILIAS-Versions
345  if ($scormType == "2004") {
346  $status['total_time_sec'] = (int) ilSCORM2004Tracking::getSumTotalTimeSecondsFromScos($a_packageId, $a_user_id, true);
347  }
348  } else {
349  $status['total_time_sec'] = (int) $val_rec["sco_total_time_sec"];
350  }
351  } else {
352  $status['total_time_sec'] = (int) $val_rec["total_time_sec"];
353  }
354 
355  return $status;
356  }
357 
361  private static function setHash(int $a_packageId, int $a_user_id): int
362  {
363  global $DIC;
364  $ilDB = $DIC->database();
365  $hash = random_int(1_000_000_000, 2_147_483_647);
366  $endDate = date('Y-m-d H:i:s', mktime((int) date("H"), (int) date("i"), (int) date("s"), (int) date("m"), (int) date("d") + 1, (int) date("Y")));
367 
368  $res = $ilDB->queryF(
369  'SELECT count(*) cnt FROM sahs_user WHERE obj_id = %s AND user_id = %s',
370  array('integer', 'integer'),
371  array($a_packageId,$a_user_id)
372  );
373  $val_rec = $ilDB->fetchAssoc($res);
374  if ($val_rec["cnt"] == 0) {
375  $ilDB->manipulateF(
376  'INSERT INTO sahs_user (obj_id, user_id, hash, hash_end) VALUES(%s, %s, %s, %s)',
377  array('integer', 'integer', 'text', 'timestamp'),
378  array($a_packageId, $a_user_id, "" . $hash, $endDate)
379  );
380  } else {
381  $ilDB->manipulateF(
382  'UPDATE sahs_user SET hash = %s, hash_end = %s WHERE obj_id = %s AND user_id = %s',
383  array('text', 'timestamp', 'integer', 'integer'),
384  array("" . $hash, $endDate, $a_packageId, $a_user_id)
385  );
386  }
387  //clean table
388  // if (fmod($hash,100) == 0) //note: do not use % for large numbers; here php-min-Version: 4.2.0
389  // {
390  // $endDate = date('Y-m-d H:i:s', mktime(date('H'), date('i'), date('s'), date('m'), date('d')-2, date('Y')));
391  // $ilDB->manipulateF('DELETE FROM cmi_custom WHERE lvalue = %s AND c_timestamp < %s',
392  // array('text', 'timestamp'),
393  // array('hash', $endDate)
394  // );
395  // }
396  return $hash;
397  }
398 }
$res
Definition: ltiservices.php:69
static getIliasScormData(int $a_packageId)
static getCookieMaxLifetimeInSeconds()
static getLogger(string $a_component_id)
Get component logger.
getSessionDeactivated()
sessionDisabled for SCORM 2004
static getImagePath(string $img, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
static getIliasScormVars(ilObjSCORMLearningModule $slm_obj)
getAutoReview()
get auto review as true/false for SCORM 1.2
static setHash(int $a_packageId, int $a_user_id)
hash for storing data without session
global $DIC
Definition: feed.php:28
$lng
const CLIENT_ID
Definition: constants.php:41
getApiStudentId()
Get cmi.core.student_id / cmi.learner_id for API.
static getStatus(int $a_packageId, int $a_user_id, bool $auto_last_visited, string $scormType="1.2")
static _lookupStatus(int $a_obj_id, int $a_user_id, bool $a_create=true)
Lookup status.
getApiStudentName()
Get cmi.core.student_name / cmi.learner_name for API note: &#39;lastname, firstname&#39; is required for SCOR...
static getIliasScormResources(int $a_packageId)
getDataDirectory(?string $mode="filesystem")
get data directory of lm
global $ilSetting
Definition: privfeed.php:18
static getIliasScormTree(int $a_packageId)
static getSumTotalTimeSecondsFromScos(int $a_obj_id, int $a_user_id, bool $a_write=false)
should be avoided; store value to increase performance for further requests
static getIdleValue(bool $fixedMode=false)
Returns the idle time in seconds.
getDefaultLessonMode()
get default lesson mode
static getInstance(int $obj_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static encodeURIComponent(string $str)