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