# frozen_string_literal: true require_relative "../base" require_relative "support/settings" require_relative "database/database" require_relative "importers/importer_factory" module ImportScripts::PhpBB3 class Importer < ImportScripts::Base # @param settings [ImportScripts::PhpBB3::Settings] # @param database [ImportScripts::PhpBB3::Database_3_0 | ImportScripts::PhpBB3::Database_3_1] def initialize(settings, database) @settings = settings super() @database = database @php_config = database.get_config_values @importers = ImporterFactory.new(@database, @lookup, @uploader, @settings, @php_config) end def perform super if settings_check_successful? end protected def execute puts "", "importing from phpBB #{@php_config[:phpbb_version]}" SiteSetting.tagging_enabled = true if @settings.tag_mappings.present? import_users import_anonymous_users if @settings.import_anonymous_users import_groups import_user_groups import_new_categories import_categories import_posts import_private_messages if @settings.import_private_messages import_bookmarks if @settings.import_bookmarks import_likes if @settings.import_likes end def change_site_settings super @importers.permalink_importer.change_site_settings end def get_site_settings_for_import settings = super max_file_size_kb = @database.get_max_attachment_size settings[:max_image_size_kb] = [max_file_size_kb, SiteSetting.max_image_size_kb].max settings[:max_attachment_size_kb] = [max_file_size_kb, SiteSetting.max_attachment_size_kb].max # temporarily disable validation since we want to import all existing images and attachments SiteSetting.type_supervisor.load_setting( :max_image_size_kb, max: settings[:max_image_size_kb], ) SiteSetting.type_supervisor.load_setting( :max_attachment_size_kb, max: settings[:max_attachment_size_kb], ) settings end def settings_check_successful? true end def import_users puts "", "creating users" total_count = @database.count_users importer = @importers.user_importer last_user_id = 0 batches do |offset| rows, last_user_id = @database.fetch_users(last_user_id, @settings.custom_fields) rows = rows.to_a.uniq { |row| row[:user_id] } break if rows.size < 1 create_users(rows, total: total_count, offset: offset) do |row| begin next if user_id_from_imported_user_id(@settings.prefix(row[:user_id])) importer.map_user(row) rescue => e log_error("Failed to map user with ID #{row[:user_id]}", e) end end end end def import_anonymous_users puts "", "creating anonymous users" total_count = @database.count_anonymous_users importer = @importers.user_importer last_username = "" batches do |offset| rows, last_username = @database.fetch_anonymous_users(last_username) break if rows.size < 1 create_users(rows, total: total_count, offset: offset) do |row| begin next if user_id_from_imported_user_id(@settings.prefix(row[:post_username])) importer.map_anonymous_user(row) rescue => e log_error("Failed to map anonymous user with ID #{row[:user_id]}", e) end end end end def import_groups puts "", "creating groups" rows = @database.fetch_groups create_groups(rows) do |row| begin next if row[:group_type] == 3 group_name = if @settings.site_name.present? "#{@settings.site_name}_#{row[:group_name]}" else row[:group_name] end[ 0..19 ].gsub(/[^a-zA-Z0-9\-_. ]/, "_") bio_raw = begin @importers.text_processor.process_raw_text(row[:group_desc]) rescue StandardError row[:group_desc] end { id: @settings.prefix(row[:group_id]), name: group_name, full_name: row[:group_name], bio_raw: bio_raw, } rescue => e log_error("Failed to map group with ID #{row[:group_id]}", e) end end end def import_user_groups puts "", "creating user groups" rows = @database.fetch_group_users rows.each do |row| group_id = @lookup.group_id_from_imported_group_id(@settings.prefix(row[:group_id])) next if !group_id user_id = @lookup.user_id_from_imported_user_id(@settings.prefix(row[:user_id])) begin GroupUser.find_or_create_by( user_id: user_id, group_id: group_id, owner: row[:group_leader], ) rescue => e log_error("Failed to add user #{row[:user_id]} to group #{row[:group_id]}", e) end end end def import_new_categories puts "", "creating new categories" create_categories(@settings.new_categories) do |row| next if row == "SKIP" { id: @settings.prefix(row[:forum_id]), name: row[:name], parent_category_id: @lookup.category_id_from_imported_category_id(@settings.prefix(row[:parent_id])), } end end def import_categories puts "", "creating categories" rows = @database.fetch_categories importer = @importers.category_importer create_categories(rows) do |row| next if @settings.category_mappings.dig(row[:forum_id].to_s, :skip) importer.map_category(row) end end def import_posts puts "", "creating topics and posts" total_count = @database.count_posts importer = @importers.post_importer last_post_id = 0 batches do |offset| rows, last_post_id = @database.fetch_posts(last_post_id) break if rows.size < 1 create_posts(rows, total: total_count, offset: offset) do |row| begin next if post_id_from_imported_post_id(@settings.prefix(row[:post_id])) importer.map_post(row) rescue => e log_error("Failed to map post with ID #{row[:post_id]}", e) end end end end def import_private_messages puts "", "creating private messages" total_count = @database.count_messages importer = @importers.message_importer last_msg_id = 0 batches do |offset| rows, last_msg_id = @database.fetch_messages(last_msg_id) break if rows.size < 1 create_posts(rows, total: total_count, offset: offset) do |row| begin next if post_id_from_imported_post_id(@settings.prefix("pm:#{row[:msg_id]}")) importer.map_message(row) rescue => e log_error("Failed to map message with ID #{row[:msg_id]}", e) end end end end def import_bookmarks puts "", "creating bookmarks" total_count = @database.count_bookmarks importer = @importers.bookmark_importer last_user_id = last_topic_id = 0 batches do |offset| rows, last_user_id, last_topic_id = @database.fetch_bookmarks(last_user_id, last_topic_id) break if rows.size < 1 create_bookmarks(rows, total: total_count, offset: offset) do |row| begin importer.map_bookmark(row) rescue => e log_error("Failed to map bookmark (#{row[:user_id]}, #{row[:topic_first_post_id]})", e) end end end end def import_likes puts "", "importing likes" total_count = @database.count_likes last_post_id = last_user_id = 0 batches do |offset| rows, last_post_id, last_user_id = @database.fetch_likes(last_post_id, last_user_id) break if rows.size < 1 create_likes(rows, total: total_count, offset: offset) do |row| { post_id: @settings.prefix(row[:post_id]), user_id: @settings.prefix(row[:user_id]), created_at: Time.zone.at(row[:thanks_time]), } end end end def update_last_seen_at # no need for this since the importer sets last_seen_at for each user during the import end # Do not use the bbcode_to_md in base.rb. It will be used in text_processor.rb instead. def use_bbcode_to_md? false end def batches super(@settings.database.batch_size) end def log_error(message, e) puts message puts e.message puts e.backtrace.join("\n") end end end