77         'basic-lti-launch-request',
    78         'ConfigureLaunchRequest',
    80         'ContentItemSelectionRequest',
    81         'ContentItemUpdateRequest',
    82         'ToolProxyRegistrationRequest',
    90     private static array 
$LTI_CONSUMER_SETTING_NAMES = array(
'custom_tc_profile_url', 
'custom_system_setting_url', 
'custom_oauth2_access_token_url');
    96                                                             'ext_ims_lis_memberships_id', 
'ext_ims_lis_memberships_url',
    97                                                             'custom_context_memberships_url', 
'custom_context_memberships_v2_url',
    98                                                             'custom_context_group_sets_url', 
'custom_context_groups_url',
    99                                                             'custom_lineitems_url', 
'custom_ags_scopes'   106                                                                   'ext_ims_lis_basic_outcome_url', 
'ext_ims_lis_resultvalue_sourcedids', 
'ext_outcome_data_values_accepted',
   107                                                                   'ext_ims_lis_memberships_id', 
'ext_ims_lis_memberships_url',
   108                                                                   'ext_ims_lti_tool_setting', 
'ext_ims_lti_tool_setting_id', 
'ext_ims_lti_tool_setting_url',
   109                                                                   'custom_link_setting_url', 
'custom_link_memberships_url',
   110                                                                   'custom_lineitems_url', 
'custom_lineitem_url', 
'custom_ags_scopes',
   123                                                                 'User.image' => 
'user_image',
   124                                                                 'User.username' => 
'username',
   125                                                                 'User.scope.mentor' => 
'role_scope_mentor',
   126                                                                 'Membership.role' => 
'roles',
   127                                                                 'Person.sourcedId' => 
'lis_person_sourcedid',
   128                                                                 'Person.name.full' => 
'lis_person_name_full',
   129                                                                 'Person.name.family' => 
'lis_person_name_family',
   130                                                                 'Person.name.given' => 
'lis_person_name_given',
   131                                                                 'Person.email.primary' => 
'lis_person_contact_email_primary',
   132                                                                 'Context.id' => 
'context_id',
   133                                                                 'Context.type' => 
'context_type',
   134                                                                 'Context.title' => 
'context_title',
   135                                                                 'Context.label' => 
'context_label',
   136                                                                 'CourseOffering.sourcedId' => 
'lis_course_offering_sourcedid',
   137                                                                 'CourseSection.sourcedId' => 
'lis_course_section_sourcedid',
   138                                                                 'CourseSection.label' => 
'context_label',
   139                                                                 'CourseSection.title' => 
'context_title',
   140                                                                 'ResourceLink.id' => 
'resource_link_id',
   141                                                                 'ResourceLink.title' => 
'resource_link_title',
   142                                                                 'ResourceLink.description' => 
'resource_link_description',
   143                                                                 'Result.sourcedId' => 
'lis_result_sourcedid',
   144                                                                 'BasicOutcome.url' => 
'lis_outcome_service_url',
   145                                                                 'ToolConsumerProfile.url' => 
'custom_tc_profile_url',
   146                                                                 'ToolProxy.url' => 
'tool_proxy_url',
   147                                                                 'ToolProxy.custom.url' => 
'custom_system_setting_url',
   148                                                                 'ToolProxyBinding.custom.url' => 
'custom_context_setting_url',
   149                                                                 'LtiLink.custom.url' => 
'custom_link_setting_url',
   150                                                                 'LineItems.url' => 
'custom_lineitems_url',
   151                                                                 'LineItem.url' => 
'custom_lineitem_url',
   152                                                                 'ToolProxyBinding.memberships.url' => 
'custom_context_memberships_url',
   153                                                                 'ToolProxyBinding.nrps.url' => 
'custom_context_memberships_v2_url',
   154                                                                 'LtiLink.memberships.url' => 
'custom_link_memberships_url',
   155                                                                 'LtiLink.acs.url' => 
'custom_ap_acs_url'   386         $this->secret = null;
   387         $this->messageUrl = null;
   388         $this->initiateLoginUrl = null;
   389         $this->redirectionUris = null;
   390         $this->rsaKey = null;
   391         $this->signatureMethod = 
'HMAC-SHA1';
   392         $this->encryptionMethod = null;
   393         $this->ltiVersion = null;
   395         $this->enabled = 
false;
   396         $this->enableFrom = null;
   397         $this->enableUntil = null;
   398         $this->lastAccess = null;
   399         $this->created = null;
   400         $this->updated = null;
   401         $this->constraints = array();
   403         $this->vendor = new \ILIAS\LTI\ToolProvider\Content\Item(null);
   405         $this->product = new \ILIAS\LTI\ToolProvider\Content\Item(null);
   406         $this->requiredServices = array();
   407         $this->optionalServices = array();
   408         $this->resourceHandlers = array();
   418         return $this->dataConnector->saveTool($this);
   426     public function delete(): 
