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:
Brian Palmer 2011-04-19 13:51:42 -06:00
parent 88fe989c7a
commit 68ec8d8c60
5 changed files with 58 additions and 15 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)