ILIAS  release_8 Revision v8.24
class.ilLTIViewGUI.php
Go to the documentation of this file.
1<?php
2
3declare(strict_types=1);
4
22
33{
37 public const CHECK_HTTP_REFERER = true;
38
42 private ?ILIAS\DI\Container $dic = null;
43 private ?int $user = null;
44 private ?ilLogger $log = null;
45 private string $link_dir = "";
46
47 private ?int $effectiveRefId = null;
48 private \ILIAS\HTTP\Wrapper\WrapperFactory $wrapper;
51
55 public ?ilLanguage $lng = null;
56
60 public function __construct()
61 {
62 global $DIC;
63 $this->dic = $DIC;
64 $this->log = ilLoggerFactory::getLogger('ltis');
65 $this->lng = $this->dic->language();
66 $this->lng->loadLanguageModule('lti');
67 $this->wrapper = $DIC->http()->wrapper();
68 $this->kindlyTo = $DIC->refinery()->kindlyTo();
69 $this->locator = $DIC['ilLocator'];
70 }
71
75 public function init(): void
76 {
77 $this->link_dir = (defined("ILIAS_MODULE")) ? "../" : "";
78 if ($this->isLTIUser()) {
79 $context = $this->dic->globalScreen()->tool()->context();
80 $context->claim()->lti();
81 $this->initGUI();
82 }
83 }
84
89 public static function getInstance()
90 {
91 global $DIC;
92 return $DIC["lti"];
93 }
94
99 private function isLTIUser(): bool
100 {
101 if (!$this->dic->user() instanceof ilObjUser) {
102 return false;
103 }
104 if ($this->dic->user()->getAuthMode() == null) {
105 return false;
106 }
107 return (strpos($this->dic->user()->getAuthMode(), 'lti_') === 0);
108 }
109
113 public function executeCommand(): void
114 {
115 global $ilCtrl;
116 $cmd = $ilCtrl->getCmd();
117 switch ($cmd) {
118 case 'exit':
119 $this->exitLti();
120 break;
121 }
122 }
123
127 public function isActive(): bool
128 {
129 return $this->isLTIUser();
130 }
131
135 public function initGUI(): void
136 {
137 $this->log->debug("initGUI");
138 $baseclass = '';
139 if ($this->wrapper->query()->has('baseClass')) {
140 $baseclass = strtolower($this->wrapper->query()->retrieve('baseClass', $this->kindlyTo->string()));
141 }
142 if ($this->wrapper->query()->has('cmdClass')) {
143 $cmdclass = strtolower($this->wrapper->query()->retrieve('cmdClass', $this->kindlyTo->string()));
144 }
145 if ($baseclass == 'illtiroutergui') {
146 return;
147 }
148 }
149
153 protected function getContextId(): ?int
154 {
155 global $DIC;
156
157 // forced lti_context_id for example request command in exitLTI
158 if ($this->wrapper->query()->has('lti_context_id') &&
159 $this->wrapper->query()->retrieve('lti_context_id', $this->kindlyTo->string()) !== '') {
160 $contextId = (int) $this->wrapper->query()->retrieve('lti_context_id', $this->kindlyTo->int());
161 $this->log->debug("find context_id by GET param: " . (string) $contextId);
162 return $contextId;
163 }
164
165 $this->findEffectiveRefId();
166
167 if (
168 (
169 $this->wrapper->query()->has('baseClass') &&
170 $this->wrapper->query()->retrieve('baseClass', $this->kindlyTo->string()) === 'ilDashboardGUI'
171 )
172 &&
173 (
174 $this->wrapper->query()->has('cmd') &&
175 $this->wrapper->query()->retrieve('cmd', $this->kindlyTo->string()) === 'jumpToSelectedItems'
176 )
177 ) {
178 $this->log->debug("jumpToSelectedItems");
179 if (ilSession::get('lti_ref_id_at_init') != "") {
180 $this->effectiveRefId = (int) ilSession::get('lti_ref_id_at_init');
181 ilSession::set('lti_ref_id_at_init', "");
182 }
183 }
184
186 if (empty($ref_id)) {
187 $this->log->debug("empty ref_id");
188 return 0;
189 }
190
191 $this->log->debug("Effective ref_id: " . $ref_id);
192 //check
193 ilSession::set('lti_ref_id_at_init', (string) $ref_id);
194
195
196 // context_id = ref_id in request
197 if (ilSession::has('lti_' . $ref_id . '_post_data')) {
198 $this->log->debug("lti context session exists for " . $ref_id);
199 // return $ref_id;
200 }
201 // sub item request
202 $this->log->debug("ref_id not exists as context_id, walking tree backwards to find a valid context_id");
203 $locator_items = $this->locator->getItems();
204 if (is_array($locator_items) && count($locator_items) > 0) {
205 for ($i = count($locator_items) - 1;$i >= 0;$i--) {
206 if (ilSession::has('lti_' . $locator_items[$i]['ref_id'] . '_post_data')) {
207 $this->log->debug("found valid ref_id in locator: " . $locator_items[$i]['ref_id']);
208 return $locator_items[$i]['ref_id'];
209 }
210 }
211 }
212 $this->log->warning("no valid context_id found for ref_id request: " . $ref_id);
213
216 $obj_type = ilObject::_lookupType($ref_id, true);
217 $context_id = 0;
218 $referer = 0;
219
220 // first try to get real http referer
221 if (isset($_SERVER['HTTP_REFERER'])) {
222 $this->findEffectiveRefId($_SERVER['HTTP_REFERER']);
223 } else { // only fallback and not reliable on multiple browser LTi contexts
224 if (ilSession::has('referer_ref_id')) {
225 $this->effectiveRefId = ilSession::get('referer_ref_id');
226 }
227 }
228
229 $referrer = (int) $this->effectiveRefId;
230
231 if ($referer > 0) {
232 if (ilSession::has('lti_' . $referer . '_post_data')) {
233 $ref_id = $referer;
234 $context_id = $referer;
235 $obj_type = ilObject::_lookupType($ref_id, true);
236 $this->log->debug("referer obj_type: " . $obj_type);
237 } else {
238 $this->log->debug("search tree of referer...");
239 if ($this->dic->repositoryTree()->isInTree($referer)) {
240 $path = $this->dic->repositoryTree()->getPathId($referer);
241 for ($i = count($path) - 1;$i >= 0;$i--) {
242 if (ilSession::has('lti_' . $path[$i] . '_post_data')) {
243 // redirect to referer, because it is valid
244 $ref_id = $referer;
245 $context_id = $path[$i];
246 $obj_type = ilObject::_lookupType($ref_id, true);
247 break;
248 }
249 }
250 }
251 }
252 }
253 if ($ref_id > 0 && $obj_type != '') {
254 if (
255 (
256 $this->wrapper->query()->has('baseClass') &&
257 $this->wrapper->query()->retrieve('baseClass', $this->kindlyTo->string()) === 'ilDashboardGUI'
258 )
259 &&
260 (
261 $this->wrapper->query()->has('cmdClass') &&
262 $this->wrapper->query()->retrieve('cmdClass', $this->kindlyTo->string()) === 'ilpersonalprofilegui'
263 )
264 ) {
265 return $context_id;
266 }
267 // $this->dic->ui()->mainTemplate()->setOnScreenMessage('failure', $this->lng->txt('permission_denied'), true);
268 $redirect = $this->link_dir . "goto.php?target=" . $obj_type . "_" . $ref_id . "&lti_context_id=" . $context_id;
269 $this->log->debug("redirect: " . $redirect);
270 ilUtil::redirect($redirect);
271 }
272 }
273 $lti_context_ids = ilSession::get('lti_context_ids');
274 if (is_array($lti_context_ids) && count($lti_context_ids) > 0) {
275 if (count($lti_context_ids) == 1) {
276 $this->log->debug("using context_id from only LTI session");
277 return $lti_context_ids[0];
278 } else {
279 $this->log->warning("Multiple LTI sessions exists. The context_id can not be clearly detected");
280 }
281 }
282 return null;
283 }
284
288 public function getPostData(): ?array
289 {
290 $context_id = $this->getContextId();
291 if ($context_id == 0) {
292 $this->log->warning("could not find any valid context_id!");
293 return null;
294 }
295 $post_data = ilSession::get('lti_' . $context_id . '_post_data');
296 if (!is_array($post_data)) {
297 $this->log->warning("no session post_data: " . "lti_" . $context_id . "_post_data");
298 return null;
299 }
300 return $post_data;
301 }
302
306 public function getExternalCss(): string
307 {
308 $post_data = $this->getPostData();
309 if ($post_data !== null) {
310 return (isset($post_data['launch_presentation_css_url'])) ? $post_data['launch_presentation_css_url'] : '';
311 }
312 return '';
313 }
314
318 public function getTitle(): string
319 {
320 $post_data = $this->getPostData();
321 if ($post_data !== null) {
322 return (isset($post_data['resource_link_title'])) ? "LTI - " . $post_data['resource_link_title'] : "LTI";
323 }
324 return "LTI";
325 }
326
330 public function getTitleForExitPage(): string
331 {
332 return $this->lng->txt('lti_exited');
333 }
334
338 public function getShortTitle(): string
339 {
340 return $this->lng->txt('lti_mode');
341 }
342
347 public function exitLti(): void
348 {
349 $this->log->info("exitLTI");
350 $force_ilias_logout = false;
351 $context_id = $this->getContextId();
352 if ($context_id == 0) {
353 $this->log->warning("could not find any valid context_id!");
354 $force_ilias_logout = true;
355 }
356 $post_data = $this->getPostData();
357
358 $return_url = '';
359 if (isset($post_data['launch_presentation_return_url'])) {
360 $return_url = $post_data['launch_presentation_return_url'];
361 }
362 $this->removeContextFromSession((string) $context_id);
363
364 if (ilSession::has('lti_' . $context_id . '_post_data')) {
365 ilSession::clear('lti_' . $context_id . '_post_data');
366 $this->log->debug('unset SESSION["' . 'lti_' . $context_id . '_post_data"]');
367 }
368
369 if (!isset($return_url) || $return_url === '') {
370 $cc = $this->dic->globalScreen()->tool()->context()->current();
371 $cc->addAdditionalData(LtiViewLayoutProvider::GS_EXIT_LTI, true);
372 $ui_factory = $this->dic->ui()->factory();
373 $renderer = $this->dic->ui()->renderer();
374 $content = [
375 $ui_factory->messageBox()->info($this->lng->txt('lti_exited_info'))
376 ];
377 $tpl = $this->dic["tpl"];
378 $tpl->setContent($renderer->render($content));
379 $this->logout($force_ilias_logout);
380 $tpl->printToStdout();
381 } else {
382 $this->logout($force_ilias_logout);
383 header('Location: ' . $return_url);
384 }
385 }
386
390 public function logout(bool $force_ilias_logout = false): void
391 {
392 if ($force_ilias_logout) {
393 $this->log->warning("forcing logout ilias session, maybe a broken LTI context");
394 } else {
395 if (is_array(ilSession::get('lti_context_ids')) && count(ilSession::get('lti_context_ids')) > 0) {
396 $this->log->debug("there is another valid consumer session: ilias session logout refused.");
397 return;
398 }
399 }
400 $this->log->info("logout");
401 $this->dic->user()->setAuthMode((string) ilAuthUtils::AUTH_LOCAL);
402 //ilSession::setClosingContext(ilSession::SESSION_CLOSE_USER); // needed?
403 $auth = $this->dic['ilAuthSession'];
404 //$auth->logout(); // needed?
405 // $auth->setExpired($auth::SESSION_AUTH_EXPIRED, ilAuthStatus::STATUS_UNDEFINED);
406 $auth->setExpired(true);
407 session_destroy();
408 ilUtil::setCookie("ilClientId", "");
409 ilUtil::setCookie("PHPSESSID", "");
410 }
411
417 public function getCmdLink(String $cmd): String
418 {
419 global $ilCtrl;
420 $lti_context_id = $this->getContextId();
421 $lti_context_id_param = ($lti_context_id != '') ? "&lti_context_id=" . $lti_context_id : '';
422 $targetScript = "";
423 return $this->link_dir . $targetScript . $this->dic->ctrl()->getLinkTargetByClass(array('illtiroutergui',strtolower(get_class($this))), $cmd) . "&baseClass=illtiroutergui" . $lti_context_id_param;
424 }
425
426 private function getSessionValue(string $sess_key): string
427 {
428 if (ilSession::has($sess_key) && ilSession::get($sess_key) != '') {
429 return ilSession::get($sess_key);
430 } else {
431 return '';
432 }
433 }
434
435 private function getCookieValue(string $cookie_key): string
436 {
437 if ($this->dic->wrapper->cookie()->has($cookie_key) && $this->dic->wrapper->cookie()->retrieve($cookie_key, $this->dic->refinery()->kindlyTo()->string() != '')) {
438 return $this->dic->wrapper->cookie()->retrieve($cookie_key, $this->dic->refinery()->kindlyTo()->string());
439 } else {
440 return '';
441 }
442 }
443
444 private function removeContextFromSession(string $context_id): void
445 {
446 $lti_context_ids = ilSession::get('lti_context_ids');
447 if (is_array($lti_context_ids) && in_array($context_id, $lti_context_ids)) {
448 array_splice($lti_context_ids, array_search($context_id, $lti_context_ids), 1);
449 ilSession::set('lti_context_ids', $lti_context_ids);
450 }
451 }
452
457 private function findEffectiveRefId(?string $url = null): void
458 {
459 $query = [];
460 if ($url === null) {
461 if ($this->wrapper->query()->has('ref_id')) {
462 $query['ref_id'] = $this->wrapper->query()->retrieve('ref_id', $this->kindlyTo->string());
463 }
464 if ($this->wrapper->query()->has('target')) {
465 $query['target'] = $this->wrapper->query()->retrieve('target', $this->kindlyTo->string());
466 }
467 } else {
468 parse_str((string) parse_url($url, PHP_URL_QUERY), $query);
469 }
470 if (isset($query['ref_id']) && (int) $query['ref_id']) {
471 $this->effectiveRefId = (int) $query['ref_id'];
472 return;
473 }
474 if (ilSession::has('lti_init_target') && ilSession::get('lti_init_target') != "") {
475 $target_arr = explode('_', ilSession::get('lti_init_target'));
476 ilSession::set('lti_init_target', "");
477 } else {
478 if (isset($query['target'])) {
479 $target_arr = explode('_', (string) $query['target']);
480 }
481 }
482 if (isset($target_arr[1]) and (int) $target_arr[1]) {
483 $this->effectiveRefId = (int) $target_arr[1];
484 }
485 }
486}
Customizing of pimple-DIC for ILIAS.
Definition: Container.php:32
@classDescription class for ILIAS ViewLTI
getSessionValue(string $sess_key)
removeContextFromSession(string $context_id)
ILIAS Refinery KindlyTo Group $kindlyTo
getCookieValue(string $cookie_key)
logout(bool $force_ilias_logout=false)
logout ILIAS and destroys Session and ilClientId cookie if no consumer is still open in the LTI User ...
findEffectiveRefId(?string $url=null)
Find effective ref_id for request.
isLTIUser()
get LTI Mode from Users->getAuthMode
ILIAS DI Container $dic
private variables
init()
Init LTI mode for lti authenticated users.
ilLanguage $lng
public variables
static getInstance()
for compatiblity with ilLTIRouterGUI
exitLti()
exit LTI session and if defined redirecting to returnUrl ToDo: Standard Template with delos ....
ilLocatorGUI $locator
getCmdLink(String $cmd)
const CHECK_HTTP_REFERER
contstants
ILIAS HTTP Wrapper WrapperFactory $wrapper
language handling
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getLogger(string $a_component_id)
Get component logger.
Component logger with individual log levels by component id.
User class.
static _lookupType(int $id, bool $reference=false)
static get(string $a_var)
static clear(string $a_var)
static set(string $a_var, $a_val)
Set a value.
static has($a_var)
static redirect(string $a_script)
static setCookie(string $a_cookie_name, string $a_cookie_value='', bool $a_also_set_super_global=true, bool $a_set_cookie_invalid=false)
global $DIC
Definition: feed.php:28
$target_arr
Definition: goto.php:50
if($DIC->http() ->request() ->getMethod()=="GET" &&isset($DIC->http() ->request() ->getQueryParams()['tex'])) $tpl
Definition: latex.php:41
$ref_id
Definition: ltiauth.php:67
$path
Definition: ltiservices.php:32
$auth
Definition: metadata.php:76
$i
Definition: metadata.php:41
$query
$url
$_SERVER['HTTP_HOST']
Definition: raiseError.php:10
$context
Definition: webdav.php:29