ims-lti 1.2.8 → 2.0.0.beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/Changelog.txt +0 -0
- data/LICENSE.txt +22 -0
- data/README.md +15 -103
- data/lib/ims/lti/converters/time_json_converter.rb +13 -0
- data/lib/ims/lti/converters.rb +5 -0
- data/lib/ims/lti/models/base_url_choice.rb +15 -0
- data/lib/ims/lti/models/base_url_selector.rb +5 -0
- data/lib/ims/lti/models/contact.rb +5 -0
- data/lib/ims/lti/models/icon_endpoint.rb +5 -0
- data/lib/ims/lti/models/icon_info.rb +6 -0
- data/lib/ims/lti/models/localized_name.rb +11 -0
- data/lib/ims/lti/models/localized_text.rb +11 -0
- data/lib/ims/lti/models/lti_model.rb +169 -0
- data/lib/ims/lti/models/message_handler.rb +6 -0
- data/lib/ims/lti/models/messages/basic_lti_launch_request.rb +8 -0
- data/lib/ims/lti/models/messages/message.rb +43 -0
- data/lib/ims/lti/models/messages/registration_request.rb +17 -0
- data/lib/ims/lti/models/messages.rb +6 -0
- data/lib/ims/lti/models/parameter.rb +5 -0
- data/lib/ims/lti/models/product_family.rb +8 -0
- data/lib/ims/lti/models/product_info.rb +19 -0
- data/lib/ims/lti/models/product_instance.rb +10 -0
- data/lib/ims/lti/models/resource_handler.rb +18 -0
- data/lib/ims/lti/models/resource_type.rb +6 -0
- data/lib/ims/lti/models/rest_service.rb +14 -0
- data/lib/ims/lti/models/rest_service_profile.rb +7 -0
- data/lib/ims/lti/models/security_contract.rb +9 -0
- data/lib/ims/lti/models/service_owner.rb +8 -0
- data/lib/ims/lti/models/service_provider.rb +11 -0
- data/lib/ims/lti/models/tool_consumer_profile.rb +20 -0
- data/lib/ims/lti/models/tool_profile.rb +22 -0
- data/lib/ims/lti/models/tool_proxy.rb +11 -0
- data/lib/ims/lti/models/vendor.rb +28 -0
- data/lib/ims/lti/models.rb +29 -0
- data/lib/ims/lti/services/message_service.rb +40 -0
- data/lib/ims/lti/services.rb +5 -0
- data/lib/ims/lti/version.rb +5 -0
- data/lib/ims/lti.rb +6 -64
- data/lib/ims.rb +3 -1
- metadata +58 -56
- data/Changelog +0 -54
- data/LICENSE +0 -18
- data/lib/ims/lti/deprecated_role_checks.rb +0 -52
- data/lib/ims/lti/extensions/canvas.rb +0 -122
- data/lib/ims/lti/extensions/content.rb +0 -258
- data/lib/ims/lti/extensions/outcome_data.rb +0 -240
- data/lib/ims/lti/extensions.rb +0 -45
- data/lib/ims/lti/launch_params.rb +0 -166
- data/lib/ims/lti/outcome_request.rb +0 -225
- data/lib/ims/lti/outcome_response.rb +0 -166
- data/lib/ims/lti/request_validator.rb +0 -56
- data/lib/ims/lti/role_checks.rb +0 -101
- data/lib/ims/lti/tool_base.rb +0 -29
- data/lib/ims/lti/tool_config.rb +0 -231
- data/lib/ims/lti/tool_consumer.rb +0 -86
- data/lib/ims/lti/tool_provider.rb +0 -145
data/lib/ims/lti/tool_config.rb
DELETED
@@ -1,231 +0,0 @@
|
|
1
|
-
module IMS::LTI
|
2
|
-
# Class used to represent an LTI configuration
|
3
|
-
#
|
4
|
-
# It can create and read the Common Cartridge XML representation of LTI links
|
5
|
-
# as described here: http://www.imsglobal.org/LTI/v1p1pd/ltiIMGv1p1pd.html#_Toc309649689
|
6
|
-
#
|
7
|
-
# == Usage
|
8
|
-
# To generate an XML configuration:
|
9
|
-
#
|
10
|
-
# # Create a config object and set some options
|
11
|
-
# tc = IMS::LTI::ToolConfig.new(:title => "Example Sinatra Tool Provider", :launch_url => url)
|
12
|
-
# tc.description = "This example LTI Tool Provider supports LIS Outcome pass-back."
|
13
|
-
#
|
14
|
-
# # generate the XML
|
15
|
-
# tc.to_xml
|
16
|
-
#
|
17
|
-
# Or to create a config object from an XML String:
|
18
|
-
#
|
19
|
-
# tc = IMS::LTI::ToolConfig.create_from_xml(xml)
|
20
|
-
class ToolConfig
|
21
|
-
attr_reader :custom_params, :extensions
|
22
|
-
|
23
|
-
attr_accessor :title, :description, :launch_url, :secure_launch_url,
|
24
|
-
:icon, :secure_icon, :cartridge_bundle, :cartridge_icon,
|
25
|
-
:vendor_code, :vendor_name, :vendor_description, :vendor_url,
|
26
|
-
:vendor_contact_email, :vendor_contact_name
|
27
|
-
|
28
|
-
# Create a new ToolConfig with the given options
|
29
|
-
#
|
30
|
-
# @param opts [Hash] The initial options for the ToolConfig
|
31
|
-
def initialize(opts={})
|
32
|
-
@custom_params = opts.delete("custom_params") || {}
|
33
|
-
@extensions = opts.delete("extensions") || {}
|
34
|
-
|
35
|
-
opts.each_pair do |key, val|
|
36
|
-
self.send("#{key}=", val) if self.respond_to?("#{key}=")
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# Create a ToolConfig from the given XML
|
41
|
-
#
|
42
|
-
# @param xml [String]
|
43
|
-
def self.create_from_xml(xml)
|
44
|
-
tc = ToolConfig.new
|
45
|
-
tc.process_xml(xml)
|
46
|
-
|
47
|
-
tc
|
48
|
-
end
|
49
|
-
|
50
|
-
def set_custom_param(key, val)
|
51
|
-
@custom_params[key] = val
|
52
|
-
end
|
53
|
-
|
54
|
-
def get_custom_param(key)
|
55
|
-
@custom_params[key]
|
56
|
-
end
|
57
|
-
|
58
|
-
# Set the extension parameters for a specific vendor
|
59
|
-
#
|
60
|
-
# @param ext_key [String] The identifier for the vendor-specific parameters
|
61
|
-
# @param ext_params [Hash] The parameters, this is allowed to be two-levels deep
|
62
|
-
def set_ext_params(ext_key, ext_params)
|
63
|
-
raise ArgumentError unless ext_params.is_a?(Hash)
|
64
|
-
@extensions[ext_key] = ext_params
|
65
|
-
end
|
66
|
-
|
67
|
-
def get_ext_params(ext_key)
|
68
|
-
@extensions[ext_key]
|
69
|
-
end
|
70
|
-
|
71
|
-
def set_ext_param(ext_key, param_key, val)
|
72
|
-
@extensions[ext_key] ||= {}
|
73
|
-
@extensions[ext_key][param_key] = val
|
74
|
-
end
|
75
|
-
|
76
|
-
def get_ext_param(ext_key, param_key)
|
77
|
-
@extensions[ext_key] && @extensions[ext_key][param_key]
|
78
|
-
end
|
79
|
-
|
80
|
-
# Namespaces used for parsing configuration XML
|
81
|
-
LTI_NAMESPACES = {
|
82
|
-
"xmlns" => 'http://www.imsglobal.org/xsd/imslticc_v1p0',
|
83
|
-
"blti" => 'http://www.imsglobal.org/xsd/imsbasiclti_v1p0',
|
84
|
-
"lticm" => 'http://www.imsglobal.org/xsd/imslticm_v1p0',
|
85
|
-
"lticp" => 'http://www.imsglobal.org/xsd/imslticp_v1p0',
|
86
|
-
}
|
87
|
-
|
88
|
-
# Parse tool configuration data out of the Common Cartridge LTI link XML
|
89
|
-
def process_xml(xml)
|
90
|
-
doc = REXML::Document.new xml
|
91
|
-
if root = REXML::XPath.first(doc, 'xmlns:cartridge_basiclti_link')
|
92
|
-
@title = get_node_text(root, 'blti:title')
|
93
|
-
@description = get_node_text(root, 'blti:description')
|
94
|
-
@launch_url = get_node_text(root, 'blti:launch_url')
|
95
|
-
@secure_launch_url = get_node_text(root, 'blti:secure_launch_url')
|
96
|
-
@icon = get_node_text(root, 'blti:icon')
|
97
|
-
@secure_icon = get_node_text(root, 'blti:secure_icon')
|
98
|
-
@cartridge_bundle = get_node_att(root, 'xmlns:cartridge_bundle', 'identifierref')
|
99
|
-
@cartridge_icon = get_node_att(root, 'xmlns:cartridge_icon', 'identifierref')
|
100
|
-
|
101
|
-
if vendor = REXML::XPath.first(root, 'blti:vendor')
|
102
|
-
@vendor_code = get_node_text(vendor, 'lticp:code')
|
103
|
-
@vendor_description = get_node_text(vendor, 'lticp:description')
|
104
|
-
@vendor_name = get_node_text(vendor, 'lticp:name')
|
105
|
-
@vendor_url = get_node_text(vendor, 'lticp:url')
|
106
|
-
@vendor_contact_email = get_node_text(vendor, '//lticp:contact/lticp:email')
|
107
|
-
@vendor_contact_name = get_node_text(vendor, '//lticp:contact/lticp:name')
|
108
|
-
end
|
109
|
-
|
110
|
-
if custom = REXML::XPath.first(root, 'blti:custom', LTI_NAMESPACES)
|
111
|
-
set_properties(@custom_params, custom)
|
112
|
-
end
|
113
|
-
|
114
|
-
REXML::XPath.each(root, 'blti:extensions', LTI_NAMESPACES) do |vendor_ext_node|
|
115
|
-
platform = vendor_ext_node.attributes['platform']
|
116
|
-
properties = {}
|
117
|
-
set_properties(properties, vendor_ext_node)
|
118
|
-
set_options(properties, vendor_ext_node)
|
119
|
-
self.set_ext_params(platform, properties)
|
120
|
-
end
|
121
|
-
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
# Generate XML from the current settings
|
126
|
-
def to_xml(opts = {})
|
127
|
-
raise IMS::LTI::InvalidLTIConfigError, "A launch url is required for an LTI configuration." unless self.launch_url || self.secure_launch_url
|
128
|
-
|
129
|
-
builder = Builder::XmlMarkup.new(:indent => opts[:indent] || 0)
|
130
|
-
builder.instruct!
|
131
|
-
builder.cartridge_basiclti_link("xmlns" => "http://www.imsglobal.org/xsd/imslticc_v1p0",
|
132
|
-
"xmlns:blti" => 'http://www.imsglobal.org/xsd/imsbasiclti_v1p0',
|
133
|
-
"xmlns:lticm" => 'http://www.imsglobal.org/xsd/imslticm_v1p0',
|
134
|
-
"xmlns:lticp" => 'http://www.imsglobal.org/xsd/imslticp_v1p0',
|
135
|
-
"xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
|
136
|
-
"xsi:schemaLocation" => "http://www.imsglobal.org/xsd/imslticc_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticc_v1p0.xsd http://www.imsglobal.org/xsd/imsbasiclti_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imsbasiclti_v1p0p1.xsd http://www.imsglobal.org/xsd/imslticm_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticm_v1p0.xsd http://www.imsglobal.org/xsd/imslticp_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticp_v1p0.xsd"
|
137
|
-
) do |blti_node|
|
138
|
-
|
139
|
-
%w{title description launch_url secure_launch_url icon secure_icon}.each do |key|
|
140
|
-
blti_node.blti key.to_sym, self.send(key) if self.send(key)
|
141
|
-
end
|
142
|
-
|
143
|
-
vendor_keys = %w{name code description url}
|
144
|
-
if vendor_keys.any?{|k|self.send("vendor_#{k}")} || vendor_contact_email
|
145
|
-
blti_node.blti :vendor do |v_node|
|
146
|
-
vendor_keys.each do |key|
|
147
|
-
v_node.lticp key.to_sym, self.send("vendor_#{key}") if self.send("vendor_#{key}")
|
148
|
-
end
|
149
|
-
if vendor_contact_email
|
150
|
-
v_node.lticp :contact do |c_node|
|
151
|
-
c_node.lticp :name, vendor_contact_name
|
152
|
-
c_node.lticp :email, vendor_contact_email
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
if !@custom_params.empty?
|
159
|
-
blti_node.tag!("blti:custom") do |custom_node|
|
160
|
-
@custom_params.keys.sort.each do |key|
|
161
|
-
val = @custom_params[key]
|
162
|
-
custom_node.lticm :property, val, 'name' => key
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
if !@extensions.empty?
|
168
|
-
@extensions.keys.sort.each do |ext_platform|
|
169
|
-
ext_params = @extensions[ext_platform]
|
170
|
-
blti_node.blti(:extensions, :platform => ext_platform) do |ext_node|
|
171
|
-
ext_params.keys.sort.each do |key|
|
172
|
-
nest_xml(ext_node, key, ext_params[key])
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
blti_node.cartridge_bundle(:identifierref => @cartridge_bundle) if @cartridge_bundle
|
179
|
-
blti_node.cartridge_icon(:identifierref => @cartridge_icon) if @cartridge_icon
|
180
|
-
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
private
|
185
|
-
|
186
|
-
def nest_xml(ext_node, key, value)
|
187
|
-
if value.is_a?(Hash)
|
188
|
-
ext_node.lticm(:options, :name => key) do |type_node|
|
189
|
-
value.keys.sort.each do |sub_key|
|
190
|
-
nest_xml(type_node, sub_key, value[sub_key])
|
191
|
-
end
|
192
|
-
end
|
193
|
-
else
|
194
|
-
ext_node.lticm :property, value, 'name' => key
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
def get_node_text(node, path)
|
199
|
-
if val = REXML::XPath.first(node, path, LTI_NAMESPACES)
|
200
|
-
val.text
|
201
|
-
else
|
202
|
-
nil
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
def get_node_att(node, path, att)
|
207
|
-
if val = REXML::XPath.first(node, path, LTI_NAMESPACES)
|
208
|
-
val.attributes[att]
|
209
|
-
else
|
210
|
-
nil
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
def set_properties(hash, node)
|
215
|
-
REXML::XPath.each(node, 'lticm:property', LTI_NAMESPACES) do |prop|
|
216
|
-
hash[prop.attributes['name']] = prop.text
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
def set_options(hash, node)
|
221
|
-
REXML::XPath.each(node, 'lticm:options', LTI_NAMESPACES) do |options_node|
|
222
|
-
opt_name = options_node.attributes['name']
|
223
|
-
options = {}
|
224
|
-
set_properties(options, options_node)
|
225
|
-
set_options(options, options_node)
|
226
|
-
hash[opt_name] = options
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
end
|
231
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
module IMS::LTI
|
2
|
-
# Class for implementing an LTI Tool Consumer
|
3
|
-
class ToolConsumer < ToolBase
|
4
|
-
attr_accessor :launch_url, :timestamp, :nonce
|
5
|
-
|
6
|
-
# Create a new ToolConsumer
|
7
|
-
#
|
8
|
-
# @param consumer_key [String] The OAuth consumer key
|
9
|
-
# @param consumer_secret [String] The OAuth consumer secret
|
10
|
-
# @param params [Hash] Set the launch parameters as described in LaunchParams
|
11
|
-
def initialize(consumer_key, consumer_secret, params={})
|
12
|
-
super(consumer_key, consumer_secret, params)
|
13
|
-
@launch_url = params['launch_url']
|
14
|
-
end
|
15
|
-
|
16
|
-
def process_post_request(post_request)
|
17
|
-
request = extend_outcome_request(OutcomeRequest.new)
|
18
|
-
request.process_post_request(post_request)
|
19
|
-
end
|
20
|
-
|
21
|
-
# Set launch data from a ToolConfig
|
22
|
-
#
|
23
|
-
# @param config [ToolConfig]
|
24
|
-
def set_config(config)
|
25
|
-
@launch_url ||= config.secure_launch_url
|
26
|
-
@launch_url ||= config.launch_url
|
27
|
-
# any parameters already set will take priority
|
28
|
-
@custom_params = config.custom_params.merge(@custom_params)
|
29
|
-
end
|
30
|
-
|
31
|
-
# Check if the required parameters for a tool launch are set
|
32
|
-
def has_required_params?
|
33
|
-
@consumer_key && @consumer_secret && @resource_link_id && @launch_url
|
34
|
-
end
|
35
|
-
|
36
|
-
# Generate the launch data including the necessary OAuth information
|
37
|
-
#
|
38
|
-
#
|
39
|
-
def generate_launch_data
|
40
|
-
raise IMS::LTI::InvalidLTIConfigError, "Not all required params set for tool launch" unless has_required_params?
|
41
|
-
|
42
|
-
params = self.to_params
|
43
|
-
params['lti_version'] ||= 'LTI-1p0'
|
44
|
-
params['lti_message_type'] ||= 'basic-lti-launch-request'
|
45
|
-
uri = URI.parse(@launch_url)
|
46
|
-
|
47
|
-
if uri.port == uri.default_port
|
48
|
-
host = uri.host
|
49
|
-
else
|
50
|
-
host = "#{uri.host}:#{uri.port}"
|
51
|
-
end
|
52
|
-
|
53
|
-
consumer = OAuth::Consumer.new(@consumer_key, @consumer_secret, {
|
54
|
-
:site => "#{uri.scheme}://#{host}",
|
55
|
-
:signature_method => "HMAC-SHA1"
|
56
|
-
})
|
57
|
-
|
58
|
-
path = uri.path
|
59
|
-
path = '/' if path.empty?
|
60
|
-
if uri.query && uri.query != ''
|
61
|
-
CGI.parse(uri.query).each do |query_key, query_values|
|
62
|
-
unless params[query_key]
|
63
|
-
params[query_key] = query_values.first
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
options = {
|
68
|
-
:scheme => 'body',
|
69
|
-
:timestamp => @timestamp,
|
70
|
-
:nonce => @nonce
|
71
|
-
}
|
72
|
-
request = consumer.create_signed_request(:post, path, nil, options, params)
|
73
|
-
|
74
|
-
# the request is made by a html form in the user's browser, so we
|
75
|
-
# want to revert the escapage and return the hash of post parameters ready
|
76
|
-
# for embedding in a html view
|
77
|
-
hash = {}
|
78
|
-
request.body.split(/&/).each do |param|
|
79
|
-
key, val = param.split(/=/).map { |v| CGI.unescape(v) }
|
80
|
-
hash[key] = val
|
81
|
-
end
|
82
|
-
hash
|
83
|
-
end
|
84
|
-
|
85
|
-
end
|
86
|
-
end
|
@@ -1,145 +0,0 @@
|
|
1
|
-
require 'cgi'
|
2
|
-
|
3
|
-
module IMS::LTI
|
4
|
-
|
5
|
-
# Class for implementing an LTI Tool Provider
|
6
|
-
#
|
7
|
-
# # Initialize TP object with OAuth creds and post parameters
|
8
|
-
# provider = IMS::LTI::ToolProvider.new(consumer_key, consumer_secret, params)
|
9
|
-
#
|
10
|
-
# # Verify OAuth signature by passing the request object
|
11
|
-
# if provider.valid_request?(request)
|
12
|
-
# # success
|
13
|
-
# else
|
14
|
-
# # handle invalid OAuth
|
15
|
-
# end
|
16
|
-
#
|
17
|
-
# if provider.outcome_service?
|
18
|
-
# # ready for grade write-back
|
19
|
-
# else
|
20
|
-
# # normal tool launch without grade write-back
|
21
|
-
# end
|
22
|
-
#
|
23
|
-
# If the tool was launch as an outcome service you can POST a score to the TC.
|
24
|
-
# The POST calls all return an OutcomeResponse object which can be used to
|
25
|
-
# handle the response appropriately.
|
26
|
-
#
|
27
|
-
# # post the score to the TC, score should be a float >= 0.0 and <= 1.0
|
28
|
-
# # this returns an OutcomeResponse object
|
29
|
-
# response = provider.post_replace_result!(score)
|
30
|
-
# if response.success?
|
31
|
-
# # grade write worked
|
32
|
-
# elsif response.processing?
|
33
|
-
# elsif response.unsupported?
|
34
|
-
# else
|
35
|
-
# # failed
|
36
|
-
# end
|
37
|
-
|
38
|
-
class ToolProvider < ToolBase
|
39
|
-
# List of outcome requests made through this instance
|
40
|
-
|
41
|
-
include DeprecatedRoleChecks
|
42
|
-
include RoleChecks
|
43
|
-
attr_accessor :outcome_requests
|
44
|
-
# Message to be sent back to the ToolConsumer when the user returns
|
45
|
-
attr_accessor :lti_errormsg, :lti_errorlog, :lti_msg, :lti_log
|
46
|
-
|
47
|
-
# Create a new ToolProvider
|
48
|
-
#
|
49
|
-
# @param consumer_key [String] The OAuth consumer key
|
50
|
-
# @param consumer_secret [String] The OAuth consumer secret
|
51
|
-
# @param params [Hash] Set the launch parameters as described in LaunchParams
|
52
|
-
def initialize(consumer_key, consumer_secret, params={})
|
53
|
-
super(consumer_key, consumer_secret, params)
|
54
|
-
@outcome_requests = []
|
55
|
-
end
|
56
|
-
|
57
|
-
# Check if the request was an LTI Launch Request
|
58
|
-
def launch_request?
|
59
|
-
lti_message_type == 'basic-lti-launch-request'
|
60
|
-
end
|
61
|
-
|
62
|
-
# Check if the Tool Launch expects an Outcome Result
|
63
|
-
def outcome_service?
|
64
|
-
!!(lis_outcome_service_url && lis_result_sourcedid)
|
65
|
-
end
|
66
|
-
|
67
|
-
# Return the full, given, or family name if set
|
68
|
-
def username(default=nil)
|
69
|
-
lis_person_name_given || lis_person_name_family || lis_person_name_full || default
|
70
|
-
end
|
71
|
-
|
72
|
-
# POSTs the given score to the Tool Consumer with a replaceResult
|
73
|
-
#
|
74
|
-
# Creates a new OutcomeRequest object and stores it in @outcome_requests
|
75
|
-
#
|
76
|
-
# @return [OutcomeResponse] the response from the Tool Consumer
|
77
|
-
def post_replace_result!(score)
|
78
|
-
new_request.post_replace_result!(score)
|
79
|
-
end
|
80
|
-
|
81
|
-
# POSTs a delete request to the Tool Consumer
|
82
|
-
#
|
83
|
-
# Creates a new OutcomeRequest object and stores it in @outcome_requests
|
84
|
-
#
|
85
|
-
# @return [OutcomeResponse] the response from the Tool Consumer
|
86
|
-
def post_delete_result!
|
87
|
-
new_request.post_delete_result!
|
88
|
-
end
|
89
|
-
|
90
|
-
# POSTs the given score to the Tool Consumer with a replaceResult, the
|
91
|
-
# returned OutcomeResponse will have the score
|
92
|
-
#
|
93
|
-
# Creates a new OutcomeRequest object and stores it in @outcome_requests
|
94
|
-
#
|
95
|
-
# @return [OutcomeResponse] the response from the Tool Consumer
|
96
|
-
def post_read_result!
|
97
|
-
new_request.post_read_result!
|
98
|
-
end
|
99
|
-
|
100
|
-
# Returns the most recent OutcomeRequest
|
101
|
-
def last_outcome_request
|
102
|
-
@outcome_requests.last
|
103
|
-
end
|
104
|
-
|
105
|
-
# Convenience method for whether the last OutcomeRequest was successful
|
106
|
-
def last_outcome_success?
|
107
|
-
last_outcome_request && last_outcome_request.outcome_post_successful?
|
108
|
-
end
|
109
|
-
|
110
|
-
# If the Tool Consumer sent a URL for the user to return to this will add
|
111
|
-
# any set messages to the URL.
|
112
|
-
#
|
113
|
-
# Example:
|
114
|
-
#
|
115
|
-
# tc = IMS::LTI::tc.new
|
116
|
-
# tc.launch_presentation_return_url = "http://example.com/return"
|
117
|
-
# tc.lti_msg = "hi there"
|
118
|
-
# tc.lti_errorlog = "error happens"
|
119
|
-
#
|
120
|
-
# tc.build_return_url # => "http://example.com/return?lti_msg=hi%20there<i_errorlog=error%20happens"
|
121
|
-
def build_return_url
|
122
|
-
return nil unless launch_presentation_return_url
|
123
|
-
messages = []
|
124
|
-
%w{lti_errormsg lti_errorlog lti_msg lti_log}.each do |m|
|
125
|
-
if message = self.send(m)
|
126
|
-
messages << "#{m}=#{CGI.escape(message)}"
|
127
|
-
end
|
128
|
-
end
|
129
|
-
q_string = messages.any? ? ("?" + messages.join("&")) : ''
|
130
|
-
launch_presentation_return_url + q_string
|
131
|
-
end
|
132
|
-
|
133
|
-
private
|
134
|
-
|
135
|
-
def new_request
|
136
|
-
@outcome_requests << OutcomeRequest.new(:consumer_key => @consumer_key,
|
137
|
-
:consumer_secret => @consumer_secret,
|
138
|
-
:lis_outcome_service_url => lis_outcome_service_url,
|
139
|
-
:lis_result_sourcedid =>lis_result_sourcedid)
|
140
|
-
|
141
|
-
extend_outcome_request(@outcome_requests.last)
|
142
|
-
end
|
143
|
-
|
144
|
-
end
|
145
|
-
end
|