canvas-lms/lib/cc/assignment_resources.rb

221 lines
9.4 KiB
Ruby

#
# Copyright (C) 2011 Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
module CC
module AssignmentResources
def add_assignments
Assignments::ScopedToUser.new(@course, @user).scope.
no_graded_quizzes_or_topics.each do |assignment|
next unless export_object?(assignment)
title = assignment.title || I18n.t('course_exports.unknown_titles.assignment', "Unknown assignment")
if !assignment.can_copy?(@user)
add_error(I18n.t('course_exports.errors.assignment_is_locked', "The assignment \"%{title}\" could not be copied because it is locked.", :title => title))
next
end
begin
add_assignment(assignment)
rescue
add_error(I18n.t('course_exports.errors.assignment', "The assignment \"%{title}\" failed to export", :title => title), $!)
end
end
end
VERSION_1_3 = Gem::Version.new('1.3')
def add_assignment(assignment)
migration_id = CCHelper.create_key(assignment)
lo_folder = File.join(@export_dir, migration_id)
FileUtils::mkdir_p lo_folder
file_name = "#{assignment.title.to_url}.html"
path = File.join(lo_folder, file_name)
html_path = File.join(migration_id, file_name)
# Write the assignment description as an .html file
# That way at least the content of the assignment will appear
# for agents that support neither CC 1.3 nor Canvas assignments
File.open(path, 'w') do |file|
file << @html_exporter.html_page(assignment.description || '', "Assignment: " + assignment.title)
end
if Gem::Version.new(@manifest.cc_version) >= VERSION_1_3
add_cc_assignment(assignment, migration_id, lo_folder, html_path)
else
add_canvas_assignment(assignment, migration_id, lo_folder, html_path)
end
end
def add_cc_assignment(assignment, migration_id, lo_folder, html_path)
File.open(File.join(lo_folder, CCHelper::ASSIGNMENT_XML), 'w') do |assignment_file|
document = Builder::XmlMarkup.new(:target => assignment_file, :indent => 2)
document.instruct!
document.assignment("identifier" => migration_id,
"xmlns" => CCHelper::ASSIGNMENT_NAMESPACE,
"xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
"xsi:schemaLocation"=> "#{CCHelper::ASSIGNMENT_NAMESPACE} #{CCHelper::ASSIGNMENT_XSD_URI}"
) do |a|
AssignmentResources.create_cc_assignment(a, assignment, migration_id, @html_exporter, @manifest)
end
end
xml_path = File.join(migration_id, CCHelper::ASSIGNMENT_XML)
@resources.resource(:identifier => migration_id,
:type => CCHelper::ASSIGNMENT_TYPE,
:href => xml_path
) do |res|
res.file(:href => xml_path)
end
@resources.resource(:identifier => migration_id + "_fallback",
:type => CCHelper::WEBCONTENT
) do |res|
res.tag!('cpx:variant', :identifier => migration_id + "_variant",
:identifierref => migration_id
) do |var|
var.tag!('cpx:metadata')
end
res.file(:href => html_path)
end
end
def add_canvas_assignment(assignment, migration_id, lo_folder, html_path)
assignment_file = File.new(File.join(lo_folder, CCHelper::ASSIGNMENT_SETTINGS), 'w')
document = Builder::XmlMarkup.new(:target=>assignment_file, :indent=>2)
document.instruct!
# Save all the meta-data into a canvas-specific xml schema
document.assignment("identifier" => migration_id,
"xmlns" => CCHelper::CANVAS_NAMESPACE,
"xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
"xsi:schemaLocation"=> "#{CCHelper::CANVAS_NAMESPACE} #{CCHelper::XSD_URI}"
) do |a|
AssignmentResources.create_canvas_assignment(a, assignment, @manifest)
end
assignment_file.close
@resources.resource(
:identifier => migration_id,
"type" => CCHelper::LOR,
:href => html_path
) do |res|
res.file(:href=>html_path)
res.file(:href=>File.join(migration_id, CCHelper::ASSIGNMENT_SETTINGS))
end
end
SUBMISSION_TYPE_MAP = {
"online_text_entry" => "html",
"online_url" => "url",
"online_upload" => "file"
}.freeze
def self.create_cc_assignment(node, assignment, migration_id, html_exporter, manifest = nil)
node.title(assignment.title)
node.text(html_exporter.html_content(assignment.description), texttype: 'text/html')
if assignment.points_possible
node.gradable(assignment.graded?, points_possible: assignment.points_possible)
else
node.gradable(assignment.graded?)
end
node.submission_formats do |fmt|
assignment.submission_types.split(',').each do |st|
if cc_type = SUBMISSION_TYPE_MAP[st]
fmt.format(:type => cc_type)
end
end
end
node.extensions do |ext|
ext.assignment("identifier" => migration_id + "_canvas",
"xmlns" => CCHelper::CANVAS_NAMESPACE,
"xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
"xsi:schemaLocation"=> "#{CCHelper::CANVAS_NAMESPACE} #{CCHelper::XSD_URI}"
) do |a|
AssignmentResources.create_canvas_assignment(a, assignment, manifest)
end
end
end
def self.create_canvas_assignment(node, assignment, manifest = nil)
node.title assignment.title
node.due_at CCHelper::ims_datetime(assignment.due_at) if assignment.due_at
node.lock_at CCHelper::ims_datetime(assignment.lock_at) if assignment.lock_at
node.unlock_at CCHelper::ims_datetime(assignment.unlock_at) if assignment.unlock_at
if manifest && manifest.try(:user).present?
node.module_locked assignment.locked_by_module_item?(manifest.user, true).present?
end
node.all_day_date CCHelper::ims_date(assignment.all_day_date) if assignment.all_day_date
node.peer_reviews_due_at CCHelper::ims_datetime(assignment.peer_reviews_due_at) if assignment.peer_reviews_due_at
node.assignment_group_identifierref CCHelper.create_key(assignment.assignment_group) if assignment.assignment_group && (!manifest || manifest.export_object?(assignment.assignment_group))
if assignment.grading_standard
if assignment.grading_standard.context == assignment.context
node.grading_standard_identifierref CCHelper.create_key(assignment.grading_standard) if (!manifest || manifest.export_object?(assignment.grading_standard))
else
node.grading_standard_external_identifier assignment.grading_standard.id
end
end
node.workflow_state assignment.workflow_state
if assignment.rubric
assoc = assignment.rubric_association
node.rubric_identifierref CCHelper.create_key(assignment.rubric)
if assignment.rubric && assignment.rubric.context != assignment.context
node.rubric_external_identifier assignment.rubric.id
end
node.rubric_use_for_grading assoc.use_for_grading
node.rubric_hide_score_total assoc.hide_score_total
if assoc.summary_data && assoc.summary_data[:saved_comments]
node.saved_rubric_comments do |sc_node|
assoc.summary_data[:saved_comments].each_pair do |key, vals|
vals.each do |val|
sc_node.comment(:criterion_id => key){|a|a << val}
end
end
end
end
end
node.quiz_identifierref CCHelper.create_key(assignment.quiz) if assignment.quiz
node.allowed_extensions assignment.allowed_extensions.join(',') unless assignment.allowed_extensions.blank?
node.has_group_category assignment.has_group_category?
node.group_category assignment.group_category.try :name if assignment.group_category
atts = [:points_possible, :grading_type,
:all_day, :submission_types, :position, :turnitin_enabled, :peer_review_count,
:peer_reviews, :automatic_peer_reviews, :moderated_grading,
:anonymous_peer_reviews, :grade_group_students_individually, :freeze_on_copy, :muted]
atts.each do |att|
node.tag!(att, assignment.send(att)) if assignment.send(att) == false || !assignment.send(att).blank?
end
if assignment.external_tool_tag
if (content = assignment.external_tool_tag.content) && content.is_a?(ContextExternalTool)
if content.context == assignment.context
node.external_tool_identifierref CCHelper.create_key(content)
else
node.external_tool_external_identifier content.id
end
end
node.external_tool_url assignment.external_tool_tag.url
node.external_tool_new_tab assignment.external_tool_tag.new_tab
end
end
end
end