1<?php
2/*
3    +-----------------------------------------------------------------------------+
4    | ILIAS open source                                                           |
5    +-----------------------------------------------------------------------------+
6    | Copyright (c) 1998-2001 ILIAS open source, University of Cologne            |
7    |                                                                             |
8    | This program is free software; you can redistribute it and/or               |
9    | modify it under the terms of the GNU General Public License                 |
10    | as published by the Free Software Foundation; either version 2              |
11    | of the License, or (at your option) any later version.                      |
12    |                                                                             |
13    | This program is distributed in the hope that it will be useful,             |
14    | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
15    | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
16    | GNU General Public License for more details.                                |
17    |                                                                             |
18    | You should have received a copy of the GNU General Public License           |
19    | along with this program; if not, write to the Free Software                 |
20    | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. |
21    +-----------------------------------------------------------------------------+
22*/
23
24/**
25 * @classDescription class for ILIAS ViewLTI
26 *
27 * @author Stefan Schneider <schneider@hrz.uni-marburg.de
28 * @version $id$
29 * @ingroup ServicesLTI
30 * @ilCtrl_IsCalledBy ilLTIViewGUI: ilLTIRouterGUI
31 *
32 */
33class ilLTIViewGUI
34{
35    const LTI_DEBUG = false; // deprecated
36
37    /**
38     * messsage codes
39     */
40    const MSG_ERROR = "failure";
41    const MSG_INFO = "info";
42    const MSG_QUESTION = "question";
43    const MSG_SUCCESS = "success";
44
45    /**
46     * private variables
47     */
48    private $user = null;
49    private $home_id = "";
50    private $home_obj_id = "";
51    private $home_type = "";
52    private $home_title = "";
53    private $home_url = "";
54    private $link_dir = "";
55    private $current_ref_id = "";
56    private $current_type = "";
57
58    /**
59     * public variables
60     */
61    public $show_locator = true;
62    public $member_view = false;
63    public $member_view_url = "";
64    public $member_view_close_txt = "";
65
66    /**
67     * Constructor
68     * @return
69     */
70    public function __construct(\ilObjUser $user)
71    {
72        if (ilContext::hasUser()) {
73            $this->user = $user;
74            $this->init();
75        } else {
76            if ($this->isActive()) {
77                $this->deactivate();
78            }
79        }
80    }
81
82    /**
83     * Init LTI mode for lit authenticated users
84     */
85    private function init()
86    {
87        $this->link_dir = (defined("ILIAS_MODULE"))
88                    ? "../"
89                    : "";
90        if ($this->isLTIUser()) {
91            $this->activate();
92        } else {
93            if ($this->isActive()) {
94                $this->deactivate();
95            }
96        }
97    }
98
99
100    /**
101     * for compatiblity with ilLTIRouterGUI
102     */
103    public static function getInstance()
104    {
105        global $DIC;
106        return $DIC["lti"];
107    }
108
109    /**
110     * get LTI Mode from Users->getAuthMode
111     * @return boolean
112     */
113    private function isLTIUser()
114    {
115        if (!$this->user instanceof ilObjUser) {
116            return false;
117        }
118        return (strpos($this->user->getAuthMode(), 'lti_') === 0);
119    }
120
121    /**
122     * for ctrl commands
123     */
124    public function executeCommand()
125    {
126        global $ilCtrl;
127        $cmd = $ilCtrl->getCmd();
128        switch ($cmd) {
129            case 'exit':
130                $this->exitLti();
131            break;
132        }
133    }
134
135    /**
136     * activate LTI GUI
137     * @return void
138     * */
139    public function activate()
140    {
141        $this->findEffectiveRefId();
142        $_SESSION['il_lti_mode'] = "1";
143        $this->initGUI();
144        $this->log("lti view activated");
145    }
146
147    /**
148     * deactivate LTI GUI
149     * @return void
150     * */
151    public function deactivate()
152    {
153        unset($_SESSION['il_lti_mode']);
154        $this->log("lti view deactivated");
155    }
156
157    /**
158     * LTI is active
159     * @return boolean
160     * */
161    public function isActive()
162    {
163        return (isset($_SESSION['il_lti_mode']));
164    }
165
166    /**
167     * Set the environment backend for GUI (tree and locator behaviour, home link, ....)
168     * it is also possible to hide locator and treeicon, but if activated elsewhere a clean root folder is defined
169     * ToDo: conceptual discussion
170     */
171    public function initGUI()
172    {
173        global $lng;
174        $this->log("initGUI");
175        $lng->loadLanguageModule("lti");
176        $baseclass = strtolower($_GET['baseClass']);
177        $cmdclass = strtolower($_GET['cmdClass']);
178
179        // init home_id, home_type, home_url and home_items if not already set
180        if ($this->home_id === '') {
181            $this->home_id = $_SESSION['lti_context_id'];
182        }
183        if ($this->home_obj_id === '') {
184            $this->home_obj_id = ilObject::_lookupObjectId($this->home_id);
185        }
186        if ($this->home_type === '') {
187            $this->home_type = ilObject::_lookupType($this->home_id, true);
188            $this->show_locator = $this->showLocator($this->home_type);
189        }
190        if ($this->home_url === '') {
191            $this->home_url = $this->getHomeLink();
192        }
193        if ($this->home_title === '') {
194            $this->home_title = $this->getHomeTitle();
195        }
196
197        switch ($baseclass) {
198            case 'illtiroutergui':
199                return;
200                break;
201        }
202    }
203
204    public function render($tpl, $part)
205    {
206        global $lng, $DIC;
207        $lng->loadLanguageModule("lti");
208        $f = $DIC->ui()->factory();
209        $renderer = $DIC->ui()->renderer();
210        switch ($part) {
211            case 'top_bar_header':
212                if (!$this->member_view) {
213                    if (!$tpl->blockExists("header_top_title")) {
214                        $tpl->addBlockFile("HEADER_TOP_TITLE", "header_top_title", "tpl.header_top_title.html", "Services/LTI");
215                    }
216                    $tpl->setVariable("TXT_HEADER_TITLE", $lng->txt("lti_session"));
217                } else {
218                    if (!$tpl->blockExists("header_back_bl")) {
219                        $tpl->addBlockFile("HEADER_BACK_BL", "header_back_bl", "tpl.header_back_bl.html", "Services/LTI");
220                    }
221                    $tpl->setVariable("URL_HEADER_BACK", $this->member_view_url);
222                    //$tpl->setVariable("TXT_HEADER_BACK", $lng->txt("lti_back_to_home")); // ToDo: $lng variable
223                    $tpl->setVariable("TXT_HEADER_BACK", $this->member_view_close_txt); // ToDo: $lng variable
224                }
225                break;
226            case 'view_nav':
227                $tpl->setVariable("TXT_VIEW_NAV", $lng->txt("lti_navigation")); // ToDo: language files
228                $nav_entries = $this->getNavEntries();
229                $tpl->setVariable("VIEW_NAV_EN", $nav_entries);
230
231                break;
232            case 'user_logged_in':
233                if (!$tpl->blockExists("userisloggedin")) {
234                    $tpl->addBlockFile("USERLOGGEDIN", "userisloggedin", "tpl.user_logged_in.html", "Services/LTI");
235                }
236                $tpl->setVariable("LINK_LTI_EXIT", $this->getCmdLink('exit'));
237                $tpl->setVariable("TXT_LTI_EXIT", $lng->txt("lti_exit"));
238                $btn = $f->button()->close();
239                $btnHtml = $renderer->render($btn);
240                $tpl->setVariable("EXIT_BUTTON", $btnHtml);
241                break;
242        }
243    }
244
245    private function getNavEntries()
246    {
247        global $lng, $ilNavigationHistory, $ilSetting, $ilCtrl;
248        include_once("./Services/UIComponent/GroupedList/classes/class.ilGroupedListGUI.php");
249        $gl = new ilGroupedListGUI();
250        $gl->setAsDropDown(true);
251
252        include_once("./Services/Link/classes/class.ilLink.php");
253
254        $icon = ilUtil::img(ilObject::_getIcon((int) $this->home_obj_id, "tiny"));
255
256        $gl->addEntry(
257            $icon . " " . $this->getHomeTitle(),
258            $this->getHomeLink(),
259            "_self"
260        );
261
262
263        $items = $ilNavigationHistory->getItems();
264        reset($items);
265        $cnt = 0;
266        $first = true;
267
268        foreach ($items as $k => $item) {
269            if ($cnt >= 10) {
270                break;
271            }
272
273            if (!isset($item["ref_id"]) || !isset($_GET["ref_id"]) ||
274                ($item["ref_id"] != $_GET["ref_id"] || !$first) && $this->home_id != $item["ref_id"]) { // do not list current item
275                if ($cnt == 0) {
276                    $gl->addGroupHeader($lng->txt("last_visited"), "ilLVNavEnt");
277                }
278                $obj_id = ilObject::_lookupObjId($item["ref_id"]);
279                $cnt++;
280                $icon = ilUtil::img(ilObject::_getIcon($obj_id, "tiny"));
281                $ititle = ilUtil::shortenText(strip_tags($item["title"]), 50, true); // #11023
282                $gl->addEntry($icon . " " . $ititle, $item["link"], "_self", "", "ilLVNavEnt");
283            }
284            $first = false;
285        }
286
287        if ($cnt > 0) {
288            $gl->addEntry(
289                "» " . $lng->txt("remove_entries"),
290                "#",
291                "",
292                "return il.MainMenu.removeLastVisitedItems('" .
293                $ilCtrl->getLinkTargetByClass("ilnavigationhistorygui", "removeEntries", "", true) . "');",
294                "ilLVNavEnt"
295            );
296        }
297
298        return $gl->getHTML();
299    }
300
301    /**
302     * add css files to the header
303     */
304    public function addCss()
305    {
306        $arr = array();
307        //$arr[] = "./Services/LTI/templates/default/hide.css";
308        return $arr;
309    }
310
311    /**
312     * append css styles just before </body>
313     */
314    public function appendInlineCss()
315    {
316        $arr = array();
317        $arr[] = "./Services/LTI/templates/default/lti.css";
318
319        if (isset($_SESSION['lti_launch_css_url']) && $_SESSION['lti_launch_css_url'] != "") {
320            $arr[] = $_SESSION['lti_launch_css_url'];
321        }
322        return $arr;
323    }
324
325    /**
326     * helper function for home link creation
327     */
328    protected function getHomeLink()
329    {
330        return $this->link_dir . "goto.php?target=" . $this->home_type . "_" . $this->home_id;
331    }
332
333    public function getHomeTitle()
334    {
335        return ilObject::_lookupTitle($this->home_obj_id);
336    }
337
338    /**
339     * exit LTI session and if defined redirecting to returnUrl
340     * ToDo: Standard Template with delos ...
341     */
342    public function exitLti()
343    {
344        global $lng;
345        $lng->loadLanguageModule("lti");
346        $this->log("exitLti");
347        if ($this->getSessionValue('lti_launch_presentation_return_url') === '') {
348            $tplExit = new ilTemplate("tpl.lti_exit.html", true, true, "Services/LTI");
349            $tplExit->setVariable('TXT_LTI_EXITED', $lng->txt('lti_exited'));
350            $tplExit->setVariable('LTI_EXITED_INFO', $lng->txt('lti_exited_info'));
351            $html = $tplExit->get();
352            $this->logout();
353            print $html;
354            exit;
355        } else {
356            $this->logout();
357            header('Location: ' . $_SESSION['lti_launch_presentation_return_url']);
358            exit;
359        }
360    }
361
362    /**
363     * logout ILIAS and destroys Session and ilClientId cookie
364     */
365    public function logout()
366    {
367        //$DIC->logger()->root()->debug("logout");
368        $this->deactivate();
369        ilSession::setClosingContext(ilSession::SESSION_CLOSE_USER);
370        //$this->dic['ilAuthSession']->logout();
371        $GLOBALS['DIC']['ilAuthSession']->logout();
372        // reset cookie
373        $client_id = $_COOKIE["ilClientId"];
374        ilUtil::setCookie("ilClientId", "");
375    }
376
377    /**
378     * Find effective ref_id for request
379     */
380    private function findEffectiveRefId()
381    {
382        if ((int) $_GET['ref_id']) {
383            $this->current_type = ilObject::_lookupType($_GET['ref_id'], true);
384            return $this->current_ref_id = (int) $_GET['ref_id'];
385        }
386
387        $target_arr = explode('_', (string) $_GET['target']);
388        if (isset($target_arr[1]) and (int) $target_arr[1]) {
389            $this->current_type = ilObject::_lookupType($target_arr[1], true);
390            $this->home_title = ilObject::_lookupTitle(ilObject::_lookupObjectId($target_arr[1]));
391            return $this->current_ref_id = (int) $target_arr[1];
392        }
393    }
394
395    /**
396     * @return bool
397     */
398    private function showLocator($obj_type)
399    {
400        //return true;
401        return preg_match("/(crs|grp|cat|root|fold|lm)/", $obj_type);
402    }
403
404    /**
405     * helper function for cmd link creation
406     */
407    protected function getCmdLink($cmd)
408    {
409        global $ilCtrl;
410        $targetScript = ($ilCtrl->getTargetScript() !== 'ilias.php') ? "ilias.php" : "";
411        return $this->link_dir . $targetScript . $ilCtrl->getLinkTargetByClass(array('illtiroutergui',strtolower(get_class($this))), $cmd) . "&baseClass=illtiroutergui";
412    }
413
414    /**
415     * get session value != ''
416     *
417     * @param $sess_key string
418     * @return string
419     */
420    public function getSessionValue($sess_key)
421    {
422        if (isset($_SESSION[$sess_key]) && $_SESSION[$sess_key] != '') {
423            return $_SESSION[$sess_key];
424        } else {
425            return '';
426        }
427    }
428
429    private function log($txt)
430    {
431        global $DIC;
432        if (self::LTI_DEBUG) {
433            $DIC->logger()->lti()->write($txt);
434        }
435    }
436}
437