66 private function __construct($a_id, $a_by_obj_id =
false, $a_user_id)
70 $this->db = $DIC->database();
71 $this->lng = $DIC->language();
72 $this->plugin_admin = $DIC[
"ilPluginAdmin"];
73 $this->
user = $DIC->user();
74 $this->user_id = $a_user_id;
78 $this->lm_obj_id = $a_id;
80 $this->lm_ref_id = $a_id;
84 include_once(
"./Modules/LearningModule/classes/class.ilLMTree.php");
100 if ($a_user_id == 0) {
104 if (!isset(self::$instances[$a_ref_id][$a_user_id])) {
105 self::$instances[$a_ref_id][$a_user_id] =
new ilLMTracker($a_ref_id,
false, $a_user_id);
107 return self::$instances[$a_ref_id][$a_user_id];
122 if ($a_user_id == 0) {
126 if (!isset(self::$instancesbyobj[$a_obj_id][$a_user_id])) {
127 self::$instancesbyobj[$a_obj_id][$a_user_id] =
new ilLMTracker($a_obj_id,
true, $a_user_id);
129 return self::$instancesbyobj[$a_obj_id][$a_user_id];
143 if ($this->lm_ref_id == 0) {
144 die(
"ilLMTracker: No Ref Id given.");
155 include_once(
"./Services/Tracking/classes/class.ilLearningProgress.php");
164 include_once(
"./Services/Tracking/classes/class.ilLPStatusWrapper.php");
183 $q =
"DELETE FROM lo_access " .
184 "WHERE usr_id = " .
$ilDB->quote((
int) $usr_id,
"integer") .
" " .
185 "AND lm_id = " .
$ilDB->quote((
int) $lm_id,
"integer");
186 $ilDB->manipulate($q);
190 $q =
"INSERT INTO lo_access " .
191 "(timestamp,usr_id,lm_id,obj_id,lm_title) " .
193 "(" .
$ilDB->now() .
"," .
194 $ilDB->quote((
int) $usr_id,
"integer") .
"," .
195 $ilDB->quote((
int) $lm_id,
"integer") .
"," .
196 $ilDB->quote((
int) $obj_id,
"integer") .
"," .
198 $ilDB->manipulate($q);
214 $set =
$ilDB->query(
"SELECT obj_id FROM lm_read_event" .
215 " WHERE obj_id = " .
$ilDB->quote($a_page_id,
"integer") .
216 " AND usr_id = " .
$ilDB->quote($this->user_id,
"integer"));
217 if (!
$ilDB->fetchAssoc($set)) {
219 "obj_id" =>
array(
"integer", $a_page_id),
220 "usr_id" =>
array(
"integer", $this->user_id)
223 $ilDB->replace(
"lm_read_event", $fields,
array());
227 $ilDB->manipulate(
"UPDATE lm_read_event SET" .
228 " read_count = read_count + 1 " .
229 " , last_access = " .
$ilDB->quote($now,
"integer") .
230 " WHERE obj_id = " .
$ilDB->quote($a_page_id,
"integer") .
231 " AND usr_id = " .
$ilDB->quote($this->user_id,
"integer"));
239 $set =
$ilDB->query(
"SELECT * FROM lo_access WHERE " .
240 "usr_id = " .
$ilDB->quote($this->user_id,
"integer") .
" AND " .
241 "lm_id = " .
$ilDB->quote($this->lm_ref_id,
"integer"));
243 if (
$res[
"obj_id"]) {
244 include_once(
'Services/Tracking/classes/class.ilObjUserTracking.php');
249 $pg_id =
$res[
"obj_id"];
250 if (!$this->lm_tree->isInTree($pg_id)) {
254 $time_diff = $read_diff = 0;
257 if (($now-$pg_ts) <= $valid_timespan) {
258 $time_diff = $now-$pg_ts;
264 $parent_st_ids =
array();
265 foreach ($this->lm_tree->getPathFull($pg_id) as $item) {
266 if ($item[
"type"] ==
"st") {
267 $parent_st_ids[] = $item[
"obj_id"];
271 if ($parent_st_ids && ($time_diff || $read_diff)) {
274 $set =
$ilDB->query(
"SELECT obj_id FROM lm_read_event" .
275 " WHERE " .
$ilDB->in(
"obj_id", $parent_st_ids,
"",
"integer") .
276 " AND usr_id = " .
$ilDB->quote($this->user_id,
"integer"));
278 $ex_st[] =
$row[
"obj_id"];
282 $missing_st = array_diff($parent_st_ids, $ex_st);
283 if (
sizeof($missing_st)) {
284 foreach ($missing_st as $st_id) {
286 "obj_id" =>
array(
"integer", $st_id),
287 "usr_id" =>
array(
"integer", $this->user_id)
290 $ilDB->replace(
"lm_read_event", $fields,
array());
295 $ilDB->manipulate(
"UPDATE lm_read_event SET" .
296 " read_count = read_count + " .
$ilDB->quote($read_diff,
"integer") .
297 " , spent_seconds = spent_seconds + " .
$ilDB->quote($time_diff,
"integer") .
298 " , last_access = " .
$ilDB->quote($now,
"integer") .
299 " WHERE " .
$ilDB->in(
"obj_id", $parent_st_ids,
"",
"integer") .
300 " AND usr_id = " .
$ilDB->quote($this->user_id,
"integer"));
317 $this->current_page_id = $a_val;
344 if ($this->loaded_for_node === (
int) $this->
getCurrentPage() && !$this->dirty) {
349 $this->dirty =
false;
352 $this->tree_arr =
array();
353 $nodes = $this->lm_tree->getSubTree($this->lm_tree->getNodeData($this->lm_tree->readRootId()));
354 foreach ($nodes as $node) {
355 $this->tree_arr[
"childs"][$node[
"parent"]][] = $node;
356 $this->tree_arr[
"parent"][$node[
"child"]] = $node[
"parent"];
357 $this->tree_arr[
"nodes"][$node[
"child"]] = $node;
361 include_once(
"./Modules/LearningModule/classes/class.ilLMObject.php");
365 $this->re_arr =
array();
366 $set =
$ilDB->query(
"SELECT * FROM lm_read_event " .
367 " WHERE " .
$ilDB->in(
"obj_id", $this->lm_obj_ids,
false,
"integer") .
368 " AND usr_id = " .
$ilDB->quote($this->user_id,
"integer"));
369 while ($rec =
$ilDB->fetchAssoc($set)) {
370 $this->re_arr[$rec[
"obj_id"]] = $rec;
374 $this->page_questions =
array();
375 $this->all_questions =
array();
376 include_once(
"./Modules/LearningModule/classes/class.ilLMPageObject.php");
378 foreach ($q[
"set"] as $quest) {
379 $this->page_questions[$quest[
"page_id"]][] = $quest[
"question_id"];
380 $this->all_questions[] = $quest[
"question_id"];
384 include_once(
"./Services/COPage/classes/class.ilPageQuestionProcessor.php");
387 $this->has_incorrect_answers =
false;
389 $has_pred_incorrect_answers =
false;
390 $has_pred_incorrect_not_unlocked_answers =
false;
391 $this->
determineProgressStatus($this->lm_tree->readRootId(), $has_pred_incorrect_answers, $has_pred_incorrect_not_unlocked_answers);
393 $this->has_incorrect_answers = $has_pred_incorrect_answers;
404 if (count($this->all_questions) > 0 && !$this->has_incorrect_answers) {
417 protected function determineProgressStatus($a_obj_id, &$a_has_pred_incorrect_answers, &$a_has_pred_incorrect_not_unlocked_answers)
421 if (isset($this->tree_arr[
"nodes"][$a_obj_id])) {
422 $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_answers"] = $a_has_pred_incorrect_answers;
423 $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_not_unlocked_answers"] = $a_has_pred_incorrect_not_unlocked_answers;
425 if (is_array($this->tree_arr[
"childs"][$a_obj_id])) {
427 $this->tree_arr[
"childs"][$a_obj_id] =
ilUtil::sortArray($this->tree_arr[
"childs"][$a_obj_id],
"lft",
"asc",
true);
430 foreach ($this->tree_arr[
"childs"][$a_obj_id] as $c) {
434 if (!self::_isNodeVisible($c)) {
440 $a_has_pred_incorrect_answers,
441 $a_has_pred_incorrect_not_unlocked_answers
455 if ($this->tree_arr[
"nodes"][$c[
"child"]][
"type"] ==
"pg") {
457 ($c_stat ==
ilLMTracker::NOT_ATTEMPTED && is_array($this->page_questions[$c[
"child"]]) && count($this->page_questions[$c[
"child"]]) > 0)) {
458 $a_has_pred_incorrect_answers =
true;
459 if (!$this->tree_arr[
"nodes"][$c[
"child"]][
"unlocked"]) {
460 $a_has_pred_incorrect_not_unlocked_answers =
true;
465 if ($cnt_completed == count($this->tree_arr[
"childs"][$a_obj_id])) {
468 } elseif ($this->tree_arr[
"nodes"][$a_obj_id][
"type"] ==
"pg") {
470 if (isset($this->re_arr[$a_obj_id]) && $this->re_arr[$a_obj_id][
"read_count"] > 0) {
477 if (is_array($this->page_questions[$a_obj_id])) {
480 foreach ($this->page_questions[$a_obj_id] as $q_id) {
481 if (is_array($this->answer_status[$q_id])
482 && $this->answer_status[$q_id][
"try"] > 0
483 && !$this->answer_status[$q_id][
"passed"]) {
485 if (!$this->answer_status[$q_id][
"unlocked"]) {
493 foreach ($this->page_questions[$a_obj_id] as $q_id) {
494 if (!is_array($this->answer_status[$q_id])
495 || $this->answer_status[$q_id][
"try"] == 0) {
504 $this->tree_arr[
"nodes"][$a_obj_id][
"unlocked"] = $unlocked;
505 $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_answers"] = $a_has_pred_incorrect_answers;
506 $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_not_unlocked_answers"] = $a_has_pred_incorrect_not_unlocked_answers;
510 $this->tree_arr[
"nodes"][$a_obj_id][
"status"] = $status;
526 if ($a_node[
"child"] == $a_highlighted_node) {
529 if (isset($this->tree_arr[
"nodes"][$a_node[
"child"]])) {
530 switch ($this->tree_arr[
"nodes"][$a_node[
"child"]][
"status"]) {
554 if (is_array($this->tree_arr[
"nodes"][$a_obj_id])) {
555 if ($a_ignore_unlock) {
556 $ret = $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_answers"];
558 $ret = $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_not_unlocked_answers"];
581 $blocked_users =
array();
584 $this->page_questions =
array();
585 $this->all_questions =
array();
586 $page_for_question =
array();
587 include_once(
"./Modules/LearningModule/classes/class.ilLMPageObject.php");
589 foreach ($q[
"set"] as $quest) {
590 $this->page_questions[$quest[
"page_id"]][] = $quest[
"question_id"];
591 $this->all_questions[] = $quest[
"question_id"];
592 $page_for_question[$quest[
"question_id"]] = $quest[
"page_id"];
595 include_once(
"./Modules/TestQuestionPool/classes/class.ilAssQuestionList.php");
597 $qlist->setParentObjId(0);
598 $qlist->setJoinObjectData(
false);
599 $qlist->addFieldFilter(
"question_id", $this->all_questions);
601 $qdata = $qlist->getQuestionDataArray();
604 include_once(
"./Services/COPage/classes/class.ilPageQuestionProcessor.php");
606 include_once(
"./Modules/LearningModule/classes/class.ilLMPageObject.php");
607 foreach ($this->answer_status as
$as) {
608 if ($as[
"try"] >= $qdata[$as[
"qst_id"]][
"nr_of_tries"] && $qdata[$as[
"qst_id"]][
"nr_of_tries"] > 0 && !$as[
"passed"]) {
611 $as[
"user_name"] =
$name[
"lastname"] .
", " .
$name[
"firstname"] .
" [" .
$name[
"login"] .
"]";
612 $as[
"question_text"] = $qdata[$as[
"qst_id"]][
"question_text"];
613 $as[
"page_id"] = $page_for_question[$as[
"qst_id"]];
615 $blocked_users[] =
$as;
619 return $blocked_users;
630 include_once(
"./Services/COPage/classes/class.ilPageObject.php");
632 if ($a_node[
"type"] !=
"pg") {
640 $lm_set->get(
"time_scheduled_page_activation")
645 if ($act_data[
"show_activation_info"] &&
static sortArray( $array, $a_array_sortby, $a_array_sortorder=0, $a_numeric=false, $a_keep_keys=false)
sortArray
static _lookupName($a_user_id)
lookup user name
Track access to ILIAS learning modules.
hasPredIncorrectAnswers($a_obj_id, $a_ignore_unlock=false)
Has predecessing incorrect answers.
trackLastPageAccess($usr_id, $lm_id, $obj_id)
Track last accessed page for a learning module.
static _updateStatus($a_obj_id, $a_usr_id, $a_obj=null, $a_percentage=false, $a_force_raise=false)
Update status.
getBlockedUsersInformation()
Get blocked users information.
setCurrentPage($a_val)
Set current page.
static _getAllLMObjectsOfLM($a_lm_id, $a_type="")
Get all objects of learning module.
static _tracProgress($a_user_id, $a_obj_id, $a_ref_id, $a_obj_type='')
getIconForLMObject($a_node, $a_highlighted_node=0)
Get icon for lm object.
static _lookupTitle($a_obj_id)
Lookup title.
static getInstanceByObjId($a_obj_id, $a_user_id=0)
Get instance.
static now()
Return current timestamp in Y-m-d H:i:s format.
getCurrentPage()
Get current page.
trackPageAndChapterAccess($a_page_id)
Track page and chapter access.
static getAnswerStatus($a_q_id, $a_user_id=0)
Get statistics for question.
getAllQuestionsCorrect()
Have all questoins been answered correctly (and questions exist)?
foreach($_POST as $key=> $value) $res
static _lookupActive($a_id, $a_parent_type, $a_check_scheduled_activation=false, $a_lang="-")
lookup activation status
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
static _lookupObjId($a_id)
static getInstance($a_tree_id)
Get Instance.
static queryQuestionsOfLearningModule( $a_lm_id, $a_order_field, $a_order_dir, $a_offset, $a_limit)
Get questions of learning module.
determineProgressStatus($a_obj_id, &$a_has_pred_incorrect_answers, &$a_has_pred_incorrect_not_unlocked_answers)
Determine progress status of nodes.
Create styles array
The data for the language used.
trackAccess($a_page_id)
Track access to lm page.
static getInstance($a_ref_id, $a_user_id=0)
Get instance.
static _lookupActivationData($a_id, $a_parent_type, $a_lang="-")
Lookup activation data.
__construct($a_id, $a_by_obj_id=false, $a_user_id)
Constructor.
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
static _isNodeVisible($a_node)
Is node visible for the learner.
loadLMTrackingData()
Load LM tracking data.
static _getValidTimeSpan()