1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4include_once("./Modules/LearningModule/classes/class.ilLMExplorerGUI.php");
5
6/**
7 * LM presentation (left frame) explorer GUI class
8 *
9 * @author	Alex Killing <alex.killing@gmx.de>
10 * @version	$Id$
11 *
12 * @ingroup ModulesLearningModule
13 */
14class ilLMTOCExplorerGUI extends ilLMExplorerGUI
15{
16    protected $lang;
17    protected $highlight_node;
18    protected $tracker;
19    protected $export_all_languages;
20
21    /**
22     * @var ilPageActivationDBRepository
23     */
24    protected $activation_repo;
25
26    /**
27     * @var array
28     */
29    protected $complete_tree;
30
31    /**
32     * @var array
33     */
34    protected $activation_data;
35
36    /**
37     * Constructor
38     *
39     * @param object $a_parent_obj parent gui object
40     * @param string $a_parent_cmd parent cmd
41     * @param ilLMPresentationGUI $a_lm_pres learning module presentation gui object
42     * @param string $a_lang language
43     */
44    public function __construct(
45        $a_parent_obj,
46        $a_parent_cmd,
47        ilLMPresentationGUI $a_lm_pres,
48        $a_lang = "-",
49        $a_focus_id = 0,
50        $export_all_languages = false
51    ) {
52        global $DIC;
53
54        $this->user = $DIC->user();
55        $this->lm_pres = $a_lm_pres;
56        $this->lm = $this->lm_pres->lm;
57        $exp_id = (!$this->getOfflineMode() && $this->lm->getProgressIcons())
58            ? "ilLMProgressTree"
59            : "";
60        parent::__construct($a_parent_obj, $a_parent_cmd, $this->lm, $exp_id);
61        $this->lm_set = new ilSetting("lm");
62        $this->lang = $a_lang;
63        if ($a_focus_id > 0) {
64            $this->setSecondaryHighlightedNodes(array($a_focus_id));
65        }
66        if ($this->lm->getTOCMode() != "pages") {
67            $this->setTypeWhiteList(array("st", "du"));
68        }
69        $this->focus_id = $a_focus_id;
70        $this->export_all_languages = $export_all_languages;
71
72        $this->activation_repo = new ilPageActivationDBRepository();
73
74        $this->initTreeData();
75    }
76
77    /**
78     * Init tree data
79     * @param
80     * @return
81     */
82    protected function initTreeData()
83    {
84        $nodes = $this->tree->getCompleteTree();
85        foreach ($nodes as $node) {
86            $this->complete_tree["childs"][$node["parent"]][] = $node;
87            $this->complete_tree["parent"][$node["child"]] = $node["parent"];
88            $this->complete_tree["nodes"][$node["child"]] = $node;
89        }
90
91        $page_ids = array_column($this->complete_tree["nodes"], "child");
92        $this->activation_data = $this->activation_repo->get(
93            "lm",
94            $page_ids,
95            $this->lm_set->get("time_scheduled_page_activation"),
96            $this->lang
97        );
98        $this->initVisibilityData($this->tree->readRootId());
99    }
100
101    /**
102     * Init visibility data
103     * @param int $node_id
104     */
105    protected function initVisibilityData($node_id)
106    {
107        $current_node = $this->complete_tree["nodes"][$node_id];
108
109        if (is_array($this->complete_tree["childs"][$node_id])) {
110            foreach ($this->complete_tree["childs"][$node_id] as $node) {
111                $this->initVisibilityData($node["child"]);
112            }
113        }
114
115        // pages are visible if they are active or activation info should be shown
116        if ($current_node["type"] == "pg") {
117            $this->complete_tree["visibility"][$node_id] = ($this->activation_data[$node_id]["active"] ||
118                $this->activation_data[$node_id]["show_info"]);
119        } elseif ($current_node["type"] == "st") {
120
121            // make chapters visible as soon as there is one visible child
122            $this->complete_tree["visibility"][$node_id] = false;
123            if (is_array($this->complete_tree["childs"][$node_id])) {
124                foreach ($this->complete_tree["childs"][$node_id] as $node) {
125                    if (isset($this->complete_tree["visibility"][$node["child"]]) &&
126                        $this->complete_tree["visibility"][$node["child"]]) {
127                        $this->complete_tree["visibility"][$node_id] = true;
128                    }
129                }
130            }
131        } else {
132            $this->complete_tree["visibility"][$node_id] = true;
133        }
134    }
135
136    /**
137     * Get root node
138     */
139    public function getRootNode()
140    {
141        $root_id = $this->getTree()->readRootId();
142        if ($this->focus_id > 0 && $this->getTree()->isInTree($this->focus_id) &&
143            ilLMObject::_lookupType($this->focus_id) == "st") {
144            //			$root_id = $this->focus_id;
145        }
146        return $this->getTree()->getNodeData($root_id);
147    }
148
149    /**
150     * Set tracker
151     *
152     * @param ilLMTracker $a_val tracker object
153     */
154    public function setTracker($a_val)
155    {
156        $this->tracker = $a_val;
157    }
158
159    /**
160     * Get tracker
161     *
162     * @return ilLMTracker tracker object
163     */
164    public function getTracker()
165    {
166        return $this->tracker;
167    }
168
169    /**
170     * Set highlighted node
171     *
172     * @param int $a_val node id
173     */
174    public function setHighlightNode($a_val)
175    {
176        $this->highlight_node = $a_val;
177    }
178
179    /**
180     * Get highlighted node
181     *
182     * @return int node id
183     */
184    public function getHighlightNode()
185    {
186        return $this->highlight_node;
187    }
188
189    /**
190     * Is node highlighted?
191     *
192     * @param mixed $a_node node object/array
193     * @return boolean node visible true/false
194     */
195    public function isNodeHighlighted($a_node)
196    {
197        if ($a_node["child"] == $this->getHighlightNode()) {
198            return true;
199        }
200        return false;
201    }
202
203    /**
204     * Get node content
205     *
206     * @param array $a_node node array
207     * @return string node content
208     */
209    public function getNodeContent($a_node)
210    {
211        if ($a_node["child"] == $this->getNodeId($this->getRootNode())) {
212            return $this->lm_pres->getLMPresentationTitle();
213        }
214
215        if ($a_node["type"] == "st") {
216            return ilStructureObject::_getPresentationTitle(
217                $a_node["child"],
218                IL_CHAPTER_TITLE,
219                $this->lm->isActiveNumbering(),
220                false,
221                false,
222                $this->lm->getId(),
223                $this->lang,
224                true
225            );
226        } elseif ($a_node["type"] == "pg") {
227            return ilLMPageObject::_getPresentationTitle(
228                $a_node["child"],
229                $this->lm->getPageHeader(),
230                $this->lm->isActiveNumbering(),
231                $this->lm_set->get("time_scheduled_page_activation"),
232                true,
233                $this->lm->getId(),
234                $this->lang,
235                true
236            );
237        } elseif ($a_node["child"] == $this->getNodeId($this->getRootNode())) {
238            return $this->lm->getTitle();
239        }
240
241        return $a_node["title"];
242    }
243
244
245    /**
246     * Get node icon
247     *
248     * @param array $a_node node array
249     * @return string icon path
250     */
251    public function getNodeIcon($a_node)
252    {
253        // overwrite chapter icons with lp info?
254        if (!$this->getOfflineMode() && $a_node["type"] == "st") {
255            $icon = $this->checkLPIcon($a_node["child"]);
256            if ($icon != "") {
257                return $icon;
258            }
259        }
260
261        // use progress icons (does not depend on lp mode)
262        if (!$this->getOfflineMode() && $this->lm->getProgressIcons()) {
263            return $this->tracker->getIconForLMObject($a_node, $this->highlight_node);
264        }
265
266        include_once("./Modules/LearningModule/classes/class.ilLMObject.php");
267
268        if ($a_node["type"] == "du") {
269            $a_node["type"] = "lm";
270        }
271        $a_name = "icon_" . $a_node["type"] . ".svg";
272        if ($a_node["type"] == "pg") {
273            include_once("./Modules/LearningModule/classes/class.ilLMPage.php");
274            $lm_set = new ilSetting("lm");
275            $active = ilLMPage::_lookupActive(
276                $a_node["child"],
277                $this->lm->getType(),
278                $lm_set->get("time_scheduled_page_activation")
279            );
280
281            // is page scheduled?
282            $img_sc = ($lm_set->get("time_scheduled_page_activation") &&
283                ilLMPage::_isScheduledActivation($a_node["child"], $this->lm->getType()) && !$active
284                && !$this->getOfflineMode())
285                ? "_sc"
286                : "";
287
288            $a_name = "icon_pg" . $img_sc . ".svg";
289
290            if (!$active && !$this->getOfflineMode()) {
291                $a_name = "icon_pg_d" . $img_sc . ".svg";
292            }
293        }
294
295        return ilUtil::getImagePath($a_name, false, "output", $this->getOfflineMode());
296    }
297
298    /**
299     * Is node clickable
300     *
301     * @param array $a_node node array
302     * @return bool clickable?
303     */
304    public function isNodeClickable($a_node)
305    {
306        $ilUser = $this->user;
307
308        $orig_node_id = $a_node["child"];
309
310        // if navigation is restricted based on correct answered questions
311        // check if we have preceeding pages including unsanswered/incorrect answered questions
312        if (!$this->getOfflineMode()) {
313            if ($this->lm->getRestrictForwardNavigation()) {
314                if ($this->getTracker()->hasPredIncorrectAnswers($orig_node_id)) {
315                    return false;
316                }
317            }
318        }
319
320        if ($a_node["type"] == "st") {
321            if (!$this->getOfflineMode()) {
322                if ($this->lm->getTOCMode() != "pages") {
323                    $a_node = $this->getTree()->fetchSuccessorNode($a_node["child"], "pg");
324                } else {
325                    // faster, but needs pages to be in explorer
326                    $a_node = $this->getSuccessorNode($a_node["child"], "pg");
327                }
328                if ($a_node["child"] == 0) {
329                    return false;
330                }
331            } else {
332                // get next activated page
333                $found = false;
334                while (!$found) {
335                    if ($this->lm->getTOCMode() != "pages") {
336                        $a_node = $this->getTree()->fetchSuccessorNode($a_node["child"], "pg");
337                    } else {
338                        $a_node = $this->getSuccessorNode($a_node["child"], "pg");
339                    }
340                    include_once("./Modules/LearningModule/classes/class.ilLMPage.php");
341                    $active = ilLMPage::_lookupActive(
342                        $a_node["child"],
343                        $this->lm->getType(),
344                        $this->lm_set->get("time_scheduled_page_activation")
345                    );
346
347                    if ($a_node["child"] > 0 && !$active) {
348                        $found = false;
349                    } else {
350                        $found = true;
351                    }
352                }
353                if ($a_node["child"] <= 0) {
354                    return false;
355                } else {
356                    $path = $this->getTree()->getPathId($a_node["child"]);
357                    if (!in_array($orig_node_id, $path)) {
358                        return false;
359                    }
360                }
361            }
362        }
363
364        if ($a_node["type"] == "pg") {
365            // check public area mode
366            include_once("./Modules/LearningModule/classes/class.ilLMObject.php");
367            if ($ilUser->getId() == ANONYMOUS_USER_ID && !ilLMObject::_isPagePublic($a_node["child"], true)) {
368                return false;
369            }
370        }
371
372        return true;
373    }
374
375
376    /**
377     * Get node icon alt text
378     *
379     * @param array $a_node node array
380     * @return string alt text
381     */
382    public function getNodeIconAlt($a_node)
383    {
384    }
385
386    /**
387     * Get href for node
388     *
389     * @param mixed $a_node node object/array
390     * @return string href attribute
391     */
392    public function getNodeHref($a_node)
393    {
394        if (!$this->getOfflineMode()) {
395            return $this->lm_pres->getLink($this->lm->getRefId(), "", $a_node["child"]);
396        //return parent::buildLinkTarget($a_node_id, $a_type);
397        } else {
398            if ($a_node["type"] != "pg") {
399                // get next activated page
400                $found = false;
401                while (!$found) {
402                    $a_node = $this->getTree()->fetchSuccessorNode($a_node["child"], "pg");
403                    include_once("./Modules/LearningModule/classes/class.ilLMPage.php");
404                    $active = ilLMPage::_lookupActive(
405                        $a_node["child"],
406                        $this->lm->getType(),
407                        $this->lm_set->get("time_scheduled_page_activation")
408                    );
409
410                    if ($a_node["child"] > 0 && !$active) {
411                        $found = false;
412                    } else {
413                        $found = true;
414                    }
415                }
416            }
417
418            $lang_suffix = "";
419            if ($this->export_all_languages) {
420                if ($this->lang != "" && $this->lang != "-") {
421                    $lang_suffix = "_" . $this->lang;
422                }
423            }
424
425            include_once("./Modules/LearningModule/classes/class.ilLMPageObject.php");
426            if ($nid = ilLMPageObject::getExportId($this->lm->getId(), $a_node["child"])) {
427                return "lm_pg_" . $nid . $lang_suffix . ".html";
428            }
429            return "lm_pg_" . $a_node["child"] . $lang_suffix . ".html";
430        }
431    }
432
433    /**
434     * Is node visible?
435     *
436     * @param mixed $a_node node object/array
437     * @return boolean node visible true/false
438     */
439    public function isNodeVisible($a_node)
440    {
441        return (bool) $this->complete_tree["visibility"][$a_node["child"]];
442        //include_once("./Modules/LearningModule/classes/class.ilLMTracker.php");
443        //return ilLMTracker::_isNodeVisible($a_node);
444    }
445}
446