ILIAS  release_7 Revision v7.30-3-g800a261c036
ilLTIToolProvider Class Reference

LTI provider for LTI launch. More...

+ Inheritance diagram for ilLTIToolProvider:
+ Collaboration diagram for ilLTIToolProvider:

Public Member Functions

 __construct (DataConnector $dataConnector)
 ilLTIToolProvider constructor. More...
 
 handleRequest ()
 Process an incoming request. More...
 

Data Fields

 $debugMode = false
 

Protected Member Functions

 onLaunch ()
 Process a valid launch request. More...
 
 onContentItem ()
 Process a valid content-item request. More...
 
 onRegister ()
 Process a valid tool proxy registration request. More...
 
 onError ()
 Process a response to an invalid request. More...
 

Protected Attributes

 $logger = null
 

Private Member Functions

 doCallback ($method=null)
 Call any callback function for the requested action. More...
 
 result ()
 Perform the result of an action. More...
 
 authenticate ()
 Check the authenticity of the LTI launch request. More...
 
 checkForShare ()
 Check if a share arrangement is in place. More...
 
 checkValue ($value, $values, $reason)
 Validate a parameter value from an array of permitted values. More...
 

Static Private Attributes

static $LTI_VERSIONS = array(self::LTI_VERSION1, self::LTI_VERSION2)
 Permitted LTI versions for messages. More...
 
static $MESSAGE_TYPES
 List of supported message types and associated class methods. More...
 
static $METHOD_NAMES
 List of supported message types and associated class methods. More...
 
static $LTI_CONSUMER_SETTING_NAMES = array('custom_tc_profile_url', 'custom_system_setting_url')
 Names of LTI parameters to be retained in the consumer settings property. More...
 
static $LTI_CONTEXT_SETTING_NAMES
 Names of LTI parameters to be retained in the context settings property. More...
 
static $LTI_RESOURCE_LINK_SETTING_NAMES
 Names of LTI parameters to be retained in the resource link settings property. More...
 
static $CUSTOM_SUBSTITUTION_VARIABLES
 Names of LTI custom parameter substitution variables (or capabilities) and their associated default message parameter names. More...
 

Detailed Description

Constructor & Destructor Documentation

◆ __construct()

ilLTIToolProvider::__construct ( DataConnector  $dataConnector)

ilLTIToolProvider constructor.

Parameters
DataConnector$dataConnector

Definition at line 122 of file class.ilLTIToolProvider.php.

123 {
124 global $DIC;
125
126 $this->logger = $DIC->logger()->lti();
127 parent::__construct($dataConnector);
128 }
global $DIC
Definition: goto.php:24
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc

References $DIC, and ILIAS\GlobalScreen\Provider\__construct().

+ Here is the call graph for this function:

Member Function Documentation

◆ authenticate()

ilLTIToolProvider::authenticate ( )
private

Check the authenticity of the LTI launch request.

The consumer, resource link and user objects will be initialised if the request is valid.

Returns
boolean True if the request has been successfully validated.

Definition at line 302 of file class.ilLTIToolProvider.php.

