19 declare(strict_types=1);
32 $ilDB = $DIC->database();
35 $data = json_decode(file_get_contents(
'php://input'));
39 if ($userId == null) {
41 self::checkIfAllowed($packageId, $userId,
$data->hash);
44 if (
$data->last !=
"") {
45 $last_visited =
$data->last;
58 $total_time_sec = null;
59 if (
$data->total_time_sec !=
"") {
60 $total_time_sec =
$data->total_time_sec;
63 SET total_time_sec = %s, last_visited = %s, hash_end =%s, last_access = %s 64 WHERE obj_id = %s AND user_id = %s',
65 array(
'integer',
'text',
'timestamp',
'timestamp',
'integer',
'integer'),
66 array($total_time_sec, $last_visited, $endDate, date(
'Y-m-d H:i:s'), $packageId, $userId)
68 if ($time_from_lms ==
true) {
69 self::ensureObjectDataCacheExistence();
72 $ilObjDataCache = $DIC[
"ilObjDataCache"];
80 SET last_visited = %s, hash_end =%s, last_access = %s 81 WHERE obj_id = %s AND user_id = %s',
82 array(
'text',
'timestamp',
'timestamp',
'integer',
'integer'),
83 array($last_visited, $endDate, date(
'Y-m-d H:i:s'), $packageId, $userId)
87 header(
'Content-Type: text/plain; charset=UTF-8');
95 $ilDB = $DIC->database();
97 'select hash from sahs_user where obj_id=%s AND user_id=%s AND hash_end>%s',
98 array(
'integer',
'integer',
'timestamp'),
99 array($packageId, $userId, date(
'Y-m-d H:i:s'))
102 if ($rowtmp && (
int) $rowtmp[
'hash'] == $hash) {
109 protected static function ensureObjectDataCacheExistence():
void 116 $ilObjDataCache = $DIC[
"ilObjDataCache"];
121 $ilObjDataCache =
new ilObjectDataCache();
122 $GLOBALS[
'DIC'][
'ilObjDataCache'] = $ilObjDataCache;
133 ?
string $data = null,
140 if ($defaultLessonMode ===
"browse") {
144 $jsMode = strpos(
$_SERVER[
'HTTP_ACCEPT'],
'text/javascript') !==
false;
146 $data = json_decode(is_string(
$data) ?
$data : file_get_contents(
'php://input'));
147 $ilLog->debug(
"dataTo_setCMIData: " . file_get_contents(
'php://input'));
151 if ($userId == null) {
153 self::checkIfAllowed($packageId, $userId,
$data->hash);
167 $new_global_status =
$data->now_global_status;
168 $return[
"new_global_status"] = $new_global_status;
171 $score_scaled =
$data->node[0][35];
172 if ($score_scaled != null) {
180 $ilLog->debug(
"SCORM: return of persistCMIData: " . json_encode($return));
182 header(
'Content-Type: text/javascript; charset=UTF-8');
183 print(json_encode($return));
185 header(
'Content-Type: text/html; charset=UTF-8');
186 print(var_export($return,
true));
198 bool $getInteractions,
203 $ilDB = $DIC->database();
212 $i_check = $data->i_check;
213 $i_set = $data->i_set;
214 $b_node_update =
false;
216 $a_map_cmi_interaction_id = array();
218 $tables = array(
'node',
'comment',
'interaction',
'objective',
'correct_response');
220 foreach ($tables as $table) {
221 if (!is_array($data->$table)) {
225 $ilLog->debug(
"SCORM: setCMIData, table -" . $table .
"-");
228 foreach ($data->$table as &$row) {
229 $ilLog->debug(
"Checking table: " . $table);
235 'SELECT cmi_node_id FROM cmi_node WHERE cp_node_id = %s and user_id = %s',
236 array(
'integer',
'integer'),
237 array($row[19], $userId)
241 if ($rowtmp != null) {
242 $cmi_node_id = $rowtmp[
'cmi_node_id'];
243 $b_node_update =
true;
245 $cmi_node_id =
$ilDB->nextId(
'cmi_node');
246 $b_node_update =
false;
248 $ilLog->debug(
"setCMIdata with cmi_node_id = " . $cmi_node_id);
250 'accesscount' => array(
'integer', $row[0]),
251 'accessduration' => array(
'text', $row[1]),
252 'accessed' => array(
'text', $row[2]),
253 'activityabsduration' => array(
'text', $row[3]),
254 'activityattemptcount' => array(
'integer', $row[4]),
255 'activityexpduration' => array(
'text', $row[5]),
256 'activityprogstatus' => array(
'integer', $row[6]),
257 'attemptabsduration' => array(
'text', $row[7]),
258 'attemptcomplamount' => array(
'float', $row[8]),
259 'attemptcomplstatus' => array(
'integer', $row[9]),
260 'attemptexpduration' => array(
'text', $row[10]),
261 'attemptprogstatus' => array(
'integer', $row[11]),
262 'audio_captioning' => array(
'integer', $row[12]),
263 'audio_level' => array(
'float', $row[13]),
264 'availablechildren' => array(
'text', $row[14]),
265 'cmi_node_id' => array(
'integer', $cmi_node_id),
266 'completion' => array(
'float', $row[16]),
267 'completion_status' => array(
'text', $row[17]),
268 'completion_threshold' => array(
'text', $row[18]),
269 'cp_node_id' => array(
'integer', $row[19]),
270 'created' => array(
'text', $row[20]),
271 'credit' => array(
'text', $row[21]),
272 'delivery_speed' => array(
'float', $row[22]),
273 'c_entry' => array(
'text', $row[23]),
274 'c_exit' => array(
'text', $row[24]),
275 'c_language' => array(
'text', $row[25]),
276 'launch_data' => array(
'clob', $row[26]),
277 'learner_name' => array(
'text', $row[27]),
278 'location' => array(
'text', $row[28]),
279 'c_max' => array(
'float', $row[29]),
280 'c_min' => array(
'float', $row[30]),
281 'c_mode' => array(
'text', $row[31]),
282 'modified' => array(
'text', $row[32]),
283 'progress_measure' => array(
'float', $row[33]),
284 'c_raw' => array(
'float', $row[34]),
285 'scaled' => array(
'float', $row[35]),
286 'scaled_passing_score' => array(
'float', $row[36]),
287 'session_time' => array(
'text', $row[37]),
288 'success_status' => array(
'text', $row[38]),
289 'suspend_data' => array(
'clob', $row[39]),
290 'total_time' => array(
'text', $row[40]),
291 'user_id' => array(
'integer', $userId),
292 'c_timestamp' => array(
'timestamp', date(
'Y-m-d H:i:s')),
293 'additional_tables' => array(
'integer', $i_check)
296 if ($b_node_update ==
false) {
297 $ilDB->insert(
'cmi_node', $a_data);
298 $ilLog->debug(
"inserted");
300 $ilDB->update(
'cmi_node', $a_data, array(
'cmi_node_id' => array(
'integer', $cmi_node_id)));
301 $ilLog->debug(
"updated");
304 if ($b_node_update ==
true) {
309 $q =
'DELETE FROM cmi_comment WHERE cmi_node_id = %s';
310 $ilDB->manipulateF($q, array(
'integer'), array($cmi_node_id));
315 if ($getInteractions) {
316 $q =
'DELETE FROM cmi_correct_response 317 WHERE cmi_interaction_id IN ( 318 SELECT cmi_interaction.cmi_interaction_id FROM cmi_interaction WHERE cmi_interaction.cmi_node_id = %s)';
319 $ilDB->manipulateF($q, array(
'integer'), array($cmi_node_id));
324 if ($getInteractions) {
325 $q =
'DELETE FROM cmi_interaction WHERE cmi_node_id = %s';
326 $ilDB->manipulateF($q, array(
'integer'), array($cmi_node_id));
331 if ($getObjectives) {
332 $q =
'DELETE FROM cmi_objective WHERE cmi_node_id = %s';
333 $ilDB->manipulateF($q, array(
'integer'), array($cmi_node_id));
339 $result[(string) $row[19]] = $cmi_node_id;
343 $row[0] =
$ilDB->nextId(
'cmi_comment');
345 $ilDB->insert(
'cmi_comment', array(
346 'cmi_comment_id' => array(
'integer', $row[0]),
347 'cmi_node_id' => array(
'integer', $cmi_node_id),
348 'c_comment' => array(
'clob', $row[2]),
349 'c_timestamp' => array(
'text', $row[3]),
350 'location' => array(
'text', $row[4]),
351 'sourceislms' => array(
'integer', $row[5])
356 $cmi_interaction_id =
$ilDB->nextId(
'cmi_interaction');
357 $a_map_cmi_interaction_id[] = array($row[0], $cmi_interaction_id);
358 $ilDB->insert(
'cmi_interaction', array(
359 'cmi_interaction_id' => array(
'integer', $cmi_interaction_id),
360 'cmi_node_id' => array(
'integer', $cmi_node_id),
361 'description' => array(
'clob', $row[2]),
362 'id' => array(
'text', $row[3]),
363 'latency' => array(
'text', $row[4]),
364 'learner_response' => array(
'clob', $row[5]),
365 'result' => array(
'text', $row[6]),
366 'c_timestamp' => array(
'text', $row[7]),
367 'c_type' => array(
'text', $row[8]),
368 'weighting' => array(
'float', $row[9])
373 $row[2] =
$ilDB->nextId(
'cmi_objective');
374 $cmi_interaction_id = null;
375 if ($row[0] != null) {
376 foreach ($a_map_cmi_interaction_id as
$i => $value) {
377 if ($row[0] == $value[0]) {
378 $cmi_interaction_id = $value[1];
382 $ilDB->insert(
'cmi_objective', array(
383 'cmi_interaction_id' => array(
'integer', $cmi_interaction_id),
384 'cmi_node_id' => array(
'integer', $cmi_node_id),
385 'cmi_objective_id' => array(
'integer', $row[2]),
386 'completion_status' => array(
'text', $row[3]),
387 'description' => array(
'clob', $row[4]),
388 'id' => array(
'text', $row[5]),
389 'c_max' => array(
'float', $row[6]),
390 'c_min' => array(
'float', $row[7]),
391 'c_raw' => array(
'float', $row[8]),
392 'scaled' => array(
'float', $row[9]),
393 'progress_measure' => array(
'float', $row[10]),
394 'success_status' => array(
'text', $row[11]),
395 'scope' => array(
'text', $row[12])
399 case 'correct_response':
400 $cmi_interaction_id = null;
401 if ($row[1] !== null) {
402 foreach ($a_map_cmi_interaction_id as
$i => $value) {
403 if ($row[1] == $value[0]) {
404 $cmi_interaction_id = $value[1];
407 $row[0] =
$ilDB->nextId(
'cmi_correct_response');
408 $ilDB->insert(
'cmi_correct_response', array(
409 'cmi_correct_resp_id' => array(
'integer', $row[0]),
410 'cmi_interaction_id' => array(
'integer', $cmi_interaction_id),
411 'pattern' => array(
'text', $row[2])
424 $changed_seq_utilities = $data->changed_seq_utilities;
425 $ilLog->debug(
"SCORM2004 adl_seq_utilities changed: " . $changed_seq_utilities);
426 if ($changed_seq_utilities == 1) {
437 public static function writeGObjective(
int $user,
int $package, ?array $g_data): array
440 $ilDB = $DIC->database();
442 $ilLog->debug(
"SCORM2004 writeGObjective");
444 $returnAr = array(null, null, null);
447 if ($g_data == null) {
451 $rows_to_insert = array();
453 foreach ($g_data as
$key => $value) {
454 $ilLog->debug(
"SCORM2004 writeGObjective -key: " .
$key);
458 foreach ($value as $skey => $svalue) {
459 $ilLog->debug(
"SCORM2004 writeGObjective -skey: " . $skey);
472 if (isset($svalue->$user->$package)) {
473 $o_value = $svalue->$user->$package;
483 $objective_id = $skey;
486 if (
$key ===
"status") {
491 $completed = $svalue->$user->{
"completed"};
492 $measure = $svalue->$user->{
"measure"};
493 $satisfied = $svalue->$user->{
"satisfied"};
495 $returnAr = array($completed, $satisfied, $measure);
497 $obj =
'-course_overall_status-';
502 SELECT user_id FROM cmi_gobjective 503 WHERE objective_id =%s 506 array(
'text',
'integer',
'integer'),
507 array($obj, $dbuser, $pkg_id)
509 $ilLog->debug(
"SCORM2004 Count is: " .
$ilDB->numRows(
$res));
513 INSERT INTO cmi_gobjective 514 (user_id, status, scope_id, measure, satisfied, objective_id) 515 VALUES (%s, %s, %s, %s, %s, %s)',
516 array(
'integer',
'text',
'integer',
'text',
'text',
'text'),
517 array($dbuser, $completed, $pkg_id, $measure, $satisfied, $obj)
519 $ilLog->debug(
"SCORM2004 cmi_gobjective Insert status=" . $completed .
" scope_id=" . $pkg_id .
" measure=" . $measure .
" satisfied=" . $satisfied .
" objective_id=" . $obj);
523 UPDATE cmi_gobjective 527 WHERE objective_id = %s 530 array(
'text',
'text',
'text',
'text',
'integer',
'integer'),
531 array($completed, $measure, $satisfied, $obj, $dbuser, $pkg_id)
537 if ($rows_to_insert[$objective_id] == null) {
538 $rows_to_insert[$objective_id] = array();
540 $rows_to_insert[$objective_id][
$key] = $toset;
547 "SELECT global_to_system FROM cp_package WHERE obj_id = %s",
552 $scope_id = (
$ilDB->fetchObject(
$res)->global_to_system) ? 0 : $package;
555 $existing_key_template =
"";
556 foreach (array_keys($rows_to_insert) as $obj_id) {
557 $existing_key_template .=
"'{$obj_id}',";
560 $existing_key_template = substr($existing_key_template, 0, -1);
561 $existing_keys = array();
563 if ($existing_key_template !=
"") {
570 AND objective_id IN ($existing_key_template)",
571 array(
'integer',
'integer'),
572 array($dbuser, $scope_id)
576 $existing_keys[] = $row[
'objective_id'];
580 foreach ($rows_to_insert as $obj_id => $vals) {
581 if (in_array($obj_id, $existing_keys)) {
583 "UPDATE cmi_gobjective 589 completion_status=%s, 591 WHERE objective_id = %s 605 array($vals[
'satisfied'],
610 $vals[
"completion_status"],
611 $vals[
"progress_measure"],
619 "INSERT INTO cmi_gobjective 620 (user_id, satisfied, measure, scope_id, status, objective_id, 621 score_raw, score_min, score_max, progress_measure, completion_status) 622 VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
644 $vals[
'progress_measure'],
645 $vals[
'completion_status']
661 $ilDB = $DIC->database();
662 $ilLog = $DIC[
"ilLog"];
663 $saved_global_status = $data->saved_global_status;
664 $ilLog->write(
"saved_global_status=" . $saved_global_status);
667 $totalTime = (
int) $data->totalTimeCentisec;
668 $totalTime = round($totalTime / 100);
670 'UPDATE sahs_user SET sco_total_time_sec=%s, status=%s, percentage_completed=%s WHERE obj_id = %s AND user_id = %s',
671 array(
'integer',
'integer',
'integer',
'integer',
'integer'),
672 array($totalTime, $new_global_status, $data->percentageCompleted, $packageId, $userId)
675 self::ensureObjectDataCacheExistence();
677 $ilObjDataCache = $DIC[
"ilObjDataCache"];
680 if ($new_global_status != null) {
686 if ($time_from_lms ==
false) {
static persistCMIData(int $packageId, int $refId, string $defaultLessonMode, bool $comments, bool $interactions, bool $objectives, bool $time_from_lms, ?string $data=null, ?int $userId=null)
static getLogger(string $a_component_id)
Get component logger.
if($DIC->http() ->wrapper() ->query() ->has('do')) $defaultLessonMode
static checkIfAllowed(int $packageId, int $userId, int $hash)
static setCMIData(int $userId, int $packageId, object $data, bool $getComments, bool $getInteractions, bool $getObjectives)
static syncGlobalStatus(int $userId, int $packageId, int $refId, object $data, int $new_global_status, bool $time_from_lms)
static writeGObjective(int $user, int $package, ?array $g_data)
Class ilSCORM2004StoreData.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static scormPlayerUnload(int $packageId, int $refId, bool $time_from_lms, ?int $userId=null)
static setGlobalObjectives(int $userId, int $packageId, object $data)
static getQuantityOfSCOs(int $a_slm_id)
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
static handleOutcomeWithoutLP(int $a_obj_id, int $a_usr_id, ?float $a_percentage)
static _syncReadEvent(int $a_obj_id, int $a_user_id, string $a_type, int $a_ref_id, ?bool $time_from_lms=null)
Synch read event table.
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.