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