303 {
304
305// Get the consumer
306 $doSaveConsumer = false;
307 // Check all required launch parameters
308 $this->ok = isset($_POST['lti_message_type']) && array_key_exists($_POST['lti_message_type'], self::$MESSAGE_TYPES);
309 if (!$this->ok) {
310 $this->reason = 'Invalid or missing lti_message_type parameter.';
311 }
312 if ($this->ok) {
313 $this->ok = isset($_POST['lti_version']) && in_array($_POST['lti_version'], self::$LTI_VERSIONS);
314 if (!$this->ok) {
315 $this->reason = 'Invalid or missing lti_version parameter.';
316 }
317 }
318 if ($this->ok) {
319 if ($_POST['lti_message_type'] === 'basic-lti-launch-request') {
320 $this->ok = isset($_POST['resource_link_id']) && (strlen(trim($_POST['resource_link_id'])) > 0);
321 if (!$this->ok) {
322 $this->reason = 'Missing resource link ID.';
323 }
324 } elseif ($_POST['lti_message_type'] === 'ContentItemSelectionRequest') {
325 if (isset($_POST['accept_media_types']) && (strlen(trim($_POST['accept_media_types'])) > 0)) {
326 $mediaTypes = array_filter(explode(',', str_replace(' ', '', $_POST['accept_media_types'])), 'strlen');
327 $mediaTypes = array_unique($mediaTypes);
328 $this->ok = count($mediaTypes) > 0;
329 if (!$this->ok) {
330 $this->reason = 'No accept_media_types found.';
331 } else {
332 $this->mediaTypes = $mediaTypes;
333 }
334 } else {
335 $this->ok = false;
336 }
337 if ($this->ok && isset($_POST['accept_presentation_document_targets']) && (strlen(trim($_POST['accept_presentation_document_targets'])) > 0)) {
338 $documentTargets = array_filter(explode(',', str_replace(' ', '', $_POST['accept_presentation_document_targets'])), 'strlen');
339 $documentTargets = array_unique($documentTargets);
340 $this->ok = count($documentTargets) > 0;
341 if (!$this->ok) {
342 $this->reason = 'Missing or empty accept_presentation_document_targets parameter.';
343 } else {
344 foreach ($documentTargets as $documentTarget) {
345 $this->ok = $this->checkValue(
346 $documentTarget,
347 array('embed', 'frame', 'iframe', 'window', 'popup', 'overlay', 'none'),
348 'Invalid value in accept_presentation_document_targets parameter: %s.'
349 );
350 if (!$this->ok) {
351 break;
352 }
353 }
354 if ($this->ok) {
355 $this->documentTargets = $documentTargets;
356 }
357 }
358 } else {
359 $this->ok = false;
360 }
361 if ($this->ok) {
362 $this->ok = isset($_POST['content_item_return_url']) && (strlen(trim($_POST['content_item_return_url'])) > 0);
363 if (!$this->ok) {
364 $this->reason = 'Missing content_item_return_url parameter.';
365 }
366 }
367 } elseif ($_POST['lti_message_type'] == 'ToolProxyRegistrationRequest') {
368 $this->ok = ((isset($_POST['reg_key']) && (strlen(trim($_POST['reg_key'])) > 0)) &&
369 (isset($_POST['reg_password']) && (strlen(trim($_POST['reg_password'])) > 0)) &&
370 (isset($_POST['tc_profile_url']) && (strlen(trim($_POST['tc_profile_url'])) > 0)) &&
371 (isset($_POST['launch_presentation_return_url']) && (strlen(trim($_POST['launch_presentation_return_url'])) > 0)));
372 if ($this->debugMode && !$this->ok) {
373 $this->reason = 'Missing message parameters.';
374 }
375 }
376 }
377 $now = time();
378
379 $this->logger->debug('Checking consumer key...');
380
381 // Check consumer key
382 if ($this->ok && ($_POST['lti_message_type'] != 'ToolProxyRegistrationRequest')) {
383 $this->ok = isset($_POST['oauth_consumer_key']);
384 if (!$this->ok) {
385 $this->reason = 'Missing consumer key.';
386 }
387 if ($this->ok) {
388 // $this->consumer = new ToolConsumer($_POST['oauth_consumer_key'], $this->dataConnector);
389 $this->consumer = new ilLTIToolConsumer($_POST['oauth_consumer_key'], $this->dataConnector);
390 $this->ok = !is_null($this->consumer->created);
391 if (!$this->ok) {
392 $this->reason = 'Invalid consumer key.';
393 }
394 }
395 if ($this->ok) {
396 $today = date('Y-m-d', $now);
397 if (is_null($this->consumer->lastAccess)) {
398 $doSaveConsumer = true;
399 } else {
400 $last = date('Y-m-d', $this->consumer->lastAccess);
401 $doSaveConsumer = $doSaveConsumer || ($last !== $today);
402 }
403 $this->consumer->last_access = $now;
404 try {
405 $store = new OAuthDataStore($this);
406 $server = new OAuth\OAuthServer($store);
407 $method = new OAuth\OAuthSignatureMethod_HMAC_SHA1();
408 $server->add_signature_method($method);
409 $request = OAuth\OAuthRequest::from_request();
410 $res = $server->verify_request($request);
411 } catch (\Exception $e) {
412 $this->ok = false;
413 if (empty($this->reason)) {
414 if ($this->debugMode) {
415 $consumer = new OAuth\OAuthConsumer($this->consumer->getKey(), $this->consumer->secret);
416 $signature = $request->build_signature($method, $consumer, false);
417 $this->reason = $e->getMessage();
418 if (empty($this->reason)) {
419 $this->reason = 'OAuth exception';
420 }
421 $this->details[] = 'Timestamp: ' . time();
422 $this->details[] = "Signature: {$signature}";
423 $this->details[] = "Base string: {$request->base_string}]";
424 } else {
425 $this->reason = 'OAuth signature check failed - perhaps an incorrect secret or timestamp.';
426 }
427 }
428 }
429 }
430 // $this->ok = true; //ACHTUNG Problem Signature bei M.
431 if ($this->ok) {
432 $today = date('Y-m-d', $now);
433 if (is_null($this->consumer->lastAccess)) {
434 $doSaveConsumer = true;
435 } else {
436 $last = date('Y-m-d', $this->consumer->lastAccess);
437 $doSaveConsumer = $doSaveConsumer || ($last !== $today);
438 }
439 $this->consumer->last_access = $now;
440 if ($this->consumer->protected) {
441 if (!is_null($this->consumer->consumerGuid)) {
442 $this->ok = empty($_POST['tool_consumer_instance_guid']) ||
443 ($this->consumer->consumerGuid === $_POST['tool_consumer_instance_guid']);
444 if (!$this->ok) {
445 $this->reason = 'Request is from an invalid tool consumer.';
446 }
447 } else {
448 $this->ok = isset($_POST['tool_consumer_instance_guid']);
449 if (!$this->ok) {
450 $this->reason = 'A tool consumer GUID must be included in the launch request.';
451 }
452 }
453 }
454 if ($this->ok) {
455 $this->ok = $this->consumer->enabled;
456 if (!$this->ok) {
457 $this->reason = 'Tool consumer has not been enabled by the tool provider.';
458 }
459 }
460 if ($this->ok) {
461 $this->ok = is_null($this->consumer->enableFrom) || ($this->consumer->enableFrom <= $now);
462 if ($this->ok) {
463 $this->ok = is_null($this->consumer->enableUntil) || ($this->consumer->enableUntil > $now);
464 if (!$this->ok) {
465 $this->reason = 'Tool consumer access has expired.';
466 }
467 } else {
468 $this->reason = 'Tool consumer access is not yet available.';
469 }
470 }
471 }
472 // Validate other message parameter values
473 if ($this->ok) {
474 if ($_POST['lti_message_type'] === 'ContentItemSelectionRequest') {
475 if (isset($_POST['accept_unsigned'])) {
476 $this->ok = $this->checkValue($_POST['accept_unsigned'], array('true', 'false'), 'Invalid value for accept_unsigned parameter: %s.');
477 }
478 if ($this->ok && isset($_POST['accept_multiple'])) {
479 $this->ok = $this->checkValue($_POST['accept_multiple'], array('true', 'false'), 'Invalid value for accept_multiple parameter: %s.');
480 }
481 if ($this->ok && isset($_POST['accept_copy_advice'])) {
482 $this->ok = $this->checkValue($_POST['accept_copy_advice'], array('true', 'false'), 'Invalid value for accept_copy_advice parameter: %s.');
483 }
484 if ($this->ok && isset($_POST['auto_create'])) {
485 $this->ok = $this->checkValue($_POST['auto_create'], array('true', 'false'), 'Invalid value for auto_create parameter: %s.');
486 }
487 if ($this->ok && isset($_POST['can_confirm'])) {
488 $this->ok = $this->checkValue($_POST['can_confirm'], array('true', 'false'), 'Invalid value for can_confirm parameter: %s.');
489 }
490 } elseif (isset($_POST['launch_presentation_document_target'])) {
491 $this->ok = $this->checkValue(
492 $_POST['launch_presentation_document_target'],
493 array('embed', 'frame', 'iframe', 'window', 'popup', 'overlay'),
494 'Invalid value for launch_presentation_document_target parameter: %s.'
495 );
496 }
497 }
498 }
499
500 if ($this->ok && ($_POST['lti_message_type'] === 'ToolProxyRegistrationRequest')) {
501 $this->ok = $_POST['lti_version'] == self::LTI_VERSION2;
502 if (!$this->ok) {
503 $this->reason = 'Invalid lti_version parameter';
504 }
505 if ($this->ok) {
506 $http = new HTTPMessage($_POST['tc_profile_url'], 'GET', null, 'Accept: application/vnd.ims.lti.v2.toolconsumerprofile+json');
507 $this->ok = $http->send();
508 if (!$this->ok) {
509 $this->reason = 'Tool consumer profile not accessible.';
510 } else {
511 $tcProfile = json_decode($http->response);
512 $this->ok = !is_null($tcProfile);
513 if (!$this->ok) {
514 $this->reason = 'Invalid JSON in tool consumer profile.';
515 }
516 }
517 }
518 // Check for required capabilities
519 if ($this->ok) {
520 // $this->consumer = new ToolConsumer($_POST['reg_key'], $this->dataConnector);
521 $this->consumer = new ilLTIToolConsumer($_POST['oauth_consumer_key'], $this->dataConnector);
522 $this->consumer->profile = $tcProfile;
523 $capabilities = $this->consumer->profile->capability_offered;
524 $missing = array();
525 foreach ($this->resourceHandlers as $resourceHandler) {
526 foreach ($resourceHandler->requiredMessages as $message) {
527 if (!in_array($message->type, $capabilities)) {
528 $missing[$message->type] = true;
529 }
530 }
531 }
532 foreach ($this->constraints as $name => $constraint) {
533 if ($constraint['required']) {
534 if (!in_array($name, $capabilities) && !in_array($name, array_flip($capabilities))) {
535 $missing[$name] = true;
536 }
537 }
538 }
539 if (!empty($missing)) {
540 ksort($missing);
541 $this->reason = 'Required capability not offered - \'' . implode('\', \'', array_keys($missing)) . '\'';
542 $this->ok = false;
543 }
544 }
545 // Check for required services
546 if ($this->ok) {
547 foreach ($this->requiredServices as $service) {
548 foreach ($service->formats as $format) {
549 if (!$this->findService($format, $service->actions)) {
550 if ($this->ok) {
551 $this->reason = 'Required service(s) not offered - ';
552 $this->ok = false;
553 } else {
554 $this->reason .= ', ';
555 }
556 $this->reason .= "'{$format}' [" . implode(', ', $service->actions) . ']';
557 }
558 }
559 }
560 }
561 if ($this->ok) {
562 if ($_POST['lti_message_type'] === 'ToolProxyRegistrationRequest') {
563 $this->consumer->profile = $tcProfile;
564 $this->consumer->secret = $_POST['reg_password'];
565 $this->consumer->ltiVersion = $_POST['lti_version'];
566 $this->consumer->name = $tcProfile->product_instance->service_owner->service_owner_name->default_value;
567 $this->consumer->consumerName = $this->consumer->name;
568 $this->consumer->consumerVersion = "{$tcProfile->product_instance->product_info->product_family->code}-{$tcProfile->product_instance->product_info->product_version}";
569 $this->consumer->consumerGuid = $tcProfile->product_instance->guid;
570 $this->consumer->enabled = true;
571 $this->consumer->protected = true;
572 $doSaveConsumer = true;
573 }
574 }
575 } elseif ($this->ok && !empty($_POST['custom_tc_profile_url']) && empty($this->consumer->profile)) {
576 $http = new HTTPMessage($_POST['custom_tc_profile_url'], 'GET', null, 'Accept: application/vnd.ims.lti.v2.toolconsumerprofile+json');
577 if ($http->send()) {
578 $tcProfile = json_decode($http->response);
579 if (!is_null($tcProfile)) {
580 $this->consumer->profile = $tcProfile;
581 $doSaveConsumer = true;
582 }
583 }
584 }
585 //ACHTUNG HIER TODO UWE
586 // Validate message parameter constraints
587 // if ($this->ok) {
588 // $invalidParameters = array();
589 // foreach ($this->constraints as $name => $constraint) {
590 // // if (empty($constraint['messages']) || in_array($_POST['lti_message_type'], $constraint['messages'])) {
591 // // $ok = true;
592 // // if ($constraint['required']) {
593 // // if (!isset($_POST[$name]) || (strlen(trim($_POST[$name])) <= 0)) {
594 // // $invalidParameters[] = "{$name} (missing)";
595 // // $ok = false;
596 // // }
597 // // }
598 // // if ($ok && !is_null($constraint['max_length']) && isset($_POST[$name])) {
599 // // if (strlen(trim($_POST[$name])) > $constraint['max_length']) {
600 // // $invalidParameters[] = "{$name} (too long)";
601 // // }
602 // // }
603 // // }
604 // }
605 // if (count($invalidParameters) > 0) {
606 // $this->ok = false;
607 // if (empty($this->reason)) {
608 // $this->reason = 'Invalid parameter(s): ' . implode(', ', $invalidParameters) . '.';
609 // }
610 // }
611 // }
612
613 $this->logger->debug('Still ok: ' . ($this->ok ? '1' : '0'));
614 if (!$this->ok) {
615 $this->logger->debug('Reason: ' . $this->reason);
616 }
617
618 if ($this->ok) {
619
620// Set the request context
621 if (isset($_POST['context_id'])) {
622 $this->context = Context::fromConsumer($this->consumer, trim($_POST['context_id']));
623 $title = '';
624 if (isset($_POST['context_title'])) {
625 $title = trim($_POST['context_title']);
626 }
627 if (empty($title)) {
628 $title = "Course {$this->context->getId()}";
629 }
630 $this->context->title = $title;
631 }
632
633 // Set the request resource link
634 if (isset($_POST['resource_link_id'])) {
635 $contentItemId = '';
636 if (isset($_POST['custom_content_item_id'])) {
637 $contentItemId = $_POST['custom_content_item_id'];
638 }
639 $this->resourceLink = ResourceLink::fromConsumer($this->consumer, trim($_POST['resource_link_id']), $contentItemId);
640 if (!empty($this->context)) {
641 $this->resourceLink->setContextId($this->context->getRecordId());
642 }
643 $title = '';
644 if (isset($_POST['resource_link_title'])) {
645 $title = trim($_POST['resource_link_title']);
646 }
647 if (empty($title)) {
648 $title = "Resource {$this->resourceLink->getId()}";
649 }
650 $this->resourceLink->title = $title;
651 // Delete any existing custom parameters
652 foreach ($this->consumer->getSettings() as $name => $value) {
653 if (strpos($name, 'custom_') === 0) {
654 $this->consumer->setSetting($name);
655 $doSaveConsumer = true;
656 }
657 }
658 if (!empty($this->context)) {
659 foreach ($this->context->getSettings() as $name => $value) {
660 if (strpos($name, 'custom_') === 0) {
661 $this->context->setSetting($name);
662 }
663 }
664 }
665 foreach ($this->resourceLink->getSettings() as $name => $value) {
666 if (strpos($name, 'custom_') === 0) {
667 $this->resourceLink->setSetting($name);
668 }
669 }
670 // Save LTI parameters
671 foreach (self::$LTI_CONSUMER_SETTING_NAMES as $name) {
672 if (isset($_POST[$name])) {
673 $this->consumer->setSetting($name, $_POST[$name]);
674 } else {
675 $this->consumer->setSetting($name);
676 }
677 }
678 if (!empty($this->context)) {
679 foreach (self::$LTI_CONTEXT_SETTING_NAMES as $name) {
680 if (isset($_POST[$name])) {
681 $this->context->setSetting($name, $_POST[$name]);
682 } else {
683 $this->context->setSetting($name);
684 }
685 }
686 }
687 foreach (self::$LTI_RESOURCE_LINK_SETTING_NAMES as $name) {
688 if (isset($_POST[$name])) {
689 $this->resourceLink->setSetting($name, $_POST[$name]);
690 } else {
691 $this->resourceLink->setSetting($name);
692 }
693 }
694 // Save other custom parameters
695 foreach ($_POST as $name => $value) {
696 if ((strpos($name, 'custom_') === 0) &&
697 !in_array($name, array_merge(self::$LTI_CONSUMER_SETTING_NAMES, self::$LTI_CONTEXT_SETTING_NAMES, self::$LTI_RESOURCE_LINK_SETTING_NAMES))) {
698 $this->resourceLink->setSetting($name, $value);
699 }
700 }
701 }
702
703 // Set the user instance
704 $userId = '';
705 if (isset($_POST['user_id'])) {
706 $userId = trim($_POST['user_id']);
707 }
708
709 $this->user = User::fromResourceLink($this->resourceLink, $userId);
710
711 // Set the user name
712 $firstname = (isset($_POST['lis_person_name_given'])) ? $_POST['lis_person_name_given'] : '';
713 $lastname = (isset($_POST['lis_person_name_family'])) ? $_POST['lis_person_name_family'] : '';
714 $fullname = (isset($_POST['lis_person_name_full'])) ? $_POST['lis_person_name_full'] : '';
715 $this->user->setNames($firstname, $lastname, $fullname);
716
717 // Set the user email
718 $email = (isset($_POST['lis_person_contact_email_primary'])) ? $_POST['lis_person_contact_email_primary'] : '';
719 $this->user->setEmail($email, $this->defaultEmail);
720
721 // Set the user image URI
722 if (isset($_POST['user_image'])) {
723 $this->user->image = $_POST['user_image'];
724 }
725
726 // Set the user roles
727 if (isset($_POST['roles'])) {
728 $this->user->roles = self::parseRoles($_POST['roles']);
729 }
730
731 // Initialise the consumer and check for changes
732 $this->consumer->defaultEmail = $this->defaultEmail;
733 if ($this->consumer->ltiVersion !== $_POST['lti_version']) {
734 $this->consumer->ltiVersion = $_POST['lti_version'];
735 $doSaveConsumer = true;
736 }
737 if (isset($_POST['tool_consumer_instance_name'])) {
738 if ($this->consumer->consumerName !== $_POST['tool_consumer_instance_name']) {
739 $this->consumer->consumerName = $_POST['tool_consumer_instance_name'];
740 $doSaveConsumer = true;
741 }
742 }
743 if (isset($_POST['tool_consumer_info_product_family_code'])) {
744 $version = $_POST['tool_consumer_info_product_family_code'];
745 if (isset($_POST['tool_consumer_info_version'])) {
746 $version .= "-{$_POST['tool_consumer_info_version']}";
747 }
748 // do not delete any existing consumer version if none is passed
749 if ($this->consumer->consumerVersion !== $version) {
750 $this->consumer->consumerVersion = $version;
751 $doSaveConsumer = true;
752 }
753 } elseif (isset($_POST['ext_lms']) && ($this->consumer->consumerName !== $_POST['ext_lms'])) {
754 $this->consumer->consumerVersion = $_POST['ext_lms'];
755 $doSaveConsumer = true;
756 }
757 if (isset($_POST['tool_consumer_instance_guid'])) {
758 if (is_null($this->consumer->consumerGuid)) {
759 $this->consumer->consumerGuid = $_POST['tool_consumer_instance_guid'];
760 $doSaveConsumer = true;
761 } elseif (!$this->consumer->protected) {
762 $doSaveConsumer = ($this->consumer->consumerGuid !== $_POST['tool_consumer_instance_guid']);
763 if ($doSaveConsumer) {
764 $this->consumer->consumerGuid = $_POST['tool_consumer_instance_guid'];
765 }
766 }
767 }
768 if (isset($_POST['launch_presentation_css_url'])) {
769 if ($this->consumer->cssPath !== $_POST['launch_presentation_css_url']) {
770 $this->consumer->cssPath = $_POST['launch_presentation_css_url'];
771 $doSaveConsumer = true;
772 }
773 } elseif (isset($_POST['ext_launch_presentation_css_url']) &&
774 ($this->consumer->cssPath !== $_POST['ext_launch_presentation_css_url'])) {
775 $this->consumer->cssPath = $_POST['ext_launch_presentation_css_url'];
776 $doSaveConsumer = true;
777 } elseif (!empty($this->consumer->cssPath)) {
778 $this->consumer->cssPath = null;
779 $doSaveConsumer = true;
780 }
781 }
782
783 // Persist changes to consumer
784 if ($doSaveConsumer) {
785 $this->consumer->save();
786 }
787 if ($this->ok && isset($this->context)) {
788 $this->context->save();//ACHTUNG TODO UWE
789 $this->logger->dump(get_class($this->context));
790 }
791
792 if ($this->ok && isset($this->resourceLink)) {
793
794// Check if a share arrangement is in place for this resource link
795 // $this->ok = $this->checkForShare();//ACHTUNG TODO UWE
796 // Persist changes to resource link
797 $this->resourceLink->save();
798
799 // Save the user instance
800 if (isset($_POST['lis_result_sourcedid'])) {
801 if ($this->user->ltiResultSourcedId !== $_POST['lis_result_sourcedid']) {
802 $this->user->ltiResultSourcedId = $_POST['lis_result_sourcedid'];
803 $this->user->save();
804 }
805 } elseif (!empty($this->user->ltiResultSourcedId)) {
806 $this->user->ltiResultSourcedId = '';
807 $this->user->save();
808 }
809 }
810 // die ($this->reason.'---'.$this->ok);//ACHTUNG WEG!
811 return $this->ok;
812 }
user()
Definition: user.php:4
$_POST["username"]
LTI provider for LTI launch.
checkValue($value, $values, $reason)
Validate a parameter value from an array of permitted values.
$server
if($format !==null) $name
Definition: metadata.php:230
$format
Definition: metadata.php:218
$store
Definition: metadata.php:90
if( $orgName !==null) if($spconfig->hasValue('contacts')) $email
Definition: metadata.php:285
$http
Definition: raiseError.php:7
$service
Definition: result.php:17
foreach($_POST as $key=> $value) $res
$message
Definition: xapiexit.php:14

