<?php /*

 Composr
 Copyright (c) ocProducts, 2004-2016

 See text/EN/licence.txt for full licencing information.


 NOTE TO PROGRAMMERS:
   Do not edit this file. If you need to make changes, save your changed file to the appropriate *_custom folder
   **** If you ignore this advice, then your website upgrades (e.g. for bug fixes) will likely kill your changes ****

*/

/**
 * @license    http://opensource.org/licenses/cpal_1.0 Common Public Attribution License
 * @copyright  ocProducts Ltd
 * @package    import
 */

/*
In Composr we have cms_merge and we have Resource-fs.

Resource-fs is intended for staging site functionality and backups, mainly.
cms_merge is intended to merge disparate sites in a more complete way.

There is overlap, but intentionally each approach is optimised in a different way.
*/

// LEGACY: There's a lot of stuff to clean up here. We only want to support 2 versions back, max. Officially 0. Plus importing from ocPortal won't usually work due to the multi-lang-content mode (you'll get lots of numbers instead of content).

/**
 * Hook class.
 */
class Hook_cms_merge
{
    /**
     * Standard importer hook info function.
     *
     * @return ?array Importer handling details, including lists of all the import types covered (import types are not necessarily the same as actual tables) (null: importer is disabled).
     */
    public function info()
    {
        $info = array();
        $info['supports_advanced_import'] = true;
        $info['product'] = do_lang('COMPOSR_SITE_MERGER');
        $info['prefix'] = 'cms_';
        $info['import'] = array(
            'attachments',
            'cns_groups',
            'cns_custom_profile_fields',
            'cns_members',
            'authors',
            'banners',
            'calendar',
            'catalogues', // including rating, trackbacks, seo
            'points_gifts_and_charges', // including leader board
            'chat_rooms',
            'config',
            'custom_comcode',
            'comcode_pages',
            'staff_checklist_cus_tasks',
            'notifications',
            'awards',
            'downloads_and_categories', // including rating, trackbacks, seo
            'cns_forum_groupings',
            'cns_emoticons',
            'cns_forums', // including intros
            'cns_topics', // including readlogs // including description remapping for comment topics
            'cns_multi_moderations',
            'cns_polls_and_votes',
            'cns_post_templates',
            'cns_posts',
            'cns_warnings',
            'cns_saved_warnings',
            'filedump',
            'images_and_galleries', // including rating, trackbacks, seo
            'match_key_messages',
            'menu_items',
            'news_and_categories', // including rating, trackbacks, seo
            'newsletter_subscriptions',
            'polls', // including rating, trackbacks, seo
            'pointstore',
            'redirects',
            'searches_saved',
            'staff_links',
            'staff_website_monitoring',
            'wiki', // including rating, trackbacks, seo
            'stats',
            'themes',
            'support_tickets',
            'useronline_tracking',
            'ip_bans',
            'wordfilter',
            'zones',
            'permissions', // including HTTPS
            'attachment_references',
            'feedback',
            'ecommerce',
            'cns_welcome_emails',
            'bookmarks',
            'quizzes',
        );
        $info['dependencies'] = array( // This dependency tree is overdefined, but I wanted to make it clear what depends on what, rather than having a simplified version
                                       'attachment_references' => array('attachments', 'cns_members', 'cns_posts', 'news_and_categories', 'wiki'),
                                       'permissions' => array_diff($info['import'], array('feedback', 'attachment_references', 'permissions', 'bookmarks', 'stats')),
                                       'feedback' => array_diff($info['import'], array('themes', 'cns_warnings', 'feedback', 'attachment_references', 'permissions', 'quizzes', 'bookmarks', 'stats')),
                                       'authors' => array('cns_members', 'catalogues'),
                                       'banners' => array('cns_members'),
                                       'catalogues' => array('cns_members'),
                                       'notifications' => array('cns_members'),
                                       'chat_rooms' => array('cns_members', 'cns_groups'),
                                       'downloads_and_categories' => array('cns_members', 'catalogues'),
                                       'filedump' => array('cns_members'),
                                       'searches_saved' => array('cns_members'),
                                       'images_and_galleries' => array('cns_members', 'catalogues'),
                                       'news_and_categories' => array('cns_members', 'attachments', 'catalogues'),
                                       'polls' => array('cns_members', 'catalogues'),
                                       'pointstore' => array('cns_members'),
                                       'wiki' => array('cns_members', 'attachments', 'catalogues'),
                                       'useronline_tracking' => array('cns_members'),
                                       'ip_bans' => array('cns_members'),
                                       'points_gifts_and_charges' => array('cns_members'),
                                       'calendar' => array('cns_members', 'catalogues'),
                                       'comcode_pages' => array('cns_members', 'catalogues'),
                                       'match_key_messages' => array(),
                                       'menu_items' => array(),
                                       'cns_custom_profile_fields' => array('cns_groups'),
                                       'cns_multi_moderations' => array('cns_forums'),
                                       //'cns_groups' => array('catalogues'), Cyclic dependency, so we won't do this one
                                       'cns_members' => array('cns_groups', 'cns_custom_profile_fields', 'attachments'),
                                       'cns_forums' => array('cns_forum_groupings', 'cns_members', 'cns_groups', 'catalogues'),
                                       'cns_topics' => array('cns_forums', 'cns_members', 'catalogues'),
                                       'cns_polls_and_votes' => array('cns_topics', 'cns_members'),
                                       'cns_posts' => array('custom_comcode', 'cns_topics', 'cns_members', 'attachments', 'catalogues'),
                                       'cns_private_topics' => array('custom_comcode', 'cns_members'),
                                       'cns_post_templates' => array('cns_forums'),
                                       'cns_warnings' => array('cns_members', 'cns_groups', 'cns_topics', 'cns_forums'),
                                       'newsletter_subscriptions' => array('attachments'),
                                       'support_tickets' => array('cns_forums', 'cns_topics', 'cns_members'),
                                       'awards' => array('calendar', 'wiki', 'news_and_categories', 'images_and_galleries', 'catalogues', 'authors', 'cns_topics', 'cns_posts', 'cns_forums', 'cns_groups', 'cns_members', 'downloads_and_categories'),
                                       'ecommerce' => array('cns_groups', 'cns_members'),
                                       'cns_welcome_emails' => array('cns_members'),
                                       'bookmarks' => array('cns_members'),
                                       'quizzes' => array('cns_members', 'catalogues'),
                                       'aggregate_type_instances' => array(),
        );

        $_cleanup_url = build_url(array('page' => 'admin_cleanup'), get_module_zone('admin_cleanup'));
        $cleanup_url = $_cleanup_url->evaluate();
        $info['message'] = (get_param_string('type', 'browse') != 'import' && get_param_string('type', 'browse') != 'hook') ? new Tempcode() : do_lang_tempcode('FORUM_CACHE_CLEAR', escape_html($cleanup_url));

        return $info;
    }

    /**
     * Do some tests, to make sure we're happy to continue importing.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     * @return ?Tempcode Error/warning UI (null: no error/warning)
     */
    public function pre_import_tests($db, $table_prefix, $file_base)
    {
        $title = get_screen_title('IMPORT');

        $bad = false;

        // Check actually is Composr DB (ERROR)
        $test = $db->query_select_value('zones', 'zone_name');
        if (is_null($test)) {
            return warn_screen($title, do_lang_tempcode('ERROR_NOT_CORRECT_DATABASE'));
        }

        // Check version (WARNING)
        $test = $db->query_select_value_if_there('values', 'the_value', array('the_name' => 'version'));
        if ((is_null($test)) || (intval($test) != cms_version())) {
            attach_message(do_lang_tempcode('ERROR_NOT_CORRECT_VERSION'), 'notice');
            $bad = true;
        }

        // Check actually is Composr file path (ERROR)
        if (((!file_exists($file_base . '/_config.php')) && (!file_exists($file_base . '/info.php'))) || (!file_exists($file_base . '/sources_custom'))) {
            attach_message(do_lang_tempcode('ERROR_NOT_CORRECT_FILES'), 'warn');
            if ((is_on_multi_site_network($db)) && (!file_exists($file_base . '/_config.php')) && (!file_exists($file_base . '/info.php'))) {
                attach_message(do_lang_tempcode('ERROR_NOT_CORRECT_LINKING_POSSIBLY'), 'warn');
            }
            $bad = true;
        }

        // Check is on same MSN or is Conversr (WARNING)
        if (file_exists($file_base . '/_config.php')) {
            global $SITE_INFO;
            $backup_site_info = $SITE_INFO;
            $SITE_INFO = null;
            @include($file_base . '/_config.php');
            if (is_null($SITE_INFO)) {
                $SITE_INFO = $backup_site_info;
                attach_message(do_lang_tempcode('ERROR_INACCESSIBLE_DIR'), 'warn');
                if (is_on_multi_site_network($db)) {
                    attach_message(do_lang_tempcode('ERROR_NOT_CORRECT_LINKING_POSSIBLY'), 'warn');
                }
                $bad = true;
            } else {
                $this_site_info = $SITE_INFO;
                $SITE_INFO = $backup_site_info;
                if (empty($SITE_INFO['db_forums_host'])) {
                    $SITE_INFO['db_forums_host'] = 'localhost';
                }
                $same_forum = (!isset($SITE_INFO['db_forums'])) || ($this_site_info['db_forums'] == $SITE_INFO['db_forums']) && ($this_site_info['db_forums_host'] == $SITE_INFO['db_forums_host']) && ($db->table_prefix);
                if (($this_site_info['forum_type'] != 'cns') && (!$same_forum)) {
                    attach_message(do_lang_tempcode('ERROR_NOT_CORRECT_LINKING'), 'warn');
                    $bad = true;
                }
            }
        }

        // Show warning
        if ($bad) {
            return do_template('CONFIRM_SCREEN', array('_GUID' => '286928b79830cdff4ac506e4f4f00f3a', 'TITLE' => $title, 'PREVIEW' => do_lang_tempcode('IMPORT_WARNINGS_GIVEN'), 'FIELDS' => build_keep_post_fields(), 'URL' => get_self_url(false, false, array('happy' => 1))));
        }

        return null;
    }

    /**
     * See if the importing site is on the same M.S.N. as the site being imported.
     *
     * @param  PATH $file_base The path to the imported site
     * @return boolean Answer
     */
    public function on_same_msn($file_base)
    {
        if (get_param_integer('keep_on_same_msn', null) === 0) {
            return false;
        }
        if (get_param_integer('keep_on_same_msn', null) === 1) {
            return true;
        }

        //return false;
        global $SITE_INFO;
        $backup_site_info = $SITE_INFO;
        $SITE_INFO = mixed();
        @include($file_base . '/_config.php');
        $sites_site_info = $SITE_INFO;
        $SITE_INFO = $backup_site_info;

        $answer = ($sites_site_info['db_forums'] == get_db_forums()) && ($sites_site_info['db_forums_host'] == get_db_forums_host()) && (@$sites_site_info['cns_table_prefix'] === @$SITE_INFO['cns_table_prefix']);

        return $answer;
    }

    /**
     * Fetch and clean up a language string.
     *
     * @param  object $db The DB connection to import from
     * @param  integer $id The string ID
     * @return string The cleaned-up string
     */
    public function get_lang_string($db, $id)
    {
        if (is_null($id)) {
            return '';
        }

        global $HAS_MULTI_LANG_CONTENT;
        $bak = $HAS_MULTI_LANG_CONTENT;
        $HAS_MULTI_LANG_CONTENT = is_integer($id);
        $text = get_translated_text($id, $db);
        $HAS_MULTI_LANG_CONTENT = $bak;

        $text = $this->update_comcode($text);

        return $text;
    }

    /**
     * Import some Comcode, making changes as required.
     *
     * @param  string $comcode Input
     * @param  ?ID_TEXT $referer_id Attachment referer type (null: not setting one now)
     * @return string Output
     */
    public function update_comcode($comcode, $referer_id = null)
    {
        $matches = array();
        $count = preg_match_all('#\](\d+)\[/attachment\]#', $comcode, $matches);
        if ($count != 0) {
            for ($i = 0; $i < $count; $i++) {
                $from = $matches[1][$i];
                $to = import_id_remap_get('attachment', $from, true);
                if (is_null($to)) {
                    $to = -1;
                }
                $comcode = str_replace(']' . $from . '[/attachment]', ']' . strval($to) . '[/attachment]', $comcode);

                if ($referer_id !== null) {
                    $GLOBALS['SITE_DB']->query_insert('attachment_refs', array('r_referer_type' => 'comcode_page', 'r_referer_id' => $referer_id, 'a_id' => $to), false, true);
                }
            }
        }

        return $comcode;
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_cns_welcome_emails($db, $table_prefix, $file_base)
    {
        if ($this->on_same_msn($file_base)) {
            return;
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_welcome_emails', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            if (import_check_if_imported('welcome_email', strval($row['id']))) {
                continue;
            }

            cns_make_welcome_email($row['w_name'], $this->get_lang_string($db, $row['w_subject']), $this->get_lang_string($db, $row['w_text']), $row['w_send_time'], array_key_exists('w_newsletter', $row) ? $row['w_newsletter'] : null, array_key_exists('w_usergroup', $row) ? $row['w_usergroup'] : null, array_key_exists('w_usergroup_type', $row) ? $row['w_usergroup_type'] : '');

            import_id_remap_put('welcome_email', strval($row['id']), 0);
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_bookmarks($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'bookmarks', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            $owner = $on_same_msn ? $row['b_owner'] : import_id_remap_get('member', strval($row['b_owner']), true);
            if (is_null($owner)) {
                $owner = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }

            $GLOBALS['SITE_DB']->query_insert('bookmarks', array('b_owner' => $owner, 'b_folder' => $row['b_folder'], 'b_title' => $row['b_title'], 'b_page_link' => $row['b_page_link']));
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_quizzes($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . ($db->table_exists('quizzes') ? 'quizzes' : 'quiz') . ' ORDER BY id', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            if (import_check_if_imported('quiz', strval($row['id']))) {
                continue;
            }

            unset($row['q_start_text__text_parsed']);
            unset($row['q_start_text__source_user']);
            unset($row['q_end_text__text_parsed']);
            unset($row['q_end_text__source_user']);
            unset($row['q_end_text_fail__text_parsed']);
            unset($row['q_end_text_fail__source_user']);

            if (!array_key_exists('q_add_date', $row)) {
                $row['q_add_date'] = time();
            }
            if (!array_key_exists('q_validated', $row)) {
                $row['q_validated'] = 1;
            }
            if (!array_key_exists('q_submitter', $row)) {
                $row['q_submitter'] = get_member();
            }

            $start_text = is_integer($row['q_start_text']) ? $this->get_lang_string($db, $row['q_start_text']) : $row['q_start_text'];
            $end_text = is_integer($row['q_end_text']) ? $this->get_lang_string($db, $row['q_end_text']) : $row['q_end_text'];
            if (!isset($row['q_end_text_fail'])) {
                $row['q_end_text_fail'] = '';
            }
            $end_text_fail = is_integer($row['q_end_text_fail']) ? $this->get_lang_string($db, $row['q_end_text_fail']) : $row['q_end_text_fail'];

            $map = array(
                'q_timeout' => $row['q_timeout'],
                'q_notes' => $row['q_notes'],
                'q_percentage' => $row['q_percentage'],
                'q_open_time' => $row['q_open_time'],
                'q_close_time' => $row['q_close_time'],
                'q_num_winners' => $row['q_num_winners'],
                'q_redo_time' => $row['q_redo_time'],
                'q_type' => array_key_exists('q_type', $row) ? $row['q_type'] : 'MULTIPLECHOICE',
                'q_validated' => $row['q_validated'],
                'q_submitter' => $row['q_submitter'],
                'q_add_date' => $row['q_add_date'],
                'q_points_for_passing' => array_key_exists('q_points_for_passing', $row) ? $row['q_points_for_passing'] : 0,
                'q_reveal_answers' => array_key_exists('q_reveal_answers', $row) ? $row['q_reveal_answers'] : 0,
                'q_shuffle_questions' => array_key_exists('q_shuffle_questions', $row) ? $row['q_shuffle_questions'] : 0,
                'q_shuffle_answers' => array_key_exists('q_shuffle_answers', $row) ? $row['q_shuffle_answers'] : 0,
            );
            $map += insert_lang('q_name', $this->get_lang_string($db, $row['q_name']), 2);
            $map += insert_lang_comcode('q_start_text', $start_text, 2);
            $map += insert_lang_comcode('q_end_text', $end_text, 2);
            $map += insert_lang_comcode('q_end_text_fail', $end_text_fail, 2);
            if (get_param_integer('keep_preserve_ids', 0) == 1) {
                $map['id'] = $row['id'];
            }
            $id_new = $GLOBALS['SITE_DB']->query_insert('quizzes', $map, true);

            import_id_remap_put('quiz', strval($row['id']), $id_new);
        }
        $this->_import_content_reviews($db, $table_prefix, 'quiz', 'quiz');
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'quiz_questions');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $i => $row) {
            if (import_check_if_imported('quiz_question', strval($row['id']))) {
                continue;
            }

            $quiz = import_id_remap_get('quiz', strval($row['q_quiz']), true);
            if (is_null($quiz)) {
                continue;
            }

            unset($row['q_question_text__text_parsed']);
            unset($row['q_question_text__source_user']);
            unset($row['q_question_extra_text__text_parsed']);
            unset($row['q_question_extra_text__source_user']);

            if (!isset($row['q_type'])) {
                $row['q_type'] = 'MULTIPLECHOICE';
            }
            if ((isset($row['q_long_input_field'])) && ($row['q_long_input_field'] == 1)) {
                $row['q_type'] = 'LONG';
            }
            if ((isset($row['q_num_choosable_answers'])) && ($row['q_num_choosable_answers'] > 0)) {
                $row['q_type'] = 'MULTIMULTIPLE';
            }

            $map = array(
                'q_order' => array_key_exists('q_order', $row) ? $row['q_order'] : $i,
                'q_type' => $row['q_type'],
                'q_quiz' => $quiz,
                'q_required' => array_key_exists('q_required', $row) ? $row['q_required'] : 0,
                'q_marked' => array_key_exists('q_marked', $row) ? $row['q_marked'] : 1,
            );
            $map += insert_lang_comcode('q_question_text', $this->get_lang_string($db, $row['q_question_text']), 2);
            $map += insert_lang_comcode('q_question_extra_text', $this->get_lang_string($db, array_key_exists('q_question_extra_text', $row) ? $row['q_question_extra_text'] : ''), 2);
            $id_new = $GLOBALS['SITE_DB']->query_insert('quiz_questions', $map, true);

            import_id_remap_put('quiz_question', strval($row['id']), $id_new);
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'quiz_question_answers');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $i => $row) {
            $question = import_id_remap_get('quiz_question', strval($row['q_question']), true);
            if (is_null($question)) {
                continue;
            }

            unset($row['q_answer_text__text_parsed']);
            unset($row['q_answer_text__source_user']);

            $map = array(
                'q_order' => array_key_exists('q_order', $row) ? $row['q_order'] : $i,
                'q_question' => $question,
                'q_is_correct' => $row['q_is_correct'],
            );
            $map += insert_lang_comcode('q_answer_text', array_key_exists('q_answer_text', $row) ? $this->get_lang_string($db, $row['q_answer_text']) : '', 2);
            $map += insert_lang('q_explanation', array_key_exists('q_explanation', $row) ? $this->get_lang_string($db, $row['q_explanation']) : '', 2);
            $GLOBALS['SITE_DB']->query_insert('quiz_question_answers', $map);
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'quiz_entries');
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            if (import_check_if_imported('quiz_entry', strval($row['id']))) {
                continue;
            }

