#!/usr/bin/ruby require File.dirname(__FILE__) + '/../config/environment' include ActionController::UrlWriter SCRIPT_TYPE = File.basename($PROGRAM_NAME) IMPORT_DIR = ENV['IMPORT_DIR'] || '/home/terceiro/src/cooperation-migration/data/export' if ARGV.size == 0 puts "usage: %s [ [ ... ] ]" % $PROGRAM_NAME exit(1) end def import_environment(domain_name) env = Environment.default env.domains << get_domain(domain_name) return Environment.default end def get_domain(envname) suffix = (ENV['RAILS_ENV'] == 'production') ? '' : '.local' domain = Domain.find_or_create_by_name(envname + suffix) end TinyMceArticle # forces loading the Noosfero class before adding stuff to it class TinyMceArticle attr_accessor :is_homepage end UploadedFile # force loading Noosfero class before addinf stuff to it class UploadedFile attr_accessor :is_homepage, :filesystem_location end Person class FileData < StringIO attr_reader :original_filename, :content_type def initialize(actual_filename, name, content_type) @original_filename = name @content_type = content_type super(File.read(actual_filename)) end end class Progress DEBUG = true class << self def start(n) @total = n @current = 0 end def step @current += 1 end def step_done say('=> done', true) end def step_failed say('=> FAILED', true) end def say(msg, force = Progress::DEBUG) puts("[%d/%d] %s" % [@current, @total, msg]) if force end end end FORBIDDEN_LOGINS = %w[ info ] Progress.start(ARGV.size) for username in ARGV Progress.step begin User.transaction do # guess environment domain_name = username.gsub(/^.*@/, '') environment = import_environment(domain_name) login = username.gsub(/@.*$/, '') if FORBIDDEN_LOGINS.include?(login) $stderr.puts "E: not importing #{username}, #{login} is not an allowed login" next end profile = nil if SCRIPT_TYPE == 'import-cooperation.net-groups' # import as a group imported_data = Hash.from_xml(File.read(File.join(IMPORT_DIR, username + '.xml')))['person'] profile = Community.create!( :identifier => login, :name => login, :contact_email => imported_data['email'], :address => imported_data['address'], :environment => environment, :preferred_domain_id => get_domain(domain_name).id ) elsif SCRIPT_TYPE == 'import-cooperation.net-articles' # only load the articles profile = Profile[login] else # import as a user # create user user = User.new(:login => login, :email => username, :environment => environment) user.enable_email = true # import person data imported_data = Hash.from_xml(File.read(File.join(IMPORT_DIR, username + '.xml')))['person'] user.crypted_password = imported_data.delete(:crypted_password.to_s) user.salt = imported_data.delete(:salt.to_s) user.password_type = imported_data.delete(:password_type.to_s) user.person_data = imported_data.merge('preferred_domain_id' => get_domain(domain_name).id) user.save! Progress.say "I: #{username} data imported" profile = user.person end # import articles Dir.glob(File.join(IMPORT_DIR, username, 'articles', '*.xml')) do |xml| Progress.say "I: Trying to import #{username}'s article in #{xml} ..." article = TinyMceArticle.new article.from_xml(File.read(xml)) article.profile = profile if article.valid? article.save! Progress.say "I: #{username}'s article #{article.name.inspect} imported" else $stderr.puts "W: #{username}'s article #{article.name.inspect} cannot be saved. Errors: #{article.errors.full_messages.join(', ')}" next end if article.is_homepage profile.home_page = article profile.save! Progress.say "I: Article #{article.name.inspect} is #{username}'s homepage!" end orig_article_number = File.basename(xml).sub(/\.xml$/, '') File.open("tmp/rewrite-articles.txt", 'a') do |file| file.puts("#{orig_article_number}\t\t\t#{url_for(article.url)}") Progress.say "I: Article with id = #{article.id} redirected to #{url_for(article.url)}" end # import attachments attachments_dir = xml.gsub(/\.xml$/, '') Dir.glob(File.join(attachments_dir, 'attachments', '*.xml')).each do |attachment_xml| file = UploadedFile.new file.from_xml(File.read(attachment_xml)) if !File.exist?(file.filesystem_location) Progress.say "W: skipping attachment pointing to unexisting file" next end Progress.say "I: about to read data from #{file.filesystem_location} (xml: #{attachment_xml})" file.uploaded_data = FileData.new(file.filesystem_location, file.filename, file.content_type) file.parent = article file.profile = profile Progress.say "I: Trying to save attachment \"#{file.filename}/#{file.slug}\"" file.save! Progress.say "I: attachment added to article #{article.id}" file.reload if file.image? file.parent.body ||= '' file.parent.body = " " + file.parent.body else if file.parent.body file.parent.body += "
#{file.abstract}
" end end file.parent.save orig_file_number = File.basename(attachment_xml).gsub(/\.xml$/, '') File.open('tmp/rewrite-files.txt', 'a') do |outfile| outfile.puts("#{orig_file_number}\t\t\t#{url_for(file.url)}") Progress.say "I: Attachment with id = #{orig_article_number} redirected to #{url_for(file.url)}" end end end if SCRIPT_TYPE != 'import-cooperation.net-articles' # import menus for i in [1,2] links = [] data = Hash.from_xml(File.read(File.join(IMPORT_DIR, username, "menu#{i}.xml"))) data['menu']['items'].each do |item| links << { :name => item['title'], :address => item['url'] } end block = profile.blocks.select { |block| block.class == LinkListBlock }[i-1] block.title = data['menu']['title'] block.links = links block.save! Progress.say "imported links: #{links.inspect}" end end end Progress.step_done rescue Exception => e $stderr.puts "==================================" $stderr.puts "E: importing <#{username}> failed." $stderr.puts e $stderr.puts e.backtrace $stderr.puts "==================================" $stderr.puts "E: Note that ALL operations above relative to <#{username}> were CANCELLED due to these errors." Progress.step_failed end end