References $_POST, Vendor\Package\$e, $email, $format, $http, $message, $name, $ok, $res, $server, $service, $store, checkValue(), and user().

Referenced by handleRequest().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ checkForShare()

ilLTIToolProvider::checkForShare ( )
private

Check if a share arrangement is in place.

Returns
boolean True if no error is reported

Definition at line 819 of file class.ilLTIToolProvider.php.

820 {
821 $ok = true;
822 $doSaveResourceLink = true;
823
824 $id = $this->resourceLink->primaryResourceLinkId;
825
826 $shareRequest = isset($_POST['custom_share_key']) && !empty($_POST['custom_share_key']);
827 if ($shareRequest) {
828 if (!$this->allowSharing) {
829 $ok = false;
830 $this->reason = 'Your sharing request has been refused because sharing is not being permitted.';
831 } else {
832 // Check if this is a new share key
833 $shareKey = new ResourceLinkShareKey($this->resourceLink, $_POST['custom_share_key']);
834 if (!is_null($shareKey->primaryConsumerKey) && !is_null($shareKey->primaryResourceLinkId)) {
835 // Update resource link with sharing primary resource link details
836 $key = $shareKey->primaryConsumerKey;
837 $id = $shareKey->primaryResourceLinkId;
838 $ok = ($key !== $this->consumer->getKey()) || ($id != $this->resourceLink->getId());
839 if ($ok) {
840 $this->resourceLink->primaryConsumerKey = $key;
841 $this->resourceLink->primaryResourceLinkId = $id;
842 $this->resourceLink->shareApproved = $shareKey->autoApprove;
843 $ok = $this->resourceLink->save();
844 if ($ok) {
845 $doSaveResourceLink = false;
846 $this->user->getResourceLink()->primaryConsumerKey = $key;
847 $this->user->getResourceLink()->primaryResourceLinkId = $id;
848 $this->user->getResourceLink()->shareApproved = $shareKey->autoApprove;
849 $this->user->getResourceLink()->updated = time();
850 // Remove share key
851 $shareKey->delete();
852 } else {
853 $this->reason = 'An error occurred initialising your share arrangement.';
854 }
855 } else {
856 $this->reason = 'It is not possible to share your resource link with yourself.';
857 }
858 }
859 if ($ok) {
860 $ok = !is_null($key);
861 if (!$ok) {
862 $this->reason = 'You have requested to share a resource link but none is available.';
863 } else {
864 $ok = (!is_null($this->user->getResourceLink()->shareApproved) && $this->user->getResourceLink()->shareApproved);
865 if (!$ok) {
866 $this->reason = 'Your share request is waiting to be approved.';
867 }
868 }
869 }
870 }
871 } else {
872 // Check no share is in place
873 $ok = is_null($id);
874 if (!$ok) {
875 $this->reason = 'You have not requested to share a resource link but an arrangement is currently in place.';
876 }
877 }
878 // Look up primary resource link
879 if ($ok && !is_null($id)) {
880 // $consumer = new ToolConsumer($key, $this->dataConnector);
881 $consumer = new ilLTIToolConsumer($_POST['oauth_consumer_key'], $this->dataConnector);
882 $ok = !is_null($consumer->created);
883 if ($ok) {
884 $resourceLink = ResourceLink::fromConsumer($consumer, $id);
885 $ok = !is_null($resourceLink->created);
886 }
887 if ($ok) {
888 if ($doSaveResourceLink) {
889 $this->resourceLink->save();
890 }
891 $this->resourceLink = $resourceLink;
892 } else {
893 $this->reason = 'Unable to load resource link being shared.';
894 }
895 }
896
897 return $ok;
898 }

