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;
 
   99        if ($a_user_id == 0) {
 
  103        if (!isset(self::$instances[$a_ref_id][$a_user_id])) {
 
  104            self::$instances[$a_ref_id][$a_user_id] = 
new ilLMTracker($a_ref_id, 
false, $a_user_id);
 
  106        return self::$instances[$a_ref_id][$a_user_id];
 
  121        if ($a_user_id == 0) {
 
  125        if (!isset(self::$instancesbyobj[$a_obj_id][$a_user_id])) {
 
  126            self::$instancesbyobj[$a_obj_id][$a_user_id] = 
new ilLMTracker($a_obj_id, 
true, $a_user_id);
 
  128        return self::$instancesbyobj[$a_obj_id][$a_user_id];
 
  142        if ($user_id == ANONYMOUS_USER_ID) {
 
  147        if ($this->lm_ref_id == 0) {
 
  187            "usr_id" => [
"integer", $usr_id],
 
  188            "lm_id" => [
"integer", $lm_id]
 
  192                "obj_id" => [
"integer", $obj_id],
 
  193                "lm_title" => [
"text", $title]
 
  211        $set = 
$ilDB->query(
"SELECT obj_id FROM lm_read_event" .
 
  212            " WHERE obj_id = " . 
$ilDB->quote($a_page_id, 
"integer") .
 
  213            " AND usr_id = " . 
$ilDB->quote($this->user_id, 
"integer"));
 
  214        if (!
$ilDB->fetchAssoc($set)) {
 
  216                "obj_id" => array(
"integer", $a_page_id),
 
  217                "usr_id" => array(
"integer", $this->user_id)
 
  220            $ilDB->replace(
"lm_read_event", $fields, array()); 
 
  224        $ilDB->manipulate(
"UPDATE lm_read_event SET" .
 
  225            " read_count = read_count + 1 " .
 
  226            " , last_access = " . 
$ilDB->quote($now, 
"integer") .
 
  227            " WHERE obj_id = " . 
$ilDB->quote($a_page_id, 
"integer") .
 
  228            " AND usr_id = " . 
$ilDB->quote($this->user_id, 
"integer"));
 
  236        $set = 
$ilDB->query(
"SELECT * FROM lo_access WHERE " .
 
  237            "usr_id = " . 
$ilDB->quote($this->user_id, 
"integer") . 
" AND " .
 
  238            "lm_id = " . 
$ilDB->quote($this->lm_ref_id, 
"integer"));
 
  240        if (
$res[
"obj_id"]) {
 
  245            $pg_id = 
$res[
"obj_id"];
 
  246            if (!$this->lm_tree->isInTree($pg_id)) {
 
  250            $time_diff = $read_diff = 0;
 
  253            if (($now - $pg_ts) <= $valid_timespan) {
 
  254                $time_diff = $now - $pg_ts;
 
  260            $parent_st_ids = array();
 
  261            foreach ($this->lm_tree->getPathFull($pg_id) as $item) {
 
  262                if ($item[
"type"] == 
"st") {
 
  263                    $parent_st_ids[] = $item[
"obj_id"];
 
  267            if ($parent_st_ids && ($time_diff || $read_diff)) {
 
  270                $set = 
$ilDB->query(
"SELECT obj_id FROM lm_read_event" .
 
  271                    " WHERE " . 
$ilDB->in(
"obj_id", $parent_st_ids, 
"", 
"integer") .
 
  272                    " AND usr_id = " . 
$ilDB->quote($this->user_id, 
"integer"));
 
  273                while ($row = 
$ilDB->fetchAssoc($set)) {
 
  274                    $ex_st[] = $row[
"obj_id"];
 
  278                $missing_st = array_diff($parent_st_ids, $ex_st);
 
  279                if (
sizeof($missing_st)) {
 
  280                    foreach ($missing_st as $st_id) {
 
  282                            "obj_id" => array(
"integer", $st_id),
 
  283                            "usr_id" => array(
"integer", $this->user_id)
 
  286                        $ilDB->replace(
"lm_read_event", $fields, array()); 
 
  291                $ilDB->manipulate(
"UPDATE lm_read_event SET" .
 
  292                    " read_count = read_count + " . 
$ilDB->quote($read_diff, 
"integer") .
 
  293                    " , spent_seconds = spent_seconds + " . 
$ilDB->quote($time_diff, 
"integer") .
 
  294                    " , last_access = " . 
$ilDB->quote($now, 
"integer") .
 
  295                    " WHERE " . 
$ilDB->in(
"obj_id", $parent_st_ids, 
"", 
"integer") .
 
  296                    " AND usr_id = " . 
$ilDB->quote($this->user_id, 
"integer"));
 
  313        $this->current_page_id = $a_val;
 
  340        if ($this->loaded_for_node === (
int) $this->
getCurrentPage() && !$this->dirty) {
 
  345        $this->dirty = 
false;
 
  348        $this->tree_arr = array();
 
  349        $nodes = $this->lm_tree->getCompleteTree();
 
  350        foreach ($nodes as $node) {
 
  351            $this->tree_arr[
"childs"][$node[
"parent"]][] = $node;
 
  352            $this->tree_arr[
"parent"][$node[
"child"]] = $node[
"parent"];
 
  353            $this->tree_arr[
"nodes"][$node[
"child"]] = $node;
 
  360        $this->re_arr = array();
 
  361        $set = 
$ilDB->query(
"SELECT * FROM lm_read_event " .
 
  362            " WHERE " . 
$ilDB->in(
"obj_id", $this->lm_obj_ids, 
false, 
"integer") .
 
  363            " AND usr_id = " . 
$ilDB->quote($this->user_id, 
"integer"));
 
  364        while ($rec = 
$ilDB->fetchAssoc($set)) {
 
  365            $this->re_arr[$rec[
"obj_id"]] = $rec;
 
  369        $this->page_questions = array();
 
  370        $this->all_questions = array();
 
  372        foreach ($q[
"set"] as $quest) {
 
  373            $this->page_questions[$quest[
"page_id"]][] = $quest[
"question_id"];
 
  374            $this->all_questions[] = $quest[
"question_id"];
 
  380        $this->has_incorrect_answers = 
false;
 
  382        $has_pred_incorrect_answers = 
false;
 
  383        $has_pred_incorrect_not_unlocked_answers = 
false;
 
  384        $this->
determineProgressStatus($this->lm_tree->readRootId(), $has_pred_incorrect_answers, $has_pred_incorrect_not_unlocked_answers);
 
  386        $this->has_incorrect_answers = $has_pred_incorrect_answers;
 
  397        if (count($this->all_questions) > 0 && !$this->has_incorrect_answers) {
 
  410    protected function determineProgressStatus($a_obj_id, &$a_has_pred_incorrect_answers, &$a_has_pred_incorrect_not_unlocked_answers)
 
  414        if (isset($this->tree_arr[
"nodes"][$a_obj_id])) {
 
  415            $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_answers"] = $a_has_pred_incorrect_answers;
 
  416            $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_not_unlocked_answers"] = $a_has_pred_incorrect_not_unlocked_answers;
 
  418            if (is_array($this->tree_arr[
"childs"][$a_obj_id])) {
 
  420                $this->tree_arr[
"childs"][$a_obj_id] = 
ilUtil::sortArray($this->tree_arr[
"childs"][$a_obj_id], 
"lft", 
"asc", 
true);
 
  423                foreach ($this->tree_arr[
"childs"][$a_obj_id] as 
$c) {
 
  427                    if (!self::_isNodeVisible(
$c)) {
 
  433                        $a_has_pred_incorrect_answers,
 
  434                        $a_has_pred_incorrect_not_unlocked_answers
 
  448                    if ($this->tree_arr[
"nodes"][
$c[
"child"]][
"type"] == 
"pg") {
 
  451                            $a_has_pred_incorrect_answers = 
true;
 
  452                            if (!$this->tree_arr[
"nodes"][
$c[
"child"]][
"unlocked"]) {
 
  453                                $a_has_pred_incorrect_not_unlocked_answers = 
true;
 
  458                if ($cnt_completed == count($this->tree_arr[
"childs"][$a_obj_id])) {
 
  461            } elseif ($this->tree_arr[
"nodes"][$a_obj_id][
"type"] == 
"pg") {
 
  463                if (isset($this->re_arr[$a_obj_id]) && $this->re_arr[$a_obj_id][
"read_count"] > 0) {
 
  470                if (is_array($this->page_questions[$a_obj_id])) {
 
  473                    foreach ($this->page_questions[$a_obj_id] as $q_id) {
 
  474                        if (is_array($this->answer_status[$q_id])
 
  475                            && $this->answer_status[$q_id][
"try"] > 0
 
  476                            && !$this->answer_status[$q_id][
"passed"]) {
 
  478                            if (!$this->answer_status[$q_id][
"unlocked"]) {
 
  486                        foreach ($this->page_questions[$a_obj_id] as $q_id) {
 
  487                            if (!is_array($this->answer_status[$q_id])
 
  488                                || $this->answer_status[$q_id][
"try"] == 0) {
 
  497                $this->tree_arr[
"nodes"][$a_obj_id][
"unlocked"] = $unlocked;
 
  498                $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_answers"] = $a_has_pred_incorrect_answers;
 
  499                $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_not_unlocked_answers"] = $a_has_pred_incorrect_not_unlocked_answers;
 
  503        $this->tree_arr[
"nodes"][$a_obj_id][
"status"] = $status;
 
  519        if ($a_node[
"child"] == $a_highlighted_node) {
 
  522        if (isset($this->tree_arr[
"nodes"][$a_node[
"child"]])) {
 
  523            switch ($this->tree_arr[
"nodes"][$a_node[
"child"]][
"status"]) {
 
  547        if (is_array($this->tree_arr[
"nodes"][$a_obj_id])) {
 
  548            if ($a_ignore_unlock) {
 
  549                $ret = $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_answers"];
 
  551                $ret = $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_not_unlocked_answers"];
 
  574        $blocked_users = array();
 
  577        $this->page_questions = array();
 
  578        $this->all_questions = array();
 
  579        $page_for_question = array();
 
  581        foreach ($q[
"set"] as $quest) {
 
  582            $this->page_questions[$quest[
"page_id"]][] = $quest[
"question_id"];
 
  583            $this->all_questions[] = $quest[
"question_id"];
 
  584            $page_for_question[$quest[
"question_id"]] = $quest[
"page_id"];
 
  588        $qlist->setParentObjId(0);
 
  589        $qlist->setJoinObjectData(
false);
 
  590        $qlist->addFieldFilter(
"question_id", $this->all_questions);
 
  592        $qdata = $qlist->getQuestionDataArray();
 
  596        foreach ($this->answer_status as $as) {
 
  597            if ($as[
"try"] >= $qdata[$as[
"qst_id"]][
"nr_of_tries"] && $qdata[$as[
"qst_id"]][
"nr_of_tries"] > 0 && !$as[
"passed"]) {
 
  600                $as[
"user_name"] = 
$name[
"lastname"] . 
", " . 
$name[
"firstname"] . 
" [" . 
$name[
"login"] . 
"]";
 
  601                $as[
"question_text"] = $qdata[$as[
"qst_id"]][
"question_text"];
 
  602                $as[
"page_id"] = $page_for_question[$as[
"qst_id"]];
 
  604                $blocked_users[] = $as;
 
  608        return $blocked_users;
 
  619        if ($a_node[
"type"] != 
"pg") {
 
  627            $lm_set->get(
"time_scheduled_page_activation")
 
  632            if ($act_data[
"show_activation_info"] &&
 
An exception for terminatinating execution or to throw for unit testing.
static _recordReadEvent( $a_type, $a_ref_id, $obj_id, $usr_id, $isCatchupWriteEvents=true, $a_ext_rc=false, $a_ext_time=false)
Records a read event and catches up with write events.
@classDescription Date and time handling
static _getAllLMObjectsOfLM($a_lm_id, $a_type="")
Get all objects of learning module.
static _lookupTitle($a_obj_id)
Lookup title.
static queryQuestionsOfLearningModule( $a_lm_id, $a_order_field, $a_order_dir, $a_offset, $a_limit)
Get questions of learning module.
Base exception class for learning module presentation.
Track access to ILIAS learning modules.
trackAccess($a_page_id, $user_id)
Track access to lm page.
static _isNodeVisible($a_node)
Is node visible for the learner.
getCurrentPage()
Get current page.
__construct($a_id, $a_by_obj_id=false, $a_user_id)
Constructor.
getAllQuestionsCorrect()
Have all questoins been answered correctly (and questions exist)?
trackLastPageAccess($usr_id, $lm_id, $obj_id)
Track last accessed page for a learning module.
trackPageAndChapterAccess($a_page_id)
Track page and chapter access.
static getInstance($a_ref_id, $a_user_id=0)
Get instance.
determineProgressStatus($a_obj_id, &$a_has_pred_incorrect_answers, &$a_has_pred_incorrect_not_unlocked_answers)
Determine progress status of nodes.
getIconForLMObject($a_node, $a_highlighted_node=0)
Get icon for lm object.
static getInstanceByObjId($a_obj_id, $a_user_id=0)
Get instance.
getBlockedUsersInformation()
Get blocked users information.
hasPredIncorrectAnswers($a_obj_id, $a_ignore_unlock=false)
Has predecessing incorrect answers.
setCurrentPage($a_val)
Set current page.
loadLMTrackingData()
Load LM tracking data.
static getInstance($a_tree_id)
Get Instance.
static _updateStatus($a_obj_id, $a_usr_id, $a_obj=null, $a_percentage=false, $a_force_raise=false)
Update status.
static _tracProgress($a_user_id, $a_obj_id, $a_ref_id, $a_obj_type='')
static _getValidTimeSpan()
static _lookupName($a_user_id)
lookup user name
static _lookupObjId($a_id)
static _lookupActive($a_id, $a_parent_type, $a_check_scheduled_activation=false, $a_lang="-")
lookup activation status
static _lookupActivationData($a_id, $a_parent_type, $a_lang="-")
Lookup activation data.
static getAnswerStatus($a_q_id, $a_user_id=0)
Get statistics for question.
static sortArray( $array, $a_array_sortby, $a_array_sortorder=0, $a_numeric=false, $a_keep_keys=false)
sortArray
static now()
Return current timestamp in Y-m-d H:i:s format.
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
foreach($_POST as $key=> $value) $res