discourse/lib/import_export/importer.rb

165 lines
4.7 KiB
Ruby

require File.join(Rails.root, 'script', 'import_scripts', 'base.rb')
module ImportExport
class Importer < ImportScripts::Base
def initialize(data)
@users = data[:users]
@groups = data[:groups]
@categories = data[:categories]
@topics = data[:topics]
# To support legacy `category_export` script
if data[:category].present?
@categories = [] if @categories.blank?
@categories << data[:category]
end
end
def perform
RateLimiter.disable
import_users
import_groups
import_categories
import_topics
self
ensure
RateLimiter.enable
end
def import_users
return if @users.blank?
@users.each do |u|
import_id = "#{u[:id]}#{import_source}"
existing = User.with_email(u[:email]).first
if existing
if existing.custom_fields["import_id"] != import_id
existing.custom_fields["import_id"] = import_id
existing.save!
end
else
u = create_user(u, import_id) # see ImportScripts::Base
end
end
self
end
def import_groups
return if @groups.blank?
@groups.each do |group_data|
g = group_data.dup
user_ids = g.delete(:user_ids)
external_id = g.delete(:id)
new_group = Group.find_by_name(g[:name]) || Group.create!(g)
user_ids.each do |external_user_id|
new_group.add(User.find(new_user_id(external_user_id))) rescue ActiveRecord::RecordNotUnique
end
end
self
end
def import_categories
return if @categories.blank?
import_ids = @categories.collect { |c| "#{c[:id]}#{import_source}" }
existing_categories = CategoryCustomField.where("name = 'import_id' AND value IN (?)", import_ids).select(:category_id, :value).to_a
existing_category_ids = existing_categories.pluck(:value)
@categories.reject! { |c| existing_category_ids.include? c[:id].to_s }
@categories.sort_by! { |c| c[:parent_category_id].presence || 0 }
@categories.each do |cat_attrs|
begin
id = cat_attrs.delete(:id)
permissions = cat_attrs.delete(:permissions_params)
category = Category.new(cat_attrs)
category.parent_category_id = new_category_id(cat_attrs[:parent_category_id]) if cat_attrs[:parent_category_id].present?
category.user_id = new_user_id(cat_attrs[:user_id])
import_id = "#{id}#{import_source}"
category.custom_fields["import_id"] = import_id
category.permissions = permissions.present? ? permissions : { "everyone" => CategoryGroup.permission_types[:full] }
category.save!
existing_categories << { category_id: category.id, value: import_id }
if cat_attrs[:description].present?
post = category.topic.ordered_posts.first
post.raw = cat_attrs[:description]
post.save!
post.rebake!
end
rescue
next
end
end
self
end
def import_topics
return if @topics.blank?
@topics.each do |t|
puts ""
print t[:title]
first_post_attrs = t[:posts].first.merge(t.slice(*(TopicExporter::TOPIC_ATTRS - [:id, :category_id])))
first_post_attrs[:user_id] = new_user_id(first_post_attrs[:user_id])
first_post_attrs[:category] = new_category_id(t[:category_id])
import_id = "#{first_post_attrs[:id]}#{import_source}"
first_post = PostCustomField.where(name: "import_id", value: import_id).first&.post
unless first_post
first_post = create_post(first_post_attrs, import_id)
end
topic_id = first_post.topic_id
t[:posts].each_with_index do |post_data, i|
next if i == 0
print "."
post_import_id = "#{post_data[:id]}#{import_source}"
existing = PostCustomField.where(name: "import_id", value: post_import_id).first&.post
unless existing
# see ImportScripts::Base
create_post(
post_data.merge(
topic_id: topic_id,
user_id: new_user_id(post_data[:user_id])
),
post_import_id
)
end
end
end
puts ""
self
end
def new_user_id(external_user_id)
ucf = UserCustomField.where(name: "import_id", value: "#{external_user_id}#{import_source}").first
ucf ? ucf.user_id : Discourse::SYSTEM_USER_ID
end
def new_category_id(external_category_id)
CategoryCustomField.where(name: "import_id", value: "#{external_category_id}#{import_source}").first.category_id rescue nil
end
def import_source
@_import_source ||= "#{ENV['IMPORT_SOURCE'] || ''}"
end
end
end