References $_POST, $ok, and user().

+ Here is the call graph for this function:

◆ checkValue()

ilLTIToolProvider::checkValue (   $value,
  $values,
  $reason 
)
private

Validate a parameter value from an array of permitted values.

Returns
boolean True if value is valid

Definition at line 904 of file class.ilLTIToolProvider.php.

905 {
906 $ok = in_array($value, $values);
907 if (!$ok && !empty($reason)) {
908 $this->reason = sprintf($reason, $value);
909 }
910
911 return $ok;
912 }

References $ok.

Referenced by authenticate().

+ Here is the caller graph for this function:

◆ doCallback()

ilLTIToolProvider::doCallback (   $method = null)
private

Call any callback function for the requested action.

This function may set the redirect_url and output properties.

Returns
boolean True if no error reported

Definition at line 216 of file class.ilLTIToolProvider.php.

217 {
218 $callback = $method;
219 if (is_null($callback)) {
220 $callback = self::$METHOD_NAMES[$_POST['lti_message_type']];
221 }
222 if (method_exists($this, $callback)) {
223 $result = $this->$callback(); // ACHTUNG HIER PROBLEM UK
224 } elseif (is_null($method) && $this->ok) {
225 $this->ok = false;
226 $this->reason = "Message type not supported: {$_POST['lti_message_type']}";
227 }
228 if ($this->ok && ($_POST['lti_message_type'] == 'ToolProxyRegistrationRequest')) {
229 $this->consumer->save();
230 }
231 }
$result

