migration refactor: account question banks import
test plan: * course migration regressions (canvas cc, course copy) * in addition: use the content migrations api to queue a content migration for an account ("/accounts/:account_id/content_migrations") to import a qti/cc package. * confirm that the question banks from the package that would have been normally imported into a course are now imported into the account closes #CNVS-12529 Change-Id: I2ef306341d2f7defe03c63a981679a3987f1aaa0 Reviewed-on: https://gerrit.instructure.com/34303 Tested-by: Jenkins <jenkins@instructure.com> Reviewed-by: Jeremy Stanley <jeremy@instructure.com> QA-Review: Clare Strong <clare@instructure.com> Product-Review: James Williams <jamesw@instructure.com>
This commit is contained in:
parent
9b28f26546
commit
2ba4531f73
|
@ -191,9 +191,7 @@ class ContentMigrationsController < ApplicationController
|
|||
end
|
||||
|
||||
def migration_plugin_supported?(plugin)
|
||||
# FIXME most migration types don't support Account either, but plugins that do would have to set additional_contexts
|
||||
# in order to not be broken by this
|
||||
@context.is_a?(Course) || @context.is_a?(Account) || Array(plugin.settings[:additional_contexts]).include?(@context.class.to_s)
|
||||
Array(plugin.settings && plugin.settings[:valid_contexts]).include?(@context.class.to_s)
|
||||
end
|
||||
private :migration_plugin_supported?
|
||||
|
||||
|
@ -446,7 +444,7 @@ class ContentMigrationsController < ApplicationController
|
|||
def find_migration_plugin(name)
|
||||
if name =~ /context_external_tool/
|
||||
plugin = Canvas::Plugin.new(name)
|
||||
plugin.meta[:settings] = {requires_file_upload: true, worker: 'CCWorker'}.with_indifferent_access
|
||||
plugin.meta[:settings] = {requires_file_upload: true, worker: 'CCWorker', valid_contexts: %w{Course}}.with_indifferent_access
|
||||
plugin
|
||||
else
|
||||
Canvas::Plugin.find(name)
|
||||
|
|
|
@ -76,6 +76,8 @@ class Account < ActiveRecord::Base
|
|||
has_many :roles
|
||||
has_many :all_roles, :class_name => 'Role', :foreign_key => 'root_account_id'
|
||||
has_many :progresses, :as => :context
|
||||
has_many :content_migrations, :as => :context
|
||||
|
||||
def inherited_assessment_question_banks(include_self = false, *additional_contexts)
|
||||
sql = []
|
||||
conds = []
|
||||
|
@ -1371,10 +1373,6 @@ class Account < ActiveRecord::Base
|
|||
false
|
||||
end
|
||||
|
||||
def import_from_migration(data, params, migration)
|
||||
Importers::AccountContentImporter.import_content(self, data, params, migration)
|
||||
end
|
||||
|
||||
def enable_fabulous_quizzes!
|
||||
root_account.enable_feature! :draft_state
|
||||
change_root_account_setting!(:enable_fabulous_quizzes, true)
|
||||
|
|
|
@ -263,13 +263,5 @@ class AssessmentQuestion < ActiveRecord::Base
|
|||
dup
|
||||
end
|
||||
|
||||
def self.process_migration(*args)
|
||||
Importers::AssessmentQuestionImporter.process_migration(*args)
|
||||
end
|
||||
|
||||
def self.import_from_migration(*args)
|
||||
Importers::AssessmentQuestionImporter.import_from_migration(*args)
|
||||
end
|
||||
|
||||
scope :active, where("assessment_questions.workflow_state<>'deleted'")
|
||||
end
|
||||
|
|
|
@ -1632,14 +1632,6 @@ class Assignment < ActiveRecord::Base
|
|||
end
|
||||
protected :readable_submission_type
|
||||
|
||||
def self.process_migration(*args)
|
||||
Importers::AssignmentImporter.process_migration(*args)
|
||||
end
|
||||
|
||||
def self.import_from_migration(*args)
|
||||
Importers::AssignmentImporter.import_from_migration(*args)
|
||||
end
|
||||
|
||||
def expects_submission?
|
||||
submission_types && submission_types.strip != "" && submission_types != "none" && submission_types != 'not_graded' && submission_types != "on_paper" && submission_types != 'external_tool'
|
||||
end
|
||||
|
|
|
@ -169,14 +169,6 @@ class AssignmentGroup < ActiveRecord::Base
|
|||
assignments.map(&:students).flatten
|
||||
end
|
||||
|
||||
def self.process_migration(*args)
|
||||
Importers::AssignmentGroupImporter.process_migration(*args)
|
||||
end
|
||||
|
||||
def self.import_from_migration(*args)
|
||||
Importers::AssignmentGroupImporter.import_from_migration(*args)
|
||||
end
|
||||
|
||||
def self.add_never_drop_assignment(group, assignment)
|
||||
rule = "never_drop:#{assignment.id}\n"
|
||||
if group.rules
|
||||
|
|
|
@ -514,14 +514,6 @@ class CalendarEvent < ActiveRecord::Base
|
|||
return CalendarEvent::IcalEvent.new(self).to_ics(in_own_calendar)
|
||||
end
|
||||
|
||||
def self.process_migration(*args)
|
||||
Importers::CalendarEventImporter.process_migration(*args)
|
||||
end
|
||||
|
||||
def self.import_from_migration(*args)
|
||||
Importers::CalendarEventImporter.import_from_migration(*args)
|
||||
end
|
||||
|
||||
def self.max_visible_calendars
|
||||
10
|
||||
end
|
||||
|
|
|
@ -33,7 +33,7 @@ class ContentMigration < ActiveRecord::Base
|
|||
DATE_FORMAT = "%m/%d/%Y"
|
||||
|
||||
attr_accessible :context, :migration_settings, :user, :source_course, :copy_options, :migration_type, :initiated_source
|
||||
attr_accessor :outcome_to_id_map
|
||||
attr_accessor :imported_migration_items, :outcome_to_id_map
|
||||
|
||||
EXPORTABLE_ATTRIBUTES = [
|
||||
:id, :context_id, :user_id, :workflow_state, :migration_settings, :started_at, :finished_at, :created_at, :updated_at, :context_type,
|
||||
|
@ -421,7 +421,7 @@ class ContentMigration < ActiveRecord::Base
|
|||
|
||||
migration_settings[:migration_ids_to_import] ||= {:copy=>{}}
|
||||
|
||||
self.context.import_from_migration(data, migration_settings[:migration_ids_to_import], self)
|
||||
Importers.content_importer_for(self.context_type).import_content(self.context, data, migration_settings[:migration_ids_to_import], self)
|
||||
|
||||
if !self.import_immediately?
|
||||
update_import_progress(100)
|
||||
|
@ -609,4 +609,12 @@ class ContentMigration < ActiveRecord::Base
|
|||
end
|
||||
hash
|
||||
end
|
||||
|
||||
def imported_migration_items
|
||||
@imported_migration_items ||= []
|
||||
end
|
||||
|
||||
def add_imported_item(item)
|
||||
self.imported_migration_items << item unless self.imported_migration_items.include?(item)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -160,7 +160,7 @@ class ContextExternalTool < ActiveRecord::Base
|
|||
if tool_hash[:error]
|
||||
@config_errors << [error_field, tool_hash[:error]]
|
||||
else
|
||||
Importers::ContextExternalToolImporter.import_from_migration(tool_hash, context, self)
|
||||
Importers::ContextExternalToolImporter.import_from_migration(tool_hash, context, nil, self)
|
||||
end
|
||||
self.name = real_name unless real_name.blank?
|
||||
rescue CC::Importer::BLTIConverter::CCImportError => e
|
||||
|
@ -537,14 +537,6 @@ class ContextExternalTool < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def self.process_migration(*args)
|
||||
Importers::ContextExternalToolImporter.process_migration(*args)
|
||||
end
|
||||
|
||||
def self.import_from_migration(*args)
|
||||
Importers::ContextExternalToolImporter.import_from_migration(*args)
|
||||
end
|
||||
|
||||
def resource_selection_settings
|
||||
settings[:resource_selection]
|
||||
end
|
||||
|
|
|
@ -524,14 +524,6 @@ class ContextModule < ActiveRecord::Base
|
|||
self.unlock_at && self.unlock_at > Time.now
|
||||
end
|
||||
|
||||
def self.process_migration(*args)
|
||||
Importers::ContextModuleImporter.process_migration(*args)
|
||||
end
|
||||
|
||||
def self.import_from_migration(*args)
|
||||
Importers::ContextModuleImporter.import_from_migration(*args)
|
||||
end
|
||||
|
||||
def migration_position
|
||||
@migration_position_counter ||= 0
|
||||
@migration_position_counter = @migration_position_counter + 1
|
||||
|
|
|
@ -182,7 +182,7 @@ class Course < ActiveRecord::Base
|
|||
has_many :page_views, :as => :context
|
||||
has_many :asset_user_accesses, :as => :context
|
||||
has_many :role_overrides, :as => :context
|
||||
has_many :content_migrations, :foreign_key => :context_id
|
||||
has_many :content_migrations, :as => :context
|
||||
has_many :content_exports
|
||||
has_many :course_imports
|
||||
has_many :alerts, :as => :context, :include => :criteria
|
||||
|
@ -1925,15 +1925,11 @@ class Course < ActiveRecord::Base
|
|||
Canvas::Plugin.value_to_boolean(val)
|
||||
end
|
||||
|
||||
def import_from_migration(data, params, migration)
|
||||
Importers::CourseContentImporter.import_content(self, data, params, migration)
|
||||
end
|
||||
|
||||
def add_migration_warning(message, exception='')
|
||||
self.content_migration.add_warning(message, exception) if self.content_migration
|
||||
end
|
||||
|
||||
attr_accessor :imported_migration_items, :full_migration_hash, :external_url_hash, :content_migration,
|
||||
attr_accessor :full_migration_hash, :external_url_hash, :content_migration,
|
||||
:folder_name_lookups, :attachment_path_id_lookup, :attachment_path_id_lookup_lower,
|
||||
:assignment_group_no_drop_assignments, :migration_results
|
||||
|
||||
|
|
|
@ -943,18 +943,6 @@ class DiscussionTopic < ActiveRecord::Base
|
|||
Rails.cache.delete(root_topic.locked_cache_key(user)) if root_topic
|
||||
end
|
||||
|
||||
def self.process_migration(data, migration)
|
||||
# TODO: access Importers::DiscussionTopic directly
|
||||
Importers::DiscussionTopicImporter.process_migration(data, migration)
|
||||
end
|
||||
|
||||
def self.import_from_migration(*args)
|
||||
# TODO: access Importers::DiscussionTopic directly
|
||||
# this class method will eventually go away. leaving now
|
||||
# for edge cases that may be using it.
|
||||
Importers::DiscussionTopicImporter.import_from_migration(*args)
|
||||
end
|
||||
|
||||
def self.podcast_elements(messages, context)
|
||||
attachment_ids = []
|
||||
media_object_ids = []
|
||||
|
|
|
@ -2,8 +2,12 @@ module Importers
|
|||
class AccountContentImporter < Importer
|
||||
|
||||
self.item_class = Account
|
||||
Importers.register_content_importer(self)
|
||||
|
||||
def self.import_content(account, data, params, migration)
|
||||
|
||||
migration.migration_settings[:import_quiz_questions_without_quiz] = true
|
||||
Importers::AssessmentQuestionImporter.process_migration(data, migration)
|
||||
Importers::LearningOutcomeImporter.process_migration(data, migration)
|
||||
|
||||
migration.progress = 100
|
||||
|
|
|
@ -53,7 +53,7 @@ module Importers
|
|||
question[:question_bank_name] ||= migration.question_bank_name
|
||||
question[:question_bank_name] ||= AssessmentQuestionBank.default_imported_title
|
||||
end
|
||||
if question[:assessment_question_migration_id]
|
||||
if question[:assessment_question_migration_id] && !migration.migration_settings[:import_quiz_questions_without_quiz]
|
||||
question_data[:qq_data][question['migration_id']] = question
|
||||
next
|
||||
end
|
||||
|
@ -81,7 +81,7 @@ module Importers
|
|||
end
|
||||
|
||||
begin
|
||||
question = self.import_from_migration(question, migration.context, question_bank)
|
||||
question = self.import_from_migration(question, migration.context, migration, question_bank)
|
||||
|
||||
# If the question appears to have links, we need to translate them so that file links point
|
||||
# to the AssessmentQuestion. Ideally we would just do this before saving the question, but
|
||||
|
@ -102,7 +102,7 @@ module Importers
|
|||
question_data
|
||||
end
|
||||
|
||||
def self.import_from_migration(hash, context, bank=nil, options={})
|
||||
def self.import_from_migration(hash, context, migration=nil, bank=nil, options={})
|
||||
hash = hash.with_indifferent_access
|
||||
if !bank
|
||||
hash[:question_bank_name] = nil if hash[:question_bank_name] == ''
|
||||
|
@ -120,8 +120,10 @@ module Importers
|
|||
end
|
||||
end
|
||||
hash.delete(:question_bank_migration_id) if hash.has_key?(:question_bank_migration_id)
|
||||
context.imported_migration_items << bank if context.imported_migration_items && !context.imported_migration_items.include?(bank)
|
||||
self.prep_for_import(hash, context)
|
||||
|
||||
migration.add_imported_item(bank) if migration
|
||||
self.prep_for_import(hash, context, migration)
|
||||
|
||||
if id = hash['assessment_question_id']
|
||||
AssessmentQuestion.where(id: id).update_all(name: hash[:question_name], question_data: hash.to_yaml,
|
||||
workflow_state: 'active', created_at: Time.now.utc, updated_at: Time.now.utc,
|
||||
|
@ -132,19 +134,19 @@ module Importers
|
|||
VALUES (?,?,'active',?,?,?,?)
|
||||
SQL
|
||||
id = AssessmentQuestion.connection.insert(query, "#{name} Create",
|
||||
AssessmentQuestion.primary_key, nil, AssessmentQuestion.sequence_name)
|
||||
AssessmentQuestion.primary_key, nil, AssessmentQuestion.sequence_name)
|
||||
hash['assessment_question_id'] = id
|
||||
end
|
||||
if context.respond_to?(:content_migration) && context.content_migration
|
||||
if migration
|
||||
hash[:missing_links].each do |field, missing_links|
|
||||
context.content_migration.add_missing_content_links(:class => self.to_s,
|
||||
:id => hash['assessment_question_id'], :field => field, :missing_links => missing_links,
|
||||
:url => "/#{context.class.to_s.underscore.pluralize}/#{context.id}/question_banks/#{bank.id}#question_#{hash['assessment_question_id']}_question_text")
|
||||
migration.add_missing_content_links(:class => self.to_s,
|
||||
:id => hash['assessment_question_id'], :field => field, :missing_links => missing_links,
|
||||
:url => "/#{context.class.to_s.underscore.pluralize}/#{context.id}/question_banks/#{bank.id}#question_#{hash['assessment_question_id']}_question_text")
|
||||
end
|
||||
if hash[:import_warnings]
|
||||
hash[:import_warnings].each do |warning|
|
||||
context.content_migration.add_warning(warning, {
|
||||
:fix_issue_html_url => "/#{context.class.to_s.underscore.pluralize}/#{context.id}/question_banks/#{bank.id}#question_#{hash['assessment_question_id']}_question_text"
|
||||
migration.add_warning(warning, {
|
||||
:fix_issue_html_url => "/#{context.class.to_s.underscore.pluralize}/#{context.id}/question_banks/#{bank.id}#question_#{hash['assessment_question_id']}_question_text"
|
||||
})
|
||||
end
|
||||
end
|
||||
|
@ -153,11 +155,11 @@ module Importers
|
|||
hash
|
||||
end
|
||||
|
||||
def self.prep_for_import(hash, context)
|
||||
def self.prep_for_import(hash, context, migration=nil)
|
||||
hash[:missing_links] = {}
|
||||
[:question_text, :correct_comments_html, :incorrect_comments_html, :neutral_comments_html, :more_comments_html].each do |field|
|
||||
hash[:missing_links][field] = []
|
||||
hash[field] = ImportedHtmlConverter.convert(hash[field], context, {:missing_links => hash[:missing_links][field], :remove_outer_nodes_if_one_child => true}) if hash[field].present?
|
||||
hash[field] = ImportedHtmlConverter.convert(hash[field], context, migration, {:missing_links => hash[:missing_links][field], :remove_outer_nodes_if_one_child => true}) if hash[field].present?
|
||||
end
|
||||
[:correct_comments, :incorrect_comments, :neutral_comments, :more_comments].each do |field|
|
||||
html_field = "#{field}_html".to_sym
|
||||
|
@ -168,7 +170,7 @@ module Importers
|
|||
hash[:answers].each_with_index do |answer, i|
|
||||
[:html, :comments_html, :left_html].each do |field|
|
||||
hash[:missing_links]["answer #{i} #{field}"] = []
|
||||
answer[field] = ImportedHtmlConverter.convert(answer[field], context, {:missing_links => hash[:missing_links]["answer #{i} #{field}"], :remove_outer_nodes_if_one_child => true}) if answer[field].present?
|
||||
answer[field] = ImportedHtmlConverter.convert(answer[field], context, migration, {:missing_links => hash[:missing_links]["answer #{i} #{field}"], :remove_outer_nodes_if_one_child => true}) if answer[field].present?
|
||||
end
|
||||
if answer[:comments].present? && answer[:comments] == answer[:comments_html]
|
||||
answer.delete(:comments_html)
|
||||
|
|
|
@ -9,7 +9,7 @@ module Importers
|
|||
groups.each do |group|
|
||||
if migration.import_object?("assignment_groups", group['migration_id'])
|
||||
begin
|
||||
import_from_migration(group, migration.context)
|
||||
import_from_migration(group, migration.context, migration)
|
||||
rescue
|
||||
migration.add_import_warning(t('#migration.assignment_group_type', "Assignment Group"), group[:title], $!)
|
||||
end
|
||||
|
@ -33,13 +33,13 @@ module Importers
|
|||
end
|
||||
end
|
||||
|
||||
def self.import_from_migration(hash, context, item=nil)
|
||||
def self.import_from_migration(hash, context, migration=nil, item=nil)
|
||||
hash = hash.with_indifferent_access
|
||||
return nil if hash[:migration_id] && hash[:assignment_groups_to_import] && !hash[:assignment_groups_to_import][hash[:migration_id]]
|
||||
item ||= AssignmentGroup.find_by_context_id_and_context_type_and_id(context.id, context.class.to_s, hash[:id])
|
||||
item ||= AssignmentGroup.find_by_context_id_and_context_type_and_migration_id(context.id, context.class.to_s, hash[:migration_id]) if hash[:migration_id]
|
||||
item ||= context.assignment_groups.new
|
||||
context.imported_migration_items << item if context.imported_migration_items && item.new_record?
|
||||
migration.add_imported_item(item) if migration && item.new_record?
|
||||
item.migration_id = hash[:migration_id]
|
||||
item.workflow_state = 'available' if item.deleted?
|
||||
item.name = hash[:title]
|
||||
|
|
|
@ -9,7 +9,7 @@ module Importers
|
|||
assignments.each do |assign|
|
||||
if migration.import_object?("assignments", assign['migration_id'])
|
||||
begin
|
||||
import_from_migration(assign, migration.context)
|
||||
import_from_migration(assign, migration.context, migration)
|
||||
rescue
|
||||
migration.add_import_warning(t('#migration.assignment_type', "Assignment"), assign[:title], $!)
|
||||
end
|
||||
|
@ -26,7 +26,7 @@ module Importers
|
|||
end
|
||||
end
|
||||
|
||||
def self.import_from_migration(hash, context, item=nil, quiz=nil)
|
||||
def self.import_from_migration(hash, context, migration=nil, item=nil, quiz=nil)
|
||||
hash = hash.with_indifferent_access
|
||||
return nil if hash[:migration_id] && hash[:assignments_to_import] && !hash[:assignments_to_import][hash[:migration_id]]
|
||||
item ||= Assignment.find_by_context_type_and_context_id_and_id(context.class.to_s, context.id, hash[:id])
|
||||
|
@ -40,8 +40,8 @@ module Importers
|
|||
end
|
||||
hash[:missing_links] = {:description => [], :instructions => [], }
|
||||
description = ""
|
||||
description += hash[:instructions_in_html] == false ? ImportedHtmlConverter.convert_text(hash[:description] || "", context) : ImportedHtmlConverter.convert(hash[:description] || "", context, {:missing_links => hash[:missing_links][:description]})
|
||||
description += hash[:instructions_in_html] == false ? ImportedHtmlConverter.convert_text(hash[:instructions] || "", context) : ImportedHtmlConverter.convert(hash[:instructions] || "", context, {:missing_links => hash[:missing_links][:instructions]})
|
||||
description += hash[:instructions_in_html] == false ? ImportedHtmlConverter.convert_text(hash[:description] || "", context) : ImportedHtmlConverter.convert(hash[:description] || "", context, migration, {:missing_links => hash[:missing_links][:description]})
|
||||
description += hash[:instructions_in_html] == false ? ImportedHtmlConverter.convert_text(hash[:instructions] || "", context) : ImportedHtmlConverter.convert(hash[:instructions] || "", context, migration, {:missing_links => hash[:missing_links][:instructions]})
|
||||
description += Attachment.attachment_list_from_migration(context, hash[:attachment_ids])
|
||||
item.description = description
|
||||
|
||||
|
@ -149,12 +149,12 @@ module Importers
|
|||
item.send("#{prop}=", hash[prop]) unless hash[prop].nil?
|
||||
end
|
||||
|
||||
context.imported_migration_items << item if context.imported_migration_items && new_record
|
||||
migration.add_imported_item(item) if migration && new_record
|
||||
item.save_without_broadcasting!
|
||||
|
||||
if context.respond_to?(:content_migration) && context.content_migration
|
||||
if migration
|
||||
hash[:missing_links].each do |field, missing_links|
|
||||
context.content_migration.add_missing_content_links(:class => item.class.to_s,
|
||||
migration.add_missing_content_links(:class => item.class.to_s,
|
||||
:id => item.id, :field => field, :missing_links => missing_links,
|
||||
:url => "/#{context.class.to_s.underscore.pluralize}/#{context.id}/#{item.class.to_s.demodulize.underscore.pluralize}/#{item.id}")
|
||||
end
|
||||
|
|
|
@ -26,7 +26,7 @@ module Importers
|
|||
attachments.values.each do |att|
|
||||
if !att['is_folder'] && (migration.import_object?("attachments", att['migration_id']) || migration.import_object?("files", att['migration_id']))
|
||||
begin
|
||||
import_from_migration(att, migration.context)
|
||||
import_from_migration(att, migration.context, migration)
|
||||
rescue
|
||||
migration.add_import_warning(I18n.t('#migration.file_type', "File"), (att[:display_name] || att[:path_name]), $!)
|
||||
end
|
||||
|
@ -56,7 +56,7 @@ module Importers
|
|||
|
||||
private
|
||||
|
||||
def self.import_from_migration(hash, context, item=nil)
|
||||
def self.import_from_migration(hash, context, migration=nil, item=nil)
|
||||
return nil if hash[:files_to_import] && !hash[:files_to_import][hash[:migration_id]]
|
||||
item ||= Attachment.find_by_context_type_and_context_id_and_id(context.class.to_s, context.id, hash[:id])
|
||||
item ||= Attachment.find_by_context_type_and_context_id_and_migration_id(context.class.to_s, context.id, hash[:migration_id]) # if hash[:migration_id]
|
||||
|
@ -68,7 +68,7 @@ module Importers
|
|||
item.file_state = 'hidden' if hash[:hidden]
|
||||
item.display_name = hash[:display_name] if hash[:display_name]
|
||||
item.save_without_broadcasting!
|
||||
context.imported_migration_items << item if context.imported_migration_items
|
||||
migration.add_imported_item(item) if migration
|
||||
end
|
||||
item
|
||||
end
|
||||
|
|
|
@ -26,7 +26,7 @@ module Importers
|
|||
events.each do |event|
|
||||
if migration.import_object?("calendar_events", event['migration_id']) || migration.import_object?("events", event['migration_id'])
|
||||
begin
|
||||
import_from_migration(event, migration.context)
|
||||
import_from_migration(event, migration.context, migration)
|
||||
rescue
|
||||
migration.add_import_warning(t('#migration.calendar_event_type', "Calendar Event"), event[:title], $!)
|
||||
end
|
||||
|
@ -34,7 +34,7 @@ module Importers
|
|||
end
|
||||
end
|
||||
|
||||
def self.import_from_migration(hash, context, item=nil)
|
||||
def self.import_from_migration(hash, context, migration=nil, item=nil)
|
||||
hash = hash.with_indifferent_access
|
||||
return nil if hash[:migration_id] && hash[:events_to_import] && !hash[:events_to_import][hash[:migration_id]]
|
||||
item ||= CalendarEvent.find_by_context_type_and_context_id_and_id(context.class.to_s, context.id, hash[:id])
|
||||
|
@ -45,7 +45,7 @@ module Importers
|
|||
item.workflow_state = 'active' if item.deleted?
|
||||
item.title = hash[:title] || hash[:name]
|
||||
hash[:missing_links] = []
|
||||
item.description = ImportedHtmlConverter.convert(hash[:description] || "", context, {:missing_links => hash[:missing_links]})
|
||||
item.description = ImportedHtmlConverter.convert(hash[:description] || "", context, migration, {:missing_links => hash[:missing_links]})
|
||||
item.description += import_migration_attachment_suffix(hash, context)
|
||||
item.start_at = Canvas::Migration::MigratorHelper.get_utc_time_from_timestamp(hash[:start_at] || hash[:start_date])
|
||||
item.end_at = Canvas::Migration::MigratorHelper.get_utc_time_from_timestamp(hash[:end_at] || hash[:end_date])
|
||||
|
@ -53,12 +53,12 @@ module Importers
|
|||
item.imported = true
|
||||
|
||||
item.save_without_broadcasting!
|
||||
if context.respond_to?(:content_migration) && context.content_migration
|
||||
context.content_migration.add_missing_content_links(:class => item.class.to_s,
|
||||
if migration
|
||||
migration.add_missing_content_links(:class => item.class.to_s,
|
||||
:id => item.id, :missing_links => hash[:missing_links],
|
||||
:url => "/#{context.class.to_s.demodulize.underscore.pluralize}/#{context.id}/#{item.class.to_s.demodulize.underscore.pluralize}/#{item.id}")
|
||||
end
|
||||
context.imported_migration_items << item if context.imported_migration_items
|
||||
migration.add_imported_item(item) if migration
|
||||
if hash[:all_day]
|
||||
item.all_day = hash[:all_day]
|
||||
item.save
|
||||
|
|
|
@ -7,7 +7,7 @@ module Importers
|
|||
tools = data['external_tools'] ? data['external_tools']: []
|
||||
tools.each do |tool|
|
||||
if migration.import_object?("context_external_tools", tool['migration_id']) || migration.import_object?("external_tools", tool['migration_id'])
|
||||
item = import_from_migration(tool, migration.context)
|
||||
item = import_from_migration(tool, migration.context, migration)
|
||||
if item.consumer_key == 'fake' || item.shared_secret == 'fake'
|
||||
migration.add_warning(t('external_tool_attention_needed', 'The security parameters for the external tool "%{tool_name}" need to be set in Course Settings.', :tool_name => item.name))
|
||||
end
|
||||
|
@ -15,7 +15,7 @@ module Importers
|
|||
end
|
||||
end
|
||||
|
||||
def self.import_from_migration(hash, context, item=nil)
|
||||
def self.import_from_migration(hash, context, migration=nil, item=nil)
|
||||
hash = hash.with_indifferent_access
|
||||
return nil if hash[:migration_id] && hash[:external_tools_to_import] && !hash[:external_tools_to_import][hash[:migration_id]]
|
||||
item ||= ContextExternalTool.find_by_context_id_and_context_type_and_migration_id(context.id, context.class.to_s, hash[:migration_id]) if hash[:migration_id]
|
||||
|
@ -48,7 +48,7 @@ module Importers
|
|||
end
|
||||
|
||||
item.save!
|
||||
context.imported_migration_items << item if context.respond_to?(:imported_migration_items) && context.imported_migration_items && item.new_record?
|
||||
migration.add_imported_item(item) if migration && item.new_record?
|
||||
item
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ module Importers
|
|||
modules.each do |mod|
|
||||
if migration.import_object?("context_modules", mod['migration_id']) || migration.import_object?("modules", mod['migration_id'])
|
||||
begin
|
||||
self.import_from_migration(mod, migration.context)
|
||||
self.import_from_migration(mod, migration.context, migration)
|
||||
rescue
|
||||
migration.add_import_warning(t('#migration.module_type', "Module"), mod[:title], $!)
|
||||
end
|
||||
|
@ -18,13 +18,13 @@ module Importers
|
|||
migration.context.touch
|
||||
end
|
||||
|
||||
def self.import_from_migration(hash, context, item=nil)
|
||||
def self.import_from_migration(hash, context, migration=nil, item=nil)
|
||||
hash = hash.with_indifferent_access
|
||||
return nil if hash[:migration_id] && hash[:modules_to_import] && !hash[:modules_to_import][hash[:migration_id]]
|
||||
item ||= ContextModule.find_by_context_type_and_context_id_and_id(context.class.to_s, context.id, hash[:id])
|
||||
item ||= ContextModule.find_by_context_type_and_context_id_and_migration_id(context.class.to_s, context.id, hash[:migration_id]) if hash[:migration_id]
|
||||
item ||= ContextModule.new(:context => context)
|
||||
context.imported_migration_items << item if context.imported_migration_items && item.new_record?
|
||||
migration.add_imported_item(item) if migration && item.new_record?
|
||||
item.name = hash[:title] || hash[:description]
|
||||
item.migration_id = hash[:migration_id]
|
||||
if hash[:workflow_state] == 'unpublished'
|
||||
|
@ -60,9 +60,9 @@ module Importers
|
|||
@item_migration_position = item.content_tags.not_deleted.map(&:position).compact.max || 0
|
||||
(hash[:items] || []).each do |tag_hash|
|
||||
begin
|
||||
self.add_module_item_from_migration(item, tag_hash, 0, context, item_map)
|
||||
self.add_module_item_from_migration(item, tag_hash, 0, context, item_map, migration)
|
||||
rescue
|
||||
context.content_migration.add_import_warning(t(:migration_module_item_type, "Module Item"), tag_hash[:title], $!) if context.content_migration
|
||||
migration.add_import_warning(t(:migration_module_item_type, "Module Item"), tag_hash[:title], $!) if migration
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -85,7 +85,7 @@ module Importers
|
|||
end
|
||||
|
||||
|
||||
def self.add_module_item_from_migration(context_module, hash, level, context, item_map)
|
||||
def self.add_module_item_from_migration(context_module, hash, level, context, item_map, migration=nil)
|
||||
hash = hash.with_indifferent_access
|
||||
hash[:migration_id] ||= hash[:item_migration_id]
|
||||
hash[:migration_id] ||= Digest::MD5.hexdigest(hash[:title]) if hash[:title]
|
||||
|
@ -97,7 +97,7 @@ module Importers
|
|||
else
|
||||
existing_item.workflow_state = 'active'
|
||||
end
|
||||
context.imported_migration_items << existing_item if context.imported_migration_items && existing_item.new_record?
|
||||
migration.add_imported_item(existing_item) if migration && existing_item.new_record?
|
||||
existing_item.migration_id = hash[:migration_id]
|
||||
hash[:indent] = [hash[:indent] || 0, level].max
|
||||
if hash[:linked_resource_type] =~ /wiki_type|wikipage/i
|
||||
|
@ -203,7 +203,7 @@ module Importers
|
|||
end
|
||||
if hash[:sub_items]
|
||||
hash[:sub_items].each do |tag_hash|
|
||||
self.add_module_item_from_migration(context_module, tag_hash, level + 1, context, item_map)
|
||||
self.add_module_item_from_migration(context_module, tag_hash, level + 1, context, item_map, migration)
|
||||
end
|
||||
end
|
||||
item
|
||||
|
|
|
@ -2,6 +2,7 @@ module Importers
|
|||
class CourseContentImporter < Importer
|
||||
|
||||
self.item_class = Course
|
||||
Importers.register_content_importer(self)
|
||||
|
||||
def self.process_migration_files(course, data, migration)
|
||||
return unless data['all_files_export'] && data['all_files_export']['file_path']
|
||||
|
@ -69,14 +70,13 @@ module Importers
|
|||
course.external_url_hash[link['link_id']] = link
|
||||
end
|
||||
ActiveRecord::Base.skip_touch_context
|
||||
course.imported_migration_items = []
|
||||
|
||||
if !migration.for_course_copy?
|
||||
# These only need to be processed once
|
||||
Attachment.skip_media_object_creation do
|
||||
self.process_migration_files(course, data, migration); migration.update_import_progress(18)
|
||||
Importers::AttachmentImporter.process_migration(data, migration); migration.update_import_progress(20)
|
||||
mo_attachments = course.imported_migration_items.find_all { |i| i.is_a?(Attachment) && i.media_entry_id.present? }
|
||||
mo_attachments = migration.imported_migration_items.find_all { |i| i.is_a?(Attachment) && i.media_entry_id.present? }
|
||||
begin
|
||||
self.import_media_objects(mo_attachments, migration)
|
||||
rescue => e
|
||||
|
@ -138,7 +138,7 @@ module Importers
|
|||
syllabus_should_be_added = everything_selected || migration.copy_options[:syllabus_body] || migration.copy_options[:all_syllabus_body]
|
||||
if syllabus_should_be_added
|
||||
syllabus_body = data[:course][:syllabus_body] if data[:course]
|
||||
self.import_syllabus_from_migration(course, syllabus_body) if syllabus_body
|
||||
self.import_syllabus_from_migration(course, syllabus_body, migration) if syllabus_body
|
||||
end
|
||||
|
||||
migration.add_warnings_for_missing_content_links
|
||||
|
@ -147,7 +147,7 @@ module Importers
|
|||
#Adjust dates
|
||||
if shift_options = migration.date_shift_options
|
||||
shift_options = self.shift_date_options(course, shift_options)
|
||||
course.imported_migration_items.each do |event|
|
||||
migration.imported_migration_items.each do |event|
|
||||
if event.is_a?(Assignment)
|
||||
event.due_at = shift_date(event.due_at, shift_options)
|
||||
event.lock_at = shift_date(event.lock_at, shift_options)
|
||||
|
@ -183,7 +183,7 @@ module Importers
|
|||
end
|
||||
migration.progress=100
|
||||
migration.migration_settings ||= {}
|
||||
migration.migration_settings[:imported_assets] = course.imported_migration_items.map(&:asset_string)
|
||||
migration.migration_settings[:imported_assets] = migration.imported_migration_items.map(&:asset_string)
|
||||
migration.workflow_state = :imported
|
||||
migration.save
|
||||
ActiveRecord::Base.skip_touch_context(false)
|
||||
|
@ -192,13 +192,14 @@ module Importers
|
|||
else
|
||||
course.touch
|
||||
end
|
||||
|
||||
Auditors::Course.record_copied(migration.source_course, course, migration.user, source: migration.initiated_source)
|
||||
course.imported_migration_items
|
||||
migration.imported_migration_items
|
||||
end
|
||||
|
||||
def self.import_syllabus_from_migration(course, syllabus_body)
|
||||
def self.import_syllabus_from_migration(course, syllabus_body, migration=nil)
|
||||
missing_links = []
|
||||
course.syllabus_body = ImportedHtmlConverter.convert(syllabus_body, course, {:missing_links => missing_links})
|
||||
course.syllabus_body = ImportedHtmlConverter.convert(syllabus_body, course, migration, {:missing_links => missing_links})
|
||||
course.content_migration.add_missing_content_links(:class => course.class.to_s,
|
||||
:id => course.id, :field => "syllabus", :missing_links => missing_links,
|
||||
:url => "/#{course.class.to_s.underscore.pluralize}/#{course.id}/assignments/syllabus")
|
||||
|
|
|
@ -3,7 +3,7 @@ module Importers
|
|||
|
||||
self.item_class = DiscussionTopic
|
||||
|
||||
attr_accessor :options, :context, :item
|
||||
attr_accessor :options, :context, :item, :migration
|
||||
|
||||
def self.process_migration(data, migration)
|
||||
process_announcements_migration(Array(data['announcements']), migration)
|
||||
|
@ -16,7 +16,7 @@ module Importers
|
|||
event[:type] = 'announcement'
|
||||
|
||||
begin
|
||||
self.import_from_migration(event, migration.context)
|
||||
self.import_from_migration(event, migration.context, migration)
|
||||
rescue
|
||||
migration.add_import_warning(t('#migration.announcement_type', "Announcement"), event[:title], $!)
|
||||
end
|
||||
|
@ -32,7 +32,7 @@ module Importers
|
|||
context ||= migration.context
|
||||
next unless context && can_import_topic?(topic, migration)
|
||||
begin
|
||||
import_from_migration(topic.merge(topic_entries_to_import: topic_entries_to_import), context)
|
||||
import_from_migration(topic.merge(topic_entries_to_import: topic_entries_to_import), context, migration)
|
||||
rescue
|
||||
migration.add_import_warning(t('#migration.discussion_topic_type', "Discussion Topic"), topic[:title], $!)
|
||||
end
|
||||
|
@ -46,14 +46,15 @@ module Importers
|
|||
migration.import_object?('announcements', topic['migration_id']))
|
||||
end
|
||||
|
||||
def self.import_from_migration(hash, context, item=nil)
|
||||
importer = self.new(hash, context, item)
|
||||
def self.import_from_migration(hash, context, migration=nil, item=nil)
|
||||
importer = self.new(hash, context, migration, item)
|
||||
importer.run
|
||||
end
|
||||
|
||||
def initialize(hash, context, item)
|
||||
def initialize(hash, context, migration, item)
|
||||
self.options = DiscussionTopicOptions.new(hash)
|
||||
self.context = context
|
||||
self.migration = migration
|
||||
self.item = find_or_create_topic(item)
|
||||
end
|
||||
|
||||
|
@ -77,7 +78,7 @@ module Importers
|
|||
:require_initial_post].each do |attr|
|
||||
item.send("#{attr}=", options[attr])
|
||||
end
|
||||
item.message = options.message ? ImportedHtmlConverter.convert(options.message, context, missing_links: options[:missing_links]) : I18n.t('#discussion_topic.empty_message', 'No message')
|
||||
item.message = options.message ? ImportedHtmlConverter.convert(options.message, context, migration, missing_links: options[:missing_links]) : I18n.t('#discussion_topic.empty_message', 'No message')
|
||||
item.posted_at = Canvas::Migration::MigratorHelper.get_utc_time_from_timestamp(options[:posted_at])
|
||||
item.delayed_post_at = Canvas::Migration::MigratorHelper.get_utc_time_from_timestamp(options.delayed_post_at)
|
||||
item.last_reply_at = item.posted_at if item.new_record?
|
||||
|
@ -102,25 +103,23 @@ module Importers
|
|||
def fetch_assignment
|
||||
return nil unless context.respond_to?(:assignments)
|
||||
if options[:assignment]
|
||||
Importers::AssignmentImporter.import_from_migration(options[:assignment], context)
|
||||
Importers::AssignmentImporter.import_from_migration(options[:assignment], context, migration)
|
||||
elsif options[:grading]
|
||||
Importers::AssignmentImporter.import_from_migration({
|
||||
grading: options[:grading], migration_id: options[:migration_id],
|
||||
submission_format: 'discussion_topic', due_date: options.due_date,
|
||||
title: options[:grading][:title]
|
||||
}, context)
|
||||
}, context, migration)
|
||||
end
|
||||
end
|
||||
|
||||
def import_migration_item
|
||||
if context.respond_to?(:imported_migration_items)
|
||||
Array(context.imported_migration_items) << item
|
||||
end
|
||||
migration.add_imported_item(item) if migration
|
||||
end
|
||||
|
||||
def add_missing_content_links
|
||||
if context.try_rescue(:content_migration)
|
||||
context.content_migration.add_missing_content_links(class: item.class.to_s,
|
||||
if migration
|
||||
migration.add_missing_content_links(class: item.class.to_s,
|
||||
id: item.id, missing_links: options[:missing_links],
|
||||
url: "/#{context.class.to_s.underscore.pluralize}/#{context.id}/#{item.class.to_s.demodulize.underscore.pluralize}/#{item.id}")
|
||||
end
|
||||
|
|
|
@ -9,7 +9,7 @@ module Importers
|
|||
tools.each do |tool|
|
||||
if tool['migration_id'] && (!to_import || to_import[tool['migration_id']])
|
||||
begin
|
||||
self.import_from_migration(tool, migration.context)
|
||||
self.import_from_migration(tool, migration.context, migration)
|
||||
rescue
|
||||
migration.add_import_warning(t('#migration.external_feed_type', "External Feed"), tool[:title], $!)
|
||||
end
|
||||
|
@ -17,7 +17,7 @@ module Importers
|
|||
end
|
||||
end
|
||||
|
||||
def self.import_from_migration(hash, context, item=nil)
|
||||
def self.import_from_migration(hash, context, migration=nil, item=nil)
|
||||
hash = hash.with_indifferent_access
|
||||
return nil if hash[:migration_id] && hash[:external_feeds_to_import] && !hash[:external_feeds_to_import][hash[:migration_id]]
|
||||
item ||= ExternalFeed.find_by_context_id_and_context_type_and_migration_id(context.id, context.class.to_s, hash[:migration_id]) if hash[:migration_id]
|
||||
|
@ -31,7 +31,7 @@ module Importers
|
|||
item.header_match = hash[:header_match] unless hash[:header_match].blank?
|
||||
|
||||
item.save!
|
||||
context.imported_migration_items << item if context.imported_migration_items && item.new_record?
|
||||
migration.add_imported_item(item) if migration && item.new_record?
|
||||
item
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ module Importers
|
|||
standards.each do |standard|
|
||||
if migration.import_object?('grading_standards', standard['migration_id'])
|
||||
begin
|
||||
self.import_from_migration(standard, migration.context)
|
||||
self.import_from_migration(standard, migration.context, migration)
|
||||
rescue
|
||||
migration.add_import_warning(t('#migration.grading_standard_type', "Grading Standard"), standard[:title], $!)
|
||||
end
|
||||
|
@ -16,7 +16,7 @@ module Importers
|
|||
end
|
||||
end
|
||||
|
||||
def self.import_from_migration(hash, context, item=nil)
|
||||
def self.import_from_migration(hash, context, migration=nil, item=nil)
|
||||
hash = hash.with_indifferent_access
|
||||
return nil if hash[:migration_id] && hash[:grading_standards_to_import] && !hash[:grading_standards_to_import][hash[:migration_id]]
|
||||
item ||= GradingStandard.find_by_context_id_and_context_type_and_migration_id(context.id, context.class.to_s, hash[:migration_id]) if hash[:migration_id]
|
||||
|
@ -31,7 +31,7 @@ module Importers
|
|||
end
|
||||
|
||||
item.save!
|
||||
context.imported_migration_items << item if context.imported_migration_items && item.new_record?
|
||||
migration.add_imported_item(item) if migration && item.new_record?
|
||||
item
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ module Importers
|
|||
groups.each do |group|
|
||||
if migration.import_object?("groups", group['migration_id'])
|
||||
begin
|
||||
self.import_from_migration(group, migration.context)
|
||||
self.import_from_migration(group, migration.context, migration)
|
||||
rescue
|
||||
migration.add_import_warning(t('#migration.group_type', "Group"), group[:title], $!)
|
||||
end
|
||||
|
@ -16,13 +16,13 @@ module Importers
|
|||
end
|
||||
end
|
||||
|
||||
def self.import_from_migration(hash, context, item=nil)
|
||||
def self.import_from_migration(hash, context, migration=nil, item=nil)
|
||||
hash = hash.with_indifferent_access
|
||||
return nil if hash[:migration_id] && hash[:groups_to_import] && !hash[:groups_to_import][hash[:migration_id]]
|
||||
item ||= Group.find_by_context_id_and_context_type_and_id(context.id, context.class.to_s, hash[:id])
|
||||
item ||= Group.find_by_context_id_and_context_type_and_migration_id(context.id, context.class.to_s, hash[:migration_id]) if hash[:migration_id]
|
||||
item ||= context.groups.new
|
||||
context.imported_migration_items << item if context.imported_migration_items && item.new_record?
|
||||
migration.add_imported_item(item) if migration && item.new_record?
|
||||
item.migration_id = hash[:migration_id]
|
||||
item.name = hash[:title]
|
||||
item.group_category = hash[:group_category].present? ?
|
||||
|
@ -30,7 +30,7 @@ module Importers
|
|||
GroupCategory.imported_for(context)
|
||||
|
||||
item.save!
|
||||
context.imported_migration_items << item
|
||||
migration.add_imported_item(item) if migration
|
||||
item
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,15 @@
|
|||
module Importers
|
||||
def self.register_content_importer(klass)
|
||||
@content_importers ||= {}
|
||||
@content_importers[klass.item_class.to_s] = klass
|
||||
end
|
||||
|
||||
def self.content_importer_for(context_type)
|
||||
klass = @content_importers[context_type]
|
||||
raise "No content importer registered for #{context_type}" unless klass
|
||||
klass
|
||||
end
|
||||
|
||||
class Importer
|
||||
class << self
|
||||
attr_accessor :item_class
|
||||
|
|
|
@ -36,7 +36,7 @@ module Importers
|
|||
root_outcome_group.adopt_outcome_group(item)
|
||||
end
|
||||
|
||||
context.imported_migration_items << item if context && context.imported_migration_items && item.new_record?
|
||||
migration.add_imported_item(item) if migration && item.new_record?
|
||||
|
||||
if hash[:outcomes]
|
||||
hash[:outcomes].each do |child|
|
||||
|
|
|
@ -76,7 +76,7 @@ module Importers
|
|||
end
|
||||
|
||||
item.save!
|
||||
context.imported_migration_items << item if context && context.imported_migration_items && item.new_record?
|
||||
migration.add_imported_item(item) if migration && item.new_record?
|
||||
else
|
||||
item = outcome
|
||||
end
|
||||
|
|
|
@ -49,18 +49,18 @@ module Importers
|
|||
if qq[:assessment_question_migration_id]
|
||||
if aq = question_data[:aq_data][qq[:assessment_question_migration_id]]
|
||||
qq['assessment_question_id'] = aq['assessment_question_id']
|
||||
aq_hash = Importers::AssessmentQuestionImporter.prep_for_import(qq, context)
|
||||
Quizzes::QuizQuestion.import_from_migration(aq_hash, context, quiz, item)
|
||||
aq_hash = Importers::AssessmentQuestionImporter.prep_for_import(qq, context, migration)
|
||||
Importers::QuizQuestionImporter.import_from_migration(aq_hash, context, migration, quiz, item)
|
||||
else
|
||||
aq_hash = Importers::AssessmentQuestionImporter.import_from_migration(qq, context)
|
||||
aq_hash = Importers::AssessmentQuestionImporter.import_from_migration(qq, context, migration)
|
||||
qq['assessment_question_id'] = aq_hash['assessment_question_id']
|
||||
Quizzes::QuizQuestion.import_from_migration(aq_hash, context, quiz, item)
|
||||
Importers::QuizQuestionImporter.import_from_migration(aq_hash, context, migration, quiz, item)
|
||||
end
|
||||
end
|
||||
elsif aq = question_data[:aq_data][question[:migration_id]]
|
||||
aq[:points_possible] = question[:points_possible] if question[:points_possible]
|
||||
aq[:position] = i + 1
|
||||
Quizzes::QuizQuestion.import_from_migration(aq, context, quiz, item)
|
||||
Importers::QuizQuestionImporter.import_from_migration(aq, context, migration, quiz, item)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -42,8 +42,7 @@ module Importers
|
|||
end
|
||||
end
|
||||
begin
|
||||
assessment[:migration] = migration
|
||||
Importers::QuizImporter.import_from_migration(assessment, migration.context, question_data, nil, allow_update)
|
||||
Importers::QuizImporter.import_from_migration(assessment, migration.context, migration, question_data, nil, allow_update)
|
||||
rescue
|
||||
migration.add_import_warning(t('#migration.quiz_type', "Quiz"), assessment[:title], $!)
|
||||
end
|
||||
|
@ -53,7 +52,7 @@ module Importers
|
|||
|
||||
# Import a quiz from a hash.
|
||||
# It assumes that all the referenced questions are already in the database
|
||||
def self.import_from_migration(hash, context, question_data, item=nil, allow_update = false)
|
||||
def self.import_from_migration(hash, context, migration=nil, question_data=nil, item=nil, allow_update = false)
|
||||
hash = hash.with_indifferent_access
|
||||
# there might not be an import id if it's just a text-only type...
|
||||
item ||= Quizzes::Quiz.find_by_context_type_and_context_id_and_id(context.class.to_s, context.id, hash[:id]) if hash[:id]
|
||||
|
@ -75,7 +74,7 @@ module Importers
|
|||
item.hide_correct_answers_at = Canvas::Migration::MigratorHelper.get_utc_time_from_timestamp(hash[:hide_correct_answers_at]) if hash[:hide_correct_answers_at]
|
||||
item.scoring_policy = hash[:which_attempt_to_keep] if hash[:which_attempt_to_keep]
|
||||
hash[:missing_links] = []
|
||||
item.description = ImportedHtmlConverter.convert(hash[:description], context, {:missing_links => hash[:missing_links]})
|
||||
item.description = ImportedHtmlConverter.convert(hash[:description], context, migration, {:missing_links => hash[:missing_links]})
|
||||
|
||||
|
||||
%w[
|
||||
|
@ -106,8 +105,8 @@ module Importers
|
|||
|
||||
item.save!
|
||||
|
||||
if context.respond_to?(:content_migration) && context.content_migration
|
||||
context.content_migration.add_missing_content_links(
|
||||
if migration
|
||||
migration.add_missing_content_links(
|
||||
:class => item.class.to_s,
|
||||
:id => item.id, :missing_links => hash[:missing_links],
|
||||
:url => "/#{context.class.to_s.demodulize.underscore.pluralize}/#{context.id}/#{item.class.to_s.demodulize.underscore.pluralize}/#{item.id}"
|
||||
|
@ -143,21 +142,21 @@ module Importers
|
|||
if qq[:assessment_question_migration_id]
|
||||
if aq = question_data[:aq_data][qq[:assessment_question_migration_id]]
|
||||
qq['assessment_question_id'] = aq['assessment_question_id']
|
||||
aq_hash = ::Importers::AssessmentQuestionImporter.prep_for_import(qq, context)
|
||||
Quizzes::QuizQuestion.import_from_migration(aq_hash, context, item)
|
||||
aq_hash = ::Importers::AssessmentQuestionImporter.prep_for_import(qq, context, migration)
|
||||
Importers::QuizQuestionImporter.import_from_migration(aq_hash, context, migration, item)
|
||||
else
|
||||
aq_hash = ::Importers::AssessmentQuestionImporter.import_from_migration(qq, context)
|
||||
aq_hash = ::Importers::AssessmentQuestionImporter.import_from_migration(qq, context, migration)
|
||||
qq['assessment_question_id'] = aq_hash['assessment_question_id']
|
||||
Quizzes::QuizQuestion.import_from_migration(aq_hash, context, item)
|
||||
Importers::QuizQuestionImporter.import_from_migration(aq_hash, context, migration, item)
|
||||
end
|
||||
end
|
||||
elsif aq = question_data[:aq_data][question[:migration_id]]
|
||||
aq[:position] = i + 1
|
||||
aq[:points_possible] = question[:points_possible] if question[:points_possible]
|
||||
Quizzes::QuizQuestion.import_from_migration(aq, context, item)
|
||||
Importers::QuizQuestionImporter.import_from_migration(aq, context, migration, item)
|
||||
end
|
||||
when "question_group"
|
||||
Importers::QuizGroupImporter.import_from_migration(question, context, item, question_data, i + 1, hash[:migration])
|
||||
Importers::QuizGroupImporter.import_from_migration(question, context, item, question_data, i + 1, migration)
|
||||
when "text_only_question"
|
||||
qq = item.quiz_questions.new
|
||||
qq.question_data = question
|
||||
|
@ -175,7 +174,7 @@ module Importers
|
|||
item.assignment = nil if item.assignment && item.assignment.quiz && item.assignment.quiz.id != item.id
|
||||
item.assignment ||= context.assignments.new
|
||||
|
||||
item.assignment = ::Importers::AssignmentImporter.import_from_migration(hash[:assignment], context, item.assignment, item)
|
||||
item.assignment = ::Importers::AssignmentImporter.import_from_migration(hash[:assignment], context, migration, item.assignment, item)
|
||||
|
||||
if !hash[:available]
|
||||
item.workflow_state = 'unpublished'
|
||||
|
@ -202,7 +201,7 @@ module Importers
|
|||
item.save
|
||||
item.assignment.save if item.assignment && item.assignment.changed?
|
||||
|
||||
context.imported_migration_items << item if context.imported_migration_items
|
||||
migration.add_imported_item(item) if migration
|
||||
item
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
module Importers
|
||||
class QuizQuestionImporter < Importer
|
||||
|
||||
self.item_class = Quizzes::QuizQuestion
|
||||
|
||||
def self.import_from_migration(hash, context, migration=nil, quiz=nil, quiz_group=nil)
|
||||
unless hash[:prepped_for_import]
|
||||
Importers::AssessmentQuestionImporter.prep_for_import(hash, context, migration)
|
||||
end
|
||||
|
||||
position = hash[:position] && hash[:position].to_i
|
||||
if id = hash['quiz_question_id']
|
||||
Quizzes::QuizQuestion.where(id: id).update_all(quiz_group_id: quiz_group,
|
||||
assessment_question_id: hash['assessment_question_id'], question_data: hash.to_yaml,
|
||||
created_at: Time.now.utc, updated_at: Time.now.utc, migration_id: hash[:migration_id],
|
||||
position: position)
|
||||
else
|
||||
query = self.item_class.send(:sanitize_sql, [<<-SQL, quiz && quiz.id, quiz_group && quiz_group.id, hash['assessment_question_id'], hash.to_yaml, Time.now.utc, Time.now.utc, hash[:migration_id], position])
|
||||
INSERT INTO quiz_questions (quiz_id, quiz_group_id, assessment_question_id, question_data, created_at, updated_at, migration_id, position)
|
||||
VALUES (?,?,?,?,?,?,?,?)
|
||||
SQL
|
||||
self.item_class.connection.insert(query, "#{self.item_class.name} Create",
|
||||
self.item_class.primary_key, nil, self.item_class.sequence_name)
|
||||
end
|
||||
hash
|
||||
end
|
||||
end
|
||||
end
|
|
@ -60,7 +60,7 @@ module Importers
|
|||
end
|
||||
end
|
||||
|
||||
context.imported_migration_items << item if context.imported_migration_items && item.new_record?
|
||||
migration.add_imported_item(item) if migration && item.new_record?
|
||||
item.save!
|
||||
end
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ module Importers
|
|||
|
||||
outline['root_folder'] = true
|
||||
begin
|
||||
self.import_from_migration(outline.merge({:outline_folders_to_import => to_import}), migration.context)
|
||||
self.import_from_migration(outline.merge({:outline_folders_to_import => to_import}), migration.context, migration)
|
||||
rescue
|
||||
migration.add_warning("Error importing the course outline.", $!)
|
||||
end
|
||||
|
@ -25,14 +25,14 @@ module Importers
|
|||
end
|
||||
next unless migration.import_object?("wiki_pages", wiki['migration_id']) || migration.import_object?("wikis", wiki['migration_id'])
|
||||
begin
|
||||
self.import_from_migration(wiki, migration.context) if wiki
|
||||
self.import_from_migration(wiki, migration.context, migration) if wiki
|
||||
rescue
|
||||
migration.add_import_warning(t('#migration.wiki_page_type', "Wiki Page"), wiki[:title], $!)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.import_from_migration(hash, context, item=nil)
|
||||
def self.import_from_migration(hash, context, migration=nil, item=nil)
|
||||
hash = hash.with_indifferent_access
|
||||
item ||= WikiPage.find_by_wiki_id_and_id(context.wiki.id, hash[:id])
|
||||
item ||= WikiPage.find_by_wiki_id_and_migration_id(context.wiki.id, hash[:migration_id])
|
||||
|
@ -61,14 +61,16 @@ module Importers
|
|||
item.workflow_state = 'unpublished'
|
||||
end
|
||||
end
|
||||
|
||||
item.set_as_front_page! if !!hash[:front_page] && context.wiki.has_no_front_page
|
||||
context.imported_migration_items << item if context.imported_migration_items && item.new_record?
|
||||
migration.add_imported_item(item) if migration && item.new_record?
|
||||
|
||||
item.migration_id = hash[:migration_id]
|
||||
(hash[:contents] || []).each do |sub_item|
|
||||
next if sub_item[:type] == 'embedded_content'
|
||||
Importers::WikiPageImporter.import_from_migration(sub_item.merge({
|
||||
:outline_folders_to_import => hash[:outline_folders_to_import]
|
||||
}), context)
|
||||
}), context, migration)
|
||||
end
|
||||
return if hash[:type] && ['folder', 'FOLDER_TYPE'].member?(hash[:type]) && hash[:linked_resource_id]
|
||||
hash[:missing_links] = {}
|
||||
|
@ -80,10 +82,10 @@ module Importers
|
|||
description = ""
|
||||
if hash[:header]
|
||||
hash[:missing_links][:field] = []
|
||||
description += hash[:header][:is_html] ? ImportedHtmlConverter.convert(hash[:header][:body] || "", context, {:missing_links => hash[:missing_links][:header]}) : ImportedHtmlConverter.convert_text(hash[:header][:body] || [""], context)
|
||||
description += hash[:header][:is_html] ? ImportedHtmlConverter.convert(hash[:header][:body] || "", context, migration, {:missing_links => hash[:missing_links][:header]}) : ImportedHtmlConverter.convert_text(hash[:header][:body] || [""], context)
|
||||
end
|
||||
hash[:missing_links][:description] = []
|
||||
description += ImportedHtmlConverter.convert(hash[:description], context, {:missing_links => hash[:missing_links][:description]}) if hash[:description]
|
||||
description += ImportedHtmlConverter.convert(hash[:description], context, migration, {:missing_links => hash[:missing_links][:description]}) if hash[:description]
|
||||
contents = ""
|
||||
allow_save = false if hash[:migration_id] && hash[:outline_folders_to_import] && !hash[:outline_folders_to_import][hash[:migration_id]]
|
||||
hash[:contents].each do |sub_item|
|
||||
|
@ -98,7 +100,7 @@ module Importers
|
|||
end
|
||||
description += "\n<h2>#{sub_item[:title]}</h2>\n" if sub_item[:title]
|
||||
hash[:missing_links][:sub_item] = []
|
||||
description += ImportedHtmlConverter.convert(sub_item[:description], context, {:missing_links => hash[:missing_links][:sub_item]}) if sub_item[:description]
|
||||
description += ImportedHtmlConverter.convert(sub_item[:description], context, migration, {:missing_links => hash[:missing_links][:sub_item]}) if sub_item[:description]
|
||||
elsif sub_item[:type] == 'linked_resource'
|
||||
case sub_item[:linked_resource_type]
|
||||
when 'TOC_TYPE'
|
||||
|
@ -131,7 +133,7 @@ module Importers
|
|||
description += "<ul>\n#{contents}\n</ul>" if contents && contents.length > 0
|
||||
if hash[:footer]
|
||||
hash[:missing_links][:footer] = []
|
||||
description += hash[:footer][:is_html] ? ImportedHtmlConverter.convert(hash[:footer][:body] || "", context, {:missing_links => hash[:missing_links][:footer]}) : ImportedHtmlConverter.convert_text(hash[:footer][:body] || [""], context)
|
||||
description += hash[:footer][:is_html] ? ImportedHtmlConverter.convert(hash[:footer][:body] || "", context, migration, {:missing_links => hash[:missing_links][:footer]}) : ImportedHtmlConverter.convert_text(hash[:footer][:body] || [""], context)
|
||||
end
|
||||
item.body = description
|
||||
allow_save = false if !description || description.empty?
|
||||
|
@ -145,7 +147,7 @@ module Importers
|
|||
topic = Importers::DiscussionTopicImporter.import_from_migration(topic.merge({
|
||||
:topics_to_import => hash[:topics_to_import],
|
||||
:topic_entries_to_import => hash[:topic_entries_to_import]
|
||||
}), context)
|
||||
}), context, migration)
|
||||
if topic
|
||||
topic_count += 1
|
||||
description += " <li><a href='/#{context.class.to_s.downcase.pluralize}/#{context.id}/discussion_topics/#{topic.id}'>#{topic.title}</a></li>\n"
|
||||
|
@ -158,13 +160,13 @@ module Importers
|
|||
#it's an actual wiki page
|
||||
item.title = hash[:title].presence || item.url.presence || "unnamed page"
|
||||
if item.title.length > WikiPage::TITLE_LENGTH
|
||||
if context.respond_to?(:content_migration) && context.content_migration
|
||||
context.content_migration.add_warning(t('warnings.truncated_wiki_title', "The title of the following wiki page was truncated: %{title}", :title => item.title))
|
||||
if migration
|
||||
migration.add_warning(t('warnings.truncated_wiki_title', "The title of the following wiki page was truncated: %{title}", :title => item.title))
|
||||
end
|
||||
item.title.splice!(0...WikiPage::TITLE_LENGTH) # truncate too-long titles
|
||||
end
|
||||
hash[:missing_links][:body] = []
|
||||
item.body = ImportedHtmlConverter.convert(hash[:text] || "", context, {:missing_links => hash[:missing_links][:body]})
|
||||
item.body = ImportedHtmlConverter.convert(hash[:text] || "", context, migration, {:missing_links => hash[:missing_links][:body]})
|
||||
item.editing_roles = hash[:editing_roles] if hash[:editing_roles].present?
|
||||
item.notify_of_update = hash[:notify_of_update] if !hash[:notify_of_update].nil?
|
||||
else
|
||||
|
@ -172,10 +174,10 @@ module Importers
|
|||
end
|
||||
if allow_save && hash[:migration_id]
|
||||
item.save_without_broadcasting!
|
||||
context.imported_migration_items << item if context.imported_migration_items
|
||||
if context.respond_to?(:content_migration) && context.content_migration
|
||||
migration.add_imported_item(item) if migration
|
||||
if migration
|
||||
hash[:missing_links].each do |field, missing_links|
|
||||
context.content_migration.add_missing_content_links(:class => item.class.to_s,
|
||||
migration.add_missing_content_links(:class => item.class.to_s,
|
||||
:id => item.id, :field => field, :missing_links => missing_links,
|
||||
:url => "/#{context.class.to_s.underscore.pluralize}/#{context.id}/wiki/#{item.url}")
|
||||
end
|
||||
|
|
|
@ -213,11 +213,4 @@ class LearningOutcome < ActiveRecord::Base
|
|||
|
||||
scope :global, where(:context_id => nil)
|
||||
|
||||
def self.process_migration(*args)
|
||||
Importers::LearningOutcomeImporter.process_migration(*args)
|
||||
end
|
||||
|
||||
def self.import_from_migration(*args)
|
||||
Importers::LearningOutcomeImporter.import_from_migration(*args)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -178,28 +178,6 @@ class Quizzes::QuizQuestion < ActiveRecord::Base
|
|||
where(:id => questions).update_all(set)
|
||||
end
|
||||
|
||||
def self.import_from_migration(hash, context, quiz=nil, quiz_group=nil)
|
||||
unless hash[:prepped_for_import]
|
||||
Importers::AssessmentQuestionImporter.prep_for_import(hash, context)
|
||||
end
|
||||
|
||||
position = hash[:position] && hash[:position].to_i
|
||||
if id = hash['quiz_question_id']
|
||||
Quizzes::QuizQuestion.where(id: id).update_all(quiz_group_id: quiz_group,
|
||||
assessment_question_id: hash['assessment_question_id'], question_data: hash.to_yaml,
|
||||
created_at: Time.now.utc, updated_at: Time.now.utc, migration_id: hash[:migration_id],
|
||||
position: position)
|
||||
else
|
||||
query = sanitize_sql([<<-SQL, quiz && quiz.id, quiz_group && quiz_group.id, hash['assessment_question_id'], hash.to_yaml, Time.now.utc, Time.now.utc, hash[:migration_id], position])
|
||||
INSERT INTO quiz_questions (quiz_id, quiz_group_id, assessment_question_id, question_data, created_at, updated_at, migration_id, position)
|
||||
VALUES (?,?,?,?,?,?,?,?)
|
||||
SQL
|
||||
self.connection.insert(query, "#{name} Create",
|
||||
primary_key, nil, sequence_name)
|
||||
end
|
||||
hash
|
||||
end
|
||||
|
||||
def migrate_file_links
|
||||
Quizzes::QuizQuestionLinkMigrator.migrate_file_links_in_question(self)
|
||||
end
|
||||
|
|
|
@ -264,12 +264,4 @@ class Rubric < ActiveRecord::Base
|
|||
def update_assessments_for_new_criteria(new_criteria)
|
||||
criteria = self.data
|
||||
end
|
||||
|
||||
def self.process_migration(*args)
|
||||
Importers::RubricImporter.process_migration(*args)
|
||||
end
|
||||
|
||||
def self.import_from_migration(*args)
|
||||
Importers::RubricImporter.import_from_migration(*args)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -433,12 +433,4 @@ class WikiPage < ActiveRecord::Base
|
|||
self.workflow_state = 'active'
|
||||
end
|
||||
end
|
||||
|
||||
def self.process_migration(*args)
|
||||
Importers::WikiPageImporter.process_migration(*args)
|
||||
end
|
||||
|
||||
def self.import_from_migration(*args)
|
||||
Importers::WikiPageImporter.import_from_migration(*args)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -946,7 +946,7 @@ routes.draw do
|
|||
end
|
||||
|
||||
scope(:controller => :content_migrations) do
|
||||
%w(course group user).each do |context|
|
||||
%w(account course group user).each do |context|
|
||||
get "#{context.pluralize}/:#{context}_id/content_migrations/migrators", :action => :available_migrators, :path_name => "#{context}_content_migration_migrators_list"
|
||||
get "#{context.pluralize}/:#{context}_id/content_migrations/:id", :action => :show, :path_name => "#{context}_content_migration"
|
||||
get "#{context.pluralize}/:#{context}_id/content_migrations", :action => :index, :path_name => "#{context}_content_migration_list"
|
||||
|
@ -957,7 +957,7 @@ routes.draw do
|
|||
end
|
||||
|
||||
scope(:controller => :migration_issues) do
|
||||
%w(course group user).each do |context|
|
||||
%w(account course group user).each do |context|
|
||||
get "#{context.pluralize}/:#{context}_id/content_migrations/:content_migration_id/migration_issues/:id", :action => :show, :path_name => "#{context}_content_migration_migration_issue"
|
||||
get "#{context.pluralize}/:#{context}_id/content_migrations/:content_migration_id/migration_issues", :action => :index, :path_name => "#{context}_content_migration_migration_issue_list"
|
||||
post "#{context.pluralize}/:#{context}_id/content_migrations/:content_migration_id/migration_issues", :action => :create, :path_name => "#{context}_content_migration_migration_issue_create"
|
||||
|
|
|
@ -118,7 +118,8 @@ Canvas::Plugin.register 'canvas_cartridge_importer', :export_system, {
|
|||
:worker => 'CCWorker',
|
||||
:migration_partial => 'canvas_config',
|
||||
:requires_file_upload => true,
|
||||
:provides =>{:canvas_cartridge => CC::Importer::Canvas::Converter}
|
||||
:provides =>{:canvas_cartridge => CC::Importer::Canvas::Converter},
|
||||
:valid_contexts => %w{Account Course}
|
||||
},
|
||||
}
|
||||
require_dependency 'canvas/migration/worker/course_copy_worker'
|
||||
|
@ -136,7 +137,8 @@ Canvas::Plugin.register 'course_copy_importer', :export_system, {
|
|||
:requires_file_upload => false,
|
||||
:skip_conversion_step => true,
|
||||
:required_options_validator => Canvas::Migration::Validators::CourseCopyValidator,
|
||||
:required_settings => [:source_course_id]
|
||||
:required_settings => [:source_course_id],
|
||||
:valid_contexts => %w{Course}
|
||||
},
|
||||
}
|
||||
require_dependency 'canvas/migration/worker/zip_file_worker'
|
||||
|
@ -155,7 +157,7 @@ Canvas::Plugin.register 'zip_file_importer', :export_system, {
|
|||
:no_selective_import => true,
|
||||
:required_options_validator => Canvas::Migration::Validators::ZipImporterValidator,
|
||||
:required_settings => [:source_folder_id],
|
||||
:additional_contexts => %w(User Group)
|
||||
:valid_contexts => %w(Course Group User)
|
||||
},
|
||||
}
|
||||
Canvas::Plugin.register 'common_cartridge_importer', :export_system, {
|
||||
|
@ -174,6 +176,7 @@ Canvas::Plugin.register 'common_cartridge_importer', :export_system, {
|
|||
:common_cartridge_1_0=>CC::Importer::Standard::Converter,
|
||||
:common_cartridge_1_1=>CC::Importer::Standard::Converter,
|
||||
:common_cartridge_1_2=>CC::Importer::Standard::Converter},
|
||||
:valid_contexts => %w{Account Course}
|
||||
},
|
||||
}
|
||||
Canvas::Plugin.register('grade_export', :sis, {
|
||||
|
|
|
@ -22,17 +22,17 @@ class ImportedHtmlConverter
|
|||
|
||||
CONTAINER_TYPES = ['div', 'p', 'body']
|
||||
|
||||
def self.convert(html, context, opts={})
|
||||
def self.convert(html, context, migration=nil, opts={})
|
||||
doc = Nokogiri::HTML(html || "")
|
||||
attrs = ['rel', 'href', 'src', 'data', 'value']
|
||||
course_path = "/#{context.class.to_s.underscore.pluralize}/#{context.id}"
|
||||
|
||||
for_course_copy = false
|
||||
domain_substitution_map = {}
|
||||
if context.respond_to?(:content_migration) && context.content_migration
|
||||
for_course_copy = true if context.content_migration.for_course_copy?
|
||||
if migration
|
||||
for_course_copy = true if migration.for_course_copy?
|
||||
|
||||
if ds_map = context.content_migration.migration_settings[:domain_substitution_map]
|
||||
if ds_map = migration.migration_settings[:domain_substitution_map]
|
||||
ds_map.each{|k, v| domain_substitution_map[k.to_s] = v.to_s } # ensure strings
|
||||
end
|
||||
end
|
||||
|
|
|
@ -99,6 +99,25 @@ describe ContentMigrationsController, type: :request do
|
|||
json.first['id'].should == @migration.id
|
||||
end
|
||||
end
|
||||
|
||||
context "Account" do
|
||||
before do
|
||||
@account = Account.create!(:name => 'name')
|
||||
@account.add_user(@user)
|
||||
@migration = @account.content_migrations.create
|
||||
@migration.migration_type = 'qti_converter'
|
||||
@migration.user = @user
|
||||
@migration.save!
|
||||
@migration_url = "/api/v1/accounts/#{@account.id}/content_migrations"
|
||||
@params = @params.reject{ |k| k == :course_id }.merge(account_id: @account.id)
|
||||
end
|
||||
|
||||
it "should return list" do
|
||||
json = api_call(:get, @migration_url, @params)
|
||||
json.length.should == 1
|
||||
json.first['id'].should == @migration.id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'show' do
|
||||
|
@ -215,10 +234,26 @@ describe ContentMigrationsController, type: :request do
|
|||
end
|
||||
end
|
||||
|
||||
context "Account" do
|
||||
before do
|
||||
@account = Account.create!(:name => 'name')
|
||||
@account.add_user(@user)
|
||||
@migration = @account.content_migrations.create
|
||||
@migration.migration_type = 'qti_converter'
|
||||
@migration.user = @user
|
||||
@migration.save!
|
||||
@migration_url = "/api/v1/accounts/#{@account.id}/content_migrations/#{@migration.id}"
|
||||
@params = @params.reject{ |k| k == :course_id }.merge(account_id: @account.id, id: @migration.to_param)
|
||||
end
|
||||
|
||||
it "should return migration" do
|
||||
json = api_call(:get, @migration_url, @params)
|
||||
json['id'].should == @migration.id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'create' do
|
||||
|
||||
before do
|
||||
@params = {:controller => 'content_migrations', :format => 'json', :course_id => @course.id.to_param, :action => 'create'}
|
||||
@post_params = {:migration_type => 'common_cartridge_importer', :pre_attachment => {:name => "test.zip"}}
|
||||
|
@ -232,7 +267,7 @@ describe ContentMigrationsController, type: :request do
|
|||
it "should queue a migration" do
|
||||
@post_params.delete :pre_attachment
|
||||
p = Canvas::Plugin.new("hi")
|
||||
p.stubs(:settings).returns('worker' => 'CCWorker')
|
||||
p.stubs(:settings).returns({'worker' => 'CCWorker', 'valid_contexts' => ['Course']}.with_indifferent_access)
|
||||
Canvas::Plugin.stubs(:find).returns(p)
|
||||
json = api_call(:post, @migration_url, @params, @post_params)
|
||||
json["workflow_state"].should == 'running'
|
||||
|
@ -243,7 +278,9 @@ describe ContentMigrationsController, type: :request do
|
|||
|
||||
it "should not queue a migration if do_not_run flag is set" do
|
||||
@post_params.delete :pre_attachment
|
||||
Canvas::Plugin.stubs(:find).returns(Canvas::Plugin.new("oi"))
|
||||
p = Canvas::Plugin.new("hi")
|
||||
p.stubs(:settings).returns({'worker' => 'CCWorker', 'valid_contexts' => ['Course']}.with_indifferent_access)
|
||||
Canvas::Plugin.stubs(:find).returns(p)
|
||||
json = api_call(:post, @migration_url, @params, @post_params.merge(:do_not_run => true))
|
||||
json["workflow_state"].should == 'pre_processing'
|
||||
migration = ContentMigration.find json['id']
|
||||
|
@ -403,6 +440,23 @@ describe ContentMigrationsController, type: :request do
|
|||
migration.context.should eql @group
|
||||
end
|
||||
end
|
||||
|
||||
context "Account" do
|
||||
before do
|
||||
@account = Account.create!(:name => 'migration account')
|
||||
@account.add_user(@user)
|
||||
@migration_url = "/api/v1/accounts/#{@account.id}/content_migrations"
|
||||
@params = @params.reject{|k| k == :course_id}.merge(:account_id => @account.to_param)
|
||||
end
|
||||
|
||||
it "should queue a migration" do
|
||||
json = api_call(:post, @migration_url, @params,
|
||||
{ :migration_type => 'qti_converter',
|
||||
:settings => { :file_url => 'http://example.com/oi.zip' }})
|
||||
migration = ContentMigration.find json['id']
|
||||
migration.context.should eql @account
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'update' do
|
||||
|
|
Binary file not shown.
|
@ -63,7 +63,6 @@ end
|
|||
|
||||
def get_import_context(system=nil)
|
||||
context = course_model
|
||||
context.imported_migration_items = []
|
||||
context.import_source == :webct if system == 'vista'
|
||||
|
||||
context
|
||||
|
|
|
@ -966,7 +966,7 @@ XML
|
|||
ag.migration_id = "i713e960ab2685259505efeb08cd48a1d"
|
||||
ag.save!
|
||||
|
||||
Importers::QuizImporter.import_from_migration(quiz_hash, @copy_to, {})
|
||||
Importers::QuizImporter.import_from_migration(quiz_hash, @copy_to, nil, {})
|
||||
q = @copy_to.quizzes.find_by_migration_id("ie3d8f8adfad423eb225229c539cdc450")
|
||||
a = q.assignment
|
||||
a.assignment_group.id.should == ag.id
|
||||
|
|
|
@ -417,6 +417,7 @@ describe "More Standard Common Cartridge importing" do
|
|||
@migration.stubs(:to_import).returns(nil)
|
||||
@migration.stubs(:context).returns(@copy_to)
|
||||
@migration.stubs(:import_object?).returns(true)
|
||||
@migration.stubs(:add_imported_item)
|
||||
end
|
||||
|
||||
it "should properly handle top-level resource references" do
|
||||
|
|
|
@ -2411,4 +2411,73 @@ equation: <img class="equation_image" title="Log_216" src="/equation_images/Log_
|
|||
worker.perform(cm)
|
||||
end
|
||||
|
||||
context "account-level import" do
|
||||
it "should import question banks from qti migrations" do
|
||||
pending unless Qti.qti_enabled?
|
||||
|
||||
account = Account.create!(:name => 'account')
|
||||
@user = user
|
||||
account.add_user(@user)
|
||||
cm = ContentMigration.new(:context => account, :user => @user)
|
||||
cm.migration_type = 'qti_converter'
|
||||
cm.migration_settings['import_immediately'] = true
|
||||
qb_name = 'Import Unfiled Questions Into Me'
|
||||
cm.migration_settings['question_bank_name'] = qb_name
|
||||
cm.save!
|
||||
|
||||
package_path = File.join(File.dirname(__FILE__) + "/../fixtures/migration/cc_default_qb_test.zip")
|
||||
attachment = Attachment.new
|
||||
attachment.context = cm
|
||||
attachment.uploaded_data = File.open(package_path, 'rb')
|
||||
attachment.filename = 'file.zip'
|
||||
attachment.save!
|
||||
|
||||
cm.attachment = attachment
|
||||
cm.save!
|
||||
|
||||
cm.queue_migration
|
||||
run_jobs
|
||||
|
||||
cm.migration_issues.should be_empty
|
||||
|
||||
account.assessment_question_banks.count.should == 1
|
||||
bank = account.assessment_question_banks.first
|
||||
bank.title.should == qb_name
|
||||
|
||||
bank.assessment_questions.count.should == 1
|
||||
end
|
||||
|
||||
it "should import questions from quizzes into question banks" do
|
||||
pending unless Qti.qti_enabled?
|
||||
|
||||
account = Account.create!(:name => 'account')
|
||||
@user = user
|
||||
account.add_user(@user)
|
||||
cm = ContentMigration.new(:context => account, :user => @user)
|
||||
cm.migration_type = 'qti_converter'
|
||||
cm.migration_settings['import_immediately'] = true
|
||||
cm.save!
|
||||
|
||||
package_path = File.join(File.dirname(__FILE__) + "/../fixtures/migration/quiz_qti.zip")
|
||||
attachment = Attachment.new
|
||||
attachment.context = cm
|
||||
attachment.uploaded_data = File.open(package_path, 'rb')
|
||||
attachment.filename = 'file.zip'
|
||||
attachment.save!
|
||||
|
||||
cm.attachment = attachment
|
||||
cm.save!
|
||||
|
||||
cm.queue_migration
|
||||
run_jobs
|
||||
|
||||
cm.migration_issues.should be_empty
|
||||
|
||||
account.assessment_question_banks.count.should == 1
|
||||
bank = account.assessment_question_banks.first
|
||||
bank.title.should == "Unnamed Quiz"
|
||||
|
||||
bank.assessment_questions.count.should == 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -689,20 +689,4 @@ describe ContextExternalTool do
|
|||
expect { ContextExternalTool.find_for("horseshoes", @course, :course_navigation) }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
|
||||
describe "import_from_migration" do
|
||||
it "should work for course-level tools" do
|
||||
course_model
|
||||
tool = Importers::ContextExternalToolImporter.import_from_migration({:title => 'tool', :url => 'http://example.com'}, @course)
|
||||
tool.should_not be_nil
|
||||
tool.context.should == @course
|
||||
end
|
||||
|
||||
it "should work for account-level tools" do
|
||||
course_model
|
||||
tool = Importers::ContextExternalToolImporter.import_from_migration({:title => 'tool', :url => 'http://example.com'}, @course.account)
|
||||
tool.should_not be_nil
|
||||
tool.context.should == @course.account
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -427,24 +427,6 @@ describe Group do
|
|||
group.group_category.should == group_category
|
||||
end
|
||||
|
||||
context "import_from_migration" do
|
||||
it "should respect group_category from the hash" do
|
||||
course_with_teacher
|
||||
group = @course.groups.build
|
||||
@course.imported_migration_items = []
|
||||
Importers::GroupImporter.import_from_migration({:group_category => "random category"}, @course, group)
|
||||
group.group_category.name.should == "random category"
|
||||
end
|
||||
|
||||
it "should default group_category to imported if not in the hash" do
|
||||
course_with_teacher
|
||||
group = @course.groups.build
|
||||
@course.imported_migration_items = []
|
||||
Importers::GroupImporter.import_from_migration({}, @course, group)
|
||||
group.group_category.should == GroupCategory.imported_for(@course)
|
||||
end
|
||||
end
|
||||
|
||||
it "as_json should include group_category" do
|
||||
course()
|
||||
gc = group_category(name: "Something")
|
||||
|
|
|
@ -32,7 +32,6 @@ describe "Assessment Question import from hash" do
|
|||
|
||||
it "should only import assessment question once" do
|
||||
context = get_import_context
|
||||
context.imported_migration_items ||= []
|
||||
data = get_import_data '', 'single_question'
|
||||
data = {'assessment_questions'=>{'assessment_questions'=>data}}
|
||||
|
||||
|
@ -49,7 +48,6 @@ describe "Assessment Question import from hash" do
|
|||
|
||||
it "should update assessment question on re-import" do
|
||||
context = get_import_context
|
||||
context.imported_migration_items ||= []
|
||||
data = get_import_data '', 'single_question'
|
||||
data = {'assessment_questions'=>{'assessment_questions'=>data}}
|
||||
|
||||
|
@ -138,7 +136,7 @@ describe "Assessment Question import from hash" do
|
|||
question_data[question[:migration_id]] = context.assessment_questions.find_by_migration_id(question[:migration_id])
|
||||
|
||||
quiz = get_import_data 'cengage', 'quiz'
|
||||
Importers::QuizImporter.import_from_migration(quiz, context, question_data)
|
||||
Importers::QuizImporter.import_from_migration(quiz, context, nil, question_data)
|
||||
quiz = context.quizzes.find_by_migration_id(quiz[:migration_id])
|
||||
|
||||
group = quiz.quiz_groups.first
|
||||
|
|
|
@ -30,7 +30,6 @@ module Importers
|
|||
let(:attachment) { stub(:context= => true, :migration_id= => true, :save_without_broadcasting! => true) }
|
||||
|
||||
before :each do
|
||||
course.imported_migration_items = []
|
||||
course.stubs(:id).returns(course_id)
|
||||
migration.stubs(:import_object?).with('attachments', migration_id).returns(true)
|
||||
end
|
||||
|
@ -56,7 +55,7 @@ module Importers
|
|||
|
||||
Importers::AttachmentImporter.process_migration(data, migration)
|
||||
|
||||
course.imported_migration_items.should == [attachment]
|
||||
migration.imported_migration_items.should == [attachment]
|
||||
end
|
||||
|
||||
it "imports attachments when the migration id is in the files_to_import hash" do
|
||||
|
@ -136,26 +135,6 @@ module Importers
|
|||
Importers::AttachmentImporter.process_migration(data, migration)
|
||||
end
|
||||
|
||||
it "does not add to the imported_migration_items if imported_migration_items is nil" do
|
||||
data = {
|
||||
'file_map' => {
|
||||
'a' => {
|
||||
id: attachment_id,
|
||||
migration_id: migration_id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
course.imported_migration_items = nil
|
||||
::Attachment.expects(:find_by_context_type_and_context_id_and_id).with("Course", course_id, attachment_id).returns(attachment)
|
||||
migration.expects(:import_object?).with('attachments', migration_id).returns(true)
|
||||
attachment.expects(:save_without_broadcasting!)
|
||||
|
||||
Importers::AttachmentImporter.process_migration(data, migration)
|
||||
|
||||
course.imported_migration_items.should == nil
|
||||
end
|
||||
|
||||
it "does not import files that are not part of the migration" do
|
||||
data = {
|
||||
'file_map' => {
|
||||
|
|
|
@ -72,7 +72,7 @@ describe Importers::CalendarEventImporter do
|
|||
it 'initializes a calendar event based on hash data' do
|
||||
event = migration_course.calendar_events.build
|
||||
hash = {
|
||||
migration_id: 42,
|
||||
migration_id: '42',
|
||||
title: 'event title',
|
||||
description: 'the event description',
|
||||
start_at: Time.now,
|
||||
|
@ -80,10 +80,10 @@ describe Importers::CalendarEventImporter do
|
|||
attachment_type: 'external_url',
|
||||
attachment_value: 'http://example.com'
|
||||
}
|
||||
Importers::CalendarEventImporter.import_from_migration(hash, migration_course, event)
|
||||
Importers::CalendarEventImporter.import_from_migration(hash, migration_course, nil, event)
|
||||
event.should_not be_new_record
|
||||
event.imported.should be_true
|
||||
event.migration_id.should == 42
|
||||
event.migration_id.should == '42'
|
||||
event.title.should == 'event title'
|
||||
event.description.should match('the event description')
|
||||
event.description.should match('example.com')
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb')
|
||||
|
||||
describe Importers::ContextExternalToolImporter do
|
||||
it "should work for course-level tools" do
|
||||
course_model
|
||||
tool = Importers::ContextExternalToolImporter.import_from_migration({:title => 'tool', :url => 'http://example.com'}, @course)
|
||||
tool.should_not be_nil
|
||||
tool.context.should == @course
|
||||
end
|
||||
|
||||
it "should work for account-level tools" do
|
||||
course_model
|
||||
tool = Importers::ContextExternalToolImporter.import_from_migration({:title => 'tool', :url => 'http://example.com'}, @course.account)
|
||||
tool.should_not be_nil
|
||||
tool.context.should == @course.account
|
||||
end
|
||||
end
|
|
@ -308,7 +308,7 @@ describe Course do
|
|||
|
||||
Auditors::Course.expects(:record_copied).once.with(migration.source_course, @course, migration.user, source: migration.initiated_source)
|
||||
|
||||
@course.import_from_migration(data, params, migration)
|
||||
Importers::CourseContentImporter.import_content(@course, data, params, migration)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -62,4 +62,17 @@ describe "Importing Groups" do
|
|||
group.discussion_topics.count.should == 1
|
||||
end
|
||||
|
||||
it "should respect group_category from the hash" do
|
||||
course_with_teacher
|
||||
group = @course.groups.build
|
||||
Importers::GroupImporter.import_from_migration({:group_category => "random category"}, @course, nil, group)
|
||||
group.group_category.name.should == "random category"
|
||||
end
|
||||
|
||||
it "should default group_category to imported if not in the hash" do
|
||||
course_with_teacher
|
||||
group = @course.groups.build
|
||||
Importers::GroupImporter.import_from_migration({}, @course, nil, group)
|
||||
group.group_category.should == GroupCategory.imported_for(@course)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -27,6 +27,7 @@ describe "Importing Rubrics" do
|
|||
context = get_import_context(system)
|
||||
migration = stub()
|
||||
migration.stubs(:context).returns(context)
|
||||
migration.stubs(:add_imported_item)
|
||||
|
||||
data[:rubrics_to_import] = {}
|
||||
Importers::RubricImporter.import_from_migration(data, migration).should be_nil
|
||||
|
|
|
@ -27,7 +27,7 @@ describe "Importers::QuizImporter" do
|
|||
context = course_model
|
||||
question_data = import_example_questions context
|
||||
data = get_import_data ['vista', 'quiz'], 'simple_quiz_data'
|
||||
Importers::QuizImporter.import_from_migration(data, context, question_data)
|
||||
Importers::QuizImporter.import_from_migration(data, context, nil, question_data)
|
||||
quiz = Quizzes::Quiz.find_by_migration_id data[:migration_id]
|
||||
quiz.title.should == data[:title]
|
||||
quiz.scoring_policy.should == data[:which_attempt_to_keep]
|
||||
|
@ -42,7 +42,7 @@ describe "Importers::QuizImporter" do
|
|||
context = course_model
|
||||
question_data = import_example_questions context
|
||||
data = get_import_data ['vista', 'quiz'], 'simple_quiz_data'
|
||||
Importers::QuizImporter.import_from_migration(data, context, question_data)
|
||||
Importers::QuizImporter.import_from_migration(data, context, nil, question_data)
|
||||
quiz = Quizzes::Quiz.find_by_migration_id data[:migration_id]
|
||||
quiz.quiz_questions.active.count.should == 1
|
||||
# Check if the expected question name is in there
|
||||
|
@ -53,7 +53,7 @@ describe "Importers::QuizImporter" do
|
|||
context = get_import_context
|
||||
question_data = import_example_questions context
|
||||
data = get_import_data ['vista', 'quiz'], 'text_only_quiz_data'
|
||||
Importers::QuizImporter.import_from_migration(data, context, question_data)
|
||||
Importers::QuizImporter.import_from_migration(data, context, nil, question_data)
|
||||
quiz = Quizzes::Quiz.find_by_migration_id data[:migration_id]
|
||||
quiz.unpublished_question_count.should == 2
|
||||
quiz.quiz_questions.active.count.should == 2
|
||||
|
@ -66,7 +66,7 @@ describe "Importers::QuizImporter" do
|
|||
context = get_import_context
|
||||
question_data = import_example_questions context
|
||||
data = get_import_data ['vista', 'quiz'], 'group_quiz_data'
|
||||
Importers::QuizImporter.import_from_migration(data, context, question_data)
|
||||
Importers::QuizImporter.import_from_migration(data, context, nil, question_data)
|
||||
quiz = Quizzes::Quiz.find_by_migration_id data[:migration_id]
|
||||
quiz.quiz_groups.count.should == 1
|
||||
quiz.quiz_groups.first.quiz_questions.active.count.should == 3
|
||||
|
@ -78,8 +78,8 @@ describe "Importers::QuizImporter" do
|
|||
context = get_import_context
|
||||
question_data = import_example_questions context
|
||||
data = get_import_data ['vista', 'quiz'], 'text_only_quiz_data'
|
||||
Importers::QuizImporter.import_from_migration(data, context, question_data)
|
||||
Importers::QuizImporter.import_from_migration(data, context, question_data)
|
||||
Importers::QuizImporter.import_from_migration(data, context, nil, question_data)
|
||||
Importers::QuizImporter.import_from_migration(data, context, nil, question_data)
|
||||
Quizzes::Quiz.count.should == 1
|
||||
quiz = Quizzes::Quiz.find_by_migration_id data[:migration_id]
|
||||
quiz.assignment.should be_nil
|
||||
|
@ -89,8 +89,8 @@ describe "Importers::QuizImporter" do
|
|||
context = get_import_context
|
||||
question_data = import_example_questions context
|
||||
data = get_import_data ['vista', 'quiz'], 'simple_quiz_data'
|
||||
Importers::QuizImporter.import_from_migration(data, context, question_data)
|
||||
Importers::QuizImporter.import_from_migration(data, context, question_data)
|
||||
Importers::QuizImporter.import_from_migration(data, context, nil, question_data)
|
||||
Importers::QuizImporter.import_from_migration(data, context, nil, question_data)
|
||||
|
||||
Assignment.count.should == 0
|
||||
Quizzes::Quiz.count.should == 1
|
||||
|
@ -105,8 +105,8 @@ describe "Importers::QuizImporter" do
|
|||
context.root_account.enable_feature!(:draft_state)
|
||||
question_data = import_example_questions context
|
||||
data = get_import_data ['vista', 'quiz'], 'simple_quiz_data'
|
||||
Importers::QuizImporter.import_from_migration(data, context, question_data)
|
||||
Importers::QuizImporter.import_from_migration(data, context, question_data)
|
||||
Importers::QuizImporter.import_from_migration(data, context, nil, question_data)
|
||||
Importers::QuizImporter.import_from_migration(data, context, nil, question_data)
|
||||
|
||||
Assignment.count.should == 1
|
||||
Quizzes::Quiz.count.should == 1
|
||||
|
@ -129,13 +129,13 @@ describe "Importers::QuizImporter" do
|
|||
context = get_import_context
|
||||
question_data = import_example_questions context
|
||||
data = get_import_data ['vista', 'quiz'], 'simple_quiz_data'
|
||||
Importers::QuizImporter.import_from_migration(data, context, question_data)
|
||||
Importers::QuizImporter.import_from_migration(data, context, nil, question_data)
|
||||
quiz = Quizzes::Quiz.find_by_migration_id data[:migration_id]
|
||||
|
||||
quiz.quiz_questions.active.first.question_data[:question_name].should == "Rocket Bee!"
|
||||
|
||||
question_data[:aq_data][data['questions'].first[:migration_id]]['question_name'] = "Not Rocket Bee?"
|
||||
Importers::QuizImporter.import_from_migration(data, context, question_data)
|
||||
Importers::QuizImporter.import_from_migration(data, context, nil, question_data)
|
||||
|
||||
quiz.quiz_questions.active.first.question_data[:question_name].should == "Not Rocket Bee?"
|
||||
end
|
||||
|
|
|
@ -13,7 +13,8 @@ Rails.configuration.to_prepare do
|
|||
:common_core_guid => AcademicBenchmark::Converter::COMMON_CORE_GUID,
|
||||
:worker => 'CCWorker',
|
||||
:converter_class => AcademicBenchmark::Converter,
|
||||
:provides => {:academic_benchmark => AcademicBenchmark::Converter}
|
||||
:provides => {:academic_benchmark => AcademicBenchmark::Converter},
|
||||
:valid_contexts => %w{Account}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
|
|
@ -9,7 +9,8 @@ Rails.configuration.to_prepare do
|
|||
:settings => {
|
||||
:migration_partial => 'moodle_config',
|
||||
:worker=> 'CCWorker',
|
||||
:provides =>{:moodle_1_9=>Moodle::Converter, :moodle_2=>Moodle::Converter}
|
||||
:provides =>{:moodle_1_9=>Moodle::Converter, :moodle_2=>Moodle::Converter},
|
||||
:valid_contexts => %w{Account Course}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
|
|
@ -16,7 +16,8 @@ Rails.configuration.to_prepare do
|
|||
:requires_file_upload => true,
|
||||
:provides =>{:qti=>Qti::Converter,
|
||||
:webct=>Qti::Converter, # It can import WebCT Quizzes
|
||||
}
|
||||
},
|
||||
:valid_contexts => %w{Account Course}
|
||||
},
|
||||
:validator => 'QtiPluginValidator'
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue