ims-lti 1.2.4 → 2.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Changelog.txt +0 -0
- data/LICENSE.txt +22 -0
- data/README.md +25 -91
- data/lib/ims/lis/context_type/handles.rb +10 -0
- data/lib/ims/lis/context_type/urns.rb +10 -0
- data/lib/ims/lis/roles/context/handles.rb +60 -0
- data/lib/ims/lis/roles/context/urns.rb +60 -0
- data/lib/ims/lis/roles/institution/handles.rb +22 -0
- data/lib/ims/lis/roles/institution/urns.rb +22 -0
- data/lib/ims/lis/roles/system/handles.rb +15 -0
- data/lib/ims/lis/roles/system/urns.rb +15 -0
- data/lib/ims/lis/statuses/simple_names.rb +9 -0
- data/lib/ims/lis/statuses/uris.rb +9 -0
- data/lib/ims/lis.rb +14 -0
- data/lib/ims/lti/converters/time_json_converter.rb +13 -0
- data/lib/ims/lti/converters.rb +5 -0
- data/lib/ims/lti/errors/authentication_failed_error.rb +11 -0
- data/lib/ims/lti/errors/invalid_lti_config_error.rb +4 -0
- data/lib/ims/lti/errors/invalid_tool_consumer_profile.rb +4 -0
- data/lib/ims/lti/errors/tool_proxy_registration_error.rb +15 -0
- data/lib/ims/lti/errors.rb +8 -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/content_item_container.rb +14 -0
- data/lib/ims/lti/models/content_item_placement.rb +20 -0
- data/lib/ims/lti/models/content_items/content_item.rb +32 -0
- data/lib/ims/lti/models/content_items/file_item.rb +15 -0
- data/lib/ims/lti/models/content_items/lti_link_item.rb +14 -0
- data/lib/ims/lti/models/content_items.rb +7 -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/image.rb +7 -0
- data/lib/ims/lti/models/localized_name.rb +12 -0
- data/lib/ims/lti/models/localized_text.rb +12 -0
- data/lib/ims/lti/models/lti_model.rb +227 -0
- data/lib/ims/lti/models/membership_service/agent.rb +11 -0
- data/lib/ims/lti/models/membership_service/container.rb +11 -0
- data/lib/ims/lti/models/membership_service/context.rb +11 -0
- data/lib/ims/lti/models/membership_service/lis_membership_container.rb +13 -0
- data/lib/ims/lti/models/membership_service/lis_person.rb +13 -0
- data/lib/ims/lti/models/membership_service/membership.rb +14 -0
- data/lib/ims/lti/models/membership_service/organization.rb +14 -0
- data/lib/ims/lti/models/membership_service/page.rb +16 -0
- data/lib/ims/lti/models/membership_service/person.rb +13 -0
- data/lib/ims/lti/models/membership_service.rb +16 -0
- data/lib/ims/lti/models/message_handler.rb +14 -0
- data/lib/ims/lti/models/messages/basic_lti_launch_request.rb +24 -0
- data/lib/ims/lti/models/messages/content_item_selection.rb +32 -0
- data/lib/ims/lti/models/messages/content_item_selection_request.rb +26 -0
- data/lib/ims/lti/models/messages/message.rb +222 -0
- data/lib/ims/lti/models/messages/registration_request.rb +20 -0
- data/lib/ims/lti/models/messages/request_message.rb +12 -0
- data/lib/ims/lti/models/messages/tool_proxy_update_request.rb +15 -0
- data/lib/ims/lti/models/messages.rb +11 -0
- data/lib/ims/lti/models/parameter.rb +28 -0
- data/lib/ims/lti/models/product_family.rb +8 -0
- data/lib/ims/lti/models/product_info.rb +26 -0
- data/lib/ims/lti/models/product_instance.rb +10 -0
- data/lib/ims/lti/models/resource_handler.rb +22 -0
- data/lib/ims/lti/models/resource_type.rb +6 -0
- data/lib/ims/lti/models/rest_service.rb +30 -0
- data/lib/ims/lti/models/rest_service_profile.rb +15 -0
- data/lib/ims/lti/models/security_contract.rb +21 -0
- data/lib/ims/lti/models/security_profile.rb +10 -0
- data/lib/ims/lti/models/serializable.rb +12 -0
- data/lib/ims/lti/models/service_owner.rb +26 -0
- data/lib/ims/lti/models/service_provider.rb +11 -0
- data/lib/ims/lti/models/tool_consumer_profile.rb +45 -0
- data/lib/ims/lti/models/tool_profile.rb +35 -0
- data/lib/ims/lti/models/tool_proxy.rb +21 -0
- data/lib/ims/lti/models/tool_setting.rb +12 -0
- data/lib/ims/lti/models/tool_setting_container.rb +14 -0
- data/lib/ims/lti/models/vendor.rb +28 -0
- data/lib/ims/lti/models.rb +38 -0
- data/lib/ims/lti/serializers/base.rb +125 -0
- data/lib/ims/lti/serializers/membership_service/agent_serializer.rb +5 -0
- data/lib/ims/lti/serializers/membership_service/container_serializer.rb +6 -0
- data/lib/ims/lti/serializers/membership_service/context_serializer.rb +9 -0
- data/lib/ims/lti/serializers/membership_service/lis_membership_container_serializer.rb +9 -0
- data/lib/ims/lti/serializers/membership_service/lis_person_serializer.rb +11 -0
- data/lib/ims/lti/serializers/membership_service/membership_serializer.rb +7 -0
- data/lib/ims/lti/serializers/membership_service/organization_serializer.rb +8 -0
- data/lib/ims/lti/serializers/membership_service/page_serializer.rb +10 -0
- data/lib/ims/lti/serializers/membership_service/person_serializer.rb +8 -0
- data/lib/ims/lti/serializers/membership_service.rb +13 -0
- data/lib/ims/lti/serializers.rb +6 -0
- data/lib/ims/lti/services/authentication_service.rb +67 -0
- data/lib/ims/lti/services/message_authenticator.rb +80 -0
- data/lib/ims/lti/services/oauth2_client.rb +18 -0
- data/lib/ims/lti/{tool_config.rb → services/tool_config.rb} +26 -34
- data/lib/ims/lti/services/tool_consumer_profile_service.rb +16 -0
- data/lib/ims/lti/services/tool_proxy_registration_service.rb +84 -0
- data/lib/ims/lti/services/tool_proxy_validator.rb +182 -0
- data/lib/ims/lti/services.rb +11 -0
- data/lib/ims/lti/version.rb +5 -0
- data/lib/ims/lti.rb +13 -63
- data/lib/ims.rb +4 -1
- metadata +266 -44
- 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 -209
- data/lib/ims/lti/extensions/outcome_data.rb +0 -216
- 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_consumer.rb +0 -86
- data/lib/ims/lti/tool_provider.rb +0 -143
@@ -1,209 +0,0 @@
|
|
1
|
-
module IMS::LTI
|
2
|
-
module Extensions
|
3
|
-
|
4
|
-
# An LTI extension that adds support for content back to the consumer
|
5
|
-
#
|
6
|
-
# # Initialize TP object with OAuth creds and post parameters
|
7
|
-
# provider = IMS::LTI::ToolProvider.new(consumer_key, consumer_secret, params)
|
8
|
-
# # add extension
|
9
|
-
# provider.extend IMS::LTI::Extensions::Content::ToolProvider
|
10
|
-
#
|
11
|
-
# If the tool was launched as an content request and it supports the content extension
|
12
|
-
# you can redirect the user to the tool consumer using the return url helper methods.
|
13
|
-
# The tool consumer is then responsible for consuming the content.
|
14
|
-
#
|
15
|
-
# #Check if a certain response type is available
|
16
|
-
# if provider.accepts_url? do
|
17
|
-
# #Generate the URL for the user
|
18
|
-
# redirect provider.url_content_return_url(url)
|
19
|
-
# end
|
20
|
-
#
|
21
|
-
module Content
|
22
|
-
module ToolProvider
|
23
|
-
include IMS::LTI::Extensions::ExtensionBase
|
24
|
-
include Base
|
25
|
-
|
26
|
-
# a list of the supported outcome data types
|
27
|
-
def accepted_content_types
|
28
|
-
return @content_types if @content_types
|
29
|
-
@content_types = []
|
30
|
-
if val = @ext_params["content_return_types"]
|
31
|
-
@content_types = val.split(',').map {|i| i.to_sym}
|
32
|
-
end
|
33
|
-
|
34
|
-
@content_types
|
35
|
-
end
|
36
|
-
|
37
|
-
def accepted_file_extensions
|
38
|
-
return @file_extensions if @file_extensions
|
39
|
-
@file_extensions = []
|
40
|
-
if val = @ext_params["content_file_extensions"]
|
41
|
-
@file_extensions = val.split(',').map {|i| i.downcase.strip}
|
42
|
-
end
|
43
|
-
|
44
|
-
@file_extensions
|
45
|
-
end
|
46
|
-
|
47
|
-
def accepts_file?(file_name = nil)
|
48
|
-
accepted_content_types.include?(:file) &&
|
49
|
-
( file_name.nil? ||
|
50
|
-
accepted_file_extensions.empty? ||
|
51
|
-
accepted_file_extensions.any?{|ext| file_name.downcase[/#{ext}$/]} )
|
52
|
-
end
|
53
|
-
|
54
|
-
def accepts_url?
|
55
|
-
accepted_content_types.include?(:url)
|
56
|
-
end
|
57
|
-
|
58
|
-
def accepts_lti_launch_url?
|
59
|
-
accepted_content_types.include?(:lti_launch_url)
|
60
|
-
end
|
61
|
-
|
62
|
-
def accepts_image_url?
|
63
|
-
accepted_content_types.include?(:image_url)
|
64
|
-
end
|
65
|
-
|
66
|
-
def accepts_iframe?
|
67
|
-
accepted_content_types.include?(:iframe)
|
68
|
-
end
|
69
|
-
|
70
|
-
def accepts_oembed?
|
71
|
-
accepted_content_types.include?(:oembed)
|
72
|
-
end
|
73
|
-
|
74
|
-
def content_intended_use
|
75
|
-
@ext_params["content_intended_use"].to_sym if @ext_params["content_intended_use"]
|
76
|
-
end
|
77
|
-
|
78
|
-
# check if the content extension is supported
|
79
|
-
def accepts_content?
|
80
|
-
!!@ext_params["content_return_types"]
|
81
|
-
end
|
82
|
-
|
83
|
-
# check if the consumer accepts a given type of content
|
84
|
-
def accepts_content_type?(content_type)
|
85
|
-
accepted_content_types.include? content_type.to_sym
|
86
|
-
end
|
87
|
-
|
88
|
-
#check the use of the content
|
89
|
-
def is_content_for? (intended_use)
|
90
|
-
content_intended_use == intended_use
|
91
|
-
end
|
92
|
-
|
93
|
-
def content_return_url
|
94
|
-
@ext_params["content_return_url"]
|
95
|
-
end
|
96
|
-
|
97
|
-
#generates the return url for file submissions
|
98
|
-
def file_content_return_url(url, text, content_type = nil)
|
99
|
-
url = CGI::escape(url)
|
100
|
-
text = CGI::escape(text)
|
101
|
-
content_type = CGI::escape(content_type) if content_type
|
102
|
-
|
103
|
-
return_url = "#{content_return_url}?return_type=file&url=#{url}&text=#{text}"
|
104
|
-
return_url = "#{return_url}&content_type=#{content_type}" if content_type
|
105
|
-
|
106
|
-
return return_url
|
107
|
-
end
|
108
|
-
|
109
|
-
#generates the return url for url submissions
|
110
|
-
def url_content_return_url(url, title = nil, text = 'link', target = '_blank')
|
111
|
-
url = CGI::escape(url)
|
112
|
-
text = CGI::escape(text)
|
113
|
-
target = CGI::escape(target)
|
114
|
-
|
115
|
-
return_url = "#{content_return_url}?return_type=url&url=#{url}&text=#{text}&target=#{target}"
|
116
|
-
return_url = "#{return_url}&title=#{CGI::escape(title)}" if title
|
117
|
-
|
118
|
-
return return_url
|
119
|
-
end
|
120
|
-
|
121
|
-
#generates the return url for lti launch submissions
|
122
|
-
def lti_launch_content_return_url(url, text='link', title=nil)
|
123
|
-
url = CGI::escape(url)
|
124
|
-
text = CGI::escape(text)
|
125
|
-
|
126
|
-
return_url = "#{content_return_url}?return_type=lti_launch_url&url=#{url}&text=#{text}"
|
127
|
-
return_url = "#{return_url}&title=#{CGI::escape(title)}" if title
|
128
|
-
|
129
|
-
return return_url
|
130
|
-
end
|
131
|
-
|
132
|
-
#generates the return url for image submissions
|
133
|
-
def image_content_return_url(url, width, height, alt = '')
|
134
|
-
url = CGI::escape(url)
|
135
|
-
width = CGI::escape(width.to_s)
|
136
|
-
height = CGI::escape(height.to_s)
|
137
|
-
alt = CGI::escape(alt)
|
138
|
-
|
139
|
-
"#{content_return_url}?return_type=image_url&url=#{url}&width=#{width}&height=#{height}&alt=#{alt}"
|
140
|
-
end
|
141
|
-
|
142
|
-
#generates the return url for iframe submissions
|
143
|
-
def iframe_content_return_url(url, width, height, title = nil)
|
144
|
-
url = CGI::escape(url)
|
145
|
-
width = CGI::escape(width.to_s)
|
146
|
-
height = CGI::escape(height.to_s)
|
147
|
-
|
148
|
-
return_url = "#{content_return_url}?return_type=iframe&url=#{url}&width=#{width}&height=#{height}"
|
149
|
-
return_url = "#{return_url}&title=#{CGI::escape(title)}" if title
|
150
|
-
|
151
|
-
return return_url
|
152
|
-
end
|
153
|
-
|
154
|
-
#generates the return url for oembed submissions
|
155
|
-
def oembed_content_return_url(url, endpoint)
|
156
|
-
url = CGI::escape(url)
|
157
|
-
endpoint = CGI::escape(endpoint)
|
158
|
-
|
159
|
-
"#{content_return_url}?return_type=oembed&url=#{url}&endpoint=#{endpoint}"
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
module ToolConsumer
|
164
|
-
include IMS::LTI::Extensions::ExtensionBase
|
165
|
-
include Base
|
166
|
-
|
167
|
-
# a list of the content types accepted
|
168
|
-
#
|
169
|
-
# tc.add_content_return_types=(['url', 'text'])
|
170
|
-
# tc.add_content_return_types=("url,text")
|
171
|
-
def content_return_types=(val)
|
172
|
-
val = val.join(',') if val.is_a? Array
|
173
|
-
set_ext_param('content_return_types', val)
|
174
|
-
end
|
175
|
-
|
176
|
-
# a comma-separated string of the supported outcome data types
|
177
|
-
def content_return_types
|
178
|
-
get_ext_param('content_return_types')
|
179
|
-
end
|
180
|
-
|
181
|
-
def content_intended_use=(val)
|
182
|
-
set_ext_param('content_intended_use', val)
|
183
|
-
end
|
184
|
-
|
185
|
-
def content_intended_use
|
186
|
-
get_ext_param('content_intended_use')
|
187
|
-
end
|
188
|
-
|
189
|
-
# convenience method for setting support for homework content
|
190
|
-
def support_homework_content!
|
191
|
-
self.content_intended_use = 'homework'
|
192
|
-
self.content_return_types = 'file,url'
|
193
|
-
end
|
194
|
-
|
195
|
-
# convenience method for setting support for embed content
|
196
|
-
def support_embed_content!
|
197
|
-
self.content_intended_use = 'embed'
|
198
|
-
self.content_return_types = 'oembed,lti_launch_url,url,image_url,iframe'
|
199
|
-
end
|
200
|
-
|
201
|
-
# convenience method for setting support for navigation content
|
202
|
-
def support_navigation_content!
|
203
|
-
self.content_intended_use = 'navigation'
|
204
|
-
self.content_return_types = 'lti_launch_url'
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
@@ -1,216 +0,0 @@
|
|
1
|
-
module IMS::LTI
|
2
|
-
module Extensions
|
3
|
-
|
4
|
-
# An LTI extension that adds support for sending data back to the consumer
|
5
|
-
# in addition to the score.
|
6
|
-
#
|
7
|
-
# # Initialize TP object with OAuth creds and post parameters
|
8
|
-
# provider = IMS::LTI::ToolProvider.new(consumer_key, consumer_secret, params)
|
9
|
-
# # add extension
|
10
|
-
# provider.extend IMS::LTI::Extensions::OutcomeData::ToolProvider
|
11
|
-
#
|
12
|
-
# If the tool was launch as an outcome service and it supports the data extension
|
13
|
-
# you can POST a score to the TC.
|
14
|
-
# The POST calls all return an OutcomeResponse object which can be used to
|
15
|
-
# handle the response appropriately.
|
16
|
-
#
|
17
|
-
# # post the score to the TC, score should be a float >= 0.0 and <= 1.0
|
18
|
-
# # this returns an OutcomeResponse object
|
19
|
-
# if provider.accepts_outcome_text?
|
20
|
-
# response = provider.post_extended_replace_result!(score: score, text: "submission text")
|
21
|
-
# else
|
22
|
-
# response = provider.post_replace_result!(score)
|
23
|
-
# end
|
24
|
-
# if response.success?
|
25
|
-
# # grade write worked
|
26
|
-
# elsif response.processing?
|
27
|
-
# elsif response.unsupported?
|
28
|
-
# else
|
29
|
-
# # failed
|
30
|
-
# end
|
31
|
-
module OutcomeData
|
32
|
-
|
33
|
-
#IMS::LTI::Extensions::OutcomeData::ToolProvider
|
34
|
-
module Base
|
35
|
-
def outcome_request_extensions
|
36
|
-
super + [IMS::LTI::Extensions::OutcomeData::OutcomeRequest]
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
module ToolProvider
|
41
|
-
include IMS::LTI::Extensions::ExtensionBase
|
42
|
-
include Base
|
43
|
-
|
44
|
-
# a list of the supported outcome data types
|
45
|
-
def accepted_outcome_types
|
46
|
-
return @outcome_types if @outcome_types
|
47
|
-
@outcome_types = []
|
48
|
-
if val = @ext_params["outcome_data_values_accepted"]
|
49
|
-
@outcome_types = val.split(',')
|
50
|
-
end
|
51
|
-
|
52
|
-
@outcome_types
|
53
|
-
end
|
54
|
-
|
55
|
-
# check if the outcome data extension is supported
|
56
|
-
def accepts_outcome_data?
|
57
|
-
!!@ext_params["outcome_data_values_accepted"]
|
58
|
-
end
|
59
|
-
|
60
|
-
# check if the consumer accepts text as outcome data
|
61
|
-
def accepts_outcome_text?
|
62
|
-
accepted_outcome_types.member?("text")
|
63
|
-
end
|
64
|
-
|
65
|
-
# check if the consumer accepts a url as outcome data
|
66
|
-
def accepts_outcome_url?
|
67
|
-
accepted_outcome_types.member?("url")
|
68
|
-
end
|
69
|
-
|
70
|
-
# check if the consumer accepts a submitted at date as outcome data
|
71
|
-
def accepts_submitted_at?
|
72
|
-
accepted_outcome_types.member?("submitted_at")
|
73
|
-
end
|
74
|
-
|
75
|
-
def accepts_outcome_lti_launch_url?
|
76
|
-
accepted_outcome_types.member?("lti_launch_url")
|
77
|
-
end
|
78
|
-
|
79
|
-
def accepts_outcome_result_total_score?
|
80
|
-
!!@ext_params["outcome_result_total_score_accepted"]
|
81
|
-
end
|
82
|
-
|
83
|
-
# POSTs the given score to the Tool Consumer with a replaceResult and
|
84
|
-
# adds the specified data. The data hash can have the keys "text", "cdata_text", "url", "submitted_at" or "lti_launch_url"
|
85
|
-
#
|
86
|
-
# If both cdata_text and text are sent, cdata_text will be used
|
87
|
-
#
|
88
|
-
# If score is nil, the replace result XML will not contain a resultScore node
|
89
|
-
#
|
90
|
-
# Creates a new OutcomeRequest object and stores it in @outcome_requests
|
91
|
-
#
|
92
|
-
# @return [OutcomeResponse] the response from the Tool Consumer
|
93
|
-
# @deprecated Use #post_extended_replace_result! instead
|
94
|
-
def post_replace_result_with_data!(score = nil, data={})
|
95
|
-
data[:score] = score if score
|
96
|
-
post_extended_replace_result!(data)
|
97
|
-
end
|
98
|
-
|
99
|
-
# POSTs the given score to the Tool Consumer with a replaceResult and
|
100
|
-
# adds the specified data. The options hash can have the keys
|
101
|
-
# :text, :cdata_text, :url, :submitted_at, :lti_launch_url, :score, or :total_score
|
102
|
-
#
|
103
|
-
# If both cdata_text and text are sent, cdata_text will be used
|
104
|
-
# If both total_score and score are sent, total_score will be used
|
105
|
-
# If score is nil, the replace result XML will not contain a resultScore node
|
106
|
-
#
|
107
|
-
# Creates a new OutcomeRequest object and stores it in @outcome_requests
|
108
|
-
#
|
109
|
-
# @return [OutcomeResponse] the response from the Tool Consumer
|
110
|
-
def post_extended_replace_result!(options = {})
|
111
|
-
opts = {}
|
112
|
-
options.each {|k,v| opts[k.to_sym] = v}
|
113
|
-
|
114
|
-
req = new_request
|
115
|
-
req.outcome_cdata_text = opts[:cdata_text]
|
116
|
-
req.outcome_text = opts[:text]
|
117
|
-
req.outcome_url = opts[:url]
|
118
|
-
req.submitted_at = opts[:submitted_at]
|
119
|
-
req.outcome_lti_launch_url = opts[:lti_launch_url]
|
120
|
-
req.total_score = opts[:total_score]
|
121
|
-
req.post_replace_result!(opts[:score])
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
module ToolConsumer
|
126
|
-
include IMS::LTI::Extensions::ExtensionBase
|
127
|
-
include Base
|
128
|
-
|
129
|
-
OUTCOME_DATA_TYPES = %w{text url lti_launch_url submitted_at}
|
130
|
-
|
131
|
-
# a list of the outcome data types accepted, currently only 'url', 'submitted_at' and
|
132
|
-
# 'text' are valid
|
133
|
-
#
|
134
|
-
# tc.outcome_data_values_accepted(['url', 'text'])
|
135
|
-
# tc.outcome_data_valued_accepted("url,text")
|
136
|
-
def outcome_data_values_accepted=(val)
|
137
|
-
if val.is_a? Array
|
138
|
-
val = val.join(',')
|
139
|
-
end
|
140
|
-
|
141
|
-
set_ext_param('outcome_data_values_accepted', val)
|
142
|
-
end
|
143
|
-
|
144
|
-
# a comma-separated string of the supported outcome data types
|
145
|
-
def outcome_data_values_accepted
|
146
|
-
get_ext_param('outcome_data_values_accepted')
|
147
|
-
end
|
148
|
-
|
149
|
-
# convenience method for setting support for all current outcome data types
|
150
|
-
def support_outcome_data!
|
151
|
-
self.outcome_data_values_accepted = OUTCOME_DATA_TYPES
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
module OutcomeRequest
|
156
|
-
include IMS::LTI::Extensions::ExtensionBase
|
157
|
-
include Base
|
158
|
-
|
159
|
-
attr_accessor :outcome_text, :outcome_url, :submitted_at, :outcome_lti_launch_url, :outcome_cdata_text, :total_score
|
160
|
-
|
161
|
-
def result_values(node)
|
162
|
-
super
|
163
|
-
|
164
|
-
if total_score
|
165
|
-
node.resultTotalScore do |res_total_score|
|
166
|
-
res_total_score.language "en" # 'en' represents the format of the number
|
167
|
-
res_total_score.textString total_score.to_s
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
if outcome_text || outcome_url || outcome_cdata_text || outcome_lti_launch_url
|
172
|
-
node.resultData do |res_data|
|
173
|
-
if outcome_cdata_text
|
174
|
-
res_data.text {
|
175
|
-
res_data.cdata! outcome_cdata_text
|
176
|
-
}
|
177
|
-
elsif outcome_text
|
178
|
-
res_data.text outcome_text
|
179
|
-
elsif outcome_lti_launch_url
|
180
|
-
res_data.ltiLaunchUrl outcome_lti_launch_url
|
181
|
-
end
|
182
|
-
res_data.url outcome_url if outcome_url
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
def details(node)
|
188
|
-
super
|
189
|
-
return unless has_details_data?
|
190
|
-
|
191
|
-
node.submittedAt submitted_at
|
192
|
-
end
|
193
|
-
|
194
|
-
def score
|
195
|
-
total_score ? nil : @score
|
196
|
-
end
|
197
|
-
|
198
|
-
def has_result_data?
|
199
|
-
!!outcome_text || !!outcome_url || !!outcome_lti_launch_url || !!outcome_cdata_text || !!total_score || super
|
200
|
-
end
|
201
|
-
|
202
|
-
def has_details_data?
|
203
|
-
!!submitted_at
|
204
|
-
end
|
205
|
-
|
206
|
-
def extention_process_xml(doc)
|
207
|
-
super
|
208
|
-
@outcome_text = doc.get_text("//resultRecord/result/resultData/text")
|
209
|
-
@outcome_url = doc.get_text("//resultRecord/result/resultData/url")
|
210
|
-
@outcome_lti_launch_url = doc.get_text("//resultRecord/result/resultData/ltiLaunchUrl")
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|
data/lib/ims/lti/extensions.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
|
2
|
-
module IMS::LTI
|
3
|
-
module Extensions
|
4
|
-
|
5
|
-
# Base functionality for creating LTI extension modules
|
6
|
-
# See the test for this class for a simple example of how to create an extension module
|
7
|
-
module Base
|
8
|
-
def outcome_request_extensions
|
9
|
-
[]
|
10
|
-
end
|
11
|
-
|
12
|
-
def outcome_response_extensions
|
13
|
-
[]
|
14
|
-
end
|
15
|
-
|
16
|
-
def extend_outcome_request(request)
|
17
|
-
outcome_request_extensions.each do |ext|
|
18
|
-
request.extend(ext)
|
19
|
-
end
|
20
|
-
request
|
21
|
-
end
|
22
|
-
|
23
|
-
def extend_outcome_response(response)
|
24
|
-
outcome_response_extensions.each do |ext|
|
25
|
-
response.extend(ext)
|
26
|
-
end
|
27
|
-
response
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
module ExtensionBase
|
32
|
-
def outcome_request_extensions
|
33
|
-
super
|
34
|
-
end
|
35
|
-
|
36
|
-
def outcome_response_extensions
|
37
|
-
super
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
require 'ims/lti/extensions/outcome_data'
|
44
|
-
require 'ims/lti/extensions/content'
|
45
|
-
require 'ims/lti/extensions/canvas'
|
@@ -1,166 +0,0 @@
|
|
1
|
-
module IMS::LTI
|
2
|
-
# Mixin module for managing LTI Launch Data
|
3
|
-
#
|
4
|
-
# Launch data documentation:
|
5
|
-
# http://www.imsglobal.org/lti/v1p1pd/ltiIMGv1p1pd.html#_Toc309649684
|
6
|
-
module LaunchParams
|
7
|
-
|
8
|
-
# List of the standard launch parameters for an LTI launch
|
9
|
-
LAUNCH_DATA_PARAMETERS = %w{
|
10
|
-
accept_media_types
|
11
|
-
accept_multiple
|
12
|
-
accept_presentation_document_targets
|
13
|
-
accept_unsigned
|
14
|
-
auto_create
|
15
|
-
content_item_return_url
|
16
|
-
context_id
|
17
|
-
context_label
|
18
|
-
context_title
|
19
|
-
context_type
|
20
|
-
launch_presentation_css_url
|
21
|
-
launch_presentation_document_target
|
22
|
-
launch_presentation_height
|
23
|
-
launch_presentation_locale
|
24
|
-
launch_presentation_return_url
|
25
|
-
launch_presentation_width
|
26
|
-
lis_course_offering_sourcedid
|
27
|
-
lis_course_section_sourcedid
|
28
|
-
lis_outcome_service_url
|
29
|
-
lis_person_contact_email_primary
|
30
|
-
lis_person_name_family
|
31
|
-
lis_person_name_full
|
32
|
-
lis_person_name_given
|
33
|
-
lis_person_sourcedid
|
34
|
-
lis_result_sourcedid
|
35
|
-
lti_message_type
|
36
|
-
lti_version
|
37
|
-
oauth_callback
|
38
|
-
oauth_consumer_key
|
39
|
-
oauth_nonce
|
40
|
-
oauth_signature
|
41
|
-
oauth_signature_method
|
42
|
-
oauth_timestamp
|
43
|
-
oauth_version
|
44
|
-
resource_link_description
|
45
|
-
resource_link_id
|
46
|
-
resource_link_title
|
47
|
-
roles
|
48
|
-
role_scope_mentor
|
49
|
-
tool_consumer_info_product_family_code
|
50
|
-
tool_consumer_info_version
|
51
|
-
tool_consumer_instance_contact_email
|
52
|
-
tool_consumer_instance_description
|
53
|
-
tool_consumer_instance_guid
|
54
|
-
tool_consumer_instance_name
|
55
|
-
tool_consumer_instance_url
|
56
|
-
user_id
|
57
|
-
user_image
|
58
|
-
}
|
59
|
-
|
60
|
-
LAUNCH_DATA_PARAMETERS.each { |p| attr_accessor p }
|
61
|
-
|
62
|
-
# Hash of custom parameters, the keys will be prepended with "custom_" at launch
|
63
|
-
attr_accessor :custom_params
|
64
|
-
|
65
|
-
# Hash of extension parameters, the keys will be prepended with "ext_" at launch
|
66
|
-
attr_accessor :ext_params
|
67
|
-
|
68
|
-
# Hash of parameters to add to the launch. These keys will not be prepended
|
69
|
-
# with any value at launch
|
70
|
-
attr_accessor :non_spec_params
|
71
|
-
|
72
|
-
# Set the roles for the current launch
|
73
|
-
#
|
74
|
-
# Full list of roles can be found here:
|
75
|
-
# http://www.imsglobal.org/LTI/v1p1pd/ltiIMGv1p1pd.html#_Toc309649700
|
76
|
-
#
|
77
|
-
# LIS roles include:
|
78
|
-
# * Student
|
79
|
-
# * Faculty
|
80
|
-
# * Member
|
81
|
-
# * Learner
|
82
|
-
# * Instructor
|
83
|
-
# * Mentor
|
84
|
-
# * Staff
|
85
|
-
# * Alumni
|
86
|
-
# * ProspectiveStudent
|
87
|
-
# * Guest
|
88
|
-
# * Other
|
89
|
-
# * Administrator
|
90
|
-
# * Observer
|
91
|
-
# * None
|
92
|
-
#
|
93
|
-
# @param roles_list [String,Array] An Array or comma-separated String of roles
|
94
|
-
def roles=(roles_list)
|
95
|
-
if roles_list
|
96
|
-
if roles_list.is_a?(Array)
|
97
|
-
@roles = roles_list
|
98
|
-
else
|
99
|
-
@roles = roles_list.split(",")
|
100
|
-
end
|
101
|
-
else
|
102
|
-
@roles = nil
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def set_custom_param(key, val)
|
107
|
-
@custom_params[key] = val
|
108
|
-
end
|
109
|
-
|
110
|
-
def get_custom_param(key)
|
111
|
-
@custom_params[key]
|
112
|
-
end
|
113
|
-
|
114
|
-
def set_non_spec_param(key, val)
|
115
|
-
@non_spec_params[key] = val
|
116
|
-
end
|
117
|
-
|
118
|
-
def get_non_spec_param(key)
|
119
|
-
@non_spec_params[key]
|
120
|
-
end
|
121
|
-
|
122
|
-
def set_ext_param(key, val)
|
123
|
-
@ext_params[key] = val
|
124
|
-
end
|
125
|
-
|
126
|
-
def get_ext_param(key)
|
127
|
-
@ext_params[key]
|
128
|
-
end
|
129
|
-
|
130
|
-
# Create a new Hash with all launch data. Custom/Extension keys will have the
|
131
|
-
# appropriate value prepended to the keys and the roles are set as a comma
|
132
|
-
# separated String
|
133
|
-
def to_params
|
134
|
-
params = launch_data_hash.merge(add_key_prefix(@custom_params, 'custom')).merge(add_key_prefix(@ext_params, 'ext')).merge(@non_spec_params)
|
135
|
-
params["roles"] = @roles.join(",") if @roles
|
136
|
-
params
|
137
|
-
end
|
138
|
-
|
139
|
-
# Populates the launch data from a Hash
|
140
|
-
#
|
141
|
-
# Only keys in LAUNCH_DATA_PARAMETERS and that start with 'custom_' or 'ext_'
|
142
|
-
# will be pulled from the provided Hash
|
143
|
-
def process_params(params)
|
144
|
-
params.each_pair do |key, val|
|
145
|
-
if LAUNCH_DATA_PARAMETERS.member?(key)
|
146
|
-
self.send("#{key}=", val)
|
147
|
-
elsif key =~ /\Acustom_(.+)\Z/
|
148
|
-
@custom_params[$1] = val
|
149
|
-
elsif key =~ /\Aext_(.+)\Z/
|
150
|
-
@ext_params[$1] = val
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
private
|
156
|
-
|
157
|
-
def launch_data_hash
|
158
|
-
LAUNCH_DATA_PARAMETERS.inject({}) { |h, k| h[k] = self.send(k) if self.send(k); h }
|
159
|
-
end
|
160
|
-
|
161
|
-
def add_key_prefix(hash, prefix)
|
162
|
-
hash.keys.inject({}) { |h, k| h["#{prefix}_#{k}"] = hash[k]; h }
|
163
|
-
end
|
164
|
-
|
165
|
-
end
|
166
|
-
end
|