ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
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 = true
 

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.

References $DIC.

123  {
124  global $DIC;
125 
126  $this->logger = $DIC->logger()->lti();
127  parent::__construct($dataConnector);
128  }
global $DIC
Definition: saml.php:7

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.

References $_POST, $email, $format, $http, $message, $name, $ok, $request, $res, $server, $store, $title, $version, checkValue(), and user().

Referenced by handleRequest().

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  }
790 
791  // $this->logger->dump(get_class($this->context));
792 
793 
794  if ($this->ok && isset($this->resourceLink)) {
795 
796 // Check if a share arrangement is in place for this resource link
797  // $this->ok = $this->checkForShare();//ACHTUNG TODO UWE
798  // Persist changes to resource link
799  $this->resourceLink->save();
800 
801  // Save the user instance
802  if (isset($_POST['lis_result_sourcedid'])) {
803  if ($this->user->ltiResultSourcedId !== $_POST['lis_result_sourcedid']) {
804  $this->user->ltiResultSourcedId = $_POST['lis_result_sourcedid'];
805  $this->user->save();
806  }
807  } elseif (!empty($this->user->ltiResultSourcedId)) {
808  $this->user->ltiResultSourcedId = '';
809  $this->user->save();
810  }
811  }
812  // die ($this->reason.'---'.$this->ok);//ACHTUNG WEG!
813  return $this->ok;
814  }
if($orgName !==null) if($spconfig->hasValue('contacts')) $email
Definition: metadata.php:201
$format
Definition: metadata.php:141
Class to represent an OAuth Data Store.
foreach($paths as $path) $request
Definition: asyncclient.php:32
checkValue($value, $values, $reason)
Validate a parameter value from an array of permitted values.
LTI provider for LTI launch.
$server
Definition: sabredav.php:48
if(! $oauthconfig->getBoolean('getUserInfo.enable', FALSE)) $store
Definition: getUserInfo.php:11
user()
Definition: user.php:4
$version
Definition: build.php:27
catch(Exception $e) $message
foreach($_POST as $key=> $value) $res
$http
Definition: raiseError.php:7
$_POST["username"]
Class to represent an HTTP message.
Definition: HTTPMessage.php:14
+ 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 821 of file class.ilLTIToolProvider.php.

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

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

References $ok, and $values.

Referenced by authenticate().

907  {
908  $ok = in_array($value, $values);
909  if (!$ok && !empty($reason)) {
910  $this->reason = sprintf($reason, $value);
911  }
912 
913  return $ok;
914  }
$values
+ 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.

References $_POST, and $result.

Referenced by handleRequest().

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
$_POST["username"]
+ Here is the caller graph for this function:

◆ handleRequest()

ilLTIToolProvider::handleRequest ( )

Process an incoming request.

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

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

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.
result()
Perform the result of an action.
doCallback($method=null)
Call any callback function for the requested action.
+ 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.

References onError().

177  {
178  $this->onError();
179  }
onError()
Process a response to an invalid request.
+ 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.

References $ok.

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

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

References user().

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  }
user()
Definition: user.php:4
Class to represent a tool consumer context.
Definition: Context.php:17
Class to represent a tool consumer user.
Definition: User.php:15
+ 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.

References onError().

187  {
188  $this->onError();
189  }
onError()
Process a response to an invalid request.
+ 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.

References $_POST, $ok, Sabre\VObject\$output, $version, exit, and onError().

Referenced by handleRequest().

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)) {
291  }
292  }
293  }
$version
Definition: build.php:27
onError()
Process a response to an invalid request.
exit
Definition: backend.php:16
$_POST["username"]
+ 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 = true

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: