71    private function __construct($a_id, $a_by_obj_id = 
false, $a_user_id)
 
   75        $this->db = 
$DIC->database();
 
   76        $this->lng = 
$DIC->language();
 
   77        $this->plugin_admin = 
$DIC[
"ilPluginAdmin"];
 
   78        $this->
user = $DIC->user();
 
   79        $this->user_id = $a_user_id;
 
   80        $this->refinery = 
$DIC[
'refinery'];
 
   84            $this->lm_obj_id = $a_id;
 
   86            $this->lm_ref_id = $a_id;
 
  105        if ($a_user_id == 0) {
 
  109        if (!isset(self::$instances[$a_ref_id][$a_user_id])) {
 
  110            self::$instances[$a_ref_id][$a_user_id] = 
new ilLMTracker($a_ref_id, 
false, $a_user_id);
 
  112        return self::$instances[$a_ref_id][$a_user_id];
 
  127        if ($a_user_id == 0) {
 
  131        if (!isset(self::$instancesbyobj[$a_obj_id][$a_user_id])) {
 
  132            self::$instancesbyobj[$a_obj_id][$a_user_id] = 
new ilLMTracker($a_obj_id, 
true, $a_user_id);
 
  134        return self::$instancesbyobj[$a_obj_id][$a_user_id];
 
  153        if ($this->lm_ref_id == 0) {
 
  193            "usr_id" => [
"integer", $usr_id],
 
  194            "lm_id" => [
"integer", $lm_id]
 
  198                "obj_id" => [
"integer", $obj_id],
 
  199                "lm_title" => [
"text", $title]
 
  217        $set = 
$ilDB->query(
"SELECT obj_id FROM lm_read_event" .
 
  218            " WHERE obj_id = " . 
$ilDB->quote($a_page_id, 
"integer") .
 
  219            " AND usr_id = " . 
$ilDB->quote($this->user_id, 
"integer"));
 
  220        if (!
$ilDB->fetchAssoc($set)) {
 
  222                "obj_id" => array(
"integer", $a_page_id),
 
  223                "usr_id" => array(
"integer", $this->user_id)
 
  226            $ilDB->replace(
"lm_read_event", $fields, array()); 
 
  230        $ilDB->manipulate(
"UPDATE lm_read_event SET" .
 
  231            " read_count = read_count + 1 " .
 
  232            " , last_access = " . 
$ilDB->quote($now, 
"integer") .
 
  233            " WHERE obj_id = " . 
$ilDB->quote($a_page_id, 
"integer") .
 
  234            " AND usr_id = " . 
$ilDB->quote($this->user_id, 
"integer"));
 
  242        $set = 
$ilDB->query(
"SELECT * FROM lo_access WHERE " .
 
  243            "usr_id = " . 
$ilDB->quote($this->user_id, 
"integer") . 
" AND " .
 
  244            "lm_id = " . 
$ilDB->quote($this->lm_ref_id, 
"integer"));
 
  246        if (
$res[
"obj_id"]) {
 
  251            $pg_id = 
$res[
"obj_id"];
 
  252            if (!$this->lm_tree->isInTree($pg_id)) {
 
  256            $time_diff = $read_diff = 0;
 
  259            if (($now - $pg_ts) <= $valid_timespan) {
 
  260                $time_diff = $now - $pg_ts;
 
  266            $parent_st_ids = array();
 
  267            foreach ($this->lm_tree->getPathFull($pg_id) as $item) {
 
  268                if ($item[
"type"] == 
"st") {
 
  269                    $parent_st_ids[] = $item[
"obj_id"];
 
  273            if ($parent_st_ids && ($time_diff || $read_diff)) {
 
  276                $set = 
$ilDB->query(
"SELECT obj_id FROM lm_read_event" .
 
  277                    " WHERE " . 
$ilDB->in(
"obj_id", $parent_st_ids, 
"", 
"integer") .
 
  278                    " AND usr_id = " . 
$ilDB->quote($this->user_id, 
"integer"));
 
  279                while ($row = 
$ilDB->fetchAssoc($set)) {
 
  280                    $ex_st[] = $row[
"obj_id"];
 
  284                $missing_st = array_diff($parent_st_ids, $ex_st);
 
  285                if (
sizeof($missing_st)) {
 
  286                    foreach ($missing_st as $st_id) {
 
  288                            "obj_id" => array(
"integer", $st_id),
 
  289                            "usr_id" => array(
"integer", $this->user_id)
 
  292                        $ilDB->replace(
"lm_read_event", $fields, array()); 
 
  297                $ilDB->manipulate(
"UPDATE lm_read_event SET" .
 
  298                    " read_count = read_count + " . 
$ilDB->quote($read_diff, 
"integer") .
 
  299                    " , spent_seconds = spent_seconds + " . 
$ilDB->quote($time_diff, 
"integer") .
 
  300                    " , last_access = " . 
$ilDB->quote($now, 
"integer") .
 
  301                    " WHERE " . 
$ilDB->in(
"obj_id", $parent_st_ids, 
"", 
"integer") .
 
  302                    " AND usr_id = " . 
$ilDB->quote($this->user_id, 
"integer"));
 
  319        $this->current_page_id = $a_val;
 
  346        if ($this->loaded_for_node === (
int) $this->
getCurrentPage() && !$this->dirty) {
 
  351        $this->dirty = 
false;
 
  354        $this->tree_arr = array();
 
  355        $nodes = $this->lm_tree->getCompleteTree();
 
  356        foreach ($nodes as $node) {
 
  357            $this->tree_arr[
"childs"][$node[
"parent"]][] = $node;
 
  358            $this->tree_arr[
"parent"][$node[
"child"]] = $node[
"parent"];
 
  359            $this->tree_arr[
"nodes"][$node[
"child"]] = $node;
 
  366        $this->re_arr = array();
 
  367        $set = 
$ilDB->query(
"SELECT * FROM lm_read_event " .
 
  368            " WHERE " . 
$ilDB->in(
"obj_id", $this->lm_obj_ids, 
false, 
"integer") .
 
  369            " AND usr_id = " . 
$ilDB->quote($this->user_id, 
"integer"));
 
  370        while ($rec = 
$ilDB->fetchAssoc($set)) {
 
  371            $this->re_arr[$rec[
"obj_id"]] = $rec;
 
  375        $this->page_questions = array();
 
  376        $this->all_questions = array();
 
  378        foreach ($q[
"set"] as $quest) {
 
  379            $this->page_questions[$quest[
"page_id"]][] = $quest[
"question_id"];
 
  380            $this->all_questions[] = $quest[
"question_id"];
 
  386        $this->has_incorrect_answers = 
false;
 
  388        $has_pred_incorrect_answers = 
false;
 
  389        $has_pred_incorrect_not_unlocked_answers = 
false;
 
  390        $this->
determineProgressStatus($this->lm_tree->readRootId(), $has_pred_incorrect_answers, $has_pred_incorrect_not_unlocked_answers);
 
  392        $this->has_incorrect_answers = $has_pred_incorrect_answers;
 
  403        if (count($this->all_questions) > 0 && !$this->has_incorrect_answers) {
 
  416    protected function determineProgressStatus($a_obj_id, &$a_has_pred_incorrect_answers, &$a_has_pred_incorrect_not_unlocked_answers)
 
  420        if (isset($this->tree_arr[
"nodes"][$a_obj_id])) {
 
  421            $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_answers"] = $a_has_pred_incorrect_answers;
 
  422            $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_not_unlocked_answers"] = $a_has_pred_incorrect_not_unlocked_answers;
 
  424            if (is_array($this->tree_arr[
"childs"][$a_obj_id])) {
 
  426                $this->tree_arr[
"childs"][$a_obj_id] = 
ilUtil::sortArray($this->tree_arr[
"childs"][$a_obj_id], 
"lft", 
"asc", 
true);
 
  429                foreach ($this->tree_arr[
"childs"][$a_obj_id] as 
$c) {
 
  433                    if (!self::_isNodeVisible(
$c)) {
 
  439                        $a_has_pred_incorrect_answers,
 
  440                        $a_has_pred_incorrect_not_unlocked_answers
 
  454                    if ($this->tree_arr[
"nodes"][
$c[
"child"]][
"type"] == 
"pg") {
 
  457                            $a_has_pred_incorrect_answers = 
true;
 
  458                            if (!$this->tree_arr[
"nodes"][
$c[
"child"]][
"unlocked"]) {
 
  459                                $a_has_pred_incorrect_not_unlocked_answers = 
true;
 
  464                if ($cnt_completed == count($this->tree_arr[
"childs"][$a_obj_id])) {
 
  467            } elseif ($this->tree_arr[
"nodes"][$a_obj_id][
"type"] == 
"pg") {
 
  469                if (isset($this->re_arr[$a_obj_id]) && $this->re_arr[$a_obj_id][
"read_count"] > 0) {
 
  476                if (is_array($this->page_questions[$a_obj_id])) {
 
  479                    foreach ($this->page_questions[$a_obj_id] as $q_id) {
 
  480                        if (is_array($this->answer_status[$q_id])
 
  481                            && $this->answer_status[$q_id][
"try"] > 0
 
  482                            && !$this->answer_status[$q_id][
"passed"]) {
 
  484                            if (!$this->answer_status[$q_id][
"unlocked"]) {
 
  492                        foreach ($this->page_questions[$a_obj_id] as $q_id) {
 
  493                            if (!is_array($this->answer_status[$q_id])
 
  494                                || $this->answer_status[$q_id][
"try"] == 0) {
 
  503                $this->tree_arr[
"nodes"][$a_obj_id][
"unlocked"] = $unlocked;
 
  504                $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_answers"] = $a_has_pred_incorrect_answers;
 
  505                $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_not_unlocked_answers"] = $a_has_pred_incorrect_not_unlocked_answers;
 
  509        $this->tree_arr[
"nodes"][$a_obj_id][
"status"] = $status;
 
  527        if ($a_node[
"child"] == $a_highlighted_node) {
 
  528            return $icons->getImagePathRunning();
 
  530        if (isset($this->tree_arr[
"nodes"][$a_node[
"child"]])) {
 
  531            switch ($this->tree_arr[
"nodes"][$a_node[
"child"]][
"status"]) {
 
  533                    return $icons->getImagePathInProgress();
 
  536                    return $icons->getImagePathFailed();
 
  539                    return $icons->getImagePathCompleted();
 
  542        return $icons->getImagePathNotAttempted();
 
  555        if (is_array($this->tree_arr[
"nodes"][$a_obj_id])) {
 
  556            if ($a_ignore_unlock) {
 
  557                $ret = $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_answers"];
 
  559                $ret = $this->tree_arr[
"nodes"][$a_obj_id][
"has_pred_incorrect_not_unlocked_answers"];
 
  583        $blocked_users = array();
 
  586        $this->page_questions = array();
 
  587        $this->all_questions = array();
 
  588        $page_for_question = array();
 
  590        foreach ($q[
"set"] as $quest) {
 
  591            $this->page_questions[$quest[
"page_id"]][] = $quest[
"question_id"];
 
  592            $this->all_questions[] = $quest[
"question_id"];
 
  593            $page_for_question[$quest[
"question_id"]] = $quest[
"page_id"];
 
  597        $qlist->setParentObjId(0);
 
  598        $qlist->setJoinObjectData(
false);
 
  599        $qlist->addFieldFilter(
"question_id", $this->all_questions);
 
  601        $qdata = $qlist->getQuestionDataArray();
 
  605        foreach ($this->answer_status as $as) {
 
  606            if ($as[
"try"] >= $qdata[$as[
"qst_id"]][
"nr_of_tries"] && $qdata[$as[
"qst_id"]][
"nr_of_tries"] > 0 && !$as[
"passed"]) {
 
  609                $as[
"user_name"] = 
$name[
"lastname"] . 
", " . 
$name[
"firstname"] . 
" [" . 
$name[
"login"] . 
"]";
 
  610                $as[
"question_text"] = $qdata[$as[
"qst_id"]][
"question_text"];
 
  611                $as[
"page_id"] = $page_for_question[$as[
"qst_id"]];
 
  613                $blocked_users[] = $as;
 
  617        return $blocked_users;
 
  628        if ($a_node[
"type"] != 
"pg") {
 
  636            $lm_set->get(
"time_scheduled_page_activation")
 
  641            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 getInstance(int $variant=ilLPStatusIcons::ICON_VARIANT_DEFAULT, ?\ILIAS\UI\Renderer $renderer=null, ?\ILIAS\UI\Factory $factory=null)
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.
foreach($_POST as $key=> $value) $res