19 declare(strict_types=1);
33 $lng = $DIC->language();
34 $lng->loadLanguageModule(
"scormtrac");
37 $udh = self::userDataHeaderForExport();
40 'lm_id,lm_title,identifierref,sco_id,sco_marked_for_learning_progress,sco_title,' . $udh[
"cols"]
41 .
',c_timestamp,lvalue,rvalue' 43 $a_true = explode(
',', $udh[
"default"] .
",identifierref,c_timestamp,lvalue,rvalue");
44 for ($i = 0, $iMax = count($a_cols); $i < $iMax; $i++) {
45 $cols[$a_cols[$i]] = array(
"txt" =>
$lng->txt($a_cols[$i]),
"default" =>
false);
47 for ($i = 0, $iMax = count($a_true); $i < $iMax; $i++) {
48 $cols[$a_true[$i]][
"default"] =
true;
59 $allowExportPrivacy = $privacy->enabledExportSCORM();
60 $returnData = array();
61 if ($allowExportPrivacy ==
true) {
62 $returnData[
"cols"] =
'login,user,email,department';
64 $returnData[
"cols"] =
'user';
66 $returnData[
"default"] =
'user';
76 $lng = $DIC->language();
77 $lng->loadLanguageModule(
"scormtrac");
80 $udh = self::userDataHeaderForExport();
83 'lm_id,lm_title,sco_id,sco_marked_for_learning_progress,sco_title,' . $udh[
"cols"]
84 .
',lesson_status,credit,c_entry,c_exit,c_max,c_min,c_raw,session_time,total_time,c_timestamp,suspend_data,launch_data' 86 $a_true = explode(
',', $udh[
"default"] .
",sco_title,lesson_status");
87 for ($i = 0, $iMax = count($a_cols); $i < $iMax; $i++) {
88 $cols[$a_cols[$i]] = array(
"txt" =>
$lng->txt($a_cols[$i]),
"default" =>
false);
90 for ($i = 0, $iMax = count($a_true); $i < $iMax; $i++) {
91 $cols[$a_true[$i]][
"default"] =
true;
102 $lng = $DIC->language();
103 $lng->loadLanguageModule(
"scormtrac");
105 $udh = self::userDataHeaderForExport();
108 'lm_id,lm_title,sco_id,sco_marked_for_learning_progress,sco_title,' . $udh[
"cols"]
109 .
',counter,id,weighting,type,result,student_response,latency,time,c_timestamp' 111 $a_true = explode(
',', $udh[
"default"] .
",sco_title,id,result,student_response");
112 for ($i = 0, $iMax = count($a_cols); $i < $iMax; $i++) {
113 $cols[$a_cols[$i]] = array(
"txt" =>
$lng->txt($a_cols[$i]),
"default" =>
false);
115 for ($i = 0, $iMax = count($a_true); $i < $iMax; $i++) {
116 $cols[$a_true[$i]][
"default"] =
true;
127 $lng = $DIC->language();
128 $lng->loadLanguageModule(
"scormtrac");
130 $udh = self::userDataHeaderForExport();
133 'lm_id,lm_title,sco_id,sco_marked_for_learning_progress,sco_title,' . $udh[
"cols"]
134 .
',counter,id,c_max,c_min,c_raw,ostatus,c_timestamp' 136 $a_true = explode(
',', $udh[
"default"] .
",sco_title,id,c_raw,ostatus");
137 for ($i = 0, $iMax = count($a_cols); $i < $iMax; $i++) {
138 $cols[$a_cols[$i]] = array(
"txt" =>
$lng->txt($a_cols[$i]),
"default" =>
false);
140 for ($i = 0, $iMax = count($a_true); $i < $iMax; $i++) {
141 $cols[$a_true[$i]][
"default"] =
true;
152 $lng = $DIC->language();
153 $lng->loadLanguageModule(
"scormtrac");
157 $udh = self::userDataHeaderForExport();
158 $a_cols = explode(
',',
'LearningModuleId,LearningModuleTitle,LearningModuleVersion,' . $udh[
"cols"]
159 .
',status,Percentage,Attempts,existingSCOs,startedSCOs,completedSCOs,passedSCOs,roundedTotal_timeSeconds,offline_mode,last_access');
160 $a_true = explode(
',', $udh[
"default"] .
",LearningModuleTitle,status,Percentage,Attempts");
162 for ($i = 0, $iMax = count($a_cols); $i < $iMax; $i++) {
163 $cols[$a_cols[$i]] = array(
"txt" =>
$lng->txt($a_cols[$i]),
"default" =>
false);
165 for ($i = 0, $iMax = count($a_true); $i < $iMax; $i++) {
166 $cols[$a_true[$i]][
"default"] =
true;
178 bool $allowExportPrivacy,
183 $ilDB = $DIC->database();
184 $lng = $DIC->language();
185 $lng->loadLanguageModule(
"scormtrac");
187 $returnData = array();
193 $query =
'SELECT user_id, st.obj_id, sco_id, identifierref, c_timestamp, lvalue, rvalue ' 194 .
'FROM scorm_tracking st ' 195 .
'JOIN sc_item si ON st.sco_id = si.obj_id ' 196 .
'WHERE ' .
$ilDB->in(
'sco_id', $a_sco,
false,
'integer') .
' ' 197 .
'AND ' .
$ilDB->in(
'user_id', $a_user,
false,
'integer') .
' ' 201 $query .=
'sco_id, user_id';
203 $query .=
'user_id, sco_id';
207 $data[
"lm_id"] = $obj_id;
208 $data[
"lm_title"] = $lmTitle;
209 $data = array_merge(
$data, self::userDataArrayForExport((
int)
$data[
"user_id"], $allowExportPrivacy));
210 $data[
"sco_marked_for_learning_progress"] = $scoProgress[$data[
"sco_id"]];
211 $data[
"sco_title"] = $scoTitles[$data[
"sco_id"]];
212 $data[
"rvalue"] =
"" . $data[
"rvalue"];
214 $returnData[] =
$data;
226 $ilDB = $DIC->database();
227 $scoTitles = array();
229 $query =
'SELECT obj_id, title 231 WHERE slm_id = %s AND c_type = %s';
234 array(
'integer',
'text'),
235 array($obj_id,
'sit')
238 $scoTitles[$row[
'obj_id']] = $row[
'title'];
246 $lng = $DIC->language();
248 $collection = $olp->getCollectionInstance();
250 foreach ($a_scos as $sco_id => $value) {
251 if ($collection && $collection->isAssignedEntry($sco_id)) {
252 $a_scos[$sco_id] =
$lng->txt(
'yes');
254 $a_scos[$sco_id] =
$lng->txt(
'no');
262 $userArray = array();
263 if ($b_allowExportPrivacy ==
false) {
264 $userArray[
"user"] = $user;
267 $ilUser = $DIC->user();
268 $userArray[
"login"] =
"";
269 $userArray[
"user"] =
"";
270 $userArray[
"email"] =
"";
271 $userArray[
"department"] =
"";
274 $userArray[
"login"] = $e_user->getLogin();
275 $userArray[
"user"] = $e_user->getLastname() .
', ' . $e_user->getFirstname();
276 $userArray[
"email"] =
"" . $e_user->getEmail();
277 $userArray[
"department"] =
"" . $e_user->getDepartment();
290 bool $allowExportPrivacy,
295 $ilDB = $DIC->database();
296 $lng = $DIC->language();
297 $lng->loadLanguageModule(
"scormtrac");
299 $returnData = array();
307 foreach ($a_user as $value) {
308 $a_empty[$value] = array();
312 $query =
'SELECT user_id, sco_id, max(c_timestamp) as c_timestamp ' 313 .
'FROM scorm_tracking ' 314 .
'WHERE ' .
$ilDB->in(
'sco_id', $a_sco,
false,
'integer') .
' ' 315 .
'AND ' .
$ilDB->in(
'user_id', $a_user,
false,
'integer') .
' ' 316 .
'GROUP BY user_id, sco_id ' 319 $query .=
'sco_id, user_id';
321 $query .=
'user_id, sco_id';
326 $a_empty[$row[
"user_id"]][$row[
"sco_id"]] =
"";
329 $a_lesson_status = $this->
getScormTrackingValue($obj_id, $a_user, $a_sco, $a_empty,
'cmi.core.lesson_status');
336 $a_session_time = $this->
getScormTrackingValue($obj_id, $a_user, $a_sco, $a_empty,
'cmi.core.session_time');
337 $a_total_time = $this->
getScormTrackingValue($obj_id, $a_user, $a_sco, $a_empty,
'cmi.core.total_time');
338 $a_suspend_data = $this->
getScormTrackingValue($obj_id, $a_user, $a_sco, $a_empty,
'cmi.suspend_data');
339 $a_launch_data = $this->
getScormTrackingValue($obj_id, $a_user, $a_sco, $a_empty,
'cmi.launch_data');
341 foreach ($dbdata as
$data) {
342 $data[
"lm_id"] = $obj_id;
343 $data[
"lm_title"] = $lmTitle;
345 $data = array_merge($data, self::userDataArrayForExport((
int) $data[
"user_id"], $allowExportPrivacy));
347 $data[
"sco_marked_for_learning_progress"] = $scoProgress[$data[
"sco_id"]];
348 $data[
"sco_title"] = $scoTitles[$data[
"sco_id"]];
352 $data[
"lesson_status"] = $a_lesson_status[$data[
'user_id']][$data[
'sco_id']];
353 $data[
"credit"] = $a_credit[$data[
'user_id']][$data[
'sco_id']];
355 $data[
"c_entry"] = $a_c_entry[$data[
'user_id']][$data[
'sco_id']];
356 $data[
"c_exit"] = $a_c_exit[$data[
'user_id']][$data[
'sco_id']];
360 $data[
"c_max"] = $a_c_max[$data[
'user_id']][$data[
'sco_id']];
361 $data[
"c_min"] = $a_c_min[$data[
'user_id']][$data[
'sco_id']];
362 $data[
"c_raw"] = $a_c_raw[$data[
'user_id']][$data[
'sco_id']];
363 $data[
"session_time"] = $a_session_time[$data[
'user_id']][$data[
'sco_id']];
366 $data[
"total_time"] = $a_total_time[$data[
'user_id']][$data[
'sco_id']];
369 $data[
"c_timestamp"] = $data[
"c_timestamp"];
370 $data[
"suspend_data"] = $a_suspend_data[$data[
'user_id']][$data[
'sco_id']];
371 $data[
"launch_data"] = $a_launch_data[$data[
'user_id']][$data[
'sco_id']];
372 $returnData[] =
$data;
378 public function getScormTrackingValue(
int $obj_id, array $a_user, array $a_sco, array $a_empty,
string $lvalue): array
381 $ilDB = $DIC->database();
383 $query =
'SELECT user_id, sco_id, rvalue ' 384 .
'FROM scorm_tracking ' 385 .
'WHERE obj_id = %s ' 386 .
'AND ' .
$ilDB->in(
'user_id', $a_user,
false,
'integer') .
' ' 387 .
'AND ' .
$ilDB->in(
'sco_id', $a_sco,
false,
'integer') .
' ' 391 array(
'integer',
'text'),
392 array($obj_id, $lvalue)
395 if (!is_null(
$data[
'rvalue'])) {
396 $a_empty[
$data[
'user_id']][
$data[
'sco_id']] = $data[
'rvalue'];
409 bool $allowExportPrivacy,
414 $ilDB = $DIC->database();
416 $returnData = array();
424 $interactionsCounter = array();
427 $query =
'SELECT user_id, sco_id, lvalue, c_timestamp ' 428 .
'FROM scorm_tracking ' 429 .
'WHERE obj_id = %s AND ' .
$ilDB->in(
'sco_id', $a_sco,
false,
'integer') .
' ' 430 .
'AND ' .
$ilDB->in(
'user_id', $a_user,
false,
'integer') .
' ' 431 .
'AND left(lvalue,17) = %s ' 434 $query .=
'sco_id, user_id, lvalue';
436 $query .=
'user_id, sco_id, lvalue';
440 array(
'integer',
'text'),
441 array($obj_id,
'cmi.interactions.')
445 $tmpar = explode(
'.', $row[
"lvalue"]);
446 $tmpcounter = $tmpar[2];
447 if (in_array($tmpcounter, $interactionsCounter) ==
false) {
448 $interactionsCounter[] = $tmpcounter;
450 if ($tmpcounter != $prevcounter) {
452 $tmpar[
"user_id"] = $row[
"user_id"];
453 $tmpar[
"sco_id"] = $row[
"sco_id"];
454 $tmpar[
"counter"] = $tmpcounter;
456 $tmpar[
"weighting"] =
"";
458 $tmpar[
"result"] =
"";
459 $tmpar[
"student_response"] =
"";
460 $tmpar[
"latency"] =
"";
462 $tmpar[
"c_timestamp"] = $row[
"c_timestamp"];
464 $prevcounter = $tmpcounter;
470 $a_weighting = array();
473 $a_student_response = array();
474 $a_latency = array();
476 foreach ($interactionsCounter as $value) {
488 $a_weighting = array_merge(
499 $a_type = array_merge(
510 $a_result = array_merge(
521 $a_student_response = array_merge(
532 $a_latency = array_merge(
543 $a_time = array_merge(
555 foreach ($dbdata as
$data) {
556 $data[
"lm_id"] = $obj_id;
557 $data[
"lm_title"] = $lmTitle;
559 $data = array_merge($data, self::userDataArrayForExport((
int) $data[
"user_id"], $allowExportPrivacy));
561 $data[
"sco_marked_for_learning_progress"] = $scoProgress[$data[
"sco_id"]];
562 $data[
"sco_title"] = $scoTitles[$data[
"sco_id"]];
564 $combinedId =
'' . $data[
"user_id"] .
'-' . $data[
"sco_id"] .
'-' . $data[
"counter"];
565 if (array_key_exists($combinedId, $a_id)) {
566 $data[
"id"] = $a_id[$combinedId];
568 if (array_key_exists($combinedId, $a_weighting)) {
569 $data[
"weighting"] = $a_weighting[$combinedId];
571 if (array_key_exists($combinedId, $a_type)) {
572 $data[
"type"] = $a_type[$combinedId];
574 if (array_key_exists($combinedId, $a_result)) {
575 $data[
"result"] = $a_result[$combinedId];
577 if (array_key_exists($combinedId, $a_student_response)) {
578 $data[
"student_response"] = $a_student_response[$combinedId];
580 if (array_key_exists($combinedId, $a_latency)) {
581 $data[
"latency"] = $a_latency[$combinedId];
583 if (array_key_exists($combinedId, $a_time)) {
584 $data[
"time"] = $a_time[$combinedId];
588 $returnData[] =
$data;
607 $ilDB = $DIC->database();
609 $query =
'SELECT user_id, sco_id, rvalue ' 610 .
'FROM scorm_tracking ' 611 .
'WHERE obj_id = %s ' 612 .
'AND ' .
$ilDB->in(
'user_id', $a_user,
false,
'integer') .
' ' 613 .
'AND ' .
$ilDB->in(
'sco_id', $a_sco,
false,
'integer') .
' ' 617 array(
'integer',
'text'),
618 array($obj_id,
'cmi.' . $topic .
'.' . $counter .
'.' . $lvalue)
621 if (!is_null(
$data[
'rvalue'])) {
622 $a_return[
'' .
$data[
'user_id'] .
'-' .
$data[
'sco_id'] .
'-' . $counter] =
$data[
'rvalue'];
635 bool $allowExportPrivacy,
640 $ilDB = $DIC->database();
642 $returnData = array();
650 $objectivesCounter = array();
653 $query =
'SELECT user_id, sco_id, lvalue, c_timestamp ' 654 .
'FROM scorm_tracking ' 655 .
'WHERE obj_id = %s AND ' .
$ilDB->in(
'sco_id', $a_sco,
false,
'integer') .
' ' 656 .
'AND ' .
$ilDB->in(
'user_id', $a_user,
false,
'integer') .
' ' 657 .
'AND left(lvalue,15) = %s ' 660 $query .=
'sco_id, user_id, lvalue';
662 $query .=
'user_id, sco_id, lvalue';
666 array(
'integer',
'text'),
667 array($obj_id,
'cmi.objectives.')
671 $tmpar = explode(
'.', $row[
"lvalue"]);
672 $tmpcounter = $tmpar[2];
673 if (in_array($tmpcounter, $objectivesCounter) ==
false) {
674 $objectivesCounter[] = $tmpcounter;
676 if ($tmpcounter != $prevcounter) {
678 $tmpar[
"user_id"] = $row[
"user_id"];
679 $tmpar[
"sco_id"] = $row[
"sco_id"];
680 $tmpar[
"counter"] = $tmpcounter;
682 $tmpar[
"c_max"] =
"";
683 $tmpar[
"c_min"] =
"";
684 $tmpar[
"c_raw"] =
"";
685 $tmpar[
"ostatus"] =
"";
686 $tmpar[
"c_timestamp"] = $row[
"c_timestamp"];
688 $prevcounter = $tmpcounter;
696 foreach ($objectivesCounter as $value) {
708 $a_c_max = array_merge(
719 $a_c_min = array_merge(
730 $a_c_raw = array_merge(
741 $a_status = array_merge(
753 foreach ($dbdata as
$data) {
754 $data[
"lm_id"] = $obj_id;
755 $data[
"lm_title"] = $lmTitle;
757 $data = array_merge($data, self::userDataArrayForExport((
int) $data[
"user_id"], $allowExportPrivacy));
759 $data[
"sco_marked_for_learning_progress"] = $scoProgress[$data[
"sco_id"]];
760 $data[
"sco_title"] = $scoTitles[$data[
"sco_id"]];
762 $combinedId =
'' . $data[
"user_id"] .
'-' . $data[
"sco_id"] .
'-' . $data[
"counter"];
763 if (array_key_exists($combinedId, $a_id)) {
764 $data[
"id"] = $a_id[$combinedId];
766 if (array_key_exists($combinedId, $a_c_max)) {
767 $data[
"c_max"] = $a_c_max[$combinedId];
769 if (array_key_exists($combinedId, $a_c_min)) {
770 $data[
"c_min"] = $a_c_min[$combinedId];
772 if (array_key_exists($combinedId, $a_c_raw)) {
773 $data[
"c_raw"] = $a_c_raw[$combinedId];
775 if (array_key_exists($combinedId, $a_status)) {
776 $data[
"ostatus"] = $a_status[$combinedId];
780 $returnData[] =
$data;
793 $ilDB = $DIC->database();
796 $query =
'SELECT count(distinct(scorm_object.obj_id)) counter ' 797 .
'FROM scorm_object, sc_item, sc_resource ' 798 .
'WHERE scorm_object.slm_id = %s ' 799 .
'AND scorm_object.obj_id = sc_item.obj_id ' 800 .
'AND sc_item.identifierref = sc_resource.import_id ' 801 .
'AND (sc_resource.scormtype = %s OR sc_resource.scormtype is null)';
804 array(
'integer',
'text'),
805 array($obj_id,
'sco')
808 $scoCounter = (
int) $row[
'counter'];
812 $u_startedSCO = array();
813 $u_completedSCO = array();
814 $u_passedSCO = array();
815 foreach ($a_user as $value) {
816 $u_startedSCO[$value] = 0;
817 $u_completedSCO[$value] = 0;
818 $u_passedSCO[$value] = 0;
821 $query =
'SELECT user_id, count(distinct(SCO_ID)) counter ' 822 .
'FROM scorm_tracking ' 823 .
'WHERE obj_id = %s ' 825 .
'AND ' .
$ilDB->in(
'user_id', $a_user,
false,
'integer') .
' ' 826 .
'GROUP BY user_id';
833 $u_startedSCO[
$data[
'user_id']] = $data[
'counter'];
836 $query =
'SELECT user_id, count(*) counter ' 837 .
'FROM scorm_tracking ' 838 .
'WHERE obj_id = %s AND lvalue = %s AND rvalue like %s ' 839 .
'AND ' .
$ilDB->in(
'user_id', $a_user,
false,
'integer') .
' ' 840 .
'GROUP BY user_id';
843 array(
'integer',
'text',
'text'),
844 array($obj_id,
'cmi.core.lesson_status',
'completed')
847 $u_completedSCO[
$data[
'user_id']] = $data[
'counter'];
852 array(
'integer',
'text',
'text'),
853 array($obj_id,
'cmi.core.lesson_status',
'passed')
856 $u_passedSCO[
$data[
'user_id']] = $data[
'counter'];
861 $query =
'SELECT * FROM sahs_user WHERE obj_id = ' .
$ilDB->quote($obj_id,
'integer')
862 .
' AND ' .
$ilDB->in(
'user_id', $a_user,
false,
'integer')
863 .
' ORDER BY user_id';
886 bool $allowExportPrivacy,
890 array $u_completedSCO,
895 $returnData = array();
896 foreach ($dbdata as
$data) {
898 $dat[
"LearningModuleId"] = $obj_id;
899 $dat[
"LearningModuleTitle"] =
"" . $lmTitle;
900 $dat[
"LearningModuleVersion"] =
"" . $data[
"module_version"];
902 $dat = array_merge($dat, self::userDataArrayForExport((
int) $data[
"user_id"], $allowExportPrivacy));
904 $dat[
"status"] =
"" . $data[
"status"];
905 $dat[
"Percentage"] =
"" . $data[
"percentage_completed"];
906 $dat[
"Attempts"] =
"" . $data[
"package_attempts"];
907 $dat[
"existingSCOs"] =
"" . $scoCounter;
908 $dat[
"startedSCOs"] =
"" . $u_startedSCO[$data[
"user_id"]];
909 $dat[
"completedSCOs"] =
"" . $u_completedSCO[$data[
"user_id"]];
910 $dat[
"passedSCOs"] =
"" . $u_passedSCO[$data[
"user_id"]];
911 $dat[
"roundedTotal_timeSeconds"] =
"" . $data[
"sco_total_time_sec"];
912 if (is_null($data[
"offline_mode"])) {
913 $dat[
"offline_mode"] =
"";
915 $dat[
"offline_mode"] = $data[
"offline_mode"];
917 $dat[
"last_access"] =
"" . $data[
"last_access"];
918 $returnData[] = $dat;
928 $tarr = explode(
":", $a_time);
930 if (count($tarr) != 3 || is_nan((
float) $tarr[0]) || is_nan((
float) $tarr[1]) || is_nan((
float) $tarr[2])) {
933 $csec = (
int) $tarr[0] * 360000 + (
int) $tarr[1] * 6000 + $tarr[2] * 100;
934 return round($csec / 100);
exportSelectedSuccessRows(array $a_user, bool $allowExportPrivacy, array $dbdata, int $scoCounter, array $u_startedSCO, array $u_completedSCO, array $u_passedSCO, int $obj_id, string $lmTitle)
static exportSelectedRawColumns()
SCORMTimeToSeconds(string $a_time)
exportSelectedInteractions(array $a_user, array $a_sco, bool $b_orderBySCO, bool $allowExportPrivacy, int $obj_id, string $lmTitle)
static exportSelectedCoreColumns(bool $b_orderBySCO, bool $b_allowExportPrivacy)
static exportSelectedInteractionsColumns()
scoTitlesForExportSelected(int $obj_id)
static exportSelectedSuccessColumns()
exportSelectedObjectives(array $a_user, array $a_sco, bool $b_orderBySCO, bool $allowExportPrivacy, int $obj_id, string $lmTitle)
static _exists(int $id, bool $reference=false, ?string $type=null)
checks if an object exists in object_data
getScormTrackingValue(int $obj_id, array $a_user, array $a_sco, array $a_empty, string $lvalue)
markedLearningStatusForExportSelected(array $a_scos, int $obj_id)
static userDataArrayForExport(int $user, bool $b_allowExportPrivacy=false)
static userDataHeaderForExport()
static exportSelectedObjectivesColumns()
exportSelectedCore(array $a_user, array $a_sco, bool $b_orderBySCO, bool $allowExportPrivacy, int $obj_id, string $lmTitle)
exportSelectedSuccess(array $a_user, bool $allowExportPrivacy, int $obj_id, string $lmTitle)
Class ilSCORMTrackingItems.
static getInstance(int $obj_id)
exportSelectedRaw(array $a_user, array $a_sco, bool $b_orderBySCO, bool $allowExportPrivacy, int $obj_id, string $lmTitle)
getScormTrackingValueForInteractionsOrObjectives(int $obj_id, array $a_user, array $a_sco, string $lvalue, int $counter, string $topic)