References $_POST, and $result.

Referenced by handleRequest().

+ Here is the caller graph for this function:

◆ handleRequest()

ilLTIToolProvider::handleRequest ( )

Process an incoming request.

Definition at line 134 of file class.ilLTIToolProvider.php.

135 {
136 if ($this->ok) {
137 if ($this->authenticate()) {
138 $this->doCallback();
139 }
140 }
141 // if return url is given, this redirects in case of errors
142 $this->result();
143 return $this->ok;
144 }
authenticate()
Check the authenticity of the LTI launch request.
doCallback($method=null)
Call any callback function for the requested action.
result()
Perform the result of an action.

References $ok, authenticate(), doCallback(), and result().

+ Here is the call graph for this function:

◆ onContentItem()

ilLTIToolProvider::onContentItem ( )
protected

Process a valid content-item request.

Returns
boolean True if no error

Definition at line 176 of file class.ilLTIToolProvider.php.

177 {
178 $this->onError();
179 }
onError()
Process a response to an invalid request.

References onError().

+ Here is the call graph for this function:

◆ onError()

ilLTIToolProvider::onError ( )
protected

Process a response to an invalid request.

Returns
boolean True if no further error processing required

Definition at line 196 of file class.ilLTIToolProvider.php.

197 {
198 // only return error status
199 return $this->ok;
200
201 //$this->doCallback('onError');
202 // return parent::onError(); //Stefan M.
203 }

