add file support to QTI imports, closes #3202
As a side-effect of this, quiz questions now get imported as HTML instead of plain text. Change-Id: I1f9ea57fbbaac7ca4905cff65bbe31bf11132ea3 Reviewed-on: https://gerrit.instructure.com/3147 Tested-by: Hudson <hudson@instructure.com> Reviewed-by: Bracken Mosbacker <bracken@instructure.com>
This commit is contained in:
parent
88fe989c7a
commit
68ec8d8c60
|
@ -47,7 +47,7 @@ class Canvas::Migrator
|
|||
raise "Migrator.export should have been overwritten by a sub-class"
|
||||
end
|
||||
|
||||
def unzip_archive
|
||||
def unzip_archive(do_delete_archive = true)
|
||||
begin
|
||||
command = Canvas::MigratorHelper.unzip_command(@archive_file_path, @unzipped_file_path)
|
||||
logger.debug "Running unzip command: #{command}"
|
||||
|
@ -64,7 +64,7 @@ class Canvas::Migrator
|
|||
message = "Error unzipping archive file: #{e.message}"
|
||||
add_error "qti", message, nil, e
|
||||
ensure
|
||||
delete_archive
|
||||
delete_archive if do_delete_archive
|
||||
end
|
||||
|
||||
false
|
||||
|
|
|
@ -22,6 +22,7 @@ module Canvas::MigratorHelper
|
|||
FULL_COURSE_JSON_FILENAME = "course_export.json"
|
||||
ERROR_FILENAME = "errors.json"
|
||||
OVERVIEW_JSON = "overview.json"
|
||||
ALL_FILES_ZIP = "all_files.zip"
|
||||
|
||||
COURSE_NO_COPY_ATTS = [:name, :course_code, :start_at, :conclude_at, :grading_standard_id, :hidden_tabs, :tab_configuration, :syllabus_body, :storage_quota]
|
||||
|
||||
|
@ -278,4 +279,4 @@ module Canvas::MigratorHelper
|
|||
# end
|
||||
@overview
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -62,11 +62,11 @@ class AssessmentItemConverter
|
|||
# The colons are replaced with dashes in the conversion from QTI 1.2
|
||||
@question[:migration_id] = @doc.at_css('assessmentitem @identifier').text.gsub(/:/, '-')
|
||||
if @doc.at_css('itembody').children.first.name == 'div' #because the selector 'itembody + div' doesn't work...
|
||||
@question[:question_text] = @doc.at_css('itembody div').text.strip.gsub(/ +/, " ")
|
||||
@question[:question_text] = @doc.at_css('itembody div').inner_html
|
||||
elsif @doc.at_css('itembody p')
|
||||
@question[:question_text] = @doc.at_css('itembody p').text.strip.gsub(/ +/, " ")
|
||||
@question[:question_text] = @doc.at_css('itembody p').inner_html
|
||||
elsif @doc.at_css('itembody')
|
||||
@question[:question_text] = @doc.at_css('itembody').text.strip.gsub(/ +/, " ")
|
||||
@question[:question_text] = @doc.at_css('itembody').inner_html
|
||||
end
|
||||
parse_instructure_metadata
|
||||
|
||||
|
|
|
@ -40,6 +40,19 @@ module Qti
|
|||
assessments
|
||||
end
|
||||
|
||||
def self.convert_files(manifest_path)
|
||||
attachments = []
|
||||
doc = Nokogiri::HTML(open(manifest_path))
|
||||
resource_nodes = doc.css('resource')
|
||||
doc.css('file').each do |file|
|
||||
# skip resource nodes, which are things like xml metadata and other sorts
|
||||
next if resource_nodes.any? { |node| node['href'] == file['href'] }
|
||||
# anything left is a file that needs to become an attachment on the context
|
||||
attachments << file['href']
|
||||
end
|
||||
attachments
|
||||
end
|
||||
|
||||
def self.get_conversion_command(out_dir, manifest_file)
|
||||
"\"#{@migration_executable}\" --ucvars --nogui --overwrite --cpout=#{out_dir.gsub(/ /, "\\ ")} #{manifest_file.gsub(/ /, "\\ ")} 2>&1"
|
||||
end
|
||||
|
|
|
@ -11,22 +11,29 @@ class QtiExporter < Canvas::Migrator
|
|||
super(settings, 'qti')
|
||||
@questions = {}
|
||||
@quizzes = {}
|
||||
@files = {}
|
||||
@converted = false
|
||||
@dest_dir_2_1 = nil
|
||||
@id_prepender = settings[:id_prepender]
|
||||
end
|
||||
|
||||
def export
|
||||
unzip_archive
|
||||
if QtiExporter.is_qti_2(File.join(@unzipped_file_path, MANIFEST_FILE))
|
||||
@dest_dir_2_1 = @unzipped_file_path
|
||||
@converted = true
|
||||
else
|
||||
run_qti_converter
|
||||
end
|
||||
unzip_archive(false)
|
||||
|
||||
@course[:assessment_questions] = convert_questions
|
||||
@course[:assessments] = convert_assessments(@course[:assessment_questions])
|
||||
begin
|
||||
if QtiExporter.is_qti_2(File.join(@unzipped_file_path, MANIFEST_FILE))
|
||||
@dest_dir_2_1 = @unzipped_file_path
|
||||
@converted = true
|
||||
else
|
||||
run_qti_converter
|
||||
end
|
||||
|
||||
@course[:assessment_questions] = convert_questions
|
||||
@course[:assessments] = convert_assessments(@course[:assessment_questions])
|
||||
@course[:file_map] = convert_files
|
||||
ensure
|
||||
delete_archive
|
||||
end
|
||||
|
||||
if settings[:apply_respondus_settings_file]
|
||||
apply_respondus_settings
|
||||
|
@ -109,6 +116,28 @@ class QtiExporter < Canvas::Migrator
|
|||
@quizzes
|
||||
end
|
||||
|
||||
def convert_files
|
||||
begin
|
||||
manifest_file = File.join(@dest_dir_2_1, MANIFEST_FILE)
|
||||
Qti.convert_files(manifest_file).each do |attachment|
|
||||
@files[attachment] = {
|
||||
'migration_id' => "#{@quizzes[:assessments].first.try(:[], :migration_id)}_#{attachment}",
|
||||
'path_name' => attachment,
|
||||
}
|
||||
end
|
||||
rescue => e
|
||||
message = "Error processing assessment QTI data: #{$!}: #{$!.backtrace.join("\n")}"
|
||||
add_error "qti_assessments", message, @files, e
|
||||
@files[:qti_error] = "#{$!}: #{$!.backtrace.join("\n")}"
|
||||
end
|
||||
unless @files.empty?
|
||||
# move the original archive to all_files.zip and it can be processed
|
||||
# during the import to grab attachments
|
||||
FileUtils.move(@archive_file_path, File.join(@base_export_dir, Canvas::MigratorHelper::ALL_FILES_ZIP))
|
||||
end
|
||||
@files
|
||||
end
|
||||
|
||||
def apply_respondus_settings
|
||||
settings_path = File.join(@unzipped_file_path, 'settings.xml')
|
||||
if File.file?(settings_path)
|
||||
|
|
Loading…
Reference in New Issue