bool   428         return $this->dataConnector->deleteTool($this);
   438         if (is_null($this->messageParameters)) {
   442                 $this->debugMode = (isset($this->messageParameters[
'custom_debug']) &&
   443                     (strtolower($this->messageParameters[
'custom_debug']) === 
'true'));
   444                 if ($this->debugMode) {
   449             if (!empty($this->messageParameters[
'lti_message_type']) &&
   450                 (($this->messageParameters[
'lti_message_type'] === 
'ContentItemSelectionRequest') || ($this->messageParameters[
'lti_message_type'] === 
'ContentItemUpdateRequest')) &&
   451                 !empty($this->messageParameters[
'content_item_return_url'])) {
   452                 $this->returnUrl = $this->messageParameters[
'content_item_return_url'];
   454             if (empty($this->returnUrl) && !empty($this->messageParameters[
'launch_presentation_return_url'])) {
   455                 $this->returnUrl = $this->messageParameters[
'launch_presentation_return_url'];
   469         if ($this->debugMode) {
   472         if (
$_SERVER[
'REQUEST_METHOD'] === 
'HEAD') {  
   474         } elseif (isset($parameters[
'iss']) && (strlen($parameters[
'iss']) > 0)) {  
   476             if (!isset($parameters[
'login_hint']) || (strlen($parameters[
'login_hint']) <= 0)) {
   478                 $this->reason = 
'Missing login_hint parameter';
   479             } elseif (!isset($parameters[
'target_link_uri']) || (strlen($parameters[
'target_link_uri']) <= 0)) {
   481                 $this->reason = 
'Missing target_link_uri parameter';
   485         } elseif (isset($parameters[
'openid_configuration']) && (strlen($parameters[
'openid_configuration']) > 0)) {  
   492                 if (empty($this->output)) {
   494                     if ($this->ok && ($this->messageParameters[
'lti_message_type'] === 
'ToolProxyRegistrationRequest')) {
   495                         $this->platform->save();
   501             $errorMessage = 
"Request failed with reason: '{$this->reason}'";
   502             if (!empty($this->details)) {
   503                 $errorMessage .= PHP_EOL . 
'Debug information:';
   504                 foreach ($this->details as $detail) {
   505                     $errorMessage .= PHP_EOL . 
"  {$detail}";
   521     public function setParameterConstraint(
string $name, 
bool $required = 
true, 
int $maxLength = null, array $messageTypes = null)
   525             $this->constraints[$name] = array(
'required' => $required, 
'max_length' => $maxLength, 
'messages' => $messageTypes);
   553         return $this->dataConnector->getPlatforms();
   565         $services = $this->platform->profile->service_offered;
   566         if (is_array($services)) {
   570                 if (!is_array($service->format) || !in_array($format, $service->format)) {
   574                 foreach ($methods as $method) {
   575                     if (!is_array($service->action) || !in_array($method, $service->action)) {
   576                         $missing[] = $method;
   580                 if (count($methods) <= 0) {
   632     ###    PROTECTED METHODS   640         $this->reason = 
'No onLaunch method found for tool';
   649         $this->reason = 
'No onConfigure method found for tool';
   658         $this->reason = 
'No onDashboard method found for tool';
   667         $this->reason = 
'No onContentItem method found for tool';
   676         $this->reason = 
'No onContentItemUpdate method found for tool';
   685         $this->reason = 
'No onRegister method found for tool';
   697             $registrationConfig = $this->
sendRegistration($platformConfig, $toolConfig);
   711         $this->reason = 
'No onLtiStartProctoring method found for tool';
   720         $this->reason = 
'No onLtiEndAssessment method found for tool';
   751             $this->ok = !empty($parameters[
'openid_configuration']);
   753                 $http = 
new HttpMessage($parameters[
'openid_configuration']);
   754                 $this->ok = 
$http->send();
   756                     $platformConfig = json_decode(
$http->response, 
true);
   757                     $this->ok = !empty($platformConfig);
   760                     $this->reason = 
'Unable to access platform configuration details.';
   763                 $this->reason = 
'Invalid registration request: missing openid_configuration parameter.';
   766                 $this->ok = !empty($platformConfig[
'registration_endpoint']) && !empty($platformConfig[
'jwks_uri']) && !empty($platformConfig[
'authorization_endpoint']) &&
   767                     !empty($platformConfig[
'token_endpoint']) && !empty($platformConfig[
'https://purl.imsglobal.org/spec/lti-platform-configuration']) &&
   768                     !empty($platformConfig[
'claims_supported']) && !empty($platformConfig[
'scopes_supported']) &&
   769                     !empty($platformConfig[
'id_token_signing_alg_values_supported']) &&
   770                     !empty($platformConfig[
'https://purl.imsglobal.org/spec/lti-platform-configuration'][
'product_family_code']) &&
   771                     !empty($platformConfig[
'https://purl.imsglobal.org/spec/lti-platform-configuration'][
'version']) &&
   772                     !empty($platformConfig[
'https://purl.imsglobal.org/spec/lti-platform-configuration'][
'messages_supported']);
   774                     $this->reason = 
'Invalid platform configuration details.';
   780                 $algorithms = \array_intersect(
   781                     $jwtClient::getSupportedAlgorithms(),
   782                     $platformConfig[
'id_token_signing_alg_values_supported']
   784                 $this->ok = !empty($algorithms);
   786                     rsort($platformConfig[
'id_token_signing_alg_values_supported']);
   788                     $this->reason = 
'None of the signature algorithms offered by the platform is supported.';
   793             $platformConfig = null;
   796         return $platformConfig;
   806         $claimsMapping = array(
   808             'Person.name.full' => 
'name',
   809             'Person.name.given' => 
'given_name',
   810             'Person.name.family' => 
'family_name',
   811             'Person.email.primary' => 
'email'   813         $toolName = (!empty($this->product->name)) ? $this->product->name : 
'Unnamed tool';
   814         $toolDescription = (!empty($this->product->description)) ? $this->product->description : 
'';
   816         $oauthRequest = LTIOAuth\OAuthRequest::from_request();
   817         $toolUrl = $oauthRequest->get_normalized_http_url();
   818         $pos = strpos($toolUrl, 
'//');
   819         $domain = substr($toolUrl, $pos + 2);
   820         $domain = substr($domain, 0, strpos($domain, 
'/'));
   821         $claimsSupported = $platformConfig[
'claims_supported'];
   822         $messagesSupported = $platformConfig[
'https://purl.imsglobal.org/spec/lti-platform-configuration'][
'messages_supported'];
   823         $scopesSupported = $platformConfig[
'scopes_supported'];
   827         $variables = array();
   828         $constants = array();
   829         $redirectUris = array();
   830         foreach ($this->resourceHandlers as $resourceHandler) {
   831             if (empty($iconUrl)) {
   832                 $iconUrl = $resourceHandler->icon;
   834             foreach (array_merge($resourceHandler->optionalMessages, $resourceHandler->requiredMessages) as $message) {
   835                 $type = $message->type;
   839                 $capabilities = array();
   840                 if ($type === 
'LtiResourceLinkRequest') {
   841                     $toolUrl = 
"{$this->baseUrl}{$message->path}";
   842                     $redirectUris[] = $toolUrl;
   843                     $capabilities = $message->capabilities;
   844                     $variables = array_merge($variables, $message->variables);
   845                     $constants = array_merge($constants, $message->constants);
   846                 } elseif (in_array($type, $messagesSupported)) {
   847                     $redirectUris[] = 
"{$this->baseUrl}{$message->path}";
   848                     $capabilities = $message->capabilities;
   849                     $variables = array_merge($message->variables, $variables);
   850                     $constants = array_merge($message->constants, $constants);
   853                         'target_link_uri' => 
"{$this->baseUrl}{$message->path}",
   857                 foreach ($capabilities as $capability) {
   858                     if (array_key_exists($capability, $claimsMapping) && in_array($claimsMapping[$capability], $claimsSupported)) {
   859                         $claims[] = $claimsMapping[$capability];
   864         if (empty($redirectUris)) {
   865             $redirectUris = array($toolUrl);
   867             $redirectUris = array_unique($redirectUris);
   873         foreach ($constants as $name => $value) {
   874             $custom[$name] = $value;
   876         foreach ($variables as $name => $value) {
   877             $custom[$name] = 
'$' . $value;
   879         $toolConfig = array();
   880         $toolConfig[
'application_type'] = 
'web';
   881         $toolConfig[
'client_name'] = $toolName;
   882         $toolConfig[
'response_types'] = array(
'id_token');
   883         $toolConfig[
'grant_types'] = array(
'implicit', 
'client_credentials');
   884         $toolConfig[
'initiate_login_uri'] = $toolUrl;
   885         $toolConfig[
'redirect_uris'] = $redirectUris;
   887         $toolConfig[
'token_endpoint_auth_method'] = 
'private_key_jwt';
   888         $toolConfig[
'https://purl.imsglobal.org/spec/lti-tool-configuration'] = array(
   890             'target_link_uri' => $toolUrl,
   891             'custom_parameters' => $custom,
   894             'description' => $toolDescription
   896         $toolConfig[
'scope'] = implode(
' ', array_intersect($this->requiredScopes, $scopesSupported));
   897         if (!empty($iconUrl)) {
   898             $toolConfig[
'logo_uri'] = 
"{$this->baseUrl}{$iconUrl}";
   914             $this->ok = !empty($parameters[
'registration_token']);
   916                 $body = json_encode($toolConfig);
   917                 $headers = 
"Content-type: application/json\n" .
   918                     "Authorization: Bearer {$parameters['registration_token']}";
   919                 $http = 
new HttpMessage($platformConfig[
'registration_endpoint'], 
'POST', $body, $headers);
   920                 $this->ok = 
$http->send();
   922                     $registrationConfig = json_decode(
$http->response, 
true);
   923                     $this->ok = !empty($registrationConfig);
   926                     $this->reason = 
'Unable to register with platform.';
   929                 $this->reason = 
'Invalid registration request: missing registration_token parameter.';
   933             $registrationConfig = null;
   936         return $registrationConfig;
   948         $domain = $platformConfig[
'issuer'];
   949         $pos = strpos($domain, 
'//');
   950         if ($pos !== 
false) {
   951             $domain = substr($domain, $pos + 2);
   952             $pos = strpos($domain, 
'/');
   953             if ($pos !== 
false) {
   954                 $domain = substr($domain, 0, $pos);
   957         $this->platform = 
new Platform($this->dataConnector);
   958         $this->platform->name = $domain;
   960         $this->platform->signatureMethod = reset($platformConfig[
'id_token_signing_alg_values_supported']);
   961         $this->platform->platformId = $platformConfig[
'issuer'];
   962         $this->platform->clientId = $registrationConfig[
'client_id'];
   963         $this->platform->deploymentId = $registrationConfig[
'https://purl.imsglobal.org/spec/lti-tool-configuration'][
'deployment_id'];
   964         $this->platform->authenticationUrl = $platformConfig[
'authorization_endpoint'];
   965         $this->platform->accessTokenUrl = $platformConfig[
'token_endpoint'];
   966         $this->platform->jku = $platformConfig[
'jwks_uri'];
   968             $this->ok = $this->platform->save();
   970                 $this->reason = 
'Sorry, an error occurred when saving the platform details.';
   984         if (!empty($this->platform)) {
   986             if (!$this->platform->enabled) {
   987                 $enabled = 
', but it will need to be enabled by the tool provider before it can be used';
   988             } elseif (!empty($this->platform->enableFrom) && ($this->platform->enableFrom > $now)) {
   989                 $enabled = 
', but you will only have access from ' . date(
'j F Y H:i T', $this->platform->enableFrom);
   990                 if (!empty($this->platform->enableUntil)) {
   991                     $enabled .= 
' until ' . date(
'j F Y H:i T', $this->platform->enableUntil);
   993             } elseif (!empty($this->platform->enableUntil)) {
   994                 if ($this->platform->enableUntil > $now) {
   995                     $enabled = 
', but you will only have access until ' . date(
'j F Y H:i T', $this->platform->enableUntil);
   997                     $enabled = 
', but your access was set to end at ' . date(
'j F Y H:i T', $this->platform->enableUntil);
  1005     <meta 
http-equiv=
"content-type" content=
"text/html; charset=UTF-8">
  1006     <title>
LTI Tool registration</title>
  1014         background-color: #d4edda;
  1015         border-color: #c3e6cb;
  1017         padding: .75rem 1.25rem;
  1018         margin-bottom: 1rem;
  1022         background-color: #f8d7da;
  1023         border-color: #f5c6cb;
  1025         padding: .75rem 1.25rem;
  1026         margin-bottom: 1rem;
  1032         border: 1px solid transparent;
  1033         padding: 0.375rem 0.75rem;
  1036         border-radius: 0.25rem;
  1038         background-color: #007bff;
  1039         border-color: #007bff;
  1041         text-decoration: none;
  1042         display: 
inline-block;
  1046     <script 
language=
"javascript" type=
"text/javascript">
  1047       function doClose(el) {
  1048         (window.opener || window.parent).postMessage({subject:
'org.imsglobal.lti.close'}, 
'*');
  1054     <h1>{$toolConfig[
'client_name']} registration</h1>
  1060       The tool registration was successful{
$enabled}.
  1063       <
button type=
"button" onclick=
"return doClose();">Close</
button>
  1070       Sorry, the registration was not successful: {$this->reason}
  1079         $this->output = $html;
  1095             if ($ok && $autoEnable) {
  1096                 $tool->enabled = 
true;
  1116                 $tool->enabled = 
true;
  1132         $tool->setRecordId($id);
  1152             $this->message = self::CONNECTION_ERROR_MESSAGE . 
' ' . 
$this->reason;
  1157             if (!empty($this->returnUrl)) {
  1159                 if (!is_null($this->platform) && isset($this->messageParameters[
'lti_message_type']) &&
  1160                     (($this->messageParameters[
'lti_message_type'] === 
'ContentItemSelectionRequest') ||
  1161                         ($this->messageParameters[
'lti_message_type'] === 
'ContentItemUpdateRequest'))) {
  1162                     $formParams = array();
  1163                     if ($this->debugMode && !is_null($this->reason)) {
  1164                         $formParams[
'lti_errormsg'] = 
"Debug error: {$this->reason}";
  1167                         if (!is_null($this->reason)) {
  1168                             $formParams[
'lti_errorlog'] = 
"Debug error: {$this->reason}";
  1171                     if (isset($this->messageParameters[
'data'])) {
  1172                         $formParams[
'data'] = $this->messageParameters[
'data'];
  1174                     $this->version = (isset($this->messageParameters[
'lti_version'])) ? $this->messageParameters[
'lti_version'] : 
Util::LTI_VERSION1;
  1175                     $page = $this->
sendMessage($errorUrl, 
'ContentItemSelection', $formParams);
  1178                     if (strpos($errorUrl, 
'?') === 
false) {
  1183                     if ($this->debugMode && !is_null($this->reason)) {
  1184                         $errorUrl .= 
'lti_errormsg=' . urlencode(
"Debug error: $this->reason");
  1186                         $errorUrl .= 
'lti_errormsg=' . urlencode($this->message);
  1187                         if (!is_null($this->reason)) {
  1188                             $errorUrl .= 
'<i_errorlog=' . urlencode(
"Debug error: $this->reason");
  1191                     header(
"Location: {$errorUrl}");
  1195                 if (!is_null($this->errorOutput)) {
  1197                 } elseif ($this->debugMode && !empty($this->reason)) {
  1198                     echo 
"Debug error: {$this->reason}";
  1200                     echo 
"Error: {$this->message}";
  1204         } elseif (!is_null($this->redirectUrl)) {
  1205             header(
"Location: {$this->redirectUrl}");
  1207         } elseif (!is_null($this->output)) {
  1221         $doSavePlatform = 
false;
  1223         if ($this->ok && $strictMode && !empty($this->jwt) && !empty($this->jwt->hasJwt())) {
  1224             if (!empty($this->jwt->getClaim(
'https://purl.imsglobal.org/spec/lti/claim/context', 
'')) &&
  1225                 empty($this->messageParameters[
'context_id'])) {
  1227                 $this->reason = 
'Missing id property in https://purl.imsglobal.org/spec/lti/claim/context claim';
  1228             } elseif (!empty($this->jwt->getClaim(
'https://purl.imsglobal.org/spec/lti/claim/tool_platform', 
'')) &&
  1229                 empty($this->messageParameters[
'tool_consumer_instance_guid'])) {
  1231                 $this->reason = 
'Missing guid property in https://purl.imsglobal.org/spec/lti/claim/tool_platform claim';
  1235             if ($this->messageParameters[
'lti_message_type'] === 
'basic-lti-launch-request') {
  1236                 $this->ok = isset($this->messageParameters[
'resource_link_id']) && (strlen(trim($this->messageParameters[
'resource_link_id'])) > 0);
  1238                     $this->reason = 
'Missing resource link ID.';
  1241                     $this->ok = isset($this->messageParameters[
'roles']);
  1243                         $this->reason = 
'Missing roles parameter.';
  1246             } elseif (($this->messageParameters[
'lti_message_type'] === 
'ContentItemSelectionRequest') ||
  1247                 ($this->messageParameters[
'lti_message_type'] === 
'ContentItemUpdateRequest')) {
  1248                 $isUpdate = ($this->messageParameters[
'lti_message_type'] === 
'ContentItemUpdateRequest');
  1249                 $mediaTypes = array();
  1250                 $contentTypes = array();
  1251                 $fileTypes = array();
  1252                 if (isset($this->messageParameters[
'accept_media_types']) && (strlen(trim($this->messageParameters[
'accept_media_types'])) > 0)) {
  1253                     $mediaTypes = array_filter(
  1254                         explode(
',', str_replace(
' ', 
'', $this->messageParameters[
'accept_media_types'])),
  1258                 $this->ok = (count($mediaTypes) > 0) || ($this->messageParameters[
'lti_version'] === 
Util::LTI_VERSION1P3);
  1260                     $this->reason = 
'No content types specified.';
  1261                 } elseif ($isUpdate) {
  1264                             $this->messageParameters[
'accept_media_types'],
  1266                             'Invalid value in accept_media_types parameter: \'%s\'.',
  1273                         $this->messageParameters[
'accept_types'],
  1275                         'Invalid value in accept_types parameter: \'%s\'.',
  1283                     $mediaTypes = array_unique($mediaTypes);
  1284                     foreach ($mediaTypes as $mediaType) {
  1285                         if (strpos($mediaType, 
'application/vnd.ims.lti.') !== 0) {
  1286                             $fileTypes[] = $mediaType;
  1288                         if (($mediaType === 
'text/html') || ($mediaType === 
'*/*')) {
  1291                         } elseif ((strpos($mediaType, 
'image/') === 0) || ($mediaType === 
'*/*')) {
  1299                     if (!empty($fileTypes)) {
  1302                     $contentTypes = array_unique($contentTypes);
  1305                     if (isset($this->messageParameters[
'accept_presentation_document_targets']) &&
  1306                         (strlen(trim($this->messageParameters[
'accept_presentation_document_targets'])) > 0)) {
  1307                         $documentTargets = array_filter(explode(
  1309                             str_replace(
' ', 
'', $this->messageParameters[
'accept_presentation_document_targets'])
  1311                         $documentTargets = array_unique($documentTargets);
  1312                         $this->ok = count($documentTargets) > 0;
  1314                             $this->reason = 
'Missing or empty accept_presentation_document_targets parameter.';
  1316                             if (empty($this->jwt) || !$this->jwt->hasJwt()) {
  1317                                 $permittedTargets = array(
'embed', 
'frame', 
'iframe', 
'window', 
'popup', 
'overlay', 
'none');
  1319                                 $permittedTargets = array(
'embed', 
'iframe', 
'window');
  1321                             foreach ($documentTargets as $documentTarget) {
  1325                                     'Invalid value in accept_presentation_document_targets parameter: \'%s\'.',
  1339                         $this->reason = 
'No accept_presentation_document_targets parameter found.';
  1343                     $this->ok = !empty($this->messageParameters[
'content_item_return_url']);
  1345                         $this->reason = 
'Missing content_item_return_url parameter.';
  1352             } elseif ($this->messageParameters[
'lti_message_type'] === 
'ToolProxyRegistrationRequest') {
  1353                 $this->ok = ((isset($this->messageParameters[
'reg_key']) && (strlen(trim($this->messageParameters[
'reg_key'])) > 0)) && (isset($this->messageParameters[
'reg_password']) && (strlen(trim($this->messageParameters[
'reg_password'])) >
  1354                             0)) && (isset($this->messageParameters[
'tc_profile_url']) && (strlen(trim($this->messageParameters[
'tc_profile_url'])) >
  1355                             0)) && (isset($this->messageParameters[
'launch_presentation_return_url']) && (strlen(trim($this->messageParameters[
'launch_presentation_return_url'])) > 0)));
  1356                 if ($this->debugMode && !$this->ok) {
  1357                     $this->reason = 
'Missing message parameters.';
  1359             } elseif ($this->messageParameters[
'lti_message_type'] === 
'LtiStartProctoring') {
  1360                 $this->ok = isset($this->messageParameters[
'resource_link_id']) && (strlen(trim($this->messageParameters[
'resource_link_id'])) > 0);
  1362                     $this->reason = 
'Missing resource link ID.';
  1364                     $this->ok = isset($this->messageParameters[
'custom_ap_attempt_number']) && (strlen(trim($this->messageParameters[
'custom_ap_attempt_number'])) > 0) &&
  1365                         is_numeric($this->messageParameters[
'custom_ap_attempt_number']);
  1367                         $this->reason = 
'Missing or invalid value for attempt number.';
  1371                     $this->ok = isset($this->messageParameters[
'user_id']) && (strlen(trim($this->messageParameters[
'user_id'])) > 0);
  1373                         $this->reason = 
'Missing user ID.';
  1380         if ($this->ok && ($this->messageParameters[
'lti_message_type'] !== 
'ToolProxyRegistrationRequest')) {
  1381             $this->ok = isset($this->messageParameters[
'oauth_consumer_key']);
  1383                 $this->reason = 
'Missing consumer key.';
  1386                 $this->ok = !is_null($this->platform->created);
  1388                     if (empty($this->jwt) || !$this->jwt->hasJwt()) {
  1389                         $this->reason = 
"Consumer key not recognised: {$this->messageParameters['oauth_consumer_key']}";
  1391                         $this->reason = 
"Platform not recognised (Platform ID | Client ID | Deployment ID): {$this->messageParameters['platform_id']} | {$this->messageParameters['oauth_consumer_key']} | {$this->messageParameters['deployment_id']}";
  1396                 if ($this->messageParameters[
'oauth_signature_method'] !== $this->platform->signatureMethod) {
  1397                     $this->platform->signatureMethod = $this->messageParameters[
'oauth_signature_method'];
  1398                     $doSavePlatform = 
true;
  1400                 $today = date(
'Y-m-d', $now);
  1401                 if (is_null($this->platform->lastAccess)) {
  1402                     $doSavePlatform = 
true;
  1404                     $last = date(
'Y-m-d', $this->platform->lastAccess);
  1405                     $doSavePlatform = $doSavePlatform || ($last !== $today);
  1407                 $this->platform->lastAccess = $now;
  1411                 if ($this->platform->protected) {
  1412                     if (!is_null($this->platform->consumerGuid)) {
  1413                         $this->ok = empty($this->messageParameters[
'tool_consumer_instance_guid']) || ($this->platform->consumerGuid === $this->messageParameters[
'tool_consumer_instance_guid']);
  1415                             $this->reason = 
'Request is from an invalid platform.';
  1418                         $this->ok = isset($this->messageParameters[
'tool_consumer_instance_guid']);
  1420                             $this->reason = 
'A platform GUID must be included in the launch request.';
  1425                     $this->ok = $this->platform->enabled;
  1427                         $this->reason = 
'Platform has not been enabled by the tool.';
  1431                     $this->ok = is_null($this->platform->enableFrom) || ($this->platform->enableFrom <= $now);
  1433                         $this->ok = is_null($this->platform->enableUntil) || ($this->platform->enableUntil > $now);
  1435                             $this->reason = 
'Platform access has expired.';
  1438                         $this->reason = 
'Platform access is not yet available.';
  1444                 if (($this->messageParameters[
'lti_message_type'] === 
'ContentItemSelectionRequest') ||
  1445                     ($this->messageParameters[
'lti_message_type'] === 
'ContentItemUpdateRequest')) {
  1446                     $isUpdate = ($this->messageParameters[
'lti_message_type'] === 
'ContentItemUpdateRequest');
  1447                     if (isset($this->messageParameters[
'accept_unsigned'])) {
  1449                             $this->messageParameters[
'accept_unsigned'],
  1450                             array(
'true', 
'false'),
  1451                             'Invalid value for accept_unsigned parameter: \'%s\'.',
  1455                     if ($this->ok && isset($this->messageParameters[
'accept_multiple'])) {
  1458                                 $this->messageParameters[
'accept_multiple'],
  1459                                 array(
'true', 
'false'),
  1460                                 'Invalid value for accept_multiple parameter: \'%s\'.',
  1465                                 $this->messageParameters[
'accept_multiple'],
  1467                                 'Invalid value for accept_multiple parameter: \'%s\'.',
  1472                     if ($this->ok && isset($this->messageParameters[
'accept_copy_advice'])) {
  1475                                 $this->messageParameters[
'accept_copy_advice'],
  1476                                 array(
'true', 
'false'),
  1477                                 'Invalid value for accept_copy_advice parameter: \'%s\'.',
  1482                                 $this->messageParameters[
'accept_copy_advice'],
  1484                                 'Invalid value for accept_copy_advice parameter: \'%s\'.',
  1489                     if ($this->ok && isset($this->messageParameters[
'auto_create'])) {
  1491                             $this->messageParameters[
'auto_create'],
  1492                             array(
'true', 
'false'),
  1493                             'Invalid value for auto_create parameter: \'%s\'.',
  1497                     if ($this->ok && isset($this->messageParameters[
'can_confirm'])) {
  1499                             $this->messageParameters[
'can_confirm'],
  1500                             array(
'true', 
'false'),
  1501                             'Invalid value for can_confirm parameter: \'%s\'.',
  1506                 if ($this->ok && isset($this->messageParameters[
'launch_presentation_document_target'])) {
  1508                         $this->messageParameters[
'launch_presentation_document_target'],
  1509                         array(
'embed', 
'frame', 
'iframe', 
'window', 
'popup', 
'overlay'),
  1510                         'Invalid value for launch_presentation_document_target parameter: \'%s\'.',
  1514                     if ($this->ok && ($this->messageParameters[
'lti_message_type'] === 
'LtiStartProctoring') &&
  1515                         ($this->messageParameters[
'launch_presentation_document_target'] !== 
'window')) {
  1516                         $this->ok = !isset($this->messageParameters[
'launch_presentation_height']) &&
  1517                             !isset($this->messageParameters[
'launch_presentation_width']);
  1519                             $this->reason = 
'Height and width parameters must only be included for the window document target.';
  1526         if ($this->ok && ($this->messageParameters[
'lti_message_type'] === 
'ToolProxyRegistrationRequest')) {
  1529                 $this->reason = 
'Invalid lti_version parameter.';
  1532                 $url = $this->messageParameters[
'tc_profile_url'];
  1533                 if (strpos(
$url, 
'?') === 
false) {
  1539                 $http = 
new HttpMessage(
$url, 
'GET', null, 
'Accept: application/vnd.ims.lti.v2.toolconsumerprofile+json');
  1540                 $this->ok = 
$http->send();
  1542                     $this->reason = 
'Platform profile not accessible.';
  1544                     $tcProfile = json_decode(
$http->response);
  1545                     $this->ok = !is_null($tcProfile);
  1547                         $this->reason = 
'Invalid JSON in platform profile.';
  1554                 $this->platform->profile = $tcProfile;
  1555                 $capabilities = $this->platform->profile->capability_offered;
  1557                 foreach ($this->resourceHandlers as $resourceHandler) {
  1558                     foreach ($resourceHandler->requiredMessages as $message) {
  1559                         if (!in_array($message->type, $capabilities)) {
  1560                             $missing[$message->type] = 
true;
  1564                 foreach ($this->constraints as $name => $constraint) {
  1565                     if ($constraint[
'required']) {
  1566                         if (empty(array_intersect(
  1568                             array_keys(array_intersect(self::$CUSTOM_SUBSTITUTION_VARIABLES, array($name)))
  1570                             $missing[$name] = 
true;
  1574                 if (!empty($missing)) {
  1576                     $this->reason = 
'Required capability not offered - \'' . implode(
'\', \
'', array_keys($missing)) . 
'\'';
  1582                 foreach ($this->requiredServices as 
$service) {
  1583                     foreach ($service->formats as $format) {
  1584                         if (!$this->
findService($format, $service->actions)) {
  1586                                 $this->reason = 
'Required service(s) not offered - ';
  1589                                 $this->reason .= 
', ';
  1591                             $this->reason .= 
"'{$format}' [" . implode(
', ', $service->actions) . 
']';
  1597                 if ($this->messageParameters[
'lti_message_type'] === 
'ToolProxyRegistrationRequest') {
  1598                     $this->platform->profile = $tcProfile;
  1599                     $this->platform->secret = $this->messageParameters[
'reg_password'];
  1600                     $this->platform->ltiVersion = $this->messageParameters[
'lti_version'];
  1601                     $this->platform->name = $tcProfile->product_instance->service_owner->service_owner_name->default_value;
  1602                     $this->platform->consumerName = $this->platform->name;
  1603                     $this->platform->consumerVersion = 
"{$tcProfile->product_instance->product_info->product_family->code}-{$tcProfile->product_instance->product_info->product_version}";
  1604                     $this->platform->consumerGuid = $tcProfile->product_instance->guid;
  1605                     $this->platform->enabled = 
true;
  1606                     $this->platform->protected = 
true;
  1607                     $doSavePlatform = 
true;
  1610         } elseif ($this->ok && !empty($this->messageParameters[
'custom_tc_profile_url']) && empty($this->platform->profile)) {
  1611             $url = $this->messageParameters[
'custom_tc_profile_url'];
  1612             if (strpos(
$url, 
'?') === 
false) {
  1617             $url .= 
'lti_version=' . $this->messageParameters[
'lti_version'];
  1618             $http = 
new HttpMessage(
$url, 
'GET', null, 
'Accept: application/vnd.ims.lti.v2.toolconsumerprofile+json');
  1619             if (
$http->send()) {
  1620                 $tcProfile = json_decode(
$http->response);
  1621                 if (!is_null($tcProfile)) {
  1622                     $this->platform->profile = $tcProfile;
  1623                     $doSavePlatform = 
true;
  1630             if (isset($this->messageParameters[
'relaunch_url'])) {
  1631                 if (empty($this->messageParameters[
'platform_state'])) {
  1633                     $this->reason = 
'Missing or empty platform_state parameter.';
  1639                 $invalidParameters = array();
  1640                 foreach ($this->constraints as $name => $constraint) {
  1641                     if (empty($constraint[
'messages']) || in_array(
  1642                         $this->messageParameters[
'lti_message_type'],
  1643                         $constraint[
'messages']
  1646                         if ($constraint[
'required']) {
  1647                             if (!isset($this->messageParameters[$name]) || (strlen(trim($this->messageParameters[$name])) <= 0)) {
  1648                                 $invalidParameters[] = 
"{$name} (missing)";
  1652                         if ($ok && !is_null($constraint[
'max_length']) && isset($this->messageParameters[$name])) {
  1653                             if (strlen(trim($this->messageParameters[$name])) > $constraint[
'max_length']) {
  1654                                 $invalidParameters[] = 
"{$name} (too long)";
  1659                 if (count($invalidParameters) > 0) {
  1661                     if (empty($this->reason)) {
  1662                         $this->reason = 
'Invalid parameter(s): ' . implode(
', ', $invalidParameters) . 
'.';
  1672                         $tpHook = 
new $className($this);
  1673                         $contextId = $tpHook->getContextId();
  1675                     if (empty($contextId) && isset($this->messageParameters[
'context_id'])) {
  1676                         $contextId = trim($this->messageParameters[
'context_id']);
  1678                     if (!empty($contextId)) {
  1681                         if (isset($this->messageParameters[
'context_title'])) {
  1682                             $title = trim($this->messageParameters[
'context_title']);
  1684                         if (empty($title)) {
  1685                             $title = 
"Course {$this->context->getId()}";
  1687                         $this->context->title = $title;
  1688                         if (isset($this->messageParameters[
'context_type'])) {
  1689                             $this->context->type = trim($this->messageParameters[
'context_type']);
  1690                             if (strpos($this->context->type, 
'http://purl.imsglobal.org/vocab/lis/v2/course#') === 0) {
  1691                                 $this->context->type = substr($this->context->type, 46);
  1697                     if (isset($this->messageParameters[
'resource_link_id'])) {
  1698                         $contentItemId = 
'';
  1699                         if (isset($this->messageParameters[
'custom_content_item_id'])) {
  1700                             $contentItemId = $this->messageParameters[
'custom_content_item_id'];
  1702                         if (empty($this->context)) {
  1705                                 trim($this->messageParameters[
'resource_link_id']),
  1711                                 trim($this->messageParameters[
'resource_link_id']),
  1716                         if (isset($this->messageParameters[
'resource_link_title'])) {
  1717                             $title = trim($this->messageParameters[
'resource_link_title']);
  1719                         if (empty($title)) {
  1720                             $title = 
"Resource {$this->resourceLink->getId()}";
  1722                         $this->resourceLink->title = $title;
  1725                     foreach ($this->platform->getSettings() as $name => $value) {
  1726                         if ((strpos($name, 
'custom_') === 0) && (!in_array($name, self::$LTI_RETAIN_SETTING_NAMES))) {
  1727                             $this->platform->setSetting($name);
  1728                             $doSavePlatform = 
true;
  1731                     if (!empty($this->context)) {
  1732                         foreach ($this->context->getSettings() as $name => $value) {
  1733                             if ((strpos($name, 
'custom_') === 0) && (!in_array($name, self::$LTI_RETAIN_SETTING_NAMES))) {
  1734                                 $this->context->setSetting($name);
  1738                     if (!empty($this->resourceLink)) {
  1739                         foreach ($this->resourceLink->getSettings() as $name => $value) {
  1740                             if ((strpos($name, 
'custom_') === 0) && (!in_array($name, self::$LTI_RETAIN_SETTING_NAMES))) {
  1741                                 $this->resourceLink->setSetting($name);
  1746                     foreach (self::$LTI_CONSUMER_SETTING_NAMES as $name) {
  1747                         if (isset($this->messageParameters[$name])) {
  1748                             $this->platform->setSetting($name, $this->messageParameters[$name]);
  1749                         } elseif (!in_array($name, self::$LTI_RETAIN_SETTING_NAMES)) {
  1750                             $this->platform->setSetting($name);
  1753                     if (!empty($this->context)) {
  1754                         foreach (self::$LTI_CONTEXT_SETTING_NAMES as $name) {
  1755                             if (isset($this->messageParameters[$name])) {
  1756                                 $this->context->setSetting($name, $this->messageParameters[$name]);
  1757                             } elseif (!in_array($name, self::$LTI_RETAIN_SETTING_NAMES)) {
  1758                                 $this->context->setSetting($name);
  1762                     if (!empty($this->resourceLink)) {
  1763                         foreach (self::$LTI_RESOURCE_LINK_SETTING_NAMES as $name) {
  1764                             if (isset($this->messageParameters[$name])) {
  1765                                 $this->resourceLink->setSetting($name, $this->messageParameters[$name]);
  1766                             } elseif (!in_array($name, self::$LTI_RETAIN_SETTING_NAMES)) {
  1767                                 $this->resourceLink->setSetting($name);
  1772                     foreach ($this->messageParameters as $name => $value) {
  1773                         if ((strpos($name, 
'custom_') === 0) && !in_array(
  1776                                 self::$LTI_CONSUMER_SETTING_NAMES,
  1777                                 self::$LTI_CONTEXT_SETTING_NAMES,
  1778                                 self::$LTI_RESOURCE_LINK_SETTING_NAMES
  1781                             $this->platform->setSetting($name, $value);
  1782                             if (!empty($this->context)) {
  1783                                 $this->context->setSetting($name, $value);
  1785                             if (!empty($this->resourceLink)) {
  1786                                 $this->resourceLink->setSetting($name, $value);
  1793                     if ($this->
hasConfiguredApiHook(self::$USER_ID_HOOK, $this->platform->getFamilyCode(), $this)) {
  1794                         $className = $this->
getApiHook(self::$USER_ID_HOOK, $this->platform->getFamilyCode());
  1795                         $tpHook = 
new $className($this);
  1796                         $userId = $tpHook->getUserId();
  1798                     if (empty($userId) && isset($this->messageParameters[
'user_id'])) {
  1799                         $userId = trim($this->messageParameters[
'user_id']);
  1805                     $firstname = (isset($this->messageParameters[
'lis_person_name_given'])) ? $this->messageParameters[
'lis_person_name_given'] : 
'';
  1806                     $lastname = (isset($this->messageParameters[
'lis_person_name_family'])) ? $this->messageParameters[
'lis_person_name_family'] : 
'';
  1807                     $fullname = (isset($this->messageParameters[
'lis_person_name_full'])) ? $this->messageParameters[
'lis_person_name_full'] : 
'';
  1808                     $this->userResult->setNames($firstname, $lastname, $fullname);
  1811                     if (isset($this->messageParameters[
'lis_person_sourcedid'])) {
  1812                         $this->userResult->sourcedId = $this->messageParameters[
'lis_person_sourcedid'];
  1816                     if (isset($this->messageParameters[
'ext_username'])) {
  1817                         $this->userResult->username = $this->messageParameters[
'ext_username'];
  1818                     } elseif (isset($this->messageParameters[
'ext_user_username'])) {
  1819                         $this->userResult->username = $this->messageParameters[
'ext_user_username'];
  1820                     } elseif (isset($this->messageParameters[
'custom_username'])) {
  1821                         $this->userResult->username = $this->messageParameters[
'custom_username'];
  1822                     } elseif (isset($this->messageParameters[
'custom_user_username'])) {
  1823                         $this->userResult->username = $this->messageParameters[
'custom_user_username'];
  1827                     $email = (isset($this->messageParameters[
'lis_person_contact_email_primary'])) ? $this->messageParameters[
'lis_person_contact_email_primary'] : 
'';
  1828                     $this->userResult->setEmail($email, $this->defaultEmail);
  1831                     if (isset($this->messageParameters[
'user_image'])) {
  1832                         $this->userResult->image = $this->messageParameters[
'user_image'];
  1836                     if (isset($this->messageParameters[
'roles'])) {
  1838                             $this->messageParameters[
'roles'],
  1839                             $this->messageParameters[
'lti_version']
  1845                     if ($this->platform->ltiVersion !== $this->messageParameters[
'lti_version']) {
  1846                         $this->platform->ltiVersion = $this->messageParameters[
'lti_version'];
  1847                         $doSavePlatform = 
true;
  1849                     if (isset($this->messageParameters[
'deployment_id'])) {
  1850                         $this->platform->deploymentId = $this->messageParameters[
'deployment_id'];
  1852                     if (isset($this->messageParameters[
'tool_consumer_instance_name'])) {
  1853                         if ($this->platform->consumerName !== $this->messageParameters[
'tool_consumer_instance_name']) {
  1854                             $this->platform->consumerName = $this->messageParameters[
'tool_consumer_instance_name'];
  1855                             $doSavePlatform = 
true;
  1858                     if (isset($this->messageParameters[
'tool_consumer_info_product_family_code'])) {
  1859                         $version = $this->messageParameters[
'tool_consumer_info_product_family_code'];
  1860                         if (isset($this->messageParameters[
'tool_consumer_info_version'])) {
  1861                             $version .= 
"-{$this->messageParameters['tool_consumer_info_version']}";
  1864                         if ($this->platform->consumerVersion !== 
$version) {
  1865                             $this->platform->consumerVersion = 
$version;
  1866                             $doSavePlatform = 
true;
  1868                     } elseif (isset($this->messageParameters[
'ext_lms']) && ($this->platform->consumerName !== $this->messageParameters[
'ext_lms'])) {
  1869                         $this->platform->consumerVersion = $this->messageParameters[
'ext_lms'];
  1870                         $doSavePlatform = 
true;
  1872                     if (isset($this->messageParameters[
'tool_consumer_instance_guid'])) {
  1873                         if (is_null($this->platform->consumerGuid)) {
  1874                             $this->platform->consumerGuid = $this->messageParameters[
'tool_consumer_instance_guid'];
  1875                             $doSavePlatform = 
true;
  1876                         } elseif (!$this->platform->protected && ($this->platform->consumerGuid !== $this->messageParameters[
'tool_consumer_instance_guid'])) {
  1877                             $this->platform->consumerGuid = $this->messageParameters[
'tool_consumer_instance_guid'];
  1878                             $doSavePlatform = 
true;
  1881                     if (isset($this->messageParameters[
'launch_presentation_css_url'])) {
  1882                         if ($this->platform->cssPath !== $this->messageParameters[
'launch_presentation_css_url']) {
  1883                             $this->platform->cssPath = $this->messageParameters[
'launch_presentation_css_url'];
  1884                             $doSavePlatform = 
true;
  1886                     } elseif (isset($this->messageParameters[
'ext_launch_presentation_css_url']) && ($this->platform->cssPath !== $this->messageParameters[
'ext_launch_presentation_css_url'])) {
  1887                         $this->platform->cssPath = $this->messageParameters[
'ext_launch_presentation_css_url'];
  1888                         $doSavePlatform = 
true;
  1889                     } elseif (!empty($this->platform->cssPath)) {
  1890                         $this->platform->cssPath = null;
  1891                         $doSavePlatform = 
true;
  1896                 if ($doSavePlatform) {
  1897                     $this->platform->save();
  1902                     if (isset($this->context)) {
  1903                         $this->context->save();
  1906                     if (isset($this->resourceLink)) {
  1908                         $this->resourceLink->save();
  1911                         $this->userResult->setResourceLinkId($this->resourceLink->getRecordId());
  1912                         if (isset($this->messageParameters[
'lis_result_sourcedid'])) {
  1913                             if ($this->userResult->ltiResultSourcedId !== $this->messageParameters[
'lis_result_sourcedid']) {
  1914                                 $this->userResult->ltiResultSourcedId = $this->messageParameters[
'lis_result_sourcedid'];
  1915                                 $this->userResult->save();
  1917                         } elseif ($this->userResult->isLearner()) {  
  1918                             $this->userResult->ltiResultSourcedId = 
'';
  1919                             $this->userResult->save();
  1939         $doSaveResourceLink = 
true;
  1941         $id = $this->resourceLink->primaryResourceLinkId;
  1943         $shareRequest = isset($this->messageParameters[
'custom_share_key']) && !empty($this->messageParameters[
'custom_share_key']);
  1944         if ($shareRequest) {
  1945             if (!$this->allowSharing) {
  1947                 $this->reason = 
'Your sharing request has been refused because sharing is not being permitted.';
  1950                 $shareKey = 
new ResourceLinkShareKey($this->resourceLink, $this->messageParameters[
'custom_share_key']);
  1951                 if (!is_null($shareKey->resourceLinkId)) {
  1953                     $id = $shareKey->resourceLinkId;
  1954                     $ok = (
$id !== $this->resourceLink->getRecordId());
  1956                         $this->resourceLink->primaryResourceLinkId = 
$id;
  1957                         $this->resourceLink->shareApproved = $shareKey->autoApprove;
  1958                         $ok = $this->resourceLink->save();
  1960                             $doSaveResourceLink = 
false;
  1961                             $this->userResult->getResourceLink()->primaryResourceLinkId = 
$id;
  1962                             $this->userResult->getResourceLink()->shareApproved = $shareKey->autoApprove;
  1963                             $this->userResult->getResourceLink()->updated = time();
  1965                             $shareKey->delete();
  1967                             $this->reason = 
'An error occurred initialising your share arrangement.';
  1970                         $this->reason = 
'It is not possible to share your resource link with yourself.';
  1974                     $ok = !is_null(
$id);
  1976                         $this->reason = 
'You have requested to share a resource link but none is available.';
  1978                         $ok = (!is_null($this->userResult->getResourceLink()->shareApproved) && $this->userResult->getResourceLink()->shareApproved);
  1980                             $this->reason = 
'Your share request is waiting to be approved.';
  1989                 $this->reason = 
'You have not requested to share a resource link but an arrangement is currently in place.';
  1994         if ($ok && !is_null(
$id)) {
  1996             $ok = !is_null($resourceLink->created);
  1998                 if ($doSaveResourceLink) {
  1999                     $this->resourceLink->save();
  2003                 $this->reason = 
'Unable to load resource link being shared.';
  2018         if (isset($parameters[
'client_id'])) {
  2021         $deploymentId = null;
  2022         if (isset($parameters[
'lti_deployment_id'])) {
  2023             $deploymentId = $parameters[
'lti_deployment_id'];
  2028             $this->debugMode = 
true;
  2031         $ok = !is_null($this->platform) && !empty($this->platform->authenticationUrl);
  2033             $this->reason = 
'Platform not found or no platform authentication request URL.';
  2037                 $ok = !$nonce->load();
  2039             $nonce->expires = time() + 10;  
  2040             $ok = $nonce->save();
  2043                 $oauthRequest = LTIOAuth\OAuthRequest::from_request();
  2044                 $redirectUri = $oauthRequest->get_normalized_http_url();
  2045                 if (!empty(
$_SERVER[
'QUERY_STRING'])) {
  2046                     if (
$_SERVER[
'REQUEST_METHOD'] === 
'POST') {
  2047                         $redirectUri .= 
"?{$_SERVER['QUERY_STRING']}";
  2053                             $parts = explode(
'=', $param, 2);
  2056                                 array(
'iss', 
'target_link_uri', 
'login_hint', 
'lti_message_hint', 
'client_id', 
'lti_deployment_id')
  2059                             } elseif (!$ignore) {
  2061                                     $queryString .= 
"&{$parts[0]}";
  2063                                     $queryString .= 
"&{$parts[0]}={$parts[1]}";
  2067                         if (!empty($queryString)) {
  2068                             $queryString = substr($queryString, 1);
  2069                             $redirectUri .= 
"?{$queryString}";
  2074                     'client_id' => $this->platform->clientId,
  2075                     'login_hint' => $parameters[
'login_hint'],
  2078                     'redirect_uri' => $redirectUri,
  2079                     'response_mode' => 
'form_post',
  2080                     'response_type' => 
'id_token',
  2081                     'scope' => 
'openid',
  2082                     'state' => $nonce->getValue()
  2084                 if (isset($parameters[
'lti_message_hint'])) {
  2085                     $params[
'lti_message_hint'] = $parameters[
'lti_message_hint'];
  2094                 $this->reason = 
'Unable to generate a state value.';
  2108             $ok = !$nonce->load();
  2110         $ok = $nonce->save();
  2113                 'tool_state' => $nonce->getValue(),
  2114                 'platform_state' => $this->messageParameters[
'platform_state']
  2116             $params = $this->platform->addSignature($this->messageParameters[
'relaunch_url'], $params);
  2117             $this->output = 
Util::sendForm($this->messageParameters[
'relaunch_url'], $params);
  2119             $this->reason = 
'Unable to generate a state value.';
  2132     private function checkValue(&$value, array $values, 
string $reason, 
bool $strictMode, 
bool $ignoreInvalid = 
false): bool
  2134         $lookupValue = $value;
  2136             $lookupValue = strtolower($value);
  2138         $ok = in_array($lookupValue, $values);
  2139         if (!$ok && !$strictMode && $ignoreInvalid) {
  2140             Util::logInfo(sprintf($reason, $value) . 
" [Error ignored]");
  2142         } elseif (!$ok && !empty($reason)) {
  2143             $this->reason = sprintf($reason, $value);
  2144         } elseif ($lookupValue !== $value) {
  2145             Util::logInfo(sprintf($reason, $value) . 
" [Changed to '{$lookupValue}']");
  2146             $value = $lookupValue;
 
const TYPE_LINK
Type for link content-item. 
 
button(string $caption, string $cmd)
 
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
 
if(! $DIC->user() ->getId()||!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) $params
 
const LTI_ASSIGNMENT_MEDIA_TYPE
Media type for LTI assignment links. 
 
const TYPE_HTML
Type for HTML content-item. 
 
const TYPE_IMAGE
Type for image content-item. 
 
$messages
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
 
static http()
Fetches the global http state from ILIAS. 
 
const TYPE_LTI_LINK
Type for LTI link content-item. 
 
static fromPlatform(Platform $platform, string $ltiContextId)
Class constructor from consumer. 
 
Class to represent a content-item object. 
 
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
 
const TYPE_LTI_ASSIGNMENT
Type for LTI assignment content-item. 
 
const TYPE_FILE
Type for file content-item. 
 
const LTI_LINK_MEDIA_TYPE
Media type for LTI launch links. 
 
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
 
Class to represent a platform context.