References $ok.

Referenced by onContentItem(), onRegister(), and result().

+ Here is the caller graph for this function:

◆ onLaunch()

ilLTIToolProvider::onLaunch ( )
protected

Process a valid launch request.

Returns
boolean True if no error

Definition at line 155 of file class.ilLTIToolProvider.php.

156 {
157 // save/update current user
158 if ($this->user instanceof User) {
159 $this->user->save();
160 }
161
162 if ($this->context instanceof Context) {
163 $this->context->save();
164 }
165
166 if ($this->resourceLink instanceof ResourceLink) {
167 $this->resourceLink->save();
168 }
169 }

References user().

+ Here is the call graph for this function:

◆ onRegister()

ilLTIToolProvider::onRegister ( )
protected

Process a valid tool proxy registration request.

Returns
boolean True if no error

Definition at line 186 of file class.ilLTIToolProvider.php.

187 {
188 $this->onError();
189 }

References onError().

+ Here is the call graph for this function:

◆ result()

ilLTIToolProvider::result ( )
private

Perform the result of an action.

This function may redirect the user to another URL rather than returning a value.

Returns
string Output to be displayed (redirection, or display HTML or message)

Definition at line 240 of file class.ilLTIToolProvider.php.

241 {
242 $ok = false;
243 if (!$this->ok) {
244 $ok = $this->onError();
245 }
246 if (!$ok) {
247 if (!$this->ok) {
248 // If not valid, return an error message to the tool consumer if a return URL is provided
249 if (!empty($this->returnUrl)) {
250 $errorUrl = $this->returnUrl;
251 if (strpos($errorUrl, '?') === false) {
252 $errorUrl .= '?';
253 } else {
254 $errorUrl .= '&';
255 }
256 if ($this->debugMode && !is_null($this->reason)) {
257 $errorUrl .= 'lti_errormsg=' . urlencode("Debug error: $this->reason");
258 } else {
259 $errorUrl .= 'lti_errormsg=' . urlencode($this->message);
260 if (!is_null($this->reason)) {
261 $errorUrl .= '&lti_errorlog=' . urlencode("Debug error: $this->reason");
262 }
263 }
264 if (!is_null($this->consumer) && isset($_POST['lti_message_type']) && ($_POST['lti_message_type'] === 'ContentItemSelectionRequest')) {
265 $formParams = array();
266 if (isset($_POST['data'])) {
267 $formParams['data'] = $_POST['data'];
268 }
269 $version = (isset($_POST['lti_version'])) ? $_POST['lti_version'] : self::LTI_VERSION1;
270 $formParams = $this->consumer->signParameters($errorUrl, 'ContentItemSelection', $version, $formParams);
271 $page = self::sendForm($errorUrl, $formParams);
272 echo $page;
273 } else {
274 header("Location: {$errorUrl}");
275 }
276 exit; //ACHTUNG HIER PROBLEM UK
277 } else {
278 if (!is_null($this->errorOutput)) {
279 echo $this->errorOutput;
280 } elseif ($this->debugMode && !empty($this->reason)) {
281 echo "Debug error: {$this->reason}";
282 } else {
283 echo "Error: {$this->message}";
284 }
285 }
286 } elseif (!is_null($this->redirectUrl)) {
287 header("Location: {$this->redirectUrl}");
288 exit;
289 } elseif (!is_null($this->output)) {
290 echo $this->output;
291 }
292 }
293 }
exit
Definition: login.php:29

