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 ($user_id == ANONYMOUS_USER_ID) {
 
  148        if ($this->lm_ref_id == 0) {
 
  160        include_once(
"./Services/Tracking/classes/class.ilLearningProgress.php");
 
  169        include_once(
"./Services/Tracking/classes/class.ilLPStatusWrapper.php");
 
  190            "usr_id" => [
"integer", $usr_id],
 
  191            "lm_id" => [
"integer", $lm_id]
 
  195                "obj_id" => [
"integer", $obj_id],
 
  196                "lm_title" => [
"text", 
$title]
 
  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)) {
 
  257            if (($now - $pg_ts) <= $valid_timespan) {
 
  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->getCompleteTree();
 
  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") {
 
  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"] &&
 
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