19declare(strict_types=1);
34 $lng->loadLanguageModule(
"scormtrac");
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';
77 $lng->loadLanguageModule(
"scormtrac");
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;
103 $lng->loadLanguageModule(
"scormtrac");
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;
128 $lng->loadLanguageModule(
"scormtrac");
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;
153 $lng->loadLanguageModule(
"scormtrac");
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,
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"]];
214 $returnData[] =
$data;
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'];
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,
297 $lng->loadLanguageModule(
"scormtrac");
299 $returnData = array();
301 $scoTitles = $this->scoTitlesForExportSelected($obj_id);
303 $scoProgress = $this->markedLearningStatusForExportSelected($scoTitles, $obj_id);
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');
330 $a_credit = $this->getScormTrackingValue($obj_id, $a_user, $a_sco, $a_empty,
'cmi.core.credit');
331 $a_c_entry = $this->getScormTrackingValue($obj_id, $a_user, $a_sco, $a_empty,
'cmi.core.entry');
332 $a_c_exit = $this->getScormTrackingValue($obj_id, $a_user, $a_sco, $a_empty,
'cmi.core.exit');
333 $a_c_max = $this->getScormTrackingValue($obj_id, $a_user, $a_sco, $a_empty,
'cmi.core.score.max');
334 $a_c_min = $this->getScormTrackingValue($obj_id, $a_user, $a_sco, $a_empty,
'cmi.core.score.min');
335 $a_c_raw = $this->getScormTrackingValue($obj_id, $a_user, $a_sco, $a_empty,
'cmi.core.score.raw');
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']];
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']];
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
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'])) {
409 bool $allowExportPrivacy,
416 $returnData = array();
418 $scoTitles = $this->scoTitlesForExportSelected($obj_id);
420 $scoProgress = $this->markedLearningStatusForExportSelected($scoTitles, $obj_id);
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) {
479 $this->getScormTrackingValueForInteractionsOrObjectives(
488 $a_weighting = array_merge(
490 $this->getScormTrackingValueForInteractionsOrObjectives(
499 $a_type = array_merge(
501 $this->getScormTrackingValueForInteractionsOrObjectives(
510 $a_result = array_merge(
512 $this->getScormTrackingValueForInteractionsOrObjectives(
521 $a_student_response = array_merge(
523 $this->getScormTrackingValueForInteractionsOrObjectives(
532 $a_latency = array_merge(
534 $this->getScormTrackingValueForInteractionsOrObjectives(
543 $a_time = array_merge(
545 $this->getScormTrackingValueForInteractionsOrObjectives(
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;
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'])) {
635 bool $allowExportPrivacy,
642 $returnData = array();
644 $scoTitles = $this->scoTitlesForExportSelected($obj_id);
646 $scoProgress = $this->markedLearningStatusForExportSelected($scoTitles, $obj_id);
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) {
699 $this->getScormTrackingValueForInteractionsOrObjectives(
708 $a_c_max = array_merge(
710 $this->getScormTrackingValueForInteractionsOrObjectives(
719 $a_c_min = array_merge(
721 $this->getScormTrackingValueForInteractionsOrObjectives(
730 $a_c_raw = array_merge(
732 $this->getScormTrackingValueForInteractionsOrObjectives(
741 $a_status = array_merge(
743 $this->getScormTrackingValueForInteractionsOrObjectives(
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;
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';
868 return $this->exportSelectedSuccessRows(
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);
static getInstance(int $obj_id)
static _exists(int $id, bool $reference=false, ?string $type=null)
checks if an object exists in object_data
Class ilSCORMTrackingItems.
exportSelectedRaw(array $a_user, array $a_sco, bool $b_orderBySCO, bool $allowExportPrivacy, int $obj_id, string $lmTitle)
markedLearningStatusForExportSelected(array $a_scos, int $obj_id)
exportSelectedObjectives(array $a_user, array $a_sco, bool $b_orderBySCO, bool $allowExportPrivacy, int $obj_id, string $lmTitle)
static exportSelectedSuccessColumns()
static exportSelectedObjectivesColumns()
scoTitlesForExportSelected(int $obj_id)
static exportSelectedRawColumns()
exportSelectedSuccess(array $a_user, bool $allowExportPrivacy, int $obj_id, string $lmTitle)
static userDataHeaderForExport()
static exportSelectedCoreColumns(bool $b_orderBySCO, bool $b_allowExportPrivacy)
static userDataArrayForExport(int $user, bool $b_allowExportPrivacy=false)
getScormTrackingValue(int $obj_id, array $a_user, array $a_sco, array $a_empty, string $lvalue)
static exportSelectedInteractionsColumns()
getScormTrackingValueForInteractionsOrObjectives(int $obj_id, array $a_user, array $a_sco, string $lvalue, int $counter, string $topic)
exportSelectedCore(array $a_user, array $a_sco, bool $b_orderBySCO, bool $allowExportPrivacy, int $obj_id, string $lmTitle)
exportSelectedSuccessRows(array $a_user, bool $allowExportPrivacy, array $dbdata, int $scoCounter, array $u_startedSCO, array $u_completedSCO, array $u_passedSCO, int $obj_id, string $lmTitle)
exportSelectedInteractions(array $a_user, array $a_sco, bool $b_orderBySCO, bool $allowExportPrivacy, int $obj_id, string $lmTitle)
SCORMTimeToSeconds(string $a_time)