References $_POST, $ok, exit, and onError().

Referenced by handleRequest().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Field Documentation

◆ $CUSTOM_SUBSTITUTION_VARIABLES

array ilLTIToolProvider::$CUSTOM_SUBSTITUTION_VARIABLES
staticprivate

Names of LTI custom parameter substitution variables (or capabilities) and their associated default message parameter names.

Definition at line 83 of file class.ilLTIToolProvider.php.

◆ $debugMode

ilLTIToolProvider::$debugMode = false

Definition at line 34 of file class.ilLTIToolProvider.php.

◆ $logger

ilLTIToolProvider::$logger = null
protected

Definition at line 31 of file class.ilLTIToolProvider.php.

◆ $LTI_CONSUMER_SETTING_NAMES

array ilLTIToolProvider::$LTI_CONSUMER_SETTING_NAMES = array('custom_tc_profile_url', 'custom_system_setting_url')
staticprivate

Names of LTI parameters to be retained in the consumer settings property.

Definition at line 58 of file class.ilLTIToolProvider.php.

◆ $LTI_CONTEXT_SETTING_NAMES

array ilLTIToolProvider::$LTI_CONTEXT_SETTING_NAMES
staticprivate
Initial value:
= array('custom_context_setting_url',
'custom_lineitems_url', 'custom_results_url',
'custom_context_memberships_url')