            $quiz = import_id_remap_get('quiz', strval($row['q_quiz']), true);
            if (is_null($quiz)) {
                continue;
            }
            $member = $on_same_msn ? $row['q_member'] : import_id_remap_get('member', strval($row['q_member']), true);
            if (is_null($member)) {
                $member = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }

            $id_new = $GLOBALS['SITE_DB']->query_insert('quiz_entries', array(
                'q_time' => $row['q_time'],
                'q_member' => $member,
                'q_quiz' => $quiz,
                'q_results' => $row['q_results'],
            ), true);

            import_id_remap_put('quiz_entry', strval($row['id']), $id_new);
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'quiz_entry_answer');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $question = import_id_remap_get('quiz_question', strval($row['q_question']), true);
            if (is_null($question)) {
                continue;
            }
            $entry = import_id_remap_get('quiz_entry', strval($row['q_entry']));

            $GLOBALS['SITE_DB']->query_insert('quiz_entry_answer', array('q_entry' => $entry, 'q_question' => $question, 'q_answer' => $row['q_answer']));
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'quiz_winner');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $quiz = import_id_remap_get('quiz', strval($row['q_quiz']), true);
            if (is_null($quiz)) {
                continue;
            }
            $entry = import_id_remap_get('quiz_entry', strval($row['q_entry']), true);
            if (is_null($entry)) {
                continue;
            }

            $GLOBALS['SITE_DB']->query_insert('quiz_winner', array('q_quiz' => $quiz, 'q_entry' => $entry, 'q_winner_level' => $row['q_winner_level']));
        }

        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'quiz', 'quiz');
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_ecommerce($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'transactions', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            foreach (array('purchase_id' => 't_purchase_id', 'status' => 't_status', 'reason' => 't_reason', 'amount' => 't_amount', 'linked' => 't_parent_txn_id', 'item' => 't_type_code', 'pending_reason' => 't_pending_reason') as $old => $new) {
                if ((!array_key_exists($new, $row)) && (array_key_exists($old, $row))) {
                    $row[$new] = $row[$old];
                    unset($row[$old]);
                }
            }

            $GLOBALS['SITE_DB']->query_insert('transactions', $row);
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'invoices ORDER BY id');
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            $row['i_member_id'] = $on_same_msn ? $row['i_member_id'] : import_id_remap_get('member', strval($row['i_member_id']), true);
            if (is_null($row['i_member_id'])) {
                continue; // Uh oh - someones deleted and they had invoices - lets hope they paid them ;)
            }
            if (get_param_integer('keep_preserve_ids', 0) == 0) {
                unset($row['id']);
            }
            $GLOBALS['SITE_DB']->query_insert('invoices', $row);
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_usergroup_subs', null, null, true);
        if (!is_null($rows)) {
            $this->_fix_comcode_ownership($rows);
            foreach ($rows as $row) {
                if (import_check_if_imported('usergroup_sub', strval($row['id']))) {
                    continue;
                }

                $group_id = $on_same_msn ? $row['s_group_id'] : import_id_remap_get('group', strval($row['s_group_id']), true);
                if (is_null($group_id)) {
                    continue;
                }

                $map = array(
                    's_cost' => $row['s_cost'],
                    's_length' => $row['s_length'],
                    's_length_units' => $row['s_length_units'],
                    's_auto_recur' => array_key_exists('s_auto_recur', $row) ? $row['s_auto_recur'] : 1,
                    's_group_id' => $group_id,
                    's_enabled' => $row['s_enabled'],
                );
                $map += insert_lang('s_title', $this->get_lang_string($db, $row['s_title']), 2);
                $map += insert_lang('s_description', $this->get_lang_string($db, $row['s_description']), 2);
                $map += insert_lang('s_mail_start', $this->get_lang_string($db, $row['s_mail_start']), 2);
                $map += insert_lang('s_mail_end', $this->get_lang_string($db, $row['s_mail_end']), 2);
                $map += insert_lang('s_mail_uhoh', $this->get_lang_string($db, $row['s_mail_uhoh']), 2);
                $id_new = $GLOBALS['SITE_DB']->query_insert('f_usergroup_subs', $map, true);

                $mails = $db->query_select('f_usergroup_sub_mails', array('*'), array('m_usergroup_sub_id' => $row['id']));
                $this->_fix_comcode_ownership($mails);
                foreach ($mails as $mail) {
                    $map = array(
                        'm_usergroup_sub_id' => $id_new,
                        'm_ref_point' => $mail['m_ref_point'],
                        'm_ref_point_offset' => $mail['m_ref_point_offset'],
                    );
                    $map += insert_lang('m_subject', $this->get_lang_string($db, $mail['m_subject']), 2);
                    $map += insert_lang('m_body', $this->get_lang_string($db, $mail['m_body']), 2);
                    $GLOBALS['SITE_DB']->query_insert('f_usergroup_sub_mails', $map);
                }

                import_id_remap_put('usergroup_sub', strval($row['id']), $id_new);
            }
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'subscriptions ORDER BY id');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $row['s_member_id'] = $on_same_msn ? $row['s_member_id'] : import_id_remap_get('member', strval($row['s_member_id']), true);
            if (is_null($row['s_member_id'])) {
                continue; // Uh oh - someones deleted and they had invoices - lets hope they paid them ;)
            }
            if (substr($row['s_type_code'], 0, 9) == 'USERGROUP') {
                $remap_id = import_id_remap_get('usergroup_sub', substr($row['s_type_code'], 9), true);
                if (is_null($remap_id)) {
                    continue;
                }
                $row['s_type_code'] = 'USERGROUP' . strval($remap_id);
            }
            if (get_param_integer('keep_preserve_ids', 0) == 0) {
                unset($row['id']);
            }
            $GLOBALS['SITE_DB']->query_insert('subscriptions', $row);
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_attachments($db, $table_prefix, $file_base)
    {
        $row_start = 0;
        $rows = array();
        do {
            $rows = $db->query('SELECT * FROM ' . $table_prefix . 'attachments ORDER BY id', 200, $row_start);
            $this->_fix_comcode_ownership($rows);
            foreach ($rows as $row) {
                if (import_check_if_imported('attachment', strval($row['id']))) {
                    continue;
                }

                $row['a_member_id'] = -$row['a_member_id']; // This is resolved when importing members
                $row_copy = $row;
                if (get_param_integer('keep_preserve_ids', 0) == 0) {
                    unset($row_copy['id']);
                }
                if (!array_key_exists('a_description', $row_copy)) {
                    $row_copy['a_description'] = '';
                }
                $id_new = $GLOBALS['SITE_DB']->query_insert('attachments', $row_copy, true);

                import_id_remap_put('attachment', strval($row['id']), $id_new);
            }
            $row_start += 200;
        } while (count($rows) > 0);
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_attachment_references($db, $table_prefix, $file_base)
    {
        $row_start = 0;
        $rows = array();
        do {
            $rows = $db->query('SELECT * FROM ' . $table_prefix . 'attachment_refs', 200, $row_start);
            $this->_fix_comcode_ownership($rows);
            foreach ($rows as $row) {
                $import_type_fixed = $row['r_referer_type'];
                if ($import_type_fixed == 'cns_post') {
                    $import_type_fixed = 'post';
                }
                if ($import_type_fixed == 'cedi_post') {
                    $import_type_fixed = 'wiki_post';
                }
                if ($import_type_fixed == 'cedi_page') {
                    $import_type_fixed = 'wiki_page';
                }

                $id_new = import_id_remap_get($import_type_fixed, $row['r_referer_id'], true);
                if (is_null($id_new)) {
                    $id_new = $row['r_referer_id'];
                }

                $aid = import_id_remap_get('attachment', strval($row['a_id']), true);
                if (!is_null($aid)) {
                    $GLOBALS['SITE_DB']->query_insert('attachment_refs', array('r_referer_type' => $row['r_referer_type'], 'r_referer_id' => $id_new, 'a_id' => $aid), false, true);
                }
            }
            $row_start += 200;
        } while (count($rows) > 0);
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_feedback($db, $table_prefix, $file_base)
    {
        $type_remap = array('downloads_category' => 'download_category', 'downloads_download' => 'download', 'downloads' => 'download');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'rating');
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            $remapped = $row['rating_for_type'];
            if (array_key_exists($remapped, $type_remap)) {
                $remapped = $type_remap[$remapped];
            }

            unset($row['id']);
            if (is_numeric($row['rating_for_id'])) {
                $id_new = import_id_remap_get($remapped, $row['rating_for_id'], true);
                if (!is_null($id_new)) {
                    $row['rating_for_id'] = strval($id_new);
                }
            }
            $row['rating_member'] = $on_same_msn ? $row['rating_member'] : import_id_remap_get('member', strval($row['rating_member']), true);
            if (is_null($row['rating_member'])) {
                $row['rating_member'] = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }
            $GLOBALS['SITE_DB']->query_insert('rating', $row);
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'trackbacks');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $remapped = $row['trackback_for_type'];
            if (array_key_exists($remapped, $type_remap)) {
                $remapped = $type_remap[$remapped];
            }

            unset($row['id']);
            if (is_numeric($row['trackback_for_id'])) {
                $id_new = import_id_remap_get($remapped, $row['trackback_for_id'], true);
                if (!is_null($id_new)) {
                    $row['trackback_for_id'] = strval($id_new);
                }
            }
            $GLOBALS['SITE_DB']->query_insert('trackbacks', $row);
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'seo_meta');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $remapped = $row['meta_for_type'];
            if (array_key_exists($remapped, $type_remap)) {
                $remapped = $type_remap[$remapped];
            }

            unset($row['id']);

            if (is_numeric($row['meta_for_id'])) {
                $id_new = import_id_remap_get($remapped, $row['meta_for_id'], true);
                if (!is_null($id_new)) {
                    $row['meta_for_id'] = strval($id_new);
                }
            }

            if (isset($row['meta_keywords'])) {
                $keywords = explode(',', $this->get_lang_string($db, $row['meta_keywords']));

                unset($row['meta_keywords']);

                foreach ($keywords as $keyword) {
                    $meta_row = array('meta_for_type' => $row['meta_for_type'], 'meta_for_id' => $row['meta_for_id']);
                    $meta_row = insert_lang('meta_keyword', $keyword, 2) + $meta_row;
                    $GLOBALS['SITE_DB']->query_insert('seo_meta_keywords', $meta_row);
                }
            }

            $row = insert_lang('meta_description', $this->get_lang_string($db, $row['meta_description']), 2) + $row;
            $GLOBALS['SITE_DB']->query_insert('seo_meta', $row);
        }

        if ($db->table_exists('seo_meta_keywords')) {
            $rows = $db->query('SELECT * FROM ' . $table_prefix . 'seo_meta_keywords');
            $this->_fix_comcode_ownership($rows);
            foreach ($rows as $row) {
                $remapped = $row['meta_for_type'];
                if (array_key_exists($remapped, $type_remap)) {
                    $remapped = $type_remap[$remapped];
                }

                unset($row['id']);

                if (is_numeric($row['meta_for_id'])) {
                    $id_new = import_id_remap_get($remapped, $row['meta_for_id'], true);
                    if (!is_null($id_new)) {
                        $row['meta_for_id'] = strval($id_new);
                    }
                }

                $row = insert_lang('meta_keyword', $this->get_lang_string($db, $row['meta_keyword']), 2) + $row;
                $GLOBALS['SITE_DB']->query_insert('seo_meta_keywords', $row);
            }
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_authors($db, $table_prefix, $file_base)
    {
        require_code('authors');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'authors', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('authors', 'author', array('author' => $row['author']));
            if (is_null($test)) {
                add_author($row['author'], $row['url'], array_key_exists('member_id', $row) ? $row['member_id'] : $row['forum_handle'], $this->get_lang_string($db, $row['description']), $this->get_lang_string($db, $row['skills']));
            }
        }
        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'author', null);
        $this->_import_content_reviews($db, $table_prefix, 'author', null);
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_banners($db, $table_prefix, $file_base)
    {
        require_code('banners2');

        if ($db->table_exists('banner_types')) {
            $rows = $db->query('SELECT * FROM ' . $table_prefix . 'banner_types');
            $this->_fix_comcode_ownership($rows);
            foreach ($rows as $row) {
                $test = $GLOBALS['SITE_DB']->query_select_value_if_there('banner_types', 'id', array('id' => $row['id']));
                if (is_null($test)) {
                    add_banner_type($row['id'], $row['t_is_textual'], $row['t_image_width'], $row['t_image_height'], $row['t_max_file_size'], $row['t_comcode_inline']);
                }
            }
            $this->_import_content_reviews($db, $table_prefix, 'banner_type', null);
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'banners', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('banners', 'name', array('name' => $row['name']));
            if (is_null($test)) {
                $submitter = $on_same_msn ? $row['submitter'] : import_id_remap_get('member', strval($row['submitter']), true);
                if (is_null($submitter)) {
                    $submitter = $GLOBALS['FORUM_DRIVER']->get_guest_id();
                }
                add_banner(
                    $row['name'],
                    $row['img_url'],
                    array_key_exists('b_title_text', $row) ? $row['b_title_text'] : '',
                    $this->get_lang_string($db, $row['caption']),
                    array_key_exists('direct_code', $row) ? $row['direct_code'] : '',
                    $row['campaign_remaining'],
                    array_key_exists('site_url', $row) ? $row['site_url'] : $row['siteurl'],
                    $row['importance_modulus'],
                    $row['notes'],
                    $row['the_type'],
                    $row['expiry_date'],
                    $submitter,
                    $row['validated'],
                    $row['b_type'],
                    $db->table_exists('banner_types') ? collapse_1d_complexity('b_type', $db->query_select('banners_types', array('b_type'), array('name' => $row['name']))) : array(),
                    $db->table_exists('content_regions') ? collapse_1d_complexity('region', $db->query_select('content_regions', array('region'), array('content_type' => 'banner', 'content_id' => $row['name']))) : array(),
                    $row['add_date'],
                    $row['hits_from'],
                    $row['hits_to'],
                    $row['views_from'],
                    $row['views_to'],
                    $row['edit_date']
                );
            }
        }
        $this->_import_content_reviews($db, $table_prefix, 'banner', null);
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_points_gifts_and_charges($db, $table_prefix, $file_base)
    {
        require_code('points2');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'chargelog', null, null, true);
        if (is_null($rows)) {
            $rows = array();
        }
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            if (!array_key_exists('member_id', $row)) {
                $row['member_id'] = $row['user_id'];
            }

            $member = $on_same_msn ? $row['member_id'] : import_id_remap_get('member', strval($row['member_id']), true);
            if (is_null($member)) {
                $member = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }
            add_to_charge_log($member, $row['amount'], $this->get_lang_string($db, $row['reason']), $row['date_and_time']);
        }
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'gifts', null, null, true);
        if (is_null($rows)) {
            $rows = array();
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            unset($row['reason__text_parsed']);
            unset($row['reason__source_user']);

            $viewer_member = $on_same_msn ? $row['gift_from'] : import_id_remap_get('member', strval($row['gift_from']), true);
            $member = $on_same_msn ? $row['gift_to'] : import_id_remap_get('member', strval($row['gift_to']), true);
            if (is_null($viewer_member)) {
                $viewer_member = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }
            if (is_null($member)) {
                $member = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }
            $map = array(
                'date_and_time' => $row['date_and_time'],
                'amount' => $row['amount'],
                'gift_from' => $viewer_member,
                'gift_to' => $member,
                'anonymous' => $row['anonymous'],
            );
            $map += insert_lang_comcode('reason', $this->get_lang_string($db, $row['reason']), 4);
            $GLOBALS['SITE_DB']->query_insert('gifts', $map);
        }
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'leader_board', null, null, true);
        if (is_null($rows)) {
            $rows = array();
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $member = $on_same_msn ? $row['lb_member'] : import_id_remap_get('member', strval($row['lb_member']), true);
            if (is_null($member)) {
                continue;
            }
            $GLOBALS['SITE_DB']->query_delete('leader_board', array('lb_member' => $member, 'lb_points' => $row['lb_points'], 'date_and_time' => $row['date_and_time']), '', 1);
            $GLOBALS['SITE_DB']->query_insert('leader_board', array('lb_member' => $member, 'lb_points' => $row['lb_points'], 'date_and_time' => $row['date_and_time']));
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_config($db, $table_prefix, $file_base)
    {
        $remap = array(
            'post_history_days' => 'post_read_history_days',
            'text' => 'community_billboard',
            'is_on_flagrant_buy' => 'is_on_community_billboard_buy',
            'leaderboard_start_date' => 'leader_board_start_date',
            'is_on_seedy' => 'is_on_wiki',
            'points_cedi' => 'points_wiki',
            'cedi_show_stats_count_pages' => 'wiki_show_stats_count_pages',
            'cedi_show_stats_count_posts' => 'wiki_show_stats_count_posts',
            'system_flagrant' => 'system_community_billboard',
            'ocp_show_conceded_mode_link' => 'show_conceded_mode_link',
            'ocp_show_personal_adminzone_link' => 'show_personal_adminzone_link',
            'ocp_show_personal_last_visit' => 'show_personal_last_visit',
            'ocp_show_personal_sub_links' => 'show_personal_sub_links',
            'ocp_show_personal_usergroup' => 'show_personal_usergroup',
            'ocp_show_staff_page_actions' => 'show_staff_page_actions',
            'ocp_show_su' => 'show_su',
            'ocp_show_avatar' => 'show_avatar',
        );

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'config');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $name = isset($row['c_name']) ? $row['c_name'] : $row['the_name'];
            if (isset($remap[$name])) {
                $name = $remap[$name];
            }

            $value = isset($row['c_value']) ? $row['c_value'] : $row['config_value'];

            if ((!is_null($value)) && ($row['c_set'] == 1)) {
                if ((isset($row['c_needs_dereference'])) && ($row['c_needs_dereference'] == 1)) {
                    $value = $this->get_lang_string($db, $row['c_value_trans']);
                }

                $test = get_option($name, true);
                if (!is_null($test)) {
                    set_option($name, $value);
                }
            }
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_polls($db, $table_prefix, $file_base)
    {
        require_code('polls2');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'poll', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            if (import_check_if_imported('poll', strval($row['id']))) {
                continue;
            }

            $submitter = $on_same_msn ? $row['submitter'] : import_id_remap_get('member', strval($row['submitter']), true);
            if (is_null($submitter)) {
                $submitter = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }
            $id_new = add_poll($this->get_lang_string($db, $row['question']),
                $this->get_lang_string($db, $row['option1']),
                $this->get_lang_string($db, $row['option2']),
                $this->get_lang_string($db, $row['option3']),
                $this->get_lang_string($db, $row['option4']),
                $this->get_lang_string($db, $row['option5']),
                array_key_exists('option6', $row) ? $this->get_lang_string($db, $row['option6']) : '',
                array_key_exists('option7', $row) ? $this->get_lang_string($db, $row['option7']) : '',
                array_key_exists('option8', $row) ? $this->get_lang_string($db, $row['option8']) : '',
                array_key_exists('option9', $row) ? $this->get_lang_string($db, $row['option9']) : '',
                array_key_exists('option10', $row) ? $this->get_lang_string($db, $row['option10']) : '',
                $row['num_options'],
                $row['is_current'],
                $row['allow_rating'],
                $row['allow_comments'],
                $row['allow_trackbacks'],
                $row['notes'],
                $row['add_time'],
                $submitter,
                $row['date_and_time'],
                $row['votes1'],
                $row['votes2'],
                $row['votes3'],
                $row['votes4'],
                $row['votes5'],
                array_key_exists('votes6', $row) ? $row['votes6'] : 0,
                array_key_exists('votes7', $row) ? $row['votes7'] : 0,
                array_key_exists('votes8', $row) ? $row['votes8'] : 0,
                array_key_exists('votes9', $row) ? $row['votes9'] : 0,
                array_key_exists('votes10', $row) ? $row['votes10'] : 0,
                $row['poll_views'],
                $row['edit_date']);

            // Who has voted in the poll?
            $votes = $db->query('SELECT * FROM ' . $table_prefix . 'poll_votes WHERE v_poll_id=' . strval($row['id']), null, null, true);
            if (is_null($votes)) { // Old Composr-style
                $voters = explode('-', $row['ip']);
                $votes = array();
                foreach ($voters as $voter) {
                    $votes[] = array(
                        'v_poll_id' => $row['id'],
                        'v_voter_id' => is_numeric($voter) ? intval($voter) : null,
                        'v_voter_ip' => is_numeric($voter) ? '' : $voter,
                        'v_vote_for' => null,
                    );
                }
            }
            foreach ($votes as $vote) {
                $GLOBALS['SITE_DB']->query_insert('poll_votes', array(
                    'v_poll_id' => $id_new,
                    'v_voter_id' => $vote['v_voter_id'],
                    'v_voter_ip' => $vote['v_voter_ip'],
                    'v_vote_for' => $vote['v_vote_for'],
                ));
            }

            import_id_remap_put('poll', strval($row['id']), $id_new);
        }
        $this->_import_review_supplement($db, $table_prefix, 'polls', 'poll');
        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'poll', 'poll');
        $this->_import_content_reviews($db, $table_prefix, 'poll', 'poll');
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_news_and_categories($db, $table_prefix, $file_base)
    {
        require_code('news2');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'news_categories ORDER BY id', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            if (import_check_if_imported('news_category', strval($row['id']))) {
                continue;
            }

            $owner = $on_same_msn ? $row['nc_owner'] : import_id_remap_get('member', strval($row['nc_owner']), true);

            $id = (get_param_integer('keep_preserve_ids', 0) == 0) ? null : $row['id'];
            $id_new = add_news_category($this->get_lang_string($db, $row['nc_title']), $row['nc_img'], $row['notes'], $owner, $id);

            import_id_remap_put('news_category', strval($row['id']), $id_new);
        }
        $this->_import_content_reviews($db, $table_prefix, 'news_category', 'news_category');
        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'news_category', 'news_category');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'news ORDER BY id');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            if (import_check_if_imported('news', strval($row['id']))) {
                continue;
            }

            $news_category = array();
            $rows2 = $db->query('SELECT news_entry_category FROM ' . $table_prefix . 'news_category_entries WHERE news_entry=' . strval($row['id']));
            foreach ($rows2 as $row2) {
                $next = import_id_remap_get('news_category', strval($row2['news_entry_category']), true);
                if (!is_null($next)) {
                    $news_category[] = $next;
                }
            }
            $submitter = $on_same_msn ? $row['submitter'] : import_id_remap_get('member', strval($row['submitter']), true);
            if (is_null($submitter)) {
                $submitter = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }
            $id = (get_param_integer('keep_preserve_ids', 0) == 0) ? null : $row['id'];
            $main_news_category = $row['news_category'];
            $main_news_category = import_id_remap_get('news_category', strval($main_news_category), true);
            if (is_null($main_news_category)) {
                $main_news_category = db_get_first_id();
            }

            $regions = $db->table_exists('content_regions') ? collapse_1d_complexity('region', $db->query_select('content_regions', array('region'), array('content_type' => 'news', 'content_id' => strval($row['id'])))) : array();

            $id_new = add_news($this->get_lang_string($db, $row['title']), $this->get_lang_string($db, $row['news']), $row['author'], $row['validated'], $row['allow_rating'], $row['allow_comments'], $row['allow_trackbacks'], $row['notes'], $this->get_lang_string($db, $row['news_article']), $main_news_category, $news_category, $row['date_and_time'], $submitter, $row['news_views'], $row['edit_date'], $id, (isset($row['news_image'])) ? $row['news_image'] : '', '', '', $regions);

            $this->_import_content_privacy($db, 'news', strval($row['id']), strval($id_new));

            import_id_remap_put('news', strval($row['id']), $id_new);
        }
        $this->_import_review_supplement($db, $table_prefix, 'news', 'news');
        $this->_import_content_reviews($db, $table_prefix, 'news', 'news');
        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'news', 'news');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'news_rss_cloud', null, null, true);
        if (!is_null($rows)) {
            $this->_fix_comcode_ownership($rows);
            foreach ($rows as $row) {
                unset($row['id']);
                $GLOBALS['SITE_DB']->query_insert('news_rss_cloud', $row);
            }
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_newsletter_subscriptions($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'newsletters', null, null, true);
        if (!is_null($rows)) {
            $this->_fix_comcode_ownership($rows);
            foreach ($rows as $row) {
                if (import_check_if_imported('newsletter', strval($row['id']))) {
                    continue;
                }

                $map = array();
                $map += insert_lang('title', $this->get_lang_string($db, $row['title']), 2);
                $map += insert_lang('description', $this->get_lang_string($db, $row['description']), 2);
                $id_new = $GLOBALS['SITE_DB']->query_insert('newsletters', $map, true);

                import_id_remap_put('newsletter', strval($row['id']), $id_new);
            }

            $old_format = false;
        } else {
            $old_format = true;
        }

        $rowsn = $db->query('SELECT * FROM ' . $table_prefix . ($db->table_exists('newsletter_subscribers') ? 'newsletter_subscribers' : 'newsletter'), null, null, true);
        if (is_null($rowsn)) {
            return;
        }
        $this->_fix_comcode_ownership($rowsn);
        $rows = array();
        foreach ($rowsn as $row) {
            $GLOBALS['SITE_DB']->query_delete('newsletter_subscribers', array('email' => $row['email'], 'language' => $row['language']), '', 1);
            if (!array_key_exists('join_time', $row)) {
                $row['join_time'] = time() - (60 * 60 * 24 * 325);
            }
            if (!array_key_exists('n_forename', $row)) {
                $row['n_forename'] = '';
            }
            if (!array_key_exists('n_surname', $row)) {
                $row['n_surname'] = '';
            }
            $GLOBALS['SITE_DB']->query_insert('newsletter_subscribers', array('n_forename' => $row['n_forename'], 'n_surname' => $row['n_surname'], 'join_time' => $row['join_time'], 'email' => $row['email'], 'code_confirm' => $row['code_confirm'], 'pass_salt' => array_key_exists('pass_salt', $row) ? $row['pass_salt'] : '', 'the_password' => $row['the_password'], 'language' => $row['language']));
            if ($old_format) {
                $rows[] = array('newsletter_id' => db_get_first_id(), 'email' => $row['email'], 'the_level' => $row['the_level']);
            }
        }
        if (!$old_format) {
            $rows = $db->query('SELECT * FROM ' . $table_prefix . 'newsletter_subscribe');
        }
        foreach ($rows as $row) {
            $newsletter_id = $row['newsletter_id'];
            if (!$old_format) {
                $newsletter_id = import_id_remap_get('newsletter', strval($newsletter_id), true);
            }
            if (is_null($newsletter_id)) {
                continue;
            }
            $GLOBALS['SITE_DB']->query_insert('newsletter_subscribe', array('newsletter_id' => $newsletter_id, 'email' => $row['email'], 'the_level' => $row['the_level']));
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'newsletter_archive');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $GLOBALS['SITE_DB']->query_insert('newsletter_archive', array('date_and_time' => $row['date_and_time'], 'subject' => $row['subject'], 'newsletter' => $row['newsletter'], 'language' => $row['language'], 'importance_level' => $row['importance_level']));
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'newsletter_periodic', null, null, true);
        if (!is_null($rows)) {
            $this->_fix_comcode_ownership($rows);
            foreach ($rows as $row) {
                unset($row['id']);
                $GLOBALS['SITE_DB']->query_insert('newsletter_periodic', $row);
            }
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_pointstore($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'prices', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $GLOBALS['SITE_DB']->query_delete('prices', array('name' => $row['name']), '', 1);
            $GLOBALS['SITE_DB']->query_insert('prices', $row);
        }
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'sales');
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            $member_id = $on_same_msn ? $row['memberid'] : import_id_remap_get('member', strval($row['memberid']), true);
            if (is_null($member_id)) {
                continue;
            }
            unset($row['id']);
            $GLOBALS['SITE_DB']->query_insert('sales', array('date_and_time' => $row['date_and_time'], 'memberid' => $member_id, 'purchasetype' => $row['purchasetype'], 'details' => $row['details'], 'details2' => $row['details2']));
        }

        $this->_import_pstore_customs($db, $table_prefix);

        $this->_import_pstore_permissions($db, $table_prefix);
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_downloads_and_categories($db, $table_prefix, $file_base)
    {
        require_code('downloads2');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'download_categories ORDER BY id', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            if (import_check_if_imported('download_category', strval($row['id']))) {
                continue;
            }

            $id = (get_param_integer('keep_preserve_ids', 0) == 0) ? null : $row['id'];
            $id = add_download_category($this->get_lang_string($db, $row['category']), -$row['parent_id'], $this->get_lang_string($db, $row['description']), $row['notes'], $row['rep_image'], $id);

            import_id_remap_put('download_category', strval($row['id']), $id);
        }
        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'download_category', 'download_category');
        $this->_import_content_reviews($db, $table_prefix, 'download_category', 'download_category');
        foreach ($rows as $row) {
            $id = import_id_remap_get('download_category', strval($row['id']));
            $parent_id = import_id_remap_get('download_category', strval($row['parent_id']), true);
            if (is_null($parent_id)) {
                $parent_id = db_get_first_id();
            }

            $GLOBALS['SITE_DB']->query_update('download_categories', array('parent_id' => $parent_id), array('id' => $id), '', 1);
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'download_downloads ORDER BY id');
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            if (import_check_if_imported('download', strval($row['id']))) {
                continue;
            }
            $submitter = $on_same_msn ? $row['submitter'] : import_id_remap_get('member', strval($row['submitter']), true);
            if (is_null($submitter)) {
                $submitter = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }
            $category_id = import_id_remap_get('download_category', strval($row['category_id']), true);
            if (is_null($category_id)) {
                $category_id = db_get_first_id();
            }
            $id = (get_param_integer('keep_preserve_ids', 0) == 0) ? null : $row['id'];
            $id_new = add_download($category_id, $this->get_lang_string($db, $row['name']), $row['url'], $this->get_lang_string($db, $row['description']), $row['author'], $this->get_lang_string($db, array_key_exists('additional_details', $row) ? $row['additional_details'] : $row['comments']), null, $row['validated'], $row['allow_rating'], $row['allow_comments'], $row['allow_trackbacks'], $row['notes'], $row['original_filename'], $row['file_size'], $row['download_cost'], $row['download_submitter_gets_points'], array_key_exists('download_licence', $row) ? $row['download_licence'] : null, $row['add_date'], $row['num_downloads'], $row['download_views'], $submitter, $row['edit_date'], $id, '', '', $row['default_pic'], array_key_exists('url_redirect', $row) ? $row['url_redirect'] : '');

            $this->_import_content_privacy($db, 'download', strval($row['id']), strval($id_new));

            import_id_remap_put('download', strval($row['id']), $id_new);
        }
        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'download', 'download');
        $this->_import_review_supplement($db, $table_prefix, 'downloads', 'download');
        $this->_import_content_reviews($db, $table_prefix, 'download', 'download');
        foreach ($rows as $row) {
            if (!is_null($row['out_mode_id'])) {
                $out_mode_id = import_id_remap_get('download', strval($row['out_mode_id']), true);
                if (is_null($out_mode_id)) {
                    $out_mode_id = null;
                }
                $id_new = import_id_remap_get('download', strval($row['id']), true);
                if (is_null($id_new)) {
                    continue;
                }
                $GLOBALS['SITE_DB']->query_update('download_downloads', array('out_mode_id' => $out_mode_id), array('id' => $id_new), '', 1);
            }
        }

        if ($db->table_exists('download_licences')) {
            $rows = $db->query('SELECT * FROM ' . $table_prefix . 'download_licences ORDER BY id');
            $this->_fix_comcode_ownership($rows);
            foreach ($rows as $row) {
                $GLOBALS['SITE_DB']->query_insert('download_licences', array('l_title' => $row['l_title'], 'l_text' => $row['l_text']));
            }
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_images_and_galleries($db, $table_prefix, $file_base)
    {
        require_code('galleries2');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'galleries', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('galleries', 'name', array('name' => $row['name']));
            if (is_null($test)) {
                add_gallery($row['name'], $this->get_lang_string($db, $row['fullname']), $this->get_lang_string($db, $row['description']), $row['notes'], $row['parent_id'], $row['accept_images'], $row['accept_videos'], $row['is_member_synched'], $row['flow_mode_interface'], $row['rep_image'], $row['watermark_top_left'], $row['watermark_top_right'], $row['watermark_bottom_left'], $row['watermark_bottom_right'], $row['allow_rating'], $row['allow_comments'], false, $row['add_date']);
            }
        }
        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'gallery', null);
        $this->_import_review_supplement($db, $table_prefix, 'galleries', null);
        $this->_import_content_reviews($db, $table_prefix, 'gallery', null);

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'images ORDER BY id');
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            if (import_check_if_imported('image', strval($row['id']))) {
                continue;
            }

            $submitter = $on_same_msn ? $row['submitter'] : import_id_remap_get('member', strval($row['submitter']), true);
            if (is_null($submitter)) {
                $submitter = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }
            $id = (get_param_integer('keep_preserve_ids', 0) == 0) ? null : $row['id'];

            $regions = $db->table_exists('content_regions') ? collapse_1d_complexity('region', $db->query_select('content_regions', array('region'), array('content_type' => 'image', 'content_id' => strval($row['id'])))) : array();

            $title = array_key_exists('title', $row) ? $row['title'] : '';
            if (is_integer($title)) {
                $title = $this->get_lang_string($db, $title);
            }
            $id_new = add_image($title, $row['cat'], $this->get_lang_string($db, array_key_exists('description', $row) ? $row['description'] : $row['comments']), $row['url'], $row['thumb_url'], $row['validated'], $row['allow_rating'], $row['allow_comments'], $row['allow_trackbacks'], $row['notes'], $submitter, $row['add_date'], $row['edit_date'], $row['image_views'], $id, '', '', $regions);

            $this->_import_content_privacy($db, 'image', strval($row['id']), strval($id_new));

            import_id_remap_put('image', strval($row['id']), $id_new);
        }
        $this->_import_review_supplement($db, $table_prefix, 'images', 'image');
        $this->_import_content_reviews($db, $table_prefix, 'image', 'image');
        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'image', null);

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'videos ORDER BY id');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            if (import_check_if_imported('video', strval($row['id']))) {
                continue;
            }

            $submitter = $on_same_msn ? $row['submitter'] : import_id_remap_get('member', strval($row['submitter']), true);
            if (is_null($submitter)) {
                $submitter = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }
            $id = (get_param_integer('keep_preserve_ids', 0) == 0) ? null : $row['id'];

            $regions = $db->table_exists('content_regions') ? collapse_1d_complexity('region', $db->query_select('content_regions', array('region'), array('content_type' => 'video', 'content_id' => strval($row['id'])))) : array();

            $title = array_key_exists('title', $row) ? $row['title'] : '';
            if (is_integer($title)) {
                $title = $this->get_lang_string($db, $title);
            }
            $id_new = add_video($title, $row['cat'], $this->get_lang_string($db, array_key_exists('description', $row) ? $row['description'] : $row['comments']), $row['url'], $row['thumb_url'], $row['validated'], $row['allow_rating'], $row['allow_comments'], $row['allow_trackbacks'], $row['notes'], $row['video_length'], $row['video_width'], $row['video_height'], $submitter, $row['add_date'], $row['edit_date'], $row['video_views'], $id, '', '', $regions);

            $this->_import_content_privacy($db, 'video', strval($row['id']), strval($id_new));

            import_id_remap_put('video', strval($row['id']), $id_new);
        }
        $this->_import_review_supplement($db, $table_prefix, 'videos', 'video');
        $this->_import_content_reviews($db, $table_prefix, 'video', 'video');
        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'video', null);
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_wiki($db, $table_prefix, $file_base)
    {
        if (!import_check_if_imported('wiki_page', strval(db_get_first_id()))) {
            import_id_remap_put('wiki_page', strval(db_get_first_id()), db_get_first_id());
        }

        $rows_pages = $db->query('SELECT * FROM ' . $table_prefix . ($db->table_exists('wiki_pages') ? 'wiki_pages' : 'seedy_pages'), null, null, true);
        if (is_null($rows_pages)) {
            return;
        }
        $this->_fix_comcode_ownership($rows_pages);
        $titlemap = array();
        foreach ($rows_pages as $row) {
            $title = $this->get_lang_string($db, $row['title']);

            if (import_check_if_imported('wiki_page', strval($row['id']))) {
                $id = import_id_remap_get('wiki_page', strval($row['id']));
                $titlemap[$id] = $title;
                continue;
            }

            unset($row['description__text_parsed']);
            unset($row['description__source_user']);

            $on_same_msn = ($this->on_same_msn($file_base));
            $submitter = $on_same_msn ? $row['submitter'] : import_id_remap_get('member', strval($row['submitter']), true);
            if (is_null($submitter)) {
                $submitter = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }

            $map = array(
                'edit_date' => array_key_exists('edit_date', $row) ? $row['edit_date'] : null,
                'submitter' => $submitter,
                'hide_posts' => array_key_exists('hide_posts', $row) ? $row['hide_posts'] : 0,
                'wiki_views' => array_key_exists('wiki_views', $row) ? $row['wiki_views'] : $row['seedy_views'],
                'notes' => $row['notes'],
                'add_date' => $row['add_date'],
            );
            $map += insert_lang('title', $title, 2);
            $map += insert_lang_comcode('description', $this->get_lang_string($db, $row['description']), 2);
            $id = $GLOBALS['SITE_DB']->query_insert('wiki_pages', $map, true);

            $titlemap[$id] = $title;

            import_id_remap_put('wiki_page', strval($row['id']), $id);
        }
        $this->_import_content_reviews($db, $table_prefix, 'wiki_page', 'wiki_page');
        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'wiki_page', 'wiki_page');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . ($db->table_exists('wiki_posts') ? 'wiki_posts' : 'seedy_posts'));
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            if (import_check_if_imported('wiki_post', strval($row['id']))) {
                continue;
            }

            unset($row['the_message__text_parsed']);
            unset($row['the_message__source_user']);

            $page_id = import_id_remap_get('wiki_page', strval($row['page_id']), true);
            if (is_null($page_id)) {
                $page_id = db_get_first_id();
            }

            if (!array_key_exists('member_id', $row)) {
                $row['member_id'] = $row['the_user'];
            }
            $member = $on_same_msn ? $row['member_id'] : import_id_remap_get('member', strval($row['member_id']), true);
            if (is_null($member)) {
                $member = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }

            $map = array(
                'wiki_views' => array_key_exists('wiki_views', $row) ? $row['wiki_views'] : $row['seedy_views'],
                'validated' => array_key_exists('validated', $row) ? $row['validated'] : 1,
                'member_id' => $member,
                'date_and_time' => $row['date_and_time'],
                'page_id' => $page_id,
                'edit_date' => $row['edit_date'],
            );
            $map += insert_lang_comcode('the_message', $this->get_lang_string($db, $row['the_message']), 2);
            $id_new = $GLOBALS['SITE_DB']->query_insert('wiki_posts', $map, true);

            import_id_remap_put('wiki_post', strval($row['id']), $id_new);
        }
        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'wiki_post', 'wiki_post');

        if ($db->table_exists('revisions') && addon_installed('actionlog')) {
            $rows = $db->query('SELECT * FROM ' . $table_prefix . 'revisions WHERE ' . db_string_equal_to('r_resource_type', 'wiki_page'));
            $this->_fix_comcode_ownership($rows);
            foreach ($rows as $row) {
                unset($row['id']);

                $actionlog_id = import_id_remap_get('wiki_page', strval($row['r_actionlog_id']), true);
                if (is_null($actionlog_id)) {
                    continue;
                }
                $row['r_actionlog_id'] = $actionlog_id;

                $category_id = import_id_remap_get('wiki_page', strval($row['r_category_id']), true);
                if (is_null($category_id)) {
                    continue;
                }
                $row['r_category_id'] = $category_id;

                if (strpos($row['log_action'], 'PAGE') !== false) {
                    $row['r_resource_id'] = import_id_remap_get('wiki_page', $row['r_resource_id'], true);
                    if (is_null($row['r_resource_id'])) {
                        continue;
                    }
                } else {
                    $row['r_resource_id'] = import_id_remap_get('wiki_post', $row['r_resource_id'], true);
                    if (is_null($row['r_resource_id'])) {
                        continue;
                    }
                }

                $row['r_original_content_owner'] = $on_same_msn ? $row['r_original_content_owner'] : import_id_remap_get('member', strval($row['r_original_content_owner']), true);
                if (is_null($row['r_original_content_owner'])) {
                    $row['r_original_content_owner'] = $GLOBALS['FORUM_DRIVER']->get_guest_id();
                }

                $GLOBALS['SITE_DB']->query_insert('revisions', $row);
            }
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . ($db->table_exists('wiki_children') ? 'wiki_children' : 'seedy_children'));
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $child_id = import_id_remap_get('wiki_page', strval($row['child_id']), true);
            $parent_id = import_id_remap_get('wiki_page', strval($row['parent_id']), true);

            if (is_null($child_id)) {
                continue;
            }
            if (is_null($parent_id)) {
                continue;
            }

            if (array_key_exists($child_id, $titlemap)) {
                $title = $titlemap[$child_id];
            } elseif (array_key_exists($child_id, $rows_pages)) {
                $title = $this->get_lang_string($db, $rows_pages[$child_id]['title']);
            } else {
                continue;
            }

            $GLOBALS['SITE_DB']->query_insert('wiki_children', array('parent_id' => $parent_id, 'child_id' => $child_id, 'the_order' => $row['the_order'], 'title' => $titlemap[$child_id]));
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_custom_comcode($db, $table_prefix, $file_base)
    {
        require_code('custom_comcode');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'custom_comcode', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('custom_comcode', 'tag_tag', array('tag_tag' => $row['tag_tag']));
            if (!is_null($test)) {
                continue;
            }

            $tag = $row['tag_tag'];
            $title = $this->get_lang_string($db, $row['tag_title']);
            $description = $this->get_lang_string($db, $row['tag_description']);
            $replace = $row['tag_replace'];
            $example = $row['tag_example'];
            $parameters = $row['tag_parameters'];
            $enabled = $row['tag_enabled'];
            $dangerous_tag = $row['tag_dangerous_tag'];
            $block_tag = $row['tag_block_tag'];
            $textual_tag = $row['tag_textual_tag'];

            add_custom_comcode_tag($tag, $title, $description, $replace, $example, $parameters, $enabled, $dangerous_tag, $block_tag, $textual_tag);
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_comcode_pages($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'comcode_pages', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            if (import_check_if_imported('comcode_page', $row['the_zone'] . ':' . $row['the_page'])) {
                continue;
            }

            $p_submitter = import_id_remap_get('member', strval($row['p_submitter']), true);
            if (is_null($p_submitter)) {
                require_code('users_active_actions');
                $p_submitter = get_first_admin_user();
            }

            $the_zone = $row['the_zone'];
            $the_page = $row['the_page'];
            $p_parent_page = $row['p_parent_page'];
            $p_validated = $row['p_validated'];
            $p_edit_date = $row['p_edit_date'];
            $p_add_date = $row['p_add_date'];
            $p_show_as_edit = $row['p_show_as_edit'];

            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('comcode_pages', 'the_page', array(
                'the_zone' => $the_zone,
                'the_page' => $the_page,
            ));
            if ($test !== null) {
                $the_page .= '_duplicate_' . substr(md5(uniqid('', true)), 0, 5);
            }

            $langs = find_all_langs();
            $found_one = false;
            foreach (array_keys($langs) as $lang) {
                $file_path_from = $file_base . (($the_zone == '') ? '' : '/') . $the_zone . '/pages/comcode_custom/' . $lang . '/' . $row['the_page'] . '.txt';
                $file_path_to = get_file_base() . (($the_zone == '') ? '' : '/') . $the_zone . '/pages/comcode_custom/' . $lang . '/' . $row['the_page'] . '.txt';
                if (is_file($file_path_from)) {
                    $found_one = true;

                    $comcode = cms_file_get_contents_safe($file_path_from);
                    $comcode_new = $this->update_comcode($comcode, $the_zone . ':' . $the_page);

                    cms_file_put_contents_safe($file_path_to, $comcode_new);
                }
            }

            if (!$found_one) {
                continue;
            }

            $GLOBALS['SITE_DB']->query_insert('comcode_pages', array(
                'the_zone' => $the_zone,
                'the_page' => $the_page,
                'p_parent_page' => $row['p_parent_page'],
                'p_validated' => $row['p_validated'],
                'p_edit_date' => $row['p_edit_date'],
                'p_add_date' => $row['p_add_date'],
                'p_submitter' => $p_submitter,
                'p_show_as_edit' => $row['p_show_as_edit'],
                'p_order' => array_key_exists('p_order', $row) ? $row['p_order'] : 0,
            ));

            import_id_remap_put('comcode_page', $row['the_zone'] . ':' . $row['the_page'], 1);
        }
        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'comcode_page', null);
        $this->_import_content_reviews($db, $table_prefix, 'comcode_page', null);
    }

    /**
     * Import custom tasks.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_staff_checklist_cus_tasks($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . ($db->table_exists('staff_checklist_cus_tasks') ? 'staff_checklist_cus_tasks' : 'customtasks'), null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $GLOBALS['SITE_DB']->query_insert('staff_checklist_cus_tasks', array(
                'task_title' => array_key_exists('task_title', $row) ? $row['task_title'] : $row['tasktitle'],
                'add_date' => array_key_exists('add_date', $row) ? $row['add_date'] : $row['datetimeadded'],
                'recur_interval' => array_key_exists('recur_interval', $row) ? $row['recur_interval'] : $row['recurinterval'],
                'recur_every' => array_key_exists('recur_every', $row) ? $row['recur_every'] : $row['recurevery'],
                'task_is_done' => array_key_exists('task_is_done', $row) ? $row['task_is_done'] : $row['taskisdone'],
            ));
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_wordfilter($db, $table_prefix, $file_base)
    {
        require_code('wordfilter');

        $rows = $db->query('SELECT word FROM ' . $table_prefix . 'wordfilter', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            add_wordfilter_word($row['word'], array_key_exists('w_replacement', $row) ? $row['w_replacement'] : '', array_key_exists('w_substr', $row) ? $row['w_substr'] : 0);
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_calendar($db, $table_prefix, $file_base)
    {
        require_code('calendar2');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'calendar_types', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            if (import_check_if_imported('event_type', strval($row['id']))) {
                continue;
            }

            if ($row['id'] == db_get_first_id()) {
                import_id_remap_put('event_type', strval($row['id']), db_get_first_id());
                continue;
            }

            $id_new = add_event_type($this->get_lang_string($db, $row['t_title']), $row['t_logo'], array_key_exists('t_external_feed', $row) ? $row['t_external_feed'] : '');

            import_id_remap_put('event_type', strval($row['id']), $id_new);
        }
        $this->_import_content_reviews($db, $table_prefix, 'calendar_type', 'event_type');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . ($db->table_exists('calendar_interests') ? 'calendar_interests' : 'calendar_declarations_of_interest'), null, null, true);
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            $member = $on_same_msn ? $row['i_member_id'] : import_id_remap_get('member', strval($row['i_member_id']), true);
            if (is_null($member)) {
                continue;
            }
            $type = import_id_remap_get('event_type', strval($row['t_type']), true);
            if (is_null($type)) {
                continue;
            }
            $GLOBALS['SITE_DB']->query_delete('calendar_interests', array('i_member_id' => $member, 't_type' => $type), '', 1);
            $GLOBALS['SITE_DB']->query_insert('calendar_interests', array('i_member_id' => $member, 't_type' => $type));
        }

        $event_rows = $db->query('SELECT * FROM ' . $table_prefix . 'calendar_events ORDER BY id');
        $this->_fix_comcode_ownership($event_rows);
        foreach ($event_rows as $row) {
            if (import_check_if_imported('event', strval($row['id']))) {
                continue;
            }

            $submitter = $on_same_msn ? $row['e_submitter'] : import_id_remap_get('member', strval($row['e_submitter']), true);
            if (is_null($submitter)) {
                $submitter = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }

            if (isset($row['e_member_calendar'])) {
                $member_calendar = $on_same_msn ? $row['e_member_calendar'] : import_id_remap_get('member', strval($row['e_member_calendar']), true);
                if (is_null($member_calendar)) {
                    $member_calendar = $GLOBALS['FORUM_DRIVER']->get_guest_id();
                }
            } else {
                $member_calendar = mixed();
            }

            $type = import_id_remap_get('event_type', strval($row['e_type']), true);
            if (is_null($type)) {
                continue;
            }

            if (!array_key_exists('validated', $row)) {
                $row['validated'] = 1;
            }
            if (!array_key_exists('notes', $row)) {
                $row['notes'] = '';
            }
            if (!array_key_exists('allow_rating', $row)) {
                $row['allow_rating'] = 1;
            }
            if (!array_key_exists('allow_comments', $row)) {
                $row['allow_comments'] = 1;
            }
            if (!array_key_exists('allow_trackbacks', $row)) {
                $row['allow_trackbacks'] = 1;
            }
            $id = (get_param_integer('keep_preserve_ids', 0) == 0) ? null : $row['id'];

            $regions = $db->table_exists('content_regions') ? collapse_1d_complexity('region', $db->query_select('content_regions', array('region'), array('content_type' => 'event', 'content_id' => strval($row['id'])))) : array();

            $id_new = add_calendar_event($type, $row['e_recurrence'], $row['e_recurrences'], array_key_exists('e_seg_recurrences', $row) ? $row['e_seg_recurrences'] : 0, $this->get_lang_string($db, $row['e_title']), $this->get_lang_string($db, $row['e_content']), $row['e_priority'], $row['e_start_year'], $row['e_start_month'], $row['e_start_day'], array_key_exists('e_start_monthly_spec_type', $row) ? $row['e_start_monthly_spec_type'] : 'day_of_month', $row['e_start_hour'], $row['e_start_minute'], $row['e_end_year'], $row['e_end_month'], $row['e_end_day'], array_key_exists('e_end_monthly_spec_type', $row) ? $row['e_end_monthly_spec_type'] : 'day_of_month', $row['e_end_hour'], $row['e_end_minute'], array_key_exists('e_timezone', $row) ? $row['e_timezone'] : null, array_key_exists('e_do_timezone_conv', $row) ? $row['e_do_timezone_conv'] : 1, $member_calendar, $row['validated'], $row['allow_rating'], $row['allow_comments'], $row['allow_trackbacks'], $row['notes'], $submitter, $row['e_views'], $row['e_add_date'], $row['e_edit_date'], $id, '', '', $regions);

            if ((array_key_exists('e_is_public', $row)) && ($row['e_is_public'] == 0)) {
                $GLOBALS['SITE_DB']->query_insert('content_privacy', array(
                    'content_type' => 'event',
                    'content_id' => strval($id_new),
                    'guest_view' => 0,
                    'member_view' => 0,
                    'friend_view' => 0,
                ));
            }

            $this->_import_content_privacy($db, 'event', strval($row['id']), strval($id_new));

            import_id_remap_put('event', strval($row['id']), $id_new);
        }
        $this->_import_review_supplement($db, $table_prefix, 'events', 'event');
        $this->_import_content_reviews($db, $table_prefix, 'event', 'event');
        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'event', 'event');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'calendar_reminders');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $event = import_id_remap_get('event', strval($row['e_id']), true);
            if (is_null($event)) {
                continue;
            }
            $member = $on_same_msn ? $row['n_member_id'] : import_id_remap_get('member', strval($row['n_member_id']), true);
            if (is_null($member)) {
                continue;
            }
            $GLOBALS['SITE_DB']->query_insert('calendar_reminders', array('e_id' => $event, 'n_member_id' => $member, 'n_seconds_before' => $row['n_seconds_before']));
        }

        require_code('calendar');
        foreach ($event_rows as $row) {
            regenerate_event_reminder_jobs(import_id_remap_get('event', strval($row['id'])));
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_redirects($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'redirects');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $GLOBALS['SITE_DB']->query_insert('redirects', $row, false, true); // Allow failure if row already there
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_themes($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'theme_images WHERE path LIKE \'' . db_encode_like('%/images\_custom/%') . '\'');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            if (!is_dir(get_file_base() . '/themes/' . $row['theme']) && !is_dir(get_custom_file_base() . '/themes/' . $row['theme'])) {
                continue;
            }

            $GLOBALS['SITE_DB']->query_delete('theme_images', $row, '', 1);
            $GLOBALS['SITE_DB']->query_insert('theme_images', $row, false, true); // Allow failure if row already there
        }
        Self_learning_cache::erase_smart_cache();
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_support_tickets($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'ticket_types', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            if (import_check_if_imported('ticket_type', strval(isset($row['id']) ? $row['id'] : $row['ticket_type']))) {
                continue;
            }

            $map = array(
                'search_faq' => array_key_exists('search_faq', $row) ? $row['search_faq'] : 0,
                'guest_emails_mandatory' => array_key_exists('guest_emails_mandatory', $row) ? $row['guest_emails_mandatory'] : 0,
            );
            $map += insert_lang('ticket_type_name', $this->get_lang_string($db, isset($row['ticket_type_name']) ? $row['ticket_type_name'] : $row['ticket_type']), 1);
            $ticket_type_id = $GLOBALS['SITE_DB']->query_insert('ticket_types', $map, true);
            import_id_remap_put('ticket_type', strval(isset($row['id']) ? $row['id'] : $row['ticket_type']), $ticket_type_id);
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'tickets');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $topic_id = import_id_remap_get('topic', strval($row['topic_id']), true);
            if (is_null($topic_id)) {
                continue;
            }
            $forum_id = import_id_remap_get('forum', strval($row['forum_id']), true);
            if (is_null($forum_id)) {
                continue;
            }
            $row['topic_id'] = strval($topic_id);
            $row['forum_id'] = strval($forum_id);

            $GLOBALS['SITE_DB']->query_delete('tickets', array('ticket_id' => $row['ticket_id']));
            $GLOBALS['SITE_DB']->query_insert('tickets', $row);
        }

        $this->_import_ticket_extra_access($db, $table_prefix);
        $this->_import_ticket_known_emailers($db, $table_prefix);
    }

    /**
     * Import ticket extra access.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     */
    protected function _import_ticket_extra_access($db, $table_prefix)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'ticket_extra_access', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $member_id = import_id_remap_get('member', strval($row['member_id']), true);
            if (is_null($member_id)) {
                continue;
            }
            $row['member_id'] = $member_id;

            $GLOBALS['SITE_DB']->query_insert('ticket_extra_access', $row);
        }
    }

    /**
     * Imports ticket known emailers.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     */
    protected function _import_ticket_known_emailers($db, $table_prefix)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'ticket_known_emailers', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $member_id = import_id_remap_get('member', strval($row['member_id']), true);
            if (is_null($member_id)) {
                continue;
            }
            $row['member_id'] = $member_id;

            $GLOBALS['SITE_DB']->query_insert('ticket_known_emailers', $row);
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_useronline_tracking($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'usersonline_track');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $GLOBALS['SITE_DB']->query_insert('usersonline_track', $row, false, true); // Allow failure if row already there
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_ip_bans($db, $table_prefix, $file_base)
    {
        require_code('failure');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . ($db->table_exists('banned_ip') ? 'banned_ip' : 'usersubmitban_ip'));
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            add_ip_ban($row['ip'], array_key_exists('i_descrip', $row) ? $row['i_descrip'] : '', array_key_exists('i_ban_until', $row) ? $row['i_ban_until'] : null, array_key_exists('i_ban_positive', $row) ? ($row['i_ban_positive'] == 1) : 1);
        }

        if ($db->table_exists('unbannable_ip')) {
            $rows = $db->query('SELECT * FROM ' . $table_prefix . 'unbannable_ip');
            $this->_fix_comcode_ownership($rows);
            foreach ($rows as $row) {
                $GLOBALS['SITE_DB']->query_insert('unbannable_ip', $row);
            }
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'usersubmitban_member');
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            $member = $on_same_msn ? $row['the_member'] : import_id_remap_get('member', strval($row['the_member']), true);
            if (is_null($member)) {
                continue;
            }
            $GLOBALS['SITE_DB']->query_insert('usersubmitban_member', array('the_member' => $member));
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_zones($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'zones');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('zones', 'zone_name', array('zone_name' => $row['zone_name']));
            if ((is_null($test)) && ($test != 'wiki') && ($test != 'supermembercentre') && ($test != 'admincentre') && ($test != 'membersonly') && ($test != 'personalcentre') && ($test != 'membercentre')) {
                $old_title = $this->get_lang_string($db, $row['zone_title']);
                $row = insert_lang('zone_title', array_key_exists('zone_title', $row) ? $old_title : $row['zone_name'], 1) + $row;
                $row = insert_lang('zone_header_text', $this->get_lang_string($db, $row['zone_header_text']), 1) + $row;

                // Just to support old-version compatibility a little
                unset($row['access_denied_counter']);
                unset($row['zone_wide']);
                unset($row['zone_displayed_in_menu']);

                $GLOBALS['SITE_DB']->query_insert('zones', $row);

                require_code('zones2');
                make_zone_directory($row['zone_name']);
            }
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_catalogues($db, $table_prefix, $file_base)
    {
        require_code('catalogues2');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'catalogues', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            unset($row['c_description__text_parsed']);
            unset($row['c_description__source_user']);

            if (import_check_if_imported('catalogue', $row['c_name'])) {
                continue;
            }

            $name = $row['c_name'];
            if ($name == '_seedy_post') {
                $name = '_wiki_post';
            }

            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('catalogues', 'c_name', array('c_name' => $name));
            if (is_null($test)) {
                $row = insert_lang('c_title', $this->get_lang_string($db, $row['c_title']), 2) + $row;
                $row = insert_lang_comcode('c_description', $this->get_lang_string($db, $row['c_description']), 2) + $row;
                if (!array_key_exists('c_display_type', $row)) {
                    $row['c_display_type'] = $row['c_own_pages'];
                    unset($row['c_own_pages']);
                }
                if (!array_key_exists('c_ecommerce', $row)) {
                    $row['c_ecommerce'] = 0;
                }
                if (!array_key_exists('c_send_view_reports', $row)) {
                    $row['c_send_view_reports'] = 0;
                }
                if (!array_key_exists('c_default_review_freq', $row)) {
                    $row['c_default_review_freq'] = null;
                }
                unset($row['c_own_template']);
                $GLOBALS['SITE_DB']->query_insert('catalogues', array('c_name' => $name) + $row);
                import_id_remap_put('catalogue', $row['c_name'], 1);

                $rows2 = $db->query('SELECT * FROM ' . $table_prefix . 'catalogue_fields WHERE ' . db_string_equal_to('c_name', $row['c_name']));
                foreach ($rows2 as $row2) {
                    if (import_check_if_imported('catalogue_field', strval($row2['id']))) {
                        continue;
                    }

                    if ($row2['cf_type'] == 'user') {
                        $row2['cf_type'] = 'member';
                    }
                    if ($row2['cf_type'] == 'user_multi') {
                        $row2['cf_type'] = 'member_multi';
                    }
                    if ($row2['cf_type'] == 'random') {
                        $row2['cf_type'] = 'codename';
                        $row2['cf_default'] = 'RANDOM';
                    }
                    if ($row2['cf_type'] == 'combo_multi') {
                        $row2['cf_type'] = 'list_multi';
                        $row2['cf_options'] = 'widget=vertical_checkboxes,custom_values=yes';
                    }
                    if ($row2['cf_type'] == 'multilist') {
                        $row2['cf_type'] = 'list_multi';
                    }
                    if ($row2['cf_type'] == 'tick_multi') {
                        $row2['cf_type'] = 'list_multi';
                        $row2['cf_options'] = 'widget=horizontal_checkboxes';
                    }
                    if ($row2['cf_type'] == 'combo') {
                        $row2['cf_type'] = 'list';
                        $row2['cf_options'] = 'widget=radio,custom_values=yes';
                    }
                    if ($row2['cf_type'] == 'radiolist') {
                        $row2['cf_type'] = 'list';
                        $row2['cf_options'] = 'widget=radio';
                    }
                    if ($row2['cf_type'] == 'auto_increment') {
                        $row2['cf_type'] = 'integer';
                        $row2['cf_default'] = 'AUTO_INCREMENT';
                    }

                    $row2 = insert_lang('cf_name', $this->get_lang_string($db, $row2['cf_name']), 2) + $row2;
                    $row2 = insert_lang('cf_description', $this->get_lang_string($db, $row2['cf_description']), 2) + $row2;
                    if (!array_key_exists('cf_put_in_category', $row2)) {
                        $row2['cf_put_in_category'] = 1;
                    }
                    if (!array_key_exists('cf_put_in_search', $row2)) {
                        $row2['cf_put_in_search'] = 1;
                    }
                    if (!array_key_exists('cf_options', $row2)) {
                        $row2['cf_options'] = '';
                    }

                    $old_id = $row2['id'];
                    unset($row2['id']);

                    $id_new = $GLOBALS['SITE_DB']->query_insert('catalogue_fields', array('c_name' => $name) + $row2, true);

                    import_id_remap_put('catalogue_field', strval($old_id), $id_new);
                }
            } else {
                attach_message(do_lang_tempcode('CANNOT_MERGE_CATALOGUES', escape_html($row['c_name'])), 'notice');
            }
        }
        $this->_import_content_reviews($db, $table_prefix, 'catalogue', null);
        $this->_import_review_supplement($db, $table_prefix, 'catalogues', 'catalogue_entry');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'catalogue_categories ORDER BY id');
        $this->_fix_comcode_ownership($rows);
        $id = mixed();
        foreach ($rows as $row) {
            if (import_check_if_imported('catalogue_category', strval($row['id']))) {
                continue;
            }

            $is_tree = $GLOBALS['SITE_DB']->query_select_value_if_there('catalogues', 'c_is_tree', array('c_name' => $row['c_name']));
            if ($is_tree === null) {
                continue;
            }

            if ((is_null($row['cc_parent_id'])) && ($is_tree == 1)) {
                $real_root = $GLOBALS['SITE_DB']->query_select_value_if_there('catalogue_categories', 'id', array('cc_parent_id' => null, 'c_name' => $row['c_name']));
                if (!is_null($real_root)) {
                    import_id_remap_put('catalogue_category', strval($row['id']), $real_root);
                    continue;
                }
            }

            $id = (get_param_integer('keep_preserve_ids', 0) == 0) ? null : $row['id'];

            $rep_image = array_key_exists('cc_rep_image', $row) ? $row['cc_rep_image'] : '';

            if ($row['c_name'] == '_seedy_post') {
                $row['c_name'] = '_wiki_post';
            }

            $id_new = actual_add_catalogue_category($row['c_name'], $this->get_lang_string($db, $row['cc_title']), $this->get_lang_string($db, $row['cc_description']), $row['cc_notes'], is_null($row['cc_parent_id']) ? null : -$row['cc_parent_id'], $rep_image, array_key_exists('cc_move_days_lower', $row) ? $row['cc_move_days_lower'] : 30, array_key_exists('cc_move_days_higher', $row) ? $row['cc_move_days_higher'] : 60, array_key_exists('cc_move_target', $row) ? $row['cc_move_target'] : null, isset($row['cc_order']) ? $row['cc_order'] : null, $row['cc_add_date'], $id);

            import_id_remap_put('catalogue_category', strval($row['id']), $id_new);
        }
        $this->_import_content_reviews($db, $table_prefix, 'catalogue_category', 'catalogue_category');

        $rows = $GLOBALS['SITE_DB']->query('SELECT id,cc_parent_id FROM ' . $GLOBALS['SITE_DB']->get_table_prefix() . 'catalogue_categories WHERE cc_parent_id<0');
        foreach ($rows as $row) {
            $parent_id = import_id_remap_get('catalogue_category', strval(-$row['cc_parent_id']), true);
            $GLOBALS['SITE_DB']->query_update('catalogue_categories', array('cc_parent_id' => $parent_id), array('id' => $row['id']), '', 1);
        }
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'catalogue_entries ORDER BY id');
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            if (!is_null(import_id_remap_get('catalogue_entry', strval($row['id']), true))) {
                continue;
            }
            $category_id = import_id_remap_get('catalogue_category', strval($row['cc_id']), true);
            if (is_null($category_id)) {
                continue;
            }
            $map = array();

            // Tedious...
            foreach (array('long', 'short', 'float', 'integer') as $table) {
                $rows2 = $db->query('SELECT * FROM ' . $table_prefix . 'catalogue_efv_' . $table . ' WHERE ce_id=' . strval($row['id']), null, null, true);
                if (!is_null($rows2)) { // Older versions of Composr don't have float and integer
                    foreach ($rows2 as $row2) {
                        $remapped = import_id_remap_get('catalogue_field', strval($row2['cf_id']), true);
                        if (is_null($remapped)) {
                            continue;
                        }
                        $value = $row2['cv_value'];
                        if (is_integer($value)) {
                            $value = strval($value);
                        } elseif (is_float($value)) {
                            $value = float_to_raw_string($value);
                        }
                        $map[$remapped] = $value;
                    }
                }
            }
            $rows2 = $db->query('SELECT * FROM ' . $table_prefix . 'catalogue_efv_long_trans WHERE ce_id=' . strval($row['id']));
            foreach ($rows2 as $row2) {
                $remapped = import_id_remap_get('catalogue_field', strval($row2['cf_id']), true);
                if (is_null($remapped)) {
                    continue;
                }
                $map[$remapped] = $this->get_lang_string($db, $row2['cv_value']);
            }
            $rows2 = $db->query('SELECT * FROM ' . $table_prefix . 'catalogue_efv_short_trans WHERE ce_id=' . strval($row['id']));
            foreach ($rows2 as $row2) {
                $remapped = import_id_remap_get('catalogue_field', strval($row2['cf_id']), true);
                if (is_null($remapped)) {
                    continue;
                }
                $map[$remapped] = $this->get_lang_string($db, $row2['cv_value']);
            }
            $submitter = $on_same_msn ? $row['ce_submitter'] : import_id_remap_get('member', strval($row['ce_submitter']), true);
            if (is_null($submitter)) {
                $submitter = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }
            $id = (get_param_integer('keep_preserve_ids', 0) == 0) ? null : $row['id'];
            $id_new = actual_add_catalogue_entry($category_id, $row['ce_validated'], $row['notes'], $row['allow_rating'], $row['allow_comments'], $row['allow_trackbacks'], $map, $row['ce_add_date'], $submitter, $row['ce_edit_date'], $row['ce_views'], $id);

            $this->_import_content_privacy($db, 'catalogue_entry', strval($row['id']), strval($id_new));
            import_id_remap_put('catalogue_entry', strval($row['id']), $id_new);
        }
        $this->_import_content_reviews($db, $table_prefix, 'catalogue_entry', 'catalogue_entry');

        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'catalogue', null);
        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'catalogue_category', 'catalogue_category');
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_chat_rooms($db, $table_prefix, $file_base)
    {
        require_code('chat2');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'chat_rooms WHERE is_im=0 ORDER BY id', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            if (import_check_if_imported('chat', strval($row['id']))) {
                continue;
            }
            $id_old = $row['id'];

            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('chat_rooms', 'id', array('room_name' => $row['room_name']));
            if (!is_null($test)) {
                continue;
            }

            $row['room_owner'] = $on_same_msn ? $row['room_owner'] : import_id_remap_get('member', strval($row['room_owner']), true);
            $row = insert_lang('c_welcome', $this->get_lang_string($db, $row['c_welcome']), 2) + $row;

            $_disallow_list_groups = explode(',', $row['disallow_list_groups']);
            $row['disallow_list_groups'] = '';
            foreach ($_disallow_list_groups as $x) {
                $row['disallow_list_groups'] .= ($on_same_msn ? $x : strval(import_id_remap_get('group', $x, true))) . ',';
            }
            $_allow_list_groups = explode(',', $row['allow_list']);
            $row['allow_list_groups'] = '';
            foreach ($_allow_list_groups as $x) {
                $row['allow_list_groups'] .= ($on_same_msn ? $x : strval(import_id_remap_get('group', $x, true))) . ',';
            }
            $_disallow_list = explode(',', $row['disallow_list']);
            $row['disallow_list'] = '';
            foreach ($_disallow_list as $x) {
                $row['disallow_list'] .= ($on_same_msn ? $x : strval(import_id_remap_get('member', $x, true))) . ',';
            }
            $_allow_list = explode(',', $row['allow_list']);
            $row['allow_list'] = '';
            foreach ($_allow_list as $x) {
                $row['allow_list'] .= ($on_same_msn ? $x : strval(import_id_remap_get('member', $x, true))) . ',';
            }

            if (get_param_integer('keep_preserve_ids', 0) == 0) {
                unset($row['id']);
            }
            $id_new = $GLOBALS['SITE_DB']->query_insert('chat_rooms', $row, true);

            import_id_remap_put('chat', strval($id_old), $id_new);
        }
        $this->_import_content_reviews($db, $table_prefix, 'chat', 'chat');

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'chat_blocking');
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            $member_blocker = import_id_remap_get('member', strval($row['member_blocker']), true);
            $member_blocked = import_id_remap_get('member', strval($row['member_blocked']), true);
            if (is_null($member_blocker)) {
                continue;
            }
            if (is_null($member_blocked)) {
                continue;
            }
            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('chat_blocking', 'member_blocker', array('member_blocker' => $member_blocker, 'member_blocked' => $member_blocked));
            if (!is_null($test)) {
                continue;
            }
            $GLOBALS['SITE_DB']->query_insert('chat_blocking', array('member_blocker' => $member_blocker, 'member_blocked' => $member_blocked, 'date_and_time' => $row['date_and_time']));
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . ($db->table_exists('chat_friends') ? 'chat_friends' : 'chat_buddies'));
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $member_likes = import_id_remap_get('member', strval($row['member_likes']), true);
            $member_liked = import_id_remap_get('member', strval($row['member_liked']), true);
            if (is_null($member_likes)) {
                continue;
            }
            if (is_null($member_liked)) {
                continue;
            }
            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('chat_friends', 'member_likes', array('member_likes' => $member_likes, 'member_liked' => $member_liked));
            if (!is_null($test)) {
                continue;
            }
            $GLOBALS['SITE_DB']->query_insert('chat_friends', array('member_likes' => $member_likes, 'member_liked' => $member_liked, 'date_and_time' => $row['date_and_time']));
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'chat_sound_effects');
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            $s_member = import_id_remap_get('member', strval($row['s_member']), true);
            if (is_null($s_member)) {
                continue;
            }
            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('chat_sound_effects', 's_member', array('s_member' => $s_member, 's_effect_id' => $row['s_effect_id']));
            if (!is_null($test)) {
                continue;
            }
            $GLOBALS['SITE_DB']->query_insert('chat_sound_effects', array('s_member' => $s_member, 's_effect_id' => $row['s_effect_id'], 's_url' => $row['s_url']));
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_awards($db, $table_prefix, $file_base)
    {
        $content_types = array();
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'award_types', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            unset($row['a_description__text_parsed']);
            unset($row['a_description__source_user']);

            $content_types[$row['id']] = $row['a_content_type'];

            if (import_check_if_imported('award_type', strval($row['id']))) {
                continue;
            }

            $row = insert_lang('a_title', $this->get_lang_string($db, $row['a_title']), 2) + $row;
            $row = insert_lang_comcode('a_description', $this->get_lang_string($db, $row['a_description']), 2) + $row;

            $id_old = $row['id'];
            if (get_param_integer('keep_preserve_ids', 0) == 0) {
                unset($row['id']);
            }
            $id_new = $GLOBALS['SITE_DB']->query_insert('award_types', $row, true);

            import_id_remap_put('award_type', strval($id_old), $id_new);
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'award_archive');
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            if (import_check_if_imported('awarded', strval($row['date_and_time']))) {
                continue;
            }

            $row['member_id'] = $on_same_msn ? $row['member_id'] : import_id_remap_get('member', strval($row['member_id']), true);
            if (is_null($row['member_id'])) {
                $row['member_id'] = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }
            if (!is_string($row['content_id'])) {
                $row['content_id'] = import_id_remap_get($content_types[$row['a_type_id']], $row['content_id'], true);
            }
            if (is_null($row['content_id'])) {
                continue;
            }
            $row['a_type_id'] = import_id_remap_get('award_type', strval($row['a_type_id']));
            $GLOBALS['SITE_DB']->query_insert('award_archive', $row);

            import_id_remap_put('awarded', strval($row['date_and_time']), $row['date_and_time']);
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_filedump($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'filedump', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            $row = insert_lang('description', $this->get_lang_string($db, $row['description']), 2) + $row;
            $row['the_member'] = $on_same_msn ? $row['the_member'] : import_id_remap_get('member', strval($row['the_member']), true);
            if (is_null($row['the_member'])) {
                $row['the_member'] = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }
            $GLOBALS['SITE_DB']->query_insert('filedump', $row);
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_permissions($db, $table_prefix, $file_base)
    {
        $remap = array(
            'moderate_personal_topic' => 'moderate_private_topic',
            'edit_personal_topic_posts' => 'edit_private_topic_posts',
            'bypass_word_filter' => 'bypass_wordfilter',
            'seedy_manage_tree' => 'wiki_manage_tree',
            'seedy_edit_pages' => 'wiki_edit_pages',
            'seedy_edit' => 'wiki_edit',
        );

        $rows = $db->query('SELECT * FROM ' . $table_prefix . ($db->table_exists('group_privileges') ? 'group_privileges' : 'gsp'));
        $on_same_msn = ($this->on_same_msn($file_base));
        foreach ($rows as $row) {
            if ($row['the_page'] == 'cedi') {
                $row['the_page'] = 'wiki';
            }

            $row['group_id'] = $on_same_msn ? $row['group_id'] : import_id_remap_get('group', strval($row['group_id']), true);
            if (is_null($row['group_id'])) {
                continue;
            }

            if (!array_key_exists('privilege', $row)) {
                $row['privilege'] = $row['specific_permission'];
                unset($row['specific_permission']);
            }
            if (isset($remap[$row['privilege']])) {
                $row['privilege'] = $remap[$row['privilege']];
            }

            $row_temp = $row;
            unset($row_temp['the_value']);

            $GLOBALS['SITE_DB']->query_delete('group_privileges', $row_temp, '', 1);

            if (!array_key_exists('the_page', $row)) {
                $row['the_page'] = '';
            }
            if (!array_key_exists('module_the_name', $row)) {
                $row['module_the_name'] = '';
            }
            if (!array_key_exists('category_name', $row)) {
                $row['category_name'] = '';
            }
            if ($row['category_name'] != '') {
                if ($row['module_the_name'] == 'seedy_page') {
                    $row['module_the_name'] = 'wiki_page';
                }

                $import_type = $row['module_the_name'];
                $str = false;
                switch ($import_type) {
                    case 'galleries':
                        $import_type = 'gallery';
                        $str = true;
                        break;
                    case 'downloads':
                        $import_type = 'download_category';
                        break;
                    case 'calendar':
                        $import_type = 'event_type';
                        break;
                    case 'catalogues_catalogue':
                        $import_type = 'catalogue';
                        $str = true;
                        break;
                    case 'catalogues_category':
                        $import_type = 'catalogue_category';
                        break;
                    case 'forums':
                        $import_type = 'forum';
                        break;
                    case 'topics':
                        $import_type = 'topic';
                        break;
                    case 'wiki_page':
                        $import_type = 'wiki_page';
                        break;
                    case 'award':
                        $import_type = 'award_type';
                        break;
                    case 'news':
                        $import_type = 'news_category';
                        break;
                    case 'tickets':
                        $import_type = 'ticket_type';
                        break;
                }
                if ($str) {
                    $id_new = import_id_remap_get($import_type, $row['category_name'], true);
                    if (is_null($id_new)) {
                        continue;
                    }
                    $row['category_name'] = strval($id_new);
                }
            }
            if (!array_key_exists('the_value', $row)) {
                $row['the_value'] = '1';
            }
            $GLOBALS['SITE_DB']->query_insert('group_privileges', $row);
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'group_page_access');
        foreach ($rows as $row) {
            if ($row['page_name'] == 'cedi') {
                $row['page_name'] = 'wiki';
            }
            if ($row['page_name'] == 'cms_cedi') {
                $row['page_name'] = 'cms_wiki';
            }

            $row['group_id'] = $on_same_msn ? $row['group_id'] : import_id_remap_get('group', strval($row['group_id']), true);
            if (is_null($row['group_id'])) {
                continue;
            }
            $GLOBALS['SITE_DB']->query_delete('group_page_access', $row, '', 1);
            $GLOBALS['SITE_DB']->query_insert('group_page_access', $row);
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'group_zone_access');
        foreach ($rows as $row) {
            $row['group_id'] = $on_same_msn ? $row['group_id'] : import_id_remap_get('group', strval($row['group_id']), true);
            if (is_null($row['group_id'])) {
                continue;
            }
            $GLOBALS['SITE_DB']->query_delete('group_zone_access', $row, '', 1);
            $GLOBALS['SITE_DB']->query_insert('group_zone_access', $row);
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'https_pages');
        foreach ($rows as $row) {
            $GLOBALS['SITE_DB']->query_delete('https_pages', $row);
            $GLOBALS['SITE_DB']->query_insert('https_pages', $row);
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'group_category_access');
        foreach ($rows as $row) {
            $row['group_id'] = $on_same_msn ? $row['group_id'] : import_id_remap_get('group', strval($row['group_id']), true);
            if (is_null($row['group_id'])) {
                continue;
            }
            if (is_numeric($row['category_name'])) {
                if ($row['module_the_name'] == 'seedy_page') {
                    $row['module_the_name'] = 'wiki_page';
                }

                $import_type = $row['module_the_name'];
                $str = false;
                switch ($import_type) {
                    case 'galleries':
                        $import_type = 'gallery';
                        $str = true;
                        break;
                    case 'downloads':
                        $import_type = 'download_category';
                        break;
                    case 'calendar':
                        $import_type = 'event_type';
                        break;
                    case 'catalogues_catalogue':
                        $import_type = 'catalogue';
                        $str = true;
                        break;
                    case 'catalogues_category':
                        $import_type = 'catalogue_category';
                        break;
                    case 'forums':
                        $import_type = 'forum';
                        break;
                    case 'topics':
                        $import_type = 'topic';
                        break;
                    case 'wiki_page':
                        $import_type = 'wiki_page';
                        break;
                    case 'award':
                        $import_type = 'award_type';
                        break;
                    case 'news':
                        $import_type = 'news_category';
                        break;
                    case 'tickets':
                        $import_type = 'ticket_type';
                        break;
                }
                if (!$str) {
                    $id_new = import_id_remap_get($import_type, $row['category_name'], true);
                    if (is_null($id_new)) {
                        continue;
                    }
                    $row['category_name'] = strval($id_new);
                }
            }
            $GLOBALS['SITE_DB']->query_delete('group_category_access', $row, '', 1);
            $GLOBALS['SITE_DB']->query_insert('group_category_access', $row);
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'member_zone_access');
        foreach ($rows as $row) {
            $member_id = import_id_remap_get('member', strval($row['member_id']), true);
            if (is_null($member_id)) {
                continue;
            }
            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('member_zone_access', 'zone_name', array('member_id' => $member_id, 'zone_name' => $row['zone_name']));
            if (!is_null($test)) {
                continue;
            }

            $GLOBALS['SITE_DB']->query_insert('member_zone_access', array('zone_name' => $row['zone_name'], 'member_id' => $member_id, 'active_until' => $row['active_until']));
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'member_category_access');
        foreach ($rows as $row) {
            $member_id = import_id_remap_get('member', strval($row['member_id']), true);
            if (is_null($member_id)) {
                continue;
            }
            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('member_category_access', 'module_the_name', array('member_id' => $member_id, 'category_name' => $row['category_name']));
            if (!is_null($test)) {
                continue;
            }

            $GLOBALS['SITE_DB']->query_insert('member_category_access', array('module_the_name' => $row['module_the_name'], 'category_name' => $row['category_name'], 'member_id' => $member_id, 'active_until' => $row['active_until']));
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'member_page_access');
        foreach ($rows as $row) {
            $member_id = import_id_remap_get('member', strval($row['member_id']), true);
            if (is_null($member_id)) {
                continue;
            }
            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('member_page_access', 'page_name', array('member_id' => $member_id, 'page_name' => $row['page_name']));
            if (!is_null($test)) {
                continue;
            }
            $zone_name = $row['zone_name'];
            $page_name = $row['page_name'];

            $GLOBALS['SITE_DB']->query_insert('member_page_access', array('page_name' => $page_name, 'zone_name' => $zone_name, 'member_id' => $member_id, 'active_until' => $row['active_until']));
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . ($db->table_exists('member_privileges') ? 'member_privileges' : 'msp'));
        foreach ($rows as $row) {
            $member_id = import_id_remap_get('member', strval($row['member_id']), true);
            if (is_null($member_id)) {
                continue;
            }

            if (!array_key_exists('privilege', $row)) {
                $row['privilege'] = $row['specific_permission'];
                unset($row['specific_permission']);
            }

            $import_type = $row['module_the_name'];
            $str = !is_numeric($row['category_name']);
            switch ($import_type) {
                case 'galleries':
                    $import_type = 'gallery';
                    $str = true;
                    break;
                case 'downloads':
                    $import_type = 'download_category';
                    break;
                case 'calendar':
                    $import_type = 'event_type';
                    break;
                case 'catalogues_catalogue':
                    $import_type = 'catalogue';
                    $str = true;
                    break;
                case 'catalogues_category':
                    $import_type = 'catalogue_category';
                    break;
                case 'forums':
                    $import_type = 'forum';
                    break;
                case 'topics':
                    $import_type = 'topic';
                    break;
                case 'wiki_page':
                    $import_type = 'wiki_page';
                    break;
                case 'award':
                    $import_type = 'award_type';
                    break;
                case 'news':
                    $import_type = 'news_category';
                    break;
                case 'tickets':
                    $import_type = 'ticket_type';
                    break;
            }
            if (!$str) {
                $id_new = import_id_remap_get($import_type, $row['category_name'], true);
                if (is_null($id_new)) {
                    continue;
                }
                $row['category_name'] = strval($id_new);
            }

            $row['member_id'] = $member_id;
            $GLOBALS['SITE_DB']->query_delete('member_privileges', $row);
            $GLOBALS['SITE_DB']->query_insert('member_privileges', $row);
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_notifications($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'notifications_enabled', null, null, true);
        if (!is_null($rows)) {
            foreach ($rows as $row) {
                $member_id = import_id_remap_get('member', strval($row['l_member_id']), true);
                if (is_null($member_id)) {
                    continue;
                }

                if ($row['l_notification_code'] == 'cedi') {
                    $row['l_notification_code'] = 'wiki';
                }

                $test = $GLOBALS['SITE_DB']->query_select_value_if_there('notifications_enabled', 'id', array('l_member_id' => $member_id, 'l_notification_code' => $row['l_notification_code']));
                if (!is_null($test)) {
                    continue;
                }

                unset($row['id']);

                $row['l_member_id'] = $member_id;

                $GLOBALS['SITE_DB']->query_insert('notifications_enabled', $row);
            }
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'device_token_details', null, null, true);
        if (!is_null($rows)) {
            foreach ($rows as $row) {
                $member_id = import_id_remap_get('member', strval($row['member_id']), true);
                if (is_null($member_id)) {
                    continue;
                }

                unset($row['id']);

                $row['member_id'] = $member_id;

                $GLOBALS['SITE_DB']->query_insert('device_token_details', $row);
            }
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'notification_lockdown', null, null, true);
        if (!is_null($rows)) {
            foreach ($rows as $row) {
                $test = $GLOBALS['SITE_DB']->query_select_value_if_there('notification_lockdown', 'l_notification_code', array('l_notification_code' => $row['l_notification_code']));
                if (!is_null($test)) {
                    continue;
                }

                unset($row['id']);

                $GLOBALS['SITE_DB']->query_insert('notification_lockdown', $row);
            }
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_cns_groups($db, $table_prefix, $file_base)
    {
        if ($this->on_same_msn($file_base)) {
            return;
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_groups');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            if (import_check_if_imported('group', strval($row['id']))) {
                continue;
            }

            $name = $this->get_lang_string($db, $row['g_name']);
            $id_new = $GLOBALS['FORUM_DB']->query_select_value_if_there('f_groups', 'id', array($GLOBALS['FORUM_DB']->translate_field_ref('g_name') => $name));
            if (is_null($id_new)) {
                $title = $this->get_lang_string($db, $row['g_title']);

                if (!array_key_exists('g_is_presented_at_install', $row)) {
                    $row['g_is_presented_at_install'] = 0;
                }

                $row['g_rank_image'] = str_replace('ocf_', 'cns_', $row['g_rank_image']);

                $id_new = cns_make_group($name, array_key_exists('g_is_default', $row) ? $row['g_is_default'] : 0, $row['g_is_super_admin'], $row['g_is_super_moderator'], $title, '', $row['g_promotion_target'], $row['g_promotion_threshold'], -$row['g_group_leader'], $row['g_flood_control_submit_secs'], $row['g_flood_control_access_secs'], $row['g_max_daily_upload_mb'], $row['g_max_attachments_per_post'], $row['g_max_avatar_width'], $row['g_max_avatar_height'], $row['g_max_post_length_comcode'], $row['g_max_sig_length_comcode'], $row['g_gift_points_base'], $row['g_gift_points_per_day'], $row['g_enquire_on_new_ips'], $row['g_is_presented_at_install'], array_key_exists('g_hidden', $row) ? $row['g_hidden'] : 0, array_key_exists('g_order', $row) ? $row['g_order'] : null, array_key_exists('g_rank_image_pri_only', $row) ? $row['g_rank_image_pri_only'] : 0, array_key_exists('g_open_membership', $row) ? $row['g_open_membership'] : 0, array_key_exists('g_is_private_club', $row) ? $row['g_is_private_club'] : 0);
            }

            import_id_remap_put('group', strval($row['id']), $id_new);
        }

        // Now we must fix promotion
        foreach ($rows as $row) {
            if (!is_null($row['g_promotion_target'])) {
                $row_promotion_target = import_id_remap_get('group', strval($row['g_promotion_target']), true);
                if (is_null($row_promotion_target)) {
                    continue;
                }
                $GLOBALS['FORUM_DB']->query_update('f_groups', array('g_promotion_target' => $row_promotion_target), array('id' => import_id_remap_get('group', strval($row['id']))), '', 1);
            }
        }
        $this->_import_content_reviews($db, $table_prefix, 'group', 'group');
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_cns_members($db, $table_prefix, $file_base)
    {
        if ($this->on_same_msn($file_base)) {
            return;
        }

        $cpf_types = collapse_2d_complexity('id', 'cf_type', $GLOBALS['FORUM_DB']->query_select('f_custom_fields', array('id', 'cf_type')));

        $row_start = 0;
        $rows = array();
        do {
            $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_members ORDER BY id', 200, $row_start);
            $this->_fix_comcode_ownership($rows);
            foreach ($rows as $row) {
                if (import_check_if_imported('member', strval($row['id']))) {
                    continue;
                }

                $id_new = $GLOBALS['CNS_DRIVER']->get_member_from_username($row['m_username']);
                if (is_null($id_new)) {
                    $primary_group = import_id_remap_get('group', strval($row['m_primary_group']));

                    $custom_fields = array();

                    $id = (get_param_integer('keep_preserve_ids', 0) == 0) ? null : $row['id'];

                    $timezone = $row['m_timezone_offset'];
                    if (is_integer($timezone)) {
                        $timezone = strval($timezone);
                    }

                    if (!isset($row['m_auto_monitor_contrib_content'])) {
                        $row['m_auto_monitor_contrib_content'] = $row['m_track_contributed_topics'];
                    }

                    $row['m_avatar_url'] = str_replace('ocf_', 'cns_', $row['m_avatar_url']);

                    $id_new = cns_make_member($row['m_username'], $row['m_pass_hash_salted'], $row['m_email_address'], null, $row['m_dob_day'], $row['m_dob_month'], $row['m_dob_year'], $custom_fields, $timezone, $primary_group, $row['m_validated'], $row['m_join_time'], $row['m_last_visit_time'], $row['m_theme'], $row['m_avatar_url'], $this->get_lang_string($db, $row['m_signature']), $row['m_is_perm_banned'], $row['m_preview_posts'], $row['m_reveal_age'], $row['m_title'], $row['m_photo_url'], $row['m_photo_thumb_url'], $row['m_views_signatures'], $row['m_auto_monitor_contrib_content'], $row['m_language'], $row['m_allow_emails'], array_key_exists('m_allow_emails_from_staff', $row) ? $row['m_allow_emails_from_staff'] : $row['m_allow_emails'], $row['m_ip_address'], $row['m_validated_email_confirm_code'], false, array_key_exists('m_password_compat_scheme', $row) ? $row['m_password_compat_scheme'] : $row['m_password_compatibility_scheme'], $row['m_pass_salt'], $row['m_last_submit_time'], $id, array_key_exists('m_highlighted_name', $row) ? $row['m_highlighted_name'] : 0, array_key_exists('m_pt_allow', $row) ? $row['m_pt_allow'] : '*', array_key_exists('m_pt_rules_text', $row) ? $this->get_lang_string($db, $row['m_pt_rules_text']) : '', $row['m_on_probation_until'], isset($row['m_auto_mark_read']) ? $row['m_auto_mark_read'] : 1, isset($row['m_profile_views']) ? $row['m_profile_views'] : 0, isset($row['m_total_sessions']) ? $row['m_total_sessions'] : 0);
                    $rows2 = $db->query('SELECT * FROM ' . $table_prefix . 'f_member_custom_fields WHERE mf_member_id=' . strval($row['id']), 1);
                    $this->_fix_comcode_ownership($rows2);
                    if (array_key_exists(0, $rows2)) {
                        $row2 = array();
                        foreach ($rows2[0] as $key => $val) {
                            if (is_null($val)) {
                                $val = '';
                            }
                            if (preg_match('#^field\_\d+$#', $key) != 0) {
                                $cpf_id = import_id_remap_get('cpf', substr($key, 6), true);
                                if (is_null($cpf_id)) {
                                    continue;
                                }
                                $cpf_type = $cpf_types[$cpf_id];
                                if (($cpf_type == 'short_trans') || ($cpf_type == 'long_trans')) {
                                    unset($row2['field_' . strval($cpf_id) . '__text_parsed']);
                                    unset($row2['field_' . strval($cpf_id) . '__source_user']);

                                    $row2 = insert_lang_comcode('field_' . strval($cpf_id), $this->get_lang_string($db, intval($val)), 3) + $row2;
                                } else {
                                    $row2['field_' . strval($cpf_id)] = $val;
                                }
                            }
                        }
                        $GLOBALS['SITE_DB']->query_update('f_member_custom_fields', $row2, array('mf_member_id' => $id_new), '', 1);
                    }

                    // Fix some tricky dependencies that we shoved to one side
                    $GLOBALS['FORUM_DB']->query_update('f_groups', array('g_group_leader' => $id_new), array('g_group_leader' => -$row['id']));
                    $GLOBALS['SITE_DB']->query_update('attachments', array('a_member_id' => $id_new), array('a_member_id' => -$row['id']));
                }

                import_id_remap_put('member', strval($row['id']), $id_new);
            }

            $row_start += 200;
        } while (count($rows) > 0);
        $this->_import_content_reviews($db, $table_prefix, 'member', 'member');

        // Group membership
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_group_members');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $row['gm_group_id'] = import_id_remap_get('group', strval($row['gm_group_id']), true);
            if (is_null($row['gm_group_id'])) {
                continue;
            }
            $row['gm_member_id'] = import_id_remap_get('member', strval($row['gm_member_id']), true);
            if (is_null($row['gm_member_id'])) {
                continue;
            }
            $GLOBALS['SITE_DB']->query_insert('f_group_members', $row, false, true);
        }

        // Known login IPs
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_member_known_login_ips');
        foreach ($rows as $row) {
            $row['i_member_id'] = import_id_remap_get('member', strval($row['i_member_id']), true);
            if (is_null($row['i_member_id'])) {
                continue;
            }
            $GLOBALS['SITE_DB']->query_insert('f_member_known_login_ips', $row);
        }

        // Group member timeouts
        if ($db->table_exists('f_group_member_timeouts')) {
            $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_group_member_timeouts');
            foreach ($rows as $row) {
                $member_id = import_id_remap_get('member', strval($row['member_id']));
                if (is_null($member_id)) {
                    continue;
                }
                $group_id = import_id_remap_get('group', strval($row['group_id']));
                if (is_null($group_id)) {
                    continue;
                }
                $GLOBALS['SITE_DB']->query_insert('f_group_member_timeouts', array('member_id' => $member_id, 'group_id' => $group_id, 'timeout' => $row['timeout']));
            }
        }

        // Invites
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_invites ORDER BY id', null, null, true);
        if (!is_null($rows)) {
            foreach ($rows as $row) {
                $i_inviter = import_id_remap_get('member', strval($row['i_inviter']), true);
                if (is_null($i_inviter)) {
                    continue;
                }

                $GLOBALS['SITE_DB']->query_insert('f_invites', array('i_inviter' => $i_inviter, 'i_email_address' => $row['i_email_address'], 'i_time' => $row['i_time'], 'i_taken' => $row['i_taken']), false, true);
            }
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_cns_custom_profile_fields($db, $table_prefix, $file_base)
    {
        if ($this->on_same_msn($file_base)) {
            return;
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_custom_fields');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            if (import_check_if_imported('cpf', strval($row['id']))) {
                continue;
            }

            $name = $this->get_lang_string($db, $row['cf_name']);
            if ($name == 'cms_points_gained_seedy') {
                $name = 'cms_points_gained_wiki';
            }
            if ($name == 'ocp_building_name_or_number') {
                $name = 'ocp_street_address';
            }
            $name = str_replace('ocp_', 'cms_', $name);

            $existing = $GLOBALS['FORUM_DB']->query_select('f_custom_fields', array('id', 'cf_type'), array($GLOBALS['FORUM_DB']->translate_field_ref('cf_name') => $name), '', 1);
            if ((!array_key_exists(0, $existing)) || ($existing[0]['cf_type'] != $row['cf_type']) && (substr($name, 0, 4) != 'cms_')) {
                if ($row['cf_type'] == 'user') {
                    $row['cf_type'] = 'member';
                }
                if ($row['cf_type'] == 'user_multi') {
                    $row['cf_type'] = 'member_multi';
                }
                if ($row['cf_type'] == 'random') {
                    $row['cf_type'] = 'codename';
                    $row['cf_default'] = 'RANDOM';
                }
                if ($row['cf_type'] == 'combo_multi') {
                    $row['cf_type'] = 'list_multi';
                    $row['cf_options'] = 'widget=vertical_checkboxes,custom_values=yes';
                }
                if ($row['cf_type'] == 'multilist') {
                    $row['cf_type'] = 'list_multi';
                }
                if ($row['cf_type'] == 'tick_multi') {
                    $row['cf_type'] = 'list_multi';
                    $row['cf_options'] = 'widget=horizontal_checkboxes';
                }
                if ($row['cf_type'] == 'combo') {
                    $row['cf_type'] = 'list';
                    $row['cf_options'] = 'widget=radio,custom_values=yes';
                }
                if ($row['cf_type'] == 'radiolist') {
                    $row['cf_type'] = 'list';
                    $row['cf_options'] = 'widget=radio';
                }
                if ($row['cf_type'] == 'auto_increment') {
                    $row['cf_type'] = 'integer';
                    $row['cf_default'] = 'AUTO_INCREMENT';
                }

                $only_group = $row['cf_only_group'];
                if ($only_group != '') {
                    $only_group2 = '';
                    foreach (explode(',', $only_group) as $_only_group) {
                        if ($only_group2 != '') {
                            $only_group2 .= ',';
                        }
                        $group = import_id_remap_get('group', $_only_group, true);
                        if (is_null($group)) {
                            continue;
                        }
                        $only_group2 .= strval($group);
                    }
                    $only_group2 = $only_group;
                }

                $id_new = cns_make_custom_field($name, $row['cf_locked'], $this->get_lang_string($db, $row['cf_description']), $row['cf_default'], $row['cf_public_view'], $row['cf_owner_view'], $row['cf_owner_set'], array_key_exists('cf_encrypted', $row) ? $row['cf_encrypted'] : 0, $row['cf_type'], $row['cf_required'], $row['cf_show_in_posts'], $row['cf_show_in_post_previews'], $row['cf_order'], (!is_string($only_group)) ? (is_null($only_group) ? '' : strval($only_group)) : $only_group, $row['cf_show_on_join_form'], array_key_exists('cf_options', $row) ? $row['cf_options'] : '');
            } else {
                $id_new = $existing[0]['id'];
            }

            import_id_remap_put('cpf', strval($row['id']), $id_new);
        }

        // import member cpf_perms
        $this->_import_f_member_cpf_perms($db, $table_prefix);
    }

    /**
     * Import cpf premissions.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     */
    protected function _import_f_member_cpf_perms($db, $table_prefix)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_member_cpf_perms', null, null, true);
        if (is_null($rows)) {
            return;
        }
        foreach ($rows as $row) {
            $member_id = import_id_remap_get('member', strval($row['member_id']), true);
            if (is_null($member_id)) {
                continue;
            }
            $field_id = import_id_remap_get('cpf', strval($row['field_id']), true);
            if (is_null($field_id)) {
                continue;
            }
            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('f_member_cpf_perms', 'member_id', array('member_id' => $member_id, 'field_id' => $field_id));
            if (is_null($test)) {
                continue;
            }
            $GLOBALS['SITE_DB']->query_insert('f_member_cpf_perms', array('member_id' => $member_id, 'field_id' => $field_id, 'guest_view' => $row['guest_view'], 'member_view' => $row['member_view'], 'friend_view' => $row['friend_view'], 'group_view' => $row['group_view']));
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_cns_forum_groupings($db, $table_prefix, $file_base)
    {
        if ($this->on_same_msn($file_base)) {
            return;
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . ($db->table_exists('f_forum_groupings') ? 'f_forum_groupings' : 'f_categories'));
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            if (import_check_if_imported('forum_groupings', strval($row['id']))) {
                continue;
            }

            $title = $row['c_title'];

            $test = $GLOBALS['FORUM_DB']->query_select_value_if_there('f_forum_groupings', 'id', array('c_title' => $title));
            if (!is_null($test)) {
                import_id_remap_put('forum_groupings', strval($row['id']), $test);
                continue;
            }

            $id_new = cns_make_forum_grouping($title, $row['c_description'], $row['c_expanded_by_default']);

            import_id_remap_put('forum_groupings', strval($row['id']), $id_new);
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_cns_forums($db, $table_prefix, $file_base)
    {
        if ($this->on_same_msn($file_base)) {
            return;
        }

        require_code('cns_forums_action2');

        $comments_forum = get_option('comments_forum_name');
        if (!is_numeric($comments_forum)) {
            $comments_forum_id = $GLOBALS['FORUM_DRIVER']->forum_id_from_name($comments_forum);
        } else {
            $comments_forum_id = intval($comments_forum);
            $comments_forum = $GLOBALS['FORUM_DB']->query_select_value('f_forums', 'f_name', array('id' => $comments_forum_id));
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_forums');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $remapped = import_id_remap_get('forum', strval($row['id']), true);
            if (!is_null($remapped)) {
                continue;
            }
            if ($row['id'] == db_get_first_id()) {
                import_id_remap_put('forum', strval(db_get_first_id()), db_get_first_id());
                continue;
            }
            if (($row['f_name'] == $comments_forum) && (!is_null($comments_forum_id))) {
                import_id_remap_put('forum', strval($row['id']), $comments_forum_id);
                continue;
            }

            $forum_groupings_id = import_id_remap_get('forum_groupings', strval(isset($row['f_forum_groupings_id']) ? $row['f_forum_groupings_id'] : $row['f_category_id']), true);

            $id_new = cns_make_forum($row['f_name'], $this->get_lang_string($db, $row['f_description']), $forum_groupings_id, array(), db_get_first_id(), $row['f_position'], $row['f_post_count_increment'], $row['f_order_sub_alpha'], $this->get_lang_string($db, $row['f_intro_question']), $row['f_intro_answer'], $row['f_redirection'], array_key_exists('f_order', $row) ? $row['f_order'] : 'last_post', array_key_exists('f_is_threaded', $row) ? $row['f_is_threaded'] : 0, array_key_exists('f_allows_anonymous_posts', $row) ? $row['f_allows_anonymous_posts'] : 0);
            import_id_remap_put('forum', strval($row['id']), $id_new);
        }

        // Now we must fix parenting
        foreach ($rows as $row) {
            if (is_null($row['f_parent_forum'])) {
                continue;
            }
            $parent_id = import_id_remap_get('forum', strval($row['f_parent_forum']), true);
            if (is_null($parent_id)) {
                $parent_id = db_get_first_id();
            }
            $GLOBALS['FORUM_DB']->query_update('f_forums', array('f_parent_forum' => $parent_id), array('id' => import_id_remap_get('forum', strval($row['id']))), '', 1);
        }

        $this->_import_content_reviews($db, $table_prefix, 'forum', 'forum');
        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'forum', 'forum');

        // Intros
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_forum_intro_ip');
        foreach ($rows as $row) {
            $row['i_forum_id'] = import_id_remap_get('forum', strval($row['i_forum_id']), true);
            if (is_null($row['i_forum_id'])) {
                continue;
            }
            $GLOBALS['FORUM_DB']->query_delete('f_forum_intro_ip', $row, '', 1);
            $GLOBALS['FORUM_DB']->query_insert('f_forum_intro_ip', $row);
        }
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_forum_intro_member');
        foreach ($rows as $row) {
            $row['i_forum_id'] = import_id_remap_get('forum', strval($row['i_forum_id']), true);
            if (is_null($row['i_forum_id'])) {
                continue;
            }
            $GLOBALS['FORUM_DB']->query_delete('f_forum_intro_member', $row, '', 1);
            $GLOBALS['FORUM_DB']->query_insert('f_forum_intro_member', $row);
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_cns_topics($db, $table_prefix, $file_base)
    {
        if ($this->on_same_msn($file_base)) {
            return;
        }

        $row_start = 0;
        $rows = array();
        do {
            $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_topics ORDER BY id', 200, $row_start);
            $this->_fix_comcode_ownership($rows);
            foreach ($rows as $row) {
                if (import_check_if_imported('topic', strval($row['id']))) {
                    continue;
                }

                if (is_null($row['t_forum_id'])) {
                    $forum_id = null;
                } else {
                    $forum_id = import_id_remap_get('forum', strval($row['t_forum_id']), true);
                    if (is_null($forum_id)) {
                        continue;
                    }
                }

                // Comment topic remapping
                $matches = array();
                if (preg_match('#: \#(\w+)s_(\d+)$#', $row['t_description'], $matches) != 0) {
                    $import_type = $matches[1];
                    if ($import_type == 'new') {
                        $import_type = 'news';
                    }
                    $c_id = import_id_remap_get($import_type, $matches[2], true);
                    if (!is_null($c_id)) {
                        $row['t_description'] = str_replace($matches[0], ': #' . $matches[1] . 's_' . strval($c_id), $row['t_description']);
                    }
                }
                // NB: Spacer post not fixed up

                $t_pt_to = $row['t_pt_to'];
                $t_pt_from = $row['t_pt_from'];
                if (!is_null($t_pt_to)) {
                    $t_pt_to = import_id_remap_get('member', strval($t_pt_to), true);
                    if (is_null($t_pt_to)) {
                        $t_pt_to = db_get_first_id();
                    }
                }
                if (!is_null($t_pt_from)) {
                    $t_pt_from = import_id_remap_get('member', strval($t_pt_from), true);
                    if (is_null($t_pt_from)) {
                        $t_pt_from = db_get_first_id();
                    }
                }

                $id = (get_param_integer('keep_preserve_ids', 0) == 0) ? null : $row['id'];

                $row['t_emoticon'] = str_replace('ocf_', 'cns_', $row['t_emoticon']);

                $id_new = cns_make_topic($forum_id, $row['t_description'], $row['t_emoticon'], $row['t_validated'], $row['t_is_open'], array_key_exists('t_is_sunk', $row) ? $row['t_is_sunk'] : 0, $row['t_pinned'], $row['t_cascading'], $t_pt_from, $t_pt_to, false, $row['t_num_views'], $id);

                import_id_remap_put('topic', strval($row['id']), $id_new);
            }

            $row_start += 200;
        } while (count($rows) > 0);

        $this->_import_content_reviews($db, $table_prefix, 'topic', 'topic');

        // Read logs
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_read_logs');
        foreach ($rows as $row) {
            $row['l_member_id'] = import_id_remap_get('member', strval($row['l_member_id']), true);
            $row['l_topic_id'] = import_id_remap_get('topic', strval($row['l_topic_id']), true);
            if (is_null($row['l_member_id'])) {
                continue;
            }
            if (is_null($row['l_topic_id'])) {
                continue;
            }
            $GLOBALS['FORUM_DB']->query_delete('f_read_logs', $row, '', 1);
            $GLOBALS['FORUM_DB']->query_insert('f_read_logs', $row);
        }

        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'topic', 'topic');

        // Special pt access
        $row_start = 0;
        $rows = array();
        do {
            $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_special_pt_access ORDER BY s_topic_id,s_member_id', 200, $row_start);
            $this->_fix_comcode_ownership($rows);
            foreach ($rows as $row) {
                $row['s_member_id'] = import_id_remap_get('member', strval($row['s_member_id']), true);
                $row['s_topic_id'] = import_id_remap_get('topic', strval($row['s_topic_id']), true);
                if (is_null($row['s_member_id'])) {
                    continue;
                }
                if (is_null($row['s_topic_id'])) {
                    continue;
                }
                $GLOBALS['FORUM_DB']->query_delete('f_special_pt_access', $row);
                $GLOBALS['FORUM_DB']->query_insert('f_special_pt_access', $row);
            }

            $row_start += 200;
        } while (count($rows) > 0);
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_cns_posts($db, $table_prefix, $file_base)
    {
        if ($this->on_same_msn($file_base)) {
            return;
        }

        global $TOPIC_FORUM_CACHE;
        $TOPIC_FORUM_CACHE = array();

        $row_start = 0;

        // Optimisation to speed through quickly, as can be slow scrolling through so many posts we may have already imported!
        do {
            $rows = $db->query('SELECT id FROM ' . $table_prefix . 'f_posts ORDER BY id', 1, $row_start + 200 - 1);
            if ((!array_key_exists(0, $rows)) || (!import_check_if_imported('post', strval($rows[0]['id'])))) {
                break;
            }

            $row_start += 200;
        } while (true);

        $rows = array();
        do {
            $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_posts ORDER BY id', 200, $row_start);
            $this->_fix_comcode_ownership($rows);
            foreach ($rows as $row) {
                if (import_check_if_imported('post', strval($row['id']))) {
                    continue;
                }

                $member_id = import_id_remap_get('member', strval($row['p_poster']), true);
                if (is_null($member_id)) {
                    $member_id = db_get_first_id();
                }

                $topic_id = import_id_remap_get('topic', strval($row['p_topic_id']), true);
                if (is_null($topic_id)) {
                    continue;
                }

                // This speeds up addition... using the cache can reduce about 7/8 of a query per post on average
                if (array_key_exists($topic_id, $TOPIC_FORUM_CACHE)) {
                    $forum_id = $TOPIC_FORUM_CACHE[$topic_id];
                } else {
                    $forum_id = $GLOBALS['FORUM_DB']->query_select_value_if_there('f_topics', 't_forum_id', array('id' => $topic_id));
                    $TOPIC_FORUM_CACHE[$topic_id] = $forum_id;
                }

                $last_edit_by = $row['p_last_edit_by'];
                if (!is_null($last_edit_by)) {
                    $last_edit_by = import_id_remap_get('member', strval($last_edit_by), true);
                }
                $intended_solely_for = $row['p_intended_solely_for'];
                if (!is_null($intended_solely_for)) {
                    $intended_solely_for = import_id_remap_get('member', strval($intended_solely_for), true);
                    if (is_null($intended_solely_for)) {
                        $intended_solely_for = -1;
                    }
                }
                $id = (get_param_integer('keep_preserve_ids', 0) == 0) ? null : $row['id'];
                $id_new = cns_make_post($topic_id, $row['p_title'], $this->get_lang_string($db, $row['p_post']), 0, false, $row['p_validated'], $row['p_is_emphasised'], $row['p_poster_name_if_guest'], $row['p_ip_address'], $row['p_time'], $member_id, $intended_solely_for, $row['p_last_edit_time'], $last_edit_by, false, false, $forum_id, false, '', 0, $id, false, true);

                import_id_remap_put('post', strval($row['id']), $id_new);
            }

            $row_start += 200;
        } while (count($rows) > 0);

        $this->_import_review_supplement($db, $table_prefix, 'post', 'post');
        $this->_import_catalogue_entry_linkage($db, $table_prefix, 'post', 'post');
        $this->_import_content_reviews($db, $table_prefix, 'post', 'post');
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_cns_polls_and_votes($db, $table_prefix, $file_base)
    {
        if ($this->on_same_msn($file_base)) {
            return;
        }

        $rows = $db->query('SELECT p.*,t.id AS tid FROM ' . $table_prefix . 'f_polls p LEFT JOIN ' . $table_prefix . 'f_topics t ON p.id=t.t_poll_id');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            if (import_check_if_imported('poll', strval($row['id']))) {
                continue;
            }

            $topic_id = import_id_remap_get('topic', strval($row['tid']), true);
            if (is_null($topic_id)) {
                continue;
            }

            $rows2 = $db->query('SELECT * FROM ' . $table_prefix . 'f_poll_votes WHERE pv_poll_id=' . strval($row['id']));
            foreach ($rows2 as $i => $row2) {
                $rows2[$i]['pv_member_id'] = import_id_remap_get('member', strval($row2['pv_member_id']), true);
            }
            $rows3 = $db->query('SELECT * FROM ' . $table_prefix . 'f_poll_answers WHERE pa_poll_id=' . strval($row['id']) . ' ORDER BY id');
            $answers = array();
            $id_ordinal_map = array();
            foreach ($rows3 as $i => $row3) {
                $answers[] = array($row3['pa_answer'], 0);
                $id_ordinal_map[$row3['id']] = $i;
            }

            $id_new = cns_make_poll($topic_id, $row['po_question'], $row['po_is_private'], $row['po_is_open'], $row['po_minimum_selections'], $row['po_maximum_selections'], $row['po_requires_reply'], $answers, false);

            $answers = collapse_1d_complexity('id', $GLOBALS['FORUM_DB']->query_select('f_poll_answers', array('id'), array('pa_poll_id' => $id_new))); // Effectively, a remapping from vote number ordinal to new vote number
            foreach ($rows2 as $row2) {
                $vote = $row2['pv_answer_id'];
                if (!array_key_exists($vote, $id_ordinal_map)) {
                    continue;
                }
                if (!array_key_exists($id_ordinal_map[$vote], $answers)) {
                    continue;
                }
                $answer = $answers[$id_ordinal_map[$vote]];
                if (is_null($row2['pv_member_id'])) {
                    continue;
                }
                $GLOBALS['FORUM_DB']->query_insert('f_poll_votes', array('pv_poll_id' => $id_new, 'pv_member_id' => $row2['pv_member_id'], 'pv_answer_id' => $answer, 'pv_ip' => array_key_exists('pv_ip', $row2) ? $row2['pv_ip'] : ''));
            }

            import_id_remap_put('f_poll', strval($row['id']), $id_new);
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_cns_emoticons($db, $table_prefix, $file_base)
    {
        if ($this->on_same_msn($file_base)) {
            return;
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_emoticons');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $test = $GLOBALS['FORUM_DB']->query_select_value_if_there('f_emoticons', 'e_code', array('e_code' => $row['e_code']));
            if (is_null($test)) {
                $row['e_theme_img_code'] = str_replace('ocf_', 'cns_', $row['e_theme_img_code']);

                $GLOBALS['FORUM_DB']->query_insert('f_emoticons', $row);
            }
        }
    }

    /**
     * Pass a multi-code through a forum remap.
     *
     * @param  SHORT_TEXT $multi_code Multi code
     * @return SHORT_TEXT New multi code
     */
    public function convert_multi_code($multi_code)
    {
        if ($multi_code == '*') {
            return $multi_code;
        }
        if ($multi_code == '') {
            return $multi_code;
        }

        $new_multi_code = '';
        if ($multi_code[0] == '+') {
            $parts = explode(',', substr($multi_code, 1));
            $new_multi_code = '+';
            foreach ($parts as $_part) {
                $part = import_id_remap_get('forum', trim($_part), true);
                if (!is_null($part)) {
                    if ($new_multi_code != '') {
                        $new_multi_code .= ',';
                    }
                    $new_multi_code .= strval($part);
                }
            }
        } else {
            $parts = explode(',', $multi_code);
            foreach ($parts as $_part) {
                $part = import_id_remap_get('forum', trim($_part), true);
                if (!is_null($part)) {
                    if ($new_multi_code != '') {
                        $new_multi_code .= ',';
                    }
                    $new_multi_code .= strval($part);
                }
            }
        }

        return $new_multi_code;
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_cns_multi_moderations($db, $table_prefix, $file_base)
    {
        if ($this->on_same_msn($file_base)) {
            return;
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_multi_moderations');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $name = $this->get_lang_string($db, $row['mm_name']);
            $test = $GLOBALS['FORUM_DB']->query_select_value_if_there('f_multi_moderations', 'id', array($GLOBALS['FORUM_DB']->translate_field_ref('mm_name') => $name));
            if (is_null($test)) {
                $move_to = is_null($row['mm_move_to']) ? null : import_id_remap_get('forum', strval($row['mm_move_to']), true);
                $multi_code = $this->convert_multi_code($row['mm_forum_multi_code']);
                cns_make_multi_moderation($name, $row['mm_post_text'], $move_to, $row['mm_pin_state'], array_key_exists('mm_sink_state', $row) ? $row['mm_sink_state'] : null, $row['mm_open_state'], $multi_code, array_key_exists('mm_title_suffix', $row) ? $row['mm_title_suffix'] : '');
            }
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_cns_post_templates($db, $table_prefix, $file_base)
    {
        if ($this->on_same_msn($file_base)) {
            return;
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_post_templates');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $multi_code = $this->convert_multi_code($row['t_forum_multi_code']);
            cns_make_post_template($row['t_title'], $row['t_text'], $multi_code, $row['t_use_default_forums']);
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_cns_warnings($db, $table_prefix, $file_base)
    {
        if ($this->on_same_msn($file_base)) {
            return;
        }

        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_warnings');
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $member_id = import_id_remap_get('member', strval($row['w_member_id']), true);
            $by = import_id_remap_get('member', strval($row['w_by']), true);
            if (is_null($member_id)) {
                continue;
            }
            if (is_null($by)) {
                $by = $GLOBALS['FORUM_DRIVER']->get_guest_id();
            }

            $silence_from_topic = array_key_exists('w_silence_from_topic', $row) ? import_id_remap_get('topic', strval($row['w_silence_from_topic']), true) : null;
            if (is_null($silence_from_topic)) {
                $silence_from_topic = null;
            }

            $silence_from_forum = array_key_exists('w_silence_from_forum', $row) ? import_id_remap_get('forum', strval($row['w_silence_from_forum']), true) : null;
            if (is_null($silence_from_forum)) {
                $silence_from_forum = null;
            }

            $changed_usergroup_from = array_key_exists('w_changed_usergroup_from', $row) ? import_id_remap_get('group', strval($row['w_changed_usergroup_from']), true) : null;
            if (is_null($changed_usergroup_from)) {
                $changed_usergroup_from = null;
            }

            cns_make_warning($member_id, $row['w_explanation'], $by, $row['w_time'], array_key_exists('w_is_warning', $row) ? $row['w_is_warning'] : 1, $silence_from_topic, $silence_from_forum, array_key_exists('w_probation', $row) ? $row['w_probation'] : 0, array_key_exists('w_banned_ip', $row) ? $row['w_banned_ip'] : '', array_key_exists('w_charged_points', $row) ? $row['w_charged_points'] : 0, array_key_exists('w_banned_member', $row) ? $row['w_banned_member'] : 0, $changed_usergroup_from);
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_aggregate_type_instances($db, $table_prefix, $file_base)
    {
        require_code('aggregate_types');

        $start = 0;
        do {
            $rows = $db->query_select('aggregate_type_instances', array('*'), null, '', 100, $start);
            $this->_fix_comcode_ownership($rows);
            foreach ($rows as $row) {
                if (import_check_if_imported('aggregate_type_instance', strval($row['id']))) {
                    continue;
                }

                $id_new = add_aggregate_type_instance($row['aggregate_label'], $row['aggregate_type'], $row['other_parameters'], $row['add_time'], $row['edit_time'], false);

                import_id_remap_put('aggregate_type_instance', strval($row['id']), $id_new);
            }
            $start += 100;
        } while (count($rows) != 0);
    }

    /**
     * Import privacy for a particular record.
     *
     * @param  object $db The DB connection to import from
     * @param  ID_TEXT $content_type The content type
     * @param  ID_TEXT $old_id The old ID
     * @param  ID_TEXT $id_new The new ID
     */
    protected function _import_content_privacy($db, $content_type, $old_id, $id_new)
    {
        if (addon_installed('content_privacy')) {
            if (!$db->table_exists('content_privacy')) {
                return;
            }

            $rows = $db->query_select('content_privacy', array('*'), array('content_type' => $content_type, 'content_id' => $old_id), '', 1);
            foreach ($rows as $row) {
                $GLOBALS['SITE_DB']->query_insert('content_privacy', array(
                    'content_id' => $id_new,
                ) + $row);
            }

            $rows = $db->query_select('content_privacy__members', array('*'), array('content_type' => $content_type, 'content_id' => $old_id));
            foreach ($rows as $row) {
                $member_id = import_id_remap_get('member', strval($row['member_id']), true);
                if (!is_null($member_id)) {
                    $GLOBALS['SITE_DB']->query_insert('content_privacy__members', array(
                        'content_id' => $id_new,
                        'member_id' => $member_id,
                    ) + $row);
                }
            }
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_cns_saved_warnings($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'f_saved_warnings', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('f_saved_warnings', 's_title', array('s_title' => $row['s_title']));
            if (!is_null($test)) {
                continue;
            }

            $GLOBALS['SITE_DB']->query_insert('f_saved_warnings', array('s_title' => $row['s_title'], 's_explanation' => $row['s_explanation'], 's_message' => $row['s_message']));
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_match_key_messages($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'match_key_messages', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            $test = $GLOBALS['SITE_DB']->query_select_value_if_there('match_key_messages', 'id', array('k_match_key' => $row['k_match_key']));
            if (!is_null($test)) {
                continue;
            }

            $row['k_message'] = $this->get_lang_string($db, $row['k_message']);

            $GLOBALS['SITE_DB']->query_insert('match_key_messages', $row);
        }
    }

    /**
     * Standard import function.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_menu_items($db, $table_prefix, $file_base)
    {
        $parent_rows = $db->query('SELECT * FROM ' . $table_prefix . 'menu_items');
        if (is_null($parent_rows)) {
            return;
        }
        $this->_fix_comcode_ownership($parent_rows);
        foreach ($parent_rows as $row) {
            $id_old = strval($row['id']);
            unset($row['id']);

            if (import_check_if_imported('menu_item', $id_old)) {
                continue;
            }

            $row['i_parent'] = is_null($row['i_parent']) ? null : (-$row['i_parent']);

            unset($row['i_caption__text_parsed']);
            unset($row['i_caption__source_user']);
            unset($row['i_caption_long__text_parsed']);
            unset($row['i_caption_long__source_user']);

            $row = insert_lang_comcode('i_caption', $this->get_lang_string($db, $row['i_caption']), 1) + $row;
            $row = insert_lang_comcode('i_caption_long', $this->get_lang_string($db, $row['i_caption_long']), 1) + $row;

            if (!array_key_exists('i_theme_img_code', $row)) {
                $row['i_theme_img_code'] = '';
            }

            if (!array_key_exists('i_include_sitemap', $row)) {
                $row['i_include_sitemap'] = 0;
            }

            $id_new = $GLOBALS['SITE_DB']->query_insert('menu_items', $row, true);
            import_id_remap_put('menu_item', $id_old, 1);
        }

        $child_rows = $GLOBALS['SITE_DB']->query('SELECT * FROM ' . get_table_prefix() . 'menu_items WHERE i_parent<0');
        foreach ($child_rows as $row) {
            $row['i_parent'] = import_id_remap_get('menu_item', strval(-$row['i_parent']), true);
            $GLOBALS['SITE_DB']->query_update('menu_items', $row, array('id' => $row['id']), '', 1);
        }
    }

    /**
     * Imports custom products.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     */
    protected function _import_pstore_customs($db, $table_prefix)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'pstore_customs', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            unset($row['id']);

            $row['c_description'] = $this->get_lang_string($db, $row['c_description']);

            $GLOBALS['SITE_DB']->query_insert('pstore_customs', $row);
        }
    }

    /**
     * Imports product store permissions.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     */
    protected function _import_pstore_permissions($db, $table_prefix)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'pstore_permissions', null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            unset($row['id']);

            if (!array_key_exists('p_privilege', $row)) {
                $row['p_privilege'] = $row['p_specific_permission'];
                unset($row['p_specific_permission']);
            }

            $row['p_description'] = $this->get_lang_string($db, $row['p_description']);

            $GLOBALS['SITE_DB']->query_insert('pstore_permissions', $row);
        }
    }

    /**
     * Import saved searches.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_searches_saved($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'searches_saved', null, null, true);
        if (is_null($rows)) {
            return;
        }
        foreach ($rows as $row) {
            $member_id = import_id_remap_get('member', strval($row['s_member_id']), true);
            if (is_null($member_id)) {
                continue;
            }
            unset($row['id']);
            $row['s_member_id'] = $member_id;

            $GLOBALS['SITE_DB']->query_insert('searches_saved', $row);
        }
    }

    /**
     * Imports site-watch-list.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_staff_website_monitoring($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . ($db->table_exists('staff_website_monitoring') ? 'staff_website_monitoring' : 'sitewatchlist'), null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            unset($row['id']);

            if (!isset($row['site_url'])) {
                $row['site_url'] = $row['siteurl'];
                unset($row['siteurl']);
            }

            $GLOBALS['SITE_DB']->query_insert('staff_website_monitoring', $row);
        }
    }

    /**
     * Imports staff-links.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  PATH $file_base The base directory we are importing from
     */
    public function import_staff_links($db, $table_prefix, $file_base)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . ($db->table_exists('staff_links') ? 'staff_links' : 'stafflinks'), null, null, true);
        if (is_null($rows)) {
            return;
        }
        $this->_fix_comcode_ownership($rows);
        foreach ($rows as $row) {
            unset($row['id']);
            $GLOBALS['SITE_DB']->query_insert('staff_links', $row);
        }
    }

    /**
     * Import reviews.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  ID_TEXT $rating_type The rating type.
     * @param  ?ID_TEXT $import_type The import type to get remapping from (null: no remapping).
     */
    protected function _import_review_supplement($db, $table_prefix, $rating_type, $import_type)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'review_supplement WHERE ' . db_string_equal_to('r_rating_type', $rating_type));
        if (is_null($rows)) {
            return;
        }
        foreach ($rows as $row) {
            $rating_for_id = is_null($import_type) ? $row['r_rating_for_id'] : import_id_remap_get($import_type, @strval($row['r_rating_for_id']), true);
            if (is_null($rating_for_id)) {
                continue;
            }

            $r_post_id = import_id_remap_get('post', strval($row['r_post_id']), true);
            if (is_null($r_post_id)) {
                continue;
            }
            $r_topic_id = import_id_remap_get('topic', strval($row['r_topic_id']), true);
            if (is_null($r_topic_id)) {
                continue;
            }
            $row['r_post_id'] = $r_post_id;
            $row['r_topic_id'] = $r_topic_id;
            $row['r_rating_for_id'] = $rating_for_id;

            $GLOBALS['SITE_DB']->query_insert('review_supplement', $row);
        }
    }

    /**
     * Import content review schedules.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  ID_TEXT $content_type The content type.
     * @param  ?ID_TEXT $import_type The import type to get remapping from (null: no remapping).
     */
    protected function _import_content_reviews($db, $table_prefix, $content_type, $import_type)
    {
        $rows = $db->query('SELECT * FROM ' . $table_prefix . 'content_reviews WHERE ' . db_string_equal_to('content_type', $content_type));
        if (is_null($rows)) {
            return;
        }
        foreach ($rows as $row) {
            $content_id = is_null($import_type) ? $row['content_id'] : import_id_remap_get($import_type, @strval($row['content_id']), true);
            if (is_null($content_id)) {
                continue;
            }

            $row['content_type'] = $content_type;
            $row['content_id'] = $content_id;

            $GLOBALS['SITE_DB']->query_insert('content_reviews', $row);
        }
    }

    /**
     * Import custom fields for a particular record.
     *
     * @param  object $db The DB connection to import from
     * @param  string $table_prefix The table prefix the target prefix is using
     * @param  ID_TEXT $content_type The content type.
     * @param  ?ID_TEXT $import_type The import type to get remapping from (null: no remapping).
     */
    protected function _import_catalogue_entry_linkage($db, $table_prefix, $content_type, $import_type)
    {
        if (!$db->table_exists('catalogue_entry_linkage')) {
            return;
        }

        $sql = 'SELECT * FROM ' . $table_prefix . 'catalogue_entry_linkage WHERE ' . db_string_equal_to('content_type', $content_type);
        if ($content_type == 'wiki_page') {
            $sql .= ' OR ' . db_string_equal_to('content_type', 'cedi_page');
        }
        if ($content_type == 'wiki_post') {
            $sql .= ' OR ' . db_string_equal_to('content_type', 'cedi_post');
        }
        $rows = $db->query($sql);
        foreach ($rows as $row) {
            $catalogue_entry_id = import_id_remap_get('catalogue_entry', strval($row['catalogue_entry_id']), true);
            if (is_null($catalogue_entry_id)) {
                continue;
            }

            $content_id = is_null($import_type) ? $row['content_id'] : import_id_remap_get($import_type, @strval($row['content_id']), true);
            if (is_null($content_id)) {
                continue;
            }

            $row['catalogue_entry_id'] = $catalogue_entry_id;
            $row['content_id'] = $content_id;

            $GLOBALS['SITE_DB']->query_insert('catalogue_entry_linkage', $row);
        }
    }

    /**
     * Remap any Comcode ownership fields.
     *
     * @param  array $rows Rows with potential fields to fix
     */
    protected function _fix_comcode_ownership(&$rows)
    {
        foreach ($rows as &$row) {
            foreach ($row as $field => $value) {
                if (substr($field, 0, 13) == '__source_user') {
                    $member_id = import_id_remap_get('member', strval($value), true);
                    if (is_null($member_id)) {
                        $member_id = db_get_first_id();
                    }

                    $row[$field] = $member_id;
                }
            }
        }
    }
}
