61 private static $LTI_VERSIONS = array(self::LTI_VERSION1, self::LTI_VERSION2);
65 private static $MESSAGE_TYPES = array(
'basic-lti-launch-request' =>
'onLaunch',
66 'ContentItemSelectionRequest' =>
'onContentItem',
67 'ToolProxyRegistrationRequest' =>
'register');
73 private static $METHOD_NAMES = array(
'basic-lti-launch-request' =>
'onLaunch',
74 'ContentItemSelectionRequest' =>
'onContentItem',
75 'ToolProxyRegistrationRequest' =>
'onRegister');
81 private static $LTI_CONSUMER_SETTING_NAMES = array(
'custom_tc_profile_url',
'custom_system_setting_url');
87 private static $LTI_CONTEXT_SETTING_NAMES = array(
'custom_context_setting_url',
88 'custom_lineitems_url',
'custom_results_url',
89 'custom_context_memberships_url');
95 private static $LTI_RESOURCE_LINK_SETTING_NAMES = array(
'lis_result_sourcedid',
'lis_outcome_service_url',
96 'ext_ims_lis_basic_outcome_url',
'ext_ims_lis_resultvalue_sourcedids',
97 'ext_ims_lis_memberships_id',
'ext_ims_lis_memberships_url',
98 'ext_ims_lti_tool_setting',
'ext_ims_lti_tool_setting_id',
'ext_ims_lti_tool_setting_url',
99 'custom_link_setting_url',
100 'custom_lineitem_url',
'custom_result_url');
106 private static $CUSTOM_SUBSTITUTION_VARIABLES = array(
'User.id' =>
'user_id',
107 'User.image' =>
'user_image',
108 'User.username' =>
'username',
109 'User.scope.mentor' =>
'role_scope_mentor',
110 'Membership.role' =>
'roles',
111 'Person.sourcedId' =>
'lis_person_sourcedid',
112 'Person.name.full' =>
'lis_person_name_full',
113 'Person.name.family' =>
'lis_person_name_family',
114 'Person.name.given' =>
'lis_person_name_given',
115 'Person.email.primary' =>
'lis_person_contact_email_primary',
116 'Context.id' =>
'context_id',
117 'Context.type' =>
'context_type',
118 'Context.title' =>
'context_title',
119 'Context.label' =>
'context_label',
120 'CourseOffering.sourcedId' =>
'lis_course_offering_sourcedid',
121 'CourseSection.sourcedId' =>
'lis_course_section_sourcedid',
122 'CourseSection.label' =>
'context_label',
123 'CourseSection.title' =>
'context_title',
124 'ResourceLink.id' =>
'resource_link_id',
125 'ResourceLink.title' =>
'resource_link_title',
126 'ResourceLink.description' =>
'resource_link_description',
127 'Result.sourcedId' =>
'lis_result_sourcedid',
128 'BasicOutcome.url' =>
'lis_outcome_service_url',
129 'ToolConsumerProfile.url' =>
'custom_tc_profile_url',
130 'ToolProxy.url' =>
'tool_proxy_url',
131 'ToolProxy.custom.url' =>
'custom_system_setting_url',
132 'ToolProxyBinding.custom.url' =>
'custom_context_setting_url',
133 'LtiLink.custom.url' =>
'custom_link_setting_url',
134 'LineItems.url' =>
'custom_lineitems_url',
135 'LineItem.url' =>
'custom_lineitem_url',
136 'Results.url' =>
'custom_results_url',
137 'Result.url' =>
'custom_result_url',
138 'ToolProxyBinding.memberships.url' =>
'custom_context_memberships_url');
298 private $callbackHandler = null;
304 private $constraints = null;
314 $this->constraints = array();
316 $this->ok = !is_null($this->dataConnector);
319 $this->debugMode = isset($_POST[
'custom_debug']) && (strtolower($_POST[
'custom_debug']) ===
'true');
322 if (isset($_POST[
'launch_presentation_return_url'])) {
323 $this->returnUrl = $_POST[
'launch_presentation_return_url'];
324 }
else if (isset($_POST[
'content_item_return_url'])) {
325 $this->returnUrl = $_POST[
'content_item_return_url'];
329 $this->requiredServices = array();
330 $this->optionalServices = array();
331 $this->resourceHandlers = array();
342 if ($this->authenticate()) {
362 if (strlen($name) > 0) {
363 $this->constraints[$name] = array(
'required' => $required,
'max_length' => $maxLength,
'messages' => $messageTypes);
376 return $this->dataConnector->getToolConsumers();
392 $services = $this->consumer->profile->service_offered;
393 if (is_array($services)) {
395 foreach ($services as $service) {
397 if (!is_array($service->format) || !in_array($format, $service->format)) {
401 foreach ($methods as $method) {
402 if (!is_array($service->action) || !in_array($method, $service->action)) {
403 $missing[] = $method;
407 if (count($methods) <= 0) {
427 $toolProxyService = $this->
findService(
'application/vnd.ims.lti.v2.toolproxy+json', array(
'POST'));
430 $http = $this->consumer->doServiceRequest($toolProxyService,
'POST',
'application/vnd.ims.lti.v2.toolproxy+json', json_encode($toolProxy));
431 $ok = $http->ok && ($http->status == 201) && isset($http->responseJson->tool_proxy_guid) && (strlen($http->responseJson->tool_proxy_guid) > 0);
433 $this->consumer->setKey($http->responseJson->tool_proxy_guid);
434 $this->consumer->secret = $toolProxy->security_contract->shared_secret;
435 $this->consumer->toolProxy = json_encode($toolProxy);
436 $this->consumer->save();
453 if (!is_array($roles)) {
454 $roles = explode(
',', $roles);
456 $parsedRoles = array();
457 foreach ($roles as $role) {
460 if (substr($role, 0, 4) !==
'urn:') {
461 $role =
'urn:lti:role:ims/lis/' . $role;
463 $parsedRoles[] = $role;
479 public static function sendForm($url, $params, $target =
'')
485 <title>IMS LTI message</title>
486 <script type=
"text/javascript">
488 function doOnLoad() {
489 document.forms[0].submit();
492 window.onload=doOnLoad;
497 <form action=
"{$url}" method=
"post" target=
"" encType=
"application/x-www-form-urlencoded">
501 foreach($params as $key => $value ) {
502 $key = htmlentities($key, ENT_COMPAT | ENT_HTML401,
'UTF-8');
503 $value = htmlentities($value, ENT_COMPAT | ENT_HTML401,
'UTF-8');
505 <input type=
"hidden" name=
"{$key}" value=
"{$value}" />
522 ### PROTECTED METHODS 568 $this->doCallback(
'onError');
583 private function doCallback($method = null)
587 if (is_null($callback)) {
588 $callback = self::$METHOD_NAMES[$_POST[
'lti_message_type']];
590 if (method_exists($this, $callback)) {
591 $result = $this->$callback();
592 }
else if (is_null($method) && $this->ok) {
594 $this->reason =
"Message type not supported: {$_POST['lti_message_type']}";
596 if ($this->ok && ($_POST[
'lti_message_type'] ==
'ToolProxyRegistrationRequest')) {
597 $this->consumer->save();
609 private function result()
620 if (!empty($this->returnUrl)) {
622 if (strpos($errorUrl,
'?') ===
false) {
627 if ($this->debugMode && !is_null($this->reason)) {
628 $errorUrl .=
'lti_errormsg=' . urlencode(
"Debug error: $this->reason");
630 $errorUrl .=
'lti_errormsg=' . urlencode($this->message);
631 if (!is_null($this->reason)) {
632 $errorUrl .=
'<i_errorlog=' . urlencode(
"Debug error: $this->reason");
635 if (!is_null($this->consumer) && isset($_POST[
'lti_message_type']) && ($_POST[
'lti_message_type'] ===
'ContentItemSelectionRequest')) {
636 $formParams = array();
637 if (isset($_POST[
'data'])) {
638 $formParams[
'data'] = $_POST[
'data'];
640 $version = (isset($_POST[
'lti_version'])) ? $_POST[
'lti_version'] : self::LTI_VERSION1;
641 $formParams = $this->consumer->signParameters($errorUrl,
'ContentItemSelection', $version, $formParams);
642 $page = self::sendForm($errorUrl, $formParams);
645 header(
"Location: {$errorUrl}");
649 if (!is_null($this->errorOutput)) {
651 }
else if ($this->debugMode && !empty($this->reason)) {
652 echo
"Debug error: {$this->reason}";
654 echo
"Error: {$this->message}";
657 }
else if (!is_null($this->redirectUrl)) {
658 header(
"Location: {$this->redirectUrl}");
660 }
else if (!is_null($this->output)) {
674 private function authenticate()
678 $doSaveConsumer =
false;
680 $this->ok = isset($_POST[
'lti_message_type']) && array_key_exists($_POST[
'lti_message_type'], self::$MESSAGE_TYPES);
682 $this->reason =
'Invalid or missing lti_message_type parameter.';
685 $this->ok = isset($_POST[
'lti_version']) && in_array($_POST[
'lti_version'], self::$LTI_VERSIONS);
687 $this->reason =
'Invalid or missing lti_version parameter.';
691 if ($_POST[
'lti_message_type'] ===
'basic-lti-launch-request') {
692 $this->ok = isset($_POST[
'resource_link_id']) && (strlen(trim($_POST[
'resource_link_id'])) > 0);
694 $this->reason =
'Missing resource link ID.';
696 }
else if ($_POST[
'lti_message_type'] ===
'ContentItemSelectionRequest') {
697 if (isset($_POST[
'accept_media_types']) && (strlen(trim($_POST[
'accept_media_types'])) > 0)) {
698 $mediaTypes = array_filter(explode(
',', str_replace(
' ',
'', $_POST[
'accept_media_types'])),
'strlen');
702 $this->reason =
'No accept_media_types found.';
709 if ($this->ok && isset($_POST[
'accept_presentation_document_targets']) && (strlen(trim($_POST[
'accept_presentation_document_targets'])) > 0)) {
710 $documentTargets = array_filter(explode(
',', str_replace(
' ',
'', $_POST[
'accept_presentation_document_targets'])),
'strlen');
714 $this->reason =
'Missing or empty accept_presentation_document_targets parameter.';
717 $this->ok = $this->checkValue($documentTarget, array(
'embed',
'frame',
'iframe',
'window',
'popup',
'overlay',
'none'),
718 'Invalid value in accept_presentation_document_targets parameter: %s.');
731 $this->ok = isset($_POST[
'content_item_return_url']) && (strlen(trim($_POST[
'content_item_return_url'])) > 0);
733 $this->reason =
'Missing content_item_return_url parameter.';
736 }
else if ($_POST[
'lti_message_type'] ==
'ToolProxyRegistrationRequest') {
737 $this->ok = ((isset($_POST[
'reg_key']) && (strlen(trim($_POST[
'reg_key'])) > 0)) &&
738 (isset($_POST[
'reg_password']) && (strlen(trim($_POST[
'reg_password'])) > 0)) &&
739 (isset($_POST[
'tc_profile_url']) && (strlen(trim($_POST[
'tc_profile_url'])) > 0)) &&
740 (isset($_POST[
'launch_presentation_return_url']) && (strlen(trim($_POST[
'launch_presentation_return_url'])) > 0)));
741 if ($this->debugMode && !$this->ok) {
742 $this->reason =
'Missing message parameters.';
748 if ($this->ok && ($_POST[
'lti_message_type'] !=
'ToolProxyRegistrationRequest')) {
749 $this->ok = isset($_POST[
'oauth_consumer_key']);
751 $this->reason =
'Missing consumer key.';
754 $this->consumer =
new ToolConsumer($_POST[
'oauth_consumer_key'], $this->dataConnector);
755 $this->ok = !is_null($this->consumer->created);
757 $this->reason =
'Invalid consumer key.';
761 $today = date(
'Y-m-d', $now);
762 if (is_null($this->consumer->lastAccess)) {
763 $doSaveConsumer =
true;
765 $last = date(
'Y-m-d', $this->consumer->lastAccess);
766 $doSaveConsumer = $doSaveConsumer || ($last !== $today);
768 $this->consumer->last_access = $now;
773 $server->add_signature_method($method);
775 $res = $server->verify_request($request);
776 }
catch (\Exception $e) {
778 if (empty($this->reason)) {
779 if ($this->debugMode) {
781 $signature = $request->build_signature($method,
$consumer,
false);
782 $this->reason = $e->getMessage();
783 if (empty($this->reason)) {
784 $this->reason =
'OAuth exception';
786 $this->details[] =
'Timestamp: ' . time();
787 $this->details[] =
"Signature: {$signature}";
788 $this->details[] =
"Base string: {$request->base_string}]";
790 $this->reason =
'OAuth signature check failed - perhaps an incorrect secret or timestamp.';
796 $today = date(
'Y-m-d', $now);
797 if (is_null($this->consumer->lastAccess)) {
798 $doSaveConsumer =
true;
800 $last = date(
'Y-m-d', $this->consumer->lastAccess);
801 $doSaveConsumer = $doSaveConsumer || ($last !== $today);
803 $this->consumer->last_access = $now;
804 if ($this->consumer->protected) {
805 if (!is_null($this->consumer->consumerGuid)) {
806 $this->ok = empty($_POST[
'tool_consumer_instance_guid']) ||
807 ($this->consumer->consumerGuid === $_POST[
'tool_consumer_instance_guid']);
809 $this->reason =
'Request is from an invalid tool consumer.';
812 $this->ok = isset($_POST[
'tool_consumer_instance_guid']);
814 $this->reason =
'A tool consumer GUID must be included in the launch request.';
819 $this->ok = $this->consumer->enabled;
821 $this->reason =
'Tool consumer has not been enabled by the tool provider.';
825 $this->ok = is_null($this->consumer->enableFrom) || ($this->consumer->enableFrom <= $now);
827 $this->ok = is_null($this->consumer->enableUntil) || ($this->consumer->enableUntil > $now);
829 $this->reason =
'Tool consumer access has expired.';
832 $this->reason =
'Tool consumer access is not yet available.';
839 if ($_POST[
'lti_message_type'] ===
'ContentItemSelectionRequest') {
840 if (isset($_POST[
'accept_unsigned'])) {
841 $this->ok = $this->checkValue($_POST[
'accept_unsigned'], array(
'true',
'false'),
'Invalid value for accept_unsigned parameter: %s.');
843 if ($this->ok && isset($_POST[
'accept_multiple'])) {
844 $this->ok = $this->checkValue($_POST[
'accept_multiple'], array(
'true',
'false'),
'Invalid value for accept_multiple parameter: %s.');
846 if ($this->ok && isset($_POST[
'accept_copy_advice'])) {
847 $this->ok = $this->checkValue($_POST[
'accept_copy_advice'], array(
'true',
'false'),
'Invalid value for accept_copy_advice parameter: %s.');
849 if ($this->ok && isset($_POST[
'auto_create'])) {
850 $this->ok = $this->checkValue($_POST[
'auto_create'], array(
'true',
'false'),
'Invalid value for auto_create parameter: %s.');
852 if ($this->ok && isset($_POST[
'can_confirm'])) {
853 $this->ok = $this->checkValue($_POST[
'can_confirm'], array(
'true',
'false'),
'Invalid value for can_confirm parameter: %s.');
855 }
else if (isset($_POST[
'launch_presentation_document_target'])) {
856 $this->ok = $this->checkValue($_POST[
'launch_presentation_document_target'], array(
'embed',
'frame',
'iframe',
'window',
'popup',
'overlay'),
857 'Invalid value for launch_presentation_document_target parameter: %s.');
862 if ($this->ok && ($_POST[
'lti_message_type'] ===
'ToolProxyRegistrationRequest')) {
863 $this->ok = $_POST[
'lti_version'] == self::LTI_VERSION2;
865 $this->reason =
'Invalid lti_version parameter';
868 $http =
new HTTPMessage($_POST[
'tc_profile_url'],
'GET', null,
'Accept: application/vnd.ims.lti.v2.toolconsumerprofile+json');
869 $this->ok = $http->send();
871 $this->reason =
'Tool consumer profile not accessible.';
873 $tcProfile = json_decode($http->response);
874 $this->ok = !is_null($tcProfile);
876 $this->reason =
'Invalid JSON in tool consumer profile.';
882 $this->consumer =
new ToolConsumer($_POST[
'reg_key'], $this->dataConnector);
883 $this->consumer->profile = $tcProfile;
884 $capabilities = $this->consumer->profile->capability_offered;
886 foreach ($this->resourceHandlers as $resourceHandler) {
887 foreach ($resourceHandler->requiredMessages as
$message) {
888 if (!in_array($message->type, $capabilities)) {
889 $missing[$message->type] =
true;
893 foreach ($this->constraints as $name => $constraint) {
894 if ($constraint[
'required']) {
895 if (!in_array($name, $capabilities) && !in_array($name, array_flip($capabilities))) {
896 $missing[$name] =
true;
900 if (!empty($missing)) {
902 $this->reason =
'Required capability not offered - \'' . implode(
'\', \
'', array_keys($missing)) .
'\'';
908 foreach ($this->requiredServices as $service) {
909 foreach ($service->formats as $format) {
910 if (!$this->
findService($format, $service->actions)) {
912 $this->reason =
'Required service(s) not offered - ';
915 $this->reason .=
', ';
917 $this->reason .=
"'{$format}' [" . implode(
', ', $service->actions) .
']';
923 if ($_POST[
'lti_message_type'] ===
'ToolProxyRegistrationRequest') {
924 $this->consumer->profile = $tcProfile;
925 $this->consumer->secret = $_POST[
'reg_password'];
926 $this->consumer->ltiVersion = $_POST[
'lti_version'];
927 $this->consumer->name = $tcProfile->product_instance->service_owner->service_owner_name->default_value;
928 $this->consumer->consumerName = $this->consumer->name;
929 $this->consumer->consumerVersion =
"{$tcProfile->product_instance->product_info->product_family->code}-{$tcProfile->product_instance->product_info->product_version}";
930 $this->consumer->consumerGuid = $tcProfile->product_instance->guid;
931 $this->consumer->enabled =
true;
932 $this->consumer->protected =
true;
933 $doSaveConsumer =
true;
936 }
else if ($this->ok && !empty($_POST[
'custom_tc_profile_url']) && empty($this->consumer->profile)) {
937 $http =
new HTTPMessage($_POST[
'custom_tc_profile_url'],
'GET', null,
'Accept: application/vnd.ims.lti.v2.toolconsumerprofile+json');
939 $tcProfile = json_decode($http->response);
940 if (!is_null($tcProfile)) {
941 $this->consumer->profile = $tcProfile;
942 $doSaveConsumer =
true;
949 $invalidParameters = array();
950 foreach ($this->constraints as $name => $constraint) {
951 if (empty($constraint[
'messages']) || in_array($_POST[
'lti_message_type'], $constraint[
'messages'])) {
953 if ($constraint[
'required']) {
954 if (!isset($_POST[$name]) || (strlen(trim($_POST[$name])) <= 0)) {
955 $invalidParameters[] =
"{$name} (missing)";
959 if (
$ok && !is_null($constraint[
'max_length']) && isset($_POST[$name])) {
960 if (strlen(trim($_POST[$name])) > $constraint[
'max_length']) {
961 $invalidParameters[] =
"{$name} (too long)";
966 if (count($invalidParameters) > 0) {
968 if (empty($this->reason)) {
969 $this->reason =
'Invalid parameter(s): ' . implode(
', ', $invalidParameters) .
'.';
977 if (isset($_POST[
'context_id'])) {
980 if (isset($_POST[
'context_title'])) {
981 $title = trim($_POST[
'context_title']);
984 $title =
"Course {$this->context->getId()}";
986 $this->context->title = $title;
990 if (isset($_POST[
'resource_link_id'])) {
992 if (isset($_POST[
'custom_content_item_id'])) {
993 $contentItemId = $_POST[
'custom_content_item_id'];
996 if (!empty($this->context)) {
997 $this->resourceLink->setContextId($this->context->getRecordId());
1000 if (isset($_POST[
'resource_link_title'])) {
1001 $title = trim($_POST[
'resource_link_title']);
1003 if (empty($title)) {
1004 $title =
"Resource {$this->resourceLink->getId()}";
1006 $this->resourceLink->title = $title;
1008 foreach ($this->consumer->getSettings() as $name => $value) {
1009 if (strpos($name,
'custom_') === 0) {
1010 $this->consumer->setSetting($name);
1011 $doSaveConsumer =
true;
1014 if (!empty($this->context)) {
1015 foreach ($this->context->getSettings() as $name => $value) {
1016 if (strpos($name,
'custom_') === 0) {
1017 $this->context->setSetting($name);
1021 foreach ($this->resourceLink->getSettings() as $name => $value) {
1022 if (strpos($name,
'custom_') === 0) {
1023 $this->resourceLink->setSetting($name);
1027 foreach (self::$LTI_CONSUMER_SETTING_NAMES as $name) {
1028 if (isset($_POST[$name])) {
1029 $this->consumer->setSetting($name, $_POST[$name]);
1031 $this->consumer->setSetting($name);
1034 if (!empty($this->context)) {
1035 foreach (self::$LTI_CONTEXT_SETTING_NAMES as $name) {
1036 if (isset($_POST[$name])) {
1037 $this->context->setSetting($name, $_POST[$name]);
1039 $this->context->setSetting($name);
1043 foreach (self::$LTI_RESOURCE_LINK_SETTING_NAMES as $name) {
1044 if (isset($_POST[$name])) {
1045 $this->resourceLink->setSetting($name, $_POST[$name]);
1047 $this->resourceLink->setSetting($name);
1051 foreach ($_POST as $name => $value) {
1052 if ((strpos($name,
'custom_') === 0) &&
1053 !in_array($name, array_merge(self::$LTI_CONSUMER_SETTING_NAMES, self::$LTI_CONTEXT_SETTING_NAMES, self::$LTI_RESOURCE_LINK_SETTING_NAMES))) {
1054 $this->resourceLink->setSetting($name, $value);
1061 if (isset($_POST[
'user_id'])) {
1062 $userId = trim($_POST[
'user_id']);
1068 $firstname = (isset($_POST[
'lis_person_name_given'])) ? $_POST[
'lis_person_name_given'] :
'';
1069 $lastname = (isset($_POST[
'lis_person_name_family'])) ? $_POST[
'lis_person_name_family'] :
'';
1070 $fullname = (isset($_POST[
'lis_person_name_full'])) ? $_POST[
'lis_person_name_full'] :
'';
1071 $this->user->setNames($firstname, $lastname, $fullname);
1074 $email = (isset($_POST[
'lis_person_contact_email_primary'])) ? $_POST[
'lis_person_contact_email_primary'] :
'';
1075 $this->user->setEmail($email, $this->defaultEmail);
1078 if (isset($_POST[
'user_image'])) {
1079 $this->user->image = $_POST[
'user_image'];
1083 if (isset($_POST[
'roles'])) {
1084 $this->user->roles = self::parseRoles($_POST[
'roles']);
1089 if ($this->consumer->ltiVersion !== $_POST[
'lti_version']) {
1090 $this->consumer->ltiVersion = $_POST[
'lti_version'];
1091 $doSaveConsumer =
true;
1093 if (isset($_POST[
'tool_consumer_instance_name'])) {
1094 if ($this->consumer->consumerName !== $_POST[
'tool_consumer_instance_name']) {
1095 $this->consumer->consumerName = $_POST[
'tool_consumer_instance_name'];
1096 $doSaveConsumer =
true;
1099 if (isset($_POST[
'tool_consumer_info_product_family_code'])) {
1100 $version = $_POST[
'tool_consumer_info_product_family_code'];
1101 if (isset($_POST[
'tool_consumer_info_version'])) {
1102 $version .=
"-{$_POST['tool_consumer_info_version']}";
1105 if ($this->consumer->consumerVersion !== $version) {
1106 $this->consumer->consumerVersion = $version;
1107 $doSaveConsumer =
true;
1109 }
else if (isset($_POST[
'ext_lms']) && ($this->consumer->consumerName !== $_POST[
'ext_lms'])) {
1110 $this->consumer->consumerVersion = $_POST[
'ext_lms'];
1111 $doSaveConsumer =
true;
1113 if (isset($_POST[
'tool_consumer_instance_guid'])) {
1114 if (is_null($this->consumer->consumerGuid)) {
1115 $this->consumer->consumerGuid = $_POST[
'tool_consumer_instance_guid'];
1116 $doSaveConsumer =
true;
1117 }
else if (!$this->consumer->protected) {
1118 $doSaveConsumer = ($this->consumer->consumerGuid !== $_POST[
'tool_consumer_instance_guid']);
1119 if ($doSaveConsumer) {
1120 $this->consumer->consumerGuid = $_POST[
'tool_consumer_instance_guid'];
1124 if (isset($_POST[
'launch_presentation_css_url'])) {
1125 if ($this->consumer->cssPath !== $_POST[
'launch_presentation_css_url']) {
1126 $this->consumer->cssPath = $_POST[
'launch_presentation_css_url'];
1127 $doSaveConsumer =
true;
1129 }
else if (isset($_POST[
'ext_launch_presentation_css_url']) &&
1130 ($this->consumer->cssPath !== $_POST[
'ext_launch_presentation_css_url'])) {
1131 $this->consumer->cssPath = $_POST[
'ext_launch_presentation_css_url'];
1132 $doSaveConsumer =
true;
1133 }
else if (!empty($this->consumer->cssPath)) {
1134 $this->consumer->cssPath = null;
1135 $doSaveConsumer =
true;
1140 if ($doSaveConsumer) {
1141 $this->consumer->save();
1143 if ($this->ok && isset($this->context)) {
1144 $this->context->save();
1146 if ($this->ok && isset($this->resourceLink)) {
1149 $this->ok = $this->checkForShare();
1152 $this->resourceLink->save();
1155 if (isset($_POST[
'lis_result_sourcedid'])) {
1156 if ($this->user->ltiResultSourcedId !== $_POST[
'lis_result_sourcedid']) {
1157 $this->user->ltiResultSourcedId = $_POST[
'lis_result_sourcedid'];
1158 $this->user->save();
1160 }
else if (!empty($this->user->ltiResultSourcedId)) {
1161 $this->user->ltiResultSourcedId =
'';
1162 $this->user->save();
1175 private function checkForShare()
1179 $doSaveResourceLink =
true;
1181 $id = $this->resourceLink->primaryResourceLinkId;
1183 $shareRequest = isset($_POST[
'custom_share_key']) && !empty($_POST[
'custom_share_key']);
1184 if ($shareRequest) {
1185 if (!$this->allowSharing) {
1187 $this->reason =
'Your sharing request has been refused because sharing is not being permitted.';
1191 if (!is_null($shareKey->primaryConsumerKey) && !is_null($shareKey->primaryResourceLinkId)) {
1193 $key = $shareKey->primaryConsumerKey;
1194 $id = $shareKey->primaryResourceLinkId;
1195 $ok = ($key !== $this->consumer->getKey()) || ($id != $this->resourceLink->getId());
1197 $this->resourceLink->primaryConsumerKey = $key;
1198 $this->resourceLink->primaryResourceLinkId = $id;
1199 $this->resourceLink->shareApproved = $shareKey->autoApprove;
1200 $ok = $this->resourceLink->save();
1202 $doSaveResourceLink =
false;
1203 $this->user->getResourceLink()->primaryConsumerKey = $key;
1204 $this->user->getResourceLink()->primaryResourceLinkId = $id;
1205 $this->user->getResourceLink()->shareApproved = $shareKey->autoApprove;
1206 $this->user->getResourceLink()->updated = time();
1208 $shareKey->delete();
1210 $this->reason =
'An error occurred initialising your share arrangement.';
1213 $this->reason =
'It is not possible to share your resource link with yourself.';
1217 $ok = !is_null($key);
1219 $this->reason =
'You have requested to share a resource link but none is available.';
1221 $ok = (!is_null($this->user->getResourceLink()->shareApproved) && $this->user->getResourceLink()->shareApproved);
1223 $this->reason =
'Your share request is waiting to be approved.';
1232 $this->reason =
'You have not requested to share a resource link but an arrangement is currently in place.';
1237 if (
$ok && !is_null($id)) {
1245 if ($doSaveResourceLink) {
1246 $this->resourceLink->save();
1250 $this->reason =
'Unable to load resource link being shared.';
1263 private function checkValue($value, $values,
$reason)
1266 $ok = in_array($value, $values);
1268 $this->reason = sprintf(
$reason, $value);
Class to represent an OAuth Data Store.
Class to represent a generic item object.
static from_request($http_method=null, $http_url=null, $parameters=null)
attempt to build up a request from what was passed to the server
static fromConsumer($consumer, $ltiContextId)
Class constructor from consumer.
Class to represent an OAuth Consumer.
Class to represent an OAuth Server.
Class to represent an HTTP message.
Class to represent an OAuth HMAC_SHA1 signature method.