Names of LTI parameters to be retained in the context settings property.

Definition at line 64 of file class.ilLTIToolProvider.php.

◆ $LTI_RESOURCE_LINK_SETTING_NAMES

array ilLTIToolProvider::$LTI_RESOURCE_LINK_SETTING_NAMES
staticprivate
Initial value:
= array('lis_result_sourcedid', 'lis_outcome_service_url',
'ext_ims_lis_basic_outcome_url', 'ext_ims_lis_resultvalue_sourcedids',
'ext_ims_lis_memberships_id', 'ext_ims_lis_memberships_url',
'ext_ims_lti_tool_setting', 'ext_ims_lti_tool_setting_id', 'ext_ims_lti_tool_setting_url',
'custom_link_setting_url',
'custom_lineitem_url', 'custom_result_url')

Names of LTI parameters to be retained in the resource link settings property.

Definition at line 72 of file class.ilLTIToolProvider.php.

◆ $LTI_VERSIONS

ilLTIToolProvider::$LTI_VERSIONS = array(self::LTI_VERSION1, self::LTI_VERSION2)
staticprivate

Permitted LTI versions for messages.

Definition at line 38 of file class.ilLTIToolProvider.php.

◆ $MESSAGE_TYPES

ilLTIToolProvider::$MESSAGE_TYPES
staticprivate
Initial value:
= array('basic-lti-launch-request' => 'onLaunch',
'ContentItemSelectionRequest' => 'onContentItem',
'ToolProxyRegistrationRequest' => 'register')

List of supported message types and associated class methods.

Definition at line 42 of file class.ilLTIToolProvider.php.

◆ $METHOD_NAMES

array ilLTIToolProvider::$METHOD_NAMES
staticprivate
Initial value:
= array('basic-lti-launch-request' => 'onLaunch',
'ContentItemSelectionRequest' => 'onContentItem',
'ToolProxyRegistrationRequest' => 'onRegister')

List of supported message types and associated class methods.

Definition at line 50 of file class.ilLTIToolProvider.php.


The documentation for this class was generated from the following file: